From 7f8a8485b5b2d24f20355cbc17d6d57e7cc62a29 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Wed, 30 Mar 2022 19:10:55 +0300 Subject: [PATCH 01/92] Circleci project setup (#1) * Added .circleci/config.yml --- .circleci/config.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..153b55131 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,29 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/2.0/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/2.0/configuration-reference/#jobs +jobs: + cargo-test: + # Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor + docker: + - image: cimg/rust:1.59.0 + # Add steps to the job + # See: https://circleci.com/docs/2.0/configuration-reference/#steps + steps: + - checkout + - run: + name: "cargo test" + command: | + cargo version; + cargo test; + + +# Invoke jobs via workflows +# See: https://circleci.com/docs/2.0/configuration-reference/#workflows +workflows: + build-and-test: + jobs: + - cargo-test From 1328c622abe164adb12f93d528576e0c6504f78a Mon Sep 17 00:00:00 2001 From: Daniel Benarroch Date: Tue, 14 Jun 2022 17:33:34 +0200 Subject: [PATCH 02/92] issuer keys implementation (#5) Implements the issuer keys as IssuerAuthorizingKey -> isk IssuerVerifyingKey -> ik Test vectors generated with zcash_test_vectors repo --- src/keys.rs | 113 ++++++++++++++++++++++++++++++++++----- src/spec/prf_expand.rs | 2 + src/test_vectors/keys.rs | 102 +++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 12 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index a7856f915..16c63b42e 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -18,7 +18,7 @@ use zcash_note_encryption::EphemeralKeyBytes; use crate::{ address::Address, - primitives::redpallas::{self, SpendAuth}, + primitives::redpallas::{self, SpendAuth, VerificationKey}, spec::{ commit_ivk, diversify_hash, extract_p, ka_orchard, ka_orchard_prepared, prf_nf, to_base, to_scalar, NonIdentityPallasPoint, NonZeroPallasBase, NonZeroPallasScalar, @@ -189,21 +189,104 @@ impl SpendValidatingKey { pub(crate) fn from_bytes(bytes: &[u8]) -> Option { <[u8; 32]>::try_from(bytes) .ok() - .and_then(|b| { - // Structural validity checks for ak_P: - // - The point must not be the identity - // (which for Pallas is canonically encoded as all-zeroes). - // - The sign of the y-coordinate must be positive. - if b != [0; 32] && b[31] & 0x80 == 0 { - >::try_from(b).ok() - } else { - None - } - }) + .and_then(check_structural_validity) .map(SpendValidatingKey) } } +/// An issuer authorizing key, used to create issuer authorization signatures. +/// This type enforces that the corresponding public point (ik^ℙ) has ỹ = 0. +/// +/// $\mathsf{isk}$ as defined in +/// [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. +/// +/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents +#[derive(Clone, Debug)] +pub struct IssuerAuthorizingKey(redpallas::SigningKey); + +impl IssuerAuthorizingKey { + /// Derives isk from sk. Internal use only, does not enforce all constraints. + fn derive_inner(sk: &SpendingKey) -> pallas::Scalar { + to_scalar(PrfExpand::ZsaIsk.expand(&sk.0)) + } +} + +impl From<&SpendingKey> for IssuerAuthorizingKey { + fn from(sk: &SpendingKey) -> Self { + let isk = Self::derive_inner(sk); + // IssuerSigningKey cannot be constructed such that this assertion would fail. + assert!(!bool::from(isk.is_zero())); + let ret = IssuerAuthorizingKey(isk.to_repr().try_into().unwrap()); + // If the last bit of repr_P(ik) is 1, negate isk. + if (<[u8; 32]>::from(IssuerValidatingKey::from(&ret).0)[31] >> 7) == 1 { + IssuerAuthorizingKey((-isk).to_repr().try_into().unwrap()) + } else { + ret + } + } +} + +/// A key used to validate issuer authorization signatures. +/// +/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. +/// Note that this is $\mathsf{ik}^\mathbb{P}$, which by construction is equivalent to +/// $\mathsf{ik}$ but stored here as a RedPallas verification key. +/// +/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents +#[derive(Debug, Clone, PartialOrd, Ord)] +pub struct IssuerValidatingKey(redpallas::VerificationKey); +impl From<&IssuerAuthorizingKey> for IssuerValidatingKey { + fn from(isk: &IssuerAuthorizingKey) -> Self { + IssuerValidatingKey((&isk.0).into()) + } +} + +impl From<&IssuerValidatingKey> for pallas::Point { + fn from(issuer_validating_key: &IssuerValidatingKey) -> pallas::Point { + pallas::Point::from_bytes(&(&issuer_validating_key.0).into()).unwrap() + } +} + +impl PartialEq for IssuerValidatingKey { + fn eq(&self, other: &Self) -> bool { + <[u8; 32]>::from(&self.0).eq(&<[u8; 32]>::from(&other.0)) + } +} + +impl Eq for IssuerValidatingKey {} + +impl IssuerValidatingKey { + /// Converts this spend validating key to its serialized form, + /// I2LEOSP_256(ik). + pub(crate) fn to_bytes(&self) -> [u8; 32] { + // This is correct because the wrapped point must have ỹ = 0, and + // so the point repr is the same as I2LEOSP of its x-coordinate. + <[u8; 32]>::from(&self.0) + } + + pub(crate) fn from_bytes(bytes: &[u8]) -> Option { + <[u8; 32]>::try_from(bytes) + .ok() + .and_then(check_structural_validity) + .map(IssuerValidatingKey) + } +} + +/// A function to check structural validity of the validating keys for authorizing transfers and +/// issuing assets +/// Structural validity checks for ik_P: +/// - The point must not be the identity (which for Pallas is canonically encoded as all-zeroes). +/// - The sign of the y-coordinate must be positive. +fn check_structural_validity( + verification_key_bytes: [u8; 32], +) -> Option> { + if verification_key_bytes != [0; 32] && verification_key_bytes[31] & 0x80 == 0 { + >::try_from(verification_key_bytes).ok() + } else { + None + } +} + /// A key used to derive [`Nullifier`]s from [`Note`]s. /// /// $\mathsf{nk}$ as defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. @@ -1060,9 +1143,15 @@ mod tests { let ask: SpendAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask); + let isk: IssuerAuthorizingKey = (&sk).into(); + assert_eq!(<[u8; 32]>::from(&isk.0), tv.isk); + let ak: SpendValidatingKey = (&ask).into(); assert_eq!(<[u8; 32]>::from(ak.0), tv.ak); + let ik: IssuerValidatingKey = (&isk).into(); + assert_eq!(<[u8; 32]>::from(ik.0), tv.ik); + let nk: NullifierDerivingKey = (&sk).into(); assert_eq!(nk.0.to_repr(), tv.nk); diff --git a/src/spec/prf_expand.rs b/src/spec/prf_expand.rs index e2f95e7ff..fa7881889 100644 --- a/src/spec/prf_expand.rs +++ b/src/spec/prf_expand.rs @@ -10,6 +10,7 @@ pub(crate) enum PrfExpand { OrchardNk, OrchardRivk, Psi, + ZsaIsk, OrchardZip32Child, OrchardDkOvk, OrchardRivkInternal, @@ -24,6 +25,7 @@ impl PrfExpand { Self::OrchardNk => 0x07, Self::OrchardRivk => 0x08, Self::Psi => 0x09, + Self::ZsaIsk => 0x0a, Self::OrchardZip32Child => 0x81, Self::OrchardDkOvk => 0x82, Self::OrchardRivkInternal => 0x83, diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 39d7dc00d..35cc1acbf 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -4,6 +4,8 @@ pub(crate) struct TestVector { pub(crate) sk: [u8; 32], pub(crate) ask: [u8; 32], pub(crate) ak: [u8; 32], + pub(crate) isk: [u8; 32], + pub(crate) ik: [u8; 32], pub(crate) nk: [u8; 32], pub(crate) rivk: [u8; 32], pub(crate) ivk: [u8; 32], @@ -41,6 +43,16 @@ pub(crate) fn test_vectors() -> Vec { 0x12, 0x8b, 0x9a, 0x14, 0x0d, 0x5e, 0x07, 0xc1, 0x51, 0x72, 0x1d, 0xc1, 0x6d, 0x25, 0xd4, 0xe2, 0x0f, 0x15, ], + isk: [ + 0x95, 0x4a, 0x86, 0xc7, 0xa7, 0x15, 0x53, 0xfa, 0x6c, 0x8b, 0x67, 0x58, 0x54, 0x26, + 0x8e, 0xa5, 0x4c, 0x51, 0xfb, 0x17, 0xd8, 0x3d, 0x80, 0xee, 0x71, 0xd4, 0xae, 0x42, + 0xa1, 0xf8, 0xc8, 0x16, + ], + ik: [ + 0x2e, 0x4f, 0xd4, 0xa6, 0xec, 0x39, 0x94, 0x87, 0xd3, 0x78, 0xb4, 0xc7, 0x25, 0xfb, + 0x9b, 0xaf, 0xbc, 0x01, 0xa5, 0xe2, 0xb7, 0xf3, 0x68, 0x2e, 0xf4, 0x53, 0x95, 0x91, + 0xbc, 0xf0, 0x59, 0x02, + ], nk: [ 0x9f, 0x2f, 0x82, 0x67, 0x38, 0x94, 0x5a, 0xd0, 0x1f, 0x47, 0xf7, 0x0d, 0xb0, 0xc3, 0x67, 0xc2, 0x46, 0xc2, 0x0c, 0x61, 0xff, 0x55, 0x83, 0x94, 0x8c, 0x39, 0xde, 0xa9, @@ -132,6 +144,16 @@ pub(crate) fn test_vectors() -> Vec { 0x2a, 0xd6, 0x43, 0x23, 0x62, 0x9c, 0xfe, 0xd1, 0xe3, 0xaa, 0x24, 0xef, 0x05, 0x2f, 0x56, 0xe4, 0x00, 0x2a, ], + isk: [ + 0xee, 0xf5, 0xe9, 0x1b, 0x36, 0xb8, 0x06, 0x86, 0x72, 0x3d, 0x14, 0xdc, 0xc7, 0x04, + 0xad, 0x59, 0x67, 0x08, 0x0b, 0x7d, 0x6e, 0x49, 0xaf, 0x97, 0x03, 0x0e, 0x4f, 0xa0, + 0xbf, 0x5a, 0xd9, 0x0b, + ], + ik: [ + 0x2e, 0xde, 0xfb, 0x15, 0x8e, 0xa4, 0x48, 0x82, 0x57, 0x2b, 0xcd, 0xb2, 0x35, 0xca, + 0x36, 0xab, 0x39, 0xc7, 0x47, 0xbb, 0x71, 0xfe, 0x0f, 0x10, 0xfa, 0xa3, 0x9b, 0xfd, + 0x62, 0x0a, 0xcc, 0x04, + ], nk: [ 0xa8, 0xb7, 0x3d, 0x97, 0x9b, 0x6e, 0xaa, 0xda, 0x89, 0x24, 0xbc, 0xbd, 0xc6, 0x3a, 0x9e, 0xf4, 0xe8, 0x73, 0x46, 0xf2, 0x30, 0xab, 0xa6, 0xbb, 0xe1, 0xe2, 0xb4, 0x3c, @@ -223,6 +245,16 @@ pub(crate) fn test_vectors() -> Vec { 0xed, 0xb4, 0x26, 0x65, 0x7b, 0x2d, 0x07, 0x40, 0x66, 0x64, 0xd8, 0x95, 0x31, 0x2e, 0xa1, 0xc3, 0xb3, 0x34, ], + isk: [ + 0x5b, 0x1f, 0xc4, 0x57, 0xae, 0x71, 0x38, 0x3c, 0x53, 0xf4, 0x69, 0x41, 0xb7, 0xcb, + 0x4c, 0xec, 0x3d, 0xea, 0xc0, 0xc6, 0x03, 0xe2, 0xcd, 0xd0, 0xd1, 0x8d, 0x94, 0x01, + 0x9e, 0x43, 0xe2, 0x07, + ], + ik: [ + 0x4f, 0x43, 0xeb, 0x7d, 0x9e, 0x03, 0x6f, 0xa6, 0x15, 0xfd, 0x04, 0xa5, 0xef, 0x6a, + 0xeb, 0x21, 0x6e, 0x06, 0x9b, 0xe9, 0x2d, 0x30, 0xe8, 0xf7, 0x16, 0x3e, 0xe3, 0x15, + 0x11, 0x6f, 0x18, 0x32, + ], nk: [ 0x04, 0x51, 0x4e, 0xa0, 0x48, 0xb9, 0x43, 0x63, 0xde, 0xa7, 0xcb, 0x3b, 0xe8, 0xd6, 0x25, 0x82, 0xac, 0x52, 0x92, 0x2e, 0x08, 0x65, 0xf6, 0x62, 0x74, 0x3b, 0x05, 0xea, @@ -314,6 +346,16 @@ pub(crate) fn test_vectors() -> Vec { 0xe7, 0x2c, 0x3b, 0x64, 0x00, 0x06, 0xff, 0x08, 0x50, 0x52, 0x80, 0xe4, 0xf0, 0x0f, 0xad, 0xf7, 0x63, 0x28, ], + isk: [ + 0x71, 0xd0, 0x64, 0xaa, 0xa0, 0x82, 0x63, 0xb8, 0xe4, 0xc3, 0xed, 0x70, 0x3c, 0x6f, + 0x54, 0x25, 0x4a, 0x88, 0x8c, 0x36, 0xec, 0x69, 0x86, 0x62, 0xf7, 0x1f, 0xbb, 0xf4, + 0x26, 0xd9, 0x09, 0x28, + ], + ik: [ + 0x12, 0xb3, 0xab, 0xff, 0x96, 0x75, 0x20, 0x9e, 0x94, 0x54, 0x07, 0x0c, 0x14, 0xac, + 0x15, 0x54, 0x65, 0xae, 0x83, 0xbe, 0x2c, 0x39, 0x46, 0x63, 0x5e, 0x38, 0x77, 0xba, + 0x67, 0xdf, 0x49, 0x12, + ], nk: [ 0xcf, 0x36, 0xad, 0x6a, 0x06, 0x6c, 0xd2, 0x13, 0xe1, 0xd7, 0x67, 0xab, 0x07, 0x1d, 0xc1, 0x16, 0x78, 0x85, 0xc4, 0x16, 0x8b, 0xc2, 0xe2, 0x17, 0x54, 0x48, 0x56, 0x3a, @@ -405,6 +447,16 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0x6d, 0x83, 0x20, 0x09, 0xf7, 0x24, 0x2e, 0x1f, 0x7c, 0x77, 0x0a, 0x12, 0x24, 0x1d, 0xfa, 0x28, 0x07, ], + isk: [ + 0x44, 0x36, 0x1a, 0x7b, 0xa6, 0xa1, 0xaa, 0x17, 0x8e, 0x72, 0xaf, 0x47, 0xbd, 0xc1, + 0x60, 0x40, 0xce, 0x1c, 0x54, 0xdd, 0x4b, 0x56, 0x33, 0x21, 0x55, 0xba, 0x9d, 0x04, + 0x09, 0x71, 0xd0, 0x07, + ], + ik: [ + 0x1f, 0x17, 0x2d, 0x79, 0xae, 0xdc, 0xc2, 0x06, 0x8c, 0x3a, 0x09, 0x08, 0x93, 0xe1, + 0xa1, 0x75, 0xd9, 0xb5, 0x78, 0xf8, 0x91, 0xaf, 0x9a, 0xb6, 0x8d, 0x4f, 0xe1, 0xe9, + 0x05, 0xa3, 0xb2, 0x11, + ], nk: [ 0x51, 0xba, 0xf3, 0x33, 0xcf, 0xf1, 0xf2, 0xd0, 0xc7, 0xe3, 0xcf, 0xf4, 0xd3, 0x01, 0x29, 0x9d, 0xc1, 0xef, 0xe9, 0x83, 0x00, 0x31, 0x4a, 0x54, 0x19, 0x38, 0x02, 0x9b, @@ -496,6 +548,16 @@ pub(crate) fn test_vectors() -> Vec { 0xdf, 0x28, 0xbb, 0x0f, 0x10, 0x21, 0xea, 0x84, 0x3f, 0x86, 0x7f, 0x8a, 0x17, 0x0f, 0x5c, 0x33, 0x90, 0x1f, ], + isk: [ + 0xdc, 0x93, 0x72, 0x9f, 0x3f, 0x28, 0x30, 0xed, 0x79, 0x1c, 0x21, 0xbe, 0xbe, 0x45, + 0x0f, 0xcf, 0x1f, 0x8f, 0xef, 0x49, 0x81, 0x39, 0xc7, 0x99, 0xd1, 0x63, 0x66, 0x5a, + 0x8c, 0x51, 0xe5, 0x2d, + ], + ik: [ + 0x1d, 0xb6, 0x1c, 0x29, 0x3e, 0x3a, 0x93, 0x34, 0x5d, 0x06, 0xb9, 0x0b, 0xd7, 0x1f, + 0xd3, 0x21, 0x5c, 0x2c, 0x1c, 0x29, 0x53, 0x5a, 0x10, 0xde, 0x9d, 0x31, 0x40, 0xb7, + 0x4d, 0xb6, 0x1d, 0x07, + ], nk: [ 0x9e, 0x99, 0x7d, 0x9d, 0x26, 0x97, 0x87, 0x26, 0x8e, 0x09, 0x2a, 0x7c, 0x85, 0x41, 0x7d, 0xa5, 0x30, 0xea, 0x42, 0xfa, 0xc6, 0x68, 0xa7, 0x49, 0xaf, 0x55, 0xdf, 0xb7, @@ -587,6 +649,16 @@ pub(crate) fn test_vectors() -> Vec { 0x65, 0x43, 0x46, 0x2a, 0x13, 0x7f, 0xfe, 0xa3, 0x7b, 0xaf, 0x41, 0xef, 0x28, 0x6b, 0xb7, 0x32, 0xbe, 0x2c, ], + isk: [ + 0xf2, 0x34, 0x52, 0x32, 0xc9, 0x19, 0xc1, 0x29, 0xe0, 0x4b, 0x0c, 0x46, 0xac, 0x2c, + 0xa8, 0x50, 0x65, 0xd9, 0x54, 0x85, 0xb9, 0x02, 0xab, 0x0f, 0x98, 0xf9, 0x3a, 0xee, + 0x59, 0x4b, 0x5f, 0x02, + ], + ik: [ + 0x2c, 0x83, 0xd9, 0x20, 0xe9, 0xf6, 0x6d, 0xa5, 0x04, 0x86, 0x37, 0xad, 0x9a, 0xa2, + 0xcc, 0xe6, 0xe1, 0x6e, 0xf4, 0x8f, 0x86, 0x50, 0xea, 0x00, 0xd8, 0xc2, 0xd7, 0x68, + 0x61, 0x8a, 0xe3, 0x36, + ], nk: [ 0xfd, 0x31, 0x64, 0xc6, 0x32, 0xbe, 0xc9, 0x4c, 0xe9, 0xfb, 0x2f, 0x30, 0x22, 0x63, 0xb8, 0x84, 0xab, 0xb9, 0xc1, 0x0e, 0x55, 0xe4, 0x48, 0x64, 0x7f, 0x67, 0x98, 0x49, @@ -678,6 +750,16 @@ pub(crate) fn test_vectors() -> Vec { 0xb3, 0x65, 0x1f, 0xfa, 0x1c, 0x69, 0x69, 0x15, 0xac, 0x00, 0xa2, 0x5e, 0xa3, 0xac, 0x7d, 0xff, 0x99, 0x01, ], + isk: [ + 0x3d, 0xa9, 0x08, 0x88, 0xba, 0x18, 0x24, 0xc8, 0x16, 0x29, 0x2d, 0x7f, 0x17, 0x33, + 0xac, 0x4c, 0xbe, 0x72, 0x2c, 0x6a, 0x12, 0x1c, 0xc7, 0x80, 0x17, 0x06, 0x26, 0xb7, + 0x0a, 0x26, 0x95, 0x28, + ], + ik: [ + 0x16, 0xa8, 0xff, 0x29, 0xb5, 0x17, 0xb5, 0xa8, 0xf7, 0xd0, 0x9b, 0x4e, 0x5e, 0x71, + 0x3a, 0x9a, 0x78, 0x4c, 0x74, 0x04, 0xd6, 0x1e, 0x3a, 0xf5, 0x30, 0x19, 0xc3, 0x47, + 0x0e, 0x90, 0x95, 0x22, + ], nk: [ 0x02, 0xab, 0x99, 0x5c, 0xe9, 0x8f, 0x63, 0x02, 0x5f, 0xb6, 0x24, 0x28, 0xa0, 0xfb, 0xf5, 0x2f, 0x25, 0x22, 0xe6, 0xa2, 0x72, 0x61, 0x07, 0x8a, 0x9f, 0x4d, 0x6a, 0x36, @@ -769,6 +851,16 @@ pub(crate) fn test_vectors() -> Vec { 0x3b, 0x02, 0xd2, 0x5c, 0xc1, 0x0c, 0x90, 0x71, 0xfc, 0x02, 0x19, 0xe9, 0x7f, 0x93, 0x92, 0xd0, 0x67, 0x0c, ], + isk: [ + 0x01, 0x65, 0x33, 0x68, 0x4f, 0xb9, 0x81, 0x15, 0xa4, 0x05, 0xc9, 0xc7, 0xad, 0x47, + 0x72, 0x76, 0xab, 0x7c, 0x72, 0xfd, 0x67, 0x1a, 0x27, 0xe3, 0x6c, 0x0a, 0x7a, 0xbe, + 0x0a, 0x76, 0x90, 0x09, + ], + ik: [ + 0xff, 0xd7, 0x5f, 0x6f, 0x9e, 0xf4, 0x27, 0xf3, 0x26, 0xcd, 0xbf, 0x3a, 0x98, 0xbc, + 0xb5, 0x93, 0x63, 0x5a, 0x2c, 0x1a, 0xd7, 0x2b, 0x39, 0x99, 0x12, 0x61, 0xe2, 0x75, + 0xa9, 0xec, 0x6f, 0x10, + ], nk: [ 0x25, 0x91, 0xed, 0xf7, 0xef, 0x4c, 0xf2, 0x18, 0x4c, 0x34, 0xbe, 0x93, 0xfc, 0xf6, 0x12, 0x91, 0x50, 0x42, 0xf1, 0x5a, 0xb5, 0x08, 0x4b, 0x14, 0xe1, 0x66, 0x79, 0x5b, @@ -860,6 +952,16 @@ pub(crate) fn test_vectors() -> Vec { 0x8d, 0x4b, 0x02, 0x5f, 0x8c, 0xc1, 0x60, 0xe1, 0xf4, 0xe9, 0x5f, 0x0a, 0x85, 0x3e, 0xbc, 0x41, 0x6a, 0x2b, ], + isk: [ + 0x76, 0x08, 0x32, 0x9d, 0xfa, 0x77, 0xc4, 0x2c, 0x4f, 0xc7, 0x6a, 0xc2, 0x95, 0x94, + 0xa2, 0x72, 0x83, 0x93, 0x4f, 0x5a, 0x93, 0x40, 0x71, 0xb9, 0xf8, 0xcd, 0x34, 0x4e, + 0x1f, 0x98, 0x45, 0x0e, + ], + ik: [ + 0x72, 0xa0, 0xac, 0x97, 0x8a, 0x2d, 0xa1, 0x61, 0xf4, 0x1f, 0x5b, 0x7a, 0x40, 0xbd, + 0x83, 0xc0, 0x58, 0x41, 0xf8, 0x1b, 0xc5, 0x11, 0x40, 0x67, 0xb8, 0x85, 0x98, 0x7f, + 0x48, 0xca, 0x52, 0x2d, + ], nk: [ 0x3e, 0x88, 0xf2, 0x07, 0x1f, 0xd9, 0xa2, 0xbb, 0x26, 0xcd, 0xa2, 0xea, 0x85, 0x6a, 0xa0, 0xfb, 0x3a, 0x80, 0xa8, 0x7d, 0x2f, 0xb6, 0x13, 0x6f, 0xab, 0x85, 0xe3, 0x6c, From e6b776295a0dc4505ac27981cc3cacc416186917 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Tue, 14 Jun 2022 21:23:03 +0300 Subject: [PATCH 03/92] Added NoteType to Notes (#2) * Added NoteType to Notes * Added NoteType to value commitment derivation --- .circleci/config.yml | 15 ++++++- src/action.rs | 7 +++- src/builder.rs | 18 +++++++-- src/bundle.rs | 2 + src/circuit.rs | 3 +- src/constants/fixed_bases.rs | 4 ++ src/keys.rs | 2 + src/note.rs | 19 ++++++++- src/note/note_type.rs | 77 ++++++++++++++++++++++++++++++++++++ src/note_encryption.rs | 8 +++- src/value.rs | 66 ++++++++++++++++++------------- 11 files changed, 182 insertions(+), 39 deletions(-) create mode 100644 src/note/note_type.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 153b55131..ba37a7890 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,6 +2,9 @@ # See: https://circleci.com/docs/2.0/configuration-reference version: 2.1 +orbs: + slack: circleci/slack@4.1 + # Define a job to be invoked later in a workflow. # See: https://circleci.com/docs/2.0/configuration-reference/#jobs jobs: @@ -17,8 +20,15 @@ jobs: - run: name: "cargo test" command: | + sudo apt update && sudo apt-get install libfontconfig libfontconfig1-dev libfreetype6-dev; cargo version; - cargo test; + cargo test --all --all-features; + - slack/notify: + event: fail + template: basic_fail_1 + - slack/notify: + event: pass + template: basic_success_1 # Invoke jobs via workflows @@ -26,4 +36,5 @@ jobs: workflows: build-and-test: jobs: - - cargo-test + - cargo-test: + context: CI-Orchard-slack diff --git a/src/action.rs b/src/action.rs index d0b73f23e..b6396ed91 100644 --- a/src/action.rs +++ b/src/action.rs @@ -126,6 +126,7 @@ pub(crate) mod testing { use proptest::prelude::*; + use crate::note::NoteType; use crate::{ note::{ commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, @@ -150,7 +151,8 @@ pub(crate) mod testing { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( spend_value - output_value, - ValueCommitTrapdoor::zero() + ValueCommitTrapdoor::zero(), + NoteType::native() ); // FIXME: make a real one from the note. let encrypted_note = TransmittedNoteCiphertext { @@ -181,7 +183,8 @@ pub(crate) mod testing { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( spend_value - output_value, - ValueCommitTrapdoor::zero() + ValueCommitTrapdoor::zero(), + NoteType::native() ); // FIXME: make a real one from the note. diff --git a/src/builder.rs b/src/builder.rs index 9cbc2a5fb..1a7ccbec1 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -8,6 +8,7 @@ use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; +use crate::note::NoteType; use crate::{ action::Action, address::Address, @@ -160,14 +161,21 @@ impl ActionInfo { /// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend fn build(self, mut rng: impl RngCore) -> (Action, Circuit) { let v_net = self.value_sum(); - let cv_net = ValueCommitment::derive(v_net, self.rcv.clone()); + let cv_net = ValueCommitment::derive(v_net, self.rcv, NoteType::native()); let nf_old = self.spend.note.nullifier(&self.spend.fvk); let ak: SpendValidatingKey = self.spend.fvk.clone().into(); let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); + let note_type = self.spend.note.note_type(); - let note = Note::new(self.output.recipient, self.output.value, nf_old, &mut rng); + let note = Note::new( + self.output.recipient, + self.output.value, + note_type, + nf_old, + &mut rng, + ); let cm_new = note.commitment(); let cmx = cm_new.into(); @@ -387,7 +395,11 @@ impl Builder { // Verify that bsk and bvk are consistent. let bvk = (actions.iter().map(|a| a.cv_net()).sum::() - - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero())) + - ValueCommitment::derive( + value_balance, + ValueCommitTrapdoor::zero(), + NoteType::native(), + )) .into_bvk(); assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); diff --git a/src/bundle.rs b/src/bundle.rs index 239cce7c2..4f4e1cb3f 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -12,6 +12,7 @@ use memuse::DynamicUsage; use nonempty::NonEmpty; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; +use crate::note::NoteType; use crate::{ action::Action, address::Address, @@ -384,6 +385,7 @@ impl> Bundle { - ValueCommitment::derive( ValueSum::from_raw(self.value_balance.into()), ValueCommitTrapdoor::zero(), + NoteType::native(), )) .into_bvk() } diff --git a/src/circuit.rs b/src/circuit.rs index d349180ed..0b271d750 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -968,6 +968,7 @@ mod tests { use rand::{rngs::OsRng, RngCore}; use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; + use crate::note::NoteType; use crate::{ keys::SpendValidatingKey, note::Note, @@ -991,7 +992,7 @@ mod tests { let value = spent_note.value() - output_note.value(); let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv.clone()); + let cv_net = ValueCommitment::derive(value, rcv, NoteType::native()); let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index af11e335f..7a86487d3 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -19,8 +19,12 @@ pub mod value_commit_v; pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard"; /// SWU hash-to-curve personalization for the value commitment generator +/// TODO: should we change to "NOTE_TYPE_PERSONALIZATION"? pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv"; +/// SWU hash-to-curve personalization for the note type generator +// pub const NOTE_TYPE_PERSONALIZATION: &str = "z.cash:Orchard-NoteType"; + /// SWU hash-to-curve value for the value commitment generator pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v"; diff --git a/src/keys.rs b/src/keys.rs index 16c63b42e..8b76c8517 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1084,6 +1084,7 @@ mod tests { testing::{arb_diversifier_index, arb_diversifier_key, arb_esk, arb_spending_key}, *, }; + use crate::note::NoteType; use crate::{ note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, value::NoteValue, @@ -1175,6 +1176,7 @@ mod tests { let note = Note::from_parts( addr, NoteValue::from_raw(tv.note_v), + NoteType::native(), rho, RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(), ) diff --git a/src/note.rs b/src/note.rs index 522b137f3..31063864c 100644 --- a/src/note.rs +++ b/src/note.rs @@ -19,6 +19,9 @@ pub use self::commitment::{ExtractedNoteCommitment, NoteCommitment}; pub(crate) mod nullifier; pub use self::nullifier::Nullifier; +pub(crate) mod note_type; +pub use self::note_type::NoteType; + /// The ZIP 212 seed randomness for a note. #[derive(Copy, Clone, Debug)] pub struct RandomSeed([u8; 32]); @@ -90,6 +93,8 @@ pub struct Note { recipient: Address, /// The value of this note. value: NoteValue, + /// The type of this note. + note_type: NoteType, /// A unique creation ID for this note. /// /// This is set to the nullifier of the note that was spent in the [`Action`] that @@ -129,12 +134,14 @@ impl Note { pub fn from_parts( recipient: Address, value: NoteValue, + note_type: NoteType, rho: Nullifier, rseed: RandomSeed, ) -> CtOption { let note = Note { recipient, value, + note_type, rho, rseed, }; @@ -149,11 +156,12 @@ impl Note { pub(crate) fn new( recipient: Address, value: NoteValue, + note_type: NoteType, rho: Nullifier, mut rng: impl RngCore, ) -> Self { loop { - let note = Note::from_parts(recipient, value, rho, RandomSeed::random(&mut rng, &rho)); + let note = Note::from_parts(recipient, value, note_type, rho, RandomSeed::random(&mut rng, &rho)); if note.is_some().into() { break note.unwrap(); } @@ -176,6 +184,7 @@ impl Note { let note = Note::new( recipient, NoteValue::zero(), + NoteType::native(), rho.unwrap_or_else(|| Nullifier::dummy(rng)), rng, ); @@ -193,6 +202,11 @@ impl Note { self.value } + /// Returns the note type + pub fn note_type(&self) -> NoteType { + self.note_type + } + /// Returns the rseed value of this note. pub fn rseed(&self) -> &RandomSeed { &self.rseed @@ -279,6 +293,7 @@ impl fmt::Debug for TransmittedNoteCiphertext { pub mod testing { use proptest::prelude::*; + use crate::note::note_type::testing::arb_note_type; use crate::{ address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, }; @@ -298,10 +313,12 @@ pub mod testing { recipient in arb_address(), rho in arb_nullifier(), rseed in arb_rseed(), + note_type in arb_note_type(), ) -> Note { Note { recipient, value, + note_type, rho, rseed, } diff --git a/src/note/note_type.rs b/src/note/note_type.rs new file mode 100644 index 000000000..d0857d61a --- /dev/null +++ b/src/note/note_type.rs @@ -0,0 +1,77 @@ +use group::GroupEncoding; +use halo2_proofs::arithmetic::CurveExt; +use pasta_curves::pallas; +use subtle::CtOption; + +use crate::constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_V_BYTES}; +use crate::keys::IssuerValidatingKey; + +/// Note type identifier. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct NoteType(pub(crate) pallas::Point); + +const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; + +// the hasher used to derive the assetID +#[allow(non_snake_case)] +fn assetID_hasher(msg: Vec) -> pallas::Point { + // TODO(zsa) replace personalization, will require circuit change? + pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION)(&msg) +} + +impl NoteType { + /// Deserialize the note_type from a byte array. + pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { + pallas::Point::from_bytes(bytes).map(NoteType) + } + + /// Serialize the note_type to its canonical byte representation. + pub fn to_bytes(self) -> [u8; 32] { + self.0.to_bytes() + } + + /// $DeriveNoteType$. + /// + /// Defined in [Zcash Protocol Spec § TBD: Note Types][notetypes]. + /// + /// [notetypes]: https://zips.z.cash/protocol/nu5.pdf#notetypes + #[allow(non_snake_case)] + pub fn derive(ik: &IssuerValidatingKey, assetDesc: Vec) -> Self { + assert!(assetDesc.len() < MAX_ASSET_DESCRIPTION_SIZE); + + let mut s = vec![]; + s.extend(ik.to_bytes()); + s.extend(assetDesc); + + NoteType(assetID_hasher(s)) + } + + /// Note type for the "native" currency (zec), maintains backward compatibility with Orchard untyped notes. + pub fn native() -> Self { + NoteType(assetID_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) + } +} + +/// Generators for property testing. +#[cfg(any(test, feature = "test-dependencies"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] +pub mod testing { + use proptest::prelude::*; + + use super::NoteType; + + use crate::keys::{testing::arb_spending_key, IssuerAuthorizingKey, IssuerValidatingKey}; + + prop_compose! { + /// Generate a uniformly distributed note type + pub fn arb_note_type()( + sk in arb_spending_key(), + bytes32a in prop::array::uniform32(prop::num::u8::ANY), + bytes32b in prop::array::uniform32(prop::num::u8::ANY), + ) -> NoteType { + let bytes64 = [bytes32a, bytes32b].concat(); + let isk = IssuerAuthorizingKey::from(&sk); + NoteType::derive(&IssuerValidatingKey::from(&isk), bytes64) + } + } +} diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 8ad06c8a9..39cd318e1 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -10,6 +10,7 @@ use zcash_note_encryption::{ OUT_PLAINTEXT_SIZE, }; +use crate::note::NoteType; use crate::{ action::Action, keys::{ @@ -75,7 +76,8 @@ where let pk_d = get_validated_pk_d(&diversifier)?; let recipient = Address::from_parts(diversifier, pk_d); - let note = Option::from(Note::from_parts(recipient, value, domain.rho, rseed))?; + // TODO: add note_type + let note = Option::from(Note::from_parts(recipient, value, NoteType::native(), domain.rho, rseed))?; Some((note, recipient)) } @@ -171,6 +173,7 @@ impl Domain for OrchardDomain { np[0] = 0x02; np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); np[12..20].copy_from_slice(¬e.value().to_bytes()); + // todo: add note_type np[20..52].copy_from_slice(note.rseed().as_bytes()); np[52..].copy_from_slice(memo); NotePlaintextBytes(np) @@ -358,6 +361,7 @@ mod tests { }; use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; + use crate::note::NoteType; use crate::{ action::Action, keys::{ @@ -413,7 +417,7 @@ mod tests { assert_eq!(ock.as_ref(), tv.ock); let recipient = Address::from_parts(d, pk_d); - let note = Note::from_parts(recipient, value, rho, rseed).unwrap(); + let note = Note::from_parts(recipient, value, NoteType::native(), rho, rseed).unwrap(); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); let action = Action::from_parts( diff --git a/src/value.rs b/src/value.rs index 1cef61c87..5ece74af2 100644 --- a/src/value.rs +++ b/src/value.rs @@ -52,10 +52,9 @@ use pasta_curves::{ use rand::RngCore; use subtle::CtOption; +use crate::note::NoteType; use crate::{ - constants::fixed_bases::{ - VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES, VALUE_COMMITMENT_V_BYTES, - }, + constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES}, primitives::redpallas::{self, Binding}, }; @@ -211,7 +210,7 @@ impl TryFrom for i64 { } /// The blinding factor for a [`ValueCommitment`]. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct ValueCommitTrapdoor(pallas::Scalar); impl ValueCommitTrapdoor { @@ -308,9 +307,8 @@ impl ValueCommitment { /// /// [concretehomomorphiccommit]: https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit #[allow(non_snake_case)] - pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor) -> Self { + pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, note_type: NoteType) -> Self { let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); - let V = hasher(&VALUE_COMMITMENT_V_BYTES); let R = hasher(&VALUE_COMMITMENT_R_BYTES); let abs_value = u64::try_from(value.0.abs()).expect("value must be in valid range"); @@ -320,7 +318,9 @@ impl ValueCommitment { pallas::Scalar::from(abs_value) }; - ValueCommitment(V * value + R * rcv.0) + let V_zsa = note_type.0; + + ValueCommitment(V_zsa * value + R * rcv.0) } pub(crate) fn into_bvk(self) -> redpallas::VerificationKey { @@ -423,6 +423,8 @@ pub mod testing { #[cfg(test)] mod tests { + use crate::note::note_type::testing::arb_note_type; + use crate::note::NoteType; use proptest::prelude::*; use super::{ @@ -431,6 +433,29 @@ mod tests { }; use crate::primitives::redpallas; + fn _bsk_consistent_with_bvk(values: &[(ValueSum, ValueCommitTrapdoor)], note_type: NoteType) { + let value_balance = values + .iter() + .map(|(value, _)| value) + .sum::>() + .expect("we generate values that won't overflow"); + + let bsk = values + .iter() + .map(|(_, rcv)| rcv) + .sum::() + .into_bsk(); + + let bvk = (values + .iter() + .map(|(value, rcv)| ValueCommitment::derive(*value, *rcv, note_type)) + .sum::() + - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero(), note_type)) + .into_bvk(); + + assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); + } + proptest! { #[test] fn bsk_consistent_with_bvk( @@ -438,28 +463,13 @@ mod tests { arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor()), n_values) ) - ) + ), + arb_note_type in arb_note_type(), ) { - let value_balance = values - .iter() - .map(|(value, _)| value) - .sum::>() - .expect("we generate values that won't overflow"); - - let bsk = values - .iter() - .map(|(_, rcv)| rcv) - .sum::() - .into_bsk(); - - let bvk = (values - .into_iter() - .map(|(value, rcv)| ValueCommitment::derive(value, rcv)) - .sum::() - - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero())) - .into_bvk(); - - assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); + // Test with native note type (zec) + _bsk_consistent_with_bvk(&values, NoteType::native()); + // Test with arbitrary note type + _bsk_consistent_with_bvk(&values, arb_note_type); } } } From 088abc6de6266bfafe1cd29c7a474936c20842f4 Mon Sep 17 00:00:00 2001 From: naure Date: Wed, 20 Jul 2022 13:08:58 +0200 Subject: [PATCH 04/92] ZSA note encryption in Orchard crate (#3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Circleci project setup (#1) * Added .circleci/config.yml * Added NoteType to Notes * reformated file * updated `derive` for NoteType * added note_type to value commit derivation * rustfmt * updated ci config * updated ci config * updated ci config * updated derive for note_type * added test for arb note_type * added test for `native` note type * zsa-note-encryption: introduce AssetType and encode and decode it in note plaintexts * zsa-note-encryption: extend the size of compact notes to include asset_type * fixed clippy warrnings * rustfmt * zsa-note-encryption: document parsing requirement * zsa-note-encryption: revert support of ZSA compact action * zsa_value: add NoteType method is_native * zsa-note-encryption: remove dependency on changes in the other crate * zsa-note-encryption: extract memo of ZSA notes * zsa-note-encryption: tests (zcash_test_vectors 77c73492) * zsa-note-encryption: simplify roundtrip test * zsa-note-encryption: more test vectors (zcash_test_vectors c10da464) * Circleci project setup (#1) * Added .circleci/config.yml * issuer keys implementation (#5) Implements the issuer keys as IssuerAuthorizingKey -> isk IssuerVerifyingKey -> ik Test vectors generated with zcash_test_vectors repo * Added NoteType to Notes (#2) * Added NoteType to Notes * Added NoteType to value commitment derivation * zsa-note-encryption: use both native and ZSA in proptests * zsa-note-encryption: test vector commit 51398c93 * zsa-note-encryption: fix after merge Co-authored-by: Paul <3682187+PaulLaux@users.noreply.github.com> Co-authored-by: Paul Co-authored-by: Aurélien Nicolas Co-authored-by: Daniel Benarroch --- .gitignore | 1 + src/constants/fixed_bases.rs | 3 + src/note.rs | 1 + src/note/commitment.rs | 54 +- src/note/note_type.rs | 29 +- src/note_encryption.rs | 140 +- src/test_vectors/note_encryption.rs | 3612 +++++++++++++++++++++------ src/value.rs | 2 +- 8 files changed, 3071 insertions(+), 771 deletions(-) diff --git a/.gitignore b/.gitignore index 173b95142..57ee1a9ad 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ **/*.rs.bk Cargo.lock .vscode +.idea diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index 7a86487d3..bd58a90c2 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -34,6 +34,9 @@ pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r"; /// SWU hash-to-curve personalization for the note commitment generator pub const NOTE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-NoteCommit"; +/// SWU hash-to-curve personalization for the ZSA note commitment generator +pub const NOTE_ZSA_COMMITMENT_PERSONALIZATION: &str = "z.cash:ZSA-NoteCommit"; + /// SWU hash-to-curve personalization for the IVK commitment generator pub const COMMIT_IVK_PERSONALIZATION: &str = "z.cash:Orchard-CommitIvk"; diff --git a/src/note.rs b/src/note.rs index 31063864c..c2edf4988 100644 --- a/src/note.rs +++ b/src/note.rs @@ -248,6 +248,7 @@ impl Note { g_d.to_bytes(), self.recipient.pk_d().to_bytes(), self.value, + self.note_type, self.rho.0, self.rseed.psi(&self.rho), self.rseed.rcm(&self.rho), diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 9de51d28e..95dc92a2c 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -7,7 +7,11 @@ use pasta_curves::pallas; use subtle::{ConstantTimeEq, CtOption}; use crate::{ - constants::{fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, L_ORCHARD_BASE}, + constants::{ + fixed_bases::{NOTE_COMMITMENT_PERSONALIZATION, NOTE_ZSA_COMMITMENT_PERSONALIZATION}, + L_ORCHARD_BASE, + }, + note::note_type::NoteType, spec::extract_p, value::NoteValue, }; @@ -41,22 +45,46 @@ impl NoteCommitment { g_d: [u8; 32], pk_d: [u8; 32], v: NoteValue, + note_type: NoteType, rho: pallas::Base, psi: pallas::Base, rcm: NoteCommitTrapdoor, ) -> CtOption { - let domain = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); - domain - .commit( - iter::empty() - .chain(BitArray::<_, Lsb0>::new(g_d).iter().by_vals()) - .chain(BitArray::<_, Lsb0>::new(pk_d).iter().by_vals()) - .chain(v.to_le_bits().iter().by_vals()) - .chain(rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)) - .chain(psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)), - &rcm.0, - ) - .map(NoteCommitment) + let g_d_bits = BitArray::<_, Lsb0>::new(g_d); + let pk_d_bits = BitArray::<_, Lsb0>::new(pk_d); + let v_bits = v.to_le_bits(); + let rho_bits = rho.to_le_bits(); + let psi_bits = psi.to_le_bits(); + + let zec_note_bits = iter::empty() + .chain(g_d_bits.iter().by_vals()) + .chain(pk_d_bits.iter().by_vals()) + .chain(v_bits.iter().by_vals()) + .chain(rho_bits.iter().by_vals().take(L_ORCHARD_BASE)) + .chain(psi_bits.iter().by_vals().take(L_ORCHARD_BASE)); + + // TODO: make this constant-time. + if note_type.is_native().into() { + // Commit to ZEC notes as per the Orchard protocol. + Self::commit(NOTE_COMMITMENT_PERSONALIZATION, zec_note_bits, rcm) + } else { + // Commit to non-ZEC notes as per the ZSA protocol. + // Append the note type to the Orchard note encoding. + let type_bits = BitArray::<_, Lsb0>::new(note_type.to_bytes()); + let zsa_note_bits = zec_note_bits.chain(type_bits.iter().by_vals()); + + // Commit in a different domain than Orchard notes. + Self::commit(NOTE_ZSA_COMMITMENT_PERSONALIZATION, zsa_note_bits, rcm) + } + } + + fn commit( + personalization: &str, + bits: impl Iterator, + rcm: NoteCommitTrapdoor, + ) -> CtOption { + let domain = sinsemilla::CommitDomain::new(personalization); + domain.commit(bits, &rcm.0).map(NoteCommitment) } } diff --git a/src/note/note_type.rs b/src/note/note_type.rs index d0857d61a..6075259e3 100644 --- a/src/note/note_type.rs +++ b/src/note/note_type.rs @@ -1,7 +1,7 @@ use group::GroupEncoding; use halo2_proofs::arithmetic::CurveExt; use pasta_curves::pallas; -use subtle::CtOption; +use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_V_BYTES}; use crate::keys::IssuerValidatingKey; @@ -15,7 +15,7 @@ const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; // the hasher used to derive the assetID #[allow(non_snake_case)] fn assetID_hasher(msg: Vec) -> pallas::Point { - // TODO(zsa) replace personalization, will require circuit change? + // TODO(zsa) replace personalization pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION)(&msg) } @@ -50,6 +50,16 @@ impl NoteType { pub fn native() -> Self { NoteType(assetID_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) } + + /// The base point used in value commitments. + pub fn cv_base(&self) -> pallas::Point { + self.0 + } + + /// Whether this note represents a native or ZSA asset. + pub fn is_native(&self) -> Choice { + self.0.ct_eq(&Self::native().0) + } } /// Generators for property testing. @@ -58,20 +68,25 @@ impl NoteType { pub mod testing { use proptest::prelude::*; - use super::NoteType; - use crate::keys::{testing::arb_spending_key, IssuerAuthorizingKey, IssuerValidatingKey}; + use super::NoteType; + prop_compose! { /// Generate a uniformly distributed note type pub fn arb_note_type()( + is_native in prop::bool::ANY, sk in arb_spending_key(), bytes32a in prop::array::uniform32(prop::num::u8::ANY), bytes32b in prop::array::uniform32(prop::num::u8::ANY), ) -> NoteType { - let bytes64 = [bytes32a, bytes32b].concat(); - let isk = IssuerAuthorizingKey::from(&sk); - NoteType::derive(&IssuerValidatingKey::from(&isk), bytes64) + if is_native { + NoteType::native() + } else { + let bytes64 = [bytes32a, bytes32b].concat(); + let isk = IssuerAuthorizingKey::from(&sk); + NoteType::derive(&IssuerValidatingKey::from(&isk), bytes64) + } } } } diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 39cd318e1..5d955e2cb 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -1,8 +1,7 @@ //! In-band secret distribution for Orchard bundles. -use core::fmt; - use blake2b_simd::{Hash, Params}; +use core::fmt; use group::ff::PrimeField; use zcash_note_encryption::{ BatchDomain, Domain, EphemeralKeyBytes, NotePlaintextBytes, OutPlaintextBytes, @@ -25,6 +24,15 @@ use crate::{ const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; +/// The size of the encoding of a ZSA asset type. +const ZSA_TYPE_SIZE: usize = 32; +/// The size of the ZSA variant of COMPACT_NOTE_SIZE. +const COMPACT_ZSA_NOTE_SIZE: usize = COMPACT_NOTE_SIZE + ZSA_TYPE_SIZE; +/// The size of the memo. +const MEMO_SIZE: usize = NOTE_PLAINTEXT_SIZE - COMPACT_NOTE_SIZE; +/// The size of the ZSA variant of the memo. +const ZSA_MEMO_SIZE: usize = NOTE_PLAINTEXT_SIZE - COMPACT_ZSA_NOTE_SIZE; + /// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. /// /// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs @@ -50,6 +58,8 @@ pub(crate) fn prf_ock_orchard( ) } +/// Domain-specific requirements: +/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. fn orchard_parse_note_plaintext_without_memo( domain: &OrchardDomain, plaintext: &[u8], @@ -61,9 +71,8 @@ where assert!(plaintext.len() >= COMPACT_NOTE_SIZE); // Check note plaintext version - if plaintext[0] != 0x02 { - return None; - } + // and parse the asset type accordingly. + let note_type = parse_version_and_asset_type(plaintext)?; // The unwraps below are guaranteed to succeed by the assertion above let diversifier = Diversifier::from_bytes(plaintext[1..12].try_into().unwrap()); @@ -76,11 +85,25 @@ where let pk_d = get_validated_pk_d(&diversifier)?; let recipient = Address::from_parts(diversifier, pk_d); - // TODO: add note_type - let note = Option::from(Note::from_parts(recipient, value, NoteType::native(), domain.rho, rseed))?; + + let note = Option::from(Note::from_parts(recipient, value, note_type, domain.rho, rseed))?; Some((note, recipient)) } +fn parse_version_and_asset_type(plaintext: &[u8]) -> Option { + // TODO: make this constant-time? + match plaintext[0] { + 0x02 => Some(NoteType::native()), + 0x03 if plaintext.len() >= COMPACT_ZSA_NOTE_SIZE => { + let bytes = &plaintext[COMPACT_NOTE_SIZE..COMPACT_ZSA_NOTE_SIZE] + .try_into() + .unwrap(); + NoteType::from_bytes(bytes).into() + } + _ => None, + } +} + /// Orchard-specific note encryption logic. #[derive(Debug)] pub struct OrchardDomain { @@ -125,7 +148,7 @@ impl Domain for OrchardDomain { type ValueCommitment = ValueCommitment; type ExtractedCommitment = ExtractedNoteCommitment; type ExtractedCommitmentBytes = [u8; 32]; - type Memo = [u8; 512]; // TODO use a more interesting type + type Memo = [u8; MEMO_SIZE]; // TODO use a more interesting type fn derive_esk(note: &Self::Note) -> Option { Some(note.esk()) @@ -169,13 +192,23 @@ impl Domain for OrchardDomain { _: &Self::Recipient, memo: &Self::Memo, ) -> NotePlaintextBytes { + let is_native: bool = note.note_type().is_native().into(); + let mut np = [0; NOTE_PLAINTEXT_SIZE]; - np[0] = 0x02; + np[0] = if is_native { 0x02 } else { 0x03 }; np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); np[12..20].copy_from_slice(¬e.value().to_bytes()); // todo: add note_type np[20..52].copy_from_slice(note.rseed().as_bytes()); - np[52..].copy_from_slice(memo); + if is_native { + np[52..].copy_from_slice(memo); + } else { + let zsa_type = note.note_type().to_bytes(); + np[52..84].copy_from_slice(&zsa_type); + let short_memo = &memo[0..memo.len() - ZSA_TYPE_SIZE]; + np[84..].copy_from_slice(short_memo); + // TODO: handle full-size memo or make short_memo explicit. + }; NotePlaintextBytes(np) } @@ -242,9 +275,20 @@ impl Domain for OrchardDomain { } fn extract_memo(&self, plaintext: &NotePlaintextBytes) -> Self::Memo { - plaintext.0[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE] - .try_into() - .unwrap() + let mut memo = [0; MEMO_SIZE]; + match get_note_version(plaintext) { + 0x02 => { + let full_memo = &plaintext.0[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]; + memo.copy_from_slice(full_memo); + } + 0x03 => { + // ZSA note plaintext have a shorter memo. + let short_memo = &plaintext.0[COMPACT_ZSA_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]; + memo[..ZSA_MEMO_SIZE].copy_from_slice(short_memo); + } + _ => {} + }; + memo } fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { @@ -272,6 +316,10 @@ impl BatchDomain for OrchardDomain { } } +fn get_note_version(plaintext: &NotePlaintextBytes) -> u8 { + plaintext.0[0] +} + /// Implementation of in-band secret distribution for Orchard bundles. pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; @@ -294,7 +342,7 @@ pub struct CompactAction { nullifier: Nullifier, cmx: ExtractedNoteCommitment, ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: [u8; 52], + enc_ciphertext: [u8; COMPACT_NOTE_SIZE], } impl fmt::Debug for CompactAction { @@ -309,7 +357,7 @@ impl From<&Action> for CompactAction { nullifier: *action.nullifier(), cmx: *action.cmx(), ephemeral_key: action.ephemeral_key(), - enc_ciphertext: action.encrypted_note().enc_ciphertext[..52] + enc_ciphertext: action.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE] .try_into() .unwrap(), } @@ -354,13 +402,13 @@ impl CompactAction { #[cfg(test)] mod tests { + use proptest::prelude::*; use rand::rngs::OsRng; use zcash_note_encryption::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, + try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; - use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; use crate::note::NoteType; use crate::{ action::Action, @@ -368,12 +416,55 @@ mod tests { DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey, }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, TransmittedNoteCiphertext}, + note::{ + testing::arb_note, ExtractedNoteCommitment, Nullifier, RandomSeed, + TransmittedNoteCiphertext, + }, primitives::redpallas, value::{NoteValue, ValueCommitment}, Address, Note, }; + use super::{get_note_version, orchard_parse_note_plaintext_without_memo}; + use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; + + proptest! { + #[test] + fn test_encoding_roundtrip( + note in arb_note(NoteValue::from_raw(10)), + ) { + let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; + + // Encode. + let plaintext = OrchardDomain::note_plaintext_bytes(¬e, ¬e.recipient(), memo); + + // Decode. + let domain = OrchardDomain { rho: note.rho() }; + let parsed_version = get_note_version(&plaintext); + let parsed_memo = domain.extract_memo(&plaintext); + + let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &plaintext.0, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + if parsed_note.note_type().is_native().into() { + assert_eq!(parsed_version, 0x02); + assert_eq!(&parsed_memo, memo); + } else { + assert_eq!(parsed_version, 0x03); + let mut short_memo = *memo; + short_memo[512 - 32..].copy_from_slice(&[0; 32]); + assert_eq!(parsed_memo, short_memo); + } + } + } + #[test] fn test_vectors() { let test_vectors = crate::test_vectors::note_encryption::test_vectors(); @@ -417,7 +508,17 @@ mod tests { assert_eq!(ock.as_ref(), tv.ock); let recipient = Address::from_parts(d, pk_d); +<<<<<<< HEAD let note = Note::from_parts(recipient, value, NoteType::native(), rho, rseed).unwrap(); +======= + + let note_type = match tv.note_type { + None => NoteType::native(), + Some(type_bytes) => NoteType::from_bytes(&type_bytes).unwrap(), + }; + + let note = Note::from_parts(recipient, value, note_type, rho, rseed); +>>>>>>> ZSA note encryption in Orchard crate (#3) assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); let action = Action::from_parts( @@ -456,7 +557,8 @@ mod tests { assert_eq!(decrypted_note, note); assert_eq!(decrypted_to, recipient); } - None => panic!("Compact note decryption failed"), + None => assert!(tv.note_type.is_some(), "Compact note decryption failed"), + // Ignore that ZSA notes are not detected in compact decryption. } match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption.rs index 10ac4f5e0..7d2b7c960 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption.rs @@ -1,4 +1,4 @@ -//! Test vectors for Orchard key components. +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_note_encryption) pub(crate) struct TestVector { pub(crate) incoming_viewing_key: [u8; 64], @@ -20,10 +20,10 @@ pub(crate) struct TestVector { pub(crate) ock: [u8; 32], pub(crate) op: [u8; 64], pub(crate) c_out: [u8; 80], + pub(crate) note_type: Option<[u8; 32]>, } pub(crate) fn test_vectors() -> Vec { - // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_note_encryption.py vec![ TestVector { incoming_viewing_key: [ @@ -97,34 +97,34 @@ pub(crate) fn test_vectors() -> Vec { 0xc1, 0x3e, 0x71, 0x01, ], rho: [ - 0xc5, 0x96, 0xfb, 0xd3, 0x2e, 0xbb, 0xcb, 0xad, 0xae, 0x60, 0xd2, 0x85, 0xc7, 0xd7, - 0x5f, 0xa8, 0x36, 0xf9, 0xd2, 0xfa, 0x86, 0x10, 0x0a, 0xb8, 0x58, 0xea, 0x2d, 0xe1, - 0xf1, 0x1c, 0x83, 0x06, + 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, + 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, + 0x05, 0xee, 0xf3, 0x27, ], cmx: [ - 0xa5, 0x70, 0x6f, 0x3d, 0x1b, 0x68, 0x8e, 0x9d, 0xc6, 0x34, 0xee, 0xe4, 0xe6, 0x5b, - 0x02, 0x8a, 0x43, 0xee, 0xae, 0xd2, 0x43, 0x5b, 0xea, 0x2a, 0xe3, 0xd5, 0x16, 0x05, - 0x75, 0xc1, 0x1a, 0x3b, + 0x23, 0x75, 0x7c, 0x51, 0x58, 0x21, 0xcb, 0xc1, 0x84, 0x3c, 0x9a, 0x45, 0x7b, 0x7e, + 0x6a, 0xe6, 0x01, 0xad, 0xd2, 0xea, 0x10, 0xb9, 0xc8, 0x6d, 0x6b, 0x31, 0x7c, 0xe2, + 0xf1, 0x7b, 0xd9, 0x21, ], esk: [ - 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, 0xd3, 0x5a, 0xd7, 0x46, - 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, 0x20, 0xa6, 0x25, 0xff, - 0x38, 0x77, 0xea, 0x3f, + 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, 0x8b, 0xfe, 0x9b, 0x38, + 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, 0x8e, 0x33, 0x35, 0x4f, + 0xff, 0xf1, 0xbd, 0x1a, ], ephemeral_key: [ - 0xad, 0xdb, 0x47, 0xb6, 0xac, 0x5d, 0xfc, 0x16, 0x55, 0x89, 0x23, 0xd3, 0xa8, 0xf3, - 0x76, 0x09, 0x5c, 0x69, 0x5c, 0x04, 0x7c, 0x4e, 0x32, 0x66, 0xae, 0x67, 0x69, 0x87, - 0xf7, 0xe3, 0x13, 0x81, + 0x8a, 0x5e, 0x13, 0x2c, 0x3a, 0x07, 0x04, 0xf2, 0x45, 0x6f, 0xbd, 0x77, 0x7a, 0x13, + 0xd6, 0xec, 0x57, 0x65, 0x56, 0x71, 0xdb, 0x07, 0x2a, 0x7d, 0x27, 0x6a, 0xd9, 0x69, + 0xf5, 0xec, 0x45, 0x17, ], shared_secret: [ - 0x30, 0x3c, 0x1c, 0x3f, 0x2b, 0xcb, 0xb9, 0xd8, 0x49, 0x70, 0x15, 0xa6, 0xdf, 0xca, - 0x95, 0x4e, 0xce, 0x0d, 0x3b, 0x6c, 0xf1, 0x0a, 0xb9, 0xf7, 0x19, 0xeb, 0x89, 0x19, - 0x9e, 0xdf, 0xe9, 0x89, + 0x36, 0xd5, 0x4c, 0xab, 0xc6, 0x7f, 0x6c, 0xc7, 0x26, 0xa7, 0x30, 0xf3, 0xa0, 0xce, + 0xed, 0x58, 0x53, 0xf0, 0x8c, 0xd3, 0x81, 0x46, 0xc8, 0x34, 0x25, 0x98, 0x98, 0x7c, + 0x21, 0x50, 0x48, 0xa5, ], k_enc: [ - 0xef, 0x9d, 0x62, 0x25, 0x68, 0x7c, 0x2c, 0x91, 0x7b, 0x5c, 0xad, 0xa1, 0x75, 0x23, - 0xe8, 0xfb, 0xdb, 0x08, 0x82, 0x25, 0xaf, 0x2d, 0xb5, 0x72, 0xbb, 0x40, 0x0e, 0x44, - 0x8b, 0x5e, 0xa8, 0x71, + 0x82, 0xc4, 0x32, 0x65, 0x33, 0x7f, 0x1a, 0xb3, 0x7b, 0x18, 0xdf, 0x27, 0x75, 0x48, + 0x61, 0x82, 0x63, 0xb8, 0x02, 0x4d, 0x9b, 0x14, 0x5a, 0x05, 0xad, 0xe2, 0xeb, 0x54, + 0x79, 0x18, 0x03, 0x20, ], p_enc: [ 0x02, 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, 0x8d, 0x5f, @@ -170,69 +170,70 @@ pub(crate) fn test_vectors() -> Vec { 0xee, 0xcc, 0x40, 0xa9, ], c_enc: [ - 0x1a, 0x9a, 0xdb, 0x14, 0x24, 0x98, 0xe3, 0xdc, 0xc7, 0x6f, 0xed, 0x77, 0x86, 0x14, - 0xdd, 0x31, 0x6c, 0x02, 0xfb, 0xb8, 0xba, 0x92, 0x44, 0xae, 0x4c, 0x2e, 0x32, 0xa0, - 0x7d, 0xae, 0xec, 0xa4, 0x12, 0x26, 0xb9, 0x8b, 0xfe, 0x74, 0xf9, 0xfc, 0xb2, 0x28, - 0xcf, 0xc1, 0x00, 0xf3, 0x18, 0x0f, 0x57, 0x75, 0xec, 0xe3, 0x8b, 0xe7, 0xed, 0x45, - 0xd9, 0x40, 0x21, 0xf4, 0x40, 0x1b, 0x2a, 0x4d, 0x75, 0x82, 0xb4, 0x28, 0xd4, 0x9e, - 0xc7, 0xf5, 0xb5, 0xa4, 0x98, 0x97, 0x3e, 0x60, 0xe3, 0x8e, 0x74, 0xf5, 0xc3, 0xe5, - 0x77, 0x82, 0x7c, 0x38, 0x28, 0x57, 0xd8, 0x16, 0x6b, 0x54, 0xe6, 0x4f, 0x66, 0xef, - 0x5c, 0x7e, 0x8c, 0x9b, 0xaa, 0x2a, 0x3f, 0xa9, 0xe3, 0x7d, 0x08, 0x77, 0x17, 0xd5, - 0xe9, 0x6b, 0xc2, 0xf7, 0x3d, 0x03, 0x14, 0x50, 0xdc, 0x24, 0x32, 0xba, 0x49, 0xd8, - 0xb7, 0x4d, 0xb2, 0x13, 0x09, 0x9e, 0xa9, 0xba, 0x04, 0xeb, 0x63, 0xb6, 0x57, 0x4d, - 0x46, 0xc0, 0x3c, 0xe7, 0x90, 0x0d, 0x4a, 0xc4, 0xbb, 0x18, 0x8e, 0xe9, 0x03, 0x0d, - 0x7f, 0x69, 0xc8, 0x95, 0xa9, 0x4f, 0xc1, 0x82, 0xf2, 0x25, 0xa9, 0x4f, 0x0c, 0xde, - 0x1b, 0x49, 0x88, 0x68, 0x71, 0xa3, 0x76, 0x34, 0x1e, 0xa9, 0x41, 0x71, 0xbe, 0xfd, - 0x95, 0xa8, 0x30, 0xfa, 0x18, 0x40, 0x70, 0x97, 0xdc, 0xa5, 0x11, 0x02, 0x54, 0x63, - 0xd4, 0x37, 0xe9, 0x69, 0x5c, 0xaa, 0x07, 0x9a, 0x2f, 0x68, 0xcd, 0xc7, 0xf2, 0xc1, - 0x32, 0x67, 0xbf, 0xf4, 0x19, 0x51, 0x37, 0xfa, 0x89, 0x53, 0x25, 0x2a, 0x81, 0xb2, - 0xaf, 0xa1, 0x58, 0x2b, 0x9b, 0xfb, 0x4a, 0xc9, 0x60, 0x37, 0xed, 0x29, 0x91, 0xd3, - 0xcb, 0xc7, 0xd5, 0x4a, 0xff, 0x6e, 0x62, 0x1b, 0x06, 0xa7, 0xb2, 0xb9, 0xca, 0xf2, - 0x95, 0x5e, 0xfa, 0xf4, 0xea, 0x8e, 0xfc, 0xfd, 0x02, 0x3a, 0x3c, 0x17, 0x48, 0xdf, - 0x3c, 0xbd, 0x43, 0xe0, 0xb9, 0xa8, 0xb0, 0x94, 0x56, 0x88, 0xd5, 0x20, 0x56, 0xc1, - 0xd1, 0x6e, 0xea, 0x37, 0xe7, 0x98, 0xba, 0x31, 0xdc, 0x3e, 0x5d, 0x49, 0x52, 0xbd, - 0x51, 0xec, 0x76, 0x9d, 0x57, 0x88, 0xb6, 0xe3, 0x5f, 0xe9, 0x04, 0x2b, 0x95, 0xd4, - 0xd2, 0x17, 0x81, 0x40, 0x0e, 0xaf, 0xf5, 0x86, 0x16, 0xad, 0x56, 0x27, 0x96, 0x63, - 0x6a, 0x50, 0xb8, 0xed, 0x6c, 0x7f, 0x98, 0x1d, 0xc7, 0xba, 0x81, 0x4e, 0xff, 0x15, - 0x2c, 0xb2, 0x28, 0xa2, 0xea, 0xd2, 0xf8, 0x32, 0x66, 0x2f, 0xa4, 0xa4, 0xa5, 0x07, - 0x97, 0xb0, 0xf8, 0x5b, 0x62, 0xd0, 0x8b, 0x1d, 0xd2, 0xd8, 0xe4, 0x3b, 0x4a, 0x5b, - 0xfb, 0xb1, 0x59, 0xed, 0x57, 0x8e, 0xf7, 0x47, 0x5d, 0xe0, 0xad, 0xa1, 0x3e, 0x17, - 0xad, 0x87, 0xcc, 0x23, 0x05, 0x67, 0x2b, 0xcc, 0x55, 0xa8, 0x88, 0x13, 0x17, 0xfd, - 0xc1, 0xbf, 0xc4, 0x59, 0xb6, 0x8b, 0x2d, 0xf7, 0x0c, 0xad, 0x37, 0x70, 0xed, 0x0f, - 0xd0, 0x2d, 0x64, 0xb9, 0x6f, 0x2b, 0xbf, 0x6f, 0x8f, 0x63, 0x2e, 0x86, 0x6c, 0xa5, - 0xd1, 0x96, 0xd2, 0x48, 0xad, 0x05, 0xc3, 0xde, 0x64, 0x41, 0x48, 0xa8, 0x0b, 0x51, - 0xad, 0xa9, 0x5b, 0xd0, 0x8d, 0x73, 0xcd, 0xbb, 0x45, 0x26, 0x4f, 0x3b, 0xd1, 0x13, - 0x83, 0x5b, 0x46, 0xf9, 0xbe, 0x7b, 0x6d, 0x23, 0xa4, 0x3b, 0xdd, 0xfe, 0x1e, 0x74, - 0x08, 0xc9, 0x70, 0x31, 0xe1, 0xa8, 0x21, 0x4b, 0xab, 0x46, 0x39, 0x10, 0x44, 0xb7, - 0x00, 0xd3, 0x8f, 0x51, 0x92, 0xc5, 0x7f, 0xe6, 0xf8, 0x71, 0x59, 0xb5, 0x55, 0x12, - 0x09, 0x4e, 0x29, 0xd2, 0xce, 0xba, 0xb8, 0x68, 0xc8, 0xf1, 0xad, 0xba, 0xd5, 0x70, - 0x77, 0xcb, 0xeb, 0x5e, 0x69, 0x65, 0x85, 0x82, 0xbf, 0x98, 0xd1, 0x9d, 0x64, 0xf4, - 0x4b, 0x0d, 0x50, 0xc7, 0xe2, 0x20, 0x9a, 0xb3, 0xfc, 0x56, 0xb4, 0xf4, 0x09, 0x12, - 0x3a, 0xae, 0xb0, 0x26, 0x3a, 0x22, 0x45, 0x1b, 0xc1, 0x4e, 0xd7, 0x56, 0xd0, 0x48, - 0x38, 0x5a, 0xed, 0xbb, 0x86, 0xa8, 0x46, 0x77, 0xbb, 0x2d, 0x21, 0xc5, 0x2c, 0xc9, - 0x49, 0x41, 0x47, 0xbf, 0x0f, 0xb1, 0x02, 0x74, 0x52, 0x82, 0x99, 0x09, 0x09, 0x72, - 0x62, 0x28, 0x18, 0x6e, 0x02, 0xc8, + 0x93, 0xe0, 0x48, 0x74, 0xb5, 0x83, 0x7c, 0x26, 0x1d, 0xaf, 0x1a, 0x27, 0xb7, 0x83, + 0xec, 0x48, 0x65, 0xd3, 0xbb, 0x72, 0x8e, 0xb1, 0x61, 0xda, 0xed, 0xb8, 0x44, 0x6a, + 0xb3, 0x8f, 0x07, 0x8e, 0xa8, 0x66, 0x2e, 0x4d, 0x2e, 0x9d, 0x00, 0xa3, 0x95, 0x27, + 0xdc, 0xde, 0x51, 0x7a, 0xc3, 0xdb, 0xf9, 0xd2, 0x7e, 0x3c, 0x79, 0xfa, 0x88, 0x1a, + 0xbb, 0x48, 0xb7, 0x0d, 0xbc, 0x28, 0xdd, 0xf4, 0xaf, 0x81, 0xae, 0xed, 0x2a, 0x29, + 0x86, 0x00, 0x51, 0x08, 0x48, 0xed, 0xbd, 0xc4, 0x2e, 0x88, 0x95, 0x48, 0x70, 0xd5, + 0xd6, 0x01, 0xcd, 0xf2, 0x90, 0x18, 0x1b, 0x53, 0x91, 0x05, 0xb9, 0xf6, 0x13, 0x86, + 0xcb, 0x07, 0x84, 0x6b, 0xc8, 0xe3, 0x19, 0xdf, 0xab, 0x8e, 0x10, 0x97, 0x66, 0xa2, + 0x8c, 0x1e, 0x0b, 0xbf, 0x91, 0x32, 0x02, 0xce, 0xcd, 0x1b, 0x48, 0x17, 0xa2, 0x28, + 0x2f, 0xc2, 0x9e, 0xd4, 0x4d, 0x9b, 0x04, 0x04, 0x9d, 0xe5, 0x5a, 0xcf, 0x54, 0x99, + 0xe5, 0xf5, 0x65, 0xd4, 0x8b, 0x8f, 0x19, 0x72, 0xc0, 0x43, 0x84, 0x77, 0x96, 0x23, + 0x0d, 0xc6, 0x8f, 0x32, 0x57, 0xc0, 0x85, 0x29, 0x14, 0x8c, 0x8e, 0x0c, 0x32, 0x7b, + 0x25, 0xb4, 0x59, 0x87, 0x7c, 0xde, 0xd9, 0x8f, 0xf7, 0x8e, 0x81, 0xfa, 0x69, 0x2e, + 0x14, 0xf8, 0xfd, 0xa1, 0xfe, 0x52, 0x4f, 0xf1, 0x50, 0x18, 0x1f, 0x73, 0x6e, 0xd3, + 0xa8, 0x8e, 0xc7, 0x89, 0xdc, 0x15, 0x95, 0x4a, 0x02, 0x63, 0x9a, 0x8a, 0x20, 0xca, + 0x38, 0xd8, 0x99, 0xbf, 0xd1, 0xc5, 0x73, 0xb0, 0x41, 0xee, 0x7b, 0xf2, 0x2b, 0x96, + 0x75, 0xbd, 0xa8, 0xc4, 0xb0, 0x58, 0xa0, 0x5a, 0x49, 0x33, 0x03, 0xb1, 0x1f, 0x35, + 0x81, 0xc1, 0x9d, 0x2d, 0xa9, 0x96, 0x6a, 0x71, 0x06, 0x6e, 0xc1, 0x7d, 0xcc, 0xd3, + 0x48, 0x20, 0x7e, 0xb3, 0x14, 0xf6, 0xcf, 0xc9, 0xd0, 0x6a, 0x62, 0x14, 0xc6, 0x72, + 0x10, 0x97, 0xa5, 0x2e, 0x27, 0x76, 0x66, 0x7c, 0x6b, 0xe9, 0xc8, 0x86, 0x2b, 0x17, + 0x3d, 0xb0, 0xe8, 0x04, 0xb1, 0x2c, 0xaa, 0xe9, 0xd9, 0xfa, 0x09, 0xf3, 0xf4, 0x8c, + 0xaf, 0x4b, 0xf7, 0x56, 0xa2, 0x78, 0x95, 0x0a, 0x25, 0x4e, 0xc4, 0x14, 0x76, 0x77, + 0xaa, 0xca, 0x21, 0x42, 0x96, 0x08, 0x1a, 0x2f, 0x62, 0x4a, 0x92, 0x78, 0x94, 0x6e, + 0x68, 0x9d, 0xd9, 0x14, 0x02, 0x90, 0x92, 0xe7, 0xfa, 0x8f, 0xbc, 0x8a, 0x04, 0x46, + 0x7d, 0x60, 0xed, 0xff, 0x5d, 0x97, 0xcb, 0x65, 0x09, 0xa0, 0xc7, 0x2c, 0xed, 0x77, + 0xac, 0xa8, 0x71, 0x30, 0x8e, 0x7d, 0xe2, 0xbe, 0xb1, 0x52, 0x0a, 0x34, 0x17, 0xd7, + 0x21, 0x3a, 0x9a, 0xbd, 0x47, 0x35, 0x8c, 0x4f, 0x32, 0x9f, 0x0f, 0x64, 0x41, 0x92, + 0x10, 0xa9, 0x9d, 0xb2, 0xde, 0x6e, 0x6d, 0x89, 0x21, 0xb0, 0xf4, 0xf9, 0x9f, 0xd6, + 0x45, 0xfa, 0xe0, 0xd6, 0x29, 0xce, 0x22, 0x11, 0x90, 0x5f, 0x25, 0xf4, 0x0d, 0x12, + 0x0b, 0x63, 0x27, 0x93, 0x75, 0xb5, 0x43, 0xc3, 0x1e, 0x3b, 0x55, 0x7e, 0x57, 0xa7, + 0xa8, 0x7c, 0x61, 0x79, 0xeb, 0xd3, 0x4f, 0x6d, 0xbb, 0x92, 0x0e, 0xc5, 0xe0, 0x5d, + 0x6a, 0x77, 0xec, 0xdf, 0x36, 0xb4, 0x57, 0xba, 0xb4, 0x56, 0x6c, 0x40, 0x8f, 0xb5, + 0x7d, 0xfc, 0xdd, 0xda, 0xa4, 0x2c, 0x51, 0x34, 0xaf, 0x3e, 0x97, 0x8d, 0xbf, 0xd0, + 0xdf, 0xb0, 0xca, 0x4f, 0xfa, 0xf1, 0x65, 0x0a, 0xbe, 0xe1, 0x62, 0x5f, 0x7f, 0x4b, + 0xf8, 0x25, 0x06, 0x01, 0x00, 0x64, 0x5b, 0x54, 0xc0, 0x04, 0x1f, 0xbf, 0xbd, 0xef, + 0xf7, 0xb9, 0x38, 0x04, 0xe9, 0xcc, 0x0c, 0xcd, 0x6f, 0x27, 0xbe, 0x40, 0x01, 0x6c, + 0x32, 0xd4, 0x2f, 0xe3, 0x66, 0xfa, 0xaa, 0x86, 0x87, 0xc2, 0xd1, 0x92, 0x61, 0x9f, + 0x56, 0x5b, 0x0c, 0x70, 0xea, 0x6a, 0x3f, 0x79, 0xd5, 0x3a, 0x52, 0x41, 0xe6, 0x9c, + 0x3c, 0xa6, 0x87, 0xa1, 0x12, 0xfb, 0x16, 0xc2, 0x5c, 0xc0, 0x83, 0x17, 0xdb, 0xa4, + 0x23, 0x97, 0x0c, 0x32, 0xdf, 0xb4, 0xbd, 0x69, 0x22, 0xe3, 0x36, 0xab, 0xf2, 0xfd, + 0xe2, 0xc3, 0xaa, 0x5d, 0xb2, 0x93, 0xef, 0x27, 0x47, 0x87, 0x6c, 0x8b, 0xd8, 0x6e, + 0xa1, 0x87, 0xcb, 0x60, 0x1a, 0xf7, ], ock: [ - 0x4e, 0x9d, 0x45, 0x94, 0x6b, 0x3e, 0xea, 0xe7, 0xfe, 0x30, 0x5d, 0x5b, 0x90, 0x50, - 0x36, 0x14, 0x1f, 0x9f, 0x40, 0x09, 0xa6, 0x29, 0x4b, 0x96, 0xc7, 0x22, 0xa4, 0xa0, - 0xbe, 0x68, 0x5d, 0xff, + 0xb3, 0x25, 0xeb, 0xe5, 0x7a, 0x2c, 0x40, 0xa8, 0xb2, 0x11, 0xcf, 0xdf, 0x72, 0xa1, + 0xa2, 0x44, 0xf1, 0x53, 0x42, 0x85, 0x98, 0x88, 0xa3, 0x64, 0x52, 0x3e, 0xfd, 0x2a, + 0xc6, 0x6a, 0x1a, 0xd6, ], op: [ 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, - 0x49, 0x50, 0x69, 0x2c, 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, - 0xd3, 0x5a, 0xd7, 0x46, 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, - 0x20, 0xa6, 0x25, 0xff, 0x38, 0x77, 0xea, 0x3f, + 0x49, 0x50, 0x69, 0x2c, 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, + 0x8b, 0xfe, 0x9b, 0x38, 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, + 0x8e, 0x33, 0x35, 0x4f, 0xff, 0xf1, 0xbd, 0x1a, ], c_out: [ - 0xcb, 0xdf, 0x68, 0xa5, 0x7f, 0xb4, 0xa4, 0x6f, 0x34, 0x60, 0xff, 0x22, 0x7b, 0xc6, - 0x18, 0xda, 0xe1, 0x12, 0x29, 0x45, 0xb3, 0x80, 0xc7, 0xe5, 0x49, 0xcf, 0x4a, 0x6e, - 0x8b, 0xf3, 0x75, 0x49, 0xba, 0xe1, 0x89, 0x1f, 0xd8, 0xd1, 0xa4, 0x94, 0x4f, 0xdf, - 0x41, 0x0f, 0x07, 0x02, 0xed, 0xa5, 0x44, 0x2f, 0x0e, 0xa0, 0x1a, 0x5d, 0xf0, 0x12, - 0xa0, 0xae, 0x4d, 0x84, 0xed, 0x79, 0x80, 0x33, 0x28, 0xbd, 0x1f, 0xd5, 0xfa, 0xc7, - 0x19, 0x21, 0x6a, 0x77, 0x6d, 0xe6, 0x4f, 0xd1, 0x67, 0xdb, - ], + 0x55, 0xb8, 0x90, 0x7c, 0x6d, 0x45, 0x4b, 0x83, 0x63, 0x4f, 0x1b, 0x9a, 0x1a, 0xa3, + 0xc3, 0xc9, 0x8a, 0xdc, 0x77, 0xd9, 0x6c, 0x2f, 0x62, 0x49, 0xec, 0x66, 0xdb, 0xae, + 0x4d, 0x0c, 0xc9, 0x40, 0xd7, 0x26, 0xbc, 0xd1, 0xec, 0x91, 0x18, 0x9f, 0xd3, 0x04, + 0x9a, 0x33, 0xf2, 0xea, 0x7d, 0x8b, 0x74, 0xaa, 0xc1, 0x7c, 0xda, 0x38, 0x83, 0x80, + 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, + 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -306,34 +307,34 @@ pub(crate) fn test_vectors() -> Vec { 0x25, 0x7a, 0xd8, 0xb3, ], rho: [ - 0x33, 0x88, 0xda, 0x05, 0x06, 0xda, 0x9e, 0xa2, 0xd5, 0x16, 0x73, 0x9b, 0x95, 0x1c, - 0x7c, 0xc0, 0x58, 0x53, 0x36, 0xb4, 0x4d, 0xf9, 0xb3, 0xb5, 0x0e, 0x48, 0x93, 0xe4, - 0xb1, 0x84, 0x92, 0x11, + 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, + 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, + 0x4d, 0xb2, 0xc7, 0x31, ], cmx: [ - 0x9e, 0x04, 0x32, 0xb2, 0xb3, 0x33, 0xcd, 0xe8, 0xce, 0x92, 0x1b, 0x77, 0xca, 0x7e, - 0x9e, 0x41, 0x51, 0xe3, 0x74, 0xd5, 0x16, 0xcd, 0xa1, 0x17, 0x63, 0x83, 0x6a, 0xf3, - 0xb6, 0x6f, 0x5b, 0x15, + 0x59, 0xb6, 0xf3, 0xd4, 0x03, 0x22, 0x3d, 0x6c, 0xe4, 0x3d, 0xed, 0xae, 0xe2, 0x35, + 0xfc, 0xa9, 0x5c, 0xc8, 0xb2, 0x49, 0x94, 0x1c, 0xcd, 0xb6, 0x6f, 0x3f, 0x61, 0x1c, + 0xc5, 0xe9, 0xf9, 0x0f, ], esk: [ - 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, 0x4d, 0x80, 0x4a, 0x17, - 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, 0x92, 0x1c, 0xd5, 0xda, - 0x8a, 0x6e, 0x1a, 0x08, + 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, 0xdd, 0x73, 0x4d, 0x0e, + 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, 0x22, 0xc0, 0x61, 0xe0, + 0xbd, 0xc9, 0xce, 0x14, ], ephemeral_key: [ - 0x91, 0x92, 0x3e, 0xd8, 0x2b, 0x76, 0xd7, 0x97, 0x30, 0x7c, 0xaa, 0x23, 0x02, 0xc0, - 0xcf, 0x75, 0x56, 0x12, 0x17, 0x24, 0x98, 0x67, 0x53, 0x2a, 0xe5, 0x1c, 0x2e, 0xa0, - 0x05, 0xed, 0xad, 0xb6, + 0xd2, 0x9e, 0x0d, 0x00, 0x1e, 0xe7, 0x1e, 0x05, 0x99, 0x08, 0x65, 0x04, 0xd8, 0x62, + 0xc7, 0xf5, 0x2b, 0x08, 0x60, 0x77, 0x0d, 0x8a, 0x4b, 0x42, 0xa8, 0x68, 0x11, 0xac, + 0x31, 0x69, 0x85, 0x8c, ], shared_secret: [ - 0x53, 0xd7, 0xe4, 0x84, 0x3a, 0x36, 0xd5, 0x79, 0xb5, 0xa7, 0xc1, 0x04, 0x11, 0x96, - 0xbd, 0x4c, 0x85, 0x80, 0x5c, 0xcd, 0x0a, 0x3f, 0x95, 0xbc, 0x9e, 0x71, 0x06, 0x90, - 0xd1, 0x1b, 0x7a, 0xaa, + 0x11, 0xa0, 0xac, 0x79, 0x9a, 0x29, 0xb0, 0xed, 0x19, 0x5e, 0xd8, 0x7b, 0x13, 0x83, + 0x22, 0x26, 0x3b, 0xbb, 0x9c, 0x31, 0x00, 0x8c, 0x29, 0x59, 0xaf, 0x2f, 0xc6, 0x36, + 0x68, 0x7e, 0xd9, 0xb0, ], k_enc: [ - 0xc2, 0xe3, 0x38, 0x9d, 0x6f, 0xc3, 0xcd, 0x06, 0x7f, 0x59, 0x0a, 0x93, 0x73, 0x05, - 0x04, 0xad, 0x9b, 0x63, 0xc4, 0x55, 0x45, 0x69, 0xb9, 0x62, 0x0f, 0x3e, 0xf0, 0xb0, - 0x65, 0x94, 0xde, 0xd6, + 0x4b, 0xbf, 0x80, 0xe7, 0xa1, 0x70, 0x3a, 0xc1, 0x4a, 0xd7, 0xb5, 0x44, 0x8a, 0x2e, + 0x8e, 0x79, 0x49, 0x30, 0x49, 0xd1, 0x9a, 0x6a, 0x51, 0x31, 0x67, 0xd5, 0x5b, 0xdd, + 0x58, 0x6a, 0xc0, 0xd9, ], p_enc: [ 0x02, 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, 0x40, 0x50, @@ -379,69 +380,70 @@ pub(crate) fn test_vectors() -> Vec { 0x8b, 0x1e, 0x88, 0x6f, ], c_enc: [ - 0x6d, 0x21, 0x18, 0x0a, 0xc4, 0x74, 0x94, 0x57, 0x8a, 0x90, 0x06, 0xaf, 0x5b, 0xeb, - 0x4e, 0x34, 0x55, 0x59, 0xab, 0xdb, 0x0e, 0x23, 0xed, 0x52, 0x65, 0xaf, 0x79, 0xce, - 0x0c, 0xc5, 0x96, 0x71, 0xea, 0x31, 0x7b, 0x3e, 0xb1, 0x52, 0x93, 0xd1, 0xe0, 0x4a, - 0x9a, 0xd8, 0x39, 0x69, 0xab, 0x9e, 0x17, 0x08, 0xf2, 0x28, 0x85, 0x3a, 0x28, 0x1f, - 0xcf, 0x6c, 0x97, 0x60, 0xae, 0x71, 0x96, 0x5b, 0xb1, 0xd4, 0x45, 0x2e, 0x5e, 0xd0, - 0x06, 0x00, 0xab, 0x58, 0x94, 0x27, 0x75, 0xb7, 0x4e, 0x12, 0x62, 0xb4, 0x22, 0x5d, - 0x3b, 0x61, 0x9c, 0x31, 0x65, 0x96, 0xd7, 0xcf, 0x9c, 0x93, 0xbd, 0xb5, 0x2a, 0xfa, - 0x77, 0x8a, 0xa1, 0x20, 0x8d, 0x56, 0xd0, 0x69, 0xe5, 0x6e, 0x27, 0x79, 0x61, 0x4d, - 0x56, 0xf4, 0x36, 0x10, 0x72, 0xbc, 0x15, 0x16, 0xa9, 0xb4, 0x56, 0x2a, 0x4f, 0x54, - 0x63, 0xa5, 0x13, 0xc4, 0x59, 0x42, 0x15, 0x70, 0xf3, 0x34, 0xef, 0xb6, 0xbc, 0xd2, - 0x08, 0xf8, 0xf8, 0x05, 0x0e, 0x15, 0x3d, 0x4e, 0x61, 0xf3, 0x1e, 0xdd, 0xbb, 0x5a, - 0x98, 0xf1, 0x70, 0xd3, 0xd0, 0x80, 0xe8, 0xec, 0x3f, 0x65, 0x20, 0xb6, 0xa2, 0xd6, - 0x08, 0x83, 0xa5, 0x87, 0xff, 0x0e, 0x98, 0x21, 0x1c, 0x73, 0x45, 0x16, 0xb5, 0xdc, - 0xc7, 0x5e, 0xf2, 0x3c, 0xfb, 0x9f, 0x55, 0xf1, 0xde, 0xed, 0xf1, 0x26, 0xc2, 0xce, - 0x17, 0x27, 0x3f, 0x41, 0xdb, 0xbb, 0xbd, 0x2f, 0x49, 0xe3, 0x55, 0x77, 0x6e, 0xc0, - 0x46, 0x98, 0x35, 0xf7, 0x9d, 0x94, 0x80, 0x42, 0xf8, 0x42, 0x0f, 0x11, 0xe1, 0xab, - 0xd7, 0x45, 0x06, 0xb7, 0x8b, 0x5e, 0x41, 0xcb, 0xe0, 0xc7, 0x07, 0x17, 0xf4, 0x6e, - 0x7e, 0xb9, 0xac, 0xdc, 0x35, 0x1c, 0x94, 0x98, 0x83, 0x3a, 0xfd, 0xed, 0x93, 0x06, - 0xa0, 0x43, 0x5b, 0x10, 0xb8, 0x3a, 0xe3, 0x95, 0xd5, 0x7f, 0x5b, 0x0a, 0x5d, 0x41, - 0xa9, 0x34, 0x2d, 0x02, 0xec, 0x58, 0xb6, 0xee, 0x16, 0x87, 0x77, 0x50, 0x16, 0xb8, - 0x74, 0x9b, 0x28, 0x7a, 0xbd, 0xd3, 0xed, 0x1a, 0x83, 0x5e, 0xa8, 0xf3, 0xb1, 0x4d, - 0x08, 0x18, 0xfe, 0x0d, 0x5d, 0x9a, 0x48, 0xeb, 0x02, 0x13, 0x64, 0x0e, 0xec, 0xc1, - 0x9a, 0x5d, 0x16, 0x61, 0xdb, 0x82, 0x2b, 0x77, 0x9b, 0x08, 0x0c, 0xd8, 0xba, 0x7f, - 0x3a, 0x27, 0x23, 0x21, 0xee, 0x5d, 0xa2, 0x27, 0x8c, 0x53, 0x85, 0x67, 0xd0, 0xd9, - 0xbb, 0x28, 0xce, 0x64, 0x21, 0x31, 0x15, 0x03, 0xa4, 0xa0, 0x17, 0x14, 0xcf, 0x91, - 0x01, 0x55, 0x2b, 0xa5, 0xef, 0xc8, 0x5c, 0x94, 0xd5, 0xe5, 0x09, 0x72, 0x7e, 0x5e, - 0x01, 0x1c, 0x15, 0xb1, 0xb2, 0xec, 0xdf, 0xf3, 0x99, 0xc0, 0xbe, 0x33, 0x42, 0xab, - 0x6e, 0xdd, 0xa8, 0xe3, 0xed, 0x81, 0x1a, 0x7d, 0x9c, 0x9c, 0xa4, 0xbb, 0x71, 0xa5, - 0x63, 0xe1, 0x59, 0x78, 0xbf, 0x8e, 0x64, 0x04, 0xac, 0x79, 0x6e, 0xb7, 0x81, 0xfd, - 0x2c, 0xf2, 0x19, 0x1b, 0x2f, 0x4d, 0x40, 0x76, 0xd9, 0x3c, 0xcc, 0x80, 0xf7, 0xe5, - 0x92, 0xfa, 0x66, 0x9b, 0x72, 0x26, 0x57, 0x82, 0xee, 0x8f, 0x5c, 0xe3, 0x03, 0x12, - 0xd3, 0x51, 0x2b, 0x35, 0x49, 0x0a, 0xfe, 0x00, 0x6b, 0xad, 0xb1, 0x62, 0x0d, 0x1b, - 0x0c, 0x79, 0xfb, 0xc4, 0xbe, 0xc5, 0x65, 0xd7, 0x46, 0x1d, 0x68, 0xef, 0x72, 0x27, - 0x79, 0x11, 0x77, 0x6c, 0xd5, 0xa7, 0xb5, 0xfc, 0x6f, 0xa8, 0xb3, 0xee, 0xfd, 0x7a, - 0x39, 0xe8, 0xe5, 0xb4, 0xf6, 0xa5, 0x0c, 0x7d, 0x58, 0xd9, 0xeb, 0x08, 0x38, 0x0d, - 0x32, 0x0b, 0x36, 0xea, 0x04, 0x37, 0x00, 0xac, 0xa7, 0x64, 0xb4, 0x8c, 0x3d, 0xa4, - 0x93, 0x67, 0xfa, 0x93, 0x35, 0x6a, 0xaa, 0x4f, 0x87, 0x08, 0xea, 0x6e, 0x34, 0x59, - 0x81, 0x84, 0x5b, 0xe7, 0x37, 0x6d, 0xa7, 0x98, 0x40, 0x53, 0xef, 0x7d, 0xd4, 0xb6, - 0xa7, 0x27, 0x92, 0x35, 0x6a, 0x6c, 0x34, 0x62, 0x68, 0x88, 0xcc, 0x70, 0xde, 0x49, - 0x9e, 0xf9, 0x10, 0x26, 0x95, 0xd9, 0xdb, 0x12, 0xaf, 0x29, 0x62, 0xfc, 0x75, 0xd4, - 0x36, 0x56, 0x19, 0xdb, 0x0e, 0x87, 0x6c, 0xdb, 0x82, 0x02, 0xe8, 0x16, 0xfd, 0xc2, - 0xcd, 0xf3, 0x7a, 0xd3, 0xbe, 0x3b, + 0x1b, 0x42, 0x34, 0x80, 0xbf, 0x37, 0x67, 0xf5, 0xeb, 0xfc, 0x40, 0xb8, 0xc8, 0x9c, + 0xc5, 0x34, 0xf1, 0x65, 0xc3, 0x5d, 0x19, 0xc8, 0xda, 0x6c, 0x32, 0x10, 0xe9, 0x52, + 0xca, 0xd8, 0x23, 0xa7, 0x84, 0x60, 0x21, 0xc3, 0xde, 0x4a, 0x86, 0x93, 0xb7, 0x1e, + 0x28, 0x7f, 0x46, 0x86, 0xac, 0x0a, 0xdd, 0xce, 0xd9, 0x4e, 0xba, 0x81, 0x0a, 0x99, + 0x8b, 0x82, 0x3a, 0x4a, 0xd2, 0x41, 0xaa, 0x9f, 0x4a, 0x3a, 0xe4, 0x82, 0x5d, 0xe9, + 0x95, 0xdd, 0x58, 0x73, 0x56, 0x62, 0x44, 0xbb, 0xd8, 0x75, 0xd0, 0x1b, 0xf3, 0x28, + 0xe8, 0x22, 0xca, 0xfd, 0xb8, 0x3e, 0xd7, 0x75, 0x3a, 0x88, 0x85, 0xd7, 0xae, 0xf2, + 0x45, 0x5a, 0x15, 0x2e, 0x23, 0xdf, 0xa2, 0xd6, 0x99, 0xb3, 0x5c, 0x33, 0xd3, 0x61, + 0x07, 0x2a, 0xe5, 0xc5, 0x12, 0x43, 0x4d, 0x34, 0x6f, 0x6c, 0x56, 0xfb, 0x5f, 0x11, + 0xb0, 0xb6, 0x47, 0xcb, 0xca, 0xfe, 0x02, 0xd8, 0x84, 0x55, 0xa6, 0x30, 0xa3, 0x50, + 0x86, 0x2b, 0x3c, 0xd1, 0x51, 0x3b, 0x6d, 0x6e, 0x41, 0x17, 0xc7, 0x5e, 0xc4, 0xb1, + 0x2f, 0xd7, 0x5a, 0x90, 0xf8, 0x2d, 0xce, 0xa1, 0xc7, 0x71, 0xfd, 0xda, 0x24, 0xec, + 0xf0, 0xa3, 0xe5, 0xb2, 0xe8, 0xa2, 0x24, 0x23, 0x6e, 0xf0, 0x9a, 0x93, 0xab, 0x59, + 0xe5, 0x9b, 0xdf, 0xb8, 0x72, 0x86, 0x0c, 0xc2, 0xd9, 0x11, 0x34, 0xca, 0xf2, 0x13, + 0x98, 0x48, 0xe3, 0x9a, 0xa6, 0x4b, 0xa2, 0xe6, 0xd7, 0x25, 0x20, 0x54, 0xf3, 0x7a, + 0xd5, 0x5c, 0x2c, 0xe5, 0xf8, 0x1b, 0x33, 0xcc, 0xb6, 0x8a, 0x94, 0x73, 0x71, 0x24, + 0x3a, 0x77, 0xe8, 0x43, 0x67, 0xd9, 0xd3, 0x5b, 0x11, 0x68, 0x14, 0x10, 0xea, 0x79, + 0x8b, 0x03, 0x87, 0xb8, 0xf1, 0x0b, 0x1f, 0x89, 0xc6, 0x8a, 0xd1, 0xcc, 0xa9, 0xa3, + 0xe0, 0x32, 0xf3, 0x49, 0x98, 0x79, 0xc8, 0x9a, 0xe6, 0x38, 0x2f, 0x38, 0x97, 0x22, + 0x01, 0x1f, 0x49, 0x25, 0x14, 0x3e, 0xa8, 0x50, 0x73, 0xe4, 0xff, 0x0c, 0xcf, 0x6d, + 0x77, 0x9b, 0xc3, 0xbf, 0x4c, 0x1b, 0x95, 0xfc, 0x7c, 0xf7, 0xf9, 0x91, 0xa2, 0x16, + 0x2a, 0xb9, 0x45, 0x41, 0xf3, 0x99, 0x8e, 0xf6, 0xbc, 0x3f, 0xe8, 0x02, 0x54, 0xab, + 0xa4, 0x1f, 0x15, 0x23, 0x15, 0x03, 0x45, 0x1b, 0x15, 0xe1, 0x08, 0x52, 0xf8, 0x5b, + 0xd2, 0xd1, 0x15, 0x93, 0x53, 0x14, 0xcd, 0x80, 0xc1, 0x23, 0xbe, 0x0b, 0x53, 0x0f, + 0xaa, 0xd6, 0xb5, 0x07, 0x49, 0x68, 0x22, 0x1d, 0xa0, 0x4b, 0x54, 0x6d, 0x96, 0x21, + 0x63, 0x29, 0x9d, 0x52, 0xce, 0xf4, 0x1e, 0x29, 0x6d, 0xa5, 0x9c, 0xb0, 0x76, 0xdb, + 0xe8, 0x99, 0x70, 0x4b, 0x61, 0x73, 0x0c, 0x19, 0xbd, 0x22, 0x1a, 0xd2, 0xbd, 0x29, + 0x81, 0xea, 0x95, 0x1b, 0xe0, 0x2c, 0x9f, 0x5b, 0xdf, 0x92, 0xd9, 0x87, 0x07, 0x46, + 0xb2, 0xa5, 0x8c, 0x3d, 0x18, 0xa7, 0xd3, 0xe5, 0xe2, 0xc6, 0x3a, 0xc2, 0x61, 0x58, + 0x37, 0xbe, 0x1c, 0x6f, 0xe0, 0x03, 0x65, 0x6c, 0x1b, 0x3d, 0x71, 0x50, 0x5f, 0x5e, + 0x21, 0x88, 0x10, 0x4e, 0x98, 0x91, 0x1b, 0x6a, 0x5e, 0x3f, 0x52, 0x82, 0xfa, 0xc0, + 0xc8, 0xfa, 0x1b, 0xa3, 0x6f, 0xfc, 0x07, 0xdc, 0x7a, 0x40, 0x9d, 0xf2, 0xeb, 0xa8, + 0xc7, 0x5f, 0x70, 0xbd, 0x59, 0xa6, 0xf0, 0x65, 0x1d, 0xc1, 0xb1, 0xb5, 0x96, 0xde, + 0x6a, 0xce, 0xc7, 0x78, 0xe2, 0xe3, 0x2f, 0x1e, 0xd4, 0x6d, 0xf7, 0xa9, 0xae, 0xf5, + 0x1d, 0xfe, 0x5a, 0xa5, 0x24, 0x36, 0xea, 0x07, 0xf5, 0x05, 0xd3, 0x39, 0xf2, 0x03, + 0x45, 0x86, 0x61, 0xc8, 0x3a, 0x9a, 0x5a, 0x27, 0xaa, 0x48, 0xb5, 0xec, 0x47, 0xf8, + 0xd6, 0x0d, 0x2a, 0x41, 0x00, 0x1f, 0xce, 0x30, 0xff, 0x75, 0x3a, 0x8a, 0x8c, 0xe4, + 0x92, 0xef, 0xcd, 0x1f, 0x75, 0x3b, 0x7f, 0x4a, 0xd7, 0x36, 0x62, 0x64, 0x47, 0xd1, + 0xb6, 0xf0, 0x7a, 0x61, 0x7d, 0x4b, 0xfc, 0xdb, 0x48, 0xaf, 0xef, 0x08, 0x2d, 0xae, + 0x1d, 0x76, 0x54, 0x4e, 0x8b, 0x63, 0xad, 0xcb, 0xb6, 0x0e, 0x14, 0x96, 0x69, 0x32, + 0x60, 0xc7, 0x20, 0xe6, 0x72, 0x1e, 0x00, 0x20, 0xef, 0xa3, 0xf8, 0xd8, 0x8d, 0x15, + 0xb5, 0xaa, 0x48, 0xa1, 0xb2, 0x2c, ], ock: [ - 0x91, 0x36, 0x59, 0x30, 0x9e, 0xcf, 0xcd, 0xfd, 0x7e, 0x0c, 0xef, 0x23, 0xf8, 0x80, - 0xae, 0x4c, 0xf4, 0xd8, 0xcf, 0x67, 0x78, 0xb9, 0xc4, 0xe6, 0xf4, 0xc7, 0x71, 0x7b, - 0xf5, 0xca, 0xf0, 0x9e, + 0xab, 0xd0, 0xc2, 0x46, 0x97, 0xe4, 0x5b, 0x8b, 0xc4, 0x83, 0x0f, 0xb1, 0x46, 0x53, + 0x2e, 0xa0, 0xac, 0x84, 0x55, 0x81, 0xca, 0x35, 0x39, 0xd3, 0x41, 0x24, 0x73, 0x54, + 0x09, 0xd0, 0x15, 0xac, ], op: [ 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, - 0x4a, 0xd7, 0xc7, 0x84, 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, - 0x4d, 0x80, 0x4a, 0x17, 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, - 0x92, 0x1c, 0xd5, 0xda, 0x8a, 0x6e, 0x1a, 0x08, + 0x4a, 0xd7, 0xc7, 0x84, 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, + 0xdd, 0x73, 0x4d, 0x0e, 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, + 0x22, 0xc0, 0x61, 0xe0, 0xbd, 0xc9, 0xce, 0x14, ], c_out: [ - 0x4d, 0xf8, 0xda, 0x22, 0xec, 0x17, 0xf4, 0x16, 0xe0, 0x59, 0x1a, 0xac, 0xc1, 0x6b, - 0x6d, 0xd2, 0xbb, 0xbf, 0x47, 0xbe, 0x04, 0x30, 0x3d, 0xc8, 0x85, 0xd3, 0x5a, 0xc3, - 0xf9, 0x92, 0x3e, 0xea, 0x41, 0xf3, 0x6b, 0x3a, 0x4a, 0x5c, 0x5e, 0x73, 0x3e, 0x32, - 0x6e, 0x96, 0xdb, 0xe5, 0x5e, 0xf9, 0xe7, 0xe8, 0x42, 0x27, 0x0c, 0xbf, 0x46, 0x7c, - 0xdc, 0x16, 0x0e, 0xbf, 0x4f, 0x10, 0x9a, 0xd6, 0x92, 0x0a, 0x6a, 0xed, 0x4a, 0x01, - 0x71, 0xd9, 0x06, 0xe3, 0xe8, 0x13, 0x32, 0xe6, 0xc5, 0x61, - ], + 0xea, 0xdf, 0x7e, 0xeb, 0x10, 0x2d, 0xb1, 0x88, 0x58, 0x54, 0xc2, 0x9e, 0xb7, 0xb0, + 0x5c, 0x7c, 0x96, 0xbb, 0xb8, 0x90, 0x00, 0x2c, 0x4e, 0xd1, 0x14, 0xed, 0x62, 0xf5, + 0xf9, 0xcc, 0xb4, 0x41, 0x6b, 0x5e, 0xdd, 0xd9, 0xad, 0xb5, 0x5c, 0xe9, 0xc7, 0xa0, + 0xd8, 0x44, 0x2b, 0xbc, 0x8a, 0xfa, 0x5c, 0x77, 0xb9, 0x90, 0xad, 0x6d, 0x46, 0x12, + 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, + 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -515,34 +517,34 @@ pub(crate) fn test_vectors() -> Vec { 0xc5, 0xb3, 0x73, 0x3e, ], rho: [ - 0xbe, 0xf8, 0xcf, 0x16, 0x98, 0xe4, 0x78, 0x47, 0xd3, 0x8e, 0x1a, 0xaa, 0x88, 0x86, - 0x10, 0x77, 0xcd, 0xb5, 0xad, 0x4c, 0xf6, 0x6f, 0xe4, 0x2f, 0xd6, 0x52, 0x57, 0x81, - 0xb6, 0xd3, 0x4f, 0x1e, + 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, + 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, + 0x25, 0xb9, 0xff, 0x16, ], cmx: [ - 0xd8, 0x19, 0xa6, 0x37, 0x7a, 0xce, 0x33, 0xf9, 0x21, 0xf2, 0x29, 0xf9, 0x32, 0x86, - 0x6d, 0x9f, 0xcd, 0xb9, 0xd0, 0x42, 0x6a, 0xfa, 0xca, 0x9e, 0x60, 0x50, 0xb4, 0x7a, - 0x83, 0x19, 0xd6, 0x0d, + 0x0b, 0x74, 0x59, 0x61, 0x6f, 0xc6, 0x93, 0x95, 0xe6, 0x44, 0x36, 0xcf, 0x4a, 0xe9, + 0x44, 0x1d, 0x37, 0x4b, 0x29, 0x04, 0x9e, 0x4c, 0x86, 0x22, 0x3a, 0x03, 0x83, 0xf4, + 0xe0, 0x24, 0x69, 0x05, ], esk: [ - 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, 0xb3, 0x5d, 0xa9, 0xc6, - 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, 0xec, 0x8a, 0xd7, 0xf7, - 0x4c, 0xd9, 0xb2, 0x1b, + 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, 0xa1, 0xc4, 0x12, 0xbc, + 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, 0x95, 0x72, 0x92, 0x93, + 0x59, 0xe0, 0x4c, 0x3a, ], ephemeral_key: [ - 0x5b, 0xcb, 0xf9, 0xf1, 0xd7, 0xdd, 0x68, 0xe7, 0xcc, 0x6d, 0x6c, 0x78, 0x49, 0x50, - 0xd1, 0xc2, 0xe0, 0xbe, 0x6a, 0x84, 0xa7, 0xa8, 0x8d, 0x6f, 0x7a, 0x20, 0x98, 0xc3, - 0xdc, 0xae, 0x3f, 0x2f, + 0x0e, 0x04, 0xd8, 0x52, 0x5d, 0xd6, 0x8f, 0x7a, 0xe8, 0x68, 0xca, 0x81, 0x1e, 0x88, + 0x33, 0xa7, 0xf4, 0x7d, 0x7a, 0xad, 0xd3, 0x76, 0x03, 0xac, 0xe6, 0x07, 0xee, 0x6c, + 0x86, 0x6b, 0xce, 0x23, ], shared_secret: [ - 0x37, 0x35, 0x1c, 0xe2, 0x57, 0xb2, 0x79, 0x4d, 0x86, 0xa5, 0x3d, 0x26, 0x8d, 0xc9, - 0x00, 0x06, 0x40, 0xc2, 0x76, 0xf3, 0xf4, 0x65, 0xe1, 0xaa, 0x70, 0xbf, 0xde, 0xf4, - 0x99, 0xa3, 0xd7, 0xaa, + 0x4a, 0x7a, 0x54, 0xac, 0x00, 0x41, 0x95, 0x98, 0xb0, 0x76, 0x01, 0x53, 0xe2, 0x6a, + 0xcc, 0xd2, 0x15, 0x05, 0x24, 0x16, 0x65, 0x17, 0x13, 0xee, 0xa1, 0x89, 0x19, 0xf3, + 0xe2, 0x62, 0xd3, 0xb6, ], k_enc: [ - 0xea, 0x22, 0x99, 0x65, 0x39, 0xd3, 0x74, 0xda, 0x6a, 0x75, 0x34, 0x39, 0x5a, 0xe9, - 0x23, 0x36, 0xfc, 0xa7, 0x85, 0x11, 0x20, 0xdd, 0x1a, 0xe4, 0x9e, 0x45, 0xb3, 0x3e, - 0x0b, 0xed, 0xe9, 0xac, + 0x30, 0x62, 0x6d, 0x92, 0xeb, 0x62, 0x0f, 0xd4, 0xa9, 0x28, 0xb4, 0x3f, 0xd5, 0x50, + 0x69, 0x74, 0x71, 0x76, 0x7d, 0xe4, 0x49, 0x6c, 0xfd, 0xad, 0xb1, 0xda, 0x18, 0xfc, + 0x0c, 0xdd, 0x5a, 0xa6, ], p_enc: [ 0x02, 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, 0x47, 0xee, @@ -588,69 +590,70 @@ pub(crate) fn test_vectors() -> Vec { 0x55, 0x21, 0x93, 0xb1, ], c_enc: [ - 0x12, 0xd6, 0x64, 0xed, 0x05, 0xd6, 0x46, 0x26, 0x89, 0xd4, 0xf2, 0x4a, 0xee, 0x5a, - 0x4f, 0x0f, 0x32, 0x35, 0xff, 0x11, 0x0b, 0x2d, 0xf9, 0x9f, 0x67, 0xd8, 0xc5, 0xb3, - 0x68, 0xdd, 0x47, 0x69, 0xd8, 0x44, 0xd3, 0xdd, 0xa0, 0x3f, 0x58, 0xc5, 0x48, 0x63, - 0x62, 0xe8, 0x90, 0x81, 0xa5, 0xdf, 0xd0, 0xa6, 0x06, 0xa3, 0x91, 0x26, 0x4b, 0x56, - 0xca, 0x3a, 0xfc, 0x4f, 0xe0, 0xe4, 0xc3, 0x05, 0xf3, 0x07, 0x78, 0x09, 0x4a, 0x00, - 0xb7, 0x33, 0x4b, 0xdd, 0x82, 0x45, 0xac, 0x56, 0x0e, 0xf3, 0x29, 0xbc, 0x68, 0x97, - 0xd4, 0xd7, 0xba, 0x31, 0xac, 0x84, 0x54, 0x44, 0x1a, 0x15, 0xc8, 0xd3, 0xce, 0xcc, - 0x71, 0x32, 0xdf, 0x0d, 0x9d, 0x0e, 0xcf, 0x92, 0x84, 0x34, 0xa0, 0xd2, 0x8c, 0x1b, - 0x00, 0x48, 0x52, 0x01, 0xec, 0x33, 0xbe, 0x9a, 0x28, 0x74, 0xb4, 0x29, 0x6c, 0x04, - 0x22, 0xc7, 0xe7, 0xa0, 0xa3, 0xa2, 0x2e, 0xc7, 0xe7, 0x21, 0xa4, 0x79, 0x22, 0x8d, - 0xa2, 0x8b, 0x47, 0x37, 0xaf, 0x52, 0x06, 0xdf, 0x7d, 0x74, 0xe4, 0x84, 0xc4, 0xf7, - 0xa8, 0x56, 0xbe, 0x8c, 0xd0, 0x4b, 0x21, 0x26, 0xb5, 0x27, 0x11, 0xe7, 0xb0, 0xaf, - 0x75, 0xc7, 0x52, 0x84, 0xa1, 0x57, 0x20, 0x40, 0xe8, 0xad, 0xe5, 0x85, 0xe8, 0xa4, - 0x82, 0x80, 0x03, 0x59, 0x67, 0x46, 0xc4, 0x0c, 0x9d, 0x76, 0x0d, 0x92, 0x74, 0xb1, - 0x25, 0x42, 0x2b, 0x63, 0x48, 0x1a, 0x17, 0xff, 0xba, 0xb8, 0xc2, 0xde, 0x13, 0xb2, - 0x19, 0xf5, 0x8a, 0x35, 0x95, 0x2d, 0x88, 0x7a, 0xed, 0xe8, 0xe0, 0x2f, 0x10, 0x33, - 0x8c, 0x23, 0x98, 0x23, 0xfb, 0x43, 0x49, 0x51, 0x84, 0x47, 0x12, 0xf6, 0x8d, 0x6e, - 0x4f, 0xef, 0xae, 0x2b, 0x79, 0x5b, 0xa9, 0x78, 0xe9, 0x81, 0xc1, 0x09, 0x27, 0xab, - 0xbc, 0x16, 0x30, 0x66, 0xa0, 0xe9, 0x60, 0xb3, 0xb8, 0xa3, 0x26, 0xc0, 0x39, 0x85, - 0x81, 0x10, 0x93, 0x99, 0xf6, 0xed, 0x60, 0x44, 0x9a, 0xa8, 0x58, 0xd5, 0xdd, 0x27, - 0xdb, 0xf8, 0x89, 0x9f, 0x9c, 0x9a, 0x50, 0x20, 0x5f, 0x25, 0xd0, 0xcc, 0x50, 0xb2, - 0xde, 0xe3, 0x63, 0x54, 0xc5, 0xe4, 0x48, 0x4d, 0x36, 0xf6, 0x3c, 0x97, 0x63, 0xd8, - 0x41, 0xad, 0x5e, 0x00, 0x21, 0x63, 0x6a, 0x85, 0x7c, 0xfb, 0x79, 0xa5, 0x12, 0x3c, - 0x3d, 0xfb, 0x77, 0x3d, 0x0c, 0x1b, 0xeb, 0x9f, 0x90, 0xa9, 0x72, 0xd0, 0xfc, 0x80, - 0x5f, 0x65, 0x5d, 0x69, 0x40, 0x85, 0x23, 0xb9, 0x9b, 0x62, 0xa8, 0xfa, 0xbe, 0xf0, - 0xc0, 0x24, 0xf2, 0x1f, 0x50, 0xe4, 0xc1, 0x12, 0xe2, 0xfe, 0xdd, 0x58, 0xca, 0xe9, - 0x60, 0x9a, 0xc6, 0xf7, 0xcc, 0x79, 0x83, 0x86, 0xc9, 0xd9, 0x06, 0x42, 0x1c, 0xa5, - 0x7c, 0xf8, 0x1b, 0x09, 0x6b, 0xba, 0xda, 0x64, 0xd0, 0xee, 0x76, 0x95, 0x18, 0x9d, - 0x5f, 0xb1, 0x7a, 0xe2, 0x53, 0x1d, 0xbb, 0x2c, 0x00, 0x58, 0x5a, 0x26, 0xa6, 0x8c, - 0x27, 0xf9, 0x77, 0x77, 0x84, 0x1a, 0x3e, 0x39, 0x30, 0xc7, 0x0f, 0xc3, 0xfa, 0x8e, - 0x2b, 0x7f, 0xc2, 0x1e, 0x87, 0xcf, 0x9f, 0x63, 0xb3, 0x63, 0xb8, 0x8d, 0xaa, 0x1f, - 0xb6, 0x7b, 0xda, 0xe8, 0xe5, 0x5b, 0x68, 0x51, 0x6d, 0x19, 0xdf, 0xef, 0xec, 0x9b, - 0x3d, 0x38, 0xe6, 0xe1, 0xd0, 0xa6, 0xe4, 0x51, 0xd6, 0xd1, 0xf5, 0x2d, 0x1f, 0x96, - 0xdd, 0x0d, 0x53, 0x6d, 0x68, 0xd2, 0x69, 0x86, 0x70, 0x9f, 0x41, 0xe7, 0x60, 0x74, - 0x05, 0x5b, 0xf7, 0x52, 0xbf, 0x38, 0x86, 0x92, 0xc8, 0x2c, 0xfd, 0xa1, 0xeb, 0xb0, - 0x17, 0x8b, 0x8e, 0x0c, 0x85, 0xad, 0x7b, 0x15, 0x99, 0x14, 0x42, 0x8e, 0x30, 0x21, - 0xda, 0xe3, 0x01, 0x0d, 0x65, 0x6c, 0x10, 0x36, 0xf4, 0xa5, 0x7e, 0x7f, 0xad, 0xe0, - 0xfc, 0x32, 0x2a, 0xa6, 0xfd, 0xde, 0x71, 0x4a, 0x8c, 0x53, 0x78, 0x79, 0xe7, 0x04, - 0x41, 0x6f, 0x51, 0x04, 0xdb, 0xbc, 0x8f, 0xf2, 0x42, 0xc1, 0x6d, 0x2d, 0xf4, 0xa8, - 0x41, 0xeb, 0x6b, 0x45, 0x3a, 0x12, 0x83, 0xf6, 0x5f, 0xe1, 0x0d, 0x70, 0xc8, 0x76, - 0x41, 0x8e, 0x44, 0x4a, 0xb3, 0x1b, 0x93, 0x71, 0xa2, 0x7d, 0x36, 0xd8, 0x6e, 0x8f, - 0x1c, 0x32, 0x77, 0xca, 0xfd, 0xf8, + 0x81, 0x56, 0x2d, 0xbe, 0xf7, 0xbb, 0x35, 0x3a, 0x62, 0xe7, 0xc8, 0x1e, 0xbe, 0x68, + 0x15, 0x6c, 0xb7, 0x5c, 0x5c, 0x7e, 0x3d, 0x96, 0xbb, 0xcd, 0x7d, 0xaf, 0xf5, 0x0c, + 0xb0, 0x95, 0x7d, 0x33, 0xdd, 0x99, 0x77, 0x9f, 0x7d, 0x3d, 0x72, 0xb1, 0x8d, 0xeb, + 0x7a, 0x69, 0x75, 0x10, 0xe0, 0x13, 0x5b, 0x8d, 0xf4, 0x83, 0xa4, 0xd7, 0x1d, 0x1a, + 0xb1, 0x08, 0x09, 0x6e, 0x76, 0x08, 0x91, 0xd5, 0x31, 0x07, 0xf0, 0x3d, 0xea, 0x4a, + 0xe8, 0xe4, 0xd3, 0xfe, 0xbd, 0x98, 0x77, 0xf8, 0x57, 0x0a, 0xa3, 0x09, 0xd0, 0x97, + 0xd4, 0x23, 0xbb, 0x76, 0x3f, 0xb3, 0xe7, 0xe9, 0xbe, 0x3c, 0x8f, 0xa0, 0x34, 0xc0, + 0x1d, 0x66, 0x4f, 0x47, 0xa0, 0xe7, 0x13, 0x3c, 0xa1, 0x1a, 0x48, 0xcd, 0x0e, 0xea, + 0x46, 0x35, 0xfa, 0x77, 0x25, 0x0a, 0x17, 0xbd, 0xf7, 0xb7, 0x32, 0xc8, 0x98, 0x46, + 0x51, 0x57, 0x4f, 0xd4, 0xf9, 0x9f, 0x7a, 0xa0, 0xdb, 0x28, 0xc2, 0x97, 0x31, 0x52, + 0xbf, 0x42, 0x6e, 0xe9, 0xa4, 0xd8, 0x41, 0xa9, 0x1d, 0x5d, 0x33, 0x57, 0x18, 0xee, + 0xcb, 0xc9, 0xc8, 0xb2, 0xa2, 0x00, 0x15, 0x70, 0xfe, 0x8b, 0x77, 0x91, 0x43, 0xdf, + 0x22, 0x95, 0x98, 0xa5, 0xbe, 0x25, 0x48, 0xcf, 0x35, 0x84, 0x25, 0x18, 0xcc, 0x1d, + 0xbc, 0x78, 0xcc, 0x2f, 0x0f, 0xc8, 0xea, 0x35, 0x7c, 0xe6, 0xc1, 0x7e, 0xb9, 0x7c, + 0x61, 0x38, 0xd5, 0x3e, 0x6c, 0x8e, 0x00, 0xf0, 0x7f, 0x80, 0x01, 0x25, 0x18, 0x2b, + 0x25, 0xa5, 0xe8, 0x75, 0xc5, 0x37, 0x72, 0x09, 0x52, 0x72, 0x22, 0x37, 0x1f, 0x72, + 0xbf, 0xbd, 0x46, 0x28, 0x44, 0xab, 0x06, 0xf3, 0xb3, 0xa1, 0xeb, 0xa3, 0x44, 0x23, + 0xb6, 0x9a, 0xbf, 0x5d, 0xe6, 0x64, 0xba, 0x83, 0xcd, 0x43, 0xb6, 0xa8, 0xe9, 0xd5, + 0xb7, 0xc5, 0x2a, 0xdb, 0x86, 0x15, 0x04, 0x1b, 0x90, 0xd9, 0x08, 0x83, 0x1a, 0x6f, + 0xf9, 0x2d, 0xb4, 0x8a, 0x14, 0xac, 0x4d, 0xfa, 0x67, 0xd0, 0x2c, 0x72, 0xe0, 0xc8, + 0x63, 0x15, 0x7d, 0x98, 0xf8, 0xf5, 0x45, 0x37, 0x92, 0x97, 0x43, 0xc9, 0x69, 0xbc, + 0x91, 0xc2, 0xc1, 0x37, 0x52, 0x04, 0x98, 0x3c, 0x99, 0x99, 0x97, 0x5f, 0xfa, 0x5e, + 0xe5, 0xfe, 0x1f, 0x69, 0x71, 0x99, 0x40, 0x5f, 0x09, 0x66, 0xe3, 0x1f, 0x34, 0xe1, + 0x52, 0x38, 0x44, 0x38, 0x18, 0x44, 0x98, 0x2b, 0x2c, 0x3b, 0x49, 0xa2, 0x09, 0xff, + 0xa3, 0xce, 0xe9, 0x79, 0xa8, 0x5b, 0x19, 0xb8, 0x50, 0xf4, 0x1d, 0xcc, 0xc4, 0x63, + 0xe2, 0x2e, 0x24, 0xa3, 0x04, 0x9d, 0x37, 0xb1, 0xfb, 0x37, 0x0d, 0xeb, 0xdd, 0xf4, + 0xde, 0x05, 0x46, 0x24, 0x5e, 0x4f, 0x02, 0xa9, 0x84, 0x98, 0xaf, 0x53, 0x2e, 0x27, + 0xac, 0xae, 0x5c, 0x7e, 0xd1, 0x43, 0xe6, 0xe9, 0xcc, 0xfa, 0x74, 0x35, 0x16, 0x02, + 0x16, 0x57, 0xac, 0xb2, 0x5e, 0x44, 0x47, 0x84, 0x5c, 0x5f, 0x9c, 0x59, 0x64, 0x60, + 0x7c, 0x4a, 0x78, 0x72, 0x1d, 0x98, 0x1a, 0x7f, 0xf2, 0xfd, 0xf6, 0xc0, 0x33, 0x62, + 0x8b, 0xff, 0xd6, 0xf0, 0xb8, 0xde, 0x0c, 0xd6, 0x35, 0xec, 0x22, 0xf8, 0xb5, 0x0e, + 0xd6, 0x37, 0xfe, 0x4e, 0x00, 0xf9, 0xd3, 0xc3, 0xd4, 0xf1, 0x81, 0x0b, 0x09, 0xb7, + 0x5c, 0x96, 0xe2, 0xfc, 0xf1, 0x11, 0x85, 0x31, 0x7e, 0xdf, 0xa3, 0x9d, 0x19, 0x25, + 0xde, 0xd8, 0x14, 0xdd, 0xe0, 0xef, 0x00, 0xa3, 0xfb, 0x47, 0xaf, 0x5d, 0x81, 0x20, + 0x94, 0xaf, 0x13, 0xd0, 0x1c, 0x98, 0x56, 0x9f, 0xf7, 0x73, 0x57, 0x87, 0xfa, 0x9b, + 0xd0, 0x1f, 0xa0, 0x69, 0x28, 0x27, 0x5f, 0xdd, 0x10, 0x38, 0x96, 0x5f, 0xb0, 0x6f, + 0xb3, 0x5e, 0xdb, 0x73, 0x80, 0xdd, 0x3c, 0x42, 0x41, 0x9e, 0x0c, 0x0e, 0xde, 0x4c, + 0x48, 0x6a, 0x9d, 0xb4, 0x95, 0x38, 0x86, 0xae, 0xc6, 0xad, 0x30, 0x70, 0x28, 0xeb, + 0x26, 0xa3, 0x7e, 0xf4, 0x71, 0x56, 0x7a, 0xd4, 0xbd, 0x4e, 0xaa, 0xb7, 0xa8, 0x2c, + 0xb0, 0xd6, 0xb5, 0xf0, 0x5e, 0x89, 0x4e, 0x53, 0x25, 0x82, 0x1d, 0x92, 0xbe, 0xd2, + 0xb8, 0x6f, 0xb2, 0x43, 0x37, 0xd5, 0x79, 0x28, 0x8f, 0x6d, 0xf7, 0x34, 0x77, 0x1d, + 0x9e, 0xf8, 0x35, 0x8b, 0xa9, 0x1a, ], ock: [ - 0xca, 0x6f, 0x98, 0xe6, 0xcf, 0x9f, 0xc3, 0x6a, 0xf5, 0xf6, 0x98, 0x82, 0x74, 0x2d, - 0x06, 0xec, 0x5d, 0x29, 0xac, 0x2a, 0x02, 0x89, 0x44, 0xa2, 0x01, 0x89, 0xd5, 0x1c, - 0x8a, 0x9b, 0xdc, 0xd6, + 0xb6, 0x36, 0xc3, 0x9a, 0x6b, 0xad, 0x22, 0x63, 0xb2, 0x44, 0x1e, 0xd5, 0xbb, 0xdb, + 0x01, 0x35, 0x88, 0xfb, 0x46, 0x27, 0x01, 0xe6, 0xf8, 0x76, 0x64, 0x6c, 0x8c, 0x17, + 0xfa, 0x2e, 0xfd, 0xe8, ], op: [ 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, - 0x15, 0x37, 0x14, 0x0d, 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, - 0xb3, 0x5d, 0xa9, 0xc6, 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, - 0xec, 0x8a, 0xd7, 0xf7, 0x4c, 0xd9, 0xb2, 0x1b, + 0x15, 0x37, 0x14, 0x0d, 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, + 0xa1, 0xc4, 0x12, 0xbc, 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, + 0x95, 0x72, 0x92, 0x93, 0x59, 0xe0, 0x4c, 0x3a, ], c_out: [ - 0xa9, 0x5e, 0x1a, 0x22, 0x45, 0x65, 0x29, 0x5e, 0x9b, 0x55, 0x3a, 0xdd, 0xe8, 0xb0, - 0x14, 0x47, 0x5c, 0x68, 0x7b, 0x5d, 0x13, 0x49, 0xc1, 0xdf, 0x8a, 0xd4, 0xb7, 0xcf, - 0xd3, 0xdf, 0xc1, 0x00, 0x6c, 0x7c, 0x37, 0xde, 0x67, 0x6d, 0x6f, 0xde, 0x31, 0x8e, - 0x2f, 0xdf, 0xcc, 0x2e, 0x2e, 0x23, 0x2c, 0xc5, 0xf8, 0x85, 0x28, 0x39, 0xe7, 0xef, - 0xab, 0x8b, 0x20, 0x0e, 0xbc, 0x6a, 0x4d, 0xf8, 0x2a, 0x75, 0x21, 0xce, 0x0f, 0x38, - 0x4f, 0xe2, 0x7a, 0x0d, 0xec, 0x59, 0xe9, 0xd2, 0xc0, 0xe3, - ], + 0x46, 0xba, 0x14, 0xf8, 0x3f, 0xf5, 0xab, 0x76, 0x0f, 0x14, 0x20, 0xeb, 0xde, 0xd9, + 0x86, 0xfd, 0x93, 0x78, 0x27, 0xbc, 0x05, 0x69, 0x2e, 0xca, 0xdb, 0x65, 0x2e, 0xbb, + 0xc8, 0xf6, 0xd9, 0xb5, 0x2e, 0xc3, 0x97, 0x87, 0xd8, 0xeb, 0xdd, 0x50, 0x6c, 0xa1, + 0xa8, 0x5d, 0xc3, 0xd5, 0xba, 0x4c, 0x5b, 0x41, 0x52, 0x61, 0xb0, 0x75, 0x3a, 0xc1, + 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, + 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -724,34 +727,34 @@ pub(crate) fn test_vectors() -> Vec { 0x32, 0xb5, 0x0e, 0x96, ], rho: [ - 0x18, 0x89, 0x8e, 0x75, 0x21, 0x7b, 0x32, 0x9b, 0x3a, 0x56, 0x7b, 0x09, 0x37, 0x89, - 0xa4, 0xd8, 0x19, 0xcd, 0xb0, 0x34, 0x88, 0xb8, 0x10, 0xda, 0x22, 0x0c, 0x3f, 0x59, - 0xba, 0x03, 0x39, 0x26, + 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, + 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, + 0xf5, 0x0e, 0x92, 0x37, ], cmx: [ - 0x23, 0xad, 0xc3, 0xbf, 0x35, 0x0e, 0xb0, 0x84, 0xbd, 0x28, 0xbc, 0x2d, 0xcf, 0xb7, - 0x98, 0x3f, 0xf6, 0xb3, 0xb6, 0xf2, 0xeb, 0x2d, 0x6f, 0x12, 0x4f, 0xfc, 0x46, 0x85, - 0xab, 0xe8, 0xde, 0x3a, + 0x05, 0xb5, 0xe3, 0x20, 0x76, 0xda, 0xe0, 0x94, 0x83, 0x35, 0xac, 0x3d, 0x65, 0x1c, + 0x6d, 0xbe, 0xa6, 0x4c, 0xe9, 0x11, 0x42, 0x3e, 0x2f, 0x2c, 0x7c, 0x1b, 0xdf, 0xa6, + 0xb1, 0x41, 0x41, 0x30, ], esk: [ - 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, 0x2c, 0xf1, 0xb8, 0x88, - 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, 0x98, 0x02, 0xf1, 0x53, - 0x6a, 0x9e, 0x9f, 0x2b, + 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, 0xfe, 0x47, 0x9a, 0x1e, + 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, 0x92, 0x3a, 0x5d, 0x00, + 0xcb, 0x52, 0xa6, 0x13, ], ephemeral_key: [ - 0x91, 0xaf, 0x13, 0x8e, 0xd9, 0x95, 0x44, 0x66, 0x95, 0x16, 0x1b, 0x14, 0x2d, 0xc2, - 0xde, 0x59, 0xac, 0x23, 0x05, 0xec, 0xbe, 0xc6, 0x29, 0x33, 0xf5, 0x2f, 0x2a, 0xa1, - 0xf9, 0xb2, 0x71, 0x86, + 0x86, 0xee, 0x66, 0xa6, 0xc7, 0xd9, 0xb5, 0xc4, 0xf0, 0xe2, 0xd2, 0xa0, 0xe1, 0x56, + 0x1e, 0x2a, 0xfa, 0x55, 0x41, 0xa7, 0x24, 0xee, 0x02, 0x7f, 0xc7, 0x0b, 0xb7, 0xe8, + 0x0a, 0x2c, 0x60, 0x98, ], shared_secret: [ - 0xe1, 0xd3, 0xaf, 0x73, 0x6a, 0xb9, 0xc6, 0x11, 0x6f, 0x46, 0x8f, 0x91, 0x66, 0x80, - 0x63, 0x20, 0x35, 0x0f, 0x7e, 0x73, 0x51, 0x3b, 0xa6, 0x05, 0x50, 0xeb, 0x2d, 0xf0, - 0x1f, 0xf7, 0x83, 0x2d, + 0x88, 0xd1, 0x38, 0x2c, 0x14, 0x42, 0x02, 0xd0, 0xd7, 0x55, 0x75, 0x87, 0xb0, 0xd5, + 0xd0, 0x21, 0x69, 0x29, 0x2a, 0x25, 0x05, 0x43, 0xcb, 0x0a, 0x06, 0xc3, 0x4f, 0x45, + 0x2f, 0x7b, 0x3b, 0x36, ], k_enc: [ - 0xb4, 0x3e, 0x43, 0x3e, 0x16, 0x45, 0xeb, 0x51, 0x5e, 0x4a, 0x4c, 0x7d, 0x10, 0xc9, - 0x3d, 0x08, 0xf2, 0xf1, 0xc3, 0x30, 0x95, 0xbf, 0x8c, 0x80, 0x0a, 0x04, 0x17, 0x62, - 0xab, 0x5c, 0xf8, 0x2c, + 0xe3, 0x73, 0xd8, 0x6e, 0xc9, 0xdd, 0xdd, 0x64, 0x5d, 0x9a, 0x6d, 0x06, 0xef, 0xce, + 0x22, 0xb8, 0x96, 0x42, 0x1d, 0x57, 0xa4, 0x4d, 0x37, 0xa6, 0x50, 0x4a, 0x5d, 0x19, + 0xdf, 0x21, 0x73, 0x73, ], p_enc: [ 0x02, 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, 0xfa, 0x3f, @@ -797,69 +800,70 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x65, 0x57, 0x53, ], c_enc: [ - 0x27, 0x62, 0x0d, 0xf5, 0xdb, 0x17, 0x76, 0x6e, 0xbd, 0x9a, 0x99, 0xd6, 0x9a, 0x9a, - 0x49, 0x38, 0x73, 0x21, 0xf0, 0xc9, 0x47, 0x25, 0x23, 0x57, 0xb5, 0xb7, 0x48, 0x49, - 0x38, 0xe3, 0xf5, 0xff, 0x9f, 0x32, 0x0e, 0x80, 0x6c, 0x4b, 0x54, 0xc3, 0x6e, 0x41, - 0x2e, 0x8a, 0x6e, 0xad, 0xe3, 0x5b, 0x83, 0x01, 0xf7, 0x34, 0xf3, 0x71, 0x2e, 0x6a, - 0xac, 0xe6, 0x99, 0xf5, 0x9e, 0x11, 0x2a, 0x7b, 0xf5, 0x44, 0x59, 0xdc, 0x5d, 0x9f, - 0x7b, 0xbf, 0x3b, 0x9f, 0x74, 0x6c, 0x45, 0xbb, 0xed, 0x69, 0xa4, 0x25, 0x1b, 0x29, - 0xf3, 0xd2, 0x15, 0xc2, 0x9f, 0x76, 0x1c, 0x7d, 0x05, 0x88, 0x19, 0xf0, 0xdd, 0x4e, - 0x70, 0x71, 0xb0, 0x77, 0xcb, 0x00, 0xcb, 0x93, 0x62, 0xa4, 0x98, 0x16, 0x88, 0x0d, - 0x49, 0xb7, 0x11, 0xf9, 0x20, 0x65, 0xf1, 0x53, 0x2e, 0x58, 0x18, 0x0b, 0xbd, 0xb4, - 0x91, 0xdb, 0xbb, 0x96, 0x8a, 0x09, 0xb5, 0x63, 0xce, 0x1d, 0x29, 0x87, 0x6f, 0xd0, - 0x52, 0x6d, 0x65, 0xda, 0x67, 0x27, 0xad, 0x40, 0xf9, 0x64, 0x02, 0xf9, 0x9a, 0xa5, - 0xac, 0x06, 0x42, 0x51, 0xc4, 0x65, 0xe3, 0xc7, 0xdb, 0x1f, 0xfe, 0xef, 0xac, 0xd7, - 0xf5, 0x1b, 0xa4, 0xf1, 0x9c, 0x6c, 0x17, 0x87, 0xa0, 0xff, 0xb4, 0x9d, 0xbb, 0x7b, - 0x0a, 0x2b, 0x15, 0x64, 0x03, 0xd6, 0x6c, 0x22, 0x13, 0xe5, 0x1d, 0x58, 0xea, 0xef, - 0xe8, 0x6d, 0x5d, 0xef, 0x0d, 0x24, 0xb7, 0xf2, 0xf8, 0xc1, 0x10, 0x32, 0x9a, 0x3a, - 0x73, 0xcb, 0x33, 0x50, 0x14, 0x0e, 0x6b, 0xf7, 0x2c, 0xb6, 0xaa, 0x22, 0x2d, 0xef, - 0x5a, 0x47, 0xe2, 0x1a, 0xf0, 0xb9, 0xae, 0xeb, 0x74, 0x8c, 0x01, 0xc6, 0x7a, 0xb6, - 0xc9, 0xfd, 0x6e, 0x53, 0x6a, 0x0d, 0x92, 0x76, 0x61, 0x51, 0xb1, 0xac, 0x7c, 0xc9, - 0x85, 0x5c, 0xa9, 0x8d, 0xea, 0x74, 0x85, 0x14, 0xef, 0xee, 0x89, 0xe8, 0x9a, 0x01, - 0x68, 0xf5, 0xdd, 0xf4, 0xac, 0x2b, 0x7c, 0xe1, 0xc9, 0xc2, 0x92, 0xfb, 0xef, 0x2f, - 0x45, 0x51, 0xa8, 0x88, 0xc3, 0x34, 0x5c, 0x65, 0x92, 0x30, 0x39, 0xfc, 0x21, 0xf7, - 0x31, 0x55, 0x9b, 0xd9, 0x24, 0xbc, 0x2c, 0x15, 0x5b, 0xc0, 0xbe, 0x80, 0x38, 0x4a, - 0x9e, 0x49, 0xbd, 0xa6, 0x9a, 0x70, 0x6b, 0x1a, 0xd6, 0xa2, 0x62, 0xab, 0xc6, 0x26, - 0x50, 0x77, 0x2f, 0xd7, 0xea, 0xbc, 0x3f, 0x75, 0xa9, 0xac, 0xca, 0xa2, 0x8b, 0xcd, - 0xea, 0x65, 0xf9, 0x4e, 0x16, 0xcc, 0x3d, 0x05, 0x38, 0xe5, 0x49, 0x86, 0x0a, 0x60, - 0x12, 0x5b, 0xb4, 0xbc, 0x0c, 0x23, 0xe3, 0x22, 0x27, 0x68, 0x2c, 0x09, 0xb5, 0xaa, - 0x30, 0x4a, 0x16, 0x09, 0x2a, 0xd4, 0xa3, 0xe2, 0xf6, 0x28, 0x3c, 0x38, 0x51, 0x80, - 0x6e, 0x72, 0x17, 0x3f, 0x7d, 0x32, 0x97, 0xed, 0x92, 0xe5, 0x32, 0x40, 0x39, 0xa7, - 0x31, 0x4f, 0x5f, 0xb7, 0x38, 0x6e, 0x09, 0x94, 0xf5, 0x2f, 0x8c, 0xcc, 0xf1, 0x87, - 0xd6, 0x20, 0x41, 0x0c, 0xce, 0x9d, 0x0b, 0x91, 0x93, 0xac, 0xec, 0x6d, 0x4c, 0x9b, - 0xd3, 0x4e, 0x08, 0x80, 0x58, 0x0a, 0xbe, 0xae, 0xd9, 0x7c, 0xb7, 0x80, 0x0f, 0x6a, - 0xbc, 0x67, 0xc2, 0x5c, 0x49, 0x19, 0x2e, 0x37, 0xdc, 0xf3, 0x3d, 0x1a, 0x59, 0x16, - 0x47, 0x5a, 0xe9, 0x99, 0x90, 0xd8, 0x29, 0xc1, 0xd5, 0x9e, 0x69, 0x2f, 0x47, 0x36, - 0x93, 0xbc, 0xe3, 0x58, 0x5a, 0xec, 0xd3, 0xc1, 0x3b, 0xae, 0x15, 0xcb, 0xef, 0xf2, - 0x98, 0x52, 0x2a, 0xab, 0xf4, 0x6b, 0xea, 0x3a, 0xbf, 0x63, 0x30, 0xa5, 0x6e, 0x37, - 0x24, 0x51, 0x81, 0x32, 0xce, 0x94, 0x39, 0x41, 0x6a, 0x28, 0xe9, 0x52, 0x0d, 0xdf, - 0x64, 0x17, 0x00, 0xb4, 0x6f, 0x37, 0x49, 0x50, 0xf3, 0x27, 0xaf, 0x3d, 0x0b, 0x3d, - 0x3b, 0x3f, 0x61, 0xa8, 0x84, 0xcf, 0x4f, 0x82, 0x02, 0x56, 0xfb, 0x91, 0x65, 0xdc, - 0xa0, 0xe4, 0x32, 0x60, 0xfc, 0xb5, 0x63, 0xef, 0x1a, 0xb4, 0xe7, 0x12, 0xef, 0x07, - 0x23, 0xd6, 0x75, 0x90, 0xa4, 0xff, 0xc3, 0x66, 0xc4, 0xa7, 0x92, 0x50, 0x29, 0x93, - 0x1b, 0xf0, 0x87, 0x3d, 0xac, 0xaa, 0xe9, 0x38, 0x5d, 0x9a, 0xd9, 0x1a, 0xed, 0x75, - 0x93, 0x9d, 0x8b, 0xd1, 0xaf, 0x5d, + 0xe7, 0x67, 0x81, 0xae, 0x63, 0x84, 0x1f, 0xff, 0xea, 0x30, 0x21, 0x96, 0x15, 0x94, + 0xc2, 0x2a, 0x87, 0x20, 0xc7, 0xd8, 0xaa, 0x80, 0x8b, 0xc8, 0x6e, 0x71, 0xa3, 0x6a, + 0xd7, 0xf8, 0x6f, 0xf8, 0x7c, 0x07, 0xd3, 0xc6, 0x50, 0xa0, 0x8e, 0x23, 0xe9, 0xb5, + 0x4f, 0x00, 0xb4, 0x0b, 0xa0, 0x15, 0x91, 0x69, 0xdf, 0xca, 0x34, 0xc1, 0x40, 0xce, + 0x93, 0x40, 0x19, 0xb2, 0xea, 0xa8, 0xea, 0x84, 0x35, 0x80, 0xb3, 0x5f, 0x14, 0xea, + 0x51, 0x92, 0xde, 0x8a, 0x12, 0xf9, 0xab, 0xc9, 0x06, 0x10, 0x15, 0xe1, 0x47, 0x9e, + 0xf9, 0x8d, 0x19, 0xa5, 0x34, 0xe9, 0xe4, 0x61, 0x64, 0xc3, 0xca, 0xc4, 0xeb, 0x54, + 0x26, 0x4c, 0xed, 0xcd, 0x83, 0xaf, 0xc2, 0xac, 0x2e, 0x08, 0x7e, 0x39, 0xdf, 0xba, + 0xe7, 0x6b, 0xd5, 0x50, 0xcc, 0x64, 0xa4, 0x04, 0xd2, 0x0c, 0x22, 0xca, 0x00, 0x3b, + 0xf7, 0x5b, 0x12, 0xfb, 0xb8, 0xc7, 0x15, 0x13, 0x72, 0x70, 0x0b, 0x43, 0x9b, 0x3e, + 0x06, 0x57, 0xec, 0xc3, 0x07, 0x70, 0x8f, 0xc3, 0x74, 0x94, 0xbd, 0x06, 0x39, 0xe8, + 0xe1, 0xea, 0xea, 0x37, 0x8f, 0x27, 0xa1, 0x35, 0x74, 0xb7, 0x1f, 0xa4, 0x88, 0x3b, + 0x80, 0x71, 0x2c, 0x7b, 0xeb, 0x5c, 0x30, 0x5f, 0x8d, 0x67, 0xe9, 0x19, 0x97, 0xf8, + 0x03, 0x19, 0xdd, 0xb1, 0x15, 0xb9, 0x51, 0x23, 0x89, 0x7a, 0xae, 0x5f, 0x2d, 0x14, + 0xff, 0xcf, 0xac, 0x7f, 0x65, 0x49, 0xca, 0x54, 0x8f, 0x6e, 0xab, 0xdf, 0x74, 0x81, + 0x70, 0x27, 0xd4, 0x2d, 0x92, 0xd5, 0xcd, 0xf8, 0x8e, 0xd8, 0xd5, 0x11, 0xd1, 0xb5, + 0xc4, 0x32, 0x2f, 0x77, 0x79, 0x74, 0x88, 0x6c, 0x0e, 0xd0, 0x13, 0x99, 0x18, 0x0a, + 0xfa, 0x59, 0x7d, 0xd2, 0xb7, 0x7c, 0x58, 0xb2, 0x7c, 0x8a, 0x61, 0x20, 0x69, 0xe3, + 0x86, 0xad, 0x63, 0x4c, 0xb0, 0x17, 0xa8, 0xe9, 0xf4, 0x8e, 0x37, 0xc4, 0x3e, 0xe8, + 0x73, 0x3a, 0x0a, 0xcb, 0x69, 0xf8, 0xed, 0x9f, 0x6f, 0x30, 0x5f, 0x3b, 0xd1, 0xe9, + 0x82, 0xb9, 0x4b, 0x1e, 0x51, 0xf4, 0xba, 0x98, 0x5b, 0x20, 0xec, 0x97, 0x4a, 0xc9, + 0xa7, 0x93, 0xaa, 0x26, 0x4d, 0x61, 0x5b, 0x9d, 0xea, 0x48, 0x59, 0xa4, 0xd4, 0xca, + 0xa7, 0x0d, 0x7a, 0x6b, 0x65, 0x30, 0x76, 0x85, 0xab, 0x53, 0x4e, 0x54, 0x55, 0x63, + 0x1f, 0x6d, 0x68, 0xa4, 0x51, 0xd8, 0xaf, 0x2d, 0x41, 0x82, 0x52, 0x80, 0x0f, 0x68, + 0x42, 0x31, 0xaf, 0xc2, 0x6d, 0x1f, 0xef, 0xc4, 0x03, 0xd7, 0x5f, 0x2e, 0x12, 0x0f, + 0x5b, 0xe2, 0xb6, 0x74, 0x48, 0x60, 0x09, 0x26, 0x7c, 0xbc, 0x0c, 0xb0, 0x01, 0xbb, + 0x47, 0xf0, 0xff, 0x46, 0x97, 0xea, 0xf5, 0x3d, 0xc9, 0x9c, 0x10, 0x77, 0x3a, 0x38, + 0xcd, 0x06, 0xb4, 0x8b, 0xa3, 0x91, 0x19, 0xdb, 0x49, 0x84, 0xd0, 0x9a, 0x5b, 0xde, + 0x13, 0x89, 0x0e, 0xa0, 0x61, 0x3d, 0x0c, 0xe0, 0x04, 0x3e, 0xae, 0x9a, 0x20, 0x89, + 0x14, 0x1f, 0xd9, 0x46, 0x59, 0x13, 0xc1, 0xcc, 0x33, 0x27, 0xa5, 0x59, 0x42, 0xb9, + 0xfd, 0x8f, 0xb8, 0x1c, 0x84, 0x7d, 0x8f, 0xdd, 0xf8, 0xbd, 0xba, 0xcf, 0xa0, 0xfb, + 0x05, 0x52, 0xc1, 0xfe, 0x4c, 0xc4, 0xc0, 0x7f, 0x4d, 0xcf, 0x15, 0x1c, 0x5e, 0x74, + 0xe8, 0xd6, 0x9b, 0x2b, 0x8b, 0xf7, 0xfd, 0x95, 0xec, 0xeb, 0x65, 0x5e, 0x00, 0x53, + 0x58, 0x16, 0xd3, 0x8b, 0x4a, 0x28, 0xd4, 0xa9, 0xae, 0xeb, 0xb6, 0x9a, 0xb4, 0xdd, + 0x12, 0xbf, 0x13, 0xfd, 0x5a, 0x45, 0x9b, 0x6b, 0xb6, 0x83, 0xff, 0xd9, 0xdd, 0x7b, + 0x0d, 0x0c, 0xe7, 0x29, 0x67, 0x75, 0x80, 0x8a, 0x84, 0x3f, 0x3b, 0x8c, 0xc7, 0x89, + 0xfd, 0x5f, 0x43, 0xe0, 0x84, 0xd8, 0x7d, 0x6a, 0xda, 0x8d, 0x1f, 0x28, 0xc2, 0x64, + 0xe6, 0x44, 0xe9, 0xad, 0x96, 0x5c, 0x28, 0x08, 0x8a, 0x52, 0xe4, 0xb3, 0x56, 0x42, + 0xf9, 0xb5, 0xe0, 0x66, 0x49, 0x90, 0x96, 0x3b, 0xc2, 0x3b, 0x9b, 0xb4, 0x8f, 0x46, + 0x74, 0x73, 0x53, 0x58, 0x0e, 0xcc, 0x45, 0x20, 0xcf, 0xf1, 0xfa, 0x7f, 0x8f, 0xbc, + 0x03, 0x0e, 0x64, 0x7d, 0xf1, 0x44, 0xee, 0x6c, 0xa5, 0xb3, 0x16, 0xb3, 0xaf, 0x90, + 0x48, 0x9a, 0x80, 0x9d, 0x9c, 0x9f, ], ock: [ - 0x2a, 0xec, 0x11, 0xd4, 0xae, 0x79, 0x84, 0xe1, 0x69, 0xd1, 0xdf, 0xf1, 0xff, 0x0f, - 0x9a, 0xf5, 0x19, 0x96, 0x34, 0x51, 0xa4, 0x1c, 0x9f, 0x5a, 0xdc, 0x58, 0xe4, 0xf9, - 0x0a, 0xf3, 0x8d, 0x47, + 0x85, 0x6e, 0x1a, 0x97, 0x09, 0xb0, 0xc4, 0x16, 0x93, 0x3f, 0x59, 0x70, 0x71, 0x5c, + 0x56, 0xe2, 0xe0, 0x5c, 0x2e, 0xa9, 0x7d, 0x81, 0x51, 0x25, 0x70, 0x14, 0x79, 0xc3, + 0x3a, 0x5d, 0x91, 0xcb, ], op: [ 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, - 0x14, 0x93, 0x16, 0x36, 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, - 0x2c, 0xf1, 0xb8, 0x88, 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, - 0x98, 0x02, 0xf1, 0x53, 0x6a, 0x9e, 0x9f, 0x2b, + 0x14, 0x93, 0x16, 0x36, 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, + 0xfe, 0x47, 0x9a, 0x1e, 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, + 0x92, 0x3a, 0x5d, 0x00, 0xcb, 0x52, 0xa6, 0x13, ], c_out: [ - 0xe6, 0xeb, 0x22, 0x47, 0xc9, 0x33, 0xe2, 0x4c, 0x9d, 0xf1, 0x28, 0xb1, 0xe0, 0x4e, - 0x8b, 0xc0, 0x5c, 0x65, 0xeb, 0x31, 0x97, 0xdf, 0x9b, 0xa8, 0x70, 0xd8, 0xa0, 0xa1, - 0x8d, 0x9c, 0x24, 0xb7, 0xc9, 0x78, 0xc3, 0x4d, 0x3c, 0x7b, 0xbd, 0x21, 0xe8, 0x7b, - 0x22, 0x39, 0x21, 0x87, 0x54, 0xd9, 0x67, 0x3a, 0x56, 0xa2, 0x73, 0x58, 0x0f, 0x6b, - 0x41, 0xc6, 0x91, 0xe5, 0xfd, 0x30, 0x9c, 0xd5, 0xd1, 0xd2, 0x6d, 0x57, 0x63, 0xa9, - 0xe8, 0xd2, 0x71, 0xc9, 0x77, 0x05, 0x0e, 0x05, 0xdc, 0x96, - ], + 0x72, 0x36, 0xea, 0xb9, 0xf0, 0x12, 0x98, 0xc8, 0x4f, 0x38, 0x28, 0xf6, 0xac, 0x15, + 0x42, 0x76, 0xb5, 0xb7, 0x64, 0x62, 0xf5, 0x74, 0x2d, 0x69, 0xdc, 0x47, 0x7a, 0x10, + 0x5d, 0xc2, 0x71, 0x1b, 0x12, 0xe9, 0xb5, 0x82, 0x8c, 0x01, 0x76, 0xfe, 0xf4, 0x4a, + 0x54, 0x0f, 0x60, 0x95, 0x8e, 0x5a, 0x3e, 0xd6, 0xa2, 0xcc, 0x5e, 0xdd, 0xe9, 0x13, + 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, + 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -933,34 +937,34 @@ pub(crate) fn test_vectors() -> Vec { 0xd2, 0x50, 0x21, 0x17, ], rho: [ - 0x23, 0x39, 0xa8, 0x95, 0x29, 0xcf, 0x35, 0x7b, 0x06, 0x7d, 0xd2, 0x8b, 0xe4, 0x06, - 0x6e, 0x16, 0x23, 0x6d, 0xc5, 0xd7, 0x87, 0x06, 0x14, 0x9a, 0x72, 0x8c, 0x3e, 0x3d, - 0x9d, 0xc1, 0x08, 0x1c, + 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, + 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, + 0x3c, 0xfb, 0xf1, 0x31, ], cmx: [ - 0xe3, 0x04, 0xcf, 0x08, 0xc7, 0x86, 0xaf, 0xcb, 0x1d, 0x65, 0x2f, 0x7a, 0x94, 0x17, - 0x29, 0x32, 0x01, 0x51, 0x71, 0x37, 0x93, 0x82, 0x89, 0x42, 0xcb, 0x88, 0xd0, 0x1f, - 0x68, 0x60, 0x4e, 0x1f, + 0xea, 0x7c, 0x13, 0xf7, 0xe1, 0x20, 0x5e, 0x78, 0xc8, 0xce, 0x4e, 0xe4, 0xfd, 0xcd, + 0xb7, 0xee, 0x76, 0x92, 0x8d, 0xdf, 0x6d, 0xbe, 0x1b, 0x2d, 0x6f, 0x69, 0x81, 0xb7, + 0xc9, 0x65, 0x79, 0x10, ], esk: [ - 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, 0x40, 0xaf, 0x89, 0x3e, - 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, 0x6b, 0x5e, 0xd1, 0xf6, - 0xbf, 0x62, 0xbe, 0x3c, + 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, 0x73, 0xe9, 0x05, 0x99, + 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, 0x89, 0xcc, 0x63, 0x00, + 0x06, 0x15, 0xb2, 0x0d, ], ephemeral_key: [ - 0xdf, 0xe0, 0xf0, 0x0e, 0xb2, 0xb2, 0xf7, 0x08, 0x04, 0x19, 0x1b, 0x5b, 0x2d, 0xdf, - 0x57, 0x8f, 0x6a, 0xda, 0x21, 0x1b, 0x8b, 0x41, 0x7d, 0x95, 0xd2, 0xb7, 0x34, 0xff, - 0xa2, 0x2d, 0x81, 0x30, + 0x89, 0xfd, 0x2c, 0xf3, 0x79, 0x56, 0xba, 0xaf, 0x11, 0x27, 0xbb, 0x0e, 0x33, 0x40, + 0x01, 0x09, 0xdb, 0x03, 0x50, 0xf4, 0xab, 0xb7, 0xd6, 0xd8, 0x1f, 0xa5, 0x84, 0x8e, + 0x1b, 0xb1, 0x69, 0x26, ], shared_secret: [ - 0x0e, 0xc6, 0x82, 0xc8, 0xdc, 0x66, 0x41, 0x41, 0x02, 0x4f, 0x92, 0x9d, 0x1a, 0xe5, - 0xd3, 0x9c, 0x39, 0x4d, 0x05, 0xa2, 0x4d, 0xad, 0x0e, 0x4a, 0x6f, 0x94, 0x98, 0xed, - 0x5f, 0x87, 0xd4, 0x88, + 0xdb, 0xa6, 0x37, 0x94, 0xb6, 0x7c, 0x49, 0x6d, 0x01, 0x1c, 0xfb, 0x6b, 0xba, 0x29, + 0x7c, 0xa5, 0x7d, 0x18, 0xc7, 0xa9, 0xad, 0xdf, 0xfb, 0xc8, 0x37, 0x17, 0x6a, 0xcf, + 0x3a, 0x30, 0x1e, 0x23, ], k_enc: [ - 0xb1, 0x24, 0x5f, 0xb6, 0x37, 0x47, 0xc0, 0x13, 0x39, 0xcd, 0xe8, 0xf9, 0x35, 0x98, - 0xdf, 0xb2, 0xd3, 0x99, 0xec, 0x5e, 0x03, 0xbe, 0xa1, 0x3f, 0x3d, 0xbf, 0x01, 0xca, - 0xdb, 0x93, 0xc9, 0xba, + 0x80, 0xe7, 0x52, 0x2c, 0xb0, 0x32, 0x51, 0xc8, 0x55, 0x34, 0x1f, 0x06, 0xf9, 0x41, + 0x33, 0x41, 0xe1, 0x6e, 0x83, 0xb4, 0x89, 0xe1, 0x5a, 0x0a, 0x00, 0x65, 0xc3, 0x3b, + 0xf3, 0x81, 0x58, 0xc4, ], p_enc: [ 0x02, 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, 0x7e, 0x65, @@ -1006,69 +1010,70 @@ pub(crate) fn test_vectors() -> Vec { 0xd7, 0x6b, 0xa4, 0x80, ], c_enc: [ - 0x31, 0xec, 0x78, 0xd4, 0x02, 0x14, 0xc1, 0xbc, 0x7b, 0x25, 0x94, 0x7b, 0x42, 0xf3, - 0x54, 0x34, 0x60, 0x72, 0x90, 0x27, 0x7c, 0x44, 0xc4, 0x89, 0xe9, 0x38, 0x72, 0x2f, - 0x7c, 0x12, 0xff, 0x55, 0xc4, 0xf1, 0xdf, 0xbe, 0x0f, 0x1a, 0x65, 0xb1, 0x5c, 0x0c, - 0xc4, 0x7a, 0x46, 0xc9, 0xbb, 0x33, 0x5b, 0xd1, 0xa3, 0xe7, 0xe6, 0x62, 0xee, 0x85, - 0x84, 0x57, 0x6b, 0x6f, 0x42, 0x81, 0x95, 0xc9, 0x8c, 0x72, 0xfb, 0x99, 0x75, 0xc7, - 0x17, 0x9c, 0x4c, 0xab, 0x58, 0x66, 0xf5, 0xb4, 0x85, 0x42, 0x8b, 0x50, 0x8e, 0x2e, - 0x05, 0xbe, 0x0c, 0x98, 0x41, 0xa3, 0xa2, 0x91, 0x12, 0x80, 0x2c, 0x52, 0x15, 0xe2, - 0x51, 0x37, 0xcf, 0xdd, 0x13, 0x8c, 0x99, 0x39, 0x0e, 0xfb, 0xce, 0xb7, 0x52, 0x4e, - 0x84, 0x7c, 0x36, 0xb4, 0x3f, 0x3e, 0xde, 0x32, 0xf2, 0x3b, 0x39, 0x81, 0xf6, 0xd3, - 0xc3, 0x2b, 0x17, 0xbb, 0xbe, 0x65, 0xf2, 0xfd, 0x01, 0xab, 0xdd, 0x99, 0x87, 0xf1, - 0xb8, 0x88, 0xeb, 0xef, 0x41, 0xef, 0x45, 0x55, 0xc9, 0xfb, 0x0c, 0x8a, 0xee, 0x9b, - 0x6d, 0xd0, 0x85, 0xb9, 0xfb, 0xc7, 0x4f, 0xe4, 0x6a, 0x1e, 0x36, 0x3d, 0x68, 0x32, - 0xb5, 0x08, 0x20, 0x0e, 0x50, 0x0d, 0xa6, 0x95, 0x13, 0xb7, 0x9e, 0x81, 0xf7, 0x33, - 0xb6, 0x6c, 0x3f, 0x24, 0x3a, 0x28, 0x5b, 0xf8, 0x6f, 0xfe, 0xef, 0x4f, 0xfd, 0x1c, - 0xac, 0xa7, 0x83, 0x07, 0x26, 0x63, 0xbf, 0x9b, 0x48, 0x7f, 0xbc, 0x3e, 0x7f, 0x5a, - 0xd2, 0xf7, 0xac, 0xbf, 0x2b, 0x6e, 0x00, 0x8e, 0x3e, 0x4d, 0x6f, 0x31, 0xe1, 0x14, - 0x75, 0xe1, 0x96, 0x98, 0x9d, 0xb9, 0x62, 0x8a, 0x5d, 0x56, 0x39, 0x7c, 0x9a, 0x04, - 0x2a, 0xab, 0x55, 0xe1, 0xec, 0xc4, 0x92, 0xfe, 0x94, 0x27, 0xd4, 0x90, 0xf2, 0x73, - 0xb6, 0x01, 0xd6, 0x51, 0x05, 0x56, 0x82, 0xd3, 0x5b, 0x30, 0x75, 0xfa, 0xda, 0x85, - 0x25, 0x84, 0x48, 0x14, 0x95, 0x7f, 0xfc, 0x9b, 0xc7, 0xfb, 0x39, 0x39, 0x73, 0x7b, - 0x01, 0x50, 0x2e, 0x0b, 0x6f, 0x1f, 0x9b, 0x88, 0xf2, 0x71, 0x54, 0x80, 0xae, 0x42, - 0x2e, 0x9b, 0xb7, 0xb7, 0x6e, 0x5d, 0x22, 0xde, 0x0d, 0x3d, 0x7a, 0xea, 0x58, 0x10, - 0x01, 0xdc, 0xf4, 0x6a, 0x62, 0x2f, 0x08, 0x03, 0x10, 0xbe, 0x50, 0xdf, 0x07, 0x75, - 0x21, 0x92, 0xd4, 0xe4, 0x1a, 0xc5, 0x18, 0xe4, 0x24, 0x1e, 0x06, 0x67, 0x76, 0xa8, - 0xea, 0xec, 0xc7, 0x42, 0xfd, 0x2c, 0x1b, 0xf0, 0x6f, 0xc5, 0x8b, 0xd2, 0x8d, 0x1d, - 0x6c, 0x60, 0x1f, 0x91, 0x5d, 0x75, 0x2e, 0x7c, 0xc3, 0xd9, 0x76, 0x3c, 0x8b, 0x9e, - 0xec, 0x14, 0x2c, 0x84, 0x81, 0xf9, 0xc5, 0x23, 0x59, 0xbf, 0xbf, 0x51, 0x24, 0x36, - 0x67, 0x84, 0xe1, 0x71, 0xd7, 0xa4, 0xaa, 0x01, 0x5e, 0x85, 0x56, 0x47, 0x4a, 0x6d, - 0x0f, 0xee, 0x69, 0xb0, 0xd5, 0x3e, 0xe7, 0xf4, 0xed, 0xf5, 0xea, 0x59, 0xfa, 0x55, - 0x97, 0xf4, 0x8d, 0xd6, 0xaa, 0x88, 0x51, 0x84, 0x29, 0xac, 0x8c, 0x18, 0xc4, 0x73, - 0x8d, 0xb8, 0x01, 0x09, 0xa5, 0xe4, 0xbc, 0x81, 0xbb, 0x84, 0xb3, 0x7d, 0x9b, 0x2a, - 0xd4, 0xb1, 0xd2, 0x6b, 0x36, 0x3d, 0x16, 0x60, 0x72, 0xf0, 0x8c, 0x56, 0x70, 0x62, - 0x27, 0xa9, 0xf8, 0x32, 0x97, 0x03, 0x70, 0x12, 0xd1, 0xf6, 0xda, 0x24, 0xa8, 0x69, - 0xeb, 0x32, 0x97, 0xbc, 0xbc, 0xcc, 0x8d, 0x7d, 0xed, 0x03, 0x0a, 0x3d, 0x60, 0xdf, - 0x88, 0x82, 0xe0, 0x62, 0x9e, 0x36, 0x14, 0x3c, 0x09, 0xca, 0x05, 0x21, 0x43, 0xcb, - 0x56, 0x62, 0x93, 0x8f, 0xa9, 0xf1, 0x15, 0xdd, 0xc0, 0x96, 0x65, 0x4c, 0x0b, 0x40, - 0x59, 0x4c, 0xba, 0x19, 0xee, 0xd4, 0x99, 0x53, 0x2b, 0x70, 0x8a, 0xde, 0xbe, 0x47, - 0x72, 0x6a, 0x83, 0xaf, 0x46, 0x3c, 0x80, 0xba, 0x2a, 0x1f, 0xe0, 0x71, 0xe1, 0x66, - 0xc4, 0x4d, 0x70, 0xdd, 0xbb, 0xba, 0x67, 0x06, 0xa1, 0xdc, 0x43, 0x27, 0x26, 0xfe, - 0x0f, 0xdb, 0xc6, 0x28, 0x21, 0xb5, 0x04, 0xea, 0x11, 0x66, 0xda, 0x48, 0xa8, 0x1b, - 0x63, 0x5e, 0x37, 0x63, 0x33, 0xd9, 0xbe, 0xfe, 0xc4, 0x93, 0xa0, 0x7d, 0xf4, 0x7b, - 0xba, 0x0a, 0x2e, 0x2f, 0x65, 0xe7, + 0x3f, 0x4e, 0x9b, 0x18, 0x56, 0xe7, 0xbf, 0xba, 0x7a, 0xbb, 0xc9, 0x4a, 0x72, 0xb4, + 0xab, 0xb1, 0xd8, 0x46, 0x26, 0x79, 0x30, 0x77, 0xe8, 0x37, 0xda, 0xf3, 0x3f, 0xff, + 0xa2, 0x7c, 0x7a, 0x33, 0x97, 0x8a, 0x54, 0x32, 0x51, 0x0d, 0x99, 0x3c, 0x7d, 0x92, + 0x24, 0xc0, 0x97, 0xac, 0xc5, 0x25, 0x88, 0x1c, 0x76, 0x08, 0x3c, 0x1b, 0x65, 0x1a, + 0x9d, 0xe1, 0xb5, 0xc1, 0xa6, 0xe0, 0x48, 0x2f, 0xae, 0x8f, 0x98, 0x6a, 0xb5, 0x9f, + 0xa7, 0xcd, 0x43, 0x98, 0x99, 0x6e, 0x2b, 0xc0, 0x3a, 0xdc, 0xa9, 0x90, 0x32, 0x3b, + 0xaa, 0xbd, 0xda, 0xae, 0x40, 0xb0, 0x56, 0xb7, 0xac, 0x17, 0xf8, 0x20, 0xd1, 0x1c, + 0x0d, 0xec, 0xba, 0x14, 0xf2, 0x57, 0xa6, 0xcf, 0x09, 0x18, 0x19, 0x8f, 0x38, 0x9c, + 0xdb, 0x29, 0x55, 0x77, 0x25, 0x96, 0x92, 0x7c, 0xbf, 0x55, 0x88, 0x56, 0x13, 0x35, + 0xe7, 0xd6, 0x2e, 0x6a, 0x8a, 0xf7, 0xbc, 0x33, 0xb9, 0x9a, 0x55, 0xaf, 0xa1, 0xb7, + 0xef, 0x20, 0xeb, 0x4e, 0xd6, 0xde, 0x89, 0x69, 0xd2, 0x9f, 0x04, 0x21, 0xcd, 0x4d, + 0x99, 0x06, 0x66, 0xfd, 0xcf, 0x1e, 0xbd, 0x09, 0x06, 0x57, 0x02, 0x13, 0x4d, 0x31, + 0xc3, 0x29, 0x26, 0xa3, 0x8b, 0x6b, 0x6b, 0x48, 0xfd, 0xc9, 0xb3, 0xc7, 0x64, 0xc3, + 0xcd, 0x95, 0xb9, 0x72, 0xe7, 0x68, 0xeb, 0xd8, 0xaa, 0xe9, 0x0d, 0x6a, 0x4a, 0x98, + 0xb2, 0xd9, 0x2f, 0xd9, 0xdf, 0xa2, 0xa2, 0x99, 0xd0, 0x60, 0xe8, 0x5e, 0xf5, 0x68, + 0x3f, 0x51, 0xd0, 0x51, 0x4a, 0x6e, 0xba, 0x72, 0x57, 0x3f, 0x7b, 0xae, 0x84, 0xa2, + 0xfd, 0x92, 0xbe, 0x64, 0x24, 0x1c, 0x27, 0xa6, 0xe5, 0xce, 0xac, 0xbf, 0x37, 0xb2, + 0xd9, 0xa9, 0x75, 0xdf, 0x7a, 0xee, 0xbb, 0xa1, 0x4d, 0x8c, 0x81, 0x15, 0x8e, 0xcf, + 0x5a, 0x0a, 0x25, 0xe1, 0x2f, 0x98, 0x5d, 0x08, 0xfb, 0xb4, 0xa1, 0xc1, 0x3f, 0x76, + 0x1f, 0x3f, 0xfe, 0xe8, 0xd5, 0x38, 0xe3, 0x93, 0xf3, 0x58, 0x0b, 0x73, 0x82, 0xcd, + 0x0b, 0xf5, 0x17, 0xce, 0x78, 0x87, 0x1c, 0x19, 0xac, 0xf8, 0xca, 0x06, 0x5d, 0x7c, + 0x83, 0x87, 0xce, 0xcd, 0x0d, 0x37, 0xae, 0x21, 0x7f, 0x44, 0x06, 0x94, 0x77, 0x2a, + 0xbd, 0x4b, 0x36, 0x55, 0x56, 0x85, 0x4b, 0xaa, 0x8b, 0xcc, 0xa9, 0xc4, 0xfe, 0xf7, + 0x18, 0x99, 0x12, 0xf9, 0x8a, 0x25, 0x27, 0x68, 0x92, 0x76, 0xa4, 0x00, 0x8c, 0x83, + 0x8f, 0xe7, 0x4f, 0x7c, 0x2b, 0x75, 0x9f, 0xc2, 0xab, 0x7a, 0xfe, 0x37, 0x82, 0x80, + 0x6e, 0x31, 0xb1, 0xc5, 0x30, 0xcc, 0x46, 0x20, 0x3b, 0xb3, 0xa5, 0x66, 0xca, 0xf4, + 0xd1, 0x5b, 0x99, 0x40, 0xb4, 0x3f, 0x33, 0xa8, 0x6a, 0x65, 0xd4, 0x9d, 0xa8, 0xb6, + 0x78, 0x7d, 0xe0, 0x96, 0x38, 0xb4, 0x81, 0xf3, 0xa8, 0x10, 0x8a, 0x96, 0x9e, 0xca, + 0xdf, 0x90, 0x98, 0xbf, 0xf2, 0x14, 0x0c, 0x4b, 0x42, 0xe2, 0xb0, 0xfb, 0x10, 0xb9, + 0x02, 0x89, 0xb0, 0xc6, 0xdb, 0x8b, 0xc0, 0x85, 0xe8, 0xaf, 0xe9, 0x5d, 0xd3, 0x6a, + 0x45, 0x36, 0xea, 0xd7, 0xe9, 0x5c, 0x99, 0x66, 0x2c, 0xd9, 0x28, 0xc2, 0x2c, 0x3e, + 0xbf, 0x39, 0x79, 0x15, 0x78, 0xbc, 0x66, 0xfe, 0xa3, 0x01, 0x4d, 0x22, 0x92, 0x94, + 0x30, 0x83, 0xe7, 0x46, 0x81, 0x24, 0x52, 0xb0, 0x0b, 0xc2, 0xf3, 0xe4, 0x7c, 0x49, + 0x47, 0x46, 0xce, 0xd5, 0x57, 0xb1, 0x3a, 0xe3, 0x03, 0x0d, 0x8a, 0x95, 0x78, 0x10, + 0x2b, 0xba, 0xd2, 0xfc, 0x3b, 0x84, 0x5f, 0x31, 0xae, 0x16, 0xf8, 0xd8, 0x0b, 0x77, + 0xf8, 0x43, 0x15, 0x84, 0xa3, 0x7e, 0x8f, 0x30, 0xb0, 0xb9, 0x5c, 0xc4, 0x55, 0x5a, + 0xbc, 0x05, 0x3a, 0x0b, 0x4f, 0xf9, 0x13, 0xb0, 0x03, 0x69, 0xf1, 0x74, 0x7b, 0x1f, + 0x1c, 0x0a, 0xc8, 0x75, 0x4f, 0x01, 0x7e, 0x99, 0x47, 0xca, 0x63, 0x25, 0x5b, 0x3c, + 0x23, 0xf4, 0x56, 0xe2, 0x3f, 0x96, 0x76, 0x13, 0x99, 0x60, 0x1f, 0xd8, 0xda, 0xdb, + 0x5e, 0x3f, 0x90, 0xab, 0x1b, 0x20, 0x13, 0x81, 0x80, 0xed, 0x69, 0x73, 0x22, 0x39, + 0xc8, 0xc2, 0x15, 0xd9, 0xcc, 0x8a, 0xc8, 0x05, 0x9b, 0xde, 0x81, 0x63, 0x27, 0xd2, + 0x20, 0xb9, 0xa8, 0xec, 0xba, 0x5d, ], ock: [ - 0xec, 0xa3, 0x70, 0x7a, 0x74, 0x5d, 0x5d, 0x58, 0x65, 0x86, 0xb2, 0x35, 0xf2, 0x92, - 0xad, 0x20, 0x48, 0x93, 0x14, 0xc4, 0x58, 0x80, 0xd9, 0x83, 0x2b, 0x7f, 0x47, 0xee, - 0xbb, 0xd4, 0x5c, 0xfe, + 0xe6, 0xb7, 0x05, 0x50, 0xe1, 0xd7, 0xa2, 0xbe, 0x73, 0x04, 0x39, 0x64, 0x41, 0xec, + 0x6a, 0xc0, 0x47, 0x45, 0x99, 0xf9, 0xea, 0xd7, 0x55, 0xc2, 0xcf, 0x27, 0x6b, 0x87, + 0x50, 0xc5, 0xcf, 0x2d, ], op: [ 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, - 0x03, 0x8e, 0x3d, 0xb3, 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, - 0x40, 0xaf, 0x89, 0x3e, 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, - 0x6b, 0x5e, 0xd1, 0xf6, 0xbf, 0x62, 0xbe, 0x3c, + 0x03, 0x8e, 0x3d, 0xb3, 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, + 0x73, 0xe9, 0x05, 0x99, 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, + 0x89, 0xcc, 0x63, 0x00, 0x06, 0x15, 0xb2, 0x0d, ], c_out: [ - 0xd0, 0x65, 0x9a, 0x03, 0xc5, 0x3e, 0x15, 0xdc, 0x11, 0x01, 0xa6, 0x6e, 0xa8, 0x0d, - 0xf4, 0x14, 0x4d, 0x5e, 0xe0, 0x1c, 0x3d, 0xbf, 0x20, 0x2c, 0xe6, 0x08, 0x7e, 0x96, - 0xa8, 0x5a, 0xe1, 0x39, 0xdd, 0x46, 0xfc, 0x82, 0xa1, 0xc3, 0x7d, 0x06, 0x05, 0xf8, - 0x49, 0x98, 0x53, 0x13, 0x16, 0xf1, 0xf0, 0xcb, 0xc0, 0x4e, 0xa2, 0x0a, 0xa4, 0x04, - 0xb3, 0xd5, 0xb0, 0x42, 0x96, 0x01, 0x49, 0x81, 0x6d, 0x9b, 0x8f, 0x06, 0x2a, 0xfc, - 0xc1, 0x93, 0x89, 0x43, 0x82, 0x7a, 0x1b, 0x43, 0xfc, 0xbd, - ], + 0x02, 0xb1, 0x37, 0x3e, 0xb1, 0x89, 0x56, 0x32, 0x2b, 0x47, 0xa1, 0x70, 0x0d, 0xb7, + 0x43, 0x31, 0x6e, 0xde, 0x46, 0x44, 0xd6, 0x59, 0x3c, 0xd7, 0x94, 0x22, 0xd7, 0x51, + 0x3d, 0x1b, 0x80, 0xe6, 0x85, 0x05, 0xdf, 0xe9, 0xd6, 0x86, 0x2e, 0x79, 0x4e, 0x30, + 0x28, 0x8b, 0xae, 0xa8, 0xb0, 0xbc, 0xb3, 0x8b, 0x35, 0x49, 0x77, 0xaa, 0xee, 0x57, + 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, + 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -1142,34 +1147,34 @@ pub(crate) fn test_vectors() -> Vec { 0xda, 0x6b, 0x15, 0x14, ], rho: [ - 0xe5, 0xd0, 0x8c, 0x40, 0x26, 0x3e, 0x4a, 0x2a, 0x56, 0x96, 0xda, 0x21, 0x0d, 0x8e, - 0x9a, 0x77, 0xf0, 0xaf, 0xc4, 0xc6, 0x8a, 0x6d, 0xda, 0x38, 0xe2, 0x85, 0xf4, 0xe3, - 0xef, 0x13, 0xb8, 0x17, + 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, + 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, + 0x21, 0x38, 0xab, 0x29, ], cmx: [ - 0xad, 0xc2, 0x44, 0x3a, 0xf9, 0x57, 0x67, 0x47, 0xca, 0x4f, 0x10, 0x4b, 0x1f, 0x5a, - 0x7a, 0xdc, 0x80, 0x5a, 0xc5, 0x5a, 0xcc, 0x56, 0x33, 0xa0, 0xb3, 0xc2, 0xdc, 0x7a, - 0xad, 0xff, 0x21, 0x26, + 0x18, 0xfc, 0xbd, 0x40, 0xac, 0xf1, 0xa7, 0xf4, 0xd6, 0x09, 0x87, 0x9a, 0x5f, 0x5e, + 0x3b, 0x39, 0x70, 0x09, 0x4f, 0xf8, 0xbe, 0x84, 0x18, 0x60, 0x70, 0x16, 0xc6, 0xa6, + 0x97, 0xf8, 0x9c, 0x20, ], esk: [ - 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, 0x82, 0x35, 0x16, 0x58, - 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, 0xb0, 0x52, 0xd5, 0xb4, - 0x20, 0x41, 0xd8, 0x1c, + 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, 0x6b, 0x8d, 0x6f, 0xea, + 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, 0xd5, 0xcb, 0xab, 0x1a, + 0xcc, 0xd5, 0x4e, 0x3a, ], ephemeral_key: [ - 0x00, 0x5d, 0x31, 0x5b, 0xd1, 0x80, 0xa2, 0x94, 0x0b, 0xd7, 0xfb, 0x34, 0xa7, 0x0e, - 0x90, 0xe8, 0x32, 0x6c, 0xb1, 0x34, 0x30, 0x66, 0x05, 0x46, 0x53, 0xd2, 0x64, 0x4d, - 0x20, 0x45, 0xe3, 0x0f, + 0xcf, 0xe0, 0x3e, 0xb2, 0xd3, 0x36, 0x76, 0xb7, 0x73, 0x83, 0x7d, 0xa8, 0x39, 0x17, + 0x2d, 0x33, 0x33, 0x31, 0x88, 0xc9, 0xdf, 0xef, 0x05, 0xc8, 0x32, 0xa2, 0x5c, 0x86, + 0xd3, 0xbf, 0x0e, 0x8f, ], shared_secret: [ - 0x8e, 0x59, 0x0d, 0x06, 0x3f, 0x7e, 0xc3, 0x8e, 0xb2, 0x00, 0x84, 0x70, 0xf9, 0xbb, - 0x42, 0x29, 0x04, 0xfc, 0x0b, 0xaf, 0x97, 0x80, 0xf8, 0xfd, 0x1f, 0x54, 0x22, 0xea, - 0x30, 0x8c, 0x47, 0xba, + 0xd2, 0xc2, 0x88, 0x9e, 0x03, 0x7e, 0xac, 0x60, 0x60, 0x58, 0x68, 0x2b, 0xaa, 0x38, + 0x86, 0xa4, 0xc2, 0xdd, 0x44, 0xea, 0xdf, 0x8b, 0x2c, 0xe4, 0x39, 0x95, 0xde, 0xd7, + 0x61, 0xfd, 0xaf, 0xb5, ], k_enc: [ - 0xeb, 0xb2, 0xff, 0x9b, 0x1f, 0x29, 0x0d, 0xa5, 0x63, 0x27, 0xa9, 0x67, 0x71, 0xb2, - 0x5f, 0x71, 0x29, 0xff, 0x10, 0x2e, 0xe6, 0xd2, 0xb2, 0x0d, 0xa0, 0x9a, 0x06, 0x25, - 0xf8, 0xbb, 0x26, 0x07, + 0xfe, 0xe3, 0xe3, 0xb5, 0xfd, 0x6c, 0xd8, 0x54, 0x44, 0x2b, 0x2a, 0xc2, 0x97, 0x70, + 0xfb, 0x0e, 0x39, 0x32, 0xf4, 0x71, 0x52, 0x43, 0x26, 0xda, 0x4a, 0x57, 0xc2, 0x56, + 0x18, 0x06, 0x9e, 0x99, ], p_enc: [ 0x02, 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, 0x91, 0x20, @@ -1215,69 +1220,70 @@ pub(crate) fn test_vectors() -> Vec { 0x34, 0x1e, 0x4e, 0x6f, ], c_enc: [ - 0x96, 0x3b, 0xe3, 0x6e, 0xdc, 0xa4, 0x8b, 0x7c, 0x4a, 0x1c, 0xd6, 0xa1, 0x37, 0x2e, - 0x84, 0xc0, 0x54, 0x54, 0x83, 0x4c, 0x5e, 0xe1, 0x92, 0x5e, 0xed, 0xeb, 0x48, 0xda, - 0x16, 0x77, 0x79, 0xe3, 0x99, 0x83, 0x58, 0xcb, 0x92, 0x7a, 0x0a, 0x0b, 0x36, 0x9c, - 0x85, 0xee, 0xb3, 0x30, 0xf7, 0x00, 0x5c, 0x26, 0x9d, 0x0b, 0xe4, 0xf2, 0x38, 0x09, - 0x57, 0xb1, 0x62, 0x97, 0x7c, 0xae, 0x7a, 0x7b, 0x1d, 0x0b, 0xe5, 0xd0, 0xb7, 0x03, - 0xd3, 0x92, 0xac, 0xae, 0xd2, 0x4f, 0x52, 0x5b, 0x83, 0xcf, 0xdd, 0x7f, 0x35, 0xc1, - 0xf1, 0x74, 0xbf, 0x06, 0x6b, 0x7a, 0xfd, 0xb7, 0x45, 0xed, 0xbe, 0xdc, 0x0b, 0x46, - 0xa5, 0x91, 0x36, 0x21, 0x47, 0x61, 0x9d, 0x6b, 0xd3, 0xf3, 0xce, 0x6b, 0x45, 0x23, - 0xf0, 0x64, 0x9a, 0x7c, 0x65, 0x32, 0x2d, 0x05, 0xfa, 0xe2, 0x22, 0x70, 0x1a, 0x8c, - 0xd6, 0xca, 0xbf, 0x8d, 0xc3, 0x2f, 0x05, 0x5f, 0xeb, 0x14, 0x1e, 0x55, 0x6d, 0xdf, - 0xb1, 0x98, 0x30, 0xb7, 0x20, 0x4c, 0x30, 0x98, 0x4e, 0xdd, 0xf4, 0x34, 0xec, 0xc5, - 0xf0, 0xea, 0x82, 0x5c, 0xf8, 0xd9, 0xd5, 0x03, 0x8f, 0x28, 0xe2, 0x3e, 0xf3, 0x6b, - 0xa9, 0x38, 0x52, 0xe5, 0x8e, 0x85, 0xf8, 0x90, 0xb1, 0x77, 0x5c, 0x6d, 0x4c, 0x13, - 0x5b, 0xef, 0x0e, 0x2a, 0x19, 0x33, 0x02, 0xd9, 0x0a, 0x80, 0x4c, 0x85, 0x31, 0x25, - 0xaa, 0x5b, 0x11, 0x6f, 0x8c, 0x58, 0x0e, 0xb6, 0x54, 0xfe, 0x35, 0xe6, 0x73, 0x79, - 0x9e, 0x93, 0xcf, 0x58, 0xfe, 0x1e, 0x70, 0xcd, 0xe1, 0x19, 0xab, 0x58, 0x6c, 0x12, - 0xc4, 0x95, 0x75, 0xe6, 0x1a, 0xc4, 0xb7, 0x71, 0xfa, 0x8e, 0xbf, 0x76, 0xca, 0x95, - 0xd6, 0x51, 0xa4, 0xba, 0x87, 0x3b, 0x24, 0xcf, 0x97, 0xff, 0x75, 0x5b, 0xc7, 0x49, - 0xf4, 0x09, 0x6d, 0x2d, 0xa1, 0x5c, 0xf8, 0x30, 0x36, 0xcc, 0x22, 0x0f, 0x0a, 0x68, - 0x93, 0x43, 0x21, 0xc9, 0xae, 0x33, 0x4e, 0x2d, 0x99, 0xa9, 0x95, 0xe9, 0x29, 0x04, - 0xc1, 0x45, 0x23, 0x33, 0x19, 0x00, 0xcb, 0xca, 0x20, 0x4a, 0xdc, 0xb6, 0x93, 0x9d, - 0xc1, 0x71, 0x87, 0x53, 0x53, 0xa1, 0x1e, 0x12, 0xba, 0xcb, 0x2a, 0xab, 0x0f, 0x57, - 0x17, 0x9f, 0x1b, 0x67, 0xea, 0xcc, 0x7e, 0x7b, 0x6c, 0x5c, 0xc8, 0xa3, 0x78, 0x64, - 0x9b, 0x62, 0xb8, 0x52, 0xfa, 0x47, 0x6f, 0x93, 0x37, 0x88, 0x59, 0xd0, 0xd9, 0xa3, - 0x03, 0x3d, 0xa1, 0x31, 0x28, 0x17, 0x57, 0xad, 0x98, 0x5c, 0x86, 0xfe, 0x03, 0x7a, - 0x4e, 0xdd, 0x0a, 0x4a, 0x49, 0xee, 0x5c, 0x4f, 0x48, 0x15, 0xf0, 0x14, 0x73, 0xb9, - 0x60, 0xa1, 0x8a, 0x3b, 0x7f, 0x75, 0x07, 0xee, 0x3d, 0x8b, 0x39, 0x5a, 0x76, 0x68, - 0x40, 0x95, 0x5b, 0xaa, 0xdd, 0x0a, 0xbb, 0xf4, 0xf5, 0x91, 0x4e, 0x92, 0x10, 0xf5, - 0x9e, 0x4c, 0xd1, 0x3c, 0x82, 0xe0, 0xac, 0xf8, 0x79, 0x51, 0x78, 0x02, 0x91, 0xd0, - 0xa9, 0xa7, 0x0f, 0x6b, 0x4f, 0xf5, 0x0d, 0x81, 0x0d, 0x50, 0x90, 0x20, 0x45, 0x30, - 0xad, 0x69, 0x44, 0xb1, 0x3d, 0x23, 0x83, 0xab, 0xca, 0x42, 0x0c, 0xb6, 0xd9, 0xfc, - 0xd8, 0xfd, 0xcb, 0xe9, 0xb3, 0xb5, 0xf4, 0x2f, 0x0a, 0xf5, 0xdf, 0x36, 0x37, 0x8c, - 0xe7, 0x3d, 0xc9, 0x06, 0x16, 0x7d, 0xd4, 0xb3, 0x80, 0x41, 0x8f, 0x17, 0xe4, 0x50, - 0x61, 0x18, 0x57, 0x23, 0xda, 0xbb, 0x6f, 0xfd, 0xbb, 0xd5, 0xa4, 0x18, 0xc3, 0xc6, - 0xfd, 0x33, 0x70, 0x34, 0x09, 0x94, 0x27, 0x7b, 0x88, 0x8e, 0xe4, 0x9b, 0x08, 0x91, - 0xbb, 0xb9, 0x4b, 0x6b, 0x8b, 0x06, 0x5f, 0xd1, 0x92, 0x00, 0xdc, 0x3a, 0x68, 0x1c, - 0xa5, 0xff, 0x2a, 0x98, 0x8f, 0xa6, 0x6d, 0x02, 0x9d, 0xdd, 0xf9, 0xb0, 0x3a, 0x5e, - 0x6c, 0x6e, 0x99, 0xb6, 0x35, 0x41, 0x15, 0x6a, 0x09, 0x51, 0xd9, 0x08, 0x7d, 0xd8, - 0x83, 0xd5, 0x13, 0x9e, 0xe6, 0x7a, 0x8c, 0xe5, 0xdd, 0x6e, 0xf1, 0x4c, 0x9a, 0x10, - 0xdb, 0x81, 0x8b, 0x93, 0x69, 0x02, 0xc7, 0x99, 0x93, 0x90, 0xf9, 0x72, 0xba, 0xfa, - 0x5a, 0x57, 0x2f, 0xc8, 0x73, 0x42, 0xe2, 0xc5, 0x1c, 0xeb, 0x80, 0x30, 0xe0, 0x6b, - 0x72, 0x40, 0x95, 0xf9, 0x8d, 0x7b, + 0xbe, 0x1d, 0xff, 0xd3, 0x37, 0x0c, 0x67, 0x56, 0x69, 0xcc, 0x9a, 0xe1, 0xd0, 0x30, + 0x2d, 0x7f, 0x90, 0x6d, 0x25, 0x23, 0x09, 0x3c, 0x24, 0xf4, 0x25, 0x7a, 0x83, 0xbc, + 0x4f, 0x36, 0x62, 0x3a, 0x08, 0x2c, 0xe6, 0xeb, 0x45, 0x21, 0x95, 0x71, 0x91, 0xd5, + 0x7e, 0x14, 0x11, 0xed, 0xe7, 0x1d, 0x44, 0xb5, 0x6c, 0x57, 0xcb, 0x22, 0x81, 0x4a, + 0x04, 0x69, 0x39, 0xd2, 0xff, 0xf9, 0x2b, 0x46, 0x62, 0x76, 0x2d, 0x4f, 0x21, 0xc0, + 0x78, 0x42, 0x74, 0x72, 0xb9, 0x18, 0x10, 0x10, 0x55, 0x56, 0xf4, 0xde, 0x0a, 0x27, + 0xe7, 0x70, 0x08, 0x47, 0x72, 0xcb, 0xfe, 0xbf, 0x87, 0xdb, 0x33, 0x14, 0xab, 0x70, + 0xf2, 0x6d, 0x11, 0xea, 0x5d, 0xe2, 0x67, 0xc3, 0xa9, 0xa8, 0xf4, 0x6b, 0xad, 0x13, + 0xc7, 0x36, 0x26, 0x10, 0xbd, 0xba, 0x81, 0x02, 0xd4, 0xb7, 0x26, 0xef, 0x26, 0xec, + 0x79, 0x4a, 0x15, 0x66, 0x57, 0x1b, 0xfd, 0xc1, 0x02, 0x47, 0x7d, 0xa5, 0xb4, 0x9b, + 0xbf, 0x9f, 0xe4, 0xb1, 0xa4, 0x4e, 0xd0, 0xb3, 0xbc, 0xed, 0x99, 0xba, 0x81, 0x9a, + 0x4f, 0x30, 0x22, 0x65, 0x49, 0x44, 0x5b, 0xc6, 0x1c, 0xff, 0x5c, 0x33, 0x16, 0x33, + 0x5f, 0x6b, 0xd4, 0xa9, 0xa4, 0x24, 0xc9, 0x4a, 0xe0, 0xb5, 0xcb, 0xe4, 0x8a, 0xfb, + 0x2b, 0x94, 0xd0, 0xc7, 0xe4, 0x4e, 0x32, 0x30, 0x95, 0xa7, 0x2e, 0x42, 0x64, 0xe9, + 0x1c, 0x48, 0x94, 0xb9, 0xe8, 0x45, 0xaf, 0x32, 0x35, 0x02, 0xda, 0xe8, 0xc1, 0x86, + 0x78, 0xa4, 0xf7, 0x40, 0xe5, 0xa6, 0x3a, 0x4c, 0x70, 0x29, 0x92, 0xfa, 0xcd, 0xd3, + 0x57, 0x35, 0xb1, 0xd1, 0x34, 0x8b, 0x91, 0x9c, 0x70, 0x0c, 0x42, 0xd3, 0x30, 0xd3, + 0x86, 0xaf, 0xb8, 0x73, 0xfa, 0xba, 0xd8, 0xcb, 0x32, 0x18, 0x15, 0x1b, 0x40, 0x18, + 0x01, 0xe3, 0x69, 0x34, 0x4f, 0xf2, 0x0a, 0xaa, 0x66, 0x73, 0x47, 0x4f, 0x4b, 0xfc, + 0x98, 0xd0, 0x7e, 0x36, 0x7b, 0xc4, 0x2e, 0xf1, 0xa0, 0x4f, 0xa1, 0xbc, 0x12, 0x52, + 0x18, 0x8d, 0xd9, 0xd3, 0xe0, 0x00, 0xe3, 0xf5, 0xe9, 0xdf, 0xc9, 0xe1, 0x3e, 0xe9, + 0xdb, 0x55, 0x04, 0x0d, 0x17, 0x22, 0x7d, 0xa4, 0x4a, 0x3e, 0x08, 0xfd, 0x5e, 0xc8, + 0x58, 0xc4, 0x9c, 0x2e, 0x6a, 0x71, 0x1f, 0x8e, 0x68, 0xd0, 0xa1, 0xdf, 0x88, 0xef, + 0x09, 0x40, 0xf7, 0x2e, 0xd7, 0x3e, 0xf4, 0x9e, 0x8a, 0x45, 0xae, 0x2e, 0x5e, 0x1b, + 0xf1, 0x37, 0xba, 0x58, 0xcf, 0xb9, 0x25, 0x79, 0xab, 0xb2, 0xa4, 0x93, 0x13, 0xa2, + 0xff, 0x3d, 0xb6, 0x16, 0x93, 0xd2, 0xb7, 0x58, 0xaf, 0x20, 0x47, 0x2a, 0xc6, 0x40, + 0x6b, 0xa3, 0x55, 0xb4, 0x8c, 0xee, 0x22, 0xe7, 0x0f, 0xb8, 0xf9, 0xd4, 0x8e, 0xa3, + 0x93, 0x4b, 0x62, 0x24, 0xac, 0xe2, 0x69, 0xb9, 0xef, 0x54, 0x6d, 0xbf, 0xc5, 0x2a, + 0xbe, 0xcf, 0xac, 0x59, 0x40, 0xf0, 0x40, 0xbd, 0x21, 0xe9, 0x0e, 0xfa, 0x82, 0x75, + 0x56, 0x1a, 0x88, 0xbc, 0x18, 0xe2, 0x6b, 0x98, 0x8d, 0x11, 0x79, 0xb7, 0xa2, 0xc3, + 0xaf, 0xd8, 0x6e, 0xf2, 0xa0, 0x90, 0x62, 0x52, 0x23, 0x23, 0x4b, 0x39, 0xc9, 0xe2, + 0x06, 0x8d, 0x94, 0x5d, 0xd7, 0x76, 0x3b, 0x01, 0x0c, 0x28, 0xc8, 0x9b, 0x72, 0xe2, + 0x55, 0x13, 0xb3, 0x9c, 0x3c, 0xe1, 0x17, 0x73, 0x42, 0x8a, 0xd3, 0x44, 0xe1, 0xd5, + 0xd5, 0x1b, 0x92, 0x00, 0x14, 0xf9, 0x17, 0x06, 0xff, 0xae, 0x3d, 0x86, 0x36, 0x14, + 0x77, 0xfd, 0x5d, 0xe0, 0x13, 0x42, 0x2c, 0x06, 0xa3, 0x32, 0xe3, 0x45, 0x79, 0x75, + 0xcf, 0x9b, 0xe9, 0xf9, 0xab, 0x3a, 0x06, 0x87, 0x2e, 0xf0, 0x71, 0x7d, 0x39, 0x08, + 0xbd, 0xeb, 0xf8, 0x41, 0x8c, 0xe5, 0x57, 0xd5, 0x2d, 0x51, 0xa2, 0x50, 0xc0, 0x8c, + 0x5b, 0x79, 0x3a, 0xd4, 0xbc, 0x0f, 0x16, 0xc6, 0x27, 0x89, 0xfe, 0xa2, 0xca, 0xb3, + 0x9c, 0xcc, 0xa4, 0x07, 0xee, 0x9e, 0x47, 0xf5, 0x6d, 0x20, 0xa7, 0x41, 0x91, 0x2c, + 0x6b, 0xad, 0xdb, 0xd7, 0xfa, 0x7b, 0x97, 0xe5, 0x46, 0x33, 0x61, 0x28, 0x74, 0x5a, + 0xe7, 0xd7, 0x30, 0xa5, 0x5a, 0x6a, 0xc7, 0xb8, 0xfc, 0xbd, 0x72, 0xce, 0x78, 0x95, + 0x9c, 0x7a, 0x79, 0x75, 0x21, 0x2c, ], ock: [ - 0x5b, 0x5b, 0x20, 0xfc, 0x46, 0xba, 0x14, 0xbd, 0x18, 0x43, 0xb6, 0xc7, 0x7e, 0xc3, - 0xf4, 0x55, 0xb7, 0x65, 0xb4, 0xd1, 0x2d, 0xb6, 0x52, 0xeb, 0x34, 0x20, 0x0c, 0x41, - 0x48, 0x88, 0x1f, 0xfc, + 0xeb, 0x3e, 0xd9, 0xfc, 0xb3, 0xaa, 0x91, 0xc4, 0xf5, 0xec, 0xfd, 0x43, 0xdb, 0xda, + 0x40, 0x33, 0x06, 0x93, 0xc3, 0xa6, 0x56, 0x75, 0x45, 0xfd, 0x23, 0x6a, 0xf1, 0x90, + 0x8e, 0x29, 0x42, 0xa3, ], op: [ 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, - 0x67, 0xa8, 0x60, 0x9e, 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, - 0x82, 0x35, 0x16, 0x58, 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, - 0xb0, 0x52, 0xd5, 0xb4, 0x20, 0x41, 0xd8, 0x1c, + 0x67, 0xa8, 0x60, 0x9e, 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, + 0x6b, 0x8d, 0x6f, 0xea, 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, + 0xd5, 0xcb, 0xab, 0x1a, 0xcc, 0xd5, 0x4e, 0x3a, ], c_out: [ - 0xe0, 0x1b, 0x5c, 0x1e, 0x01, 0x90, 0x0f, 0xf7, 0x9b, 0xf7, 0x27, 0xf5, 0x37, 0xc4, - 0xac, 0x36, 0xf8, 0x06, 0x7a, 0x0c, 0xc5, 0xc8, 0xe9, 0xc8, 0x20, 0x44, 0x28, 0x43, - 0x69, 0x35, 0x30, 0x91, 0x8a, 0xea, 0x67, 0x2c, 0x4c, 0xd8, 0xfa, 0x3f, 0x6f, 0x2c, - 0xb6, 0x8b, 0x87, 0x17, 0x22, 0xe7, 0x78, 0xf6, 0xe2, 0x5e, 0x78, 0xae, 0x00, 0xa8, - 0x43, 0x28, 0xc4, 0xc2, 0xbf, 0x1c, 0x79, 0xb2, 0xc9, 0xd8, 0x69, 0x72, 0x60, 0xcd, - 0x44, 0x7e, 0x2e, 0xff, 0x31, 0x5d, 0x74, 0xb5, 0xb1, 0xfd, - ], + 0x60, 0xf3, 0xe8, 0x94, 0xe3, 0x86, 0x4e, 0xfb, 0x48, 0xcc, 0xae, 0x50, 0xe1, 0x0d, + 0xa7, 0x73, 0xdc, 0xcf, 0x85, 0x62, 0x45, 0x5d, 0x1b, 0x73, 0x1a, 0xad, 0x44, 0xe1, + 0x5e, 0x3e, 0x40, 0x18, 0x31, 0xce, 0x6f, 0x92, 0xf4, 0x53, 0x2d, 0x90, 0x83, 0x92, + 0x59, 0xce, 0x9c, 0xb1, 0x44, 0x62, 0x1f, 0x12, 0x01, 0x77, 0x8f, 0x61, 0x5d, 0x09, + 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, + 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -1351,34 +1357,34 @@ pub(crate) fn test_vectors() -> Vec { 0x88, 0xff, 0xee, 0x2f, ], rho: [ - 0xe9, 0x16, 0x93, 0xc3, 0x7d, 0x04, 0x37, 0x5e, 0x67, 0xc5, 0x71, 0x5a, 0x39, 0xc9, - 0x79, 0x4a, 0x4e, 0xcd, 0x08, 0x38, 0xe2, 0x35, 0x1f, 0xd7, 0xcd, 0x93, 0xa1, 0x55, - 0x7f, 0x01, 0x02, 0x3e, + 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, + 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, + 0x92, 0xd7, 0xa0, 0x24, ], cmx: [ - 0xcc, 0x29, 0x41, 0xe0, 0xf6, 0x38, 0x25, 0x7f, 0xb6, 0x51, 0x6a, 0x27, 0xc3, 0x0e, - 0xaa, 0xe0, 0xb4, 0x6d, 0x2f, 0xf0, 0x6a, 0x73, 0x50, 0x70, 0x41, 0x74, 0x6c, 0xdc, - 0x23, 0x07, 0x61, 0x25, + 0x1d, 0x51, 0xea, 0x92, 0xfa, 0x43, 0x55, 0x0a, 0x0e, 0xdd, 0xea, 0x23, 0x6e, 0x17, + 0xa0, 0x16, 0x93, 0xc2, 0x2d, 0x8d, 0xd8, 0x1c, 0x9c, 0x9e, 0xc8, 0x76, 0xa2, 0x4e, + 0x67, 0xd4, 0x93, 0x0b, ], esk: [ - 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, 0xbf, 0xb7, 0x8a, 0xec, - 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, 0x77, 0xc9, 0x46, 0xe9, - 0xcd, 0x7a, 0x24, 0x23, + 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, 0x14, 0xb0, 0xdf, 0x85, + 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, 0xc4, 0x84, 0xa9, 0xf4, + 0xc7, 0xda, 0x74, 0x36, ], ephemeral_key: [ - 0xad, 0xa7, 0x60, 0x27, 0xdc, 0xae, 0xb5, 0xf1, 0x58, 0xac, 0x6c, 0x5c, 0x6d, 0x7f, - 0x05, 0x31, 0x8f, 0xec, 0x26, 0xd5, 0xc7, 0x94, 0xf2, 0xe9, 0x00, 0xcb, 0x96, 0x29, - 0x92, 0x49, 0xe0, 0xb5, + 0x8f, 0xbe, 0xb6, 0xb3, 0x03, 0x8e, 0x69, 0x49, 0x91, 0x6a, 0x2c, 0x06, 0x0e, 0xf9, + 0xa4, 0xb1, 0xfe, 0xf1, 0x3a, 0xce, 0x2f, 0xee, 0x00, 0x25, 0xda, 0x32, 0xc3, 0x6d, + 0x23, 0x1a, 0x61, 0x34, ], shared_secret: [ - 0xc2, 0x5c, 0xf1, 0xd6, 0x53, 0x2e, 0x06, 0xcb, 0x8b, 0x15, 0x22, 0x14, 0x76, 0x6e, - 0xee, 0xd7, 0x5a, 0x17, 0x8c, 0x82, 0x2a, 0x11, 0x51, 0xf6, 0x9e, 0x92, 0xe9, 0xcf, - 0xfa, 0x47, 0xcb, 0x19, + 0x67, 0xd6, 0x8a, 0x5a, 0x05, 0x93, 0xfd, 0x16, 0x7d, 0x38, 0x08, 0x2e, 0x49, 0xd2, + 0x30, 0x30, 0x86, 0xe5, 0x5a, 0x43, 0xc1, 0x24, 0xd5, 0xaa, 0xa8, 0x20, 0xab, 0x0c, + 0x3f, 0x5c, 0xc5, 0x37, ], k_enc: [ - 0xd4, 0xef, 0x89, 0xc4, 0x64, 0xbe, 0x8f, 0x42, 0xf6, 0xb7, 0xf2, 0x6d, 0x89, 0x37, - 0x8b, 0x73, 0xa3, 0x55, 0xa4, 0xfe, 0x24, 0x6c, 0x2e, 0xc8, 0xe8, 0x14, 0x6b, 0xef, - 0x7d, 0xdd, 0x14, 0x19, + 0x6b, 0x8d, 0x83, 0xf2, 0xf1, 0xfd, 0x1e, 0xad, 0x7d, 0x45, 0x42, 0xb3, 0x63, 0x09, + 0x34, 0x07, 0xc5, 0x0a, 0x20, 0xed, 0x7f, 0x0e, 0x8c, 0xf2, 0xdb, 0x53, 0x6d, 0xb1, + 0xbe, 0x25, 0xe9, 0x8d, ], p_enc: [ 0x02, 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, 0x10, 0xb8, @@ -1424,69 +1430,70 @@ pub(crate) fn test_vectors() -> Vec { 0x1a, 0x81, 0xa3, 0x59, ], c_enc: [ - 0xea, 0x86, 0x7e, 0x07, 0xac, 0xb7, 0xfa, 0x03, 0xe7, 0x36, 0xce, 0xdd, 0xed, 0x82, - 0x3d, 0x19, 0x91, 0x30, 0xfb, 0x3f, 0xef, 0x62, 0xcc, 0x3e, 0xa9, 0xa0, 0xc9, 0x35, - 0xdf, 0x05, 0xc5, 0xad, 0x5e, 0x67, 0xf7, 0x4f, 0xcb, 0xa6, 0x67, 0xe0, 0x81, 0x1c, - 0xdc, 0x0c, 0xa9, 0xf3, 0xd7, 0x81, 0x76, 0x43, 0x75, 0x56, 0x47, 0xbe, 0x59, 0xdf, - 0x09, 0x6e, 0x46, 0x5e, 0xc1, 0x11, 0x24, 0x36, 0x3c, 0x98, 0x1c, 0x55, 0xd5, 0x5f, - 0x8d, 0x8a, 0xc8, 0xb6, 0x54, 0x0a, 0x98, 0xcf, 0xcc, 0x29, 0x4a, 0xa7, 0xcc, 0x62, - 0x95, 0x50, 0x85, 0x3a, 0x25, 0xbf, 0x6b, 0x32, 0x35, 0x16, 0xe1, 0x58, 0x2b, 0x4e, - 0x8b, 0x82, 0x95, 0xe2, 0x7f, 0x6b, 0x99, 0x94, 0x80, 0x2e, 0xfe, 0xf5, 0x43, 0x1f, - 0x03, 0x7d, 0x22, 0x09, 0xa0, 0x88, 0x07, 0x34, 0x6f, 0xb3, 0x9c, 0xad, 0xd8, 0x93, - 0xd6, 0x5f, 0x64, 0xc7, 0xfe, 0x92, 0xec, 0xbc, 0xdf, 0xe5, 0x55, 0x54, 0xca, 0xff, - 0xb0, 0xcf, 0x41, 0xeb, 0x5c, 0x55, 0x72, 0xba, 0x44, 0x39, 0x90, 0x00, 0xe9, 0xfa, - 0x9a, 0xaf, 0x6e, 0xb7, 0x6c, 0x2a, 0x8a, 0x5d, 0x7b, 0x6b, 0x52, 0xb9, 0xa9, 0xef, - 0x6e, 0xc3, 0xed, 0xa6, 0x65, 0xfe, 0x8a, 0xa8, 0x07, 0x48, 0xb8, 0x1f, 0x7d, 0x55, - 0x96, 0xf1, 0x94, 0x2f, 0xf7, 0x1d, 0x29, 0xc6, 0x78, 0xa3, 0xb6, 0xc6, 0x6b, 0xa7, - 0x0f, 0x45, 0xb1, 0xfc, 0xf2, 0x22, 0x38, 0x84, 0x50, 0x68, 0xf3, 0x60, 0xb0, 0x99, - 0xae, 0xe9, 0xf2, 0xf0, 0xef, 0x22, 0x33, 0x3f, 0xd6, 0x4f, 0xf1, 0x1e, 0x48, 0x15, - 0x43, 0xa5, 0x2b, 0xb3, 0x3f, 0x52, 0x3d, 0xe2, 0xec, 0x92, 0x3a, 0xe9, 0x86, 0x58, - 0x57, 0x71, 0x7b, 0x65, 0xd4, 0x4c, 0x3d, 0x9d, 0xb7, 0xb3, 0xec, 0xb2, 0xff, 0x02, - 0x25, 0x29, 0x7d, 0xeb, 0x83, 0xdd, 0x1b, 0x9a, 0x39, 0x4d, 0x69, 0x7c, 0x09, 0xd7, - 0xfe, 0xc6, 0x1e, 0xac, 0xee, 0x39, 0xa2, 0xf1, 0xce, 0xd9, 0xe6, 0xfd, 0xa5, 0xc0, - 0xf3, 0x27, 0x71, 0xc6, 0xce, 0x3f, 0x17, 0xbe, 0x0e, 0xef, 0x81, 0x10, 0x99, 0xc1, - 0x09, 0xe4, 0xfb, 0x6a, 0xec, 0x30, 0xdf, 0x04, 0x5b, 0x43, 0xda, 0x89, 0x30, 0x8b, - 0xc8, 0x37, 0x68, 0x8b, 0xb0, 0xf4, 0xa2, 0xc6, 0x04, 0xa1, 0x54, 0xa8, 0x47, 0xc5, - 0xd7, 0x87, 0x27, 0xf0, 0xe1, 0xab, 0x11, 0xe3, 0x40, 0xcf, 0xd4, 0xc7, 0xe8, 0xc6, - 0xba, 0xff, 0xfe, 0xfc, 0x74, 0xef, 0x55, 0x3d, 0x4b, 0x29, 0x26, 0x9f, 0x38, 0xb4, - 0xb7, 0xfe, 0x6e, 0x07, 0x3a, 0x70, 0xae, 0xf2, 0x0d, 0x6c, 0x23, 0x8b, 0x9f, 0xfd, - 0x24, 0x1f, 0xf6, 0x99, 0x99, 0x92, 0x30, 0xf0, 0xb3, 0x9c, 0x96, 0x3e, 0xfa, 0x00, - 0xef, 0x7f, 0x09, 0x2d, 0x76, 0x0c, 0x40, 0x9a, 0x2b, 0x6c, 0x26, 0xb4, 0x97, 0x82, - 0x9b, 0x81, 0xcb, 0xa4, 0xc8, 0x3b, 0x11, 0x44, 0xc6, 0x5a, 0x2d, 0x31, 0x78, 0xbb, - 0x28, 0xc1, 0xd8, 0xe3, 0x30, 0xd3, 0xf4, 0xaf, 0x90, 0x10, 0xad, 0x49, 0xa5, 0xdb, - 0x70, 0xd6, 0x6a, 0xf5, 0x70, 0x19, 0x21, 0x49, 0x80, 0x5f, 0xe1, 0xca, 0x61, 0xc6, - 0xd4, 0xec, 0xaf, 0xa7, 0x97, 0x51, 0x7f, 0x33, 0x06, 0xaf, 0x2a, 0x32, 0x27, 0x3b, - 0xf3, 0xd6, 0x98, 0xaa, 0x55, 0xa5, 0x72, 0xb2, 0xdf, 0x80, 0x36, 0xd9, 0x7c, 0xf5, - 0x8c, 0x12, 0x9f, 0x82, 0x85, 0xd0, 0xd7, 0xea, 0x04, 0xc1, 0x88, 0xa8, 0x39, 0x6e, - 0x73, 0x8b, 0xd4, 0x48, 0x46, 0x5e, 0x7b, 0x9a, 0x64, 0xb7, 0x96, 0x7b, 0xcb, 0x25, - 0xf8, 0xaa, 0x85, 0x9e, 0xa5, 0xca, 0x06, 0xc3, 0xdf, 0x39, 0x0f, 0xac, 0x8a, 0xc6, - 0x06, 0x05, 0x03, 0x1a, 0x02, 0x09, 0xbb, 0x80, 0x24, 0x0d, 0x05, 0x45, 0xf4, 0x11, - 0x77, 0xea, 0xb4, 0x40, 0x2e, 0x8a, 0x42, 0x3a, 0x40, 0xcc, 0xff, 0x58, 0x6b, 0x2e, - 0xdd, 0x6a, 0xcf, 0xb8, 0xf1, 0xd8, 0x0d, 0x8c, 0x60, 0x5f, 0x49, 0x05, 0x2e, 0x7a, - 0x30, 0x82, 0x6e, 0x1f, 0x03, 0x09, 0x9c, 0x71, 0x43, 0xad, 0x0b, 0x51, 0xfc, 0x63, - 0x6f, 0x1d, 0x87, 0x05, 0x83, 0xd6, 0xed, 0xce, 0xcd, 0xe9, 0x42, 0x38, 0x9e, 0x6c, - 0x01, 0x00, 0x66, 0x78, 0xda, 0xad, + 0x77, 0xc6, 0xef, 0xc8, 0xb5, 0x42, 0xa7, 0x07, 0xc0, 0xa5, 0xcf, 0x5c, 0xe3, 0xf3, + 0xb9, 0x6d, 0xe1, 0x91, 0x95, 0x7c, 0x9f, 0xa6, 0xe9, 0xbb, 0x4b, 0x8d, 0x89, 0x9e, + 0x1f, 0x19, 0xe0, 0x20, 0xba, 0x7b, 0xb3, 0xfe, 0xf1, 0x67, 0x81, 0xc8, 0x8c, 0xc5, + 0xd4, 0x4a, 0x5e, 0xf8, 0x17, 0x31, 0x47, 0xdc, 0x3d, 0x1b, 0x51, 0x6a, 0xf6, 0xdd, + 0x77, 0xdd, 0xb6, 0xee, 0x67, 0xaa, 0xf5, 0x42, 0xce, 0xe2, 0xbe, 0xd3, 0xe4, 0xa0, + 0x7e, 0xce, 0x42, 0x8f, 0x22, 0xa8, 0x01, 0xcf, 0x01, 0xba, 0xad, 0x18, 0x27, 0xfd, + 0x42, 0x57, 0x46, 0xc5, 0x45, 0x00, 0x1c, 0x35, 0x6d, 0x0a, 0xbe, 0xaa, 0xa5, 0xa4, + 0x22, 0xdf, 0xff, 0x0e, 0xe2, 0x18, 0xac, 0x37, 0xef, 0x83, 0x97, 0xc6, 0x2c, 0xa8, + 0x6f, 0xab, 0xeb, 0xb6, 0x88, 0xb3, 0x8f, 0xb4, 0xa6, 0x54, 0x29, 0x11, 0xbe, 0x1c, + 0x5e, 0x71, 0x77, 0x8b, 0x5e, 0xb5, 0x3a, 0xf1, 0xc4, 0xcb, 0x4d, 0xd9, 0x94, 0x72, + 0x4f, 0x61, 0x0f, 0x38, 0x72, 0x4a, 0x73, 0xdf, 0x09, 0x2b, 0xea, 0xe8, 0xb8, 0x7f, + 0x7f, 0x6a, 0x2b, 0xc0, 0x9d, 0xf2, 0xaa, 0x18, 0xc2, 0xf8, 0xee, 0xba, 0x63, 0xee, + 0x0d, 0x31, 0x35, 0x3b, 0x6f, 0x28, 0x3e, 0xf5, 0x9a, 0xc1, 0x53, 0x60, 0x73, 0xda, + 0x7a, 0x6d, 0x82, 0xbf, 0xdc, 0x09, 0x74, 0x02, 0x08, 0x0f, 0xa1, 0x03, 0xcb, 0x8b, + 0x3e, 0xfb, 0x94, 0x1e, 0xe5, 0x01, 0xf6, 0x41, 0x2c, 0xfb, 0xc2, 0x50, 0xaf, 0xad, + 0xbe, 0x54, 0x4a, 0xc5, 0x1f, 0xce, 0x41, 0x5a, 0x24, 0x93, 0xba, 0x83, 0x9e, 0x38, + 0x18, 0xb0, 0xfe, 0x30, 0x18, 0xbf, 0xa4, 0x37, 0xf0, 0x6e, 0x31, 0x86, 0x14, 0x8a, + 0xa4, 0x05, 0xba, 0xb8, 0x21, 0xa2, 0x6e, 0xa0, 0x7f, 0x93, 0xcf, 0xe7, 0x56, 0x8f, + 0xe3, 0xef, 0x08, 0xfa, 0x0b, 0x80, 0xfc, 0xec, 0x5b, 0xd5, 0x91, 0x5f, 0x68, 0x8c, + 0xf5, 0x99, 0x31, 0x5e, 0x79, 0xaa, 0xea, 0x34, 0xd5, 0x18, 0xd9, 0x55, 0xfe, 0xef, + 0x30, 0x3f, 0x69, 0xb2, 0x87, 0xc6, 0xd0, 0x51, 0x6d, 0xa2, 0x39, 0xfb, 0xbd, 0xdb, + 0xaf, 0x25, 0x56, 0xeb, 0xce, 0x77, 0xa3, 0xd5, 0x97, 0x23, 0x5c, 0x22, 0xd3, 0x8c, + 0x5b, 0x5e, 0xeb, 0x98, 0xc7, 0xc0, 0x8d, 0xa8, 0xd3, 0x76, 0xbb, 0xa1, 0xb5, 0x07, + 0x85, 0xbe, 0x82, 0xbf, 0xe0, 0x9a, 0xe7, 0x1c, 0xcc, 0xaf, 0x31, 0xa2, 0xf0, 0xcf, + 0xa0, 0x76, 0xd1, 0xe4, 0xd1, 0xb5, 0x2f, 0xee, 0x45, 0xc8, 0xed, 0x23, 0xdf, 0x33, + 0xa8, 0x1c, 0xb1, 0xa8, 0xac, 0xec, 0x9f, 0x53, 0x5d, 0xa4, 0x96, 0x70, 0xf9, 0x98, + 0x6d, 0x5c, 0x92, 0xc8, 0x2b, 0x0a, 0xd2, 0x20, 0xf8, 0x5f, 0x3b, 0x38, 0x72, 0xeb, + 0xe0, 0x53, 0xcd, 0xeb, 0x96, 0x1b, 0xd2, 0xd3, 0xab, 0x3b, 0xcd, 0x67, 0x6e, 0x6f, + 0xd7, 0xcb, 0xe9, 0x79, 0x5e, 0x1f, 0x2d, 0x82, 0x87, 0x00, 0x7c, 0x91, 0x0e, 0x7b, + 0x43, 0x01, 0x69, 0xe4, 0x51, 0xf0, 0xb2, 0xd7, 0x63, 0xe5, 0x43, 0x03, 0x3b, 0xc6, + 0xc7, 0x38, 0x9f, 0xa1, 0x61, 0x5b, 0xa1, 0x9d, 0x1f, 0x27, 0x48, 0xb2, 0x17, 0xc9, + 0x60, 0xfe, 0x05, 0x04, 0x07, 0xc8, 0xf4, 0x73, 0x35, 0x6b, 0xaa, 0x6e, 0x0c, 0x7d, + 0x77, 0xfa, 0xc6, 0xc7, 0xdb, 0x45, 0x12, 0xaf, 0x57, 0x96, 0xb3, 0xbc, 0xf1, 0x23, + 0xe0, 0x90, 0xb9, 0x80, 0xeb, 0xc2, 0xd6, 0x4b, 0x86, 0xdd, 0x24, 0xcb, 0x9a, 0x6d, + 0xab, 0x1d, 0xb4, 0x13, 0x04, 0x75, 0x38, 0x90, 0x2e, 0x2e, 0x49, 0x0e, 0x4f, 0xc8, + 0x78, 0xaa, 0x04, 0xdb, 0xef, 0x66, 0x99, 0x63, 0x9c, 0x3d, 0xab, 0x17, 0xc5, 0x14, + 0x70, 0x48, 0xac, 0x6d, 0x48, 0x49, 0x0d, 0xc4, 0x88, 0x5e, 0xd9, 0x86, 0x70, 0x63, + 0x35, 0xf4, 0x1b, 0xa4, 0x15, 0x59, 0x65, 0x9e, 0x1b, 0x53, 0xda, 0x76, 0x51, 0x4c, + 0xc4, 0x0a, 0xdb, 0x66, 0xc3, 0x5c, 0xe5, 0x6f, 0x3a, 0xbe, 0x39, 0xe1, 0xae, 0xe5, + 0x84, 0x9f, 0xff, 0xcc, 0x6e, 0x1f, 0x1b, 0xf8, 0x11, 0xce, 0xb6, 0x65, 0xa6, 0xfc, + 0xf8, 0x80, 0x6b, 0xbb, 0xba, 0x4a, 0x5b, 0x87, 0x38, 0xa1, 0x17, 0xdc, 0xaf, 0xfb, + 0x4f, 0xdf, 0x10, 0x08, 0x00, 0x6f, ], ock: [ - 0xf9, 0x59, 0x87, 0xcc, 0x0c, 0x73, 0x57, 0xc7, 0x20, 0x26, 0x27, 0xa5, 0xa5, 0x50, - 0x09, 0xef, 0xd7, 0x17, 0x55, 0x3e, 0x9d, 0x34, 0xc1, 0x5f, 0xad, 0xf5, 0xc9, 0x46, - 0xa9, 0xa0, 0x72, 0x17, + 0xb4, 0xf8, 0x8a, 0x29, 0x2d, 0x09, 0xd9, 0x35, 0xb4, 0x77, 0x5a, 0x29, 0x30, 0xeb, + 0x38, 0xce, 0xbd, 0x5a, 0xf6, 0xff, 0x3f, 0x39, 0xef, 0x5b, 0xb2, 0x4c, 0xd5, 0x72, + 0x81, 0xf0, 0x8c, 0xfb, ], op: [ 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, - 0x6b, 0x80, 0xbb, 0xb7, 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, - 0xbf, 0xb7, 0x8a, 0xec, 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, - 0x77, 0xc9, 0x46, 0xe9, 0xcd, 0x7a, 0x24, 0x23, + 0x6b, 0x80, 0xbb, 0xb7, 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, + 0x14, 0xb0, 0xdf, 0x85, 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, + 0xc4, 0x84, 0xa9, 0xf4, 0xc7, 0xda, 0x74, 0x36, ], c_out: [ - 0x28, 0x9d, 0x00, 0xd4, 0x62, 0x78, 0x0b, 0xdb, 0xb6, 0xcd, 0x6c, 0xec, 0x93, 0x6b, - 0xe6, 0x5e, 0x63, 0x0d, 0x4a, 0x3c, 0x2a, 0xf7, 0x6e, 0x10, 0x4b, 0x17, 0x4e, 0x3d, - 0x5b, 0x71, 0x66, 0x39, 0xb0, 0x68, 0xb3, 0x85, 0x00, 0xd8, 0x04, 0x00, 0xee, 0x64, - 0x2f, 0x8e, 0x08, 0xc8, 0xdb, 0x29, 0xff, 0xd5, 0xa9, 0xda, 0xde, 0x84, 0xa5, 0x49, - 0x5d, 0x57, 0x7b, 0x2f, 0x56, 0xd3, 0x2b, 0x07, 0x96, 0xca, 0x23, 0xf0, 0x0f, 0x0f, - 0x8e, 0xf9, 0x93, 0x07, 0x4f, 0x88, 0x0d, 0x6a, 0xeb, 0xcb, - ], + 0x94, 0xe3, 0x7f, 0xd6, 0x62, 0x82, 0xc0, 0x2e, 0x90, 0xe7, 0x69, 0x91, 0x4c, 0xaf, + 0x95, 0xa4, 0x95, 0xf4, 0x89, 0x7f, 0x55, 0xa5, 0xae, 0x95, 0xad, 0xe8, 0xbf, 0x67, + 0x61, 0xe3, 0x1b, 0xa5, 0xd1, 0xcf, 0xeb, 0x30, 0x6f, 0x4e, 0x22, 0x01, 0x42, 0x51, + 0xcb, 0xe3, 0xf8, 0x72, 0x4b, 0xe7, 0x69, 0x21, 0xe2, 0xad, 0xa4, 0x6e, 0x3b, 0x14, + 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, + 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -1560,34 +1567,34 @@ pub(crate) fn test_vectors() -> Vec { 0xe2, 0x3c, 0x39, 0x11, ], rho: [ - 0x35, 0x6f, 0xc7, 0x2e, 0x1b, 0xf1, 0xe3, 0xa2, 0xa5, 0x9a, 0xa9, 0xe4, 0x75, 0x15, - 0x5c, 0xf7, 0x43, 0xf8, 0xfd, 0xf0, 0xd1, 0x5b, 0x4c, 0xc4, 0x02, 0x60, 0xd0, 0xd0, - 0x9a, 0xda, 0x04, 0x08, + 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, + 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, + 0x3e, 0xe8, 0xed, 0x20, ], cmx: [ - 0xca, 0xa2, 0x8a, 0x69, 0x04, 0x54, 0x66, 0x37, 0xa7, 0xd4, 0xe5, 0xfb, 0xc2, 0x65, - 0x4c, 0xbf, 0x24, 0x4d, 0x18, 0x77, 0x9d, 0x35, 0x62, 0x25, 0x6c, 0x14, 0xd5, 0xb1, - 0x00, 0x5d, 0xc6, 0x0f, + 0xbe, 0x43, 0xee, 0x84, 0x70, 0x70, 0x75, 0xac, 0x48, 0x08, 0xd0, 0x97, 0x54, 0x07, + 0xc0, 0x27, 0x36, 0xd7, 0x66, 0x64, 0xf4, 0xe7, 0xae, 0xce, 0x01, 0xd9, 0xcc, 0x68, + 0x32, 0x4a, 0xe9, 0x04, ], esk: [ - 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, 0x42, 0x0e, 0xff, 0xd7, - 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, 0x91, 0x90, 0x01, 0xf8, - 0x66, 0xa8, 0xe9, 0x2c, + 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, 0x14, 0x49, 0x72, 0x62, + 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, 0xe2, 0x63, 0xf3, 0xe3, + 0x99, 0x07, 0xea, 0x0c, ], ephemeral_key: [ - 0x00, 0x62, 0x7e, 0x29, 0xc1, 0x83, 0x3e, 0x4e, 0x8f, 0xad, 0xe0, 0x82, 0x52, 0xf3, - 0x83, 0x67, 0x78, 0xb9, 0x39, 0x4c, 0x1f, 0xfe, 0xab, 0x70, 0xbf, 0x35, 0x93, 0xd5, - 0x9a, 0x81, 0xa0, 0xa5, + 0xfa, 0x19, 0xa1, 0x52, 0x7b, 0x76, 0x04, 0x8f, 0xf3, 0x7f, 0xa4, 0xf8, 0x27, 0x89, + 0xfe, 0x80, 0xb0, 0xcd, 0xd3, 0x5d, 0x5d, 0xa9, 0xc2, 0xec, 0x3f, 0xe3, 0x04, 0x38, + 0x05, 0xc0, 0x61, 0x23, ], shared_secret: [ - 0xa9, 0x93, 0x34, 0x1f, 0x99, 0xeb, 0xa8, 0x2d, 0xb6, 0xec, 0x5e, 0x71, 0x3e, 0xe2, - 0x9c, 0x01, 0xf4, 0xce, 0x2a, 0x8b, 0xb6, 0xb5, 0xeb, 0xb6, 0x0b, 0xa6, 0xeb, 0xa9, - 0x6b, 0xa4, 0x17, 0x9b, + 0x2d, 0xb5, 0xb8, 0x92, 0xb6, 0x1b, 0x9c, 0x55, 0x3b, 0x6c, 0x9b, 0x7a, 0xcc, 0x7d, + 0x71, 0x05, 0xc1, 0xdd, 0x4c, 0x28, 0xc6, 0x7f, 0x97, 0x8b, 0x6d, 0x79, 0xc7, 0x1b, + 0x98, 0xa0, 0xd0, 0x00, ], k_enc: [ - 0x35, 0x81, 0x19, 0x19, 0x3c, 0x9d, 0x2a, 0xb6, 0xd4, 0x95, 0xe0, 0x19, 0xf9, 0x7a, - 0x1c, 0x41, 0x30, 0xae, 0xe6, 0x3d, 0xae, 0xc6, 0xbb, 0xa2, 0xf2, 0x74, 0x40, 0x0f, - 0xd3, 0x4f, 0xad, 0x28, + 0x16, 0xe3, 0xf9, 0x85, 0xc0, 0x7f, 0xef, 0xe5, 0x30, 0xd9, 0xe6, 0x94, 0x5e, 0xde, + 0xc1, 0x90, 0x3b, 0xb1, 0xca, 0x8d, 0xa5, 0xa2, 0x5b, 0xe9, 0x59, 0x78, 0x63, 0x7a, + 0x40, 0x8c, 0x2e, 0xfe, ], p_enc: [ 0x02, 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, 0x46, 0x49, @@ -1633,69 +1640,70 @@ pub(crate) fn test_vectors() -> Vec { 0x84, 0x37, 0x3f, 0x4f, ], c_enc: [ - 0x31, 0xac, 0xda, 0xa6, 0xc1, 0x76, 0xbb, 0x7a, 0x2c, 0x7d, 0x66, 0x09, 0xdc, 0x2c, - 0x5e, 0x7b, 0x2e, 0xe7, 0x1d, 0xa9, 0x3c, 0x73, 0x87, 0x52, 0x74, 0xfa, 0x6c, 0x2a, - 0xd6, 0x26, 0x13, 0xc7, 0x18, 0x9b, 0x35, 0x33, 0xec, 0xf0, 0x34, 0xd8, 0x76, 0xc7, - 0x26, 0xf1, 0xed, 0x99, 0x43, 0xd4, 0x45, 0x07, 0x87, 0x52, 0x75, 0xa8, 0xe3, 0x71, - 0x0a, 0x11, 0x8d, 0x91, 0x64, 0x72, 0x91, 0x28, 0x6c, 0xf8, 0x80, 0xa7, 0x82, 0xab, - 0xea, 0xa8, 0xa6, 0xc3, 0x2f, 0xdf, 0x6f, 0x30, 0x4b, 0x0e, 0xe5, 0xbc, 0xb1, 0x4b, - 0x82, 0x79, 0x2a, 0xa3, 0xaf, 0xd7, 0x24, 0x3f, 0x57, 0xb7, 0xdc, 0xa7, 0x93, 0x52, - 0x19, 0xdf, 0x98, 0x2c, 0xe1, 0x28, 0xae, 0xa6, 0xf6, 0xbd, 0x18, 0xe1, 0x30, 0x7e, - 0xba, 0x0e, 0x3d, 0xb0, 0x06, 0x14, 0xc2, 0x65, 0xc6, 0xf2, 0x8b, 0xfe, 0x58, 0xc1, - 0x1d, 0x4a, 0xc9, 0x6d, 0x49, 0x02, 0x96, 0x7b, 0x54, 0xbc, 0x5d, 0xd1, 0x5c, 0x14, - 0x3f, 0xf4, 0x2b, 0xbb, 0x62, 0xb9, 0x34, 0xb0, 0x9e, 0x79, 0xb6, 0x1e, 0xaf, 0xe7, - 0x9a, 0xbc, 0x86, 0x94, 0x47, 0x5b, 0x6c, 0x8e, 0x19, 0x94, 0xba, 0x05, 0x5e, 0xa3, - 0xc1, 0x82, 0x93, 0xb0, 0x3c, 0x42, 0x49, 0x50, 0x1d, 0xfd, 0xc0, 0x14, 0x60, 0xcf, - 0x78, 0xcd, 0x97, 0x51, 0x30, 0xae, 0x34, 0x05, 0xba, 0x7d, 0xdc, 0x71, 0x30, 0xcb, - 0xdb, 0xb9, 0x8c, 0x7a, 0xaf, 0x6b, 0x1d, 0x0b, 0x44, 0xa5, 0x16, 0x79, 0xaa, 0x63, - 0x0a, 0x43, 0xae, 0x23, 0xb3, 0xd2, 0x2f, 0x73, 0x4c, 0xe1, 0xdb, 0xed, 0xea, 0x17, - 0x5a, 0x00, 0x62, 0xb0, 0x6e, 0x23, 0xf4, 0xd0, 0x6d, 0x2a, 0xd0, 0x45, 0xae, 0x98, - 0x2d, 0xb4, 0x34, 0x8f, 0x20, 0xc8, 0x9b, 0xf9, 0x67, 0x0e, 0x2f, 0xda, 0x47, 0x2e, - 0x55, 0xce, 0x4c, 0x35, 0x82, 0xb7, 0x64, 0x43, 0xe0, 0xab, 0xbb, 0x77, 0x8a, 0xec, - 0xa0, 0xf3, 0x9c, 0x55, 0xb6, 0xab, 0xbe, 0xd8, 0x1f, 0xde, 0x89, 0xad, 0x2c, 0x56, - 0x7d, 0xfe, 0x27, 0x7b, 0xb2, 0x69, 0xac, 0x6a, 0xe0, 0xe1, 0x88, 0x39, 0x8d, 0xea, - 0x24, 0xad, 0xcc, 0xe1, 0x82, 0xe7, 0xfd, 0xdc, 0x80, 0xeb, 0xd7, 0x69, 0xd0, 0xf0, - 0x76, 0xf9, 0xaf, 0x2d, 0xd9, 0x83, 0x07, 0xa5, 0x27, 0xc6, 0x99, 0x42, 0xdf, 0xa3, - 0xe7, 0xf4, 0x86, 0x76, 0x10, 0x1a, 0x47, 0xeb, 0x07, 0x80, 0xb6, 0x90, 0xb1, 0xaf, - 0x10, 0xfc, 0xfb, 0x5e, 0xe2, 0xbd, 0x40, 0xd2, 0x7d, 0x10, 0x9b, 0xa1, 0x5a, 0xb0, - 0xb1, 0xe9, 0x55, 0x4f, 0xdd, 0xfa, 0x81, 0x6b, 0x99, 0xcd, 0x8f, 0xdd, 0xe6, 0x81, - 0xae, 0x6b, 0x6c, 0xbb, 0xfb, 0xf0, 0x2c, 0x36, 0x32, 0x68, 0xd0, 0xf3, 0xc6, 0xa7, - 0x26, 0x1b, 0x6d, 0x00, 0x87, 0xbc, 0xad, 0xb6, 0xfb, 0x9b, 0xf3, 0x93, 0x04, 0xfc, - 0x08, 0x41, 0x5d, 0x83, 0x6f, 0xe4, 0x09, 0xa4, 0x3f, 0xaf, 0x9e, 0x28, 0xfb, 0x48, - 0x3f, 0x4a, 0x47, 0xaa, 0xd7, 0xe1, 0xf7, 0x97, 0x30, 0xb3, 0x21, 0x53, 0x60, 0x80, - 0xdb, 0x35, 0x12, 0x48, 0xb2, 0x66, 0x9b, 0x6e, 0x74, 0x48, 0x90, 0x87, 0xae, 0x72, - 0xba, 0x15, 0xd2, 0xae, 0xdd, 0x0c, 0x1e, 0x7e, 0xb1, 0x5a, 0x2f, 0x5a, 0x77, 0x31, - 0xeb, 0x45, 0xa6, 0x17, 0x8a, 0x44, 0x87, 0x09, 0x31, 0xec, 0x8e, 0x34, 0x8c, 0x19, - 0x2b, 0xc8, 0x87, 0xc8, 0x63, 0x60, 0x56, 0x67, 0x6f, 0x58, 0xd0, 0xc6, 0x34, 0xfc, - 0x99, 0xea, 0x7b, 0x07, 0xfa, 0x1b, 0x62, 0x99, 0xae, 0x5d, 0xbf, 0xe0, 0x84, 0x45, - 0xad, 0x99, 0x9f, 0x45, 0xdf, 0x00, 0xf1, 0xa4, 0x7a, 0xa5, 0xef, 0x6f, 0x88, 0xcd, - 0xba, 0x80, 0xc8, 0x8f, 0x94, 0x01, 0xe6, 0xe9, 0x09, 0xca, 0x2c, 0x5d, 0xe2, 0xcf, - 0x8f, 0x6a, 0x98, 0x44, 0xca, 0x32, 0xfe, 0x91, 0xf7, 0x13, 0xfe, 0x10, 0xa0, 0x69, - 0x8a, 0x1b, 0x3b, 0xfd, 0xf4, 0x47, 0x43, 0x75, 0xb4, 0x79, 0x1d, 0xc8, 0x50, 0x50, - 0xc9, 0x28, 0x90, 0x0e, 0x73, 0x1f, 0x7c, 0x4a, 0x12, 0x9d, 0x8e, 0x21, 0xfc, 0xf4, - 0x17, 0x62, 0x7c, 0x47, 0xdd, 0xc9, 0xf5, 0x88, 0x40, 0x38, 0x41, 0x31, 0x7a, 0x9a, - 0xc2, 0x6e, 0xef, 0x6c, 0xda, 0x23, + 0x2d, 0x40, 0x4a, 0x68, 0x81, 0xa6, 0xee, 0x76, 0x0c, 0xb5, 0x3b, 0x9c, 0xc2, 0x71, + 0x5c, 0xa7, 0x6a, 0x3a, 0x2f, 0xc9, 0x69, 0x3b, 0x1a, 0xbb, 0xcd, 0xc7, 0x5c, 0xb6, + 0xd6, 0xc3, 0x6e, 0xcf, 0x84, 0xd6, 0x93, 0x67, 0x2c, 0x53, 0xce, 0xd8, 0x79, 0x8c, + 0xc8, 0xf1, 0xe5, 0x3b, 0x8a, 0x9d, 0xe7, 0xbb, 0xb5, 0xe8, 0xc5, 0xa4, 0x6c, 0x3a, + 0x74, 0x12, 0xdf, 0x11, 0xc5, 0xda, 0x16, 0xb4, 0xdd, 0x22, 0x90, 0x1a, 0x59, 0x2b, + 0x0e, 0x93, 0x29, 0x77, 0xba, 0x06, 0x67, 0x3d, 0x6f, 0xd0, 0x38, 0xac, 0xba, 0xa9, + 0xbf, 0x79, 0xc1, 0x5b, 0xa6, 0x2b, 0x6e, 0x30, 0x74, 0xef, 0x95, 0x3b, 0x81, 0x4c, + 0xf1, 0xbd, 0xf0, 0x15, 0x77, 0xed, 0x3e, 0x3f, 0xae, 0xf4, 0x71, 0x55, 0xc9, 0x1c, + 0x68, 0xee, 0x32, 0x88, 0x1b, 0x73, 0x74, 0x94, 0xb3, 0xb4, 0x76, 0x08, 0x3b, 0x3b, + 0xd1, 0x77, 0x93, 0xc4, 0x98, 0x93, 0x1e, 0xaa, 0x92, 0xb1, 0x7c, 0x7d, 0x10, 0x47, + 0x58, 0xfc, 0x8b, 0x34, 0x93, 0xd2, 0x47, 0x41, 0x7f, 0x5e, 0xc1, 0x97, 0x9a, 0x35, + 0x28, 0x93, 0xe9, 0x95, 0x63, 0xb6, 0xc3, 0xab, 0x95, 0xcc, 0x5a, 0xfa, 0x37, 0x32, + 0xef, 0xae, 0xce, 0x9e, 0x74, 0x32, 0xc8, 0x04, 0x15, 0xe2, 0x5f, 0x55, 0x56, 0x53, + 0xc7, 0xda, 0x5d, 0xb0, 0xcc, 0x61, 0x08, 0x74, 0x21, 0x95, 0x9b, 0xb1, 0xdf, 0x80, + 0x03, 0xb7, 0x3d, 0xa0, 0xbe, 0xf0, 0x60, 0xf3, 0xa8, 0x4c, 0x8b, 0xc2, 0x4c, 0xc7, + 0x6d, 0x0d, 0x9e, 0x9c, 0x33, 0x76, 0x5c, 0x20, 0xf0, 0x7d, 0x80, 0xe2, 0x0f, 0xdf, + 0x27, 0x81, 0x5d, 0xbd, 0x9d, 0x71, 0x7c, 0x09, 0x66, 0xf8, 0x0b, 0x94, 0xb9, 0x59, + 0x15, 0x08, 0x1e, 0xa4, 0x55, 0x37, 0xa5, 0xa0, 0x74, 0xb9, 0xc9, 0x4b, 0x43, 0xdd, + 0xf4, 0xa9, 0xcb, 0xad, 0xe9, 0x04, 0x51, 0x0e, 0xaa, 0x96, 0x9e, 0x66, 0x6c, 0x94, + 0x34, 0xb9, 0xf6, 0x3e, 0xae, 0x62, 0xad, 0x58, 0x27, 0x99, 0x62, 0xe9, 0x41, 0x33, + 0x05, 0x5c, 0xbc, 0xc4, 0xb1, 0x55, 0xc0, 0x0f, 0x1b, 0x83, 0xff, 0x41, 0x28, 0xa8, + 0xab, 0xb4, 0xce, 0x68, 0xe9, 0xf1, 0xe3, 0x08, 0xe6, 0xf9, 0x7e, 0x51, 0x3a, 0xf5, + 0x95, 0x47, 0x1a, 0x16, 0x77, 0xef, 0x78, 0xe9, 0x77, 0x0f, 0x43, 0xad, 0xde, 0x1a, + 0x64, 0x58, 0x6d, 0xe6, 0xa5, 0x87, 0xc3, 0xd6, 0x93, 0xfe, 0xa8, 0xfc, 0xc6, 0xac, + 0xc8, 0x94, 0x96, 0x1e, 0x2f, 0x47, 0xb2, 0x02, 0xe8, 0x6a, 0x57, 0x38, 0x79, 0xb5, + 0xbf, 0xd7, 0x29, 0xda, 0x2f, 0xbe, 0xfc, 0x64, 0x5c, 0xfa, 0xb1, 0x88, 0x0d, 0x51, + 0x76, 0x40, 0xdf, 0x5f, 0x53, 0xe5, 0x7c, 0x72, 0xd6, 0x5a, 0x63, 0x3a, 0xa5, 0x36, + 0xb2, 0x98, 0x34, 0xbf, 0x28, 0x16, 0xb1, 0xf7, 0x16, 0xbf, 0x43, 0x6d, 0x6b, 0x2b, + 0x6e, 0x47, 0x73, 0x28, 0xc9, 0x58, 0xa6, 0xb8, 0xcf, 0x73, 0xb9, 0x5d, 0x22, 0xf6, + 0x99, 0x3b, 0x3f, 0xc5, 0x25, 0xdb, 0x62, 0x7f, 0x6f, 0x38, 0xd0, 0x77, 0x9a, 0x1d, + 0x39, 0xaf, 0x05, 0xed, 0x74, 0xfd, 0xfe, 0xff, 0x98, 0x7a, 0x95, 0x88, 0xd8, 0x0b, + 0x7e, 0x79, 0x69, 0x4a, 0xe4, 0x55, 0x29, 0x29, 0x88, 0x1c, 0x5b, 0xfe, 0x20, 0x49, + 0x2f, 0xd6, 0xf3, 0x37, 0xca, 0x88, 0xdf, 0xb5, 0x01, 0xe5, 0x45, 0xd2, 0x36, 0x73, + 0xac, 0xac, 0xbc, 0x3d, 0x33, 0x14, 0xa8, 0xbb, 0xf5, 0xec, 0x70, 0xb7, 0x05, 0xcc, + 0x9d, 0x26, 0x57, 0xbd, 0xd5, 0xa7, 0x09, 0x15, 0xbe, 0xf6, 0xd0, 0xf0, 0x39, 0xd3, + 0xeb, 0xa6, 0xbb, 0x71, 0x5b, 0xe5, 0x1e, 0xbf, 0x6e, 0xf6, 0x59, 0xea, 0x32, 0xff, + 0x80, 0xc8, 0x2c, 0x04, 0x21, 0x67, 0x5f, 0xe3, 0x71, 0xef, 0x49, 0xf1, 0xb9, 0xe3, + 0x8f, 0x43, 0x7b, 0x4a, 0x76, 0x55, 0xdc, 0x29, 0x16, 0xaa, 0x30, 0x86, 0xde, 0x6c, + 0x62, 0xa8, 0x2b, 0x36, 0x1c, 0x05, 0x3f, 0xc6, 0x34, 0x54, 0xcc, 0xd0, 0x2c, 0x22, + 0xd4, 0x1f, 0xf5, 0xbb, 0x83, 0x62, 0xde, 0xaa, 0x70, 0x82, 0x5a, 0xd2, 0xf9, 0x93, + 0x63, 0x9f, 0xc4, 0x46, 0x06, 0x9d, 0x78, 0xa6, 0x1d, 0x33, 0x8d, 0xf5, 0x8f, 0x77, + 0x63, 0xe3, 0x55, 0xe6, 0xa9, 0xff, ], ock: [ - 0x9c, 0x10, 0x3d, 0xd5, 0xd6, 0x38, 0x6c, 0xdd, 0x67, 0x69, 0x51, 0xe6, 0x56, 0x4b, - 0x16, 0x6b, 0xc5, 0xc5, 0x72, 0x32, 0xcf, 0xc3, 0x1e, 0x0e, 0x69, 0xce, 0x84, 0xda, - 0xe8, 0x32, 0x76, 0xbe, + 0x8b, 0x0d, 0x29, 0x8e, 0xe8, 0xb4, 0x25, 0x34, 0xa4, 0x2f, 0xb9, 0x63, 0x5b, 0xa7, + 0x58, 0xea, 0x9f, 0x91, 0x8b, 0x83, 0x16, 0xc0, 0xe8, 0x94, 0xa9, 0x08, 0x48, 0x89, + 0x01, 0xd9, 0xfb, 0xa3, ], op: [ 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, - 0x17, 0x5b, 0xa9, 0x8b, 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, - 0x42, 0x0e, 0xff, 0xd7, 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, - 0x91, 0x90, 0x01, 0xf8, 0x66, 0xa8, 0xe9, 0x2c, + 0x17, 0x5b, 0xa9, 0x8b, 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, + 0x14, 0x49, 0x72, 0x62, 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, + 0xe2, 0x63, 0xf3, 0xe3, 0x99, 0x07, 0xea, 0x0c, ], c_out: [ - 0xdf, 0x6b, 0xb6, 0x2e, 0x3b, 0x64, 0xf7, 0xe9, 0x37, 0xc1, 0xde, 0x38, 0xaa, 0xc5, - 0xe6, 0xb1, 0x61, 0x35, 0xba, 0x2f, 0x9d, 0xbe, 0xed, 0xb0, 0x7a, 0x45, 0xb6, 0xf0, - 0x9d, 0xf3, 0xeb, 0xec, 0xac, 0x04, 0x6c, 0x61, 0x92, 0xfb, 0xe8, 0x95, 0xd2, 0x31, - 0x02, 0x77, 0xb3, 0xe0, 0x3a, 0x90, 0xfd, 0xc8, 0x53, 0x48, 0x4a, 0x01, 0x5c, 0x88, - 0xd6, 0x63, 0x2e, 0x97, 0xba, 0x98, 0xad, 0xca, 0x9e, 0x49, 0xf5, 0x38, 0xc3, 0xa7, - 0xcb, 0x6d, 0x77, 0x23, 0xbd, 0xcc, 0x9c, 0x03, 0xae, 0x88, - ], + 0xf3, 0xbf, 0x90, 0x76, 0xf3, 0xdb, 0x66, 0x32, 0x6d, 0xa6, 0x0c, 0xc7, 0x94, 0x3c, + 0x85, 0x4d, 0x8d, 0xe9, 0x9f, 0x57, 0x53, 0xf7, 0x0c, 0x32, 0xed, 0x01, 0xfb, 0x2e, + 0x84, 0x9c, 0x9d, 0xc7, 0x3f, 0x80, 0xb5, 0xcb, 0xaa, 0xb4, 0x99, 0x2d, 0xd7, 0xe7, + 0x38, 0xb9, 0x61, 0xfd, 0x75, 0x3f, 0x7c, 0x5b, 0x29, 0x24, 0xd1, 0xd9, 0x63, 0x06, + 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, + 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -1769,34 +1777,34 @@ pub(crate) fn test_vectors() -> Vec { 0x87, 0xe5, 0x05, 0xad, ], rho: [ - 0x32, 0x91, 0x87, 0x35, 0x66, 0x3f, 0x34, 0xad, 0xa0, 0x22, 0x8a, 0xea, 0x4a, 0xcc, - 0x19, 0x2a, 0x12, 0x3f, 0xcf, 0xa0, 0x60, 0x46, 0x89, 0xf9, 0x1a, 0xcb, 0xe9, 0x38, - 0x31, 0xe4, 0x8c, 0x0c, + 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, + 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, + 0x45, 0x89, 0x35, 0x14, ], cmx: [ - 0xde, 0x7b, 0xf1, 0x55, 0x08, 0x29, 0x51, 0x96, 0x0a, 0x10, 0xbb, 0x8b, 0x75, 0x41, - 0x02, 0x43, 0x0f, 0x89, 0xf5, 0x32, 0x67, 0x24, 0x04, 0x36, 0x81, 0xf5, 0x06, 0xf7, - 0x48, 0xe2, 0x6f, 0x07, + 0x6d, 0x29, 0x97, 0xd1, 0xce, 0x0a, 0x94, 0x9a, 0x63, 0x70, 0x0f, 0x46, 0x1b, 0x57, + 0x12, 0xae, 0xeb, 0x43, 0xd4, 0x55, 0x04, 0xe3, 0x5b, 0xda, 0x16, 0x52, 0x97, 0x77, + 0xc7, 0x4d, 0x19, 0x1b, ], esk: [ - 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, 0x59, 0xa1, 0x33, 0xf3, - 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, 0xdd, 0x63, 0xe0, 0x62, - 0x83, 0x05, 0x47, 0x08, + 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, 0x6b, 0xa0, 0x02, 0x0c, + 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, 0x57, 0x32, 0x63, 0xf4, + 0x99, 0xbd, 0x4c, 0x13, ], ephemeral_key: [ - 0x18, 0x20, 0x84, 0x5b, 0x2d, 0x90, 0xe5, 0x45, 0x76, 0x0f, 0xca, 0x4d, 0xab, 0x30, - 0xa6, 0x78, 0x3e, 0x03, 0x1c, 0x0e, 0x54, 0x28, 0xcc, 0x22, 0x6f, 0x3f, 0x40, 0x1d, - 0xec, 0x20, 0x0b, 0x11, + 0xe4, 0x76, 0x95, 0x86, 0x30, 0x4a, 0x6a, 0x9b, 0x3a, 0x2a, 0xef, 0x3a, 0xf5, 0x8b, + 0x97, 0xda, 0xc2, 0xcc, 0x4a, 0xeb, 0x38, 0x9f, 0x68, 0xc1, 0x28, 0x87, 0x73, 0x1e, + 0x0e, 0x12, 0xbc, 0x1e, ], shared_secret: [ - 0x79, 0x38, 0x77, 0xa1, 0xae, 0xda, 0xe9, 0xac, 0x6d, 0xa3, 0xd7, 0xe8, 0x02, 0xb5, - 0xbc, 0x77, 0x3c, 0x0d, 0x93, 0x1c, 0x79, 0x6d, 0x17, 0x0c, 0x59, 0x7f, 0x22, 0xba, - 0x6f, 0xcc, 0xa2, 0x06, + 0xf6, 0xba, 0x4b, 0x1f, 0xbe, 0x01, 0xfa, 0x2f, 0x1d, 0xd4, 0x09, 0x3c, 0x5c, 0xc4, + 0x85, 0xa9, 0xbf, 0xd9, 0xef, 0x0f, 0x57, 0x89, 0x49, 0xd6, 0xe1, 0x00, 0xb0, 0x05, + 0x5c, 0xb8, 0xf3, 0x31, ], k_enc: [ - 0x28, 0x20, 0xb9, 0x38, 0xd6, 0xfc, 0xea, 0x99, 0xa7, 0x23, 0x37, 0x50, 0xa0, 0xf0, - 0x9a, 0x32, 0x10, 0xad, 0x91, 0x73, 0x46, 0x16, 0x6a, 0xea, 0xdc, 0x89, 0xbb, 0x50, - 0xf4, 0x54, 0x50, 0xa3, + 0xd3, 0xc2, 0x20, 0x51, 0x00, 0x3e, 0x88, 0x2a, 0x5d, 0xdd, 0xfb, 0x48, 0x23, 0xd6, + 0x77, 0x26, 0x96, 0xa7, 0xe9, 0x9f, 0x26, 0xb1, 0xa6, 0xac, 0xd2, 0x4b, 0xee, 0xd5, + 0xf2, 0x2f, 0x9f, 0xf8, ], p_enc: [ 0x02, 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, 0x22, 0x92, @@ -1842,69 +1850,70 @@ pub(crate) fn test_vectors() -> Vec { 0x3e, 0xcc, 0xc6, 0x23, ], c_enc: [ - 0xd9, 0x6a, 0xe8, 0x2f, 0xba, 0xff, 0xb9, 0xe4, 0xbd, 0x36, 0x47, 0x57, 0x96, 0x33, - 0xbc, 0x8a, 0x89, 0x66, 0xae, 0x4e, 0x18, 0x85, 0x99, 0xdc, 0x3c, 0xf0, 0x30, 0x41, - 0xd2, 0x64, 0x4f, 0x60, 0x3c, 0xe5, 0x56, 0x2e, 0x7f, 0xa1, 0xd3, 0x83, 0x12, 0x79, - 0xb6, 0x32, 0x60, 0x4d, 0x06, 0x5e, 0xd2, 0x46, 0xad, 0x2d, 0x4f, 0x73, 0xf3, 0xa4, - 0x1b, 0x2a, 0x27, 0x99, 0xe5, 0xba, 0xf8, 0x6e, 0x7d, 0x9f, 0xcc, 0x64, 0xd5, 0x6b, - 0xde, 0x56, 0xcb, 0xb0, 0x01, 0xeb, 0x7c, 0x7c, 0x0c, 0xf1, 0xe2, 0xae, 0xc3, 0xce, - 0xb1, 0x49, 0x2d, 0xdf, 0x4e, 0x35, 0x20, 0x76, 0x1f, 0x70, 0xf6, 0xa9, 0x5c, 0x9e, - 0xde, 0xed, 0x51, 0x43, 0x6d, 0xca, 0xcf, 0x71, 0x1e, 0xb5, 0x53, 0x24, 0xd3, 0xf0, - 0x1d, 0xcc, 0xa0, 0x1b, 0xca, 0x15, 0xba, 0xf2, 0x8f, 0xed, 0x81, 0x4c, 0xc3, 0x3a, - 0x43, 0x6b, 0xbc, 0x08, 0x60, 0x56, 0x78, 0x55, 0xa4, 0x9f, 0x5e, 0xfd, 0x49, 0xea, - 0x78, 0x30, 0xc2, 0xf6, 0x00, 0x61, 0xd8, 0x13, 0xa8, 0x49, 0xb4, 0x40, 0xb1, 0x2e, - 0x8f, 0x31, 0xe2, 0xdc, 0x0c, 0x39, 0x4c, 0xeb, 0x92, 0x4f, 0x0d, 0xc6, 0xd5, 0x7b, - 0xcc, 0x39, 0x1d, 0x4a, 0x5f, 0x56, 0x9f, 0x34, 0x74, 0x6b, 0x9d, 0x92, 0x08, 0x82, - 0x25, 0xb1, 0xaa, 0x3e, 0x90, 0x6f, 0x6d, 0xe4, 0xa7, 0x92, 0x2a, 0xc1, 0x16, 0xac, - 0xb2, 0x78, 0xe8, 0xef, 0xbb, 0xf6, 0xf1, 0xe3, 0xe0, 0x8d, 0x66, 0xb3, 0x4d, 0x6e, - 0xde, 0x34, 0xae, 0x78, 0x40, 0xa8, 0x80, 0x2b, 0x7c, 0x10, 0x0f, 0xa7, 0x98, 0x46, - 0x4d, 0xb5, 0x29, 0x45, 0xdb, 0xbe, 0x35, 0xe7, 0x7a, 0x77, 0x21, 0xb2, 0xe0, 0xf8, - 0xb9, 0xa1, 0x0f, 0x6b, 0xf9, 0xa2, 0x80, 0x8f, 0xa5, 0x85, 0xff, 0x21, 0xb0, 0xa3, - 0xaf, 0xfd, 0x5f, 0x3c, 0xb2, 0x30, 0x63, 0x4e, 0x2e, 0x43, 0xff, 0xde, 0x6d, 0x09, - 0x0a, 0xfc, 0xc6, 0x70, 0x4d, 0x7b, 0x3f, 0xc6, 0x15, 0x44, 0x85, 0x3b, 0xcd, 0xa7, - 0xa1, 0x06, 0xd8, 0x5b, 0xd8, 0xd8, 0x6c, 0x6f, 0x8c, 0xe0, 0x34, 0x01, 0x6e, 0xd9, - 0xa3, 0x69, 0x46, 0xf8, 0x52, 0x8b, 0x6f, 0x1e, 0x1a, 0x19, 0x82, 0xd6, 0x8d, 0x38, - 0x86, 0xe5, 0xea, 0xe6, 0xc1, 0xe3, 0x88, 0xf3, 0xde, 0xad, 0x0d, 0x35, 0x3b, 0x6c, - 0x0c, 0xbf, 0x57, 0xc2, 0xe4, 0x7d, 0x30, 0x72, 0x3e, 0xac, 0x95, 0x7b, 0x4a, 0xec, - 0x82, 0xc8, 0xa1, 0x00, 0x9e, 0x3d, 0x71, 0x96, 0x92, 0xb2, 0xfc, 0xbd, 0xda, 0xae, - 0x62, 0x5a, 0x89, 0x6a, 0x47, 0x29, 0x85, 0xb7, 0x9e, 0xb6, 0x2b, 0x1f, 0xe3, 0x3d, - 0x6e, 0x27, 0xbc, 0x1f, 0x10, 0xe4, 0xfe, 0x5c, 0x06, 0xb2, 0x4c, 0x59, 0x7f, 0x72, - 0x3c, 0x67, 0x13, 0x36, 0x13, 0xae, 0x8e, 0x15, 0x4d, 0x81, 0x69, 0x78, 0xb8, 0xfc, - 0xa6, 0x50, 0xc0, 0x1d, 0x77, 0x1a, 0x62, 0x69, 0x2a, 0x84, 0x82, 0x94, 0x2e, 0x28, - 0xfe, 0xf0, 0x45, 0x19, 0x9e, 0xd1, 0xa6, 0x64, 0x99, 0xeb, 0xa1, 0xee, 0xc1, 0x9a, - 0xc8, 0x4a, 0x12, 0xe4, 0x10, 0x29, 0xd2, 0x2f, 0x21, 0x87, 0x6e, 0xd7, 0x4a, 0x76, - 0xef, 0x39, 0xa0, 0x57, 0xce, 0x0a, 0x15, 0x8e, 0x68, 0x51, 0xec, 0x35, 0x6d, 0x97, - 0x7b, 0x1a, 0xa6, 0x8d, 0xcf, 0x70, 0x88, 0xa9, 0xf0, 0xf9, 0xe4, 0x75, 0xa2, 0xbb, - 0xc1, 0xc4, 0x49, 0x5b, 0x54, 0x6f, 0xff, 0xed, 0xaa, 0x66, 0xc4, 0xf9, 0x51, 0x74, - 0xc6, 0x2f, 0x56, 0x5a, 0x3c, 0xc0, 0xac, 0xaf, 0x85, 0x4a, 0xde, 0xd4, 0xb4, 0x25, - 0xa0, 0xc7, 0xdb, 0xcd, 0x37, 0x42, 0xa7, 0xe0, 0x59, 0x2e, 0x83, 0x73, 0x41, 0xf8, - 0x95, 0x32, 0x90, 0x99, 0xe1, 0x70, 0xb6, 0xff, 0xb1, 0x05, 0xfd, 0xbc, 0x77, 0x29, - 0x8e, 0x8c, 0x0f, 0x5e, 0xeb, 0x9e, 0x99, 0xc6, 0x58, 0x4b, 0xcf, 0xf1, 0x20, 0x20, - 0x9d, 0x69, 0x22, 0xb5, 0x34, 0xbe, 0xc9, 0xfa, 0xc1, 0xd7, 0xd2, 0x74, 0xdb, 0xcb, - 0x4a, 0x12, 0xea, 0x5a, 0x99, 0x21, 0x39, 0x2f, 0x00, 0x96, 0x60, 0x29, 0xff, 0x26, - 0x0e, 0xd2, 0x4c, 0x32, 0x78, 0x58, 0xe0, 0x34, 0x64, 0x0a, 0x8c, 0xfb, 0x28, 0xad, - 0x97, 0xe5, 0x3d, 0x80, 0xe1, 0xc9, + 0x72, 0x29, 0xa0, 0xa5, 0x6a, 0x14, 0x4b, 0x04, 0x2c, 0x1e, 0xad, 0x91, 0x80, 0xac, + 0x54, 0xda, 0xc6, 0xc5, 0x5c, 0xf4, 0xc2, 0x2f, 0xbe, 0x7c, 0xde, 0x99, 0x96, 0x0b, + 0xc6, 0x20, 0xd4, 0xdd, 0x60, 0xe4, 0xbf, 0x18, 0xa0, 0xea, 0x7a, 0xd9, 0x09, 0x3b, + 0xcd, 0x3f, 0xf6, 0xd1, 0x61, 0x1c, 0x56, 0x5f, 0x88, 0xe7, 0x35, 0xef, 0x4c, 0x51, + 0x8c, 0x77, 0xd6, 0x22, 0x28, 0xe1, 0xe4, 0xa1, 0x35, 0xca, 0x6c, 0xb4, 0xed, 0x5a, + 0xbb, 0xdf, 0x3e, 0x81, 0xd0, 0x96, 0x50, 0xa8, 0xfa, 0x9b, 0x5c, 0x3d, 0x05, 0xb6, + 0xda, 0xcf, 0x3c, 0x3d, 0xb3, 0xb3, 0x63, 0xe4, 0x10, 0x57, 0x23, 0x70, 0x0c, 0x69, + 0x13, 0x9f, 0x81, 0xec, 0xc4, 0x8d, 0x88, 0x3d, 0xa0, 0x39, 0xdd, 0xed, 0x5e, 0xf6, + 0x04, 0x0a, 0xb2, 0x12, 0x0e, 0x53, 0x3b, 0x1f, 0xfd, 0x06, 0x74, 0xdb, 0x5b, 0x92, + 0x6e, 0x58, 0x7f, 0x16, 0xe7, 0xe8, 0x96, 0x2b, 0x12, 0x48, 0x35, 0xbd, 0x56, 0xcf, + 0xd8, 0xe7, 0x5b, 0xf6, 0xaa, 0x4d, 0xcd, 0x4d, 0x6f, 0x0b, 0x55, 0x61, 0x71, 0x9c, + 0x80, 0xaa, 0x82, 0xb3, 0xbc, 0xea, 0x16, 0x7a, 0x31, 0xc6, 0x69, 0x87, 0x61, 0xe2, + 0xd2, 0x6c, 0xb5, 0x6d, 0xd3, 0x04, 0x16, 0x72, 0x1c, 0x93, 0x37, 0x32, 0x92, 0x85, + 0x33, 0x58, 0xfa, 0xfe, 0x74, 0x95, 0x55, 0x8d, 0xb9, 0x9e, 0x47, 0xa3, 0xa1, 0x6e, + 0xd2, 0x2c, 0xdb, 0x9d, 0x7d, 0x16, 0xcf, 0xd9, 0xa7, 0xbb, 0x55, 0x9c, 0x72, 0x86, + 0xed, 0x84, 0xf8, 0x89, 0x9c, 0xb0, 0x52, 0x2e, 0x8a, 0x49, 0x7f, 0x3e, 0x14, 0x45, + 0x2b, 0xa8, 0xa9, 0x4a, 0x7f, 0x58, 0xe5, 0xde, 0x37, 0x1d, 0x76, 0xec, 0xc9, 0xef, + 0xe2, 0x0a, 0xe7, 0x9b, 0xee, 0x12, 0xbc, 0xe4, 0xe4, 0xb6, 0xf2, 0x35, 0x35, 0xe5, + 0xc3, 0xc4, 0x3a, 0x4c, 0xa2, 0x07, 0x6f, 0xd6, 0x73, 0xf0, 0x80, 0x6f, 0xa9, 0x85, + 0xc5, 0x88, 0xd1, 0x14, 0xc0, 0x7d, 0x8c, 0xe3, 0xa2, 0x33, 0xe5, 0x4d, 0x77, 0x11, + 0x6c, 0x8a, 0x2a, 0x56, 0xa6, 0x82, 0xe7, 0xa4, 0x85, 0xdf, 0x71, 0xb3, 0x02, 0xa0, + 0x36, 0xdd, 0xab, 0x21, 0x4d, 0xee, 0x77, 0x62, 0x19, 0xcc, 0x24, 0x25, 0x94, 0xf7, + 0x5b, 0x8e, 0xbd, 0x56, 0x6d, 0x74, 0xb1, 0x6c, 0x9e, 0xc0, 0x05, 0x8b, 0xca, 0x28, + 0x81, 0xb7, 0x9b, 0x10, 0xe8, 0xa8, 0x01, 0x08, 0x20, 0x61, 0x8a, 0xc6, 0x52, 0x6c, + 0xf9, 0x4b, 0x13, 0xd9, 0x75, 0x9f, 0x37, 0x33, 0x93, 0x34, 0xe8, 0xb2, 0xc6, 0xbd, + 0xd1, 0xd0, 0xf5, 0xe2, 0x46, 0x3c, 0xff, 0x2b, 0x8d, 0xa6, 0xd2, 0xc6, 0x86, 0xaa, + 0x98, 0x7c, 0xd1, 0xf0, 0x7e, 0x9a, 0xa2, 0x60, 0xdd, 0x04, 0x28, 0xa4, 0xff, 0x78, + 0xaa, 0x8f, 0xda, 0x47, 0x7a, 0xb3, 0x8a, 0xcf, 0xcc, 0xb1, 0x90, 0x91, 0x77, 0xb5, + 0x27, 0xe9, 0x38, 0xf1, 0xf9, 0xdc, 0xf3, 0x1f, 0x4f, 0x40, 0xa9, 0x62, 0x89, 0x51, + 0xfc, 0x2a, 0x7a, 0xbc, 0x04, 0x1e, 0x8c, 0x93, 0x36, 0x08, 0xbb, 0x47, 0xb4, 0x50, + 0xb2, 0x8f, 0xee, 0xe0, 0x41, 0x58, 0xa8, 0x17, 0x4b, 0xff, 0xe4, 0x97, 0x06, 0x02, + 0x48, 0x86, 0x42, 0xc1, 0x9e, 0x61, 0xd4, 0x73, 0xf3, 0xde, 0x0c, 0xb0, 0xb6, 0x4a, + 0x30, 0xd6, 0xf1, 0x46, 0x68, 0xd1, 0xb0, 0x17, 0x77, 0x56, 0x6f, 0xb5, 0xac, 0xc2, + 0xe9, 0x2e, 0x64, 0xd9, 0x75, 0x7f, 0xba, 0x13, 0xc1, 0xee, 0x9c, 0xd0, 0x3a, 0xbe, + 0x98, 0xbd, 0x7e, 0x8a, 0xd7, 0x04, 0x1c, 0x3f, 0xea, 0xe7, 0xc1, 0xa7, 0x24, 0x3a, + 0xe3, 0x61, 0x0a, 0xac, 0x64, 0xfe, 0xc6, 0xc9, 0xfc, 0x94, 0x3d, 0x6a, 0xbc, 0xe9, + 0x10, 0xad, 0xbe, 0x23, 0xb5, 0x46, 0xb4, 0xc2, 0x4a, 0xa9, 0xf2, 0xce, 0x5d, 0x97, + 0x06, 0x2e, 0xe0, 0xd1, 0xcc, 0xc4, 0x8c, 0xfd, 0x1f, 0xdb, 0xa7, 0xfd, 0xac, 0x0b, + 0x04, 0xd1, 0xb3, 0xdc, 0x7a, 0x70, 0x78, 0x1c, 0xdd, 0xa2, 0xa2, 0x70, 0x3d, 0xe0, + 0x03, 0xcd, 0x01, 0x51, 0xec, 0x65, 0xbf, 0x7d, 0x1a, 0xc6, 0x3b, 0xb7, 0x35, 0xbc, + 0x2b, 0xb6, 0x7a, 0xd2, 0xb0, 0x1e, 0xd6, 0xb9, 0xae, 0x2e, 0xbb, 0xd3, 0x7a, 0x8f, + 0x8e, 0xc1, 0xa6, 0x53, 0xa8, 0x7e, ], ock: [ - 0x28, 0xcf, 0x3b, 0xea, 0xc3, 0xbd, 0xe2, 0xe9, 0x63, 0xaa, 0x60, 0x91, 0x3f, 0x10, - 0x5d, 0x25, 0x67, 0xcd, 0xaf, 0xbb, 0x66, 0x09, 0x08, 0x5a, 0x84, 0x3f, 0x75, 0x68, - 0xe4, 0x92, 0xd4, 0x4e, + 0x1b, 0xa4, 0xac, 0xd7, 0x75, 0x10, 0xc4, 0xf0, 0xc7, 0x66, 0xad, 0xf7, 0xc7, 0xdf, + 0x1d, 0x1c, 0x54, 0xd5, 0xbc, 0xe3, 0xd6, 0x0a, 0xf3, 0x5e, 0x8d, 0xd4, 0x8f, 0xdd, + 0x04, 0xa7, 0x8c, 0x0b, ], op: [ 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, - 0x01, 0x70, 0x89, 0x1a, 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, - 0x59, 0xa1, 0x33, 0xf3, 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, - 0xdd, 0x63, 0xe0, 0x62, 0x83, 0x05, 0x47, 0x08, + 0x01, 0x70, 0x89, 0x1a, 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, + 0x6b, 0xa0, 0x02, 0x0c, 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, + 0x57, 0x32, 0x63, 0xf4, 0x99, 0xbd, 0x4c, 0x13, ], c_out: [ - 0x0b, 0x2c, 0xc0, 0xa2, 0x2d, 0x06, 0xfc, 0x36, 0xa0, 0x8a, 0x7d, 0x82, 0x33, 0x8d, - 0x4a, 0xd0, 0x95, 0xa3, 0x93, 0xa1, 0xc2, 0x4a, 0x78, 0x8d, 0x45, 0x24, 0x35, 0x94, - 0x4a, 0xcc, 0xe6, 0x38, 0x1e, 0xcc, 0x69, 0x37, 0xf2, 0xc3, 0x8c, 0x89, 0xa5, 0xf5, - 0x1a, 0xa6, 0x0c, 0xa6, 0x58, 0xfe, 0x71, 0x37, 0x1c, 0x2a, 0x83, 0xf4, 0x96, 0xca, - 0x2e, 0x62, 0x49, 0x79, 0x2e, 0x09, 0xeb, 0x79, 0xea, 0x3a, 0x13, 0x80, 0x32, 0x18, - 0xff, 0x20, 0x88, 0x9d, 0x8c, 0x59, 0xc8, 0x5e, 0x90, 0x99, - ], + 0x43, 0x0d, 0xaa, 0x6b, 0x75, 0x63, 0x22, 0x80, 0xd5, 0xe6, 0xda, 0xcb, 0xd2, 0xa0, + 0xff, 0xe2, 0xaf, 0x98, 0x60, 0xc8, 0x3a, 0x3d, 0x2a, 0x87, 0xf1, 0x79, 0x62, 0x88, + 0xeb, 0xed, 0x64, 0xd0, 0xcd, 0xc4, 0x60, 0xe2, 0xc8, 0x61, 0xc4, 0xf9, 0x38, 0x7d, + 0x92, 0x59, 0xfc, 0x60, 0x01, 0xac, 0xd0, 0xe7, 0x6f, 0x3b, 0x0f, 0xdb, 0x5d, 0xac, + 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, + 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, + ], + note_type: None, }, TestVector { incoming_viewing_key: [ @@ -1978,34 +1987,34 @@ pub(crate) fn test_vectors() -> Vec { 0x71, 0x55, 0x00, 0xb5, ], rho: [ - 0x3b, 0x37, 0x96, 0x78, 0x0c, 0x0a, 0xec, 0x14, 0xed, 0x28, 0x74, 0xb5, 0x23, 0x06, - 0xe1, 0xc3, 0xd5, 0xde, 0x45, 0x93, 0xc6, 0x69, 0xaf, 0x1c, 0xaf, 0x11, 0xbc, 0xb4, - 0xd3, 0x5c, 0x60, 0x12, + 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, + 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, + 0xa3, 0x18, 0x53, 0x3e, ], cmx: [ - 0x4d, 0xa9, 0xdf, 0xdc, 0x70, 0x8c, 0xe8, 0xa0, 0x77, 0xa0, 0x6e, 0xc0, 0x67, 0x79, - 0x24, 0xcf, 0x37, 0x70, 0xed, 0xc2, 0x07, 0xfd, 0x5e, 0x7d, 0x69, 0x5f, 0x71, 0xb0, - 0x15, 0xbb, 0x03, 0x05, + 0x6a, 0xba, 0x28, 0x10, 0x5b, 0xc0, 0x72, 0xc5, 0x2a, 0xb8, 0xa3, 0x14, 0x79, 0x7f, + 0xf8, 0x66, 0x66, 0xdf, 0xb7, 0xcd, 0x8a, 0x2a, 0xe1, 0x7c, 0x58, 0x5f, 0xb7, 0xb6, + 0x51, 0x5b, 0x97, 0x1c, ], esk: [ - 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, 0x52, 0x6d, 0x66, 0x54, - 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, 0xfb, 0xee, 0x5d, 0xe3, - 0x99, 0xca, 0x31, 0x26, + 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, 0xd5, 0x64, 0x6b, 0xc4, + 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, 0x15, 0x5b, 0xef, 0x4d, + 0x46, 0x1e, 0xec, 0x29, ], ephemeral_key: [ - 0x2d, 0xa0, 0x59, 0x4c, 0xd8, 0x74, 0x91, 0x46, 0x52, 0x67, 0xe7, 0x2c, 0x61, 0x89, - 0x07, 0x91, 0xfe, 0xb4, 0x25, 0xa2, 0xbb, 0xcd, 0xda, 0xcf, 0xe4, 0x5a, 0x66, 0x62, - 0x2f, 0x49, 0xef, 0x35, + 0x95, 0x9b, 0xea, 0x8e, 0x11, 0x96, 0x8b, 0x0f, 0x34, 0x3c, 0x04, 0xcd, 0x6d, 0x50, + 0x16, 0xfc, 0xd4, 0x33, 0x90, 0x75, 0x36, 0xa2, 0x46, 0xba, 0x1c, 0x5d, 0x3e, 0x88, + 0x97, 0xf3, 0x23, 0x1c, ], shared_secret: [ - 0xe0, 0xb1, 0x52, 0x67, 0xfd, 0x21, 0x08, 0xeb, 0xbd, 0xd4, 0x16, 0x3f, 0x83, 0xad, - 0xef, 0xb6, 0x1c, 0x3e, 0xdf, 0x56, 0x6d, 0x94, 0x6f, 0xa1, 0xc1, 0x5e, 0x96, 0x46, - 0x43, 0xb1, 0x9c, 0x8e, + 0xe2, 0x69, 0x19, 0xb4, 0x0c, 0x70, 0xaf, 0x74, 0x1d, 0xf9, 0x04, 0x51, 0x72, 0x55, + 0x03, 0x58, 0x89, 0xee, 0x5a, 0x44, 0x42, 0x6d, 0x6a, 0xb8, 0x5c, 0x07, 0x4b, 0x86, + 0x2b, 0xa0, 0x63, 0x08, ], k_enc: [ - 0x28, 0x48, 0xae, 0x53, 0xaa, 0xce, 0xbe, 0x7c, 0xab, 0x58, 0x73, 0x1d, 0xc2, 0x21, - 0x88, 0x1b, 0x60, 0x2c, 0xc5, 0xa5, 0x3b, 0xcc, 0x1f, 0x76, 0xc8, 0x20, 0xb0, 0xea, - 0x13, 0x55, 0x68, 0x8e, + 0x09, 0xda, 0xc6, 0x51, 0x1c, 0x38, 0x44, 0x58, 0x7f, 0x82, 0x9c, 0x2f, 0x1e, 0xa0, + 0x37, 0xa8, 0x1a, 0x8d, 0x54, 0x85, 0xed, 0x04, 0xea, 0xf2, 0x75, 0x80, 0x05, 0xb3, + 0x2a, 0x20, 0x47, 0x0b, ], p_enc: [ 0x02, 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, 0xad, 0x95, @@ -2051,69 +2060,2210 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0xc6, 0x38, 0xbf, ], c_enc: [ - 0xf1, 0x42, 0xc4, 0xe5, 0x0e, 0xef, 0x2c, 0x64, 0x44, 0xcc, 0xd4, 0x0b, 0x8c, 0x99, - 0xe5, 0x6a, 0x72, 0xec, 0x4e, 0x30, 0xcf, 0x73, 0x68, 0x75, 0xf0, 0xaa, 0x6b, 0x8e, - 0x6d, 0x9c, 0xc3, 0x67, 0x73, 0x2d, 0xbc, 0x9a, 0xf0, 0xb3, 0x7d, 0x1f, 0xca, 0x6d, - 0x5b, 0xdd, 0x1d, 0xc1, 0x23, 0x79, 0x29, 0x66, 0x99, 0x9d, 0x62, 0xea, 0xf8, 0xc5, - 0xfe, 0x8d, 0x99, 0x91, 0x84, 0xf2, 0x8b, 0x99, 0xec, 0xef, 0xcc, 0x8f, 0x14, 0x8d, - 0xbd, 0x52, 0x02, 0x6f, 0xdb, 0x48, 0xdf, 0xda, 0x7b, 0xad, 0xb6, 0xd1, 0xfc, 0xd2, - 0x9a, 0xd2, 0x19, 0xea, 0xbf, 0xbb, 0x44, 0x3f, 0x5d, 0x0f, 0x98, 0xb6, 0x6a, 0x3a, - 0x25, 0x73, 0x1b, 0x52, 0xd7, 0xf2, 0xdf, 0x70, 0x01, 0x4b, 0x4a, 0xc6, 0x99, 0x34, - 0x32, 0xf8, 0x98, 0x1e, 0x9c, 0xbf, 0xe1, 0x69, 0x13, 0xf6, 0x8a, 0x93, 0x5d, 0x2d, - 0xd0, 0x06, 0xd4, 0x28, 0xf1, 0x45, 0x53, 0xe7, 0x29, 0x86, 0xc7, 0x0f, 0xb4, 0x43, - 0x18, 0xd2, 0x7c, 0x4d, 0x6f, 0x6f, 0xd3, 0x92, 0x3a, 0xb0, 0xf6, 0x28, 0x9a, 0x02, - 0x48, 0x5e, 0x87, 0x17, 0xe5, 0x7d, 0xa0, 0x24, 0xeb, 0xe1, 0x6e, 0x9c, 0xf8, 0x35, - 0xcf, 0x53, 0xd2, 0x19, 0x4f, 0xd4, 0x25, 0x50, 0x06, 0xb8, 0x1b, 0xfd, 0x51, 0xd1, - 0xef, 0x5a, 0xe9, 0xf9, 0xef, 0x6a, 0xf6, 0x57, 0x41, 0x81, 0xe2, 0xe2, 0x26, 0x50, - 0xcb, 0x91, 0x2a, 0x6b, 0x89, 0x88, 0xa0, 0x28, 0x86, 0x32, 0xbc, 0x73, 0x62, 0xbb, - 0xe1, 0x87, 0x23, 0xd8, 0x27, 0xf7, 0x94, 0x58, 0x62, 0x26, 0x0d, 0xf7, 0x8e, 0x95, - 0xd7, 0xd5, 0xe3, 0x31, 0x3f, 0x5a, 0xff, 0x72, 0xe2, 0x1c, 0xe2, 0xdf, 0x00, 0xee, - 0x7e, 0x81, 0x5a, 0xba, 0x17, 0xcc, 0xde, 0x15, 0xc2, 0x7e, 0xee, 0x08, 0x5f, 0x52, - 0xf3, 0x6c, 0x02, 0xec, 0xd6, 0x6c, 0xe1, 0x8b, 0x40, 0x15, 0xbe, 0xb6, 0x09, 0x23, - 0x3f, 0x6e, 0xb2, 0x8e, 0x4a, 0xd5, 0xcd, 0xbe, 0x6f, 0xdc, 0xab, 0x68, 0xbf, 0xbb, - 0x6f, 0xfd, 0x87, 0xd3, 0x86, 0xd8, 0x7e, 0xb1, 0xfe, 0x00, 0x34, 0x27, 0x0f, 0x41, - 0x27, 0x1e, 0xa0, 0x1f, 0x9e, 0xae, 0xa9, 0xe8, 0x9f, 0x78, 0x35, 0x9e, 0x41, 0x73, - 0x94, 0xbb, 0x9d, 0xf5, 0xb6, 0x1c, 0x36, 0xe3, 0x0b, 0xc1, 0xce, 0x4a, 0xb1, 0xbd, - 0xd7, 0x9f, 0xa4, 0x08, 0x3e, 0x82, 0x8d, 0xd1, 0x04, 0xe4, 0x73, 0x80, 0xcd, 0x83, - 0xcd, 0x65, 0x9d, 0xf4, 0x4d, 0xb9, 0x43, 0xdc, 0x07, 0xbc, 0xc8, 0x07, 0x05, 0x04, - 0xa1, 0xc6, 0x55, 0x23, 0x02, 0xe7, 0x4b, 0xe4, 0xb9, 0xc4, 0x32, 0x75, 0xec, 0xc2, - 0x88, 0xce, 0xda, 0x41, 0x59, 0xa9, 0xcc, 0x55, 0x7c, 0x18, 0x19, 0x5c, 0xec, 0x92, - 0x62, 0x24, 0xd8, 0xd6, 0x9e, 0x98, 0xe1, 0x83, 0x5a, 0x2e, 0x29, 0x05, 0x63, 0xef, - 0x20, 0xd0, 0x83, 0xd1, 0x4e, 0x93, 0xcc, 0x1f, 0x3f, 0x76, 0x3e, 0xf5, 0x58, 0x0e, - 0x13, 0x5f, 0xae, 0x1b, 0xb8, 0x54, 0x4a, 0x0c, 0x5c, 0x6d, 0x88, 0x17, 0x41, 0xe4, - 0x51, 0x34, 0x47, 0xac, 0xeb, 0x09, 0x33, 0xe6, 0xeb, 0xaf, 0x0c, 0xe3, 0x13, 0xc1, - 0x8c, 0x9a, 0xf9, 0x5b, 0xa5, 0x61, 0x31, 0xf7, 0x8f, 0x42, 0x72, 0x41, 0x22, 0x65, - 0xbc, 0xf4, 0xc5, 0xf6, 0x80, 0x89, 0x3c, 0xcd, 0xa5, 0x73, 0x7d, 0xa8, 0x23, 0xb7, - 0x63, 0x6e, 0x98, 0xdb, 0xa5, 0x62, 0x44, 0xf2, 0xb9, 0x6a, 0x10, 0x90, 0xa6, 0x60, - 0x38, 0x15, 0xc0, 0xef, 0x54, 0x97, 0x50, 0xf2, 0x47, 0x06, 0x19, 0x0b, 0x55, 0x76, - 0x6e, 0x8a, 0x62, 0x09, 0xa1, 0xc2, 0x2f, 0x67, 0xe8, 0x77, 0x62, 0x66, 0xb6, 0xfa, - 0xe4, 0x5b, 0xf7, 0x94, 0x90, 0x7f, 0x64, 0x71, 0x4f, 0xbe, 0x26, 0xc3, 0x0a, 0xc4, - 0x04, 0x11, 0xf5, 0xe6, 0x4f, 0xc1, 0x66, 0xc8, 0x4f, 0x28, 0xb8, 0x23, 0xfd, 0xaa, - 0x68, 0x32, 0xa3, 0x25, 0x63, 0x31, 0x7d, 0x25, 0x4c, 0x53, 0x16, 0x9b, 0x9f, 0xfb, - 0x24, 0x53, 0xa1, 0x12, 0x2f, 0xa4, 0x4c, 0x7f, 0x17, 0xc1, 0x36, 0xb5, 0x7e, 0x20, - 0xad, 0x17, 0x7a, 0x7e, 0xee, 0xbf, 0x9f, 0x56, 0xfb, 0x0b, 0x55, 0xcc, 0xcf, 0x68, - 0x2b, 0x8a, 0x5b, 0xd8, 0xa7, 0x45, + 0x7b, 0x59, 0x87, 0x78, 0xa7, 0x28, 0x4d, 0x52, 0xa7, 0x47, 0x77, 0x4c, 0x54, 0xbd, + 0x92, 0x57, 0xb3, 0xf1, 0x7a, 0xf1, 0x3e, 0xcc, 0x72, 0xc0, 0xe3, 0xcd, 0x95, 0xeb, + 0xfa, 0xfa, 0xa3, 0x7d, 0x16, 0x65, 0x15, 0x53, 0xdd, 0x27, 0xf0, 0x1c, 0x9c, 0xf2, + 0x4b, 0x62, 0xd7, 0xdc, 0xfd, 0x52, 0xfa, 0x4b, 0x2b, 0x3b, 0x4a, 0x8c, 0xa9, 0xeb, + 0xfc, 0xe7, 0xf4, 0xfc, 0xec, 0x27, 0xe6, 0x05, 0x8e, 0x44, 0x68, 0xc1, 0x50, 0x10, + 0xd0, 0x17, 0xcb, 0x90, 0x1a, 0xbf, 0xb2, 0x2e, 0xad, 0x86, 0x99, 0x83, 0xf6, 0x9a, + 0xed, 0xf2, 0xda, 0x7d, 0x6a, 0xaf, 0xd1, 0x30, 0x6e, 0xe7, 0x36, 0xf2, 0xdb, 0x33, + 0xbc, 0xe4, 0xb0, 0x9f, 0xca, 0x74, 0x69, 0x2a, 0x52, 0x09, 0xa7, 0x39, 0x2b, 0x7e, + 0xa9, 0x68, 0x5b, 0xe9, 0xec, 0x43, 0x1f, 0xfe, 0x50, 0xf7, 0x0f, 0x90, 0x22, 0x74, + 0x05, 0x03, 0x45, 0x2a, 0xb5, 0x14, 0x92, 0xb1, 0xf7, 0x47, 0x7e, 0xda, 0x42, 0x7b, + 0x42, 0x3a, 0x93, 0x1b, 0x26, 0x38, 0x6c, 0x56, 0xe4, 0x27, 0x86, 0x3d, 0x46, 0xb1, + 0x99, 0xff, 0xa0, 0x8c, 0x52, 0x9f, 0xa5, 0x72, 0x1f, 0x68, 0xe9, 0x14, 0xf6, 0xea, + 0x6a, 0x8a, 0xe6, 0xae, 0xcb, 0xf7, 0x37, 0x47, 0x1e, 0xbd, 0x83, 0xdb, 0xa9, 0xa7, + 0xcd, 0x89, 0x75, 0x66, 0x20, 0x4e, 0x2b, 0xae, 0x63, 0xe3, 0x4e, 0x70, 0x32, 0x51, + 0x02, 0x96, 0x92, 0x0d, 0x7e, 0x7a, 0x7c, 0xcf, 0x0f, 0xeb, 0xe7, 0xa8, 0x33, 0x69, + 0x6a, 0x4b, 0x67, 0x41, 0x88, 0x5e, 0x9b, 0x94, 0x0c, 0x61, 0xdd, 0x8d, 0x44, 0x38, + 0x54, 0x74, 0x15, 0x31, 0x0b, 0x15, 0xcf, 0x18, 0xdc, 0x19, 0x90, 0x07, 0x8c, 0x70, + 0x8b, 0xea, 0xc3, 0x32, 0xa8, 0xe0, 0x81, 0x46, 0xa6, 0x95, 0x8e, 0xa6, 0xf4, 0x3f, + 0xd0, 0xc2, 0xc8, 0xe9, 0x99, 0xaa, 0x4f, 0xdf, 0x1e, 0x77, 0xef, 0xde, 0x54, 0xfd, + 0x65, 0xc6, 0x7a, 0x3f, 0x07, 0xda, 0xf5, 0xf6, 0x04, 0x49, 0x60, 0xa0, 0xb6, 0xdd, + 0x84, 0x1f, 0xf8, 0xb8, 0xa5, 0x92, 0xc7, 0xb1, 0x09, 0x34, 0x2c, 0x73, 0x5c, 0x2a, + 0x0e, 0x37, 0xb3, 0x0b, 0x8b, 0xaa, 0x5c, 0x77, 0x01, 0xeb, 0xc7, 0xa8, 0xf8, 0x20, + 0xc0, 0x22, 0x7c, 0xa5, 0x00, 0x3f, 0x36, 0xee, 0x68, 0xf7, 0xb2, 0x89, 0x81, 0xc2, + 0x73, 0x32, 0x03, 0x9d, 0xd6, 0xa4, 0x94, 0xf0, 0xcd, 0x02, 0xbd, 0xd2, 0x8f, 0x68, + 0x3e, 0xca, 0x1b, 0x03, 0x2a, 0xfc, 0x09, 0xdd, 0x0c, 0xd8, 0x56, 0xcb, 0xc1, 0xa3, + 0x5e, 0x74, 0xd4, 0x0c, 0x24, 0x53, 0xdf, 0xe2, 0x42, 0xc8, 0x6a, 0x7a, 0x60, 0xbc, + 0xbd, 0xdb, 0x17, 0x96, 0x6c, 0x7d, 0xba, 0x76, 0x9e, 0xab, 0xd1, 0xc1, 0x67, 0xb7, + 0xe8, 0x19, 0x78, 0xf9, 0x12, 0x8b, 0xac, 0x26, 0xa2, 0x8d, 0x77, 0x21, 0x30, 0x79, + 0xcb, 0x56, 0xc0, 0x95, 0xa7, 0xc0, 0x60, 0xde, 0x0e, 0x77, 0x5c, 0xa8, 0xac, 0x8e, + 0x6c, 0xa9, 0x4d, 0x19, 0xc6, 0x16, 0x2e, 0x44, 0xf7, 0xa8, 0xf0, 0x14, 0x9d, 0x31, + 0xd3, 0x46, 0x3d, 0x01, 0xb6, 0x1a, 0x14, 0x63, 0xa9, 0xde, 0x3d, 0x8a, 0xb7, 0x40, + 0x04, 0x0a, 0x76, 0xe0, 0x5b, 0x37, 0x64, 0x28, 0x86, 0x29, 0x87, 0x59, 0x5b, 0x87, + 0xce, 0xa6, 0x94, 0xfe, 0x92, 0x0a, 0x06, 0x7e, 0x81, 0x6b, 0x4f, 0x29, 0xa3, 0xa2, + 0x24, 0x50, 0x14, 0x0f, 0x13, 0x5d, 0x71, 0x9a, 0x97, 0x1b, 0x81, 0xfc, 0x19, 0x16, + 0x98, 0x0a, 0x55, 0xdd, 0xf8, 0xd9, 0x87, 0x30, 0x57, 0x36, 0x35, 0xa0, 0x70, 0x85, + 0xc4, 0xe7, 0x7c, 0x7e, 0x1c, 0xdb, 0xb6, 0x85, 0x42, 0x6e, 0xe4, 0x62, 0xcc, 0x30, + 0x83, 0xa3, 0xf5, 0xa3, 0xb9, 0x17, 0xc0, 0x6f, 0x9a, 0x96, 0xf9, 0xf7, 0xbd, 0x81, + 0xac, 0xa4, 0x9b, 0xef, 0x95, 0xb9, 0x28, 0x06, 0xc4, 0x2d, 0x09, 0x12, 0x01, 0x31, + 0x42, 0xb2, 0x2a, 0x7b, 0xad, 0x72, 0x12, 0x11, 0x46, 0x91, 0xf1, 0xdc, 0x72, 0x64, + 0xc6, 0x7e, 0x76, 0x34, 0xf5, 0xd7, 0x95, 0xc9, 0x75, 0x30, 0x62, 0xe3, 0x06, 0xc0, + 0x6b, 0xc1, 0x03, 0xaa, 0x01, 0xc1, 0x0d, 0x1f, 0x5d, 0xd4, 0xcd, 0x59, 0xf6, 0x53, + 0x2c, 0xb7, 0x23, 0xe3, 0xa0, 0x26, ], ock: [ - 0x06, 0x3c, 0x83, 0xa4, 0x95, 0x74, 0xe7, 0x80, 0x35, 0x89, 0xcc, 0x3d, 0x34, 0xb4, - 0x38, 0x90, 0xf3, 0xd7, 0x63, 0x87, 0x35, 0xe7, 0xbd, 0x5e, 0xbd, 0xd1, 0xa5, 0xea, - 0xb9, 0xd9, 0xc5, 0xd6, + 0x4a, 0x25, 0x25, 0x4c, 0xcc, 0x44, 0x4e, 0xc6, 0x1c, 0x2b, 0xac, 0xeb, 0x2e, 0xe3, + 0x97, 0x7a, 0x63, 0x32, 0x44, 0x9a, 0x3a, 0x53, 0xad, 0xd2, 0x31, 0xab, 0xf3, 0xd1, + 0x8b, 0xb3, 0x29, 0x3d, ], op: [ 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, - 0x44, 0x6d, 0xf4, 0x39, 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, - 0x52, 0x6d, 0x66, 0x54, 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, - 0xfb, 0xee, 0x5d, 0xe3, 0x99, 0xca, 0x31, 0x26, + 0x44, 0x6d, 0xf4, 0x39, 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, + 0xd5, 0x64, 0x6b, 0xc4, 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, + 0x15, 0x5b, 0xef, 0x4d, 0x46, 0x1e, 0xec, 0x29, + ], + c_out: [ + 0x7b, 0xf4, 0x12, 0x7d, 0x22, 0xcc, 0x57, 0x35, 0x87, 0x51, 0x2f, 0xf8, 0x1e, 0x55, + 0x3e, 0x3c, 0x98, 0x23, 0x5f, 0x51, 0xc7, 0x23, 0x7e, 0x9e, 0x76, 0x1a, 0x08, 0xf2, + 0xe1, 0xe8, 0x0d, 0x04, 0x26, 0x98, 0xfc, 0x3b, 0x1d, 0x03, 0x18, 0xf1, 0xfd, 0xca, + 0x8e, 0x41, 0xa3, 0x16, 0xd6, 0xaf, 0x3a, 0xc0, 0xc4, 0x0c, 0xe1, 0x99, 0x47, 0xa2, + 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, + 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, + ], + note_type: None, + }, + TestVector { + incoming_viewing_key: [ + 0xdc, 0x10, 0x95, 0x20, 0x57, 0xc4, 0xbe, 0xaa, 0xd8, 0xaf, 0x37, 0xce, 0x4e, 0xee, + 0x9b, 0x10, 0xed, 0x84, 0xf4, 0x6b, 0xad, 0xd4, 0x8e, 0x0a, 0x22, 0x9b, 0xe8, 0x41, + 0x54, 0xa9, 0xbf, 0x75, 0x6b, 0xe0, 0x2e, 0xcf, 0xa9, 0xad, 0x6d, 0x9c, 0x02, 0xc8, + 0xf9, 0x54, 0xcb, 0x15, 0x71, 0x7b, 0x79, 0x46, 0x1f, 0x00, 0x4b, 0xf1, 0xbc, 0x5c, + 0x7e, 0x3f, 0xda, 0x73, 0x53, 0x7c, 0x1a, 0x0a, + ], + ovk: [ + 0x97, 0x74, 0x85, 0xcd, 0xdf, 0xbe, 0xd5, 0x93, 0x2f, 0x50, 0x7b, 0x79, 0x94, 0x7a, + 0xdb, 0x2f, 0xad, 0x37, 0x61, 0x5a, 0xa7, 0x17, 0xdb, 0x5f, 0x29, 0x80, 0x99, 0xf2, + 0x0f, 0x26, 0x3b, 0x35, + ], + default_d: [ + 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, + ], + default_pk_d: [ + 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, + 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, + 0xe6, 0x84, 0x45, 0xbb, + ], + v: 2111628168871420429, + rseed: [ + 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, + 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, + 0x3b, 0xd5, 0xbc, 0x87, + ], + memo: [ + 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, + 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, + 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, + 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, + 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, + 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, + 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, + 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, + 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, + 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, + 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, + 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, + 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, + 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, + 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, + 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, + 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, + 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, + 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, + 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, + 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, + 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, + 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, + 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, + 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, + 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, + 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, + 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, + 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, + 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, + 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, + 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, + 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, + 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, + 0xd8, 0x02, 0xf7, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x09, 0xee, 0x7e, 0xf6, 0x3a, 0xb1, 0xcf, 0x24, 0x2b, 0xaa, 0x76, 0xfc, 0xbf, 0xfb, + 0xe5, 0x75, 0x5f, 0x13, 0x14, 0x2b, 0x38, 0xb1, 0xa0, 0x40, 0x4d, 0x7d, 0x5a, 0x3f, + 0x4f, 0x22, 0x1e, 0x96, + ], + rho: [ + 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, + 0xa9, 0x4a, 0x06, 0x04, 0xb8, 0x00, 0x6c, 0xc7, 0x94, 0xbc, 0xab, 0x57, 0x73, 0x49, + 0xbc, 0xf8, 0x63, 0x37, + ], + cmx: [ + 0x85, 0xec, 0x16, 0xe8, 0x78, 0x77, 0x33, 0x37, 0x07, 0x9a, 0xec, 0xf3, 0x2c, 0x45, + 0x5e, 0xbf, 0x16, 0x96, 0x8d, 0xa1, 0xd4, 0x34, 0x51, 0xb7, 0xa3, 0x06, 0x87, 0x6c, + 0xa3, 0x08, 0xea, 0x3c, + ], + esk: [ + 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, 0x39, 0x16, 0x0f, 0xe5, + 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, 0xe0, 0xd2, 0x9b, 0x35, + 0x9a, 0xc4, 0xfa, 0x2c, + ], + ephemeral_key: [ + 0x10, 0x0d, 0xf0, 0x1d, 0x49, 0x86, 0x01, 0x21, 0x8a, 0x28, 0x6b, 0x8f, 0x4e, 0x54, + 0xda, 0x9b, 0x3f, 0x14, 0x5c, 0x34, 0x70, 0xa9, 0xdb, 0xc4, 0x14, 0x48, 0x0a, 0xa8, + 0xf2, 0xf4, 0x90, 0x9c, + ], + shared_secret: [ + 0x93, 0x68, 0xdd, 0x4f, 0x2a, 0xf6, 0x23, 0x34, 0xb8, 0x85, 0xb9, 0x6b, 0xc4, 0xc3, + 0x8f, 0x10, 0x3a, 0xec, 0x25, 0x6b, 0xed, 0xc2, 0x8b, 0x5e, 0x2e, 0x10, 0x36, 0x4c, + 0xdd, 0xf3, 0x84, 0xa4, + ], + k_enc: [ + 0x7a, 0xff, 0xfc, 0x6e, 0xae, 0x5d, 0x56, 0xb2, 0x7b, 0x86, 0xdb, 0x9e, 0xc8, 0xae, + 0xc2, 0x70, 0xbb, 0x0a, 0xb7, 0x31, 0x23, 0xfd, 0x2a, 0x0b, 0x83, 0xf4, 0xef, 0x84, + 0xc6, 0x98, 0xe1, 0x67, + ], + p_enc: [ + 0x03, 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, 0x0d, 0x22, + 0x4a, 0xb7, 0xa1, 0x02, 0x4e, 0x1d, 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, + 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, + 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, 0x3b, 0xd5, 0xbc, 0x87, 0xa9, 0x71, 0x5e, 0x65, + 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, 0x84, 0xef, 0xd9, 0x2c, + 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, 0x4f, 0x95, 0x22, 0xb2, + 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, + 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, + 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, + 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, + 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, + 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, + 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, + 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, + 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, + 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, + 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, + 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, + 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, + 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, + 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, + 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, + 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, + 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, + 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, + 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, + 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, + 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, + 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, + 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, + 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, + 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, + 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, + 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, + 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, + 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, + 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, + 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, + 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, + 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, + 0xd8, 0x02, 0xf7, 0x73, + ], + c_enc: [ + 0x45, 0x6b, 0x2b, 0xb8, 0x03, 0xc7, 0xdf, 0xf7, 0xac, 0x82, 0xe6, 0x42, 0xf4, 0xd8, + 0x46, 0x1e, 0x0b, 0x7a, 0x3b, 0x3c, 0x95, 0xa4, 0xcb, 0xf1, 0xc0, 0x6f, 0xeb, 0x93, + 0xa1, 0x8b, 0xeb, 0xa2, 0x9f, 0x2b, 0x8f, 0x12, 0x1a, 0x61, 0x5c, 0xa5, 0x3f, 0xc2, + 0xa7, 0x60, 0x63, 0xb8, 0x0d, 0xaa, 0x71, 0x01, 0x8b, 0x66, 0x3b, 0x7c, 0x46, 0x6d, + 0xb2, 0x63, 0xf9, 0x04, 0x27, 0xd0, 0x11, 0x7f, 0x0b, 0x89, 0x90, 0x6e, 0x98, 0x41, + 0x7f, 0x3e, 0xe8, 0x5a, 0xcc, 0xed, 0xb1, 0x41, 0xfb, 0x10, 0x26, 0xa3, 0xb3, 0xf7, + 0xa4, 0xfd, 0x10, 0x24, 0xf9, 0xc8, 0x08, 0x9a, 0x2e, 0xbe, 0x1a, 0x27, 0x82, 0xf8, + 0xb0, 0xbf, 0x5c, 0x40, 0xb6, 0xd5, 0x2f, 0xfe, 0x38, 0x37, 0xf4, 0xe4, 0x42, 0x52, + 0x13, 0x41, 0xc2, 0x4d, 0x3e, 0x89, 0x55, 0x95, 0x08, 0x86, 0x27, 0x85, 0xea, 0x63, + 0x56, 0xb4, 0xe4, 0x66, 0xc3, 0x25, 0x9c, 0xeb, 0x0d, 0x28, 0x2e, 0x07, 0xbb, 0x35, + 0xdc, 0xf2, 0xd9, 0xa8, 0x62, 0xc7, 0x47, 0x58, 0xd3, 0x83, 0xaa, 0xa2, 0x82, 0xfa, + 0xc4, 0xfa, 0xcf, 0xe5, 0x39, 0xe4, 0xe1, 0xbb, 0xd5, 0x46, 0x8a, 0xcf, 0x25, 0xec, + 0x2b, 0x4b, 0xa5, 0x11, 0x9d, 0xea, 0xed, 0x01, 0x1d, 0x4f, 0x30, 0xb0, 0xc5, 0x82, + 0x01, 0xfe, 0xe1, 0xc6, 0xe4, 0xf6, 0xb5, 0x2e, 0x41, 0xad, 0xfa, 0x5d, 0x6f, 0xda, + 0x94, 0xa5, 0x23, 0x20, 0xe8, 0x3b, 0x80, 0xc6, 0xfc, 0xee, 0xb8, 0x97, 0x89, 0xd8, + 0x79, 0x94, 0xb7, 0xa0, 0x16, 0xec, 0x64, 0xe4, 0x70, 0x78, 0x07, 0xf8, 0xf2, 0xd2, + 0x30, 0x63, 0x10, 0x74, 0x10, 0x9f, 0xc5, 0x9d, 0xe3, 0xe4, 0x37, 0x10, 0xca, 0xe8, + 0x9c, 0xb1, 0x89, 0xa0, 0xa4, 0x64, 0x8b, 0x37, 0x54, 0x5d, 0x25, 0x49, 0x47, 0x95, + 0xa8, 0xdf, 0x3f, 0xfc, 0x7a, 0x3a, 0x21, 0xe3, 0xb9, 0x1c, 0x95, 0x96, 0xe0, 0xd5, + 0x10, 0x5d, 0xf8, 0xad, 0xa9, 0xcf, 0xe9, 0x31, 0x10, 0xb1, 0x9f, 0xf2, 0xaf, 0x83, + 0x03, 0xb5, 0xd2, 0x79, 0x3f, 0xff, 0xd0, 0x4d, 0x8e, 0x02, 0xf7, 0xb9, 0x30, 0x14, + 0x80, 0xdf, 0xd9, 0x35, 0x50, 0x2d, 0x98, 0xe2, 0xf3, 0xc3, 0xe9, 0xe9, 0x5e, 0x64, + 0xe4, 0x96, 0xeb, 0x7d, 0x15, 0xcf, 0x2c, 0x70, 0x11, 0x94, 0xe6, 0x25, 0xde, 0x52, + 0x1a, 0x02, 0x55, 0x20, 0xdf, 0x67, 0xac, 0x2b, 0xa4, 0x3b, 0x9c, 0x4a, 0x6d, 0x77, + 0xb8, 0x6a, 0x40, 0x18, 0x2d, 0x70, 0x31, 0x8b, 0x8f, 0xa3, 0x48, 0xb1, 0x86, 0x47, + 0xd8, 0x4e, 0x0e, 0xe5, 0xf0, 0x56, 0x07, 0xa2, 0xb8, 0xf2, 0x69, 0xe1, 0x86, 0xc7, + 0x94, 0x28, 0xbe, 0xa6, 0x7c, 0xbf, 0x71, 0xda, 0xcc, 0x98, 0xe9, 0xcc, 0x72, 0x5e, + 0x50, 0x53, 0xa4, 0x40, 0xca, 0xa6, 0xca, 0xd2, 0x41, 0xa5, 0x06, 0x28, 0x18, 0x3a, + 0xe9, 0xef, 0x9f, 0x0c, 0xbd, 0xfe, 0xf7, 0x0a, 0x42, 0xe5, 0xb7, 0x97, 0xbc, 0x99, + 0xd9, 0x22, 0xfc, 0xc2, 0x81, 0x37, 0x84, 0xea, 0xe4, 0x48, 0x60, 0x18, 0x0e, 0xf8, + 0xe8, 0x1f, 0x7b, 0x94, 0xf2, 0xad, 0x62, 0x12, 0x8b, 0xb6, 0x1f, 0x10, 0xd5, 0x0c, + 0x9c, 0xad, 0x9d, 0x80, 0x48, 0xd9, 0x78, 0x01, 0x8a, 0x1f, 0x3b, 0xc9, 0x24, 0x28, + 0xf8, 0x9d, 0x7d, 0xdc, 0xe5, 0x45, 0x4b, 0xc4, 0x49, 0x1f, 0xb4, 0xc2, 0xcb, 0x66, + 0x88, 0x35, 0xb2, 0x2f, 0xcc, 0x4d, 0xf2, 0x08, 0xf2, 0x16, 0x64, 0xf7, 0x12, 0x94, + 0xc5, 0xce, 0xd3, 0x3c, 0x8e, 0x11, 0xd4, 0x25, 0xd1, 0x39, 0x85, 0x23, 0xc2, 0x79, + 0x88, 0x3a, 0x38, 0x2f, 0x70, 0xfe, 0xfe, 0xc8, 0x25, 0xc5, 0xe3, 0x50, 0x85, 0xaf, + 0x82, 0xd0, 0xa0, 0xa9, 0xbf, 0x45, 0x11, 0x65, 0x0a, 0x2b, 0xfb, 0xf0, 0xb2, 0x18, + 0x82, 0x10, 0x5e, 0xc6, 0xe5, 0x99, 0x74, 0xd8, 0xd6, 0xce, 0x73, 0x07, 0x8f, 0xb4, + 0xb5, 0x63, 0x4e, 0x85, 0xd7, 0xe2, 0x0a, 0x97, 0xff, 0xb6, 0x5d, 0x4f, 0x5e, 0xaf, + 0x42, 0x63, 0x9b, 0x09, 0xf5, 0xed, 0xa5, 0x9a, 0xb1, 0x04, 0x97, 0x69, 0x95, 0x41, + 0xd1, 0xc8, 0x22, 0x8e, 0xb5, 0xdf, 0x47, 0xa6, 0x67, 0xc4, 0x6d, 0x4c, 0xff, 0xeb, + 0xfe, 0x3f, 0xbb, 0x0a, 0x4e, 0x48, + ], + ock: [ + 0x17, 0xeb, 0xb4, 0x82, 0xdf, 0x8d, 0x13, 0xc2, 0x0d, 0x9b, 0x4a, 0x03, 0x9f, 0x40, + 0x5a, 0x93, 0x69, 0x8a, 0xc2, 0x24, 0xf3, 0xea, 0x03, 0xfb, 0x55, 0x8d, 0x5b, 0x53, + 0x11, 0x46, 0xfb, 0xea, + ], + op: [ + 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, + 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, + 0xe6, 0x84, 0x45, 0xbb, 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, + 0x39, 0x16, 0x0f, 0xe5, 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, + 0xe0, 0xd2, 0x9b, 0x35, 0x9a, 0xc4, 0xfa, 0x2c, + ], + c_out: [ + 0x2d, 0x76, 0x57, 0x79, 0x67, 0x44, 0x5f, 0xb9, 0x17, 0xee, 0x72, 0xd3, 0x2d, 0x4b, + 0x75, 0x3b, 0x25, 0x10, 0xd8, 0x05, 0x5d, 0xec, 0x8b, 0xf1, 0x22, 0x0a, 0x75, 0xf0, + 0x65, 0xbd, 0x47, 0xe2, 0xcc, 0xb6, 0x03, 0x98, 0x84, 0x50, 0x23, 0x1b, 0xd3, 0x1c, + 0x15, 0x6f, 0xf2, 0xa7, 0x2a, 0xfd, 0x4a, 0x96, 0x0b, 0x6f, 0x6a, 0x78, 0x84, 0x65, + 0x13, 0x51, 0xe2, 0x4b, 0x47, 0x02, 0x87, 0xd5, 0x83, 0xba, 0x69, 0x71, 0x18, 0xec, + 0x07, 0xf6, 0x59, 0x2c, 0x4c, 0xd7, 0xcd, 0x6a, 0xc7, 0x7e, + ], + note_type: Some([ + 0xa9, 0x71, 0x5e, 0x65, 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, + 0x84, 0xef, 0xd9, 0x2c, 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, + 0x4f, 0x95, 0x22, 0xb2, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0xb6, 0x6c, 0x73, 0x33, 0x75, 0xda, 0xc6, 0xff, 0xcc, 0x98, 0xf5, 0x0f, 0x3a, 0xf0, + 0xb0, 0x76, 0x05, 0x53, 0xfe, 0x98, 0xed, 0x61, 0xff, 0xa4, 0x93, 0xea, 0xe6, 0x8d, + 0xf0, 0xb3, 0x33, 0x4e, 0xe8, 0xd4, 0x39, 0x37, 0xb7, 0xdb, 0x8e, 0xbb, 0xfe, 0xbd, + 0x54, 0x8a, 0x28, 0x02, 0x51, 0xea, 0x87, 0xaa, 0x5d, 0x8c, 0xa5, 0x36, 0x86, 0x1b, + 0x38, 0x4f, 0x20, 0x86, 0x9f, 0x8f, 0xe8, 0x01, + ], + ovk: [ + 0xe9, 0x4c, 0x15, 0x24, 0x5f, 0x1a, 0x95, 0x88, 0x40, 0xba, 0x3f, 0x38, 0x0a, 0x4d, + 0x20, 0xf1, 0x18, 0x4e, 0x77, 0x82, 0x7d, 0xe3, 0xff, 0x8f, 0x3d, 0x73, 0x45, 0x9a, + 0xfe, 0x24, 0x1f, 0x72, + ], + default_d: [ + 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, + ], + default_pk_d: [ + 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, + 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, + 0x25, 0xc8, 0xd6, 0xae, + ], + v: 16065731808124965111, + rseed: [ + 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, + 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, + 0x71, 0x8c, 0x29, 0xdd, + ], + memo: [ + 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, + 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, + 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, + 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, + 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, + 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, + 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, + 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, + 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, + 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, + 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, + 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, + 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, + 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, + 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, + 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, + 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, + 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, + 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, + 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, + 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, + 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, + 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, + 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, + 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, + 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, + 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, + 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, + 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, + 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, + 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, + 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, + 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, + 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, + 0xb6, 0x50, 0x82, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x54, 0xb6, 0x99, 0x64, 0x13, 0x6b, 0x63, 0xd1, 0x7d, 0x62, 0x44, 0x1a, 0x69, 0x37, + 0x13, 0x9d, 0x2c, 0xe1, 0x4b, 0xb5, 0x5c, 0x42, 0x07, 0xfe, 0x74, 0xd7, 0x70, 0x83, + 0x53, 0x51, 0x5b, 0xa8, + ], + rho: [ + 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, + 0x51, 0x1c, 0x9b, 0xab, 0x65, 0xb6, 0xd8, 0xd5, 0xc5, 0xbd, 0x1e, 0x32, 0x77, 0x1a, + 0xb6, 0xf6, 0x4c, 0x26, + ], + cmx: [ + 0x40, 0x8f, 0x59, 0x4f, 0xdd, 0xc5, 0x0c, 0x67, 0xf5, 0x47, 0xe1, 0xeb, 0x3e, 0xa2, + 0x99, 0xa3, 0x1f, 0x69, 0xf5, 0x7f, 0xc9, 0x92, 0x03, 0x01, 0x42, 0x90, 0x35, 0xa6, + 0xc2, 0x49, 0x79, 0x1a, + ], + esk: [ + 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, 0xef, 0x08, 0xbd, 0xf6, + 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, 0xf5, 0x3b, 0x57, 0xc3, + 0x45, 0xa9, 0x87, 0x2f, + ], + ephemeral_key: [ + 0xa5, 0xc8, 0x0a, 0x29, 0xf2, 0xec, 0xdd, 0xd7, 0x01, 0x96, 0xef, 0x45, 0x9e, 0xd5, + 0x03, 0xc4, 0xb3, 0xc2, 0x22, 0x8d, 0x10, 0xcc, 0xbc, 0xad, 0x9a, 0x28, 0x23, 0x30, + 0x07, 0x7b, 0xca, 0x0c, + ], + shared_secret: [ + 0x37, 0x14, 0x15, 0xfc, 0x1e, 0x98, 0x42, 0xa1, 0x26, 0xa3, 0x7a, 0xa7, 0x7b, 0x8f, + 0x0f, 0x1a, 0xb6, 0x48, 0xa3, 0xf7, 0x43, 0x57, 0x34, 0x89, 0x6f, 0x07, 0x59, 0x52, + 0xe7, 0xd1, 0x60, 0x17, + ], + k_enc: [ + 0xd7, 0x36, 0xf0, 0x3c, 0x81, 0x2d, 0x9b, 0xf9, 0x54, 0xff, 0xd2, 0x41, 0x84, 0x07, + 0xf3, 0x36, 0xa5, 0xf9, 0x69, 0x8b, 0x62, 0x85, 0x23, 0x2f, 0x5c, 0x85, 0xf0, 0xd1, + 0x1d, 0x5e, 0x9d, 0x0a, + ], + p_enc: [ + 0x03, 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, 0xf7, 0x90, + 0xfb, 0xa7, 0xf5, 0xf1, 0xf4, 0xde, 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, + 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, + 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, 0x71, 0x8c, 0x29, 0xdd, 0xdf, 0xfd, 0x79, 0xa9, + 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, 0x01, 0xe2, 0x99, 0x0a, + 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, 0xfd, 0x7d, 0x05, 0x8a, + 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, + 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, + 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, + 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, + 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, + 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, + 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, + 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, + 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, + 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, + 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, + 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, + 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, + 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, + 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, + 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, + 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, + 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, + 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, + 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, + 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, + 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, + 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, + 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, + 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, + 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, + 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, + 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, + 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, + 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, + 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, + 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, + 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, + 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, + 0xb6, 0x50, 0x82, 0xa6, + ], + c_enc: [ + 0xfc, 0x90, 0xcb, 0xe1, 0xcd, 0x9f, 0x59, 0x9a, 0x1a, 0x24, 0xc7, 0xa3, 0xea, 0xf6, + 0x07, 0xd9, 0x13, 0xbf, 0x48, 0xbd, 0xc1, 0xa4, 0x6d, 0xf7, 0xb1, 0x74, 0x7f, 0x12, + 0x60, 0x64, 0x49, 0x4b, 0xf5, 0x39, 0x61, 0xe9, 0xa5, 0xa2, 0xb9, 0x69, 0x80, 0x57, + 0x63, 0x44, 0x2e, 0x2c, 0x38, 0x8d, 0x21, 0x2d, 0x74, 0x84, 0x6e, 0x57, 0x27, 0x87, + 0x2d, 0x06, 0x3f, 0xc9, 0x94, 0xa4, 0x4f, 0x9e, 0xb6, 0x55, 0x25, 0xd6, 0x8f, 0x98, + 0x24, 0xa6, 0x03, 0x75, 0xfe, 0x43, 0xc0, 0x5f, 0x08, 0xfe, 0x45, 0x42, 0xa7, 0xe4, + 0x0c, 0x03, 0x8d, 0xe7, 0x10, 0x85, 0x01, 0x17, 0x95, 0x1b, 0x9a, 0x32, 0x1e, 0xea, + 0x4f, 0x8c, 0x91, 0xc0, 0x1d, 0x39, 0xdb, 0xb5, 0xd4, 0x12, 0x40, 0xf8, 0xb1, 0xb1, + 0xdb, 0xb3, 0x3f, 0x45, 0x87, 0x87, 0xdb, 0x8c, 0xda, 0x06, 0x9b, 0x64, 0x5a, 0x76, + 0x38, 0xc2, 0xec, 0xca, 0xd3, 0xd9, 0xa7, 0x39, 0xd6, 0x4c, 0x9a, 0xd5, 0xd5, 0xb3, + 0xa0, 0x24, 0x55, 0xa4, 0xec, 0xd6, 0x96, 0x7c, 0xf3, 0xb3, 0x3b, 0xf0, 0x4e, 0xf6, + 0xdd, 0x88, 0x10, 0xe1, 0x0c, 0x25, 0x86, 0xf7, 0x89, 0x32, 0x44, 0xea, 0x72, 0x80, + 0xd1, 0x34, 0xcf, 0x37, 0xb3, 0xdc, 0x0c, 0x32, 0x82, 0x3b, 0x1a, 0x29, 0xc5, 0x0c, + 0xa6, 0x48, 0x31, 0xd8, 0x4e, 0xbd, 0xf5, 0xe0, 0x1c, 0x14, 0xca, 0x36, 0x05, 0xbe, + 0x02, 0xf1, 0x5f, 0x31, 0x57, 0x90, 0xf7, 0x4e, 0x20, 0x57, 0x7f, 0x92, 0x39, 0x51, + 0x2f, 0xbd, 0xdd, 0x67, 0x63, 0x77, 0xae, 0x50, 0xc3, 0xfe, 0x71, 0xc9, 0x30, 0xa8, + 0x29, 0x57, 0xd1, 0x54, 0x70, 0xeb, 0x1b, 0x55, 0xb2, 0x0c, 0xe5, 0x02, 0x35, 0x64, + 0xfe, 0xa7, 0xe1, 0x81, 0xbe, 0x04, 0xa9, 0x33, 0xa7, 0xa3, 0xa1, 0x11, 0x89, 0x4d, + 0xec, 0xf7, 0x2a, 0x56, 0x54, 0xcb, 0x4e, 0xac, 0x32, 0xe1, 0xd5, 0x96, 0xad, 0x99, + 0x1a, 0x2f, 0x4c, 0x62, 0xe8, 0xe2, 0x82, 0x57, 0x13, 0x7b, 0xcb, 0xa5, 0x03, 0xdc, + 0x91, 0xed, 0x9e, 0x90, 0xb3, 0x08, 0xcd, 0xa5, 0xcc, 0xcc, 0xc9, 0xd1, 0x4e, 0xa6, + 0xd0, 0x3b, 0x3d, 0xec, 0xa1, 0x57, 0xd5, 0x30, 0xde, 0x63, 0x1e, 0x1e, 0x45, 0x8f, + 0x6a, 0x60, 0x8e, 0x1f, 0x9d, 0x57, 0x9b, 0x6e, 0xe6, 0x00, 0x5c, 0xd0, 0xa8, 0xc3, + 0xe2, 0xdf, 0x89, 0x46, 0x8a, 0xcf, 0xb4, 0x36, 0xcb, 0x59, 0x84, 0x56, 0xf0, 0x38, + 0x95, 0x5d, 0xc6, 0xb4, 0x07, 0xec, 0x33, 0x00, 0xa5, 0xcf, 0xcd, 0xc8, 0x45, 0x47, + 0xe3, 0xef, 0xe9, 0xfc, 0xa1, 0x7e, 0xd2, 0xc2, 0x74, 0xf0, 0x03, 0x0b, 0x63, 0xcc, + 0x42, 0xe2, 0x38, 0x94, 0xa5, 0xf2, 0x53, 0x66, 0xcb, 0xc3, 0xbf, 0xcb, 0x77, 0x2d, + 0x04, 0x17, 0xf6, 0x24, 0x4b, 0x2f, 0xd8, 0x17, 0xc4, 0xc6, 0x79, 0x06, 0xc3, 0x38, + 0x4d, 0x69, 0xd7, 0x93, 0xef, 0xca, 0x6e, 0x5d, 0x6a, 0xf2, 0x5e, 0x4e, 0xbc, 0x0f, + 0x53, 0x56, 0xeb, 0x74, 0x28, 0x85, 0x19, 0xe8, 0xf4, 0x49, 0x38, 0xeb, 0xf9, 0xb2, + 0x5b, 0xe5, 0x85, 0xe1, 0x35, 0x1f, 0x62, 0x59, 0x6c, 0x31, 0x79, 0xca, 0xe4, 0x5e, + 0x75, 0x49, 0xd7, 0xfb, 0xb5, 0x91, 0x3b, 0xe9, 0xc3, 0xba, 0xa5, 0x7c, 0xab, 0x7c, + 0xd4, 0xb5, 0x67, 0x12, 0x8d, 0x1b, 0xa5, 0x20, 0x31, 0xd7, 0xd5, 0xa5, 0xbd, 0x69, + 0xde, 0x61, 0x4a, 0xbb, 0x8c, 0xa3, 0x8a, 0x94, 0x51, 0xcd, 0x1b, 0xad, 0xd9, 0x71, + 0xb3, 0xf1, 0xb0, 0xb5, 0x0c, 0x7f, 0x21, 0xbf, 0xc4, 0x23, 0x04, 0xa4, 0xa5, 0x3e, + 0x0d, 0x55, 0x92, 0x0d, 0xa0, 0x53, 0x27, 0x14, 0x79, 0x13, 0x45, 0xfb, 0x07, 0x4c, + 0x66, 0xc4, 0xb7, 0xc9, 0x89, 0x28, 0x30, 0xf9, 0x62, 0x09, 0xb8, 0x1c, 0x26, 0xd1, + 0x74, 0xf8, 0xa9, 0x33, 0xc3, 0x77, 0x9d, 0x97, 0x88, 0x55, 0x3f, 0x6e, 0xeb, 0x21, + 0xf7, 0xdb, 0x57, 0x78, 0xf4, 0xf8, 0x17, 0x4c, 0xb4, 0x6f, 0x71, 0xfd, 0xdc, 0x4b, + 0xe4, 0xd8, 0x70, 0x3e, 0xbf, 0xbc, 0xd2, 0xa7, 0x72, 0x89, 0xee, 0xfa, 0x72, 0x76, + 0x56, 0x74, 0xdb, 0xf0, 0xe0, 0x65, 0xff, 0xcb, 0xf6, 0xbb, 0xa0, 0x18, 0x09, 0x1e, + 0x49, 0xaa, 0x90, 0xe6, 0x02, 0xc8, + ], + ock: [ + 0x59, 0xf9, 0xcc, 0x26, 0x38, 0x4c, 0x6f, 0x73, 0xce, 0xa9, 0xb9, 0xe0, 0x94, 0x40, + 0xf8, 0xf0, 0x4c, 0x40, 0x25, 0xb5, 0x59, 0x04, 0x42, 0x3c, 0x35, 0x39, 0xc6, 0x6c, + 0x75, 0x11, 0x31, 0x23, + ], + op: [ + 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, + 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, + 0x25, 0xc8, 0xd6, 0xae, 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, + 0xef, 0x08, 0xbd, 0xf6, 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, + 0xf5, 0x3b, 0x57, 0xc3, 0x45, 0xa9, 0x87, 0x2f, + ], + c_out: [ + 0x21, 0xe3, 0xf8, 0x97, 0xe1, 0xb1, 0x36, 0xe1, 0x74, 0xd7, 0xae, 0x88, 0xd7, 0x85, + 0xa0, 0x61, 0xe6, 0x71, 0xef, 0xf1, 0x81, 0x98, 0x0a, 0x6f, 0xf5, 0x19, 0xb3, 0xbb, + 0x6b, 0xbd, 0xaf, 0xea, 0x9d, 0xf9, 0x92, 0xbc, 0xaa, 0xc0, 0x2b, 0xdb, 0xcd, 0x4d, + 0xb1, 0xc1, 0xd3, 0xf3, 0x2d, 0xef, 0xcd, 0xf7, 0xf4, 0xad, 0x54, 0x1b, 0x6b, 0xee, + 0xe8, 0x27, 0xdd, 0x43, 0x89, 0xb8, 0x57, 0xd1, 0x6d, 0xb8, 0x24, 0xe7, 0x72, 0xba, + 0x5a, 0xb5, 0xe2, 0x8d, 0xd6, 0xe9, 0x80, 0x82, 0x6b, 0xed, + ], + note_type: Some([ + 0xdf, 0xfd, 0x79, 0xa9, 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, + 0x01, 0xe2, 0x99, 0x0a, 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, + 0xfd, 0x7d, 0x05, 0x8a, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0x8c, 0x45, 0x43, 0xe1, 0x1f, 0x9f, 0x30, 0x7e, 0xc9, 0x04, 0x31, 0x61, 0x29, 0x46, + 0xfb, 0x01, 0x81, 0xb3, 0x6e, 0x1b, 0x52, 0xdb, 0x43, 0x1e, 0x6d, 0xf9, 0x38, 0x8c, + 0xac, 0xd3, 0x08, 0xe8, 0x99, 0xd9, 0x3f, 0x70, 0xad, 0x2a, 0xea, 0xec, 0x99, 0x5e, + 0xcc, 0xe1, 0x80, 0x1c, 0x61, 0x56, 0xe2, 0x3e, 0xc4, 0x1b, 0x1a, 0xe1, 0xcd, 0x2f, + 0xd6, 0xe3, 0x9b, 0x69, 0x98, 0x2f, 0x46, 0x33, + ], + ovk: [ + 0x01, 0x76, 0xae, 0x33, 0x93, 0x25, 0xd5, 0xa5, 0x88, 0xda, 0x57, 0x96, 0xfa, 0xae, + 0x5b, 0xab, 0x7c, 0x82, 0x97, 0x7c, 0x0f, 0xf7, 0x97, 0x09, 0x3e, 0x2c, 0x1f, 0x3a, + 0xe8, 0x55, 0xf6, 0x5a, + ], + default_d: [ + 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, + ], + default_pk_d: [ + 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, + 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, + 0x36, 0x34, 0xb0, 0x23, + ], + v: 3775288302605163507, + rseed: [ + 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, + 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, + 0x3e, 0xcd, 0xd7, 0x99, + ], + memo: [ + 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, + 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, + 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, + 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, + 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, + 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, + 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, + 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, + 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, + 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, + 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, + 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, + 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, + 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, + 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, + 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, + 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, + 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, + 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, + 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, + 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, + 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, + 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, + 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, + 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, + 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, + 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, + 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, + 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, + 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, + 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, + 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, + 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, + 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, + 0x6e, 0x67, 0x57, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x10, 0xb2, 0x33, 0xd2, 0x49, 0x94, 0x68, 0xe0, 0xb0, 0xdf, 0x47, 0x3d, 0x5a, 0x21, + 0xb9, 0x3f, 0x7d, 0x2b, 0x5d, 0x5f, 0x09, 0x95, 0xa9, 0x55, 0xd0, 0x86, 0x8a, 0x27, + 0x45, 0x3f, 0x96, 0x82, + ], + rho: [ + 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, + 0xe0, 0xe8, 0x14, 0x11, 0x94, 0x7e, 0x9e, 0x69, 0xb7, 0x19, 0xfa, 0xb7, 0x41, 0x72, + 0x1d, 0x40, 0x9b, 0x33, + ], + cmx: [ + 0x9e, 0x3d, 0x61, 0x35, 0x6b, 0x0d, 0x88, 0x95, 0x9e, 0x3f, 0x0f, 0xcc, 0x4a, 0x93, + 0x2e, 0x93, 0x2e, 0xac, 0xbc, 0x80, 0x1d, 0x48, 0xc0, 0x19, 0x5b, 0x9c, 0x8b, 0xd1, + 0x05, 0x5a, 0x8e, 0x2e, + ], + esk: [ + 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, 0xa9, 0x19, 0xa2, 0x06, + 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, 0x25, 0xec, 0xff, 0x47, + 0x72, 0x16, 0x8c, 0x05, + ], + ephemeral_key: [ + 0xc1, 0xce, 0x25, 0xfb, 0x89, 0xe5, 0xca, 0x89, 0x97, 0xf9, 0xb4, 0xbb, 0x0e, 0x1e, + 0xfb, 0xcc, 0x1a, 0x8c, 0xbf, 0x44, 0xec, 0xfd, 0x33, 0x2c, 0x6c, 0x5c, 0x17, 0x3b, + 0xb1, 0x1f, 0xb5, 0x87, + ], + shared_secret: [ + 0x2e, 0xe5, 0x69, 0xce, 0xb3, 0xfd, 0xb8, 0x67, 0xa5, 0xd8, 0x4c, 0x92, 0x68, 0x24, + 0xef, 0x54, 0x9f, 0x2d, 0xd2, 0x8f, 0x8b, 0x04, 0x8d, 0x67, 0xd0, 0x28, 0x81, 0x7d, + 0xbf, 0xf5, 0xd2, 0xb1, + ], + k_enc: [ + 0x41, 0x4d, 0x80, 0x67, 0xc9, 0xfe, 0xbd, 0x5e, 0xbc, 0xd9, 0xae, 0x8c, 0x05, 0x99, + 0x4e, 0x3b, 0x06, 0x85, 0xc8, 0x86, 0x6f, 0x88, 0x95, 0x94, 0xc3, 0x74, 0xb3, 0x75, + 0xac, 0x2c, 0x6d, 0x24, + ], + p_enc: [ + 0x03, 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, 0xf3, 0xdb, + 0x77, 0x79, 0xb5, 0x84, 0x64, 0x34, 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, + 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, + 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, 0x3e, 0xcd, 0xd7, 0x99, 0xa6, 0x33, 0x05, 0x44, + 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, 0x5a, 0x31, 0xf6, 0x2e, + 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, 0xb4, 0x42, 0x68, 0x3c, + 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, + 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, + 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, + 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, + 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, + 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, + 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, + 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, + 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, + 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, + 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, + 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, + 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, + 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, + 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, + 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, + 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, + 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, + 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, + 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, + 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, + 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, + 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, + 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, + 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, + 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, + 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, + 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, + 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, + 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, + 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, + 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, + 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, + 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, + 0x6e, 0x67, 0x57, 0x61, + ], + c_enc: [ + 0xbc, 0x8a, 0x16, 0xfd, 0x57, 0xbc, 0x03, 0x60, 0x59, 0xe5, 0x4d, 0xc2, 0xbc, 0xfa, + 0xad, 0x9c, 0xc1, 0xfa, 0xe8, 0xcb, 0x2b, 0xe2, 0xa0, 0xc8, 0x5e, 0x81, 0x6c, 0x67, + 0xfd, 0xcd, 0x0b, 0x93, 0xe6, 0xa1, 0xed, 0xc8, 0x3b, 0xfa, 0xc4, 0x1e, 0xb4, 0x19, + 0x1c, 0x56, 0x4b, 0xac, 0x58, 0x01, 0x62, 0x92, 0x2d, 0x88, 0x25, 0x30, 0x28, 0xeb, + 0x88, 0xed, 0x46, 0xbf, 0x24, 0x2d, 0x82, 0x28, 0x6c, 0xb0, 0xa5, 0x66, 0xce, 0x01, + 0x18, 0x09, 0x4c, 0x90, 0x8f, 0xc2, 0x68, 0xb3, 0x2b, 0xcb, 0xdc, 0x4c, 0x22, 0x82, + 0xc5, 0x24, 0x2a, 0x65, 0x15, 0x48, 0x8b, 0x83, 0x3d, 0x29, 0x8e, 0x49, 0xda, 0x33, + 0x3a, 0xdd, 0x96, 0xc9, 0x9b, 0x98, 0xac, 0x06, 0x7f, 0x21, 0x41, 0x28, 0x9a, 0xcd, + 0x89, 0x49, 0x64, 0xfc, 0xf8, 0x94, 0xc9, 0x26, 0xf1, 0x81, 0xb1, 0x19, 0x85, 0x68, + 0xb1, 0xdd, 0x6f, 0x5e, 0xd1, 0x22, 0xdc, 0x70, 0x44, 0xad, 0x96, 0x76, 0xa7, 0xc5, + 0xae, 0x8e, 0xa9, 0x0f, 0x64, 0xbc, 0x59, 0x09, 0x36, 0xe0, 0xdf, 0x53, 0x1c, 0x1b, + 0x94, 0xb7, 0x35, 0xcd, 0x7b, 0x18, 0x73, 0xc8, 0x51, 0x6f, 0xea, 0x83, 0x64, 0x91, + 0x40, 0xbc, 0xbb, 0x9b, 0x42, 0xea, 0x6c, 0xb7, 0xaf, 0x67, 0xdc, 0x2d, 0xdb, 0xb4, + 0x7a, 0xb2, 0x25, 0xe7, 0x98, 0x29, 0xcd, 0xaf, 0x77, 0x04, 0xfb, 0x56, 0x5b, 0x43, + 0x91, 0x76, 0xf3, 0x35, 0xe4, 0x2b, 0x64, 0xc1, 0x6d, 0xdf, 0xe0, 0x88, 0x45, 0x38, + 0xbf, 0x43, 0x33, 0xe3, 0x2c, 0xa1, 0xe6, 0x27, 0x41, 0xc3, 0xe7, 0x4c, 0x8f, 0xaa, + 0xde, 0x0d, 0x89, 0xfa, 0x10, 0x30, 0xcd, 0x8e, 0xfd, 0x20, 0x22, 0x3e, 0x41, 0xc3, + 0xfc, 0xca, 0xaa, 0xe7, 0x76, 0xe6, 0x8e, 0xe8, 0x40, 0x56, 0x6f, 0x4d, 0x13, 0xc1, + 0xc9, 0xd5, 0xcb, 0xbe, 0xcf, 0xa7, 0x49, 0x9d, 0x43, 0x12, 0x7c, 0xe8, 0xfd, 0x83, + 0xdb, 0x6e, 0x89, 0x67, 0x90, 0x32, 0x25, 0x24, 0x87, 0x21, 0x40, 0x0d, 0x5e, 0x3e, + 0xc0, 0xc1, 0x8e, 0x10, 0xf5, 0xe6, 0x6e, 0x10, 0x17, 0x0c, 0xb3, 0x74, 0x48, 0x22, + 0x4a, 0xde, 0x39, 0x9f, 0x1d, 0x74, 0xa2, 0x16, 0x7d, 0x9f, 0xdb, 0xfe, 0x36, 0xe1, + 0x28, 0xe4, 0x8c, 0x01, 0x62, 0x61, 0x16, 0xc1, 0xa2, 0xdf, 0x3c, 0xb0, 0x23, 0xd8, + 0x0a, 0xed, 0x9b, 0xfc, 0x02, 0x71, 0xb8, 0x1f, 0xf9, 0x79, 0x81, 0x01, 0x6f, 0xff, + 0x19, 0x61, 0x08, 0x88, 0x8b, 0xcb, 0xca, 0x84, 0x5b, 0x5d, 0x97, 0x1b, 0xd5, 0x4f, + 0x49, 0x7d, 0x3f, 0x3a, 0x09, 0x29, 0x9e, 0x56, 0x50, 0xd3, 0x26, 0xd8, 0x9b, 0x9a, + 0x5e, 0xff, 0x3e, 0xbd, 0x27, 0x39, 0x34, 0xc4, 0x9f, 0x81, 0x46, 0x7e, 0xb8, 0x4f, + 0x56, 0x98, 0x90, 0xcf, 0x89, 0x05, 0xb7, 0x4c, 0xd3, 0xed, 0xa6, 0x3c, 0x53, 0x88, + 0xd5, 0x51, 0x5e, 0x3f, 0xd8, 0x1c, 0x70, 0xc1, 0x5e, 0x2a, 0x98, 0x2d, 0x59, 0x0e, + 0x87, 0xb8, 0x64, 0x45, 0x4b, 0xcd, 0xf5, 0xf8, 0x4d, 0x9f, 0x11, 0xcb, 0x9c, 0xf2, + 0xb5, 0xde, 0x3c, 0x5e, 0x0e, 0x2a, 0x6c, 0x48, 0x16, 0x61, 0x64, 0x96, 0x6f, 0xb9, + 0x0d, 0xac, 0xf8, 0x67, 0x4f, 0x9f, 0x1a, 0x34, 0xd2, 0xcd, 0xc7, 0xc9, 0x48, 0xab, + 0x99, 0xc3, 0x58, 0xa1, 0x95, 0x47, 0x0a, 0xdd, 0x06, 0x5e, 0xaf, 0x79, 0x24, 0xfa, + 0xed, 0x63, 0x27, 0xa6, 0x10, 0xf5, 0x2e, 0xd5, 0xd3, 0xa8, 0x7e, 0x11, 0xb5, 0x97, + 0x4f, 0xa0, 0x60, 0x45, 0xa4, 0x08, 0x95, 0xcd, 0xad, 0x60, 0x1c, 0xae, 0x01, 0xed, + 0xda, 0x17, 0x52, 0x81, 0x62, 0xd7, 0x21, 0x24, 0xf2, 0x05, 0x6b, 0x9a, 0xb8, 0xc0, + 0xc0, 0xf5, 0xc6, 0xdd, 0xaa, 0x0f, 0x5e, 0x33, 0xfb, 0x04, 0x23, 0x0b, 0x61, 0x1b, + 0xff, 0xd8, 0xbd, 0xdc, 0x63, 0x4c, 0x79, 0x60, 0xa3, 0xd4, 0xe6, 0x8f, 0x21, 0xe7, + 0x83, 0x04, 0xe4, 0xc4, 0xd2, 0xdc, 0xd6, 0xa1, 0x9c, 0xfc, 0x04, 0x57, 0x97, 0x09, + 0xf0, 0x33, 0xf1, 0x95, 0x78, 0xae, 0x7f, 0x0b, 0xc6, 0x46, 0x32, 0xa6, 0xd7, 0xda, + 0x40, 0xdc, 0x0c, 0x38, 0x3b, 0xca, 0xa8, 0x68, 0x6a, 0xc8, 0x49, 0x3b, 0x2c, 0xb8, + 0xf1, 0xd7, 0xd3, 0x95, 0x8a, 0x54, + ], + ock: [ + 0xdb, 0x1e, 0xf1, 0x9a, 0xf6, 0xdd, 0x1b, 0x7b, 0xf0, 0x64, 0x89, 0xe7, 0xdb, 0x86, + 0xca, 0xae, 0x27, 0xf6, 0x70, 0x1e, 0x09, 0x16, 0x8c, 0x6e, 0x0d, 0x2b, 0x89, 0x78, + 0xdf, 0x14, 0xe0, 0x96, + ], + op: [ + 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, + 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, + 0x36, 0x34, 0xb0, 0x23, 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, + 0xa9, 0x19, 0xa2, 0x06, 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, + 0x25, 0xec, 0xff, 0x47, 0x72, 0x16, 0x8c, 0x05, + ], + c_out: [ + 0x55, 0xdd, 0xba, 0xc4, 0x35, 0x64, 0x19, 0x54, 0xbd, 0xb1, 0xc9, 0x43, 0x4c, 0x36, + 0x79, 0x32, 0x19, 0x18, 0xbc, 0x1f, 0x29, 0x90, 0x7a, 0xc4, 0x24, 0x43, 0x55, 0x2d, + 0xfb, 0xe7, 0x05, 0xab, 0x26, 0x19, 0x1b, 0x4e, 0x2b, 0xae, 0xa4, 0xaa, 0xe0, 0x6d, + 0xa9, 0xf1, 0x38, 0x4e, 0x23, 0x7b, 0xee, 0xab, 0xb1, 0xa2, 0xd8, 0x22, 0x99, 0x5e, + 0xe7, 0xb9, 0x41, 0x0d, 0x6b, 0xe7, 0x59, 0x2a, 0xed, 0xa9, 0xf5, 0x2d, 0x56, 0xd8, + 0xc9, 0xf9, 0x3a, 0x0b, 0xe3, 0x8c, 0xfc, 0x8d, 0xc2, 0x94, + ], + note_type: Some([ + 0xa6, 0x33, 0x05, 0x44, 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, + 0x5a, 0x31, 0xf6, 0x2e, 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, + 0xb4, 0x42, 0x68, 0x3c, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0x47, 0x30, 0x68, 0xbf, 0x68, 0xe5, 0x0b, 0xe3, 0x85, 0x7d, 0xec, 0xb2, 0xef, 0xd5, + 0xde, 0x20, 0xea, 0xc8, 0x1b, 0x37, 0x5b, 0xd0, 0xbb, 0xe8, 0x36, 0x86, 0x6e, 0x99, + 0x36, 0x3b, 0x37, 0x50, 0x9d, 0x53, 0x8f, 0xcc, 0xa9, 0x33, 0x37, 0xad, 0xbc, 0x24, + 0x81, 0xe2, 0x70, 0x26, 0x18, 0x4c, 0x3f, 0x4f, 0x48, 0xcc, 0x5d, 0x5a, 0x0e, 0x4a, + 0x4c, 0xfa, 0x4d, 0x6a, 0x24, 0x7f, 0x2e, 0x39, + ], + ovk: [ + 0x25, 0xb4, 0xc2, 0x6e, 0xb0, 0x3f, 0x71, 0x66, 0x46, 0x61, 0x9a, 0xf0, 0x24, 0x56, + 0xae, 0x69, 0x59, 0x62, 0xfe, 0x5e, 0x93, 0x1a, 0x63, 0xb5, 0xc7, 0x90, 0x52, 0xec, + 0xd3, 0x33, 0xe1, 0x84, + ], + default_d: [ + 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, + ], + default_pk_d: [ + 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, + 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, + 0x34, 0xeb, 0x90, 0x2c, + ], + v: 15119422206032203650, + rseed: [ + 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, + 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, + 0x2d, 0x9b, 0x4c, 0x8f, + ], + memo: [ + 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, + 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, + 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, + 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, + 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, + 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, + 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, + 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, + 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, + 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, + 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, + 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, + 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, + 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, + 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, + 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, + 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, + 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, + 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, + 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, + 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, + 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, + 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, + 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, + 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, + 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, + 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, + 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, + 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, + 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, + 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, + 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, + 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, + 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, + 0x08, 0x74, 0x86, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x7e, 0xfd, 0xf4, 0x17, 0xcf, 0xd6, 0x44, 0x7d, 0x96, 0x58, 0x1d, 0xd1, 0x7b, 0x82, + 0x12, 0xee, 0x53, 0x7b, 0x13, 0x4b, 0x05, 0xa5, 0x58, 0x67, 0x4a, 0x39, 0xe6, 0x66, + 0x97, 0xe6, 0x3a, 0x29, + ], + rho: [ + 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, + 0x85, 0x72, 0xa3, 0x05, 0xfa, 0x3b, 0x70, 0x68, 0xa3, 0x78, 0x38, 0x27, 0xaf, 0xe2, + 0x14, 0x7a, 0x27, 0x10, + ], + cmx: [ + 0xf2, 0x04, 0x22, 0x51, 0xa0, 0x59, 0xa2, 0xf5, 0x8a, 0xb8, 0xe9, 0x0b, 0x52, 0x64, + 0xd0, 0xa4, 0x3f, 0x96, 0xd7, 0x7e, 0xdd, 0x54, 0xf8, 0x0f, 0xf4, 0x9d, 0x43, 0x86, + 0x81, 0x4d, 0x73, 0x2e, + ], + esk: [ + 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, 0x1d, 0xa4, 0xb1, 0x44, + 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, 0xaf, 0x2b, 0xd1, 0xa0, + 0x8c, 0x67, 0xd9, 0x3f, + ], + ephemeral_key: [ + 0x46, 0x73, 0x1f, 0xff, 0xc5, 0x9a, 0xf4, 0xc1, 0x28, 0x82, 0xbc, 0xca, 0xea, 0xa7, + 0xb8, 0xed, 0x39, 0x0b, 0x14, 0x66, 0x72, 0xe1, 0x36, 0x51, 0xc3, 0x2e, 0x57, 0x80, + 0x62, 0x68, 0x65, 0xa7, + ], + shared_secret: [ + 0x9d, 0x56, 0xbd, 0x96, 0x00, 0x39, 0x62, 0x5e, 0x11, 0x7d, 0x7b, 0xfe, 0xd4, 0x3a, + 0x57, 0x3b, 0x11, 0x51, 0x7f, 0xfa, 0x76, 0x14, 0xea, 0x2d, 0xa7, 0x7e, 0xdf, 0x62, + 0x7f, 0x6f, 0x13, 0xaa, + ], + k_enc: [ + 0x04, 0x2f, 0x92, 0x82, 0x13, 0x44, 0xde, 0x97, 0x7c, 0xee, 0x89, 0x9e, 0xd2, 0x1b, + 0xc8, 0x48, 0xf5, 0xc4, 0xfe, 0xdc, 0x39, 0xf2, 0xdf, 0xed, 0xad, 0x62, 0xcc, 0x7a, + 0x92, 0x7f, 0x74, 0xfd, + ], + p_enc: [ + 0x03, 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, 0x82, 0xcf, + 0xb3, 0xe7, 0x63, 0xfa, 0xd2, 0xd1, 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, + 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, + 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, 0x2d, 0x9b, 0x4c, 0x8f, 0x61, 0x16, 0xcf, 0xec, + 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, 0x6a, 0xe8, 0xf7, 0xcc, + 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, 0x38, 0xe1, 0x73, 0x29, + 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, + 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, + 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, + 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, + 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, + 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, + 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, + 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, + 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, + 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, + 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, + 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, + 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, + 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, + 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, + 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, + 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, + 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, + 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, + 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, + 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, + 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, + 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, + 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, + 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, + 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, + 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, + 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, + 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, + 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, + 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, + 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, + 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, + 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, + 0x08, 0x74, 0x86, 0x9c, + ], + c_enc: [ + 0x16, 0x76, 0x72, 0x3a, 0x18, 0xff, 0x58, 0x77, 0x70, 0x15, 0x8d, 0x6b, 0x85, 0x09, + 0x3c, 0x49, 0x20, 0x16, 0xf8, 0x7e, 0xc3, 0xfa, 0xe8, 0xb0, 0xb4, 0x7c, 0xd9, 0x29, + 0x8f, 0xa2, 0x07, 0xc4, 0xb6, 0x09, 0xc6, 0x92, 0xdd, 0xb9, 0x10, 0x19, 0x72, 0xc9, + 0x4c, 0x71, 0x87, 0x84, 0x85, 0x42, 0x1e, 0xfb, 0x70, 0x1c, 0xf5, 0x15, 0xa2, 0x3f, + 0xbf, 0x36, 0xfe, 0x93, 0x54, 0x0d, 0x82, 0xd6, 0x9a, 0x72, 0x62, 0x4e, 0x25, 0x4f, + 0xe3, 0xa0, 0x11, 0xc5, 0xdb, 0xdb, 0xd2, 0xbd, 0xff, 0xb8, 0x83, 0x8a, 0xf3, 0x7d, + 0x03, 0xce, 0x69, 0x12, 0x6b, 0x2f, 0x68, 0x21, 0x25, 0xb7, 0xa9, 0xb2, 0xa3, 0xee, + 0x11, 0x8a, 0xe5, 0xad, 0xb4, 0x60, 0xa4, 0x68, 0x7c, 0x24, 0x30, 0x18, 0x7b, 0xfd, + 0x0f, 0x6c, 0x2a, 0x3d, 0x5d, 0x74, 0x30, 0x1c, 0xbd, 0x8f, 0xd0, 0x26, 0xc8, 0x64, + 0x4f, 0xbf, 0xa2, 0x65, 0x69, 0x88, 0xe9, 0x58, 0x59, 0x0b, 0x81, 0x6a, 0x1e, 0x64, + 0x0e, 0x46, 0x71, 0x0e, 0x46, 0xfa, 0x15, 0x94, 0xff, 0x2a, 0x61, 0xd6, 0xf6, 0xe7, + 0xb4, 0xa9, 0xf6, 0xe0, 0xde, 0x68, 0x3d, 0x95, 0xe5, 0x9d, 0x43, 0x57, 0xf7, 0x9a, + 0xc4, 0x93, 0x86, 0x6d, 0xab, 0x06, 0x57, 0x76, 0xc0, 0xb1, 0x43, 0x6b, 0x8e, 0x04, + 0x47, 0x68, 0x43, 0xc2, 0x8b, 0x48, 0x45, 0xea, 0xff, 0x17, 0x83, 0xa8, 0x50, 0xc2, + 0x4a, 0x90, 0x65, 0xc3, 0x36, 0x51, 0xc4, 0xb3, 0xdd, 0x19, 0x92, 0xf4, 0xf2, 0x08, + 0xb8, 0x51, 0xbf, 0xff, 0xe9, 0xb7, 0xbb, 0x7a, 0xad, 0x76, 0x7c, 0x23, 0x60, 0xb0, + 0x5c, 0x11, 0x23, 0x09, 0x66, 0xda, 0x55, 0x7e, 0x31, 0x3a, 0xe6, 0x1c, 0x95, 0x42, + 0x97, 0x66, 0x10, 0x6b, 0x4b, 0x1b, 0x35, 0x47, 0x64, 0xe4, 0xe1, 0xe4, 0xdf, 0x90, + 0xc1, 0x2d, 0x24, 0x37, 0x9d, 0x67, 0xba, 0xc6, 0x66, 0x97, 0xaf, 0x23, 0x44, 0x97, + 0xf2, 0xd6, 0xf9, 0xa6, 0x12, 0x85, 0x0d, 0xd7, 0x1d, 0x1c, 0x98, 0xce, 0x65, 0xd8, + 0x50, 0x7f, 0xa3, 0x46, 0x35, 0x83, 0x12, 0x39, 0xe2, 0x10, 0xf7, 0xdb, 0xb3, 0x05, + 0x04, 0x2d, 0x47, 0x50, 0xd9, 0x5a, 0xdf, 0xff, 0xc9, 0x8d, 0xeb, 0x0f, 0x17, 0x13, + 0xbc, 0x01, 0xaf, 0x5d, 0xb5, 0x99, 0x29, 0x89, 0x76, 0xab, 0xba, 0xdb, 0x0f, 0x4d, + 0xed, 0x1a, 0x2f, 0xe4, 0xcf, 0x90, 0x60, 0x0e, 0x0d, 0x28, 0xd3, 0x07, 0xc6, 0x41, + 0xf7, 0x52, 0x3c, 0x16, 0x66, 0x40, 0x1d, 0x78, 0x6f, 0xd2, 0x4a, 0xe1, 0x68, 0x0f, + 0xe9, 0x26, 0x70, 0x4c, 0xb6, 0xe2, 0xaf, 0x80, 0x1a, 0x0d, 0x82, 0x75, 0x9d, 0xd8, + 0x7a, 0x8c, 0xd8, 0x7b, 0x85, 0xbb, 0x07, 0x51, 0xa7, 0x08, 0xc9, 0xf4, 0xa7, 0xd3, + 0x24, 0xe5, 0xc9, 0x3a, 0xd2, 0x2b, 0x86, 0x43, 0xdf, 0xfa, 0x5f, 0x50, 0x79, 0xfc, + 0x6f, 0x01, 0x6d, 0x94, 0x3c, 0x99, 0x09, 0x27, 0x5c, 0x96, 0xf5, 0xfe, 0x7b, 0x56, + 0x33, 0x3c, 0x24, 0x01, 0x99, 0x73, 0xd9, 0x4f, 0x06, 0xeb, 0xf6, 0xc0, 0xf6, 0xef, + 0xdd, 0x42, 0xea, 0xb0, 0x63, 0x49, 0xd5, 0xe8, 0xb9, 0x60, 0xba, 0x8c, 0x68, 0xee, + 0xfd, 0x44, 0x49, 0x99, 0xf6, 0xfa, 0x3d, 0x6a, 0x3a, 0xe3, 0x1a, 0xe8, 0x54, 0x6e, + 0xdc, 0x62, 0x78, 0x25, 0x63, 0x7e, 0x1e, 0x86, 0x39, 0x8d, 0x0e, 0xd3, 0xd8, 0x8b, + 0xfa, 0xea, 0x8b, 0x4b, 0x08, 0x50, 0xd8, 0xa8, 0x28, 0x6e, 0xa9, 0xf3, 0xd1, 0x3f, + 0xa8, 0xf4, 0x16, 0x53, 0x45, 0x1b, 0x97, 0xb3, 0x8b, 0x06, 0x3a, 0x5f, 0xc6, 0xdb, + 0xe4, 0xe9, 0x19, 0x94, 0x87, 0xc9, 0x73, 0xef, 0x8f, 0x2c, 0x26, 0x3f, 0x85, 0x05, + 0xf4, 0xc3, 0xbe, 0xc9, 0xd1, 0x79, 0xbb, 0xd6, 0x5d, 0x1e, 0xdc, 0x58, 0x95, 0xa1, + 0x6c, 0xc7, 0x98, 0x6b, 0xcf, 0xc4, 0xba, 0xe8, 0x7e, 0xc0, 0xb2, 0x9b, 0xf1, 0xb3, + 0x97, 0x61, 0x5c, 0x95, 0x13, 0xfa, 0x52, 0xeb, 0xe1, 0xe9, 0xfc, 0xfb, 0xf1, 0x92, + 0xed, 0x49, 0x26, 0x27, 0x27, 0xa0, 0x8a, 0xd3, 0xc2, 0x95, 0x5b, 0x3d, 0xf2, 0xee, + 0xad, 0x30, 0x24, 0x3e, 0x06, 0x66, 0xf2, 0x3c, 0x7f, 0x97, 0xe7, 0x84, 0xbe, 0x68, + 0xcc, 0x22, 0xca, 0x1d, 0x09, 0xd5, + ], + ock: [ + 0xcf, 0x22, 0xd2, 0x83, 0x95, 0x98, 0x5d, 0x31, 0x6a, 0xf9, 0x50, 0x19, 0x21, 0xba, + 0xc1, 0x52, 0x57, 0x11, 0xbb, 0x3f, 0x3c, 0xc3, 0xc3, 0xc2, 0x82, 0xa3, 0xd1, 0x8e, + 0x43, 0xd4, 0x78, 0x05, + ], + op: [ + 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, + 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, + 0x34, 0xeb, 0x90, 0x2c, 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, + 0x1d, 0xa4, 0xb1, 0x44, 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, + 0xaf, 0x2b, 0xd1, 0xa0, 0x8c, 0x67, 0xd9, 0x3f, + ], + c_out: [ + 0x7a, 0xe6, 0x91, 0xd9, 0xbc, 0xd5, 0x38, 0x42, 0x7b, 0x4f, 0x07, 0xe2, 0x38, 0x81, + 0x94, 0x18, 0xbb, 0xb8, 0x18, 0x31, 0x88, 0x89, 0x93, 0x08, 0xfd, 0x6a, 0xab, 0x2b, + 0xf4, 0xf0, 0x69, 0x9c, 0xc5, 0x61, 0x9c, 0x8d, 0x4f, 0xc9, 0x95, 0xc2, 0x11, 0x76, + 0xbf, 0xea, 0x13, 0xee, 0x04, 0x03, 0xc0, 0xce, 0x57, 0x4f, 0xc8, 0xfa, 0x16, 0x81, + 0xb3, 0x76, 0xcf, 0x33, 0xc9, 0xff, 0x27, 0xa5, 0xaa, 0x01, 0x58, 0x24, 0xe6, 0x78, + 0x6e, 0x16, 0xe3, 0x7b, 0x35, 0x5c, 0xf7, 0x54, 0x52, 0xdb, + ], + note_type: Some([ + 0x61, 0x16, 0xcf, 0xec, 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, + 0x6a, 0xe8, 0xf7, 0xcc, 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, + 0x38, 0xe1, 0x73, 0x29, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0xfc, 0x8c, 0x64, 0x1c, 0x0b, 0x28, 0xbe, 0xbf, 0x85, 0x24, 0x25, 0xae, 0x95, 0x5f, + 0xe6, 0x40, 0x1c, 0xfd, 0x9e, 0x60, 0x63, 0xf2, 0x50, 0x11, 0x3d, 0xa0, 0xb5, 0x8b, + 0x2a, 0x0f, 0x49, 0xb9, 0x12, 0x0b, 0x89, 0x9f, 0x08, 0x10, 0x6b, 0x30, 0x86, 0xb2, + 0xf4, 0x11, 0x63, 0x6f, 0x50, 0xab, 0x48, 0x7c, 0xfb, 0x28, 0x81, 0x89, 0x77, 0x8f, + 0xe4, 0xe5, 0xa1, 0x91, 0x8b, 0x98, 0xd5, 0x0a, + ], + ovk: [ + 0xbe, 0xd1, 0x7d, 0xf5, 0xf8, 0x88, 0xc8, 0xca, 0x14, 0x67, 0xae, 0x17, 0xdb, 0xbc, + 0xde, 0x31, 0xc1, 0x10, 0x5c, 0xb5, 0xbd, 0xa8, 0x8a, 0xc6, 0xc6, 0x27, 0x00, 0x2c, + 0xe2, 0x1c, 0x02, 0x14, + ], + default_d: [ + 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, + ], + default_pk_d: [ + 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, + 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, + 0x89, 0xcf, 0xf9, 0x1e, + ], + v: 7555450289479839818, + rseed: [ + 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, + 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, + 0x03, 0xaa, 0xe0, 0x4b, + ], + memo: [ + 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, + 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, + 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, + 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, + 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, + 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, + 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, + 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, + 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, + 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, + 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, + 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, + 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, + 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, + 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, + 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, + 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, + 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, + 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, + 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, + 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, + 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, + 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, + 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, + 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, + 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, + 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, + 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, + 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, + 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, + 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, + 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, + 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, + 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, + 0x6b, 0x21, 0x43, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0xf5, 0xc1, 0xcf, 0xbc, 0xb9, 0x2d, 0x34, 0xe4, 0x66, 0x1d, 0x58, 0x25, 0x42, 0xf7, + 0x0d, 0x05, 0x99, 0x09, 0x15, 0x20, 0xfe, 0x2a, 0xfa, 0xd8, 0xe8, 0x75, 0xca, 0x3b, + 0xcc, 0x70, 0x8a, 0x11, + ], + rho: [ + 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, + 0x4d, 0x4b, 0x32, 0x36, 0xdb, 0x1f, 0x32, 0xac, 0xa7, 0x94, 0x5c, 0xf2, 0x6e, 0xc8, + 0xb9, 0xd0, 0xb7, 0x32, + ], + cmx: [ + 0xe1, 0xc7, 0x67, 0xf3, 0x30, 0x15, 0xb5, 0xe2, 0x4a, 0x9a, 0xa5, 0x8b, 0x64, 0x7b, + 0x6b, 0x61, 0x32, 0x3c, 0xd3, 0x47, 0xe7, 0x21, 0x4c, 0x29, 0x1d, 0x09, 0x95, 0xc0, + 0xf5, 0xa6, 0x93, 0x2f, + ], + esk: [ + 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, 0x58, 0x93, 0x20, 0x26, + 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, 0x44, 0x72, 0x83, 0xf9, + 0x4e, 0xd5, 0x95, 0x3d, + ], + ephemeral_key: [ + 0xce, 0x67, 0x94, 0x31, 0x5f, 0x46, 0x2d, 0xed, 0xf3, 0xc5, 0x77, 0x4a, 0xac, 0x7f, + 0x3c, 0x7b, 0x70, 0xba, 0x7d, 0x72, 0x43, 0xbb, 0x0c, 0xc3, 0xb0, 0x67, 0xdc, 0x28, + 0x38, 0xf1, 0x11, 0xa3, + ], + shared_secret: [ + 0xea, 0x22, 0x6b, 0x69, 0xec, 0x2d, 0x9f, 0xcf, 0x91, 0x9c, 0xe5, 0x70, 0x06, 0x09, + 0x89, 0x94, 0xf7, 0x14, 0xb3, 0x9c, 0x34, 0x61, 0x52, 0xbc, 0x11, 0x51, 0xa0, 0xc6, + 0x9e, 0xe0, 0x04, 0x06, + ], + k_enc: [ + 0xb4, 0x56, 0x1b, 0xdb, 0xe0, 0xea, 0x44, 0x20, 0x75, 0xe7, 0xe6, 0x6f, 0xb3, 0xc0, + 0xfa, 0xd3, 0xaf, 0xc2, 0x85, 0x6e, 0xf4, 0xf3, 0x61, 0xb4, 0xac, 0x33, 0xaa, 0xe0, + 0x15, 0x52, 0xfd, 0x49, + ], + p_enc: [ + 0x03, 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, 0x4a, 0x70, + 0x91, 0xfe, 0x01, 0x5a, 0xda, 0x68, 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, + 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, + 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, 0x03, 0xaa, 0xe0, 0x4b, 0x29, 0x8a, 0xc0, 0xaf, + 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, 0x62, 0xcd, 0x1c, 0xa0, + 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, 0x82, 0x1a, 0x41, 0x84, + 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, + 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, + 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, + 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, + 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, + 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, + 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, + 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, + 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, + 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, + 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, + 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, + 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, + 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, + 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, + 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, + 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, + 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, + 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, + 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, + 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, + 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, + 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, + 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, + 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, + 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, + 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, + 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, + 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, + 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, + 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, + 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, + 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, + 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, + 0x6b, 0x21, 0x43, 0x0f, + ], + c_enc: [ + 0x59, 0x9a, 0x4d, 0x9f, 0x53, 0x3c, 0x46, 0xa9, 0x6f, 0x92, 0xaf, 0x8c, 0x08, 0xae, + 0x59, 0x71, 0x10, 0x23, 0x0e, 0xb8, 0x41, 0xc2, 0xf7, 0xc9, 0xd4, 0xf1, 0x45, 0x87, + 0x76, 0x36, 0xc8, 0x9d, 0xd8, 0xf3, 0x84, 0xa9, 0x40, 0xdc, 0x89, 0x72, 0x55, 0x53, + 0x57, 0xbc, 0x07, 0x48, 0x2a, 0x0a, 0x32, 0x3d, 0x87, 0xae, 0x10, 0xeb, 0x99, 0x82, + 0x5a, 0xe4, 0xe0, 0x06, 0x0e, 0x25, 0x6c, 0x3c, 0x3b, 0xeb, 0xa3, 0x2f, 0xa2, 0xb2, + 0xd2, 0x7f, 0x04, 0x6f, 0x7a, 0x93, 0x6d, 0xf8, 0xa9, 0x61, 0xc8, 0x18, 0x4e, 0xe3, + 0xc6, 0x8e, 0xbc, 0xe9, 0x80, 0x64, 0x45, 0xb4, 0x3e, 0x66, 0x67, 0x19, 0x95, 0xa2, + 0x43, 0x7a, 0x7f, 0x70, 0x91, 0x47, 0x14, 0x8a, 0x76, 0x03, 0x6d, 0x25, 0x5e, 0xba, + 0xc4, 0xd0, 0xd8, 0x34, 0x82, 0x93, 0x23, 0x9a, 0x78, 0x64, 0xe7, 0x9b, 0xef, 0xf7, + 0x6f, 0x61, 0x50, 0xe0, 0xc4, 0xf4, 0x7a, 0x85, 0x26, 0xe3, 0xed, 0x06, 0x75, 0xfa, + 0xc6, 0xac, 0xcc, 0x30, 0xa4, 0xd6, 0x73, 0xca, 0x80, 0x85, 0x95, 0x96, 0xfe, 0xc9, + 0xcd, 0x6a, 0x93, 0xfb, 0xa0, 0xe8, 0x9e, 0xf5, 0x3f, 0x3e, 0x26, 0x74, 0xd3, 0x2a, + 0x4b, 0x43, 0xf9, 0xa4, 0x38, 0x7d, 0xce, 0x33, 0xac, 0xa1, 0xe4, 0xff, 0xdc, 0x6d, + 0x2d, 0x31, 0x89, 0xc6, 0x23, 0xca, 0x56, 0x4d, 0x03, 0xac, 0x5b, 0x35, 0xb1, 0xa7, + 0x47, 0xff, 0x44, 0x6b, 0xc2, 0x5e, 0xd2, 0x2d, 0x09, 0x68, 0x2c, 0xef, 0x3a, 0x30, + 0xff, 0xa5, 0xc4, 0x0e, 0x27, 0x70, 0xf1, 0x84, 0x98, 0xb1, 0x2f, 0x86, 0x8b, 0xa9, + 0x2a, 0x13, 0xaa, 0x4f, 0xa2, 0x14, 0xb0, 0x62, 0xe3, 0x64, 0x9c, 0xf9, 0xc8, 0x5e, + 0x7a, 0x8a, 0x55, 0xf5, 0xf3, 0xdd, 0x68, 0x84, 0x2a, 0xea, 0x7c, 0x92, 0x79, 0x2a, + 0x52, 0x60, 0x0f, 0x86, 0x6c, 0x34, 0xa1, 0x0c, 0x51, 0x14, 0x13, 0x62, 0x02, 0x24, + 0xfb, 0x85, 0xaf, 0xc6, 0x06, 0xdd, 0x4f, 0x7b, 0x2f, 0x76, 0xbe, 0x76, 0x0c, 0xa1, + 0x94, 0xb6, 0xd4, 0x88, 0x2e, 0x5a, 0x4a, 0x76, 0x3d, 0x75, 0x0d, 0xb7, 0xe1, 0x68, + 0xa4, 0x18, 0x11, 0x92, 0x35, 0xda, 0xf9, 0xcb, 0x1b, 0xdb, 0x07, 0xff, 0x46, 0x83, + 0x3a, 0x87, 0xa3, 0x92, 0x6b, 0x14, 0xa5, 0x26, 0x4f, 0x10, 0x4f, 0x7f, 0x89, 0xf7, + 0x6f, 0x10, 0x10, 0x8f, 0x2b, 0x6e, 0xa5, 0x05, 0xd4, 0xf0, 0xd2, 0x6d, 0x58, 0x31, + 0x1c, 0xc7, 0x21, 0x9c, 0x6b, 0xc4, 0x38, 0xd0, 0xe1, 0xb3, 0x17, 0x60, 0x18, 0x73, + 0x9e, 0x6f, 0x75, 0xd0, 0x73, 0x59, 0xf5, 0xe8, 0x95, 0x7e, 0x12, 0xc3, 0x03, 0xaa, + 0x52, 0x9b, 0x11, 0xa1, 0x81, 0x66, 0x25, 0xa1, 0x20, 0xf3, 0x6d, 0xcd, 0xdd, 0xff, + 0x9c, 0x65, 0xbc, 0xac, 0x8f, 0x10, 0x67, 0xc7, 0xfe, 0x88, 0xf6, 0x44, 0x85, 0x94, + 0xcf, 0x1d, 0xff, 0x8e, 0x29, 0x00, 0xae, 0x84, 0xd2, 0xa7, 0xc8, 0x1b, 0x90, 0x6d, + 0xd0, 0xbc, 0x86, 0x96, 0xe3, 0x70, 0x98, 0x07, 0x4b, 0x75, 0xd8, 0x38, 0xd8, 0xab, + 0xdc, 0x90, 0x46, 0x08, 0x2b, 0xe4, 0xa6, 0x09, 0x95, 0xc4, 0xf4, 0xed, 0x80, 0xe2, + 0xd7, 0x87, 0x38, 0x25, 0x77, 0x3b, 0xa6, 0x3e, 0xe4, 0xcb, 0x97, 0x36, 0x9a, 0x50, + 0x70, 0xb5, 0x72, 0x5c, 0x5f, 0xeb, 0x32, 0x62, 0x45, 0x87, 0x80, 0x1e, 0x5a, 0xc0, + 0x30, 0xe6, 0x45, 0xbd, 0xf2, 0xe5, 0x86, 0xcf, 0x98, 0x66, 0xea, 0xfb, 0x76, 0xf5, + 0x59, 0x76, 0xa3, 0x3d, 0x62, 0xae, 0xdc, 0x76, 0x27, 0x78, 0x3b, 0x48, 0x48, 0x93, + 0x61, 0xf9, 0x9c, 0xae, 0xb1, 0xb1, 0x9c, 0x55, 0x22, 0x58, 0x9f, 0xd2, 0x1d, 0x51, + 0x45, 0x49, 0xd7, 0x4a, 0xb1, 0x92, 0x25, 0xed, 0x6e, 0x4c, 0x20, 0x3a, 0xdd, 0xfa, + 0x55, 0xfc, 0x9e, 0xc9, 0x89, 0xb6, 0x69, 0x02, 0x3c, 0xf3, 0x05, 0xb4, 0x2b, 0x33, + 0x0f, 0xc2, 0x30, 0x80, 0xab, 0xe4, 0x25, 0x01, 0xe5, 0x9c, 0x85, 0x1c, 0x54, 0xc7, + 0x49, 0x66, 0xf6, 0x0b, 0xe9, 0xdc, 0x56, 0x1a, 0x2d, 0x91, 0xf5, 0xd3, 0x2a, 0xdd, + 0x19, 0xb8, 0x9a, 0xca, 0x7a, 0x73, 0x85, 0x39, 0x59, 0x33, 0x48, 0x6f, 0xab, 0x00, + 0xcc, 0x53, 0x03, 0xc5, 0xf3, 0xf0, + ], + ock: [ + 0xe3, 0xf2, 0x74, 0x2e, 0xa1, 0x97, 0x55, 0xa7, 0x99, 0x73, 0x1a, 0xcf, 0xe9, 0x98, + 0x86, 0xfb, 0x9f, 0xbb, 0x80, 0x48, 0xb5, 0x3a, 0x77, 0x72, 0xa2, 0x80, 0xd8, 0x17, + 0x19, 0xff, 0xfd, 0x28, + ], + op: [ + 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, + 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, + 0x89, 0xcf, 0xf9, 0x1e, 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, + 0x58, 0x93, 0x20, 0x26, 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, + 0x44, 0x72, 0x83, 0xf9, 0x4e, 0xd5, 0x95, 0x3d, + ], + c_out: [ + 0x92, 0xe7, 0x7c, 0x9b, 0x69, 0x92, 0xee, 0x85, 0x06, 0x30, 0x6a, 0x96, 0xc8, 0xa5, + 0x1c, 0xc9, 0xa8, 0x96, 0x18, 0xc6, 0x36, 0x6f, 0xce, 0x78, 0xb2, 0x9a, 0xdb, 0x10, + 0x9b, 0x4a, 0x3b, 0x17, 0x48, 0x49, 0x13, 0x4f, 0x7a, 0xa2, 0x9c, 0x79, 0x1b, 0x91, + 0x5f, 0xd7, 0x5a, 0x6f, 0xfc, 0x57, 0x42, 0x78, 0xef, 0x50, 0x2b, 0x84, 0x02, 0x46, + 0x9a, 0xb5, 0xa7, 0xce, 0x77, 0x2b, 0x52, 0x2c, 0x4b, 0xaa, 0x12, 0x95, 0xd8, 0x8f, + 0x15, 0xdc, 0x75, 0x1d, 0xdf, 0x7d, 0x20, 0x8d, 0xd5, 0x17, + ], + note_type: Some([ + 0x29, 0x8a, 0xc0, 0xaf, 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, + 0x62, 0xcd, 0x1c, 0xa0, 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, + 0x82, 0x1a, 0x41, 0x84, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0x53, 0x3d, 0xc3, 0xd4, 0x93, 0xf2, 0xb8, 0x7a, 0x03, 0x3d, 0xf5, 0x07, 0x05, 0xf2, + 0x90, 0x54, 0x16, 0x38, 0xe9, 0x08, 0x7d, 0xcd, 0xbc, 0xfe, 0x52, 0x7e, 0x77, 0x5a, + 0xaf, 0x09, 0x30, 0x29, 0xac, 0xec, 0x74, 0xdd, 0xe6, 0x02, 0xfc, 0x7c, 0x73, 0xcb, + 0x38, 0x50, 0xbd, 0xfb, 0xf2, 0x61, 0x79, 0x4c, 0x9c, 0x29, 0x9d, 0x0b, 0x98, 0xee, + 0x0f, 0x20, 0x71, 0xd6, 0xd4, 0xe3, 0x7b, 0x05, + ], + ovk: [ + 0x32, 0x4d, 0xce, 0x2a, 0x1e, 0xa1, 0xe4, 0x30, 0x4f, 0x49, 0xe4, 0x3a, 0xe0, 0x65, + 0xe3, 0xfb, 0x19, 0x6f, 0x76, 0xd9, 0xb8, 0x79, 0xc7, 0x20, 0x08, 0x62, 0xea, 0xd1, + 0x8d, 0xea, 0x5f, 0xb6, + ], + default_d: [ + 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, + ], + default_pk_d: [ + 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, + 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, + 0xab, 0x00, 0xa0, 0x28, + ], + v: 12711846894898776584, + rseed: [ + 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, + 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, + 0xad, 0xe8, 0x24, 0xf3, + ], + memo: [ + 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, + 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, + 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, + 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, + 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, + 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, + 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, + 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, + 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, + 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, + 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, + 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, + 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, + 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, + 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, + 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, + 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, + 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, + 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, + 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, + 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, + 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, + 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, + 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, + 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, + 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, + 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, + 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, + 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, + 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, + 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, + 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, + 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, + 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, + 0x66, 0x17, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x65, 0x73, 0x3c, 0x9d, 0x97, 0xea, 0x82, 0xf6, 0xde, 0xf3, 0xde, 0x1f, 0xe8, 0x7e, + 0x12, 0x37, 0x6a, 0x92, 0x49, 0xdc, 0x86, 0x14, 0x67, 0x2d, 0x5e, 0xda, 0x15, 0xf3, + 0xca, 0xf4, 0x5b, 0x8c, + ], + rho: [ + 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, + 0x4f, 0xfb, 0xc2, 0x36, 0x9c, 0xb1, 0x48, 0xeb, 0x76, 0xf1, 0xed, 0xf1, 0xb5, 0xc7, + 0x41, 0x84, 0x28, 0x2a, + ], + cmx: [ + 0xd7, 0x60, 0xac, 0xdb, 0xca, 0xda, 0xd1, 0x88, 0x08, 0x4f, 0xe4, 0x1a, 0x5c, 0x03, + 0xc2, 0xc8, 0xce, 0x34, 0xe1, 0x5f, 0x9d, 0xf4, 0x7b, 0x86, 0x9c, 0x44, 0xc7, 0x21, + 0x13, 0xa4, 0x0c, 0x3d, + ], + esk: [ + 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, 0xdf, 0x7c, 0xe2, 0xd2, + 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, 0x86, 0x48, 0x56, 0x2c, + 0xbd, 0x86, 0x3f, 0x09, + ], + ephemeral_key: [ + 0x5a, 0x48, 0x58, 0x15, 0xc4, 0xa7, 0x47, 0x06, 0xe9, 0xde, 0x87, 0xfa, 0x60, 0xa2, + 0x81, 0x6f, 0x89, 0x0b, 0xe3, 0xdb, 0x54, 0xeb, 0x3f, 0x4b, 0xaf, 0x37, 0xdb, 0xc9, + 0xbd, 0xe5, 0xfe, 0x9d, + ], + shared_secret: [ + 0x96, 0x8d, 0xf2, 0xe8, 0x5d, 0x7b, 0xd1, 0x08, 0xf5, 0x72, 0x12, 0x53, 0x93, 0x76, + 0xaf, 0x25, 0x83, 0x2e, 0xf4, 0xdb, 0xd6, 0x40, 0x2a, 0x41, 0x4d, 0x73, 0xc5, 0x6b, + 0xee, 0xe4, 0xf2, 0xa8, + ], + k_enc: [ + 0xf7, 0x73, 0x91, 0x24, 0x3f, 0xdb, 0x35, 0xb2, 0x26, 0x94, 0xdb, 0x91, 0xde, 0xbd, + 0x78, 0x55, 0x79, 0x3c, 0xa7, 0x1e, 0x82, 0xbd, 0xc2, 0xee, 0x74, 0xc9, 0xb7, 0xb6, + 0x97, 0xc0, 0x24, 0x71, + ], + p_enc: [ + 0x03, 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, 0x08, 0x0a, + 0x98, 0x91, 0x66, 0x8d, 0x69, 0xb0, 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, + 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, + 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, 0xad, 0xe8, 0x24, 0xf3, 0xf9, 0x78, 0x1e, 0xbe, + 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, 0xf1, 0xb1, 0xaa, 0x9b, + 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, 0xe3, 0x81, 0x93, 0xbc, + 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, + 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, + 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, + 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, + 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, + 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, + 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, + 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, + 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, + 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, + 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, + 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, + 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, + 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, + 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, + 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, + 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, + 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, + 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, + 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, + 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, + 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, + 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, + 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, + 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, + 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, + 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, + 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, + 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, + 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, + 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, + 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, + 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, + 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, + 0x66, 0x17, 0x00, 0x8c, + ], + c_enc: [ + 0xf9, 0x09, 0x97, 0x73, 0x8b, 0x14, 0xd8, 0xa8, 0x4e, 0x32, 0x74, 0xbb, 0x70, 0x76, + 0x31, 0x15, 0xb7, 0x2e, 0x0a, 0x3d, 0xde, 0x8e, 0xa4, 0x70, 0x91, 0x1f, 0xb4, 0x58, + 0x70, 0xb0, 0x14, 0x8e, 0x7d, 0x37, 0x2b, 0xf2, 0x26, 0x8b, 0x3e, 0xe8, 0xda, 0xe5, + 0xfd, 0xe5, 0xea, 0x9b, 0x61, 0x59, 0x8e, 0xf1, 0x1b, 0x73, 0x14, 0x4f, 0x75, 0x53, + 0xb2, 0x13, 0xa0, 0x4c, 0x85, 0xf2, 0x5c, 0x54, 0x6c, 0x8a, 0x38, 0xa6, 0x0e, 0x50, + 0x86, 0x08, 0xb9, 0xca, 0x59, 0x3b, 0x94, 0xd8, 0x68, 0x8d, 0x6e, 0xff, 0xa5, 0x36, + 0x04, 0xd4, 0xdb, 0xc0, 0xf3, 0x45, 0x03, 0xaa, 0xe4, 0x6f, 0x3c, 0x8a, 0x8d, 0x2e, + 0x46, 0xa8, 0x1f, 0x09, 0x12, 0x6c, 0x45, 0x36, 0xfd, 0x02, 0x58, 0xf5, 0x97, 0x40, + 0xad, 0x0d, 0xb8, 0x02, 0xcc, 0x02, 0x42, 0x53, 0x4d, 0xdf, 0x52, 0xa6, 0xbf, 0x6a, + 0x03, 0x4d, 0xe6, 0x26, 0xf0, 0x18, 0x84, 0x4a, 0xdc, 0xb2, 0x6d, 0xcd, 0xc2, 0x85, + 0x16, 0x37, 0x16, 0xdd, 0x54, 0x65, 0x1c, 0x88, 0x73, 0x53, 0xf1, 0xff, 0xef, 0xa0, + 0x37, 0x71, 0x2a, 0xc0, 0xdf, 0x3a, 0x92, 0x98, 0x19, 0x06, 0x87, 0x54, 0x9d, 0x79, + 0xc6, 0xa3, 0x60, 0x0c, 0xc1, 0xc7, 0x29, 0xa3, 0x93, 0xd4, 0x4f, 0xec, 0xe5, 0x7f, + 0xd4, 0xcb, 0x0c, 0x0f, 0xb0, 0xc7, 0x86, 0x1b, 0x92, 0x5b, 0x94, 0xcd, 0x6a, 0x26, + 0x90, 0xf0, 0x02, 0xc4, 0x3a, 0x16, 0x6e, 0x56, 0x77, 0x72, 0x9f, 0x35, 0x52, 0xae, + 0xe0, 0xf2, 0xc1, 0x95, 0xaa, 0x91, 0xb2, 0xdd, 0xe3, 0x65, 0xdd, 0x14, 0xf2, 0xf0, + 0x7b, 0x3c, 0x38, 0x34, 0x7f, 0x6c, 0x0d, 0xab, 0x82, 0x84, 0x1e, 0xba, 0xde, 0x1e, + 0xf8, 0x13, 0xf2, 0xcd, 0x88, 0x5b, 0x57, 0x84, 0x37, 0x44, 0x45, 0x24, 0x93, 0x6a, + 0x65, 0x46, 0xc4, 0x55, 0xd6, 0xc9, 0x2e, 0x6d, 0x3d, 0xc5, 0x38, 0xb6, 0xcd, 0x9f, + 0x6d, 0x4c, 0xc0, 0xd7, 0x4d, 0x7b, 0xc2, 0x46, 0x7e, 0x21, 0x5b, 0xe8, 0xc3, 0xd4, + 0xff, 0x91, 0x8a, 0x2d, 0x98, 0x71, 0x00, 0xff, 0x34, 0x02, 0x4c, 0x88, 0x62, 0x79, + 0xd6, 0x4c, 0xaf, 0xdf, 0xd9, 0x0f, 0x1c, 0x04, 0xc4, 0x6b, 0xc9, 0xd5, 0xe9, 0xe2, + 0xaf, 0xd0, 0x3a, 0xb7, 0x55, 0xe4, 0x0f, 0x08, 0x7e, 0xb5, 0x1e, 0xe3, 0xd1, 0x02, + 0xb6, 0xb0, 0x69, 0xb6, 0x50, 0xf5, 0xd8, 0x55, 0x03, 0x35, 0x47, 0x1b, 0x24, 0x46, + 0x5d, 0x93, 0x4d, 0x63, 0x34, 0x39, 0xb1, 0x08, 0xd9, 0x04, 0x2b, 0x37, 0xf9, 0xf7, + 0x2e, 0x74, 0xfd, 0x6b, 0xa0, 0x01, 0x58, 0x5b, 0x08, 0x62, 0xdb, 0x99, 0x4a, 0x5e, + 0xc1, 0x2d, 0xc9, 0x1e, 0x01, 0x48, 0x6a, 0x8d, 0xc6, 0x8a, 0xb9, 0xa3, 0x41, 0x93, + 0x52, 0x61, 0x73, 0xec, 0xc0, 0xd1, 0x55, 0xb5, 0xcd, 0xd6, 0xbc, 0x07, 0xe6, 0x3e, + 0x41, 0xaf, 0x9e, 0x52, 0x4c, 0xd3, 0xe6, 0x55, 0x5d, 0x38, 0xb4, 0x6d, 0xb2, 0xd9, + 0x9e, 0x5b, 0xa4, 0xa4, 0x95, 0xff, 0x30, 0xfe, 0xf2, 0x54, 0xc9, 0xfe, 0x7b, 0x79, + 0x0c, 0xe5, 0x6a, 0x40, 0xf4, 0x00, 0x27, 0xbb, 0x62, 0x05, 0x86, 0x38, 0xc4, 0x94, + 0x17, 0x7b, 0x7f, 0x5c, 0x8f, 0x29, 0x44, 0x9e, 0x9e, 0xc3, 0xbd, 0xb3, 0xab, 0x04, + 0x16, 0x0d, 0x96, 0xd0, 0xd4, 0x04, 0x79, 0x5d, 0x54, 0x28, 0x40, 0x82, 0xb6, 0x35, + 0x7d, 0x58, 0x1d, 0xc2, 0x64, 0x81, 0x13, 0x67, 0xbb, 0xb1, 0x31, 0x9a, 0x31, 0xf7, + 0x66, 0x4a, 0x4e, 0xca, 0x93, 0x2a, 0xbb, 0xd7, 0x33, 0xa7, 0x1a, 0x31, 0xaf, 0x23, + 0x11, 0xc4, 0x9a, 0xc9, 0xaf, 0x22, 0xf8, 0x16, 0x7b, 0x25, 0x51, 0xac, 0xf5, 0x73, + 0xd9, 0x1b, 0x40, 0x98, 0xc4, 0xde, 0xa8, 0xa9, 0x79, 0x9d, 0x9d, 0x54, 0x52, 0x0c, + 0xc6, 0x3e, 0x55, 0x71, 0x8a, 0x24, 0x85, 0xbf, 0x6f, 0x63, 0x16, 0x30, 0x7c, 0xea, + 0x21, 0x5e, 0x22, 0x22, 0x8d, 0x45, 0x34, 0x9a, 0x03, 0x50, 0x31, 0xa4, 0xcb, 0x67, + 0x7b, 0x52, 0x3a, 0x3a, 0x51, 0x25, 0x2c, 0x6c, 0x61, 0xd0, 0xe2, 0x43, 0x2b, 0x94, + 0xac, 0x9c, 0x0d, 0xb5, 0x40, 0xf3, 0x5b, 0x1d, 0xde, 0x91, 0xa3, 0xaf, 0x37, 0xa6, + 0x71, 0xb8, 0xaa, 0x9f, 0x69, 0xf0, + ], + ock: [ + 0x42, 0x46, 0x14, 0xa3, 0xb5, 0x79, 0x96, 0xef, 0xb1, 0x24, 0xb7, 0xf4, 0x50, 0xae, + 0x2a, 0xf7, 0xf6, 0xdc, 0x8c, 0x8c, 0xee, 0xa9, 0x4f, 0x17, 0x74, 0x77, 0x72, 0x1b, + 0x84, 0x61, 0x3b, 0x23, + ], + op: [ + 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, + 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, + 0xab, 0x00, 0xa0, 0x28, 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, + 0xdf, 0x7c, 0xe2, 0xd2, 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, + 0x86, 0x48, 0x56, 0x2c, 0xbd, 0x86, 0x3f, 0x09, ], c_out: [ - 0xca, 0xb7, 0x8d, 0xd1, 0x83, 0xf3, 0xe1, 0x6a, 0xf7, 0x6e, 0x9a, 0x90, 0x3d, 0xd4, - 0x2a, 0x96, 0x67, 0xbf, 0xe7, 0x08, 0xce, 0x88, 0x79, 0xb8, 0x38, 0x6e, 0x62, 0xac, - 0x9f, 0x66, 0x74, 0xf4, 0x93, 0x59, 0x5d, 0xa5, 0x06, 0xe9, 0xef, 0x06, 0xbb, 0xa2, - 0x4a, 0x93, 0x80, 0x60, 0xe5, 0xd3, 0x82, 0xcc, 0x75, 0xdf, 0xab, 0x97, 0xe0, 0xf8, - 0x49, 0x4b, 0x47, 0x6a, 0xdf, 0x4f, 0xfd, 0x96, 0xff, 0x7f, 0x1b, 0x4f, 0x16, 0xf8, - 0x59, 0x4b, 0x7c, 0x5a, 0x21, 0x9c, 0x7a, 0x00, 0xad, 0x15, + 0x8b, 0x94, 0x8b, 0x33, 0xf5, 0x55, 0xcd, 0x45, 0x5f, 0xaa, 0x36, 0x51, 0x7b, 0x8e, + 0xab, 0x29, 0xe1, 0xa5, 0x1f, 0x6c, 0xec, 0x21, 0x79, 0xd9, 0xea, 0xe4, 0xea, 0xca, + 0x92, 0x50, 0xbb, 0x9b, 0x55, 0xe4, 0xb5, 0x49, 0x49, 0x15, 0xc1, 0xf0, 0x01, 0x65, + 0xf8, 0x9d, 0x7c, 0x02, 0xa0, 0x25, 0x45, 0xb9, 0xd5, 0x98, 0x08, 0x6e, 0xeb, 0x96, + 0x1e, 0x58, 0x7e, 0x43, 0xfd, 0xfc, 0x65, 0xfe, 0x52, 0xf1, 0xe0, 0xc6, 0xa0, 0x46, + 0x46, 0x48, 0xcd, 0x1f, 0xc8, 0x9e, 0x80, 0xbd, 0x78, 0x0f, + ], + note_type: Some([ + 0xf9, 0x78, 0x1e, 0xbe, 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, + 0xf1, 0xb1, 0xaa, 0x9b, 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, + 0xe3, 0x81, 0x93, 0xbc, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0x77, 0x5c, 0x7f, 0x5c, 0xab, 0x43, 0x86, 0x88, 0x64, 0x3d, 0xdd, 0x15, 0x8d, 0xda, + 0xed, 0xf9, 0xa0, 0xea, 0xef, 0x61, 0x4b, 0x54, 0x90, 0x60, 0xf1, 0xe4, 0xd7, 0xcc, + 0x3e, 0x7e, 0x8b, 0x64, 0x49, 0x9a, 0x81, 0x8a, 0x6d, 0x0e, 0x33, 0x57, 0x68, 0x6e, + 0x65, 0xbc, 0x27, 0x4e, 0x3f, 0x7d, 0x45, 0x5b, 0x91, 0x1f, 0x13, 0x9f, 0x19, 0xf0, + 0x81, 0x61, 0x57, 0x51, 0x91, 0x3e, 0xb4, 0x12, ], + ovk: [ + 0x45, 0xe1, 0x59, 0x6c, 0xbf, 0x46, 0x70, 0xb7, 0xe0, 0x5d, 0xfd, 0xaf, 0xbb, 0x0c, + 0xf3, 0xdd, 0xee, 0x28, 0xd7, 0x6a, 0x82, 0x42, 0x8e, 0x8a, 0xba, 0x43, 0x64, 0xe8, + 0x4b, 0xac, 0x37, 0x92, + ], + default_d: [ + 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, + ], + default_pk_d: [ + 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, + 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, + 0x96, 0xdc, 0xe6, 0xb7, + ], + v: 10238534295395242511, + rseed: [ + 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, + 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, + 0xa5, 0xfa, 0x38, 0x5d, + ], + memo: [ + 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, + 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, + 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, + 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, + 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, + 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, + 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, + 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, + 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, + 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, + 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, + 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, + 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, + 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, + 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, + 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, + 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, + 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, + 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, + 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, + 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, + 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, + 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, + 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, + 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, + 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, + 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, + 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, + 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, + 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, + 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, + 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, + 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, + 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, + 0xee, 0xfc, 0x52, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x81, 0xa8, 0xbb, 0x76, 0xf2, 0x62, 0x73, 0x62, 0x8b, 0x9f, 0x9b, 0x66, 0x04, 0x94, + 0xb3, 0x45, 0xb7, 0x9d, 0x45, 0x16, 0x3c, 0x7b, 0x4c, 0xc5, 0x5a, 0x49, 0xff, 0x3f, + 0xc6, 0xb8, 0x1d, 0xaa, + ], + rho: [ + 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, + 0x53, 0xb9, 0x3b, 0xcb, 0xb4, 0x37, 0x57, 0x1c, 0x62, 0xf3, 0x75, 0x60, 0x7e, 0x90, + 0x4e, 0xb3, 0xa2, 0x08, + ], + cmx: [ + 0x8f, 0x56, 0xd1, 0x3f, 0xd9, 0xc8, 0x3e, 0xb7, 0x1b, 0x95, 0x87, 0x7a, 0x4f, 0x29, + 0x39, 0x64, 0xbf, 0x3f, 0x73, 0x1d, 0x8d, 0xf2, 0x04, 0x32, 0x2c, 0xed, 0xcb, 0x38, + 0x68, 0x21, 0x90, 0x3c, + ], + esk: [ + 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, 0x44, 0xb0, 0xb0, 0x4f, + 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, 0xa9, 0xec, 0x88, 0x17, + 0x18, 0x65, 0x40, 0x33, + ], + ephemeral_key: [ + 0x51, 0x66, 0x26, 0x31, 0x6e, 0xea, 0x63, 0xa6, 0x45, 0xae, 0x56, 0x23, 0x81, 0x5a, + 0x31, 0x74, 0xb3, 0xed, 0x36, 0x64, 0xc3, 0x3e, 0x6a, 0x51, 0x81, 0xa9, 0xf5, 0xb5, + 0x42, 0x76, 0x7a, 0x2d, + ], + shared_secret: [ + 0xf6, 0x04, 0x23, 0x98, 0x7f, 0x0e, 0x67, 0x6d, 0x1a, 0x3b, 0xb6, 0xef, 0xe0, 0x39, + 0x42, 0x1d, 0xbb, 0xc8, 0x24, 0xb6, 0x90, 0xc1, 0x94, 0xa4, 0x90, 0xe4, 0x17, 0x1d, + 0xde, 0x21, 0x58, 0x19, + ], + k_enc: [ + 0x20, 0x98, 0x25, 0x7e, 0x2b, 0x9b, 0x7f, 0xc0, 0x62, 0x82, 0x38, 0x03, 0x38, 0x59, + 0x7d, 0xcb, 0x62, 0x7d, 0xdf, 0x47, 0x3e, 0x83, 0xa7, 0x2e, 0x61, 0xb0, 0xf2, 0x2c, + 0xcf, 0xaf, 0xbe, 0x4e, + ], + p_enc: [ + 0x03, 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, 0x0f, 0x12, + 0xb0, 0x11, 0xb2, 0x94, 0x16, 0x8e, 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, + 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, + 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, 0xa5, 0xfa, 0x38, 0x5d, 0x76, 0xba, 0x24, 0x3f, + 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, 0xc4, 0xbd, 0x4f, 0xc9, + 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, 0xf6, 0x99, 0x03, 0x18, + 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, + 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, + 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, + 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, + 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, + 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, + 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, + 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, + 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, + 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, + 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, + 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, + 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, + 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, + 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, + 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, + 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, + 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, + 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, + 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, + 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, + 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, + 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, + 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, + 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, + 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, + 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, + 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, + 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, + 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, + 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, + 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, + 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, + 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, + 0xee, 0xfc, 0x52, 0x7b, + ], + c_enc: [ + 0xa4, 0x01, 0xab, 0x60, 0x1f, 0x8d, 0x69, 0xd9, 0x38, 0x0c, 0x3d, 0xef, 0x1f, 0x1a, + 0x34, 0xbe, 0x6c, 0xfa, 0x4d, 0x83, 0x8b, 0xf8, 0x7f, 0x00, 0xe3, 0x6b, 0xe6, 0xbe, + 0x68, 0x60, 0xbe, 0xa8, 0x3d, 0xab, 0xdd, 0x00, 0xab, 0xe7, 0xe0, 0xd1, 0x21, 0x90, + 0xfb, 0x54, 0xb0, 0xf2, 0xad, 0xcf, 0xef, 0x9e, 0xf4, 0x2b, 0xa2, 0x31, 0x77, 0x6a, + 0xd3, 0xee, 0x09, 0x86, 0xdb, 0x3f, 0x4f, 0xc0, 0xa8, 0xa1, 0xc6, 0xa7, 0xfe, 0x54, + 0xa6, 0x6b, 0xd7, 0x68, 0xa9, 0xde, 0xd2, 0x5b, 0xb1, 0x89, 0xd5, 0x87, 0x1c, 0xaf, + 0x4d, 0xf8, 0x95, 0x6c, 0x2f, 0x30, 0x70, 0x15, 0x89, 0xa4, 0xdc, 0xdb, 0x68, 0x11, + 0x6d, 0x0f, 0x50, 0x9b, 0x34, 0x1e, 0x8f, 0x25, 0x8e, 0x17, 0x38, 0xb5, 0x51, 0x9c, + 0x99, 0xf1, 0xdb, 0xd0, 0x86, 0x31, 0x56, 0x2f, 0x90, 0xd1, 0x5e, 0x72, 0x8a, 0x85, + 0x25, 0xa1, 0x1b, 0xfe, 0x53, 0x95, 0x24, 0x5d, 0x71, 0x79, 0xcf, 0x8e, 0x97, 0xa8, + 0x3f, 0xaa, 0x4c, 0xf3, 0xb2, 0xa8, 0xb5, 0xef, 0x62, 0x13, 0xe3, 0x30, 0x89, 0xb4, + 0xeb, 0x03, 0xe7, 0xc2, 0xf0, 0x12, 0x11, 0xfc, 0x53, 0xbc, 0x01, 0x16, 0x40, 0x05, + 0x01, 0x5d, 0xbf, 0x33, 0xc6, 0x50, 0xa3, 0xf8, 0x33, 0xba, 0x67, 0x77, 0xcf, 0xf1, + 0xd7, 0x38, 0xe2, 0x1c, 0x58, 0xdc, 0x05, 0xc3, 0xb4, 0xec, 0xb9, 0x7a, 0x6c, 0xe0, + 0xb0, 0xc5, 0xee, 0x94, 0x4c, 0x24, 0xb3, 0x3b, 0xb0, 0xce, 0x32, 0xbe, 0x02, 0x3e, + 0x21, 0x3f, 0xf7, 0xc9, 0xd4, 0x12, 0x4f, 0xc9, 0xdc, 0x4a, 0xa7, 0xca, 0x47, 0x13, + 0x86, 0x48, 0xe2, 0xbb, 0x80, 0x7c, 0xea, 0x7a, 0x58, 0xe7, 0x67, 0xd3, 0x27, 0x07, + 0x4a, 0xe5, 0xe3, 0x9c, 0x3c, 0x17, 0xb7, 0x7c, 0x09, 0x0a, 0xf9, 0x42, 0x5b, 0xc6, + 0x40, 0xd2, 0x1d, 0xd6, 0x81, 0xa6, 0x37, 0x45, 0xe9, 0x02, 0x59, 0xe2, 0xd1, 0x09, + 0x0c, 0x88, 0x48, 0x8e, 0x21, 0x48, 0xb9, 0xee, 0x24, 0x31, 0xc5, 0xae, 0xf5, 0x10, + 0x95, 0xb3, 0x5a, 0x37, 0x7c, 0xfa, 0x76, 0x5d, 0x82, 0x24, 0x98, 0x83, 0x00, 0x04, + 0x71, 0x79, 0xa5, 0x09, 0x40, 0x28, 0xbe, 0x52, 0x7d, 0x5d, 0xe1, 0xc2, 0x69, 0xff, + 0x45, 0x2c, 0x0a, 0xaf, 0x5a, 0x47, 0x7e, 0x93, 0x90, 0xa0, 0xf0, 0xa8, 0x68, 0x11, + 0x3c, 0x7c, 0xd1, 0x9e, 0x2e, 0xac, 0x54, 0x0d, 0xc6, 0x59, 0xda, 0x29, 0x60, 0x06, + 0x77, 0x6e, 0xda, 0x0d, 0xf9, 0x81, 0xc4, 0x11, 0xc1, 0x50, 0x01, 0xa9, 0x8b, 0x6a, + 0xd6, 0x58, 0xd9, 0xa6, 0x4c, 0x12, 0x6a, 0xbe, 0xfc, 0x73, 0x9a, 0xa1, 0xf4, 0x44, + 0xbb, 0x83, 0xf3, 0xf1, 0x4d, 0x11, 0x3d, 0x02, 0x8f, 0xae, 0x10, 0xe4, 0xc5, 0xdb, + 0xe7, 0x78, 0x51, 0x96, 0x83, 0xcd, 0xf4, 0xc2, 0xf4, 0x6c, 0x4a, 0x52, 0xae, 0x12, + 0x09, 0xe1, 0x12, 0x7f, 0x9d, 0xc4, 0xed, 0x86, 0x7d, 0x8e, 0xda, 0x02, 0x4a, 0x68, + 0x9f, 0x6b, 0x15, 0xb8, 0x05, 0x38, 0x03, 0x02, 0x44, 0x02, 0xa1, 0xce, 0x6f, 0x1c, + 0x63, 0x6f, 0x2e, 0xfc, 0xf9, 0xd0, 0x60, 0x51, 0x5c, 0xd6, 0x14, 0x71, 0x8d, 0x51, + 0x52, 0x7d, 0x26, 0x7a, 0xd8, 0x95, 0xfa, 0xd8, 0xec, 0xfb, 0x23, 0x51, 0xf8, 0x92, + 0x45, 0x0d, 0xc8, 0x74, 0xe8, 0x74, 0x39, 0x2c, 0x91, 0xed, 0x3a, 0xf1, 0x18, 0x38, + 0xc4, 0xb5, 0x48, 0x2e, 0x8c, 0x92, 0xeb, 0xc7, 0xa0, 0x08, 0x8e, 0x49, 0xd2, 0xb0, + 0xb4, 0xa1, 0xbd, 0x33, 0x3b, 0x38, 0x7f, 0x49, 0xe3, 0x0f, 0xd2, 0x1a, 0x6e, 0xdc, + 0x89, 0x94, 0x83, 0x4f, 0x28, 0xe9, 0xf2, 0x52, 0x9a, 0x7e, 0x27, 0x24, 0x21, 0x6d, + 0x9e, 0x1a, 0xe5, 0xb4, 0x6e, 0xb1, 0x9a, 0x53, 0xea, 0x2b, 0x97, 0x99, 0x65, 0xf7, + 0x5b, 0x83, 0xf6, 0x86, 0xed, 0xc0, 0x1d, 0x25, 0x7a, 0x06, 0x58, 0xd7, 0x4e, 0x25, + 0xc0, 0xe1, 0xa8, 0xb0, 0x65, 0x60, 0x43, 0x1f, 0x85, 0x10, 0x5c, 0xf9, 0x8a, 0x1f, + 0xfe, 0x28, 0x40, 0x8a, 0x64, 0xf4, 0xc0, 0x27, 0x8d, 0x36, 0xed, 0xea, 0x76, 0x40, + 0xa2, 0x18, 0x26, 0xc3, 0x5d, 0x13, 0x20, 0x25, 0x08, 0x07, 0x2b, 0x68, 0x82, 0xf4, + 0xd8, 0x2e, 0x93, 0x3c, 0x89, 0xe1, + ], + ock: [ + 0x71, 0x5c, 0x9a, 0x01, 0x87, 0xab, 0x90, 0xb2, 0x4d, 0x3c, 0xbb, 0xa3, 0xf1, 0xab, + 0x30, 0x67, 0xc5, 0x63, 0x06, 0x04, 0x48, 0xc0, 0x0e, 0xf2, 0x74, 0xb7, 0xea, 0x66, + 0x11, 0x13, 0x0d, 0x26, + ], + op: [ + 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, + 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, + 0x96, 0xdc, 0xe6, 0xb7, 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, + 0x44, 0xb0, 0xb0, 0x4f, 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, + 0xa9, 0xec, 0x88, 0x17, 0x18, 0x65, 0x40, 0x33, + ], + c_out: [ + 0x22, 0xce, 0xb6, 0x94, 0x21, 0xab, 0x9e, 0xd0, 0x29, 0x97, 0x3f, 0xf2, 0x2e, 0xc9, + 0x5f, 0x23, 0x36, 0x56, 0xbe, 0x41, 0xd2, 0x25, 0x1a, 0x76, 0x77, 0xce, 0xb0, 0xd3, + 0x14, 0x22, 0x11, 0x6f, 0x8c, 0xa5, 0xf0, 0xae, 0x23, 0x12, 0xd4, 0xec, 0x60, 0x0c, + 0x5d, 0x7c, 0x56, 0x44, 0x5b, 0x6d, 0x8d, 0xc4, 0xb8, 0x0b, 0x47, 0x0b, 0xb1, 0xf6, + 0x51, 0xa5, 0x38, 0x28, 0x0d, 0xaa, 0x94, 0x20, 0x3a, 0xb5, 0x02, 0xa8, 0x15, 0x09, + 0xe4, 0x3a, 0x61, 0xa6, 0x98, 0x56, 0x57, 0xd9, 0xe8, 0x4e, + ], + note_type: Some([ + 0x76, 0xba, 0x24, 0x3f, 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, + 0xc4, 0xbd, 0x4f, 0xc9, 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, + 0xf6, 0x99, 0x03, 0x18, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0x9c, 0xe9, 0x20, 0x37, 0x6a, 0x6a, 0x54, 0x1e, 0x6a, 0xad, 0x66, 0x0e, 0xfa, 0x09, + 0x8d, 0xc5, 0x4c, 0x18, 0xfc, 0xeb, 0x13, 0xd0, 0x99, 0x9f, 0xbc, 0xc7, 0xfd, 0x45, + 0xa5, 0x7c, 0xcc, 0x10, 0xb8, 0xaa, 0x86, 0xc4, 0x54, 0x0d, 0x0a, 0x9f, 0xc6, 0x6d, + 0xf8, 0x5d, 0xad, 0xd6, 0x21, 0x56, 0x36, 0x5e, 0x28, 0xa3, 0xe9, 0x80, 0xb9, 0x8d, + 0x13, 0x1b, 0x50, 0x3a, 0xa0, 0x6a, 0x6c, 0x19, + ], + ovk: [ + 0xf8, 0x1a, 0xd6, 0x17, 0xfa, 0x26, 0xf0, 0xdf, 0xb8, 0x36, 0x55, 0xb8, 0xa2, 0x9a, + 0x7f, 0x83, 0x42, 0x32, 0x42, 0x5e, 0x8c, 0x47, 0x45, 0x88, 0xf1, 0x8d, 0xd3, 0x26, + 0xaa, 0x39, 0x6c, 0x3e, + ], + default_d: [ + 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, + ], + default_pk_d: [ + 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, + 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, + 0x43, 0x4b, 0x1e, 0xb0, + ], + v: 2690686290017047047, + rseed: [ + 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, + 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, + 0xee, 0xba, 0xe6, 0xfa, + ], + memo: [ + 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, + 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, + 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, + 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, + 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, + 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, + 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, + 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, + 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, + 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, + 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, + 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, + 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, + 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, + 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, + 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, + 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, + 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, + 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, + 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, + 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, + 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, + 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, + 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, + 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, + 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, + 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, + 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, + 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, + 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, + 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, + 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, + 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, + 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, + 0xe8, 0xba, 0x4f, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x40, 0x21, 0x95, 0x68, 0x0e, 0x02, 0x27, 0x30, 0x2c, 0x3a, 0x75, 0x6a, 0x34, 0xdf, + 0xdb, 0x13, 0x6b, 0xbd, 0x28, 0x7d, 0x7d, 0xc1, 0x25, 0x81, 0xd0, 0x8e, 0x2a, 0x63, + 0xb9, 0xc3, 0x92, 0x3e, + ], + rho: [ + 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, + 0xa5, 0xed, 0x09, 0xc6, 0xee, 0x3b, 0x7f, 0x39, 0x34, 0x14, 0xe1, 0x1c, 0xd4, 0x20, + 0x4c, 0x3f, 0x8d, 0x26, + ], + cmx: [ + 0x69, 0x4b, 0x6f, 0x3a, 0xb8, 0x37, 0xa9, 0x26, 0xd6, 0x77, 0x3e, 0xc4, 0xa6, 0x76, + 0x5d, 0xef, 0x82, 0x89, 0x33, 0x74, 0x2d, 0x93, 0x29, 0xfc, 0x88, 0x67, 0x1c, 0xcd, + 0x81, 0x21, 0xa4, 0x23, + ], + esk: [ + 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, 0xa5, 0xd8, 0x9a, 0xa8, + 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, 0x6a, 0x72, 0xcb, 0x74, + 0xfb, 0x18, 0xd1, 0x17, + ], + ephemeral_key: [ + 0x3c, 0x04, 0xbe, 0x6e, 0x42, 0xa6, 0xca, 0x7f, 0x5d, 0xda, 0x0d, 0x82, 0xdf, 0x30, + 0x7b, 0xd9, 0x6b, 0xb7, 0xb1, 0xae, 0x8d, 0x62, 0x31, 0x87, 0xe3, 0x9c, 0x00, 0xa4, + 0x8c, 0x25, 0xaa, 0x9d, + ], + shared_secret: [ + 0x3a, 0x60, 0x2b, 0xaf, 0xb8, 0xa2, 0x66, 0x5a, 0x74, 0xdf, 0x34, 0xab, 0x6e, 0x3c, + 0x48, 0x8b, 0x09, 0xe2, 0x28, 0x4e, 0xa1, 0x7d, 0x56, 0x02, 0x62, 0xe2, 0x1f, 0x7f, + 0x3c, 0xba, 0xa3, 0x95, + ], + k_enc: [ + 0x1b, 0x6d, 0xd1, 0x03, 0x49, 0x63, 0x67, 0xc9, 0x2b, 0x36, 0x8f, 0xc2, 0xf1, 0xc6, + 0x2e, 0x56, 0xc8, 0xc9, 0xfb, 0xe3, 0x4a, 0x35, 0x84, 0x1f, 0xe1, 0xa3, 0x70, 0x96, + 0x43, 0xe1, 0x35, 0xe1, + ], + p_enc: [ + 0x03, 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, 0x07, 0xd2, + 0x7a, 0xc6, 0xec, 0x3c, 0x57, 0x25, 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, + 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, + 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, 0xee, 0xba, 0xe6, 0xfa, 0x64, 0xd0, 0x87, 0x40, + 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, 0xc3, 0x93, 0x11, 0x78, + 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, 0xe5, 0xf5, 0xd4, 0xbc, + 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, + 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, + 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, + 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, + 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, + 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, + 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, + 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, + 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, + 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, + 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, + 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, + 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, + 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, + 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, + 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, + 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, + 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, + 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, + 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, + 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, + 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, + 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, + 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, + 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, + 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, + 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, + 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, + 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, + 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, + 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, + 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, + 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, + 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, + 0xe8, 0xba, 0x4f, 0x52, + ], + c_enc: [ + 0xb4, 0x15, 0x88, 0x23, 0x1d, 0x6b, 0xa2, 0x9c, 0xc5, 0xb9, 0xaa, 0xf0, 0xc1, 0xf0, + 0xba, 0x44, 0x16, 0x6e, 0xdb, 0x8a, 0x27, 0x29, 0xca, 0xba, 0x53, 0x71, 0xe7, 0xac, + 0x36, 0x90, 0x0f, 0xaa, 0x64, 0xf5, 0x76, 0x0d, 0xce, 0x55, 0x20, 0xda, 0x82, 0x8d, + 0x5e, 0x25, 0xbd, 0x83, 0x51, 0x95, 0x11, 0x64, 0x12, 0x11, 0x80, 0x9d, 0xff, 0xd8, + 0xcf, 0xeb, 0xff, 0xf3, 0xcd, 0xdc, 0xd2, 0x75, 0x88, 0x1e, 0x39, 0xb6, 0x3d, 0xac, + 0x4d, 0x98, 0x6b, 0x10, 0xc0, 0xe4, 0xc5, 0x52, 0x63, 0xde, 0x3e, 0x02, 0x54, 0x94, + 0x81, 0x8a, 0x38, 0x08, 0xd9, 0xab, 0xc6, 0xec, 0x38, 0x8f, 0x95, 0x26, 0x73, 0x95, + 0x0a, 0xa2, 0xd0, 0xe4, 0xba, 0x00, 0x53, 0x75, 0xac, 0x60, 0x5d, 0xc8, 0x25, 0xde, + 0x4d, 0xd8, 0x93, 0x8b, 0x94, 0x7f, 0xf7, 0x19, 0x4c, 0xfe, 0x7c, 0x1d, 0x79, 0xa1, + 0x27, 0x15, 0x5d, 0x11, 0xcb, 0xe3, 0x43, 0xf3, 0x2f, 0xd1, 0x0c, 0x7d, 0xae, 0x39, + 0x1f, 0x00, 0xb4, 0x4f, 0xbe, 0x30, 0x1c, 0x63, 0xfd, 0x4b, 0xf1, 0xc0, 0xdf, 0xb6, + 0xc9, 0xec, 0xb4, 0xc3, 0xf3, 0xfe, 0xf5, 0x40, 0xb6, 0x7e, 0xb9, 0x23, 0x13, 0x71, + 0x9c, 0x5a, 0x30, 0x7a, 0xd3, 0x95, 0x6b, 0xb9, 0x4e, 0x29, 0x86, 0x85, 0x2a, 0x64, + 0x5a, 0x95, 0xd6, 0xdc, 0x75, 0xaa, 0x27, 0x4c, 0xcf, 0xd2, 0x71, 0xd0, 0xea, 0xe2, + 0x65, 0x81, 0xf5, 0xf5, 0x5d, 0x64, 0x74, 0xaa, 0xad, 0x37, 0x4c, 0x86, 0x45, 0x05, + 0xe6, 0x92, 0x37, 0xf6, 0x66, 0x99, 0xee, 0x39, 0xe9, 0xfc, 0xf5, 0xb1, 0xb7, 0x03, + 0x35, 0x1e, 0x71, 0xf6, 0x3b, 0x02, 0x33, 0x40, 0x82, 0xee, 0xbe, 0xd8, 0x68, 0xb5, + 0x61, 0x2a, 0x33, 0x95, 0x78, 0x5a, 0x33, 0x2a, 0x52, 0x43, 0xe4, 0x98, 0x6e, 0x1f, + 0xf5, 0xb4, 0x2d, 0x06, 0x69, 0xc1, 0x5c, 0x45, 0xff, 0x81, 0xe2, 0x2e, 0xea, 0xe4, + 0xde, 0x7d, 0x9a, 0x4f, 0x57, 0x24, 0xc8, 0x96, 0x03, 0x94, 0x92, 0x5b, 0xa1, 0xa1, + 0x90, 0x0f, 0xa2, 0xb5, 0x59, 0x3d, 0x55, 0x45, 0x5e, 0x0b, 0xe0, 0x31, 0x8c, 0x80, + 0x23, 0x81, 0xec, 0x9c, 0x0a, 0x83, 0xc2, 0xe5, 0xf9, 0x33, 0x9f, 0x02, 0x9c, 0x44, + 0x24, 0x72, 0x8f, 0x91, 0x9d, 0x18, 0x4f, 0x36, 0x16, 0x50, 0xba, 0x65, 0xd6, 0x98, + 0xa8, 0xd1, 0x67, 0xbe, 0xd9, 0xdd, 0x01, 0xfa, 0x70, 0x74, 0xe4, 0x6a, 0xf6, 0x57, + 0x16, 0xdd, 0xd9, 0x7e, 0x7b, 0xb6, 0x00, 0x13, 0x05, 0x96, 0x8c, 0xd5, 0xb4, 0x87, + 0x0d, 0xf2, 0x00, 0x42, 0xe7, 0x69, 0xe0, 0x2d, 0xf1, 0x8b, 0x9f, 0xde, 0x9f, 0xda, + 0xa7, 0x6b, 0x00, 0xca, 0x26, 0x45, 0x9d, 0x54, 0x37, 0x19, 0x19, 0x72, 0xd7, 0x08, + 0xde, 0xda, 0xbf, 0x1d, 0x61, 0x7f, 0x73, 0x3a, 0x60, 0xeb, 0xfe, 0xc6, 0xac, 0xf0, + 0x0b, 0xb1, 0xdf, 0xbf, 0x11, 0x2d, 0x3a, 0xaa, 0xc9, 0xfb, 0xd2, 0x30, 0xcc, 0xaa, + 0x9c, 0xf3, 0x58, 0x45, 0x93, 0x54, 0xac, 0x5b, 0x29, 0xbd, 0xb7, 0x3a, 0x45, 0x27, + 0x1b, 0x1f, 0x9e, 0xd0, 0x0e, 0x3e, 0x20, 0xb1, 0x2f, 0xed, 0x5c, 0xd5, 0x6a, 0xbb, + 0xb0, 0xb9, 0x4a, 0x9e, 0xee, 0x5f, 0xf8, 0xf9, 0x36, 0x1d, 0xfd, 0x6c, 0x94, 0x08, + 0x5d, 0x28, 0x98, 0xe5, 0x46, 0xeb, 0x92, 0xe6, 0xdb, 0xe9, 0xf0, 0x2e, 0xb5, 0xbf, + 0x7d, 0x12, 0x67, 0x5d, 0x3c, 0x6a, 0xc7, 0x18, 0x4b, 0x26, 0x01, 0xe4, 0xf4, 0x05, + 0x37, 0x3a, 0x4f, 0x1c, 0x5d, 0xf7, 0x6b, 0x3c, 0xb5, 0x29, 0x99, 0xd8, 0x0f, 0x59, + 0xb3, 0x94, 0xbc, 0xed, 0x9f, 0x66, 0xbc, 0xf7, 0xdc, 0x37, 0xc2, 0xb4, 0xc6, 0xf7, + 0x74, 0x5b, 0xc6, 0xf0, 0x37, 0x74, 0xfa, 0xc6, 0x24, 0x5d, 0x7c, 0x63, 0x6d, 0xfc, + 0x5f, 0x76, 0x58, 0xb2, 0xd2, 0xfd, 0x84, 0xac, 0xa9, 0xe0, 0xef, 0xcd, 0xe0, 0x09, + 0x3e, 0x62, 0x29, 0x38, 0xb7, 0x5d, 0xae, 0x66, 0xcf, 0x63, 0xf6, 0xd2, 0x35, 0x17, + 0x2e, 0x5a, 0x0b, 0xbe, 0xcd, 0x15, 0x56, 0x6c, 0x61, 0xfe, 0x5a, 0x58, 0x94, 0x7c, + 0x18, 0xb9, 0xb5, 0xa1, 0x21, 0x11, 0x25, 0x94, 0x3b, 0x09, 0x32, 0x24, 0x96, 0x7b, + 0x7e, 0x44, 0x16, 0x70, 0x64, 0xc9, + ], + ock: [ + 0xbc, 0x1b, 0xa7, 0xae, 0x73, 0xe7, 0x39, 0x7a, 0x64, 0xe0, 0xbd, 0x98, 0x63, 0xf1, + 0x33, 0x95, 0xdc, 0x0b, 0x15, 0xd4, 0x4e, 0x86, 0x70, 0xf1, 0x85, 0x5b, 0x68, 0xc2, + 0x9f, 0x97, 0x9a, 0xd2, + ], + op: [ + 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, + 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, + 0x43, 0x4b, 0x1e, 0xb0, 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, + 0xa5, 0xd8, 0x9a, 0xa8, 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, + 0x6a, 0x72, 0xcb, 0x74, 0xfb, 0x18, 0xd1, 0x17, + ], + c_out: [ + 0xe2, 0x76, 0x3c, 0x2c, 0xd3, 0x04, 0x29, 0x45, 0x25, 0xf6, 0x6d, 0x17, 0xcd, 0xb4, + 0x2a, 0x6d, 0xaf, 0xd7, 0x47, 0x38, 0x37, 0x71, 0x52, 0x35, 0x62, 0xb2, 0x71, 0xbb, + 0xf5, 0xb2, 0x88, 0x41, 0xb5, 0xca, 0x65, 0xfd, 0xd3, 0x42, 0xee, 0x80, 0x2f, 0xee, + 0x12, 0x12, 0x47, 0x22, 0xcf, 0xf5, 0xe1, 0x99, 0xd6, 0xd9, 0x5c, 0x2f, 0x88, 0xc4, + 0xe2, 0x31, 0x31, 0xf4, 0xe7, 0x6b, 0xa7, 0x6b, 0x9d, 0x64, 0x66, 0x78, 0xd8, 0x53, + 0xd1, 0xdc, 0xaf, 0x81, 0xb8, 0x0e, 0x2e, 0xfd, 0xf0, 0x60, + ], + note_type: Some([ + 0x64, 0xd0, 0x87, 0x40, 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, + 0xc3, 0x93, 0x11, 0x78, 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, + 0xe5, 0xf5, 0xd4, 0xbc, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0xb4, 0x9e, 0x3c, 0x5b, 0xb9, 0x9e, 0x47, 0xc5, 0x3d, 0x6e, 0x5c, 0x34, 0x7c, 0x99, + 0x8f, 0x30, 0x2d, 0x3f, 0xf4, 0x75, 0x23, 0xe7, 0xc3, 0xd7, 0xb6, 0x4c, 0x82, 0x98, + 0xdc, 0x7b, 0x10, 0xe9, 0x54, 0xdf, 0x06, 0x00, 0x0b, 0xc0, 0xcc, 0x30, 0xec, 0xf6, + 0x75, 0x5d, 0x92, 0x7e, 0xee, 0xce, 0xe6, 0xec, 0x9e, 0x8e, 0x0c, 0xba, 0xa3, 0x1b, + 0x71, 0xe0, 0xa4, 0x33, 0x4a, 0xd6, 0x42, 0x1b, + ], + ovk: [ + 0x97, 0x9f, 0x06, 0x58, 0x66, 0x73, 0xbc, 0x6f, 0xf1, 0xc5, 0xd3, 0xb3, 0x20, 0xf3, + 0x49, 0xa5, 0xb3, 0xa8, 0xb3, 0x55, 0x59, 0x22, 0x96, 0xaa, 0xf6, 0x1c, 0x5b, 0x72, + 0x52, 0xf7, 0x3e, 0xc0, + ], + default_d: [ + 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, + ], + default_pk_d: [ + 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, + 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, + 0xf4, 0x1a, 0x1f, 0x88, + ], + v: 5531329397987978327, + rseed: [ + 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, + 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, + 0xd0, 0x11, 0x8b, 0xbd, + ], + memo: [ + 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, + 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, + 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, + 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, + 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, + 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, + 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, + 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, + 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, + 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, + 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, + 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, + 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, + 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, + 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, + 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, + 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, + 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, + 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, + 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, + 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, + 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, + 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, + 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, + 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, + 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, + 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, + 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, + 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, + 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, + 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, + 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, + 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, + 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, + 0x09, 0x5d, 0x98, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x50, 0xaf, 0x90, 0x31, 0xf4, 0xe0, 0x4b, 0x79, 0xd7, 0xda, 0xb5, 0xe8, 0x5b, 0x51, + 0xee, 0x9b, 0xea, 0x56, 0xf7, 0xc5, 0x6b, 0x52, 0x22, 0x73, 0xd2, 0x30, 0xaa, 0x51, + 0x2b, 0xa9, 0xe7, 0x06, + ], + rho: [ + 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, + 0x67, 0x93, 0xc3, 0xfe, 0xfa, 0xda, 0xee, 0xa8, 0xe2, 0x3c, 0x44, 0xd5, 0xe0, 0x18, + 0x4b, 0xc8, 0x45, 0x10, + ], + cmx: [ + 0x76, 0xf1, 0xbd, 0x50, 0xf9, 0xb9, 0x06, 0xcb, 0x9f, 0xf2, 0xdd, 0x91, 0x8a, 0x36, + 0x7e, 0x5f, 0xb1, 0xa2, 0xef, 0x39, 0xf1, 0x4f, 0x6c, 0xe9, 0x4f, 0xf9, 0xf0, 0x91, + 0x55, 0xf8, 0xc2, 0x11, + ], + esk: [ + 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, 0xa1, 0xe6, 0xfb, 0x57, + 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, 0xb9, 0x5f, 0xc8, 0x7e, + 0xa7, 0x37, 0x3e, 0x2f, + ], + ephemeral_key: [ + 0xda, 0x72, 0x84, 0xa0, 0xe0, 0xde, 0x52, 0x09, 0x3c, 0xc2, 0xe1, 0x9c, 0x0a, 0xf1, + 0x93, 0xbd, 0xb4, 0x2c, 0x80, 0xc9, 0xc7, 0xf9, 0xf2, 0x36, 0x00, 0xe6, 0x08, 0x01, + 0x72, 0xc5, 0xf5, 0x39, + ], + shared_secret: [ + 0x9b, 0xcf, 0xb9, 0x6f, 0x4c, 0xf1, 0x83, 0xc1, 0x7f, 0xb1, 0x99, 0xda, 0x16, 0x5f, + 0xbf, 0x8a, 0x47, 0x47, 0x7e, 0x00, 0x36, 0x6d, 0x1c, 0xb7, 0x3b, 0x32, 0xec, 0x0e, + 0x3a, 0xc1, 0x98, 0x0f, + ], + k_enc: [ + 0x21, 0xe0, 0x97, 0x87, 0x0a, 0xee, 0xc0, 0x19, 0x76, 0x86, 0xee, 0x37, 0x22, 0x78, + 0xfe, 0x4a, 0xa2, 0x23, 0x8d, 0x87, 0x65, 0x32, 0x63, 0x84, 0x8a, 0x2f, 0xf5, 0x27, + 0x9f, 0x2b, 0x1d, 0x9b, + ], + p_enc: [ + 0x03, 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, 0x57, 0xac, + 0xbf, 0xfe, 0xc7, 0x3a, 0xc3, 0x4c, 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, + 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, + 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, 0xd0, 0x11, 0x8b, 0xbd, 0xc3, 0xcc, 0x4f, 0x43, + 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, 0xe3, 0x7a, 0x83, 0xec, + 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, 0x29, 0x03, 0x35, 0xaa, + 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, + 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, + 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, + 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, + 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, + 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, + 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, + 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, + 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, + 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, + 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, + 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, + 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, + 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, + 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, + 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, + 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, + 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, + 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, + 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, + 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, + 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, + 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, + 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, + 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, + 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, + 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, + 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, + 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, + 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, + 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, + 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, + 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, + 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, + 0x09, 0x5d, 0x98, 0x77, + ], + c_enc: [ + 0x13, 0xd7, 0xdf, 0xcd, 0x1d, 0x75, 0x4d, 0xcd, 0x16, 0x52, 0x32, 0x83, 0x8f, 0x14, + 0xdd, 0x80, 0x5e, 0x12, 0xcc, 0x7e, 0x75, 0x15, 0x43, 0xd2, 0xa6, 0x8e, 0x23, 0x7a, + 0x92, 0x3b, 0xce, 0xeb, 0xa3, 0x5a, 0x62, 0x43, 0xc6, 0xa4, 0xc5, 0xf0, 0xd2, 0xa4, + 0xc3, 0x86, 0x07, 0xa6, 0xf1, 0x1b, 0x17, 0xfd, 0xd6, 0xc6, 0x92, 0x66, 0xf2, 0xc9, + 0x6a, 0xdc, 0x44, 0x6f, 0x2e, 0x2d, 0x07, 0x3e, 0xe9, 0xea, 0xe2, 0x9a, 0x37, 0xef, + 0x5d, 0x03, 0xf6, 0x78, 0xf5, 0x56, 0x29, 0x45, 0xb2, 0x08, 0x27, 0x76, 0xce, 0x9f, + 0x39, 0x08, 0x87, 0x3a, 0x99, 0xa6, 0xa2, 0x8b, 0xae, 0xdc, 0x7f, 0x54, 0x89, 0xce, + 0x4b, 0x30, 0xd8, 0x43, 0x66, 0xc5, 0x46, 0xb4, 0x36, 0x67, 0x91, 0x44, 0xf9, 0x27, + 0xf7, 0x1c, 0x65, 0x09, 0x69, 0xda, 0x22, 0x42, 0x28, 0x5a, 0x86, 0x27, 0x96, 0x54, + 0x89, 0xb7, 0x0b, 0x35, 0x6c, 0xf7, 0x4e, 0x07, 0x8a, 0xa2, 0x7d, 0xa8, 0xf9, 0x2f, + 0xb3, 0x09, 0x57, 0x12, 0x62, 0xf2, 0xd4, 0xc3, 0x36, 0xf7, 0x12, 0x15, 0x9b, 0x3e, + 0x9b, 0x43, 0x24, 0x38, 0x5b, 0xb3, 0x26, 0x2a, 0xc5, 0xf3, 0x13, 0x57, 0xaf, 0x9e, + 0x1a, 0xaa, 0x75, 0xd0, 0x1c, 0x06, 0x31, 0xbf, 0xdd, 0x34, 0xc5, 0x9b, 0x27, 0xd5, + 0x3b, 0xeb, 0xf1, 0xaa, 0x54, 0xe9, 0xc4, 0xaa, 0x98, 0x0f, 0x24, 0x7b, 0xf4, 0x22, + 0xa0, 0xe6, 0xdb, 0xf5, 0x54, 0x6e, 0xdc, 0x10, 0x0f, 0xce, 0x6c, 0xce, 0xc8, 0x32, + 0x7e, 0xb4, 0x8a, 0x9a, 0x39, 0xe4, 0xc2, 0xa9, 0x12, 0xb2, 0x98, 0x85, 0xe0, 0xc3, + 0xe7, 0x33, 0x55, 0x58, 0xbd, 0x85, 0x84, 0x38, 0xd0, 0x35, 0xd2, 0xf2, 0xbe, 0x1d, + 0x35, 0x66, 0xe4, 0x22, 0xfe, 0x37, 0xc0, 0xcb, 0x2e, 0x05, 0x8d, 0xad, 0x8c, 0xc6, + 0x45, 0x62, 0xa5, 0x50, 0x1b, 0x54, 0xa4, 0x4f, 0x9a, 0x77, 0x77, 0xc6, 0xd2, 0x77, + 0x04, 0xa4, 0xce, 0xad, 0x26, 0xa1, 0xc2, 0x56, 0x01, 0x8d, 0xc1, 0xbb, 0xfa, 0x58, + 0x84, 0xa0, 0x6c, 0xc7, 0x25, 0x23, 0xaf, 0xfb, 0x43, 0xf5, 0xc5, 0xbc, 0x2f, 0x1d, + 0x36, 0x04, 0x0f, 0x85, 0xf7, 0xe8, 0xc0, 0x62, 0xc1, 0xf2, 0x26, 0x50, 0x9d, 0x20, + 0xf9, 0xa4, 0x88, 0x5e, 0x15, 0x70, 0x4f, 0x73, 0x01, 0xdf, 0x60, 0x3d, 0xa1, 0xfc, + 0x5b, 0xca, 0x84, 0xf8, 0x55, 0xc1, 0x17, 0xcb, 0x30, 0x55, 0xc5, 0x70, 0x83, 0x45, + 0x7e, 0x1d, 0x14, 0x85, 0x7c, 0x2b, 0xf9, 0x41, 0xe8, 0x20, 0x73, 0x5c, 0x58, 0x8a, + 0xae, 0x6f, 0x66, 0x45, 0xdc, 0x3f, 0xbd, 0x30, 0x65, 0xab, 0xa1, 0x7f, 0xd2, 0x48, + 0x2a, 0x1b, 0x37, 0xb2, 0xf3, 0x88, 0x07, 0x5e, 0x46, 0xbb, 0x9d, 0x37, 0x27, 0xcc, + 0x73, 0xdb, 0xae, 0x0e, 0x96, 0xa8, 0x44, 0x5f, 0xda, 0x8f, 0x87, 0x64, 0xf9, 0x68, + 0x0b, 0xf6, 0xc5, 0x91, 0xa8, 0x48, 0x10, 0xfa, 0x0c, 0x1b, 0x5a, 0x2f, 0x2a, 0xa9, + 0xad, 0xbb, 0x88, 0x64, 0x22, 0x31, 0x72, 0x1e, 0xd6, 0xea, 0x12, 0x16, 0xab, 0x9b, + 0xfa, 0x0e, 0x12, 0x4c, 0xe4, 0x74, 0x94, 0x44, 0x53, 0x4d, 0x68, 0x70, 0x19, 0x74, + 0x60, 0xf7, 0x49, 0xef, 0xb0, 0x28, 0x8f, 0x96, 0x28, 0x3f, 0xc9, 0x37, 0xef, 0xbb, + 0x14, 0x59, 0xaa, 0x73, 0xc2, 0x7b, 0x6b, 0x2b, 0x5c, 0x57, 0x7d, 0x46, 0x60, 0xf9, + 0x8e, 0x81, 0x8c, 0xaa, 0xad, 0xbe, 0x45, 0x4e, 0xcd, 0x16, 0xc1, 0xd8, 0xa9, 0x9b, + 0x77, 0x97, 0x8e, 0x93, 0xd6, 0x9d, 0xcb, 0x8b, 0xf0, 0xe8, 0x4a, 0x0a, 0x91, 0x3f, + 0x55, 0xcc, 0x16, 0x50, 0xc2, 0xb9, 0x2d, 0x4c, 0x9d, 0xcd, 0xb1, 0x2e, 0xe2, 0x36, + 0x7e, 0xd9, 0x79, 0xb9, 0x53, 0x5f, 0xe1, 0x5c, 0x87, 0xd1, 0x7f, 0x37, 0xa3, 0x24, + 0x84, 0x7f, 0x16, 0x45, 0x39, 0x75, 0x7d, 0x83, 0x00, 0x87, 0xf6, 0x39, 0xeb, 0x6c, + 0x3e, 0xfb, 0x8d, 0xa4, 0xff, 0xa5, 0xd7, 0xca, 0x58, 0x34, 0x4d, 0x65, 0x81, 0x76, + 0x64, 0xa7, 0x4e, 0xaf, 0xa1, 0xa4, 0x7f, 0x69, 0xf1, 0xc8, 0x10, 0x6b, 0x6f, 0x5f, + 0x96, 0x4f, 0x4c, 0x73, 0x68, 0xed, 0x11, 0x06, 0x29, 0x54, 0xd2, 0xe8, 0xd3, 0x0c, + 0xcc, 0xac, 0xba, 0xd9, 0xa2, 0xfa, + ], + ock: [ + 0xc7, 0x5b, 0x5b, 0xfa, 0x9f, 0x2e, 0xeb, 0xd9, 0x99, 0x80, 0x78, 0xf1, 0x8f, 0x0e, + 0x9b, 0x79, 0xf1, 0xe2, 0x13, 0xe8, 0x25, 0x61, 0x6f, 0xeb, 0x26, 0x08, 0xe9, 0xc7, + 0x81, 0xb5, 0x00, 0x95, + ], + op: [ + 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, + 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, + 0xf4, 0x1a, 0x1f, 0x88, 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, + 0xa1, 0xe6, 0xfb, 0x57, 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, + 0xb9, 0x5f, 0xc8, 0x7e, 0xa7, 0x37, 0x3e, 0x2f, + ], + c_out: [ + 0xca, 0x4d, 0x6e, 0xb3, 0xea, 0x95, 0xc5, 0x5a, 0x91, 0x16, 0x85, 0x66, 0xe6, 0x67, + 0x63, 0xd1, 0x9e, 0x9c, 0x44, 0x33, 0x07, 0x3c, 0x08, 0x9a, 0x7d, 0xb9, 0x5b, 0x93, + 0xc8, 0xc4, 0x55, 0x0e, 0xb0, 0x8e, 0x28, 0xdd, 0xef, 0xba, 0x64, 0xe0, 0x58, 0xac, + 0x68, 0x44, 0xad, 0x77, 0x20, 0x67, 0xa1, 0x7c, 0x32, 0x53, 0xc3, 0x9a, 0x72, 0x4d, + 0xd8, 0x15, 0xf7, 0x29, 0x8c, 0x1d, 0x59, 0x09, 0x1f, 0x1b, 0x38, 0x7a, 0x26, 0x46, + 0xe7, 0xfe, 0x36, 0x3a, 0xde, 0x83, 0x63, 0xa9, 0x2a, 0xde, + ], + note_type: Some([ + 0xc3, 0xcc, 0x4f, 0x43, 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, + 0xe3, 0x7a, 0x83, 0xec, 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, + 0x29, 0x03, 0x35, 0xaa, + ]), + }, + TestVector { + incoming_viewing_key: [ + 0xa6, 0x68, 0x13, 0x52, 0xa3, 0x52, 0x26, 0x91, 0x10, 0x0f, 0x53, 0xfc, 0x34, 0xab, + 0x73, 0x32, 0x8a, 0xf1, 0xb9, 0xf3, 0xa4, 0xa0, 0x6d, 0xbd, 0x3a, 0x14, 0x99, 0x67, + 0x09, 0xe6, 0xf2, 0x84, 0x31, 0xee, 0x72, 0xf2, 0x69, 0xae, 0xd7, 0x5d, 0x36, 0x34, + 0x89, 0x36, 0x90, 0x5e, 0xbb, 0x91, 0x80, 0x7d, 0x74, 0xd5, 0x0c, 0xb2, 0x7f, 0xcd, + 0x8b, 0x4f, 0xb6, 0xf4, 0x48, 0xc3, 0x62, 0x03, + ], + ovk: [ + 0x78, 0xf1, 0x45, 0xea, 0x29, 0xd2, 0x71, 0xb9, 0x40, 0xc6, 0x99, 0x41, 0xe4, 0xc3, + 0xfd, 0x2d, 0x71, 0xf3, 0xb1, 0x90, 0x69, 0x0e, 0xe1, 0x6f, 0x5d, 0x14, 0xac, 0x22, + 0x24, 0xe6, 0xfc, 0x89, + ], + default_d: [ + 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, + ], + default_pk_d: [ + 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, + 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, + 0x3a, 0x56, 0x6a, 0xaa, + ], + v: 15093716717054627455, + rseed: [ + 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, + 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, + 0x24, 0x57, 0x16, 0xa4, + ], + memo: [ + 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, + 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, + 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, + 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, + 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, + 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, + 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, + 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, + 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, + 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, + 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, + 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, + 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, + 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, + 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, + 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, + 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, + 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, + 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, + 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, + 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, + 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, + 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, + 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, + 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, + 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, + 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, + 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, + 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, + 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, + 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, + 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, + 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, + 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, + 0x70, 0xe0, 0x90, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + cv_net: [ + 0x72, 0xd8, 0x2a, 0xd6, 0x89, 0xd2, 0x9f, 0x9b, 0x18, 0x9d, 0x5b, 0x44, 0x78, 0x9f, + 0x55, 0xfe, 0x1e, 0x9b, 0xab, 0x78, 0x8f, 0xf8, 0x7e, 0xbe, 0x9f, 0xc8, 0x59, 0x50, + 0x4f, 0xb2, 0x3c, 0x8a, + ], + rho: [ + 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, + 0xd0, 0x28, 0x44, 0x22, 0x13, 0x50, 0x86, 0x4e, 0xed, 0x56, 0x3d, 0xab, 0x30, 0x22, + 0x7f, 0x28, 0x4b, 0x2e, + ], + cmx: [ + 0x89, 0xe6, 0xa2, 0xb9, 0x70, 0x84, 0xe3, 0xd3, 0x34, 0x4f, 0xee, 0xb4, 0x64, 0x65, + 0x05, 0x72, 0x51, 0xb1, 0x9d, 0xa0, 0xce, 0xdf, 0x79, 0x71, 0x94, 0xc5, 0x97, 0xf9, + 0xf7, 0x7e, 0xf2, 0x1f, + ], + esk: [ + 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, 0x02, 0xf5, 0x10, 0xe9, + 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, 0xc4, 0x69, 0x2d, 0x0c, + 0x1b, 0x30, 0x33, 0x01, + ], + ephemeral_key: [ + 0x27, 0xcb, 0x40, 0x68, 0x0f, 0xb1, 0xd9, 0x19, 0x64, 0x6e, 0x74, 0x20, 0xe6, 0xa8, + 0xb5, 0x20, 0xe1, 0x9a, 0x17, 0x3f, 0x1e, 0x79, 0x4d, 0x2b, 0x49, 0x2b, 0xfa, 0xbb, + 0x83, 0xce, 0x6c, 0xa0, + ], + shared_secret: [ + 0x1c, 0xd0, 0x66, 0x91, 0x6c, 0x19, 0xfa, 0x33, 0x69, 0xaa, 0x3c, 0x6a, 0x53, 0x76, + 0x97, 0xf4, 0xb4, 0x26, 0x44, 0xda, 0x20, 0xca, 0x46, 0x79, 0x93, 0x2b, 0x7c, 0x90, + 0x5f, 0x2d, 0x69, 0x00, + ], + k_enc: [ + 0xce, 0x9d, 0x22, 0x0d, 0x3a, 0xfe, 0xc6, 0x23, 0x21, 0xdd, 0xf1, 0x97, 0xa6, 0x36, + 0xdc, 0xb3, 0x45, 0x58, 0x83, 0xb7, 0x35, 0x82, 0x8c, 0x65, 0xe7, 0x16, 0x6c, 0x15, + 0xd8, 0xcc, 0xfc, 0xf9, + ], + p_enc: [ + 0x03, 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, 0x7f, 0x8e, + 0x6a, 0x5c, 0x62, 0xa7, 0x77, 0xd1, 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, + 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, + 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, 0x24, 0x57, 0x16, 0xa4, 0x96, 0x86, 0xaa, 0x36, + 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, 0xab, 0xcf, 0xac, 0x88, + 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, 0x07, 0x2d, 0x2d, 0x18, + 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, + 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, + 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, + 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, + 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, + 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, + 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, + 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, + 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, + 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, + 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, + 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, + 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, + 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, + 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, + 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, + 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, + 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, + 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, + 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, + 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, + 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, + 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, + 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, + 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, + 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, + 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, + 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, + 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, + 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, + 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, + 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, + 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, + 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, + 0x70, 0xe0, 0x90, 0x3a, + ], + c_enc: [ + 0xb1, 0x69, 0x64, 0x77, 0xe6, 0x58, 0xb6, 0xf8, 0xe2, 0x4e, 0x02, 0x55, 0x52, 0xb4, + 0x8d, 0xd4, 0x84, 0x58, 0xf2, 0xcd, 0x75, 0x70, 0xc0, 0xe8, 0xce, 0xc4, 0xed, 0x4c, + 0xf7, 0x9b, 0xd5, 0xb6, 0x9e, 0xa8, 0x54, 0x12, 0x3b, 0x4e, 0xaf, 0x97, 0x8b, 0x14, + 0x2e, 0xb3, 0xef, 0x53, 0xaa, 0xfc, 0x78, 0x90, 0xdd, 0xa2, 0x8a, 0xfa, 0x25, 0xf1, + 0x45, 0xc8, 0xb9, 0x7f, 0x7b, 0x94, 0x50, 0xc1, 0xd5, 0xe0, 0xc3, 0x7d, 0xaf, 0x5e, + 0xd4, 0xec, 0xd9, 0xb6, 0x3d, 0xbc, 0xd2, 0x15, 0x11, 0x23, 0x13, 0x9b, 0xbc, 0x2b, + 0x65, 0x1a, 0x8f, 0x69, 0xcf, 0xbf, 0xb7, 0xcb, 0x60, 0x44, 0x78, 0xf3, 0xf2, 0x64, + 0xd9, 0xdd, 0x75, 0xcf, 0x31, 0x9e, 0x3e, 0xcd, 0xf5, 0xb3, 0x34, 0x26, 0x54, 0x85, + 0x7c, 0x52, 0xa1, 0xfc, 0x61, 0x40, 0x55, 0xa2, 0x46, 0xf5, 0x26, 0x3e, 0x85, 0x36, + 0x83, 0xef, 0x54, 0x41, 0x3b, 0xac, 0x99, 0x1a, 0xe6, 0x35, 0x01, 0x50, 0xe1, 0x34, + 0x52, 0xa3, 0xa6, 0x20, 0xc5, 0x3f, 0x80, 0xda, 0xcc, 0x7a, 0xf0, 0x59, 0x26, 0xd9, + 0xc5, 0x9a, 0x94, 0xe4, 0x78, 0x9a, 0xcc, 0x68, 0xd8, 0x51, 0x05, 0x6b, 0x75, 0xa7, + 0x4e, 0x2e, 0x1b, 0x38, 0xbf, 0xcb, 0x6d, 0xba, 0xab, 0x37, 0xa3, 0x8a, 0xe0, 0x2c, + 0x9c, 0x35, 0x25, 0x9e, 0x52, 0x84, 0xe4, 0xfe, 0x83, 0xdd, 0xb2, 0x29, 0x24, 0xa1, + 0xc4, 0x0a, 0xa2, 0x5e, 0xd1, 0xf5, 0xc0, 0x6d, 0xa1, 0x58, 0x31, 0xf0, 0x41, 0x50, + 0xa3, 0x7c, 0x1b, 0xa3, 0xd1, 0x17, 0x04, 0x93, 0xca, 0x29, 0xf3, 0x43, 0x4a, 0xfa, + 0x06, 0x9b, 0x46, 0xaf, 0xdc, 0x87, 0x0a, 0x29, 0x6f, 0xdc, 0x0e, 0xb6, 0x1b, 0x55, + 0x70, 0x77, 0xa1, 0xda, 0x1f, 0xe8, 0x22, 0xb6, 0xce, 0x24, 0x7c, 0x8e, 0x19, 0x9f, + 0xc4, 0x85, 0x14, 0x6f, 0x38, 0x4a, 0xcf, 0x5c, 0x52, 0x69, 0x7e, 0xfa, 0xcc, 0x5b, + 0xfe, 0x42, 0x02, 0xe8, 0x5f, 0x06, 0x4b, 0xc8, 0xe1, 0x2e, 0xee, 0x39, 0x79, 0x6d, + 0xfd, 0x13, 0x99, 0xb1, 0xc1, 0xe8, 0xc7, 0x4b, 0x5e, 0xc3, 0xc3, 0x1d, 0x2c, 0xfa, + 0x44, 0x87, 0x02, 0x5c, 0xeb, 0x5d, 0xb3, 0x55, 0x9d, 0x4b, 0x7b, 0xac, 0x02, 0x73, + 0xf1, 0x33, 0x51, 0xd2, 0xd1, 0x3c, 0xec, 0x0a, 0x44, 0x8c, 0x00, 0x11, 0x09, 0x45, + 0x2c, 0x40, 0x92, 0xc8, 0x11, 0x91, 0xa0, 0xda, 0xa9, 0x79, 0xe2, 0x6a, 0x96, 0x24, + 0xe4, 0x0c, 0xa4, 0xac, 0xcb, 0x63, 0x46, 0xaa, 0xe1, 0x88, 0xca, 0x09, 0x39, 0xdd, + 0x9f, 0x6b, 0x6e, 0x45, 0xe4, 0x1b, 0xca, 0xeb, 0xdc, 0x1d, 0xa8, 0x01, 0xcc, 0xd4, + 0xdc, 0x93, 0x32, 0x26, 0x6f, 0xb3, 0xeb, 0x23, 0x7b, 0x07, 0x72, 0x45, 0xa7, 0x91, + 0xec, 0xb4, 0x0e, 0x5c, 0x40, 0x56, 0xad, 0xd6, 0xb1, 0xb5, 0xf7, 0xf8, 0xfa, 0x10, + 0x4f, 0xba, 0x61, 0x3e, 0xd9, 0x29, 0xe1, 0xfa, 0xd2, 0x26, 0x47, 0x50, 0x35, 0xb6, + 0x1a, 0x9f, 0x85, 0xaf, 0xba, 0xfb, 0x16, 0x6b, 0x24, 0xc2, 0x4d, 0x2c, 0x28, 0x93, + 0x7b, 0x17, 0x70, 0xba, 0x26, 0x9c, 0x15, 0xeb, 0x2d, 0x9b, 0xdc, 0x2b, 0x83, 0xea, + 0xd8, 0xa0, 0x1d, 0xdb, 0x11, 0x08, 0x3b, 0x13, 0xd6, 0x2d, 0x57, 0x2c, 0xf7, 0x8d, + 0x5c, 0xba, 0x6f, 0x36, 0x52, 0xca, 0xc4, 0xd2, 0x4c, 0x71, 0xc5, 0x47, 0x27, 0x26, + 0x24, 0xc0, 0x78, 0xe0, 0xb9, 0x69, 0x68, 0xfe, 0x09, 0xd8, 0x3e, 0xf7, 0x30, 0x20, + 0x62, 0xbb, 0x5d, 0x3a, 0x2c, 0xcf, 0x73, 0x4e, 0x0f, 0xd3, 0x51, 0x01, 0xfd, 0x58, + 0x64, 0x73, 0x3f, 0x44, 0xd0, 0x75, 0xc3, 0x8b, 0x73, 0xf6, 0xbf, 0xb8, 0xc3, 0x9c, + 0x7b, 0x6b, 0x3d, 0xbc, 0xd1, 0x9a, 0x05, 0x89, 0x91, 0x86, 0x37, 0xf7, 0x5b, 0xbe, + 0x40, 0x15, 0x7b, 0x80, 0xe5, 0x9e, 0x55, 0x58, 0x50, 0x28, 0xa5, 0xec, 0x20, 0x1e, + 0x00, 0x8f, 0xf6, 0xf5, 0x12, 0xe2, 0x53, 0xcc, 0x9a, 0xcf, 0x62, 0x7d, 0x94, 0x35, + 0xdb, 0x6b, 0x14, 0xb9, 0x82, 0x48, 0x79, 0xf4, 0xe4, 0x0a, 0x36, 0xd5, 0xec, 0x94, + 0x2b, 0xff, 0x04, 0xfd, 0x90, 0xa6, 0xaf, 0x8c, 0x58, 0x1d, 0xf6, 0x09, 0xc4, 0x11, + 0xf4, 0x76, 0x11, 0x41, 0xd4, 0xa6, + ], + ock: [ + 0xdc, 0xf9, 0x34, 0xcf, 0x6a, 0x64, 0x90, 0x3f, 0x2d, 0x99, 0xa3, 0x07, 0xe1, 0x55, + 0xfb, 0x90, 0xe9, 0x7a, 0xc9, 0x0c, 0x38, 0x7f, 0x1b, 0xa5, 0xa6, 0xea, 0x43, 0xb5, + 0x91, 0xb0, 0x5d, 0x69, + ], + op: [ + 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, + 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, + 0x3a, 0x56, 0x6a, 0xaa, 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, + 0x02, 0xf5, 0x10, 0xe9, 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, + 0xc4, 0x69, 0x2d, 0x0c, 0x1b, 0x30, 0x33, 0x01, + ], + c_out: [ + 0x25, 0xf4, 0xbb, 0x9f, 0xb4, 0x45, 0x06, 0x78, 0x9c, 0xf5, 0x1d, 0xc3, 0xf6, 0x5f, + 0x17, 0xaf, 0xee, 0xe0, 0x34, 0x92, 0x79, 0xc7, 0x89, 0x28, 0x9b, 0x03, 0xd3, 0x8c, + 0x2e, 0x20, 0xd3, 0x12, 0x5d, 0xe7, 0xc5, 0x6e, 0x18, 0x29, 0x2d, 0xec, 0xc6, 0x41, + 0x81, 0xa7, 0xe9, 0xa7, 0xbc, 0x12, 0xeb, 0x97, 0x85, 0xf0, 0xdd, 0x51, 0xd5, 0x88, + 0x62, 0x00, 0xfb, 0x18, 0x7d, 0x2c, 0x16, 0x90, 0x65, 0xaf, 0x84, 0xcc, 0x02, 0x3d, + 0x6d, 0x63, 0xce, 0x05, 0x83, 0x28, 0xe2, 0x47, 0xb5, 0x98, + ], + note_type: Some([ + 0x96, 0x86, 0xaa, 0x36, 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, + 0xab, 0xcf, 0xac, 0x88, 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, + 0x07, 0x2d, 0x2d, 0x18, + ]), }, ] } diff --git a/src/value.rs b/src/value.rs index 5ece74af2..8525ab8fe 100644 --- a/src/value.rs +++ b/src/value.rs @@ -318,7 +318,7 @@ impl ValueCommitment { pallas::Scalar::from(abs_value) }; - let V_zsa = note_type.0; + let V_zsa = note_type.cv_base(); ValueCommitment(V_zsa * value + R * rcv.0) } From 1420f84932e23fda0655570e3bde9e578a8f41ae Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Mon, 19 Sep 2022 13:26:08 +0300 Subject: [PATCH 05/92] Zsa builder (#4) + Updated test bsk_consistent_with_bvk to verify mixed note types. + Added NoteType support to the builder and the bundle. + added split_flag to SpentInfo and as input to the Circuit (currently commented out) + added conditional cv_sum calculation (currently commented out) + added padding to actions --- .gitignore | 2 + benches/circuit.rs | 9 ++- benches/note_decryption.rs | 17 ++++- src/action.rs | 8 ++- src/builder.rs | 133 +++++++++++++++++++++++++++++-------- src/circuit.rs | 4 +- src/note.rs | 7 +- src/note/note_type.rs | 33 +++++++-- src/note_encryption.rs | 9 +-- src/tree.rs | 2 +- src/value.rs | 74 +++++++++++++++++---- tests/builder.rs | 17 ++++- 12 files changed, 250 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index 57ee1a9ad..d7f36bd31 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ Cargo.lock .vscode .idea +action-circuit-layout.png +proptest-regressions/*.txt diff --git a/benches/circuit.rs b/benches/circuit.rs index 3140a90a4..6400513e2 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -6,6 +6,7 @@ use criterion::{BenchmarkId, Criterion}; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; +use orchard::note::NoteType; use orchard::{ builder::Builder, bundle::Flags, @@ -32,7 +33,13 @@ fn criterion_benchmark(c: &mut Criterion) { ); for _ in 0..num_recipients { builder - .add_recipient(None, recipient, NoteValue::from_raw(10), None) + .add_recipient( + None, + recipient, + NoteValue::from_raw(10), + NoteType::native(), + None, + ) .unwrap(); } let bundle: Bundle<_, i64> = builder.build(rng).unwrap(); diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 3ebbc6ed5..28e02de61 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -4,6 +4,7 @@ use orchard::{ bundle::Flags, circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, + note::NoteType, note_encryption::{CompactAction, OrchardDomain}, value::NoteValue, Anchor, Bundle, @@ -52,10 +53,22 @@ fn bench_note_decryption(c: &mut Criterion) { // The builder pads to two actions, and shuffles their order. Add two recipients // so the first action is always decryptable. builder - .add_recipient(None, recipient, NoteValue::from_raw(10), None) + .add_recipient( + None, + recipient, + NoteValue::from_raw(10), + NoteType::native(), + None, + ) .unwrap(); builder - .add_recipient(None, recipient, NoteValue::from_raw(10), None) + .add_recipient( + None, + recipient, + NoteValue::from_raw(10), + NoteType::native(), + None, + ) .unwrap(); let bundle: Bundle<_, i64> = builder.build(rng).unwrap(); bundle diff --git a/src/action.rs b/src/action.rs index b6396ed91..b1eda4819 100644 --- a/src/action.rs +++ b/src/action.rs @@ -126,7 +126,7 @@ pub(crate) mod testing { use proptest::prelude::*; - use crate::note::NoteType; + use crate::note::note_type::testing::arb_note_type; use crate::{ note::{ commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, @@ -147,12 +147,13 @@ pub(crate) mod testing { nf in arb_nullifier(), rk in arb_spendauth_verification_key(), note in arb_note(output_value), + note_type in arb_note_type() ) -> Action<()> { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( spend_value - output_value, ValueCommitTrapdoor::zero(), - NoteType::native() + note_type ); // FIXME: make a real one from the note. let encrypted_note = TransmittedNoteCiphertext { @@ -179,12 +180,13 @@ pub(crate) mod testing { note in arb_note(output_value), rng_seed in prop::array::uniform32(prop::num::u8::ANY), fake_sighash in prop::array::uniform32(prop::num::u8::ANY), + note_type in arb_note_type() ) -> Action> { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( spend_value - output_value, ValueCommitTrapdoor::zero(), - NoteType::native() + note_type ); // FIXME: make a real one from the note. diff --git a/src/builder.rs b/src/builder.rs index 1a7ccbec1..a3ba5ff84 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -2,6 +2,7 @@ use core::fmt; use core::iter; +use std::collections::HashMap; use ff::Field; use nonempty::NonEmpty; @@ -57,13 +58,15 @@ impl From for Error { } /// Information about a specific note to be spent in an [`Action`]. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct SpendInfo { pub(crate) dummy_sk: Option, pub(crate) fvk: FullViewingKey, pub(crate) scope: Scope, pub(crate) note: Note, pub(crate) merkle_path: MerklePath, + // a flag to indicate whether the value of the note will be counted in the `ValueSum` of the action. + pub(crate) split_flag: bool, } impl SpendInfo { @@ -84,14 +87,15 @@ impl SpendInfo { scope, note, merkle_path, + split_flag: false, }) } /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(rng: &mut impl RngCore) -> Self { - let (sk, fvk, note) = Note::dummy(rng, None); + fn dummy(note_type: NoteType, rng: &mut impl RngCore) -> Self { + let (sk, fvk, note) = Note::dummy(rng, None, note_type); let merkle_path = MerklePath::dummy(rng); SpendInfo { @@ -102,16 +106,26 @@ impl SpendInfo { scope: Scope::External, note, merkle_path, + split_flag: false, } } + + /// Duplicates the spend info and set the split flag to `true`. + fn create_split_spend(&self) -> Self { + let mut split_spend = SpendInfo::new(self.fvk.clone(), self.note, self.merkle_path.clone()) + .expect("The spend info is valid"); + split_spend.split_flag = true; + split_spend + } } /// Information about a specific recipient to receive funds in an [`Action`]. -#[derive(Debug)] +#[derive(Debug, Clone)] struct RecipientInfo { ovk: Option, recipient: Address, value: NoteValue, + note_type: NoteType, memo: Option<[u8; 512]>, } @@ -127,6 +141,7 @@ impl RecipientInfo { ovk: None, recipient, value: NoteValue::zero(), + note_type: NoteType::native(), memo: None, } } @@ -150,7 +165,17 @@ impl ActionInfo { } /// Returns the value sum for this action. + /// Split notes does not contribute to the value sum. fn value_sum(&self) -> ValueSum { + // TODO: Aurel, uncomment when circuit for split flag is implemented. + // let spent_value = self + // .spend + // .split_flag + // .then(|| self.spend.note.value()) + // .unwrap_or_else(NoteValue::zero); + // + // spent_value - self.output.value + self.spend.note.value() - self.output.value } @@ -160,8 +185,15 @@ impl ActionInfo { /// /// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend fn build(self, mut rng: impl RngCore) -> (Action, Circuit) { + assert_eq!( + self.output.note_type, + self.spend.note.note_type(), + "spend and recipient note types must be equal" + ); + let v_net = self.value_sum(); - let cv_net = ValueCommitment::derive(v_net, self.rcv, NoteType::native()); + let note_type = self.output.note_type; + let cv_net = ValueCommitment::derive(v_net, self.rcv, note_type); let nf_old = self.spend.note.nullifier(&self.spend.fvk); let ak: SpendValidatingKey = self.spend.fvk.clone().into(); @@ -275,6 +307,7 @@ impl Builder { scope, note, merkle_path, + split_flag: false, }); Ok(()) @@ -286,6 +319,7 @@ impl Builder { ovk: Option, recipient: Address, value: NoteValue, + note_type: NoteType, memo: Option<[u8; 512]>, ) -> Result<(), &'static str> { if !self.flags.outputs_enabled() { @@ -296,6 +330,7 @@ impl Builder { ovk, recipient, value, + note_type, memo, }); @@ -332,23 +367,31 @@ impl Builder { /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. pub fn build>( - mut self, + self, mut rng: impl RngCore, ) -> Result, V>, Error> { + let mut pre_actions: Vec<_> = Vec::new(); + // Pair up the spends and recipients, extending with dummy values as necessary. - let pre_actions: Vec<_> = { - let num_spends = self.spends.len(); - let num_recipients = self.recipients.len(); + for (note_type, (mut spends, mut recipients)) in partition(&self.spends, &self.recipients) { + let num_spends = spends.len(); + let num_recipients = recipients.len(); let num_actions = [num_spends, num_recipients, MIN_ACTIONS] .iter() .max() .cloned() .unwrap(); - self.spends.extend( - iter::repeat_with(|| SpendInfo::dummy(&mut rng)).take(num_actions - num_spends), + // use the first spend to create split spend(s) or create a dummy if empty. + let dummy_spend = spends.first().map_or_else( + || SpendInfo::dummy(note_type, &mut rng), + |s| s.create_split_spend(), ); - self.recipients.extend( + + // Extend the spends and recipients with dummy values. + spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); + + recipients.extend( iter::repeat_with(|| RecipientInfo::dummy(&mut rng)) .take(num_actions - num_recipients), ); @@ -356,15 +399,16 @@ impl Builder { // Shuffle the spends and recipients, so that learning the position of a // specific spent note or output note doesn't reveal anything on its own about // the meaning of that note in the transaction context. - self.spends.shuffle(&mut rng); - self.recipients.shuffle(&mut rng); - - self.spends - .into_iter() - .zip(self.recipients.into_iter()) - .map(|(spend, recipient)| ActionInfo::new(spend, recipient, &mut rng)) - .collect() - }; + spends.shuffle(&mut rng); + recipients.shuffle(&mut rng); + + pre_actions.extend( + spends + .into_iter() + .zip(recipients.into_iter()) + .map(|(spend, recipient)| ActionInfo::new(spend, recipient, &mut rng)), + ); + } // Move some things out of self that we will need. let flags = self.flags; @@ -416,6 +460,30 @@ impl Builder { } } +/// partition a list of spends and recipients by note types. +fn partition( + spends: &[SpendInfo], + recipients: &[RecipientInfo], +) -> HashMap, Vec)> { + let mut hm = HashMap::new(); + + for s in spends.iter() { + hm.entry(s.note.note_type()) + .or_insert((vec![], vec![])) + .0 + .push(s.clone()); + } + + for r in recipients.iter() { + hm.entry(r.note_type) + .or_insert((vec![], vec![])) + .1 + .push(r.clone()) + } + + hm +} + /// Marker trait representing bundle signatures in the process of being created. pub trait InProgressSignatures: fmt::Debug { /// The authorization type of an Orchard action in the process of being authorized. @@ -680,6 +748,7 @@ pub mod testing { use proptest::collection::vec; use proptest::prelude::*; + use crate::note::NoteType; use crate::{ address::testing::arb_address, bundle::{Authorized, Bundle, Flags}, @@ -707,7 +776,7 @@ pub mod testing { sk: SpendingKey, anchor: Anchor, notes: Vec<(Note, MerklePath)>, - recipient_amounts: Vec<(Address, NoteValue)>, + recipient_amounts: Vec<(Address, NoteValue, NoteType)>, } impl ArbitraryBundleInputs { @@ -721,12 +790,12 @@ pub mod testing { builder.add_spend(fvk.clone(), note, path).unwrap(); } - for (addr, value) in self.recipient_amounts.into_iter() { + for (addr, value, note_type) in self.recipient_amounts.into_iter() { let scope = fvk.scope_for_address(&addr).unwrap(); let ovk = fvk.to_ovk(scope); builder - .add_recipient(Some(ovk.clone()), addr, value, None) + .add_recipient(Some(ovk.clone()), addr, value, note_type, None) .unwrap(); } @@ -760,9 +829,11 @@ pub mod testing { recipient_amounts in vec( arb_address().prop_flat_map(move |a| { arb_positive_note_value(MAX_NOTE_VALUE / n_recipients as u64) - .prop_map(move |v| (a, v)) + .prop_map(move |v| { + (a,v, NoteType::native()) + }) }), - n_recipients as usize + n_recipients as usize, ), rng_seed in prop::array::uniform32(prop::num::u8::ANY) ) -> ArbitraryBundleInputs { @@ -810,6 +881,8 @@ mod tests { use rand::rngs::OsRng; use super::Builder; + // use crate::keys::{IssuerAuthorizingKey, IssuerValidatingKey}; + use crate::note::NoteType; use crate::{ bundle::{Authorized, Bundle, Flags}, circuit::ProvingKey, @@ -834,7 +907,13 @@ mod tests { ); builder - .add_recipient(None, recipient, NoteValue::from_raw(5000), None) + .add_recipient( + None, + recipient, + NoteValue::from_raw(5000), + NoteType::native(), + None, + ) .unwrap(); let balance: i64 = builder.value_balance().unwrap(); assert_eq!(balance, -5000); diff --git a/src/circuit.rs b/src/circuit.rs index 0b271d750..97d5efda2 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -977,7 +977,7 @@ mod tests { }; fn generate_circuit_instance(mut rng: R) -> (Circuit, Instance) { - let (_, fvk, spent_note) = Note::dummy(&mut rng, None); + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, NoteType::native()); let sender_address = spent_note.recipient(); let nk = *fvk.nk(); @@ -987,7 +987,7 @@ mod tests { let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old)); + let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old), NoteType::native()); let cmx = output_note.commitment().into(); let value = spent_note.value() - output_note.value(); diff --git a/src/note.rs b/src/note.rs index c2edf4988..04938cbe0 100644 --- a/src/note.rs +++ b/src/note.rs @@ -176,6 +176,7 @@ impl Note { pub(crate) fn dummy( rng: &mut impl RngCore, rho: Option, + note_type: NoteType, ) -> (SpendingKey, FullViewingKey, Self) { let sk = SpendingKey::random(rng); let fvk: FullViewingKey = (&sk).into(); @@ -184,7 +185,7 @@ impl Note { let note = Note::new( recipient, NoteValue::zero(), - NoteType::native(), + note_type, rho.unwrap_or_else(|| Nullifier::dummy(rng)), rng, ); @@ -202,7 +203,7 @@ impl Note { self.value } - /// Returns the note type + /// Returns the note type of this note. pub fn note_type(&self) -> NoteType { self.note_type } @@ -309,7 +310,7 @@ pub mod testing { } prop_compose! { - /// Generate an action without authorization data. + /// Generate an arbitrary note pub fn arb_note(value: NoteValue)( recipient in arb_address(), rho in arb_nullifier(), diff --git a/src/note/note_type.rs b/src/note/note_type.rs index 6075259e3..8ac04b00b 100644 --- a/src/note/note_type.rs +++ b/src/note/note_type.rs @@ -1,16 +1,18 @@ use group::GroupEncoding; use halo2_proofs::arithmetic::CurveExt; use pasta_curves::pallas; +use std::hash::{Hash, Hasher}; + use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_V_BYTES}; use crate::keys::IssuerValidatingKey; /// Note type identifier. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct NoteType(pub(crate) pallas::Point); +#[derive(Clone, Copy, Debug, Eq)] +pub struct NoteType(pallas::Point); -const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; +pub const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; // the hasher used to derive the assetID #[allow(non_snake_case)] @@ -62,16 +64,29 @@ impl NoteType { } } +impl Hash for NoteType { + fn hash(&self, h: &mut H) { + h.write(&self.to_bytes()); + h.finish(); + } +} + +impl PartialEq for NoteType { + fn eq(&self, other: &Self) -> bool { + bool::from(self.0.ct_eq(&other.0)) + } +} + /// Generators for property testing. #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { + use super::NoteType; + use proptest::prelude::*; use crate::keys::{testing::arb_spending_key, IssuerAuthorizingKey, IssuerValidatingKey}; - use super::NoteType; - prop_compose! { /// Generate a uniformly distributed note type pub fn arb_note_type()( @@ -89,4 +104,12 @@ pub mod testing { } } } + + prop_compose! { + /// Generate the native note type + pub fn native_note_type()(_i in 0..10) -> NoteType { + // TODO: remove _i + NoteType::native() + } + } } diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 5d955e2cb..57dd76589 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -409,6 +409,7 @@ mod tests { EphemeralKeyBytes, }; + use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; use crate::note::NoteType; use crate::{ action::Action, @@ -426,7 +427,6 @@ mod tests { }; use super::{get_note_version, orchard_parse_note_plaintext_without_memo}; - use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; proptest! { #[test] @@ -453,6 +453,7 @@ mod tests { // Check. assert_eq!(parsed_note, note); assert_eq!(parsed_recipient, note.recipient()); + if parsed_note.note_type().is_native().into() { assert_eq!(parsed_version, 0x02); assert_eq!(&parsed_memo, memo); @@ -508,17 +509,13 @@ mod tests { assert_eq!(ock.as_ref(), tv.ock); let recipient = Address::from_parts(d, pk_d); -<<<<<<< HEAD - let note = Note::from_parts(recipient, value, NoteType::native(), rho, rseed).unwrap(); -======= let note_type = match tv.note_type { None => NoteType::native(), Some(type_bytes) => NoteType::from_bytes(&type_bytes).unwrap(), }; - let note = Note::from_parts(recipient, value, note_type, rho, rseed); ->>>>>>> ZSA note encryption in Orchard crate (#3) + let note = Note::from_parts(recipient, value, note_type, rho, rseed).unwrap(); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); let action = Action::from_parts( diff --git a/src/tree.rs b/src/tree.rs index c2854200b..7e9601312 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -77,7 +77,7 @@ impl Anchor { /// The Merkle path from a leaf of the note commitment tree /// to its anchor. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct MerklePath { position: u32, auth_path: [MerkleHashOrchard; MERKLE_DEPTH_ORCHARD], diff --git a/src/value.rs b/src/value.rs index 8525ab8fe..ce5d6c94f 100644 --- a/src/value.rs +++ b/src/value.rs @@ -40,6 +40,7 @@ use core::fmt::{self, Debug}; use core::iter::Sum; use core::ops::{Add, RangeInclusive, Sub}; +use std::ops::Neg; use bitvec::{array::BitArray, order::Lsb0}; use ff::{Field, PrimeField}; @@ -189,6 +190,18 @@ impl Add for ValueSum { } } +impl Neg for ValueSum { + type Output = Option; + + #[allow(clippy::suspicious_arithmetic_impl)] + fn neg(self) -> Self::Output { + self.0 + .checked_neg() + .filter(|v| VALUE_SUM_RANGE.contains(v)) + .map(ValueSum) + } +} + impl<'a> Sum<&'a ValueSum> for Result { fn sum>(iter: I) -> Self { iter.fold(Ok(ValueSum(0)), |acc, v| (acc? + *v).ok_or(OverflowError)) @@ -423,7 +436,8 @@ pub mod testing { #[cfg(test)] mod tests { - use crate::note::note_type::testing::arb_note_type; + use crate::note::note_type::testing::{arb_note_type, native_note_type}; + use crate::note::NoteType; use proptest::prelude::*; @@ -433,43 +447,77 @@ mod tests { }; use crate::primitives::redpallas; - fn _bsk_consistent_with_bvk(values: &[(ValueSum, ValueCommitTrapdoor)], note_type: NoteType) { - let value_balance = values + fn _bsk_consistent_with_bvk( + native_values: &[(ValueSum, ValueCommitTrapdoor, NoteType)], + arb_values: &[(ValueSum, ValueCommitTrapdoor, NoteType)], + neg_trapdoors: &[ValueCommitTrapdoor], + ) { + // for each arb value, create a negative value with a different trapdoor + let neg_arb_values: Vec<_> = arb_values + .iter() + .cloned() + .zip(neg_trapdoors.iter().cloned()) + .map(|((value, _, note_type), rcv)| ((-value).unwrap(), rcv, note_type)) + .collect(); + + let native_value_balance = native_values .iter() - .map(|(value, _)| value) + .map(|(value, _, _)| value) .sum::>() .expect("we generate values that won't overflow"); + let values = [native_values, arb_values, &neg_arb_values].concat(); + let bsk = values .iter() - .map(|(_, rcv)| rcv) + .map(|(_, rcv, _)| rcv) .sum::() .into_bsk(); let bvk = (values .iter() - .map(|(value, rcv)| ValueCommitment::derive(*value, *rcv, note_type)) + .map(|(value, rcv, note_type)| ValueCommitment::derive(*value, *rcv, *note_type)) .sum::() - - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero(), note_type)) + - ValueCommitment::derive( + native_value_balance, + ValueCommitTrapdoor::zero(), + NoteType::native(), + )) .into_bvk(); assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); } + proptest! { + #[test] + fn bsk_consistent_with_bvk_native_only( + native_values in (1usize..10).prop_flat_map(|n_values| + arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_note_type()), n_values) + ) + ), + ) { + // Test with native note type (zec) only + _bsk_consistent_with_bvk(&native_values, &[], &[]); + } + } + proptest! { #[test] fn bsk_consistent_with_bvk( - values in (1usize..10).prop_flat_map(|n_values| + native_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_note_type()), n_values) ) ), - arb_note_type in arb_note_type(), + (arb_values,neg_trapdoors) in (1usize..10).prop_flat_map(|n_values| + (arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_note_type()), n_values) + ), prop::collection::vec(arb_trapdoor(), n_values)) + ), ) { // Test with native note type (zec) - _bsk_consistent_with_bvk(&values, NoteType::native()); - // Test with arbitrary note type - _bsk_consistent_with_bvk(&values, arb_note_type); + _bsk_consistent_with_bvk(&native_values, &arb_values, &neg_trapdoors); } } } diff --git a/tests/builder.rs b/tests/builder.rs index f9b0f2717..428ebf81c 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -1,4 +1,5 @@ use incrementalmerkletree::{bridgetree::BridgeTree, Hashable, Tree}; +use orchard::note::NoteType; use orchard::{ builder::Builder, bundle::{Authorized, Flags}, @@ -43,7 +44,13 @@ fn bundle_chain() { let mut builder = Builder::new(Flags::from_parts(false, true), anchor); assert_eq!( - builder.add_recipient(None, recipient, NoteValue::from_raw(5000), None), + builder.add_recipient( + None, + recipient, + NoteValue::from_raw(5000), + NoteType::native(), + None + ), Ok(()) ); let unauthorized = builder.build(&mut rng).unwrap(); @@ -85,7 +92,13 @@ fn bundle_chain() { let mut builder = Builder::new(Flags::from_parts(true, true), anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!( - builder.add_recipient(None, recipient, NoteValue::from_raw(5000), None), + builder.add_recipient( + None, + recipient, + NoteValue::from_raw(5000), + NoteType::native(), + None + ), Ok(()) ); let unauthorized = builder.build(&mut rng).unwrap(); From 0b2988acc7f3ceed4593c855b6cfdba87aaafea0 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:32:16 +0300 Subject: [PATCH 06/92] Issuance (#12) - added IssueBundle and IssueAction - added a builder for IssueBundle - added verify_issue_bundle() for consensus verification. - unit tests. --- src/builder.rs | 1 - src/bundle/commitments.rs | 30 + src/issuance.rs | 1094 +++++++++++++++++++++++++++++++++++++ src/keys.rs | 42 +- src/lib.rs | 1 + src/note.rs | 22 + src/note/note_type.rs | 23 +- src/value.rs | 5 + 8 files changed, 1207 insertions(+), 11 deletions(-) create mode 100644 src/issuance.rs diff --git a/src/builder.rs b/src/builder.rs index a3ba5ff84..a6933276d 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -881,7 +881,6 @@ mod tests { use rand::rngs::OsRng; use super::Builder; - // use crate::keys::{IssuerAuthorizingKey, IssuerValidatingKey}; use crate::note::NoteType; use crate::{ bundle::{Authorized, Bundle, Flags}, diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index ef440a272..40808b57f 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -3,12 +3,15 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; use crate::bundle::{Authorization, Authorized, Bundle}; +use crate::issuance::{IssueAuth, IssueBundle, Signed}; const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActCHash"; const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; +const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcZSAIssue"; +const ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION: &[u8; 16] = b"ZTxAuthZSAOrHash"; fn hasher(personal: &[u8; 16]) -> State { Params::new().hash_length(32).personal(personal).to_state() @@ -90,3 +93,30 @@ pub(crate) fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2 pub fn hash_bundle_auth_empty() -> Blake2bHash { hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION).finalize() } + +/// Construct the commitment for the issue bundle +pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION); + + for action in bundle.actions().iter() { + for note in action.notes().iter() { + h.update(¬e.recipient().to_raw_address_bytes()); + h.update(¬e.value().to_bytes()); + h.update(¬e.note_type().to_bytes()); + h.update(¬e.rho().to_bytes()); + h.update(note.rseed().as_bytes()); + } + h.update(action.asset_desc().as_bytes()); + h.update(&[u8::from(action.is_finalized())]); + } + h.update(&bundle.ik().to_bytes()); + h.finalize() +} + +/// Construct the commitment to the authorizing data of an +/// authorized issue bundle +pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION); + h.update(&<[u8; 64]>::from(bundle.authorization().signature())); + h.finalize() +} diff --git a/src/issuance.rs b/src/issuance.rs new file mode 100644 index 000000000..b5ac7aaa3 --- /dev/null +++ b/src/issuance.rs @@ -0,0 +1,1094 @@ +//! Structs related to issuance bundles and the associated logic. +use blake2b_simd::Hash as Blake2bHash; +use nonempty::NonEmpty; +use rand::{CryptoRng, RngCore}; +use std::collections::HashSet; +use std::fmt; + +use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; +use crate::issuance::Error::{ + IssueActionAlreadyFinalized, IssueActionIncorrectNoteType, IssueActionNotFound, + IssueActionPreviouslyFinalizedNoteType, IssueBundleIkMismatchNoteType, + IssueBundleInvalidSignature, WrongAssetDescSize, +}; +use crate::keys::{IssuerAuthorizingKey, IssuerValidatingKey}; +use crate::note::note_type::MAX_ASSET_DESCRIPTION_SIZE; +use crate::note::{NoteType, Nullifier}; +use crate::value::NoteValue; +use crate::{ + primitives::redpallas::{self, SpendAuth}, + Address, Note, +}; + +/// A bundle of actions to be applied to the ledger. +#[derive(Debug)] +pub struct IssueBundle { + /// The issuer key for the note being created. + ik: IssuerValidatingKey, + /// The list of issue actions that make up this bundle. + actions: Vec, + /// The authorization for this action. + authorization: T, +} + +/// An issue action applied to the global ledger. +/// +/// Externally, this creates new zsa notes (adding a commitment to the global ledger). +#[derive(Debug, Clone)] +pub struct IssueAction { + /// Asset description for verification. + asset_desc: String, + /// The newly issued notes. + notes: NonEmpty, + /// `finalize` will prevent further issuance of the same asset type. + finalize: bool, +} + +impl IssueAction { + /// Constructs a new `IssueAction`. + pub fn new(asset_desc: String, note: &Note) -> Self { + IssueAction { + asset_desc, + notes: NonEmpty { + head: *note, + tail: vec![], + }, + finalize: false, + } + } + + /// Constructs an `IssueAction` from its constituent parts. + pub fn from_parts(asset_desc: String, notes: NonEmpty, finalize: bool) -> Self { + IssueAction { + asset_desc, + notes, + finalize, + } + } + + /// Returns the asset description for the note being created. + pub fn asset_desc(&self) -> &str { + &self.asset_desc + } + + /// Returns the issued notes. + pub fn notes(&self) -> &NonEmpty { + &self.notes + } + + /// Returns whether the asset type was finalized in this action. + pub fn is_finalized(&self) -> bool { + self.finalize + } + + /// Return the `NoteType` if the provided `ik` is used to derive the `note_type` for **all** internal notes. + fn are_note_types_derived_correctly( + &self, + ik: &IssuerValidatingKey, + ) -> Result { + match self + .notes + .iter() + .try_fold(self.notes().head.note_type(), |note_type, ¬e| { + // Fail if not all note types are equal + note.note_type() + .eq(¬e_type) + .then(|| note_type) + .ok_or(IssueActionIncorrectNoteType) + }) { + Ok(note_type) => note_type // check that the note_type was properly derived. + .eq(&NoteType::derive(ik, &self.asset_desc)) + .then(|| note_type) + .ok_or(IssueBundleIkMismatchNoteType), + Err(e) => Err(e), + } + } +} + +/// Defines the authorization type of an Issue bundle. +pub trait IssueAuth: fmt::Debug {} + +/// Marker for an unauthorized bundle with no proofs or signatures. +#[derive(Debug)] +pub struct Unauthorized; + +/// Marker for an unauthorized bundle with injected sighash. +#[derive(Debug)] +pub struct Prepared { + sighash: [u8; 32], +} + +/// Marker for an authorized bundle. +#[derive(Debug)] +pub struct Signed { + signature: redpallas::Signature, +} + +impl Signed { + /// Returns the signature for this authorization. + pub fn signature(&self) -> &redpallas::Signature { + &self.signature + } +} + +impl IssueAuth for Unauthorized {} +impl IssueAuth for Prepared {} +impl IssueAuth for Signed {} + +impl IssueBundle { + /// Returns the issuer verification key for the bundle. + pub fn ik(&self) -> &IssuerValidatingKey { + &self.ik + } + /// Return the actions for a given `IssueBundle`. + pub fn actions(&self) -> &Vec { + &self.actions + } + + /// Returns the authorization for this action. + pub fn authorization(&self) -> &T { + &self.authorization + } + + /// Find an action by `ik` and `asset_desc` for a given `IssueBundle`. + pub fn get_action(&self, asset_desc: String) -> Option<&IssueAction> { + self.actions.iter().find(|a| a.asset_desc.eq(&asset_desc)) + } + + /// Find an action by `note_type` for a given `IssueBundle`. + pub fn get_action_by_type(&self, note_type: NoteType) -> Option<&IssueAction> { + let action = self + .actions + .iter() + .find(|a| NoteType::derive(&self.ik, &a.asset_desc).eq(¬e_type)); + action + } + + /// Computes a commitment to the effects of this bundle, suitable for inclusion within + /// a transaction ID. + pub fn commitment(&self) -> IssueBundleCommitment { + IssueBundleCommitment(hash_issue_bundle_txid_data(self)) + } +} + +impl IssueBundle { + /// Constructs a new `IssueBundle`. + pub fn new(ik: IssuerValidatingKey) -> IssueBundle { + IssueBundle { + ik, + actions: Vec::new(), + authorization: Unauthorized, + } + } + + /// Add a new note to the `IssueBundle`. + /// + /// Rho will be randomly sampled, similar to dummy note generation. + /// + /// # Panics + /// + /// Panics if `asset_desc` is empty or longer than 512 bytes. + pub fn add_recipient( + &mut self, + asset_desc: String, + recipient: Address, + value: NoteValue, + finalize: bool, + mut rng: impl RngCore, + ) -> Result { + if !is_asset_desc_valid(&asset_desc) { + return Err(WrongAssetDescSize); + } + + let note_type = NoteType::derive(&self.ik, &asset_desc); + + let note = Note::new( + recipient, + value, + note_type, + Nullifier::dummy(&mut rng), + &mut rng, + ); + + match self + .actions + .iter_mut() + .find(|issue_action| issue_action.asset_desc.eq(&asset_desc)) + { + // Append to an existing IssueAction. + Some(action) => { + if action.finalize { + return Err(IssueActionAlreadyFinalized); + }; + action.notes.push(note); + finalize.then(|| action.finalize = true); + } + // Insert a new IssueAction. + None => { + let mut action = IssueAction::new(asset_desc, ¬e); + finalize.then(|| action.finalize = true); + self.actions.push(action); + } + } + + Ok(note_type) + } + + /// Finalizes a given `IssueAction` + /// + /// # Panics + /// + /// Panics if `asset_desc` is empty or longer than 512 bytes. + pub fn finalize_action(&mut self, asset_desc: String) -> Result<(), Error> { + if !is_asset_desc_valid(&asset_desc) { + return Err(WrongAssetDescSize); + } + + match self + .actions + .iter_mut() + .find(|issue_action| issue_action.asset_desc.eq(&asset_desc)) + { + Some(issue_action) => { + issue_action.finalize = true; + } + None => { + return Err(IssueActionNotFound); + } + } + + Ok(()) + } + + /// Loads the sighash into the bundle, as preparation for signing. + pub fn prepare(self, sighash: [u8; 32]) -> IssueBundle { + IssueBundle { + ik: self.ik, + actions: self.actions, + authorization: Prepared { sighash }, + } + } +} + +impl IssueBundle { + /// Sign the `IssueBundle`. + /// The call makes sure that the provided `isk` matches the `ik` and the driven `note_type` for each note in the bundle. + pub fn sign( + self, + mut rng: R, + isk: &IssuerAuthorizingKey, + ) -> Result, Error> { + let expected_ik: IssuerValidatingKey = (isk).into(); + + // Make sure the `expected_ik` matches the note_type for all notes. + self.actions.iter().try_for_each(|action| { + action + .are_note_types_derived_correctly(&expected_ik) + .map(|_| ()) // Transform Result into Result<(),Error)>. + })?; + + Ok(IssueBundle { + ik: self.ik, + actions: self.actions, + authorization: Signed { + signature: isk.sign(&mut rng, &self.authorization.sighash), + }, + }) + } +} + +/// A commitment to a bundle of actions. +/// +/// This commitment is non-malleable, in the sense that a bundle's commitment will only +/// change if the effects of the bundle are altered. +#[derive(Debug)] +pub struct IssueBundleCommitment(pub Blake2bHash); + +impl From for [u8; 32] { + /// Serializes issue bundle commitment as byte array + fn from(commitment: IssueBundleCommitment) -> Self { + // The commitment uses BLAKE2b-256. + commitment.0.as_bytes().try_into().unwrap() + } +} + +/// A commitment to the authorizing data within a bundle of actions. +#[derive(Debug)] +pub struct IssueBundleAuthorizingCommitment(pub Blake2bHash); + +impl IssueBundle { + /// Computes a commitment to the authorizing data within for this bundle. + /// + /// This together with `IssueBundle::commitment` bind the entire bundle. + pub fn authorizing_commitment(&self) -> IssueBundleAuthorizingCommitment { + IssueBundleAuthorizingCommitment(hash_issue_bundle_auth_data(self)) + } +} + +fn is_asset_desc_valid(asset_desc: &str) -> bool { + !asset_desc.is_empty() && asset_desc.bytes().len() <= MAX_ASSET_DESCRIPTION_SIZE +} + +/// Validation for Orchard IssueBundles +/// +/// A set of previously finalized asset types must be provided. +/// In case of success, the `Result` will contain a set of the provided **and** the newly finalized `NoteType`s +/// +/// The following checks are performed: +/// * For the `IssueBundle`: +/// * the Signature on top of the provided `sighash` verifies correctly. +/// * For each `IssueAction`: +/// * Asset description size is collect. +/// * `NoteType` for the `IssueAction` has not been previously finalized. +/// * For each `Note` inside an `IssueAction`: +/// * All notes have the same, correct `NoteType` +pub fn verify_issue_bundle<'a>( + bundle: &IssueBundle, + sighash: [u8; 32], + previously_finalized: &'a mut HashSet, // The current note_type finalization set. +) -> Result<&'a mut HashSet, Error> { + if let Err(e) = bundle.ik.verify(&sighash, &bundle.authorization.signature) { + return Err(IssueBundleInvalidSignature(e)); + }; + + // Any IssueAction could have just one properly derived NoteType. + bundle + .actions() + .iter() + .try_fold(previously_finalized, |acc, action| { + if !is_asset_desc_valid(action.asset_desc()) { + return Err(WrongAssetDescSize); + } + + // Fail if any note in the IssueAction has incorrect note type. + let note_type = action.are_note_types_derived_correctly(bundle.ik())?; + + // Fail if the current note_type was previously finalized. + if acc.contains(¬e_type) { + return Err(IssueActionPreviouslyFinalizedNoteType(note_type)); + } + + // Add to finalization set, if needed. + if action.is_finalized() { + acc.insert(note_type); + } + + // Proceed with the new accumulated note_type finalization set. + Ok(acc) + }) + + // The iterator will return the the new accumulated note_type finalization set or fail. +} + +/// Errors produced during the issuance process +#[derive(Debug, PartialEq, Eq)] +pub enum Error { + /// Unable to add note to the IssueAction since it has already been finalized. + IssueActionAlreadyFinalized, + /// The requested IssueAction not exists in the bundle. + IssueActionNotFound, + /// Not all `NoteType`s are the same inside the action. + IssueActionIncorrectNoteType, + /// The provided `isk` and the driven `ik` does not match at least one note type. + IssueBundleIkMismatchNoteType, + /// `asset_desc` should be between 1 and 512 bytes. + WrongAssetDescSize, + + /// Verification errors: + /// Invalid signature. + IssueBundleInvalidSignature(reddsa::Error), + /// The provided `NoteType` has been previously finalized. + IssueActionPreviouslyFinalizedNoteType(NoteType), +} + +impl std::error::Error for Error {} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + IssueActionAlreadyFinalized => { + write!( + f, + "unable to add note to the IssueAction since it has already been finalized" + ) + } + IssueActionNotFound => { + write!(f, "the requested IssueAction not exists in the bundle.") + } + IssueActionIncorrectNoteType => { + write!(f, "not all `NoteType`s are the same inside the action") + } + IssueBundleIkMismatchNoteType => { + write!( + f, + "the provided `isk` and the driven `ik` does not match at least one note type" + ) + } + WrongAssetDescSize => { + write!(f, "`asset_desc` should be between 1 and 512 bytes") + } + IssueBundleInvalidSignature(_) => { + write!(f, "invalid signature") + } + IssueActionPreviouslyFinalizedNoteType(_) => { + write!(f, "the provided `NoteType` has been previously finalized") + } + } + } +} + +#[cfg(test)] +mod tests { + use super::IssueBundle; + use crate::issuance::Error::{ + IssueActionAlreadyFinalized, IssueActionIncorrectNoteType, IssueActionNotFound, + IssueActionPreviouslyFinalizedNoteType, IssueBundleIkMismatchNoteType, + IssueBundleInvalidSignature, WrongAssetDescSize, + }; + use crate::issuance::{verify_issue_bundle, IssueAction, Signed}; + use crate::keys::{ + FullViewingKey, IssuerAuthorizingKey, IssuerValidatingKey, Scope, SpendingKey, + }; + use crate::note::{NoteType, Nullifier}; + use crate::value::NoteValue; + use crate::{Address, Note}; + use nonempty::NonEmpty; + use rand::rngs::OsRng; + use rand::RngCore; + use reddsa::Error::InvalidSignature; + use std::borrow::BorrowMut; + use std::collections::HashSet; + + fn setup_params() -> ( + OsRng, + IssuerAuthorizingKey, + IssuerValidatingKey, + Address, + [u8; 32], + ) { + let mut rng = OsRng; + let sk = SpendingKey::random(&mut rng); + let isk: IssuerAuthorizingKey = (&sk).into(); + let ik: IssuerValidatingKey = (&isk).into(); + + let fvk = FullViewingKey::from(&sk); + let recipient = fvk.address_at(0u32, Scope::External); + + let mut sighash = [0u8; 32]; + rng.fill_bytes(&mut sighash); + + (rng, isk, ik, recipient, sighash) + } + + #[test] + fn issue_bundle_basic() { + let (rng, _, ik, recipient, _) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + let str = String::from("Halo"); + let str2 = String::from("Halo2"); + + assert_eq!( + bundle + .add_recipient( + String::from_utf8(vec![b'X'; 513]).unwrap(), + recipient, + NoteValue::unsplittable(), + true, + rng, + ) + .unwrap_err(), + WrongAssetDescSize + ); + + assert_eq!( + bundle + .add_recipient( + "".to_string(), + recipient, + NoteValue::unsplittable(), + true, + rng, + ) + .unwrap_err(), + WrongAssetDescSize + ); + + let note_type = bundle + .add_recipient(str.clone(), recipient, NoteValue::from_raw(5), false, rng) + .unwrap(); + + let another_note_type = bundle + .add_recipient(str, recipient, NoteValue::from_raw(10), false, rng) + .unwrap(); + assert_eq!(note_type, another_note_type); + + let third_note_type = bundle + .add_recipient(str2.clone(), recipient, NoteValue::from_raw(15), false, rng) + .unwrap(); + assert_ne!(note_type, third_note_type); + + let actions = bundle.actions(); + assert_eq!(actions.len(), 2); + + let action = bundle.get_action_by_type(note_type).unwrap(); + assert_eq!(action.notes.len(), 2); + assert_eq!(action.notes.first().value().inner(), 5); + assert_eq!(action.notes.first().note_type(), note_type); + assert_eq!(action.notes.first().recipient(), recipient); + + assert_eq!(action.notes.tail().first().unwrap().value().inner(), 10); + assert_eq!(action.notes.tail().first().unwrap().note_type(), note_type); + assert_eq!(action.notes.tail().first().unwrap().recipient(), recipient); + + let action2 = bundle.get_action(str2).unwrap(); + assert_eq!(action2.notes.len(), 1); + assert_eq!(action2.notes().first().value().inner(), 15); + assert_eq!(action2.notes().first().note_type(), third_note_type); + } + + #[test] + fn issue_bundle_finalize_asset() { + let (rng, _, ik, recipient, _) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("Precious NFT"), + recipient, + NoteValue::from_raw(u64::MIN), + false, + rng, + ) + .expect("Should properly add recipient"); + + bundle + .finalize_action(String::from("Precious NFT")) + .expect("Should finalize properly"); + + assert_eq!( + bundle + .add_recipient( + String::from("Precious NFT"), + recipient, + NoteValue::unsplittable(), + false, + rng, + ) + .unwrap_err(), + IssueActionAlreadyFinalized + ); + + assert_eq!( + bundle + .finalize_action(String::from("Another precious NFT")) + .unwrap_err(), + IssueActionNotFound + ); + + assert_eq!( + bundle + .finalize_action(String::from_utf8(vec![b'X'; 513]).unwrap()) + .unwrap_err(), + WrongAssetDescSize + ); + + assert_eq!( + bundle.finalize_action("".to_string()).unwrap_err(), + WrongAssetDescSize + ); + + bundle + .add_recipient( + String::from("Another precious NFT"), + recipient, + NoteValue::unsplittable(), + true, + rng, + ) + .expect("should add and finalize"); + + assert_eq!( + bundle + .add_recipient( + String::from("Another precious NFT"), + recipient, + NoteValue::unsplittable(), + true, + rng, + ) + .unwrap_err(), + IssueActionAlreadyFinalized + ); + } + + #[test] + fn issue_bundle_prepare() { + let (rng, _, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("Frost"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let prepared = bundle.prepare(sighash); + assert_eq!(prepared.authorization().sighash, sighash); + } + + #[test] + fn issue_bundle_sign() { + let (rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik.clone()); + + bundle + .add_recipient( + String::from("Sign"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + + ik.verify(&sighash, &signed.authorization.signature) + .expect("signature should be valid"); + } + + #[test] + fn issue_bundle_invalid_isk_for_signature() { + let (rng, _, ik, recipient, _) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("IssueBundle"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let wrong_isk: IssuerAuthorizingKey = (&SpendingKey::random(&mut OsRng)).into(); + + let err = bundle + .prepare([0; 32]) + .sign(rng, &wrong_isk) + .expect_err("should not be able to sign"); + + assert_eq!(err, IssueBundleIkMismatchNoteType); + } + + #[test] + fn issue_bundle_incorrect_note_type_for_signature() { + let (mut rng, isk, ik, recipient, _) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + // Add "normal" note + bundle + .add_recipient( + String::from("IssueBundle"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + // Add "bad" note + let note = Note::new( + recipient, + NoteValue::from_raw(5), + NoteType::derive(bundle.ik(), "Poisoned pill"), + Nullifier::dummy(&mut rng), + &mut rng, + ); + bundle + .actions + .first_mut() + .unwrap() + .notes + .borrow_mut() + .push(note); + + let err = bundle + .prepare([0; 32]) + .sign(rng, &isk) + .expect_err("should not be able to sign"); + + assert_eq!(err, IssueActionIncorrectNoteType); + } + + #[test] + fn issue_bundle_verify() { + let (rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("Verify"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + + let prev_finalized = &mut HashSet::new(); + + let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); + assert!(finalized.unwrap().is_empty()); + } + + #[test] + fn issue_bundle_verify_with_finalize() { + let (rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik.clone()); + + bundle + .add_recipient( + String::from("verify_with_finalize"), + recipient, + NoteValue::from_raw(7), + true, + rng, + ) + .unwrap(); + + let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + + let prev_finalized = &mut HashSet::new(); + + let finalized = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); + assert!(finalized.contains(&NoteType::derive( + &ik, + &String::from("verify_with_finalize") + ))); + assert_eq!(finalized.len(), 1); + } + + #[test] + fn issue_bundle_verify_fail_previously_finalized() { + let (rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik.clone()); + + bundle + .add_recipient( + String::from("already final"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let prev_finalized = &mut HashSet::new(); + + let final_type = NoteType::derive(&ik, &String::from("already final")); + + prev_finalized.insert(final_type); + + let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); + assert_eq!( + finalized.unwrap_err(), + IssueActionPreviouslyFinalizedNoteType(final_type) + ); + } + + #[test] + fn issue_bundle_verify_fail_bad_signature() { + // we want to inject "bad" signatures for test purposes. + impl IssueBundle { + pub fn set_authorization(&mut self, authorization: Signed) { + self.authorization = authorization; + } + } + + let (mut rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("bad sig"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let wrong_isk: IssuerAuthorizingKey = (&SpendingKey::random(&mut rng)).into(); + + let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + + signed.set_authorization(Signed { + signature: wrong_isk.sign(&mut rng, &sighash), + }); + + let prev_finalized = &mut HashSet::new(); + + assert_eq!( + verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), + IssueBundleInvalidSignature(InvalidSignature) + ); + } + + #[test] + fn issue_bundle_verify_fail_wrong_sighash() { + let (rng, isk, ik, recipient, random_sighash) = setup_params(); + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("Good description"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let sighash: [u8; 32] = bundle.commitment().into(); + let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let prev_finalized = &mut HashSet::new(); + + // 2. Try empty description + let finalized = verify_issue_bundle(&signed, random_sighash, prev_finalized); + + assert_eq!( + finalized.unwrap_err(), + IssueBundleInvalidSignature(InvalidSignature) + ); + } + + #[test] + fn issue_bundle_verify_fail_incorrect_asset_description() { + let (mut rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("Good description"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + + // Add "bad" note + let note = Note::new( + recipient, + NoteValue::from_raw(5), + NoteType::derive(signed.ik(), "Poisoned pill"), + Nullifier::dummy(&mut rng), + &mut rng, + ); + + signed + .actions + .first_mut() + .unwrap() + .notes + .borrow_mut() + .push(note); + + let prev_finalized = &mut HashSet::new(); + let err = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(); + + assert_eq!(err, IssueActionIncorrectNoteType); + } + + #[test] + fn issue_bundle_verify_fail_incorrect_ik() { + let asset_description = "asset"; + + let (mut rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from(asset_description), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + + let incorrect_sk = SpendingKey::random(&mut rng); + let incorrect_isk: IssuerAuthorizingKey = (&incorrect_sk).into(); + let incorrect_ik: IssuerValidatingKey = (&incorrect_isk).into(); + + // Add "bad" note + let note = Note::new( + recipient, + NoteValue::from_raw(55), + NoteType::derive(&incorrect_ik, asset_description), + Nullifier::dummy(&mut rng), + &mut rng, + ); + + signed.actions.first_mut().unwrap().notes = NonEmpty::new(note); + + let prev_finalized = &mut HashSet::new(); + let err = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(); + + assert_eq!(err, IssueBundleIkMismatchNoteType); + } + + #[test] + fn issue_bundle_verify_fail_wrong_asset_descr_size() { + // we want to inject "bad" description for test purposes. + impl IssueAction { + pub fn modify_descr(&mut self, new_descr: String) { + self.asset_desc = new_descr; + } + } + + let (rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik); + + bundle + .add_recipient( + String::from("Good description"), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let prev_finalized = &mut HashSet::new(); + + // 1. Try too long description + signed + .actions + .first_mut() + .unwrap() + .modify_descr(String::from_utf8(vec![b'X'; 513]).unwrap()); + let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); + + assert_eq!(finalized.unwrap_err(), WrongAssetDescSize); + + // 2. Try empty description + signed + .actions + .first_mut() + .unwrap() + .modify_descr("".to_string()); + let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); + + assert_eq!(finalized.unwrap_err(), WrongAssetDescSize); + } +} + +/// Generators for property testing. +#[cfg(any(test, feature = "test-dependencies"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] +pub mod testing { + use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized}; + use crate::keys::testing::{arb_issuer_authorizing_key, arb_issuer_validating_key}; + use crate::note::testing::arb_zsa_note; + use proptest::collection::vec; + use proptest::prelude::*; + use proptest::prop_compose; + use proptest::string::string_regex; + use rand::{rngs::StdRng, SeedableRng}; + + prop_compose! { + /// Generate an issue action given note value + pub fn arb_issue_action()( + note in arb_zsa_note(), + asset_descr in string_regex(".{1,512}").unwrap() + ) -> IssueAction { + IssueAction::new(asset_descr, ¬e) + } + } + + prop_compose! { + /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_issue_bundle`] + pub fn arb_unathorized_issue_bundle(n_actions: usize) + ( + actions in vec(arb_issue_action(), n_actions), + ik in arb_issuer_validating_key() + ) -> IssueBundle { + IssueBundle { + ik, + actions, + authorization: Unauthorized + } + } + } + + prop_compose! { + /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_issue_bundle`] + pub fn arb_prepared_issue_bundle(n_actions: usize) + ( + actions in vec(arb_issue_action(), n_actions), + ik in arb_issuer_validating_key(), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY) + ) -> IssueBundle { + IssueBundle { + ik, + actions, + authorization: Prepared { sighash: fake_sighash } + } + } + } + + prop_compose! { + /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_issue_bundle`] + pub fn arb_signed_issue_bundle(n_actions: usize) + ( + actions in vec(arb_issue_action(), n_actions), + ik in arb_issuer_validating_key(), + isk in arb_issuer_authorizing_key(), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY) + ) -> IssueBundle { + let rng = StdRng::from_seed(rng_seed); + + IssueBundle { + ik, + actions, + authorization: Prepared { sighash: fake_sighash }, + }.sign(rng, &isk).unwrap() + } + } +} diff --git a/src/keys.rs b/src/keys.rs index 8b76c8517..7f603a5b8 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -12,7 +12,7 @@ use group::{ Curve, GroupEncoding, }; use pasta_curves::pallas; -use rand::RngCore; +use rand::{CryptoRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_note_encryption::EphemeralKeyBytes; @@ -209,6 +209,15 @@ impl IssuerAuthorizingKey { fn derive_inner(sk: &SpendingKey) -> pallas::Scalar { to_scalar(PrfExpand::ZsaIsk.expand(&sk.0)) } + + /// Sign the provided message using the `IssuerAuthorizingKey`. + pub fn sign( + &self, + rng: &mut (impl RngCore + CryptoRng), + msg: &[u8], + ) -> redpallas::Signature { + self.0.sign(rng, msg) + } } impl From<&SpendingKey> for IssuerAuthorizingKey { @@ -270,6 +279,15 @@ impl IssuerValidatingKey { .and_then(check_structural_validity) .map(IssuerValidatingKey) } + + /// Verifies a purported `signature` over `msg` made by this verification key. + pub fn verify( + &self, + msg: &[u8], + signature: &redpallas::Signature, + ) -> Result<(), reddsa::Error> { + self.0.verify(msg, signature) + } } /// A function to check structural validity of the validating keys for authorizing transfers and @@ -1024,9 +1042,12 @@ impl SharedSecret { #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { + use super::{ + DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuerAuthorizingKey, + IssuerValidatingKey, SpendingKey, + }; use proptest::prelude::*; - - use super::{DiversifierIndex, DiversifierKey, EphemeralSecretKey, SpendingKey}; + use rand::{rngs::StdRng, SeedableRng}; prop_compose! { /// Generate a uniformly distributed Orchard spending key. @@ -1073,6 +1094,21 @@ pub mod testing { DiversifierIndex::from(d_bytes) } } + + prop_compose! { + /// Generate a uniformly distributed RedDSA issuer authorizing key. + pub fn arb_issuer_authorizing_key()(rng_seed in prop::array::uniform32(prop::num::u8::ANY)) -> IssuerAuthorizingKey { + let mut rng = StdRng::from_seed(rng_seed); + IssuerAuthorizingKey::from(&SpendingKey::random(&mut rng)) + } + } + + prop_compose! { + /// Generate a uniformly distributed RedDSA issuer validating key. + pub fn arb_issuer_validating_key()(isk in arb_issuer_authorizing_key()) -> IssuerValidatingKey { + IssuerValidatingKey::from(&isk) + } + } } #[cfg(test)] diff --git a/src/lib.rs b/src/lib.rs index d30e9c834..c0e63ce9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ pub mod builder; pub mod bundle; pub mod circuit; mod constants; +pub mod issuance; pub mod keys; pub mod note; pub mod note_encryption; diff --git a/src/note.rs b/src/note.rs index 04938cbe0..75c3d9c64 100644 --- a/src/note.rs +++ b/src/note.rs @@ -173,6 +173,7 @@ impl Note { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes + /// TODO zsa: remove note_type pub(crate) fn dummy( rng: &mut impl RngCore, rho: Option, @@ -296,6 +297,8 @@ pub mod testing { use proptest::prelude::*; use crate::note::note_type::testing::arb_note_type; + use crate::note::note_type::testing::zsa_note_type; + use crate::value::testing::arb_note_value; use crate::{ address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, }; @@ -326,4 +329,23 @@ pub mod testing { } } } + + prop_compose! { + /// Generate an arbitrary ZSA note + pub fn arb_zsa_note()( + recipient in arb_address(), + value in arb_note_value(), + rho in arb_nullifier(), + rseed in arb_rseed(), + note_type in zsa_note_type(), + ) -> Note { + Note { + recipient, + value, + note_type, + rho, + rseed, + } + } + } } diff --git a/src/note/note_type.rs b/src/note/note_type.rs index 8ac04b00b..45e0b532b 100644 --- a/src/note/note_type.rs +++ b/src/note/note_type.rs @@ -38,12 +38,12 @@ impl NoteType { /// /// [notetypes]: https://zips.z.cash/protocol/nu5.pdf#notetypes #[allow(non_snake_case)] - pub fn derive(ik: &IssuerValidatingKey, assetDesc: Vec) -> Self { - assert!(assetDesc.len() < MAX_ASSET_DESCRIPTION_SIZE); + pub fn derive(ik: &IssuerValidatingKey, asset_desc: &str) -> Self { + assert!(!asset_desc.is_empty() && asset_desc.len() <= MAX_ASSET_DESCRIPTION_SIZE); let mut s = vec![]; s.extend(ik.to_bytes()); - s.extend(assetDesc); + s.extend(asset_desc.as_bytes()); NoteType(assetID_hasher(s)) } @@ -92,15 +92,13 @@ pub mod testing { pub fn arb_note_type()( is_native in prop::bool::ANY, sk in arb_spending_key(), - bytes32a in prop::array::uniform32(prop::num::u8::ANY), - bytes32b in prop::array::uniform32(prop::num::u8::ANY), + str in "[A-Za-z]{255}", ) -> NoteType { if is_native { NoteType::native() } else { - let bytes64 = [bytes32a, bytes32b].concat(); let isk = IssuerAuthorizingKey::from(&sk); - NoteType::derive(&IssuerValidatingKey::from(&isk), bytes64) + NoteType::derive(&IssuerValidatingKey::from(&isk), &str) } } } @@ -112,4 +110,15 @@ pub mod testing { NoteType::native() } } + + prop_compose! { + /// Generate the ZSA note type + pub fn zsa_note_type()( + sk in arb_spending_key(), + str in "[A-Za-z]{255}" + ) -> NoteType { + let isk = IssuerAuthorizingKey::from(&sk); + NoteType::derive(&IssuerValidatingKey::from(&isk), &str) + } + } } diff --git a/src/value.rs b/src/value.rs index ce5d6c94f..d6e18ba23 100644 --- a/src/value.rs +++ b/src/value.rs @@ -116,6 +116,11 @@ impl NoteValue { pub(crate) fn to_le_bits(self) -> BitArray<[u8; 8], Lsb0> { BitArray::<_, Lsb0>::new(self.0.to_le_bytes()) } + + /// The minimum, greater than zero, note value that can not be split further. + pub fn unsplittable() -> Self { + NoteValue(1u64) + } } impl From<&NoteValue> for Assigned { From 9b434976ab6d4ed0683919e92052e8d24682ec03 Mon Sep 17 00:00:00 2001 From: Alexey Koren Date: Thu, 20 Oct 2022 15:43:18 +0200 Subject: [PATCH 07/92] E2E tests for issuance (#20) added tests in `tests/zsa.rs` --- .github/workflows/ci.yml | 2 +- src/builder.rs | 23 +- src/issuance.rs | 9 +- tests/builder.rs | 39 ++-- tests/zsa.rs | 448 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 489 insertions(+), 32 deletions(-) create mode 100644 tests/zsa.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 966cc8da8..2a52477ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,7 +75,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: tarpaulin - args: --all-features --timeout 600 --out Xml + args: --all-features --timeout 1200 --out Xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 with: diff --git a/src/builder.rs b/src/builder.rs index a6933276d..30bfab4f4 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -133,7 +133,7 @@ impl RecipientInfo { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(rng: &mut impl RngCore) -> Self { + fn dummy(rng: &mut impl RngCore, note_type: NoteType) -> Self { let fvk: FullViewingKey = (&SpendingKey::random(rng)).into(); let recipient = fvk.address_at(0u32, Scope::External); @@ -141,7 +141,7 @@ impl RecipientInfo { ovk: None, recipient, value: NoteValue::zero(), - note_type: NoteType::native(), + note_type, memo: None, } } @@ -167,16 +167,13 @@ impl ActionInfo { /// Returns the value sum for this action. /// Split notes does not contribute to the value sum. fn value_sum(&self) -> ValueSum { - // TODO: Aurel, uncomment when circuit for split flag is implemented. - // let spent_value = self - // .spend - // .split_flag - // .then(|| self.spend.note.value()) - // .unwrap_or_else(NoteValue::zero); - // - // spent_value - self.output.value - - self.spend.note.value() - self.output.value + let spent_value = self + .spend + .split_flag + .then(NoteValue::zero) + .unwrap_or_else(|| self.spend.note.value()); + + spent_value - self.output.value } /// Builds the action. @@ -392,7 +389,7 @@ impl Builder { spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); recipients.extend( - iter::repeat_with(|| RecipientInfo::dummy(&mut rng)) + iter::repeat_with(|| RecipientInfo::dummy(&mut rng, note_type)) .take(num_actions - num_recipients), ); diff --git a/src/issuance.rs b/src/issuance.rs index b5ac7aaa3..8900d4219 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -144,6 +144,13 @@ impl IssueBundle { pub fn actions(&self) -> &Vec { &self.actions } + /// Return the notes from all actions for a given `IssueBundle`. + pub fn get_all_notes(&self) -> Vec { + self.actions + .iter() + .flat_map(|action| action.notes.clone().into_iter()) + .collect() + } /// Returns the authorization for this action. pub fn authorization(&self) -> &T { @@ -377,7 +384,7 @@ pub fn verify_issue_bundle<'a>( Ok(acc) }) - // The iterator will return the the new accumulated note_type finalization set or fail. + // The iterator will return the new finalization set or will fail. } /// Errors produced during the issuance process diff --git a/tests/builder.rs b/tests/builder.rs index 428ebf81c..7d044fcd6 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -9,13 +9,13 @@ use orchard::{ note_encryption::OrchardDomain, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, - Bundle, + Anchor, Bundle, Note, }; use rand::rngs::OsRng; use zcash_note_encryption::try_note_decryption; -fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey) { - assert!(matches!(bundle.verify_proof(vk), Ok(()))); +pub fn verify_bundle(bundle: &Bundle, _vk: &VerifyingKey) { + // TODO uncomment when circuit can work with split flag - assert!(matches!(bundle.verify_proof(vk), Ok(()))); let sighash: [u8; 32] = bundle.commitment().into(); let bvk = bundle.binding_validating_key(); for action in bundle.actions() { @@ -27,6 +27,24 @@ fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey) { ); } +pub fn build_merkle_path(note: &Note) -> (MerklePath, Anchor) { + // Use the tree with a single leaf. + let cmx: ExtractedNoteCommitment = note.commitment().into(); + let leaf = MerkleHashOrchard::from_cmx(&cmx); + let mut tree = BridgeTree::::new(0); + tree.append(&leaf); + let position = tree.witness().unwrap(); + let root = tree.root(0).unwrap(); + let auth_path = tree.authentication_path(position, &root).unwrap(); + let merkle_path = MerklePath::from_parts( + u64::from(position).try_into().unwrap(), + auth_path[..].try_into().unwrap(), + ); + let anchor = root.into(); + assert_eq!(anchor, merkle_path.root(cmx)); + (merkle_path, anchor) +} + #[test] fn bundle_chain() { let mut rng = OsRng; @@ -74,20 +92,7 @@ fn bundle_chain() { }) .unwrap(); - // Use the tree with a single leaf. - let cmx: ExtractedNoteCommitment = note.commitment().into(); - let leaf = MerkleHashOrchard::from_cmx(&cmx); - let mut tree = BridgeTree::::new(0); - tree.append(&leaf); - let position = tree.witness().unwrap(); - let root = tree.root(0).unwrap(); - let auth_path = tree.authentication_path(position, &root).unwrap(); - let merkle_path = MerklePath::from_parts( - u64::from(position).try_into().unwrap(), - auth_path[..].try_into().unwrap(), - ); - let anchor = root.into(); - assert_eq!(anchor, merkle_path.root(cmx)); + let (merkle_path, anchor) = build_merkle_path(¬e); let mut builder = Builder::new(Flags::from_parts(true, true), anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); diff --git a/tests/zsa.rs b/tests/zsa.rs new file mode 100644 index 000000000..9b40d284f --- /dev/null +++ b/tests/zsa.rs @@ -0,0 +1,448 @@ +mod builder; + +use crate::builder::verify_bundle; +use incrementalmerkletree::bridgetree::BridgeTree; +use incrementalmerkletree::{Hashable, Tree}; +use orchard::bundle::Authorized; +use orchard::issuance::{verify_issue_bundle, IssueBundle, Signed, Unauthorized}; +use orchard::keys::{IssuerAuthorizingKey, IssuerValidatingKey}; +use orchard::note::{ExtractedNoteCommitment, NoteType}; +use orchard::note_encryption::OrchardDomain; +use orchard::tree::{MerkleHashOrchard, MerklePath}; +use orchard::{ + builder::Builder, + bundle::Flags, + circuit::{ProvingKey, VerifyingKey}, + keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, + value::NoteValue, + Address, Anchor, Bundle, Note, +}; +use rand::rngs::OsRng; +use std::collections::HashSet; +use zcash_note_encryption::try_note_decryption; + +#[derive(Debug)] +struct Keychain { + pk: ProvingKey, + vk: VerifyingKey, + sk: SpendingKey, + fvk: FullViewingKey, + isk: IssuerAuthorizingKey, + ik: IssuerValidatingKey, + recipient: Address, +} + +impl Keychain { + fn pk(&self) -> &ProvingKey { + &self.pk + } + fn sk(&self) -> &SpendingKey { + &self.sk + } + fn fvk(&self) -> &FullViewingKey { + &self.fvk + } + fn isk(&self) -> &IssuerAuthorizingKey { + &self.isk + } + fn ik(&self) -> &IssuerValidatingKey { + &self.ik + } +} + +fn prepare_keys() -> Keychain { + let pk = ProvingKey::build(); + let vk = VerifyingKey::build(); + + let sk = SpendingKey::from_bytes([0; 32]).unwrap(); + let fvk = FullViewingKey::from(&sk); + let recipient = fvk.address_at(0u32, Scope::External); + + let isk = IssuerAuthorizingKey::from(&sk); + let ik = IssuerValidatingKey::from(&isk); + Keychain { + pk, + vk, + sk, + fvk, + isk, + ik, + recipient, + } +} + +fn sign_issue_bundle( + unauthorized: IssueBundle, + mut rng: OsRng, + isk: IssuerAuthorizingKey, +) -> IssueBundle { + let sighash = unauthorized.commitment().into(); + let proven = unauthorized.prepare(sighash); + proven.sign(&mut rng, &isk).unwrap() +} + +fn build_and_sign_bundle( + builder: Builder, + mut rng: OsRng, + pk: &ProvingKey, + sk: &SpendingKey, +) -> Bundle { + let unauthorized = builder.build(&mut rng).unwrap(); + let sighash = unauthorized.commitment().into(); + let proven = unauthorized.create_proof(pk, &mut rng).unwrap(); + proven + .apply_signatures(&mut rng, sighash, &[SpendAuthorizingKey::from(sk)]) + .unwrap() +} + +pub fn build_merkle_path_with_two_leaves( + note1: &Note, + note2: &Note, +) -> (MerklePath, MerklePath, Anchor) { + let mut tree = BridgeTree::::new(0); + + // Add first leaf + let cmx1: ExtractedNoteCommitment = note1.commitment().into(); + let leaf1 = MerkleHashOrchard::from_cmx(&cmx1); + tree.append(&leaf1); + let position1 = tree.witness().unwrap(); + + // Add second leaf + let cmx2: ExtractedNoteCommitment = note2.commitment().into(); + let leaf2 = MerkleHashOrchard::from_cmx(&cmx2); + tree.append(&leaf2); + let position2 = tree.witness().unwrap(); + + let root = tree.root(0).unwrap(); + let anchor = root.into(); + + // Calculate first path + let auth_path1 = tree.authentication_path(position1, &root).unwrap(); + let merkle_path1 = MerklePath::from_parts( + u64::from(position1).try_into().unwrap(), + auth_path1[..].try_into().unwrap(), + ); + + // Calculate second path + let auth_path2 = tree.authentication_path(position2, &root).unwrap(); + let merkle_path2 = MerklePath::from_parts( + u64::from(position2).try_into().unwrap(), + auth_path2[..].try_into().unwrap(), + ); + + assert_eq!(anchor, merkle_path1.root(cmx1)); + assert_eq!(anchor, merkle_path2.root(cmx2)); + (merkle_path1, merkle_path2, anchor) +} + +fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { + let mut rng = OsRng; + // Create a issuance bundle + let mut unauthorized = IssueBundle::new(keys.ik().clone()); + + assert!(unauthorized + .add_recipient( + asset_descr.to_string(), + keys.recipient, + NoteValue::from_raw(40), + false, + &mut rng, + ) + .is_ok()); + assert!(unauthorized + .add_recipient( + asset_descr.to_string(), + keys.recipient, + NoteValue::from_raw(2), + false, + &mut rng, + ) + .is_ok()); + + let issue_bundle = sign_issue_bundle(unauthorized, rng, keys.isk().clone()); + + // Take notes from first action + let notes = issue_bundle.get_all_notes(); + let note1 = notes.get(0).unwrap(); + let note2 = notes.get(1).unwrap(); + + assert!(verify_issue_bundle( + &issue_bundle, + issue_bundle.commitment().into(), + &mut HashSet::new(), + ) + .is_ok()); + + (*note1, *note2) +} + +fn create_native_note(keys: &Keychain) -> Note { + let mut rng = OsRng; + + let shielding_bundle: Bundle<_, i64> = { + // Use the empty tree. + let anchor = MerkleHashOrchard::empty_root(32.into()).into(); + + let mut builder = Builder::new(Flags::from_parts(false, true), anchor); + assert_eq!( + builder.add_recipient( + None, + keys.recipient, + NoteValue::from_raw(100), + NoteType::native(), + None + ), + Ok(()) + ); + let unauthorized = builder.build(&mut rng).unwrap(); + let sighash = unauthorized.commitment().into(); + let proven = unauthorized.create_proof(keys.pk(), &mut rng).unwrap(); + proven.apply_signatures(&mut rng, sighash, &[]).unwrap() + }; + let ivk = keys.fvk().to_ivk(Scope::External); + let (native_note, _, _) = shielding_bundle + .actions() + .iter() + .find_map(|action| { + let domain = OrchardDomain::for_action(action); + try_note_decryption(&domain, &ivk, action) + }) + .unwrap(); + + native_note +} + +struct TestSpendInfo { + note: Note, + merkle_path: MerklePath, +} + +impl TestSpendInfo { + fn merkle_path(&self) -> &MerklePath { + &self.merkle_path + } +} + +struct TestOutputInfo { + value: NoteValue, + note_type: NoteType, +} + +fn build_and_verify_bundle( + spends: Vec<&TestSpendInfo>, + outputs: Vec, + anchor: Anchor, + expected_num_actions: usize, + keys: &Keychain, +) { + let rng = OsRng; + let shielded_bundle: Bundle<_, i64> = { + let mut builder = Builder::new(Flags::from_parts(true, true), anchor); + + spends.iter().for_each(|spend| { + assert_eq!( + builder.add_spend(keys.fvk().clone(), spend.note, spend.merkle_path().clone()), + Ok(()) + ); + }); + outputs.iter().for_each(|output| { + assert_eq!( + builder.add_recipient(None, keys.recipient, output.value, output.note_type, None), + Ok(()) + ) + }); + build_and_sign_bundle(builder, rng, keys.pk(), keys.sk()) + }; + + // Verify the shielded bundle + verify_bundle(&shielded_bundle, &keys.vk); + assert_eq!(shielded_bundle.actions().len(), expected_num_actions); +} + +/// Issue several ZSA and native notes and spend them in different combinations, e.g. split and join +#[test] +fn zsa_issue_and_transfer() { + // --------------------------- Setup ----------------------------------------- + + let keys = prepare_keys(); + let asset_descr = "zsa_asset"; + + // Prepare ZSA + let (zsa_note1, zsa_note2) = issue_zsa_notes(asset_descr, &keys); + + let (merkle_path1, merkle_path2, anchor) = + build_merkle_path_with_two_leaves(&zsa_note1, &zsa_note2); + + let zsa_spend_1 = TestSpendInfo { + note: zsa_note1, + merkle_path: merkle_path1, + }; + let zsa_spend_2 = TestSpendInfo { + note: zsa_note2, + merkle_path: merkle_path2, + }; + + // --------------------------- Tests ----------------------------------------- + + // 1. Spend single ZSA note + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![TestOutputInfo { + value: zsa_spend_1.note.value(), + note_type: zsa_spend_1.note.note_type(), + }], + anchor, + 2, + &keys, + ); + + // 2. Split single ZSA note into 2 notes + let delta = 2; // arbitrary number for value manipulation + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![ + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta), + note_type: zsa_spend_1.note.note_type(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta), + note_type: zsa_spend_1.note.note_type(), + }, + ], + anchor, + 2, + &keys, + ); + + // 3. Join 2 ZSA notes into a single note + build_and_verify_bundle( + vec![&zsa_spend_1, &zsa_spend_2], + vec![TestOutputInfo { + value: NoteValue::from_raw( + zsa_spend_1.note.value().inner() + zsa_spend_2.note.value().inner(), + ), + note_type: zsa_spend_1.note.note_type(), + }], + anchor, + 2, + &keys, + ); + + // 4. Take 2 ZSA notes and send them as 2 notes with different denomination + build_and_verify_bundle( + vec![&zsa_spend_1, &zsa_spend_2], + vec![ + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta), + note_type: zsa_spend_1.note.note_type(), + }, + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_2.note.value().inner() + delta), + note_type: zsa_spend_2.note.note_type(), + }, + ], + anchor, + 2, + &keys, + ); + + // 5. Spend single ZSA note, mixed with native note (shielding) + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![ + TestOutputInfo { + value: zsa_spend_1.note.value(), + note_type: zsa_spend_1.note.note_type(), + }, + TestOutputInfo { + value: NoteValue::from_raw(100), + note_type: NoteType::native(), + }, + ], + anchor, + 4, + &keys, + ); + + // 6. Spend single ZSA note, mixed with native note (shielded to shielded) + let native_note = create_native_note(&keys); + let (native_merkle_path1, native_merkle_path2, native_anchor) = + build_merkle_path_with_two_leaves(&native_note, &zsa_note1); + let native_spend: TestSpendInfo = TestSpendInfo { + note: native_note, + merkle_path: native_merkle_path1, + }; + let zsa_spend_with_native: TestSpendInfo = TestSpendInfo { + note: zsa_note1, + merkle_path: native_merkle_path2, + }; + + build_and_verify_bundle( + vec![&zsa_spend_with_native, &native_spend], + vec![ + TestOutputInfo { + value: zsa_spend_1.note.value(), + note_type: zsa_spend_1.note.note_type(), + }, + TestOutputInfo { + value: native_spend.note.value(), + note_type: NoteType::native(), + }, + ], + native_anchor, + 4, + &keys, + ); + + // 7. Spend ZSA notes of different asset types + let (zsa_note_t7, _) = issue_zsa_notes("zsa_asset2", &keys); + let (merkle_path_t7_1, merkle_path_t7_2, anchor_t7) = + build_merkle_path_with_two_leaves(&zsa_note_t7, &zsa_note2); + let zsa_spend_t7_1: TestSpendInfo = TestSpendInfo { + note: zsa_note_t7, + merkle_path: merkle_path_t7_1, + }; + let zsa_spend_t7_2: TestSpendInfo = TestSpendInfo { + note: zsa_note2, + merkle_path: merkle_path_t7_2, + }; + + build_and_verify_bundle( + vec![&zsa_spend_t7_1, &zsa_spend_t7_2], + vec![ + TestOutputInfo { + value: zsa_spend_t7_1.note.value(), + note_type: zsa_spend_t7_1.note.note_type(), + }, + TestOutputInfo { + value: zsa_spend_t7_2.note.value(), + note_type: zsa_spend_t7_2.note.note_type(), + }, + ], + anchor_t7, + 4, + &keys, + ); + + // 8. Same but wrong denomination + let result = std::panic::catch_unwind(|| { + build_and_verify_bundle( + vec![&zsa_spend_t7_1, &zsa_spend_t7_2], + vec![ + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_t7_1.note.value().inner() + delta), + note_type: zsa_spend_t7_1.note.note_type(), + }, + TestOutputInfo { + value: NoteValue::from_raw(zsa_spend_t7_2.note.value().inner() - delta), + note_type: zsa_spend_t7_2.note.note_type(), + }, + ], + anchor_t7, + 4, + &keys, + ); + }); + assert!(result.is_err()); +} From 985d0d243e32f3a2aaea21cdcd638626bf728264 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Thu, 20 Oct 2022 17:46:57 +0300 Subject: [PATCH 08/92] disabled split notes (#22) * disabled split notes and proof check for zsa transfer --- src/builder.rs | 10 ++++++---- tests/builder.rs | 10 ++++++---- tests/zsa.rs | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 30bfab4f4..18fb46dd8 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -379,11 +379,13 @@ impl Builder { .cloned() .unwrap(); + // TODO: uncomment once the circuit is ready. // use the first spend to create split spend(s) or create a dummy if empty. - let dummy_spend = spends.first().map_or_else( - || SpendInfo::dummy(note_type, &mut rng), - |s| s.create_split_spend(), - ); + // let dummy_spend = spends.first().map_or_else( + // || SpendInfo::dummy(note_type, &mut rng), + // |s| s.create_split_spend(), + // ); + let dummy_spend = SpendInfo::dummy(note_type, &mut rng); // Extend the spends and recipients with dummy values. spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); diff --git a/tests/builder.rs b/tests/builder.rs index 7d044fcd6..bf94fc2ee 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -14,8 +14,10 @@ use orchard::{ use rand::rngs::OsRng; use zcash_note_encryption::try_note_decryption; -pub fn verify_bundle(bundle: &Bundle, _vk: &VerifyingKey) { - // TODO uncomment when circuit can work with split flag - assert!(matches!(bundle.verify_proof(vk), Ok(()))); +pub fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey, verify_proof: bool) { + if verify_proof { + assert!(matches!(bundle.verify_proof(vk), Ok(()))); + } let sighash: [u8; 32] = bundle.commitment().into(); let bvk = bundle.binding_validating_key(); for action in bundle.actions() { @@ -78,7 +80,7 @@ fn bundle_chain() { }; // Verify the shielding bundle. - verify_bundle(&shielding_bundle, &vk); + verify_bundle(&shielding_bundle, &vk, true); // Create a shielded bundle spending the previous output. let shielded_bundle: Bundle<_, i64> = { @@ -115,5 +117,5 @@ fn bundle_chain() { }; // Verify the shielded bundle. - verify_bundle(&shielded_bundle, &vk); + verify_bundle(&shielded_bundle, &vk, true); } diff --git a/tests/zsa.rs b/tests/zsa.rs index 9b40d284f..0335d3358 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -254,8 +254,8 @@ fn build_and_verify_bundle( build_and_sign_bundle(builder, rng, keys.pk(), keys.sk()) }; - // Verify the shielded bundle - verify_bundle(&shielded_bundle, &keys.vk); + // Verify the shielded bundle, currently without the proof. + verify_bundle(&shielded_bundle, &keys.vk, false); assert_eq!(shielded_bundle.actions().len(), expected_num_actions); } From f3ebe7a1abe88833d265b3b1d0d12a49333ab468 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Wed, 26 Oct 2022 21:11:37 +0300 Subject: [PATCH 09/92] Review fixes (#23) * fixes and suggestions * changed "issuer" to "issuance" as per https://github.com/zcash/orchard/pull/356#discussion_r967668241 * terminology fixes * updated naming --- src/builder.rs | 10 +++-- src/constants/fixed_bases.rs | 1 - src/issuance.rs | 42 ++++++++++---------- src/keys.rs | 76 ++++++++++++++++++------------------ src/note/note_type.rs | 31 ++++++++------- tests/zsa.rs | 16 ++++---- 6 files changed, 90 insertions(+), 86 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 18fb46dd8..526fe471e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -370,7 +370,9 @@ impl Builder { let mut pre_actions: Vec<_> = Vec::new(); // Pair up the spends and recipients, extending with dummy values as necessary. - for (note_type, (mut spends, mut recipients)) in partition(&self.spends, &self.recipients) { + for (note_type, (mut spends, mut recipients)) in + partition_by_asset(&self.spends, &self.recipients) + { let num_spends = spends.len(); let num_recipients = recipients.len(); let num_actions = [num_spends, num_recipients, MIN_ACTIONS] @@ -460,20 +462,20 @@ impl Builder { } /// partition a list of spends and recipients by note types. -fn partition( +fn partition_by_asset( spends: &[SpendInfo], recipients: &[RecipientInfo], ) -> HashMap, Vec)> { let mut hm = HashMap::new(); - for s in spends.iter() { + for s in spends { hm.entry(s.note.note_type()) .or_insert((vec![], vec![])) .0 .push(s.clone()); } - for r in recipients.iter() { + for r in recipients { hm.entry(r.note_type) .or_insert((vec![], vec![])) .1 diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index bd58a90c2..d9c92edd3 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -19,7 +19,6 @@ pub mod value_commit_v; pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard"; /// SWU hash-to-curve personalization for the value commitment generator -/// TODO: should we change to "NOTE_TYPE_PERSONALIZATION"? pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv"; /// SWU hash-to-curve personalization for the note type generator diff --git a/src/issuance.rs b/src/issuance.rs index 8900d4219..e8027e67f 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -11,7 +11,7 @@ use crate::issuance::Error::{ IssueActionPreviouslyFinalizedNoteType, IssueBundleIkMismatchNoteType, IssueBundleInvalidSignature, WrongAssetDescSize, }; -use crate::keys::{IssuerAuthorizingKey, IssuerValidatingKey}; +use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use crate::note::note_type::MAX_ASSET_DESCRIPTION_SIZE; use crate::note::{NoteType, Nullifier}; use crate::value::NoteValue; @@ -24,7 +24,7 @@ use crate::{ #[derive(Debug)] pub struct IssueBundle { /// The issuer key for the note being created. - ik: IssuerValidatingKey, + ik: IssuanceValidatingKey, /// The list of issue actions that make up this bundle. actions: Vec, /// The authorization for this action. @@ -84,7 +84,7 @@ impl IssueAction { /// Return the `NoteType` if the provided `ik` is used to derive the `note_type` for **all** internal notes. fn are_note_types_derived_correctly( &self, - ik: &IssuerValidatingKey, + ik: &IssuanceValidatingKey, ) -> Result { match self .notes @@ -137,7 +137,7 @@ impl IssueAuth for Signed {} impl IssueBundle { /// Returns the issuer verification key for the bundle. - pub fn ik(&self) -> &IssuerValidatingKey { + pub fn ik(&self) -> &IssuanceValidatingKey { &self.ik } /// Return the actions for a given `IssueBundle`. @@ -180,7 +180,7 @@ impl IssueBundle { impl IssueBundle { /// Constructs a new `IssueBundle`. - pub fn new(ik: IssuerValidatingKey) -> IssueBundle { + pub fn new(ik: IssuanceValidatingKey) -> IssueBundle { IssueBundle { ik, actions: Vec::new(), @@ -283,9 +283,9 @@ impl IssueBundle { pub fn sign( self, mut rng: R, - isk: &IssuerAuthorizingKey, + isk: &IssuanceAuthorizingKey, ) -> Result, Error> { - let expected_ik: IssuerValidatingKey = (isk).into(); + let expected_ik: IssuanceValidatingKey = (isk).into(); // Make sure the `expected_ik` matches the note_type for all notes. self.actions.iter().try_for_each(|action| { @@ -454,7 +454,7 @@ mod tests { }; use crate::issuance::{verify_issue_bundle, IssueAction, Signed}; use crate::keys::{ - FullViewingKey, IssuerAuthorizingKey, IssuerValidatingKey, Scope, SpendingKey, + FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; use crate::note::{NoteType, Nullifier}; use crate::value::NoteValue; @@ -468,15 +468,15 @@ mod tests { fn setup_params() -> ( OsRng, - IssuerAuthorizingKey, - IssuerValidatingKey, + IssuanceAuthorizingKey, + IssuanceValidatingKey, Address, [u8; 32], ) { let mut rng = OsRng; let sk = SpendingKey::random(&mut rng); - let isk: IssuerAuthorizingKey = (&sk).into(); - let ik: IssuerValidatingKey = (&isk).into(); + let isk: IssuanceAuthorizingKey = (&sk).into(); + let ik: IssuanceValidatingKey = (&isk).into(); let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); @@ -689,7 +689,7 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuerAuthorizingKey = (&SpendingKey::random(&mut OsRng)).into(); + let wrong_isk: IssuanceAuthorizingKey = (&SpendingKey::random(&mut OsRng)).into(); let err = bundle .prepare([0; 32]) @@ -845,7 +845,7 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuerAuthorizingKey = (&SpendingKey::random(&mut rng)).into(); + let wrong_isk: IssuanceAuthorizingKey = (&SpendingKey::random(&mut rng)).into(); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -951,8 +951,8 @@ mod tests { let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); let incorrect_sk = SpendingKey::random(&mut rng); - let incorrect_isk: IssuerAuthorizingKey = (&incorrect_sk).into(); - let incorrect_ik: IssuerValidatingKey = (&incorrect_isk).into(); + let incorrect_isk: IssuanceAuthorizingKey = (&incorrect_sk).into(); + let incorrect_ik: IssuanceValidatingKey = (&incorrect_isk).into(); // Add "bad" note let note = Note::new( @@ -1024,7 +1024,7 @@ mod tests { #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized}; - use crate::keys::testing::{arb_issuer_authorizing_key, arb_issuer_validating_key}; + use crate::keys::testing::{arb_issuance_authorizing_key, arb_issuance_validating_key}; use crate::note::testing::arb_zsa_note; use proptest::collection::vec; use proptest::prelude::*; @@ -1049,7 +1049,7 @@ pub mod testing { pub fn arb_unathorized_issue_bundle(n_actions: usize) ( actions in vec(arb_issue_action(), n_actions), - ik in arb_issuer_validating_key() + ik in arb_issuance_validating_key() ) -> IssueBundle { IssueBundle { ik, @@ -1066,7 +1066,7 @@ pub mod testing { pub fn arb_prepared_issue_bundle(n_actions: usize) ( actions in vec(arb_issue_action(), n_actions), - ik in arb_issuer_validating_key(), + ik in arb_issuance_validating_key(), fake_sighash in prop::array::uniform32(prop::num::u8::ANY) ) -> IssueBundle { IssueBundle { @@ -1084,8 +1084,8 @@ pub mod testing { pub fn arb_signed_issue_bundle(n_actions: usize) ( actions in vec(arb_issue_action(), n_actions), - ik in arb_issuer_validating_key(), - isk in arb_issuer_authorizing_key(), + ik in arb_issuance_validating_key(), + isk in arb_issuance_authorizing_key(), rng_seed in prop::array::uniform32(prop::num::u8::ANY), fake_sighash in prop::array::uniform32(prop::num::u8::ANY) ) -> IssueBundle { diff --git a/src/keys.rs b/src/keys.rs index 7f603a5b8..d10e6e24e 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -178,7 +178,7 @@ impl SpendValidatingKey { self.0.randomize(randomizer) } - /// Converts this spend validating key to its serialized form, + /// Converts this issuance validating key to its serialized form, /// I2LEOSP_256(ak). pub(crate) fn to_bytes(&self) -> [u8; 32] { // This is correct because the wrapped point must have ỹ = 0, and @@ -194,23 +194,23 @@ impl SpendValidatingKey { } } -/// An issuer authorizing key, used to create issuer authorization signatures. +/// An issuance authorizing key, used to create issuance authorization signatures. /// This type enforces that the corresponding public point (ik^ℙ) has ỹ = 0. /// /// $\mathsf{isk}$ as defined in -/// [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. +/// [Issuance of Zcash Shielded Assets ZIP-0227 § Asset Identifier Generation (DRAFT ZIP)][IssuanceZSA]. /// -/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents +/// [IssuanceZSA]: https://qed-it.github.io/zips/draft-ZIP-0227.html#asset-identifier-generation #[derive(Clone, Debug)] -pub struct IssuerAuthorizingKey(redpallas::SigningKey); +pub struct IssuanceAuthorizingKey(redpallas::SigningKey); -impl IssuerAuthorizingKey { +impl IssuanceAuthorizingKey { /// Derives isk from sk. Internal use only, does not enforce all constraints. fn derive_inner(sk: &SpendingKey) -> pallas::Scalar { to_scalar(PrfExpand::ZsaIsk.expand(&sk.0)) } - /// Sign the provided message using the `IssuerAuthorizingKey`. + /// Sign the provided message using the `IssuanceAuthorizingKey`. pub fn sign( &self, rng: &mut (impl RngCore + CryptoRng), @@ -220,51 +220,51 @@ impl IssuerAuthorizingKey { } } -impl From<&SpendingKey> for IssuerAuthorizingKey { +impl From<&SpendingKey> for IssuanceAuthorizingKey { fn from(sk: &SpendingKey) -> Self { let isk = Self::derive_inner(sk); - // IssuerSigningKey cannot be constructed such that this assertion would fail. + // IssuanceSigningKey cannot be constructed such that this assertion would fail. assert!(!bool::from(isk.is_zero())); - let ret = IssuerAuthorizingKey(isk.to_repr().try_into().unwrap()); + let ret = IssuanceAuthorizingKey(isk.to_repr().try_into().unwrap()); // If the last bit of repr_P(ik) is 1, negate isk. - if (<[u8; 32]>::from(IssuerValidatingKey::from(&ret).0)[31] >> 7) == 1 { - IssuerAuthorizingKey((-isk).to_repr().try_into().unwrap()) + if (<[u8; 32]>::from(IssuanceValidatingKey::from(&ret).0)[31] >> 7) == 1 { + IssuanceAuthorizingKey((-isk).to_repr().try_into().unwrap()) } else { ret } } } -/// A key used to validate issuer authorization signatures. +/// A key used to validate issuance authorization signatures. /// -/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. +/// Defined in [Issuance of Zcash Shielded Assets ZIP-0227 § Asset Identifier Generation (DRAFT PR)][IssuanceZSA]. /// Note that this is $\mathsf{ik}^\mathbb{P}$, which by construction is equivalent to /// $\mathsf{ik}$ but stored here as a RedPallas verification key. /// -/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents +/// [IssuanceZSA]: https://qed-it.github.io/zips/draft-ZIP-0227.html#asset-identifier-generation #[derive(Debug, Clone, PartialOrd, Ord)] -pub struct IssuerValidatingKey(redpallas::VerificationKey); -impl From<&IssuerAuthorizingKey> for IssuerValidatingKey { - fn from(isk: &IssuerAuthorizingKey) -> Self { - IssuerValidatingKey((&isk.0).into()) +pub struct IssuanceValidatingKey(redpallas::VerificationKey); +impl From<&IssuanceAuthorizingKey> for IssuanceValidatingKey { + fn from(isk: &IssuanceAuthorizingKey) -> Self { + IssuanceValidatingKey((&isk.0).into()) } } -impl From<&IssuerValidatingKey> for pallas::Point { - fn from(issuer_validating_key: &IssuerValidatingKey) -> pallas::Point { - pallas::Point::from_bytes(&(&issuer_validating_key.0).into()).unwrap() +impl From<&IssuanceValidatingKey> for pallas::Point { + fn from(issuance_validating_key: &IssuanceValidatingKey) -> pallas::Point { + pallas::Point::from_bytes(&(&issuance_validating_key.0).into()).unwrap() } } -impl PartialEq for IssuerValidatingKey { +impl PartialEq for IssuanceValidatingKey { fn eq(&self, other: &Self) -> bool { <[u8; 32]>::from(&self.0).eq(&<[u8; 32]>::from(&other.0)) } } -impl Eq for IssuerValidatingKey {} +impl Eq for IssuanceValidatingKey {} -impl IssuerValidatingKey { +impl IssuanceValidatingKey { /// Converts this spend validating key to its serialized form, /// I2LEOSP_256(ik). pub(crate) fn to_bytes(&self) -> [u8; 32] { @@ -277,7 +277,7 @@ impl IssuerValidatingKey { <[u8; 32]>::try_from(bytes) .ok() .and_then(check_structural_validity) - .map(IssuerValidatingKey) + .map(IssuanceValidatingKey) } /// Verifies a purported `signature` over `msg` made by this verification key. @@ -292,9 +292,9 @@ impl IssuerValidatingKey { /// A function to check structural validity of the validating keys for authorizing transfers and /// issuing assets -/// Structural validity checks for ik_P: +/// Structural validity checks for ak_P or ik_P: /// - The point must not be the identity (which for Pallas is canonically encoded as all-zeroes). -/// - The sign of the y-coordinate must be positive. +/// - The compressed y-coordinate bit must be 0. fn check_structural_validity( verification_key_bytes: [u8; 32], ) -> Option> { @@ -1043,8 +1043,8 @@ impl SharedSecret { #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { use super::{ - DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuerAuthorizingKey, - IssuerValidatingKey, SpendingKey, + DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuanceAuthorizingKey, + IssuanceValidatingKey, SpendingKey, }; use proptest::prelude::*; use rand::{rngs::StdRng, SeedableRng}; @@ -1096,17 +1096,17 @@ pub mod testing { } prop_compose! { - /// Generate a uniformly distributed RedDSA issuer authorizing key. - pub fn arb_issuer_authorizing_key()(rng_seed in prop::array::uniform32(prop::num::u8::ANY)) -> IssuerAuthorizingKey { + /// Generate a uniformly distributed RedDSA issuance authorizing key. + pub fn arb_issuance_authorizing_key()(rng_seed in prop::array::uniform32(prop::num::u8::ANY)) -> IssuanceAuthorizingKey { let mut rng = StdRng::from_seed(rng_seed); - IssuerAuthorizingKey::from(&SpendingKey::random(&mut rng)) + IssuanceAuthorizingKey::from(&SpendingKey::random(&mut rng)) } } prop_compose! { - /// Generate a uniformly distributed RedDSA issuer validating key. - pub fn arb_issuer_validating_key()(isk in arb_issuer_authorizing_key()) -> IssuerValidatingKey { - IssuerValidatingKey::from(&isk) + /// Generate a uniformly distributed RedDSA issuance validating key. + pub fn arb_issuance_validating_key()(isk in arb_issuance_authorizing_key()) -> IssuanceValidatingKey { + IssuanceValidatingKey::from(&isk) } } } @@ -1180,13 +1180,13 @@ mod tests { let ask: SpendAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask); - let isk: IssuerAuthorizingKey = (&sk).into(); + let isk: IssuanceAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&isk.0), tv.isk); let ak: SpendValidatingKey = (&ask).into(); assert_eq!(<[u8; 32]>::from(ak.0), tv.ak); - let ik: IssuerValidatingKey = (&isk).into(); + let ik: IssuanceValidatingKey = (&isk).into(); assert_eq!(<[u8; 32]>::from(ik.0), tv.ik); let nk: NullifierDerivingKey = (&sk).into(); diff --git a/src/note/note_type.rs b/src/note/note_type.rs index 45e0b532b..cd69f16ea 100644 --- a/src/note/note_type.rs +++ b/src/note/note_type.rs @@ -6,7 +6,7 @@ use std::hash::{Hash, Hasher}; use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_V_BYTES}; -use crate::keys::IssuerValidatingKey; +use crate::keys::IssuanceValidatingKey; /// Note type identifier. #[derive(Clone, Copy, Debug, Eq)] @@ -15,8 +15,7 @@ pub struct NoteType(pallas::Point); pub const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; // the hasher used to derive the assetID -#[allow(non_snake_case)] -fn assetID_hasher(msg: Vec) -> pallas::Point { +fn asset_id_hasher(msg: Vec) -> pallas::Point { // TODO(zsa) replace personalization pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION)(&msg) } @@ -32,25 +31,29 @@ impl NoteType { self.0.to_bytes() } - /// $DeriveNoteType$. + /// Note type derivation$. /// - /// Defined in [Zcash Protocol Spec § TBD: Note Types][notetypes]. + /// Defined in [Transfer and Burn of Zcash Shielded Assets][notetypes]. /// - /// [notetypes]: https://zips.z.cash/protocol/nu5.pdf#notetypes + /// [notetypes]: https://qed-it.github.io/zips/draft-ZIP-0226.html#asset-types + /// + /// # Panics + /// + /// Panics if `asset_desc` is empty or greater than `MAX_ASSET_DESCRIPTION_SIZE`. #[allow(non_snake_case)] - pub fn derive(ik: &IssuerValidatingKey, asset_desc: &str) -> Self { + pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &str) -> Self { assert!(!asset_desc.is_empty() && asset_desc.len() <= MAX_ASSET_DESCRIPTION_SIZE); let mut s = vec![]; s.extend(ik.to_bytes()); s.extend(asset_desc.as_bytes()); - NoteType(assetID_hasher(s)) + NoteType(asset_id_hasher(s)) } /// Note type for the "native" currency (zec), maintains backward compatibility with Orchard untyped notes. pub fn native() -> Self { - NoteType(assetID_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) + NoteType(asset_id_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) } /// The base point used in value commitments. @@ -85,7 +88,7 @@ pub mod testing { use proptest::prelude::*; - use crate::keys::{testing::arb_spending_key, IssuerAuthorizingKey, IssuerValidatingKey}; + use crate::keys::{testing::arb_spending_key, IssuanceAuthorizingKey, IssuanceValidatingKey}; prop_compose! { /// Generate a uniformly distributed note type @@ -97,8 +100,8 @@ pub mod testing { if is_native { NoteType::native() } else { - let isk = IssuerAuthorizingKey::from(&sk); - NoteType::derive(&IssuerValidatingKey::from(&isk), &str) + let isk = IssuanceAuthorizingKey::from(&sk); + NoteType::derive(&IssuanceValidatingKey::from(&isk), &str) } } } @@ -117,8 +120,8 @@ pub mod testing { sk in arb_spending_key(), str in "[A-Za-z]{255}" ) -> NoteType { - let isk = IssuerAuthorizingKey::from(&sk); - NoteType::derive(&IssuerValidatingKey::from(&isk), &str) + let isk = IssuanceAuthorizingKey::from(&sk); + NoteType::derive(&IssuanceValidatingKey::from(&isk), &str) } } } diff --git a/tests/zsa.rs b/tests/zsa.rs index 0335d3358..6dfff6dc0 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -5,7 +5,7 @@ use incrementalmerkletree::bridgetree::BridgeTree; use incrementalmerkletree::{Hashable, Tree}; use orchard::bundle::Authorized; use orchard::issuance::{verify_issue_bundle, IssueBundle, Signed, Unauthorized}; -use orchard::keys::{IssuerAuthorizingKey, IssuerValidatingKey}; +use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use orchard::note::{ExtractedNoteCommitment, NoteType}; use orchard::note_encryption::OrchardDomain; use orchard::tree::{MerkleHashOrchard, MerklePath}; @@ -27,8 +27,8 @@ struct Keychain { vk: VerifyingKey, sk: SpendingKey, fvk: FullViewingKey, - isk: IssuerAuthorizingKey, - ik: IssuerValidatingKey, + isk: IssuanceAuthorizingKey, + ik: IssuanceValidatingKey, recipient: Address, } @@ -42,10 +42,10 @@ impl Keychain { fn fvk(&self) -> &FullViewingKey { &self.fvk } - fn isk(&self) -> &IssuerAuthorizingKey { + fn isk(&self) -> &IssuanceAuthorizingKey { &self.isk } - fn ik(&self) -> &IssuerValidatingKey { + fn ik(&self) -> &IssuanceValidatingKey { &self.ik } } @@ -58,8 +58,8 @@ fn prepare_keys() -> Keychain { let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); - let isk = IssuerAuthorizingKey::from(&sk); - let ik = IssuerValidatingKey::from(&isk); + let isk = IssuanceAuthorizingKey::from(&sk); + let ik = IssuanceValidatingKey::from(&isk); Keychain { pk, vk, @@ -74,7 +74,7 @@ fn prepare_keys() -> Keychain { fn sign_issue_bundle( unauthorized: IssueBundle, mut rng: OsRng, - isk: IssuerAuthorizingKey, + isk: IssuanceAuthorizingKey, ) -> IssueBundle { let sighash = unauthorized.commitment().into(); let proven = unauthorized.prepare(sighash); From 355b5691ea5faf70c7a4a07de0cafa5474a14c30 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Thu, 27 Oct 2022 19:23:15 +0300 Subject: [PATCH 10/92] Review fixes2 (#24) * rename 2 note_type -> asset as per https://github.com/zcash/orchard/pull/356#discussion_r967636009 * added a dedicated type for "IssuanceAuth" * disabled codecov github action due to bad behavior. * extracted "is_asset_desc_of_valid_size()" into asset_id.rs --- .github/workflows/ci.yml | 51 +++++----- benches/circuit.rs | 4 +- benches/note_decryption.rs | 6 +- src/action.rs | 10 +- src/builder.rs | 75 +++++++------- src/bundle.rs | 4 +- src/bundle/commitments.rs | 2 +- src/circuit.rs | 8 +- src/constants/fixed_bases.rs | 2 +- src/issuance.rs | 136 ++++++++++++------------- src/keys.rs | 18 ++-- src/note.rs | 39 ++++--- src/note/{note_type.rs => asset_id.rs} | 45 ++++---- src/note/commitment.rs | 8 +- src/note_encryption.rs | 42 ++++---- src/test_vectors/note_encryption.rs | 42 ++++---- src/value.rs | 26 ++--- tests/builder.rs | 6 +- tests/zsa.rs | 40 ++++---- 19 files changed, 288 insertions(+), 276 deletions(-) rename src/note/{note_type.rs => asset_id.rs} (73%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a52477ab..e7b900029 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,31 +55,32 @@ jobs: - name: Test Orchard book run: mdbook test book/ - codecov: - name: Code coverage - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - # Use stable for this to ensure that cargo-tarpaulin can be built. - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - name: Install cargo-tarpaulin - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-tarpaulin - - name: Generate coverage report - uses: actions-rs/cargo@v1 - with: - command: tarpaulin - args: --all-features --timeout 1200 --out Xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1 - with: - token: ${{secrets.CODECOV_TOKEN}} +# disabled due to performance issues: +# codecov: +# name: Code coverage +# runs-on: ubuntu-latest +# +# steps: +# - uses: actions/checkout@v2 +# # Use stable for this to ensure that cargo-tarpaulin can be built. +# - uses: actions-rs/toolchain@v1 +# with: +# toolchain: stable +# override: true +# - name: Install cargo-tarpaulin +# uses: actions-rs/cargo@v1 +# with: +# command: install +# args: cargo-tarpaulin +# - name: Generate coverage report +# uses: actions-rs/cargo@v1 +# with: +# command: tarpaulin +# args: --all-features --timeout 1200 --out Xml +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v1 +# with: +# token: ${{secrets.CODECOV_TOKEN}} doc-links: name: Intra-doc links diff --git a/benches/circuit.rs b/benches/circuit.rs index 6400513e2..e9bab616c 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -6,7 +6,7 @@ use criterion::{BenchmarkId, Criterion}; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; -use orchard::note::NoteType; +use orchard::note::AssetId; use orchard::{ builder::Builder, bundle::Flags, @@ -37,7 +37,7 @@ fn criterion_benchmark(c: &mut Criterion) { None, recipient, NoteValue::from_raw(10), - NoteType::native(), + AssetId::native(), None, ) .unwrap(); diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 28e02de61..1417a2b6c 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -4,7 +4,7 @@ use orchard::{ bundle::Flags, circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, - note::NoteType, + note::AssetId, note_encryption::{CompactAction, OrchardDomain}, value::NoteValue, Anchor, Bundle, @@ -57,7 +57,7 @@ fn bench_note_decryption(c: &mut Criterion) { None, recipient, NoteValue::from_raw(10), - NoteType::native(), + AssetId::native(), None, ) .unwrap(); @@ -66,7 +66,7 @@ fn bench_note_decryption(c: &mut Criterion) { None, recipient, NoteValue::from_raw(10), - NoteType::native(), + AssetId::native(), None, ) .unwrap(); diff --git a/src/action.rs b/src/action.rs index b1eda4819..94fe4f3f4 100644 --- a/src/action.rs +++ b/src/action.rs @@ -126,7 +126,7 @@ pub(crate) mod testing { use proptest::prelude::*; - use crate::note::note_type::testing::arb_note_type; + use crate::note::asset_id::testing::arb_asset_id; use crate::{ note::{ commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, @@ -147,13 +147,13 @@ pub(crate) mod testing { nf in arb_nullifier(), rk in arb_spendauth_verification_key(), note in arb_note(output_value), - note_type in arb_note_type() + asset in arb_asset_id() ) -> Action<()> { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( spend_value - output_value, ValueCommitTrapdoor::zero(), - note_type + asset ); // FIXME: make a real one from the note. let encrypted_note = TransmittedNoteCiphertext { @@ -180,13 +180,13 @@ pub(crate) mod testing { note in arb_note(output_value), rng_seed in prop::array::uniform32(prop::num::u8::ANY), fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - note_type in arb_note_type() + asset in arb_asset_id() ) -> Action> { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( spend_value - output_value, ValueCommitTrapdoor::zero(), - note_type + asset ); // FIXME: make a real one from the note. diff --git a/src/builder.rs b/src/builder.rs index 526fe471e..5c6147022 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -9,7 +9,7 @@ use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; -use crate::note::NoteType; +use crate::note::AssetId; use crate::{ action::Action, address::Address, @@ -94,8 +94,8 @@ impl SpendInfo { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(note_type: NoteType, rng: &mut impl RngCore) -> Self { - let (sk, fvk, note) = Note::dummy(rng, None, note_type); + fn dummy(asset: AssetId, rng: &mut impl RngCore) -> Self { + let (sk, fvk, note) = Note::dummy(rng, None, asset); let merkle_path = MerklePath::dummy(rng); SpendInfo { @@ -110,7 +110,7 @@ impl SpendInfo { } } - /// Duplicates the spend info and set the split flag to `true`. + /// Return a copy of this note with the split flag set to `true`. fn create_split_spend(&self) -> Self { let mut split_spend = SpendInfo::new(self.fvk.clone(), self.note, self.merkle_path.clone()) .expect("The spend info is valid"); @@ -125,7 +125,7 @@ struct RecipientInfo { ovk: Option, recipient: Address, value: NoteValue, - note_type: NoteType, + asset: AssetId, memo: Option<[u8; 512]>, } @@ -133,7 +133,7 @@ impl RecipientInfo { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(rng: &mut impl RngCore, note_type: NoteType) -> Self { + fn dummy(rng: &mut impl RngCore, asset: AssetId) -> Self { let fvk: FullViewingKey = (&SpendingKey::random(rng)).into(); let recipient = fvk.address_at(0u32, Scope::External); @@ -141,7 +141,7 @@ impl RecipientInfo { ovk: None, recipient, value: NoteValue::zero(), - note_type, + asset, memo: None, } } @@ -165,13 +165,13 @@ impl ActionInfo { } /// Returns the value sum for this action. - /// Split notes does not contribute to the value sum. + /// Split notes do not contribute to the value sum. fn value_sum(&self) -> ValueSum { - let spent_value = self - .spend - .split_flag - .then(NoteValue::zero) - .unwrap_or_else(|| self.spend.note.value()); + let spent_value = if self.spend.split_flag { + NoteValue::zero() + } else { + self.spend.note.value() + }; spent_value - self.output.value } @@ -181,27 +181,30 @@ impl ActionInfo { /// Defined in [Zcash Protocol Spec § 4.7.3: Sending Notes (Orchard)][orchardsend]. /// /// [orchardsend]: https://zips.z.cash/protocol/nu5.pdf#orchardsend + /// + /// # Panics + /// + /// Panics if the asset types of the spent and output notes do not match. fn build(self, mut rng: impl RngCore) -> (Action, Circuit) { assert_eq!( - self.output.note_type, - self.spend.note.note_type(), + self.spend.note.asset(), + self.output.asset, "spend and recipient note types must be equal" ); let v_net = self.value_sum(); - let note_type = self.output.note_type; - let cv_net = ValueCommitment::derive(v_net, self.rcv, note_type); + let asset = self.output.asset; + let cv_net = ValueCommitment::derive(v_net, self.rcv, asset); let nf_old = self.spend.note.nullifier(&self.spend.fvk); let ak: SpendValidatingKey = self.spend.fvk.clone().into(); let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let note_type = self.spend.note.note_type(); let note = Note::new( self.output.recipient, self.output.value, - note_type, + self.output.asset, nf_old, &mut rng, ); @@ -316,7 +319,7 @@ impl Builder { ovk: Option, recipient: Address, value: NoteValue, - note_type: NoteType, + asset: AssetId, memo: Option<[u8; 512]>, ) -> Result<(), &'static str> { if !self.flags.outputs_enabled() { @@ -327,7 +330,7 @@ impl Builder { ovk, recipient, value, - note_type, + asset, memo, }); @@ -370,7 +373,7 @@ impl Builder { let mut pre_actions: Vec<_> = Vec::new(); // Pair up the spends and recipients, extending with dummy values as necessary. - for (note_type, (mut spends, mut recipients)) in + for (asset, (mut spends, mut recipients)) in partition_by_asset(&self.spends, &self.recipients) { let num_spends = spends.len(); @@ -384,16 +387,16 @@ impl Builder { // TODO: uncomment once the circuit is ready. // use the first spend to create split spend(s) or create a dummy if empty. // let dummy_spend = spends.first().map_or_else( - // || SpendInfo::dummy(note_type, &mut rng), + // || SpendInfo::dummy(asset, &mut rng), // |s| s.create_split_spend(), // ); - let dummy_spend = SpendInfo::dummy(note_type, &mut rng); + let dummy_spend = SpendInfo::dummy(asset, &mut rng); // Extend the spends and recipients with dummy values. spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); recipients.extend( - iter::repeat_with(|| RecipientInfo::dummy(&mut rng, note_type)) + iter::repeat_with(|| RecipientInfo::dummy(&mut rng, asset)) .take(num_actions - num_recipients), ); @@ -443,7 +446,7 @@ impl Builder { - ValueCommitment::derive( value_balance, ValueCommitTrapdoor::zero(), - NoteType::native(), + AssetId::native(), )) .into_bvk(); assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); @@ -465,18 +468,18 @@ impl Builder { fn partition_by_asset( spends: &[SpendInfo], recipients: &[RecipientInfo], -) -> HashMap, Vec)> { +) -> HashMap, Vec)> { let mut hm = HashMap::new(); for s in spends { - hm.entry(s.note.note_type()) + hm.entry(s.note.asset()) .or_insert((vec![], vec![])) .0 .push(s.clone()); } for r in recipients { - hm.entry(r.note_type) + hm.entry(r.asset) .or_insert((vec![], vec![])) .1 .push(r.clone()) @@ -749,7 +752,7 @@ pub mod testing { use proptest::collection::vec; use proptest::prelude::*; - use crate::note::NoteType; + use crate::note::AssetId; use crate::{ address::testing::arb_address, bundle::{Authorized, Bundle, Flags}, @@ -777,7 +780,7 @@ pub mod testing { sk: SpendingKey, anchor: Anchor, notes: Vec<(Note, MerklePath)>, - recipient_amounts: Vec<(Address, NoteValue, NoteType)>, + recipient_amounts: Vec<(Address, NoteValue, AssetId)>, } impl ArbitraryBundleInputs { @@ -791,12 +794,12 @@ pub mod testing { builder.add_spend(fvk.clone(), note, path).unwrap(); } - for (addr, value, note_type) in self.recipient_amounts.into_iter() { + for (addr, value, asset) in self.recipient_amounts.into_iter() { let scope = fvk.scope_for_address(&addr).unwrap(); let ovk = fvk.to_ovk(scope); builder - .add_recipient(Some(ovk.clone()), addr, value, note_type, None) + .add_recipient(Some(ovk.clone()), addr, value, asset, None) .unwrap(); } @@ -831,7 +834,7 @@ pub mod testing { arb_address().prop_flat_map(move |a| { arb_positive_note_value(MAX_NOTE_VALUE / n_recipients as u64) .prop_map(move |v| { - (a,v, NoteType::native()) + (a,v, AssetId::native()) }) }), n_recipients as usize, @@ -882,7 +885,7 @@ mod tests { use rand::rngs::OsRng; use super::Builder; - use crate::note::NoteType; + use crate::note::AssetId; use crate::{ bundle::{Authorized, Bundle, Flags}, circuit::ProvingKey, @@ -911,7 +914,7 @@ mod tests { None, recipient, NoteValue::from_raw(5000), - NoteType::native(), + AssetId::native(), None, ) .unwrap(); diff --git a/src/bundle.rs b/src/bundle.rs index 4f4e1cb3f..6f7e0bce9 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -12,7 +12,7 @@ use memuse::DynamicUsage; use nonempty::NonEmpty; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; -use crate::note::NoteType; +use crate::note::AssetId; use crate::{ action::Action, address::Address, @@ -385,7 +385,7 @@ impl> Bundle { - ValueCommitment::derive( ValueSum::from_raw(self.value_balance.into()), ValueCommitTrapdoor::zero(), - NoteType::native(), + AssetId::native(), )) .into_bvk() } diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 40808b57f..285ba31f7 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -102,7 +102,7 @@ pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) for note in action.notes().iter() { h.update(¬e.recipient().to_raw_address_bytes()); h.update(¬e.value().to_bytes()); - h.update(¬e.note_type().to_bytes()); + h.update(¬e.asset().to_bytes()); h.update(¬e.rho().to_bytes()); h.update(note.rseed().as_bytes()); } diff --git a/src/circuit.rs b/src/circuit.rs index 97d5efda2..7797f563e 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -968,7 +968,7 @@ mod tests { use rand::{rngs::OsRng, RngCore}; use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; - use crate::note::NoteType; + use crate::note::AssetId; use crate::{ keys::SpendValidatingKey, note::Note, @@ -977,7 +977,7 @@ mod tests { }; fn generate_circuit_instance(mut rng: R) -> (Circuit, Instance) { - let (_, fvk, spent_note) = Note::dummy(&mut rng, None, NoteType::native()); + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetId::native()); let sender_address = spent_note.recipient(); let nk = *fvk.nk(); @@ -987,12 +987,12 @@ mod tests { let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old), NoteType::native()); + let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old), AssetId::native()); let cmx = output_note.commitment().into(); let value = spent_note.value() - output_note.value(); let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv, NoteType::native()); + let cv_net = ValueCommitment::derive(value, rcv, AssetId::native()); let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index d9c92edd3..4b5d1518e 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -22,7 +22,7 @@ pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard"; pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv"; /// SWU hash-to-curve personalization for the note type generator -// pub const NOTE_TYPE_PERSONALIZATION: &str = "z.cash:Orchard-NoteType"; +// pub const ASSET_ID_PERSONALIZATION: &str = "z.cash:Orchard-NoteType"; /// SWU hash-to-curve value for the value commitment generator pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v"; diff --git a/src/issuance.rs b/src/issuance.rs index e8027e67f..4fbcd8421 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -12,8 +12,8 @@ use crate::issuance::Error::{ IssueBundleInvalidSignature, WrongAssetDescSize, }; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; -use crate::note::note_type::MAX_ASSET_DESCRIPTION_SIZE; -use crate::note::{NoteType, Nullifier}; +use crate::note::asset_id::is_asset_desc_of_valid_size; +use crate::note::{AssetId, Nullifier}; use crate::value::NoteValue; use crate::{ primitives::redpallas::{self, SpendAuth}, @@ -81,24 +81,24 @@ impl IssueAction { self.finalize } - /// Return the `NoteType` if the provided `ik` is used to derive the `note_type` for **all** internal notes. - fn are_note_types_derived_correctly( + /// Return the `AssetId` if the provided `ik` is used to derive the `asset_id` for **all** internal notes. + fn are_note_asset_ids_derived_correctly( &self, ik: &IssuanceValidatingKey, - ) -> Result { + ) -> Result { match self .notes .iter() - .try_fold(self.notes().head.note_type(), |note_type, ¬e| { + .try_fold(self.notes().head.asset(), |asset, ¬e| { // Fail if not all note types are equal - note.note_type() - .eq(¬e_type) - .then(|| note_type) + note.asset() + .eq(&asset) + .then(|| asset) .ok_or(IssueActionIncorrectNoteType) }) { - Ok(note_type) => note_type // check that the note_type was properly derived. - .eq(&NoteType::derive(ik, &self.asset_desc)) - .then(|| note_type) + Ok(asset) => asset // check that the asset was properly derived. + .eq(&AssetId::derive(ik, &self.asset_desc)) + .then(|| asset) .ok_or(IssueBundleIkMismatchNoteType), Err(e) => Err(e), } @@ -162,12 +162,12 @@ impl IssueBundle { self.actions.iter().find(|a| a.asset_desc.eq(&asset_desc)) } - /// Find an action by `note_type` for a given `IssueBundle`. - pub fn get_action_by_type(&self, note_type: NoteType) -> Option<&IssueAction> { + /// Find an action by `asset` for a given `IssueBundle`. + pub fn get_action_by_type(&self, asset: AssetId) -> Option<&IssueAction> { let action = self .actions .iter() - .find(|a| NoteType::derive(&self.ik, &a.asset_desc).eq(¬e_type)); + .find(|a| AssetId::derive(&self.ik, &a.asset_desc).eq(&asset)); action } @@ -202,17 +202,17 @@ impl IssueBundle { value: NoteValue, finalize: bool, mut rng: impl RngCore, - ) -> Result { - if !is_asset_desc_valid(&asset_desc) { + ) -> Result { + if !is_asset_desc_of_valid_size(&asset_desc) { return Err(WrongAssetDescSize); } - let note_type = NoteType::derive(&self.ik, &asset_desc); + let asset = AssetId::derive(&self.ik, &asset_desc); let note = Note::new( recipient, value, - note_type, + asset, Nullifier::dummy(&mut rng), &mut rng, ); @@ -238,7 +238,7 @@ impl IssueBundle { } } - Ok(note_type) + Ok(asset) } /// Finalizes a given `IssueAction` @@ -247,7 +247,7 @@ impl IssueBundle { /// /// Panics if `asset_desc` is empty or longer than 512 bytes. pub fn finalize_action(&mut self, asset_desc: String) -> Result<(), Error> { - if !is_asset_desc_valid(&asset_desc) { + if !is_asset_desc_of_valid_size(&asset_desc) { return Err(WrongAssetDescSize); } @@ -279,7 +279,7 @@ impl IssueBundle { impl IssueBundle { /// Sign the `IssueBundle`. - /// The call makes sure that the provided `isk` matches the `ik` and the driven `note_type` for each note in the bundle. + /// The call makes sure that the provided `isk` matches the `ik` and the driven `asset` for each note in the bundle. pub fn sign( self, mut rng: R, @@ -287,10 +287,10 @@ impl IssueBundle { ) -> Result, Error> { let expected_ik: IssuanceValidatingKey = (isk).into(); - // Make sure the `expected_ik` matches the note_type for all notes. + // Make sure the `expected_ik` matches the `asset` for all notes. self.actions.iter().try_for_each(|action| { action - .are_note_types_derived_correctly(&expected_ik) + .are_note_asset_ids_derived_correctly(&expected_ik) .map(|_| ()) // Transform Result into Result<(),Error)>. })?; @@ -332,14 +332,10 @@ impl IssueBundle { } } -fn is_asset_desc_valid(asset_desc: &str) -> bool { - !asset_desc.is_empty() && asset_desc.bytes().len() <= MAX_ASSET_DESCRIPTION_SIZE -} - /// Validation for Orchard IssueBundles /// /// A set of previously finalized asset types must be provided. -/// In case of success, the `Result` will contain a set of the provided **and** the newly finalized `NoteType`s +/// In case of success, `finalized` will contain a set of the provided **and** the newly finalized `NoteType`s /// /// The following checks are performed: /// * For the `IssueBundle`: @@ -348,43 +344,46 @@ fn is_asset_desc_valid(asset_desc: &str) -> bool { /// * Asset description size is collect. /// * `NoteType` for the `IssueAction` has not been previously finalized. /// * For each `Note` inside an `IssueAction`: -/// * All notes have the same, correct `NoteType` -pub fn verify_issue_bundle<'a>( +/// * All notes have the same, correct `NoteType`. +pub fn verify_issue_bundle( bundle: &IssueBundle, sighash: [u8; 32], - previously_finalized: &'a mut HashSet, // The current note_type finalization set. -) -> Result<&'a mut HashSet, Error> { + finalized: &mut HashSet, // The current finalization set. +) -> Result<(), Error> { if let Err(e) = bundle.ik.verify(&sighash, &bundle.authorization.signature) { return Err(IssueBundleInvalidSignature(e)); }; + let currently_finalized: &mut HashSet = &mut HashSet::new(); + // Any IssueAction could have just one properly derived NoteType. - bundle + let res = bundle .actions() .iter() - .try_fold(previously_finalized, |acc, action| { - if !is_asset_desc_valid(action.asset_desc()) { + .try_fold(currently_finalized, |acc, action| { + if !is_asset_desc_of_valid_size(action.asset_desc()) { return Err(WrongAssetDescSize); } // Fail if any note in the IssueAction has incorrect note type. - let note_type = action.are_note_types_derived_correctly(bundle.ik())?; + let asset = action.are_note_asset_ids_derived_correctly(bundle.ik())?; - // Fail if the current note_type was previously finalized. - if acc.contains(¬e_type) { - return Err(IssueActionPreviouslyFinalizedNoteType(note_type)); + // Fail if the current asset was previously finalized. + if finalized.contains(&asset) || acc.contains(&asset) { + return Err(IssueActionPreviouslyFinalizedNoteType(asset)); } // Add to finalization set, if needed. if action.is_finalized() { - acc.insert(note_type); + acc.insert(asset); } - // Proceed with the new accumulated note_type finalization set. + // Proceed with the new asset finalization set. Ok(acc) - }) + })?; - // The iterator will return the new finalization set or will fail. + finalized.extend(res.iter()); + Ok(()) } /// Errors produced during the issuance process @@ -405,7 +404,7 @@ pub enum Error { /// Invalid signature. IssueBundleInvalidSignature(reddsa::Error), /// The provided `NoteType` has been previously finalized. - IssueActionPreviouslyFinalizedNoteType(NoteType), + IssueActionPreviouslyFinalizedNoteType(AssetId), } impl std::error::Error for Error {} @@ -456,7 +455,7 @@ mod tests { use crate::keys::{ FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; - use crate::note::{NoteType, Nullifier}; + use crate::note::{AssetId, Nullifier}; use crate::value::NoteValue; use crate::{Address, Note}; use nonempty::NonEmpty; @@ -522,37 +521,37 @@ mod tests { WrongAssetDescSize ); - let note_type = bundle + let asset = bundle .add_recipient(str.clone(), recipient, NoteValue::from_raw(5), false, rng) .unwrap(); - let another_note_type = bundle + let another_asset = bundle .add_recipient(str, recipient, NoteValue::from_raw(10), false, rng) .unwrap(); - assert_eq!(note_type, another_note_type); + assert_eq!(asset, another_asset); - let third_note_type = bundle + let third_asset = bundle .add_recipient(str2.clone(), recipient, NoteValue::from_raw(15), false, rng) .unwrap(); - assert_ne!(note_type, third_note_type); + assert_ne!(asset, third_asset); let actions = bundle.actions(); assert_eq!(actions.len(), 2); - let action = bundle.get_action_by_type(note_type).unwrap(); + let action = bundle.get_action_by_type(asset).unwrap(); assert_eq!(action.notes.len(), 2); assert_eq!(action.notes.first().value().inner(), 5); - assert_eq!(action.notes.first().note_type(), note_type); + assert_eq!(action.notes.first().asset(), asset); assert_eq!(action.notes.first().recipient(), recipient); assert_eq!(action.notes.tail().first().unwrap().value().inner(), 10); - assert_eq!(action.notes.tail().first().unwrap().note_type(), note_type); + assert_eq!(action.notes.tail().first().unwrap().asset(), asset); assert_eq!(action.notes.tail().first().unwrap().recipient(), recipient); let action2 = bundle.get_action(str2).unwrap(); assert_eq!(action2.notes.len(), 1); assert_eq!(action2.notes().first().value().inner(), 15); - assert_eq!(action2.notes().first().note_type(), third_note_type); + assert_eq!(action2.notes().first().asset(), third_asset); } #[test] @@ -700,7 +699,7 @@ mod tests { } #[test] - fn issue_bundle_incorrect_note_type_for_signature() { + fn issue_bundle_incorrect_asset_for_signature() { let (mut rng, isk, ik, recipient, _) = setup_params(); let mut bundle = IssueBundle::new(ik); @@ -720,7 +719,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - NoteType::derive(bundle.ik(), "Poisoned pill"), + AssetId::derive(bundle.ik(), "Poisoned pill"), Nullifier::dummy(&mut rng), &mut rng, ); @@ -760,8 +759,9 @@ mod tests { let prev_finalized = &mut HashSet::new(); - let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); - assert!(finalized.unwrap().is_empty()); + let res = verify_issue_bundle(&signed, sighash, prev_finalized); + assert!(res.is_ok()); + assert!(prev_finalized.is_empty()); } #[test] @@ -784,12 +784,12 @@ mod tests { let prev_finalized = &mut HashSet::new(); - let finalized = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); - assert!(finalized.contains(&NoteType::derive( - &ik, - &String::from("verify_with_finalize") - ))); - assert_eq!(finalized.len(), 1); + let res = verify_issue_bundle(&signed, sighash, prev_finalized); + assert!(res.is_ok()); + assert!( + prev_finalized.contains(&AssetId::derive(&ik, &String::from("verify_with_finalize"))) + ); + assert_eq!(prev_finalized.len(), 1); } #[test] @@ -811,7 +811,7 @@ mod tests { let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); let prev_finalized = &mut HashSet::new(); - let final_type = NoteType::derive(&ik, &String::from("already final")); + let final_type = AssetId::derive(&ik, &String::from("already final")); prev_finalized.insert(final_type); @@ -911,7 +911,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - NoteType::derive(signed.ik(), "Poisoned pill"), + AssetId::derive(signed.ik(), "Poisoned pill"), Nullifier::dummy(&mut rng), &mut rng, ); @@ -958,7 +958,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(55), - NoteType::derive(&incorrect_ik, asset_description), + AssetId::derive(&incorrect_ik, asset_description), Nullifier::dummy(&mut rng), &mut rng, ); diff --git a/src/keys.rs b/src/keys.rs index d10e6e24e..65d464147 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -194,6 +194,9 @@ impl SpendValidatingKey { } } +/// We currently use `SpendAuth` as the `IssuanceAuth`. +type IssuanceAuth = SpendAuth; + /// An issuance authorizing key, used to create issuance authorization signatures. /// This type enforces that the corresponding public point (ik^ℙ) has ỹ = 0. /// @@ -202,7 +205,7 @@ impl SpendValidatingKey { /// /// [IssuanceZSA]: https://qed-it.github.io/zips/draft-ZIP-0227.html#asset-identifier-generation #[derive(Clone, Debug)] -pub struct IssuanceAuthorizingKey(redpallas::SigningKey); +pub struct IssuanceAuthorizingKey(redpallas::SigningKey); impl IssuanceAuthorizingKey { /// Derives isk from sk. Internal use only, does not enforce all constraints. @@ -215,7 +218,7 @@ impl IssuanceAuthorizingKey { &self, rng: &mut (impl RngCore + CryptoRng), msg: &[u8], - ) -> redpallas::Signature { + ) -> redpallas::Signature { self.0.sign(rng, msg) } } @@ -223,7 +226,7 @@ impl IssuanceAuthorizingKey { impl From<&SpendingKey> for IssuanceAuthorizingKey { fn from(sk: &SpendingKey) -> Self { let isk = Self::derive_inner(sk); - // IssuanceSigningKey cannot be constructed such that this assertion would fail. + // IssuanceAuthorizingKey cannot be constructed such that this assertion would fail. assert!(!bool::from(isk.is_zero())); let ret = IssuanceAuthorizingKey(isk.to_repr().try_into().unwrap()); // If the last bit of repr_P(ik) is 1, negate isk. @@ -243,7 +246,8 @@ impl From<&SpendingKey> for IssuanceAuthorizingKey { /// /// [IssuanceZSA]: https://qed-it.github.io/zips/draft-ZIP-0227.html#asset-identifier-generation #[derive(Debug, Clone, PartialOrd, Ord)] -pub struct IssuanceValidatingKey(redpallas::VerificationKey); +pub struct IssuanceValidatingKey(VerificationKey); + impl From<&IssuanceAuthorizingKey> for IssuanceValidatingKey { fn from(isk: &IssuanceAuthorizingKey) -> Self { IssuanceValidatingKey((&isk.0).into()) @@ -284,7 +288,7 @@ impl IssuanceValidatingKey { pub fn verify( &self, msg: &[u8], - signature: &redpallas::Signature, + signature: &redpallas::Signature, ) -> Result<(), reddsa::Error> { self.0.verify(msg, signature) } @@ -1120,7 +1124,7 @@ mod tests { testing::{arb_diversifier_index, arb_diversifier_key, arb_esk, arb_spending_key}, *, }; - use crate::note::NoteType; + use crate::note::AssetId; use crate::{ note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, value::NoteValue, @@ -1212,7 +1216,7 @@ mod tests { let note = Note::from_parts( addr, NoteValue::from_raw(tv.note_v), - NoteType::native(), + AssetId::native(), rho, RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(), ) diff --git a/src/note.rs b/src/note.rs index 75c3d9c64..3ac8560e1 100644 --- a/src/note.rs +++ b/src/note.rs @@ -19,8 +19,8 @@ pub use self::commitment::{ExtractedNoteCommitment, NoteCommitment}; pub(crate) mod nullifier; pub use self::nullifier::Nullifier; -pub(crate) mod note_type; -pub use self::note_type::NoteType; +pub(crate) mod asset_id; +pub use self::asset_id::AssetId; /// The ZIP 212 seed randomness for a note. #[derive(Copy, Clone, Debug)] @@ -93,8 +93,8 @@ pub struct Note { recipient: Address, /// The value of this note. value: NoteValue, - /// The type of this note. - note_type: NoteType, + /// The asset id of this note. + asset: AssetId, /// A unique creation ID for this note. /// /// This is set to the nullifier of the note that was spent in the [`Action`] that @@ -134,14 +134,14 @@ impl Note { pub fn from_parts( recipient: Address, value: NoteValue, - note_type: NoteType, + asset: AssetId, rho: Nullifier, rseed: RandomSeed, ) -> CtOption { let note = Note { recipient, value, - note_type, + asset, rho, rseed, }; @@ -156,12 +156,12 @@ impl Note { pub(crate) fn new( recipient: Address, value: NoteValue, - note_type: NoteType, + asset: AssetId, rho: Nullifier, mut rng: impl RngCore, ) -> Self { loop { - let note = Note::from_parts(recipient, value, note_type, rho, RandomSeed::random(&mut rng, &rho)); + let note = Note::from_parts(recipient, value, asset, rho, RandomSeed::random(&mut rng, &rho)); if note.is_some().into() { break note.unwrap(); } @@ -173,11 +173,10 @@ impl Note { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - /// TODO zsa: remove note_type pub(crate) fn dummy( rng: &mut impl RngCore, rho: Option, - note_type: NoteType, + asset: AssetId, ) -> (SpendingKey, FullViewingKey, Self) { let sk = SpendingKey::random(rng); let fvk: FullViewingKey = (&sk).into(); @@ -186,7 +185,7 @@ impl Note { let note = Note::new( recipient, NoteValue::zero(), - note_type, + asset, rho.unwrap_or_else(|| Nullifier::dummy(rng)), rng, ); @@ -205,8 +204,8 @@ impl Note { } /// Returns the note type of this note. - pub fn note_type(&self) -> NoteType { - self.note_type + pub fn asset(&self) -> AssetId { + self.asset } /// Returns the rseed value of this note. @@ -250,7 +249,7 @@ impl Note { g_d.to_bytes(), self.recipient.pk_d().to_bytes(), self.value, - self.note_type, + self.asset, self.rho.0, self.rseed.psi(&self.rho), self.rseed.rcm(&self.rho), @@ -296,8 +295,8 @@ impl fmt::Debug for TransmittedNoteCiphertext { pub mod testing { use proptest::prelude::*; - use crate::note::note_type::testing::arb_note_type; - use crate::note::note_type::testing::zsa_note_type; + use crate::note::asset_id::testing::arb_asset_id; + use crate::note::asset_id::testing::zsa_asset_id; use crate::value::testing::arb_note_value; use crate::{ address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, @@ -318,12 +317,12 @@ pub mod testing { recipient in arb_address(), rho in arb_nullifier(), rseed in arb_rseed(), - note_type in arb_note_type(), + asset in arb_asset_id(), ) -> Note { Note { recipient, value, - note_type, + asset, rho, rseed, } @@ -337,12 +336,12 @@ pub mod testing { value in arb_note_value(), rho in arb_nullifier(), rseed in arb_rseed(), - note_type in zsa_note_type(), + asset in zsa_asset_id(), ) -> Note { Note { recipient, value, - note_type, + asset, rho, rseed, } diff --git a/src/note/note_type.rs b/src/note/asset_id.rs similarity index 73% rename from src/note/note_type.rs rename to src/note/asset_id.rs index cd69f16ea..6d9466e05 100644 --- a/src/note/note_type.rs +++ b/src/note/asset_id.rs @@ -10,7 +10,7 @@ use crate::keys::IssuanceValidatingKey; /// Note type identifier. #[derive(Clone, Copy, Debug, Eq)] -pub struct NoteType(pallas::Point); +pub struct AssetId(pallas::Point); pub const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; @@ -20,13 +20,13 @@ fn asset_id_hasher(msg: Vec) -> pallas::Point { pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION)(&msg) } -impl NoteType { - /// Deserialize the note_type from a byte array. +impl AssetId { + /// Deserialize the asset_id from a byte array. pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Point::from_bytes(bytes).map(NoteType) + pallas::Point::from_bytes(bytes).map(AssetId) } - /// Serialize the note_type to its canonical byte representation. + /// Serialize the asset_id to its canonical byte representation. pub fn to_bytes(self) -> [u8; 32] { self.0.to_bytes() } @@ -42,18 +42,18 @@ impl NoteType { /// Panics if `asset_desc` is empty or greater than `MAX_ASSET_DESCRIPTION_SIZE`. #[allow(non_snake_case)] pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &str) -> Self { - assert!(!asset_desc.is_empty() && asset_desc.len() <= MAX_ASSET_DESCRIPTION_SIZE); + assert!(is_asset_desc_of_valid_size(asset_desc)); let mut s = vec![]; s.extend(ik.to_bytes()); s.extend(asset_desc.as_bytes()); - NoteType(asset_id_hasher(s)) + AssetId(asset_id_hasher(s)) } /// Note type for the "native" currency (zec), maintains backward compatibility with Orchard untyped notes. pub fn native() -> Self { - NoteType(asset_id_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) + AssetId(asset_id_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) } /// The base point used in value commitments. @@ -67,14 +67,19 @@ impl NoteType { } } -impl Hash for NoteType { +impl Hash for AssetId { fn hash(&self, h: &mut H) { h.write(&self.to_bytes()); h.finish(); } } -impl PartialEq for NoteType { +/// Check that `asset_desc` is of valid size. +pub fn is_asset_desc_of_valid_size(asset_desc: &str) -> bool { + !asset_desc.is_empty() && asset_desc.bytes().len() <= MAX_ASSET_DESCRIPTION_SIZE +} + +impl PartialEq for AssetId { fn eq(&self, other: &Self) -> bool { bool::from(self.0.ct_eq(&other.0)) } @@ -84,7 +89,7 @@ impl PartialEq for NoteType { #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { - use super::NoteType; + use super::AssetId; use proptest::prelude::*; @@ -92,36 +97,36 @@ pub mod testing { prop_compose! { /// Generate a uniformly distributed note type - pub fn arb_note_type()( + pub fn arb_asset_id()( is_native in prop::bool::ANY, sk in arb_spending_key(), str in "[A-Za-z]{255}", - ) -> NoteType { + ) -> AssetId { if is_native { - NoteType::native() + AssetId::native() } else { let isk = IssuanceAuthorizingKey::from(&sk); - NoteType::derive(&IssuanceValidatingKey::from(&isk), &str) + AssetId::derive(&IssuanceValidatingKey::from(&isk), &str) } } } prop_compose! { /// Generate the native note type - pub fn native_note_type()(_i in 0..10) -> NoteType { + pub fn native_asset_id()(_i in 0..10) -> AssetId { // TODO: remove _i - NoteType::native() + AssetId::native() } } prop_compose! { /// Generate the ZSA note type - pub fn zsa_note_type()( + pub fn zsa_asset_id()( sk in arb_spending_key(), str in "[A-Za-z]{255}" - ) -> NoteType { + ) -> AssetId { let isk = IssuanceAuthorizingKey::from(&sk); - NoteType::derive(&IssuanceValidatingKey::from(&isk), &str) + AssetId::derive(&IssuanceValidatingKey::from(&isk), &str) } } } diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 95dc92a2c..f4bc7247b 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -11,7 +11,7 @@ use crate::{ fixed_bases::{NOTE_COMMITMENT_PERSONALIZATION, NOTE_ZSA_COMMITMENT_PERSONALIZATION}, L_ORCHARD_BASE, }, - note::note_type::NoteType, + note::asset_id::AssetId, spec::extract_p, value::NoteValue, }; @@ -45,7 +45,7 @@ impl NoteCommitment { g_d: [u8; 32], pk_d: [u8; 32], v: NoteValue, - note_type: NoteType, + asset: AssetId, rho: pallas::Base, psi: pallas::Base, rcm: NoteCommitTrapdoor, @@ -64,13 +64,13 @@ impl NoteCommitment { .chain(psi_bits.iter().by_vals().take(L_ORCHARD_BASE)); // TODO: make this constant-time. - if note_type.is_native().into() { + if asset.is_native().into() { // Commit to ZEC notes as per the Orchard protocol. Self::commit(NOTE_COMMITMENT_PERSONALIZATION, zec_note_bits, rcm) } else { // Commit to non-ZEC notes as per the ZSA protocol. // Append the note type to the Orchard note encoding. - let type_bits = BitArray::<_, Lsb0>::new(note_type.to_bytes()); + let type_bits = BitArray::<_, Lsb0>::new(asset.to_bytes()); let zsa_note_bits = zec_note_bits.chain(type_bits.iter().by_vals()); // Commit in a different domain than Orchard notes. diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 57dd76589..48456e261 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -9,7 +9,7 @@ use zcash_note_encryption::{ OUT_PLAINTEXT_SIZE, }; -use crate::note::NoteType; +use crate::note::AssetId; use crate::{ action::Action, keys::{ @@ -72,7 +72,7 @@ where // Check note plaintext version // and parse the asset type accordingly. - let note_type = parse_version_and_asset_type(plaintext)?; + let asset = parse_version_and_asset_type(plaintext)?; // The unwraps below are guaranteed to succeed by the assertion above let diversifier = Diversifier::from_bytes(plaintext[1..12].try_into().unwrap()); @@ -86,19 +86,19 @@ where let recipient = Address::from_parts(diversifier, pk_d); - let note = Option::from(Note::from_parts(recipient, value, note_type, domain.rho, rseed))?; + let note = Option::from(Note::from_parts(recipient, value, asset, domain.rho, rseed))?; Some((note, recipient)) } -fn parse_version_and_asset_type(plaintext: &[u8]) -> Option { +fn parse_version_and_asset_type(plaintext: &[u8]) -> Option { // TODO: make this constant-time? match plaintext[0] { - 0x02 => Some(NoteType::native()), + 0x02 => Some(AssetId::native()), 0x03 if plaintext.len() >= COMPACT_ZSA_NOTE_SIZE => { let bytes = &plaintext[COMPACT_NOTE_SIZE..COMPACT_ZSA_NOTE_SIZE] .try_into() .unwrap(); - NoteType::from_bytes(bytes).into() + AssetId::from_bytes(bytes).into() } _ => None, } @@ -192,18 +192,18 @@ impl Domain for OrchardDomain { _: &Self::Recipient, memo: &Self::Memo, ) -> NotePlaintextBytes { - let is_native: bool = note.note_type().is_native().into(); + let is_native: bool = note.asset().is_native().into(); let mut np = [0; NOTE_PLAINTEXT_SIZE]; np[0] = if is_native { 0x02 } else { 0x03 }; np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); np[12..20].copy_from_slice(¬e.value().to_bytes()); - // todo: add note_type + // todo: add asset_id np[20..52].copy_from_slice(note.rseed().as_bytes()); if is_native { np[52..].copy_from_slice(memo); } else { - let zsa_type = note.note_type().to_bytes(); + let zsa_type = note.asset().to_bytes(); np[52..84].copy_from_slice(&zsa_type); let short_memo = &memo[0..memo.len() - ZSA_TYPE_SIZE]; np[84..].copy_from_slice(short_memo); @@ -276,13 +276,13 @@ impl Domain for OrchardDomain { fn extract_memo(&self, plaintext: &NotePlaintextBytes) -> Self::Memo { let mut memo = [0; MEMO_SIZE]; - match get_note_version(plaintext) { + match get_note_plaintext_version(plaintext) { 0x02 => { let full_memo = &plaintext.0[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]; memo.copy_from_slice(full_memo); } 0x03 => { - // ZSA note plaintext have a shorter memo. + // ZSA note plaintexts have a shorter memo. let short_memo = &plaintext.0[COMPACT_ZSA_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]; memo[..ZSA_MEMO_SIZE].copy_from_slice(short_memo); } @@ -316,7 +316,7 @@ impl BatchDomain for OrchardDomain { } } -fn get_note_version(plaintext: &NotePlaintextBytes) -> u8 { +fn get_note_plaintext_version(plaintext: &NotePlaintextBytes) -> u8 { plaintext.0[0] } @@ -410,7 +410,7 @@ mod tests { }; use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; - use crate::note::NoteType; + use crate::note::AssetId; use crate::{ action::Action, keys::{ @@ -426,7 +426,7 @@ mod tests { Address, Note, }; - use super::{get_note_version, orchard_parse_note_plaintext_without_memo}; + use super::{get_note_plaintext_version, orchard_parse_note_plaintext_without_memo}; proptest! { #[test] @@ -440,7 +440,7 @@ mod tests { // Decode. let domain = OrchardDomain { rho: note.rho() }; - let parsed_version = get_note_version(&plaintext); + let parsed_version = get_note_plaintext_version(&plaintext); let parsed_memo = domain.extract_memo(&plaintext); let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &plaintext.0, @@ -454,7 +454,7 @@ mod tests { assert_eq!(parsed_note, note); assert_eq!(parsed_recipient, note.recipient()); - if parsed_note.note_type().is_native().into() { + if parsed_note.asset().is_native().into() { assert_eq!(parsed_version, 0x02); assert_eq!(&parsed_memo, memo); } else { @@ -510,12 +510,12 @@ mod tests { let recipient = Address::from_parts(d, pk_d); - let note_type = match tv.note_type { - None => NoteType::native(), - Some(type_bytes) => NoteType::from_bytes(&type_bytes).unwrap(), + let asset = match tv.asset { + None => AssetId::native(), + Some(type_bytes) => AssetId::from_bytes(&type_bytes).unwrap(), }; - let note = Note::from_parts(recipient, value, note_type, rho, rseed).unwrap(); + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); let action = Action::from_parts( @@ -554,7 +554,7 @@ mod tests { assert_eq!(decrypted_note, note); assert_eq!(decrypted_to, recipient); } - None => assert!(tv.note_type.is_some(), "Compact note decryption failed"), + None => assert!(tv.asset.is_some(), "Compact note decryption failed"), // Ignore that ZSA notes are not detected in compact decryption. } diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption.rs index 7d2b7c960..9501a79b1 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption.rs @@ -20,7 +20,7 @@ pub(crate) struct TestVector { pub(crate) ock: [u8; 32], pub(crate) op: [u8; 64], pub(crate) c_out: [u8; 80], - pub(crate) note_type: Option<[u8; 32]>, + pub(crate) asset: Option<[u8; 32]>, } pub(crate) fn test_vectors() -> Vec { @@ -233,7 +233,7 @@ pub(crate) fn test_vectors() -> Vec { 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -443,7 +443,7 @@ pub(crate) fn test_vectors() -> Vec { 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -653,7 +653,7 @@ pub(crate) fn test_vectors() -> Vec { 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -863,7 +863,7 @@ pub(crate) fn test_vectors() -> Vec { 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -1073,7 +1073,7 @@ pub(crate) fn test_vectors() -> Vec { 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -1283,7 +1283,7 @@ pub(crate) fn test_vectors() -> Vec { 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -1493,7 +1493,7 @@ pub(crate) fn test_vectors() -> Vec { 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -1703,7 +1703,7 @@ pub(crate) fn test_vectors() -> Vec { 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -1913,7 +1913,7 @@ pub(crate) fn test_vectors() -> Vec { 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -2123,7 +2123,7 @@ pub(crate) fn test_vectors() -> Vec { 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, ], - note_type: None, + asset: None, }, TestVector { incoming_viewing_key: [ @@ -2333,7 +2333,7 @@ pub(crate) fn test_vectors() -> Vec { 0x13, 0x51, 0xe2, 0x4b, 0x47, 0x02, 0x87, 0xd5, 0x83, 0xba, 0x69, 0x71, 0x18, 0xec, 0x07, 0xf6, 0x59, 0x2c, 0x4c, 0xd7, 0xcd, 0x6a, 0xc7, 0x7e, ], - note_type: Some([ + asset: Some([ 0xa9, 0x71, 0x5e, 0x65, 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, 0x84, 0xef, 0xd9, 0x2c, 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, 0x4f, 0x95, 0x22, 0xb2, @@ -2547,7 +2547,7 @@ pub(crate) fn test_vectors() -> Vec { 0xe8, 0x27, 0xdd, 0x43, 0x89, 0xb8, 0x57, 0xd1, 0x6d, 0xb8, 0x24, 0xe7, 0x72, 0xba, 0x5a, 0xb5, 0xe2, 0x8d, 0xd6, 0xe9, 0x80, 0x82, 0x6b, 0xed, ], - note_type: Some([ + asset: Some([ 0xdf, 0xfd, 0x79, 0xa9, 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, 0x01, 0xe2, 0x99, 0x0a, 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, 0xfd, 0x7d, 0x05, 0x8a, @@ -2761,7 +2761,7 @@ pub(crate) fn test_vectors() -> Vec { 0xe7, 0xb9, 0x41, 0x0d, 0x6b, 0xe7, 0x59, 0x2a, 0xed, 0xa9, 0xf5, 0x2d, 0x56, 0xd8, 0xc9, 0xf9, 0x3a, 0x0b, 0xe3, 0x8c, 0xfc, 0x8d, 0xc2, 0x94, ], - note_type: Some([ + asset: Some([ 0xa6, 0x33, 0x05, 0x44, 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, 0x5a, 0x31, 0xf6, 0x2e, 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, 0xb4, 0x42, 0x68, 0x3c, @@ -2975,7 +2975,7 @@ pub(crate) fn test_vectors() -> Vec { 0xb3, 0x76, 0xcf, 0x33, 0xc9, 0xff, 0x27, 0xa5, 0xaa, 0x01, 0x58, 0x24, 0xe6, 0x78, 0x6e, 0x16, 0xe3, 0x7b, 0x35, 0x5c, 0xf7, 0x54, 0x52, 0xdb, ], - note_type: Some([ + asset: Some([ 0x61, 0x16, 0xcf, 0xec, 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, 0x6a, 0xe8, 0xf7, 0xcc, 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, 0x38, 0xe1, 0x73, 0x29, @@ -3189,7 +3189,7 @@ pub(crate) fn test_vectors() -> Vec { 0x9a, 0xb5, 0xa7, 0xce, 0x77, 0x2b, 0x52, 0x2c, 0x4b, 0xaa, 0x12, 0x95, 0xd8, 0x8f, 0x15, 0xdc, 0x75, 0x1d, 0xdf, 0x7d, 0x20, 0x8d, 0xd5, 0x17, ], - note_type: Some([ + asset: Some([ 0x29, 0x8a, 0xc0, 0xaf, 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, 0x62, 0xcd, 0x1c, 0xa0, 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, 0x82, 0x1a, 0x41, 0x84, @@ -3403,7 +3403,7 @@ pub(crate) fn test_vectors() -> Vec { 0x1e, 0x58, 0x7e, 0x43, 0xfd, 0xfc, 0x65, 0xfe, 0x52, 0xf1, 0xe0, 0xc6, 0xa0, 0x46, 0x46, 0x48, 0xcd, 0x1f, 0xc8, 0x9e, 0x80, 0xbd, 0x78, 0x0f, ], - note_type: Some([ + asset: Some([ 0xf9, 0x78, 0x1e, 0xbe, 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, 0xf1, 0xb1, 0xaa, 0x9b, 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, 0xe3, 0x81, 0x93, 0xbc, @@ -3617,7 +3617,7 @@ pub(crate) fn test_vectors() -> Vec { 0x51, 0xa5, 0x38, 0x28, 0x0d, 0xaa, 0x94, 0x20, 0x3a, 0xb5, 0x02, 0xa8, 0x15, 0x09, 0xe4, 0x3a, 0x61, 0xa6, 0x98, 0x56, 0x57, 0xd9, 0xe8, 0x4e, ], - note_type: Some([ + asset: Some([ 0x76, 0xba, 0x24, 0x3f, 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, 0xc4, 0xbd, 0x4f, 0xc9, 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, 0xf6, 0x99, 0x03, 0x18, @@ -3831,7 +3831,7 @@ pub(crate) fn test_vectors() -> Vec { 0xe2, 0x31, 0x31, 0xf4, 0xe7, 0x6b, 0xa7, 0x6b, 0x9d, 0x64, 0x66, 0x78, 0xd8, 0x53, 0xd1, 0xdc, 0xaf, 0x81, 0xb8, 0x0e, 0x2e, 0xfd, 0xf0, 0x60, ], - note_type: Some([ + asset: Some([ 0x64, 0xd0, 0x87, 0x40, 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, 0xc3, 0x93, 0x11, 0x78, 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, 0xe5, 0xf5, 0xd4, 0xbc, @@ -4045,7 +4045,7 @@ pub(crate) fn test_vectors() -> Vec { 0xd8, 0x15, 0xf7, 0x29, 0x8c, 0x1d, 0x59, 0x09, 0x1f, 0x1b, 0x38, 0x7a, 0x26, 0x46, 0xe7, 0xfe, 0x36, 0x3a, 0xde, 0x83, 0x63, 0xa9, 0x2a, 0xde, ], - note_type: Some([ + asset: Some([ 0xc3, 0xcc, 0x4f, 0x43, 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, 0xe3, 0x7a, 0x83, 0xec, 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, 0x29, 0x03, 0x35, 0xaa, @@ -4259,7 +4259,7 @@ pub(crate) fn test_vectors() -> Vec { 0x62, 0x00, 0xfb, 0x18, 0x7d, 0x2c, 0x16, 0x90, 0x65, 0xaf, 0x84, 0xcc, 0x02, 0x3d, 0x6d, 0x63, 0xce, 0x05, 0x83, 0x28, 0xe2, 0x47, 0xb5, 0x98, ], - note_type: Some([ + asset: Some([ 0x96, 0x86, 0xaa, 0x36, 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, 0xab, 0xcf, 0xac, 0x88, 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, 0x07, 0x2d, 0x2d, 0x18, diff --git a/src/value.rs b/src/value.rs index d6e18ba23..02d845b4c 100644 --- a/src/value.rs +++ b/src/value.rs @@ -53,7 +53,7 @@ use pasta_curves::{ use rand::RngCore; use subtle::CtOption; -use crate::note::NoteType; +use crate::note::AssetId; use crate::{ constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES}, primitives::redpallas::{self, Binding}, @@ -325,7 +325,7 @@ impl ValueCommitment { /// /// [concretehomomorphiccommit]: https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit #[allow(non_snake_case)] - pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, note_type: NoteType) -> Self { + pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, asset: AssetId) -> Self { let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); let R = hasher(&VALUE_COMMITMENT_R_BYTES); let abs_value = u64::try_from(value.0.abs()).expect("value must be in valid range"); @@ -336,7 +336,7 @@ impl ValueCommitment { pallas::Scalar::from(abs_value) }; - let V_zsa = note_type.cv_base(); + let V_zsa = asset.cv_base(); ValueCommitment(V_zsa * value + R * rcv.0) } @@ -441,9 +441,9 @@ pub mod testing { #[cfg(test)] mod tests { - use crate::note::note_type::testing::{arb_note_type, native_note_type}; + use crate::note::asset_id::testing::{arb_asset_id, native_asset_id}; - use crate::note::NoteType; + use crate::note::AssetId; use proptest::prelude::*; use super::{ @@ -453,8 +453,8 @@ mod tests { use crate::primitives::redpallas; fn _bsk_consistent_with_bvk( - native_values: &[(ValueSum, ValueCommitTrapdoor, NoteType)], - arb_values: &[(ValueSum, ValueCommitTrapdoor, NoteType)], + native_values: &[(ValueSum, ValueCommitTrapdoor, AssetId)], + arb_values: &[(ValueSum, ValueCommitTrapdoor, AssetId)], neg_trapdoors: &[ValueCommitTrapdoor], ) { // for each arb value, create a negative value with a different trapdoor @@ -462,7 +462,7 @@ mod tests { .iter() .cloned() .zip(neg_trapdoors.iter().cloned()) - .map(|((value, _, note_type), rcv)| ((-value).unwrap(), rcv, note_type)) + .map(|((value, _, asset), rcv)| ((-value).unwrap(), rcv, asset)) .collect(); let native_value_balance = native_values @@ -481,12 +481,12 @@ mod tests { let bvk = (values .iter() - .map(|(value, rcv, note_type)| ValueCommitment::derive(*value, *rcv, *note_type)) + .map(|(value, rcv, asset)| ValueCommitment::derive(*value, *rcv, *asset)) .sum::() - ValueCommitment::derive( native_value_balance, ValueCommitTrapdoor::zero(), - NoteType::native(), + AssetId::native(), )) .into_bvk(); @@ -498,7 +498,7 @@ mod tests { fn bsk_consistent_with_bvk_native_only( native_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_note_type()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_id()), n_values) ) ), ) { @@ -512,12 +512,12 @@ mod tests { fn bsk_consistent_with_bvk( native_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_note_type()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_id()), n_values) ) ), (arb_values,neg_trapdoors) in (1usize..10).prop_flat_map(|n_values| (arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_note_type()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values) ), prop::collection::vec(arb_trapdoor(), n_values)) ), ) { diff --git a/tests/builder.rs b/tests/builder.rs index bf94fc2ee..312541ecf 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -1,5 +1,5 @@ use incrementalmerkletree::{bridgetree::BridgeTree, Hashable, Tree}; -use orchard::note::NoteType; +use orchard::note::AssetId; use orchard::{ builder::Builder, bundle::{Authorized, Flags}, @@ -68,7 +68,7 @@ fn bundle_chain() { None, recipient, NoteValue::from_raw(5000), - NoteType::native(), + AssetId::native(), None ), Ok(()) @@ -103,7 +103,7 @@ fn bundle_chain() { None, recipient, NoteValue::from_raw(5000), - NoteType::native(), + AssetId::native(), None ), Ok(()) diff --git a/tests/zsa.rs b/tests/zsa.rs index 6dfff6dc0..f8ae6d23c 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -6,14 +6,14 @@ use incrementalmerkletree::{Hashable, Tree}; use orchard::bundle::Authorized; use orchard::issuance::{verify_issue_bundle, IssueBundle, Signed, Unauthorized}; use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; -use orchard::note::{ExtractedNoteCommitment, NoteType}; +use orchard::note::{AssetId, ExtractedNoteCommitment}; use orchard::note_encryption::OrchardDomain; use orchard::tree::{MerkleHashOrchard, MerklePath}; use orchard::{ builder::Builder, bundle::Flags, circuit::{ProvingKey, VerifyingKey}, - keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, + keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey, PreparedIncomingViewingKey}, value::NoteValue, Address, Anchor, Bundle, Note, }; @@ -189,7 +189,7 @@ fn create_native_note(keys: &Keychain) -> Note { None, keys.recipient, NoteValue::from_raw(100), - NoteType::native(), + AssetId::native(), None ), Ok(()) @@ -205,7 +205,7 @@ fn create_native_note(keys: &Keychain) -> Note { .iter() .find_map(|action| { let domain = OrchardDomain::for_action(action); - try_note_decryption(&domain, &ivk, action) + try_note_decryption(&domain, &PreparedIncomingViewingKey::new(&ivk), action) }) .unwrap(); @@ -225,7 +225,7 @@ impl TestSpendInfo { struct TestOutputInfo { value: NoteValue, - note_type: NoteType, + asset: AssetId, } fn build_and_verify_bundle( @@ -247,7 +247,7 @@ fn build_and_verify_bundle( }); outputs.iter().for_each(|output| { assert_eq!( - builder.add_recipient(None, keys.recipient, output.value, output.note_type, None), + builder.add_recipient(None, keys.recipient, output.value, output.asset, None), Ok(()) ) }); @@ -289,7 +289,7 @@ fn zsa_issue_and_transfer() { vec![&zsa_spend_1], vec![TestOutputInfo { value: zsa_spend_1.note.value(), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }], anchor, 2, @@ -303,11 +303,11 @@ fn zsa_issue_and_transfer() { vec![ TestOutputInfo { value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }, TestOutputInfo { value: NoteValue::from_raw(delta), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }, ], anchor, @@ -322,7 +322,7 @@ fn zsa_issue_and_transfer() { value: NoteValue::from_raw( zsa_spend_1.note.value().inner() + zsa_spend_2.note.value().inner(), ), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }], anchor, 2, @@ -335,11 +335,11 @@ fn zsa_issue_and_transfer() { vec![ TestOutputInfo { value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }, TestOutputInfo { value: NoteValue::from_raw(zsa_spend_2.note.value().inner() + delta), - note_type: zsa_spend_2.note.note_type(), + asset: zsa_spend_2.note.asset(), }, ], anchor, @@ -353,11 +353,11 @@ fn zsa_issue_and_transfer() { vec![ TestOutputInfo { value: zsa_spend_1.note.value(), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }, TestOutputInfo { value: NoteValue::from_raw(100), - note_type: NoteType::native(), + asset: AssetId::native(), }, ], anchor, @@ -383,11 +383,11 @@ fn zsa_issue_and_transfer() { vec![ TestOutputInfo { value: zsa_spend_1.note.value(), - note_type: zsa_spend_1.note.note_type(), + asset: zsa_spend_1.note.asset(), }, TestOutputInfo { value: native_spend.note.value(), - note_type: NoteType::native(), + asset: AssetId::native(), }, ], native_anchor, @@ -413,11 +413,11 @@ fn zsa_issue_and_transfer() { vec![ TestOutputInfo { value: zsa_spend_t7_1.note.value(), - note_type: zsa_spend_t7_1.note.note_type(), + asset: zsa_spend_t7_1.note.asset(), }, TestOutputInfo { value: zsa_spend_t7_2.note.value(), - note_type: zsa_spend_t7_2.note.note_type(), + asset: zsa_spend_t7_2.note.asset(), }, ], anchor_t7, @@ -432,11 +432,11 @@ fn zsa_issue_and_transfer() { vec![ TestOutputInfo { value: NoteValue::from_raw(zsa_spend_t7_1.note.value().inner() + delta), - note_type: zsa_spend_t7_1.note.note_type(), + asset: zsa_spend_t7_1.note.asset(), }, TestOutputInfo { value: NoteValue::from_raw(zsa_spend_t7_2.note.value().inner() - delta), - note_type: zsa_spend_t7_2.note.note_type(), + asset: zsa_spend_t7_2.note.asset(), }, ], anchor_t7, From 9405f801cd95ad4193c098eea6b47de954198461 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Fri, 28 Oct 2022 10:46:02 +0300 Subject: [PATCH 11/92] verify_issue_bundle() cleanup (#25) * improved `verify_issue_bundle()` --- .github/workflows/bench.yml | 2 +- .github/workflows/ci.yml | 10 +++++----- .github/workflows/lints-stable.yml | 6 +++--- Cargo.toml | 2 +- README.md | 2 +- rust-toolchain | 2 +- src/issuance.rs | 26 +++++++++++++------------- src/note.rs | 8 +++++++- tests/zsa.rs | 2 +- 9 files changed, 33 insertions(+), 27 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index e8e263848..21f631759 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 override: true - name: Run benchmark run: cargo bench -- --output-format bencher | tee output.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7b900029..101cee1ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 override: true - name: Run tests uses: actions-rs/cargo@v1 @@ -30,7 +30,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 override: true # Build benchmarks to prevent bitrot - name: Build benchmarks @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 override: true - name: Setup mdBook uses: peaceiris/actions-mdbook@v1 @@ -90,7 +90,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 override: true - name: cargo fetch uses: actions-rs/cargo@v1 @@ -113,7 +113,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 diff --git a/.github/workflows/lints-stable.yml b/.github/workflows/lints-stable.yml index 242041e89..88a727090 100644 --- a/.github/workflows/lints-stable.yml +++ b/.github/workflows/lints-stable.yml @@ -5,19 +5,19 @@ on: pull_request jobs: clippy: - name: Clippy (1.56.1) + name: Clippy (1.61) timeout-minutes: 30 runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.56.1 + toolchain: 1.61 components: clippy override: true - name: Run Clippy uses: actions-rs/clippy-check@v1 with: - name: Clippy (1.56.1) + name: Clippy (1.61) token: ${{ secrets.GITHUB_TOKEN }} args: --all-features --all-targets -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index 813b0aee3..ed956ef27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "Kris Nuttycombe ", ] edition = "2021" -rust-version = "1.56.1" +rust-version = "1.61" description = "The Orchard shielded transaction protocol" license-file = "LICENSE-BOSL" repository = "https://github.com/zcash/orchard" diff --git a/README.md b/README.md index 12b74651b..4d4ac85eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) # -Requires Rust 1.56.1+. +Requires Rust 1.61+. ## Documentation diff --git a/rust-toolchain b/rust-toolchain index 43c989b55..4213d88dc 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.56.1 +1.61 diff --git a/src/issuance.rs b/src/issuance.rs index 4fbcd8421..9f15d638f 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -335,32 +335,32 @@ impl IssueBundle { /// Validation for Orchard IssueBundles /// /// A set of previously finalized asset types must be provided. -/// In case of success, `finalized` will contain a set of the provided **and** the newly finalized `NoteType`s +/// In case of success, `finalized` will contain a set of the provided **and** the newly finalized `AssetId`s /// /// The following checks are performed: /// * For the `IssueBundle`: /// * the Signature on top of the provided `sighash` verifies correctly. /// * For each `IssueAction`: /// * Asset description size is collect. -/// * `NoteType` for the `IssueAction` has not been previously finalized. +/// * `AssetId` for the `IssueAction` has not been previously finalized. /// * For each `Note` inside an `IssueAction`: /// * All notes have the same, correct `NoteType`. pub fn verify_issue_bundle( bundle: &IssueBundle, sighash: [u8; 32], - finalized: &mut HashSet, // The current finalization set. + finalized: &mut HashSet, // The finalization set. ) -> Result<(), Error> { if let Err(e) = bundle.ik.verify(&sighash, &bundle.authorization.signature) { return Err(IssueBundleInvalidSignature(e)); }; - let currently_finalized: &mut HashSet = &mut HashSet::new(); + let s = &mut HashSet::::new(); - // Any IssueAction could have just one properly derived NoteType. - let res = bundle + // An IssueAction could have just one properly derived AssetId. + let newly_finalized = bundle .actions() .iter() - .try_fold(currently_finalized, |acc, action| { + .try_fold(s, |newly_finalized, action| { if !is_asset_desc_of_valid_size(action.asset_desc()) { return Err(WrongAssetDescSize); } @@ -368,21 +368,21 @@ pub fn verify_issue_bundle( // Fail if any note in the IssueAction has incorrect note type. let asset = action.are_note_asset_ids_derived_correctly(bundle.ik())?; - // Fail if the current asset was previously finalized. - if finalized.contains(&asset) || acc.contains(&asset) { + // Fail if the asset was previously finalized. + if finalized.contains(&asset) || newly_finalized.contains(&asset) { return Err(IssueActionPreviouslyFinalizedNoteType(asset)); } // Add to finalization set, if needed. if action.is_finalized() { - acc.insert(asset); + newly_finalized.insert(asset); } - // Proceed with the new asset finalization set. - Ok(acc) + // Proceed with the new finalization set. + Ok(newly_finalized) })?; - finalized.extend(res.iter()); + finalized.extend(newly_finalized.iter()); Ok(()) } diff --git a/src/note.rs b/src/note.rs index 3ac8560e1..d5a58a838 100644 --- a/src/note.rs +++ b/src/note.rs @@ -161,7 +161,13 @@ impl Note { mut rng: impl RngCore, ) -> Self { loop { - let note = Note::from_parts(recipient, value, asset, rho, RandomSeed::random(&mut rng, &rho)); + let note = Note::from_parts( + recipient, + value, + asset, + rho, + RandomSeed::random(&mut rng, &rho), + ); if note.is_some().into() { break note.unwrap(); } diff --git a/tests/zsa.rs b/tests/zsa.rs index f8ae6d23c..f65b18616 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -13,7 +13,7 @@ use orchard::{ builder::Builder, bundle::Flags, circuit::{ProvingKey, VerifyingKey}, - keys::{FullViewingKey, Scope, SpendAuthorizingKey, SpendingKey, PreparedIncomingViewingKey}, + keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, value::NoteValue, Address, Anchor, Bundle, Note, }; From d8f3563c1c6ae83ee44627557954313cebfdd796 Mon Sep 17 00:00:00 2001 From: Alexey Koren Date: Wed, 7 Dec 2022 16:19:51 +0100 Subject: [PATCH 12/92] ZSA burn functionality (#35) Added a method to add assets to burn to the Builder bvk computation now includes the burnt assets Added Tests for bsk/bvk consistency for burning Added E2E tests for assets burning --- .circleci/config.yml | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/ci.yml | 10 +-- .github/workflows/lints-stable.yml | 6 +- .gitignore | 1 - Cargo.toml | 2 +- rust-toolchain | 2 +- src/builder.rs | 58 ++++++++----- src/bundle.rs | 52 +++++++++-- src/value.rs | 76 ++++++++++------ tests/zsa.rs | 135 ++++++++++++++++++++--------- 11 files changed, 238 insertions(+), 108 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ba37a7890..9dead1280 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ jobs: # Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor docker: - - image: cimg/rust:1.59.0 + - image: cimg/rust:1.61.0 # Add steps to the job # See: https://circleci.com/docs/2.0/configuration-reference/#steps steps: diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 21f631759..ba1ceea59 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 override: true - name: Run benchmark run: cargo bench -- --output-format bencher | tee output.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 101cee1ec..66b8c4d3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 override: true - name: Run tests uses: actions-rs/cargo@v1 @@ -30,7 +30,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 override: true # Build benchmarks to prevent bitrot - name: Build benchmarks @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 override: true - name: Setup mdBook uses: peaceiris/actions-mdbook@v1 @@ -90,7 +90,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 override: true - name: cargo fetch uses: actions-rs/cargo@v1 @@ -113,7 +113,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 diff --git a/.github/workflows/lints-stable.yml b/.github/workflows/lints-stable.yml index 88a727090..a000ab449 100644 --- a/.github/workflows/lints-stable.yml +++ b/.github/workflows/lints-stable.yml @@ -5,19 +5,19 @@ on: pull_request jobs: clippy: - name: Clippy (1.61) + name: Clippy (1.61.0) timeout-minutes: 30 runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61 + toolchain: 1.61.0 components: clippy override: true - name: Run Clippy uses: actions-rs/clippy-check@v1 with: - name: Clippy (1.61) + name: Clippy (1.61.0) token: ${{ secrets.GITHUB_TOKEN }} args: --all-features --all-targets -- -D warnings diff --git a/.gitignore b/.gitignore index d7f36bd31..f4ca20140 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ Cargo.lock .vscode .idea action-circuit-layout.png -proptest-regressions/*.txt diff --git a/Cargo.toml b/Cargo.toml index ed956ef27..cb7508702 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "Kris Nuttycombe ", ] edition = "2021" -rust-version = "1.61" +rust-version = "1.61.0" description = "The Orchard shielded transaction protocol" license-file = "LICENSE-BOSL" repository = "https://github.com/zcash/orchard" diff --git a/rust-toolchain b/rust-toolchain index 4213d88dc..91951fd8a 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.61 +1.61.0 diff --git a/src/builder.rs b/src/builder.rs index 5c6147022..4229cbb28 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -251,6 +251,7 @@ impl ActionInfo { pub struct Builder { spends: Vec, recipients: Vec, + burn: HashMap, flags: Flags, anchor: Anchor, } @@ -261,6 +262,7 @@ impl Builder { Builder { spends: vec![], recipients: vec![], + burn: HashMap::new(), flags, anchor, } @@ -337,6 +339,17 @@ impl Builder { Ok(()) } + /// Add an instruction to burn a given amount of a specific asset. + pub fn add_burn(&mut self, asset: AssetId, value: NoteValue) -> Result<(), &'static str> { + if asset.is_native().into() { + return Err("Burning is only possible for non-native assets"); + } + let cur = *self.burn.get(&asset).unwrap_or(&ValueSum::zero()); + let sum = (cur + value).ok_or("Orchard ValueSum operation overflowed")?; + self.burn.insert(asset, sum); + Ok(()) + } + /// The net value of the bundle to be built. The value of all spends, /// minus the value of all outputs. /// @@ -366,7 +379,7 @@ impl Builder { /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. - pub fn build>( + pub fn build + Copy + Into>( self, mut rng: impl RngCore, ) -> Result, V>, Error> { @@ -419,16 +432,14 @@ impl Builder { let anchor = self.anchor; // Determine the value balance for this bundle, ensuring it is valid. - let value_balance = pre_actions + let native_value_balance: V = pre_actions .iter() + .filter(|action| action.spend.note.asset().is_native().into()) .fold(Some(ValueSum::zero()), |acc, action| { acc? + action.value_sum() }) - .ok_or(OverflowError)?; - - let result_value_balance: V = i64::try_from(value_balance) - .map_err(Error::ValueSum) - .and_then(|i| V::try_from(i).map_err(|_| Error::ValueSum(value::OverflowError)))?; + .ok_or(OverflowError)? + .into()?; // Compute the transaction binding signing key. let bsk = pre_actions @@ -441,26 +452,26 @@ impl Builder { let (actions, circuits): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); - // Verify that bsk and bvk are consistent. - let bvk = (actions.iter().map(|a| a.cv_net()).sum::() - - ValueCommitment::derive( - value_balance, - ValueCommitTrapdoor::zero(), - AssetId::native(), - )) - .into_bvk(); - assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); - - Ok(Bundle::from_parts( + let bundle = Bundle::from_parts( NonEmpty::from_vec(actions).unwrap(), flags, - result_value_balance, + native_value_balance, + self.burn + .into_iter() + .map(|(asset, value)| Ok((asset, value.into()?))) + .collect::>()?, anchor, InProgress { proof: Unproven { circuits }, sigs: Unauthorized { bsk }, }, - )) + ); + + assert_eq!( + redpallas::VerificationKey::from(&bundle.authorization().sigs.bsk), + bundle.binding_validating_key() + ); + Ok(bundle) } } @@ -785,7 +796,7 @@ pub mod testing { impl ArbitraryBundleInputs { /// Create a bundle from the set of arbitrary bundle inputs. - fn into_bundle>(mut self) -> Bundle { + fn into_bundle + Copy + Into>(mut self) -> Bundle { let fvk = FullViewingKey::from(&self.sk); let flags = Flags::from_parts(true, true); let mut builder = Builder::new(flags, self.anchor); @@ -866,14 +877,15 @@ pub mod testing { } /// Produce an arbitrary valid Orchard bundle using a random spending key. - pub fn arb_bundle + Debug>() -> impl Strategy> { + pub fn arb_bundle + Debug + Copy + Into>( + ) -> impl Strategy> { arb_spending_key() .prop_flat_map(arb_bundle_inputs) .prop_map(|inputs| inputs.into_bundle::()) } /// Produce an arbitrary valid Orchard bundle using a specified spending key. - pub fn arb_bundle_with_key + Debug>( + pub fn arb_bundle_with_key + Debug + Copy + Into>( k: SpendingKey, ) -> impl Strategy> { arb_bundle_inputs(k).prop_map(|inputs| inputs.into_bundle::()) diff --git a/src/bundle.rs b/src/bundle.rs index 6f7e0bce9..cbc66e796 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -140,6 +140,9 @@ pub struct Bundle { /// /// This is the sum of Orchard spends minus the sum of Orchard outputs. value_balance: V, + /// Assets intended for burning + /// TODO We need to add a consensus check to make sure that it is impossible to burn ZEC. + burn: Vec<(AssetId, V)>, /// The root of the Orchard commitment tree that this bundle commits to. anchor: Anchor, /// The authorization for this bundle. @@ -172,6 +175,7 @@ impl Bundle { actions: NonEmpty>, flags: Flags, value_balance: V, + burn: Vec<(AssetId, V)>, anchor: Anchor, authorization: T, ) -> Self { @@ -179,6 +183,7 @@ impl Bundle { actions, flags, value_balance, + burn, anchor, authorization, } @@ -214,8 +219,8 @@ impl Bundle { } /// Construct a new bundle by applying a transformation that might fail - /// to the value balance. - pub fn try_map_value_balance Result>( + /// to the value balance and balances of assets to burn. + pub fn try_map_value_balance Result>( self, f: F, ) -> Result, E> { @@ -223,6 +228,11 @@ impl Bundle { actions: self.actions, flags: self.flags, value_balance: f(self.value_balance)?, + burn: self + .burn + .into_iter() + .map(|(asset, value)| Ok((asset, f(value)?))) + .collect::, E>>()?, anchor: self.anchor, authorization: self.authorization, }) @@ -244,6 +254,7 @@ impl Bundle { value_balance: self.value_balance, anchor: self.anchor, authorization: step(context, authorization), + burn: self.burn, } } @@ -267,6 +278,7 @@ impl Bundle { value_balance: self.value_balance, anchor: self.anchor, authorization: step(context, authorization)?, + burn: self.burn, }) } @@ -386,7 +398,19 @@ impl> Bundle { ValueSum::from_raw(self.value_balance.into()), ValueCommitTrapdoor::zero(), AssetId::native(), - )) + ) + - self + .burn + .clone() + .into_iter() + .map(|(asset, value)| { + ValueCommitment::derive( + ValueSum::from_raw(value.into()), + ValueCommitTrapdoor::zero(), + asset, + ) + }) + .sum::()) .into_bvk() } } @@ -503,6 +527,9 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; pub use crate::action::testing::{arb_action, arb_unauthorized_action}; + use crate::note::asset_id::testing::zsa_asset_id; + use crate::note::AssetId; + use crate::value::testing::arb_value_sum; /// Marker for an unauthorized bundle with no proofs or signatures. #[derive(Debug)] @@ -562,6 +589,13 @@ pub mod testing { }) } + prop_compose! { + /// Create an arbitrary vector of assets to burn. + pub fn arb_asset_to_burn()(asset_id in zsa_asset_id(), value in arb_value_sum()) -> (AssetId, ValueSum) { + (asset_id, value) + } + } + prop_compose! { /// Create an arbitrary set of flags. pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY) -> Flags { @@ -589,7 +623,8 @@ pub mod testing { ( acts in vec(arb_unauthorized_action_n(n_actions, flags), n_actions), anchor in arb_base().prop_map(Anchor::from), - flags in Just(flags) + flags in Just(flags), + burn in vec(arb_asset_to_burn(), 1usize..10) ) -> Bundle { let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); @@ -597,8 +632,9 @@ pub mod testing { NonEmpty::from_vec(actions).unwrap(), flags, balances.into_iter().sum::>().unwrap(), + burn, anchor, - Unauthorized + Unauthorized, ) } } @@ -618,7 +654,8 @@ pub mod testing { rng_seed in prop::array::uniform32(prop::num::u8::ANY), fake_proof in vec(prop::num::u8::ANY, 1973), fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - flags in Just(flags) + flags in Just(flags), + burn in vec(arb_asset_to_burn(), 1usize..10) ) -> Bundle { let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); let rng = StdRng::from_seed(rng_seed); @@ -627,11 +664,12 @@ pub mod testing { NonEmpty::from_vec(actions).unwrap(), flags, balances.into_iter().sum::>().unwrap(), + burn, anchor, Authorized { proof: Proof::new(fake_proof), binding_signature: sk.sign(rng, &fake_sighash), - } + }, ) } } diff --git a/src/value.rs b/src/value.rs index 02d845b4c..dd3a5546d 100644 --- a/src/value.rs +++ b/src/value.rs @@ -53,6 +53,7 @@ use pasta_curves::{ use rand::RngCore; use subtle::CtOption; +use crate::builder::Error; use crate::note::AssetId; use crate::{ constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES}, @@ -129,6 +130,12 @@ impl From<&NoteValue> for Assigned { } } +impl From for i128 { + fn from(value: NoteValue) -> Self { + value.0 as i128 + } +} + impl Sub for NoteValue { type Output = ValueSum; @@ -181,15 +188,21 @@ impl ValueSum { sign, ) } + + pub(crate) fn into>(self) -> Result { + i64::try_from(self) + .map_err(Error::ValueSum) + .and_then(|i| V::try_from(i).map_err(|_| Error::ValueSum(OverflowError))) + } } -impl Add for ValueSum { +impl> Add for ValueSum { type Output = Option; #[allow(clippy::suspicious_arithmetic_impl)] - fn add(self, rhs: Self) -> Self::Output { + fn add(self, rhs: T) -> Self::Output { self.0 - .checked_add(rhs.0) + .checked_add(rhs.into()) .filter(|v| VALUE_SUM_RANGE.contains(v)) .map(ValueSum) } @@ -227,6 +240,12 @@ impl TryFrom for i64 { } } +impl From for i128 { + fn from(value: ValueSum) -> Self { + value.0 + } +} + /// The blinding factor for a [`ValueCommitment`]. #[derive(Clone, Copy, Debug)] pub struct ValueCommitTrapdoor(pallas::Scalar); @@ -452,10 +471,11 @@ mod tests { }; use crate::primitives::redpallas; - fn _bsk_consistent_with_bvk( + fn check_binding_signature( native_values: &[(ValueSum, ValueCommitTrapdoor, AssetId)], arb_values: &[(ValueSum, ValueCommitTrapdoor, AssetId)], neg_trapdoors: &[ValueCommitTrapdoor], + arb_values_to_burn: &[(ValueSum, ValueCommitTrapdoor, AssetId)], ) { // for each arb value, create a negative value with a different trapdoor let neg_arb_values: Vec<_> = arb_values @@ -471,7 +491,13 @@ mod tests { .sum::>() .expect("we generate values that won't overflow"); - let values = [native_values, arb_values, &neg_arb_values].concat(); + let values = [ + native_values, + arb_values, + &neg_arb_values, + arb_values_to_burn, + ] + .concat(); let bsk = values .iter() @@ -480,14 +506,20 @@ mod tests { .into_bsk(); let bvk = (values - .iter() - .map(|(value, rcv, asset)| ValueCommitment::derive(*value, *rcv, *asset)) + .into_iter() + .map(|(value, rcv, asset)| ValueCommitment::derive(value, rcv, asset)) .sum::() - ValueCommitment::derive( native_value_balance, ValueCommitTrapdoor::zero(), AssetId::native(), - )) + ) + - arb_values_to_burn + .iter() + .map(|(value, _, asset)| { + ValueCommitment::derive(*value, ValueCommitTrapdoor::zero(), *asset) + }) + .sum::()) .into_bvk(); assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); @@ -495,34 +527,26 @@ mod tests { proptest! { #[test] - fn bsk_consistent_with_bvk_native_only( - native_values in (1usize..10).prop_flat_map(|n_values| - arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_id()), n_values) - ) - ), - ) { - // Test with native note type (zec) only - _bsk_consistent_with_bvk(&native_values, &[], &[]); - } - } - - proptest! { - #[test] - fn bsk_consistent_with_bvk( + fn bsk_consistent_with_bvk_native_with_zsa_transfer_and_burning( native_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_id()), n_values) ) ), - (arb_values,neg_trapdoors) in (1usize..10).prop_flat_map(|n_values| + (asset_values, neg_trapdoors) in (1usize..10).prop_flat_map(|n_values| (arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values) ), prop::collection::vec(arb_trapdoor(), n_values)) ), + burn_values in (1usize..10).prop_flat_map(|n_values| + arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64) + .prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values)) + ) ) { - // Test with native note type (zec) - _bsk_consistent_with_bvk(&native_values, &arb_values, &neg_trapdoors); + check_binding_signature(&native_values, &[], &[], &[]); + check_binding_signature(&native_values, &[], &[], &burn_values); + check_binding_signature(&native_values, &asset_values, &neg_trapdoors, &[]); + check_binding_signature(&native_values, &asset_values, &neg_trapdoors, &burn_values); } } } diff --git a/tests/zsa.rs b/tests/zsa.rs index f65b18616..9aad802d5 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -231,32 +231,31 @@ struct TestOutputInfo { fn build_and_verify_bundle( spends: Vec<&TestSpendInfo>, outputs: Vec, + assets_to_burn: Vec<(AssetId, NoteValue)>, anchor: Anchor, expected_num_actions: usize, keys: &Keychain, -) { +) -> Result<(), &'static str> { let rng = OsRng; let shielded_bundle: Bundle<_, i64> = { let mut builder = Builder::new(Flags::from_parts(true, true), anchor); - spends.iter().for_each(|spend| { - assert_eq!( - builder.add_spend(keys.fvk().clone(), spend.note, spend.merkle_path().clone()), - Ok(()) - ); - }); - outputs.iter().for_each(|output| { - assert_eq!( - builder.add_recipient(None, keys.recipient, output.value, output.asset, None), - Ok(()) - ) - }); + spends.iter().try_for_each(|spend| { + builder.add_spend(keys.fvk().clone(), spend.note, spend.merkle_path().clone()) + })?; + outputs.iter().try_for_each(|output| { + builder.add_recipient(None, keys.recipient, output.value, output.asset, None) + })?; + assets_to_burn + .into_iter() + .try_for_each(|(asset, value)| builder.add_burn(asset, value))?; build_and_sign_bundle(builder, rng, keys.pk(), keys.sk()) }; // Verify the shielded bundle, currently without the proof. verify_bundle(&shielded_bundle, &keys.vk, false); assert_eq!(shielded_bundle.actions().len(), expected_num_actions); + Ok(()) } /// Issue several ZSA and native notes and spend them in different combinations, e.g. split and join @@ -268,20 +267,32 @@ fn zsa_issue_and_transfer() { let asset_descr = "zsa_asset"; // Prepare ZSA - let (zsa_note1, zsa_note2) = issue_zsa_notes(asset_descr, &keys); + let (zsa_note_1, zsa_note_2) = issue_zsa_notes(asset_descr, &keys); let (merkle_path1, merkle_path2, anchor) = - build_merkle_path_with_two_leaves(&zsa_note1, &zsa_note2); + build_merkle_path_with_two_leaves(&zsa_note_1, &zsa_note_2); let zsa_spend_1 = TestSpendInfo { - note: zsa_note1, + note: zsa_note_1, merkle_path: merkle_path1, }; let zsa_spend_2 = TestSpendInfo { - note: zsa_note2, + note: zsa_note_2, merkle_path: merkle_path2, }; + let native_note = create_native_note(&keys); + let (native_merkle_path_1, native_merkle_path_2, native_anchor) = + build_merkle_path_with_two_leaves(&native_note, &zsa_note_1); + let native_spend: TestSpendInfo = TestSpendInfo { + note: native_note, + merkle_path: native_merkle_path_1, + }; + let zsa_spend_with_native: TestSpendInfo = TestSpendInfo { + note: zsa_note_1, + merkle_path: native_merkle_path_2, + }; + // --------------------------- Tests ----------------------------------------- // 1. Spend single ZSA note @@ -291,10 +302,12 @@ fn zsa_issue_and_transfer() { value: zsa_spend_1.note.value(), asset: zsa_spend_1.note.asset(), }], + vec![], anchor, 2, &keys, - ); + ) + .unwrap(); // 2. Split single ZSA note into 2 notes let delta = 2; // arbitrary number for value manipulation @@ -310,10 +323,12 @@ fn zsa_issue_and_transfer() { asset: zsa_spend_1.note.asset(), }, ], + vec![], anchor, 2, &keys, - ); + ) + .unwrap(); // 3. Join 2 ZSA notes into a single note build_and_verify_bundle( @@ -324,10 +339,12 @@ fn zsa_issue_and_transfer() { ), asset: zsa_spend_1.note.asset(), }], + vec![], anchor, 2, &keys, - ); + ) + .unwrap(); // 4. Take 2 ZSA notes and send them as 2 notes with different denomination build_and_verify_bundle( @@ -342,10 +359,12 @@ fn zsa_issue_and_transfer() { asset: zsa_spend_2.note.asset(), }, ], + vec![], anchor, 2, &keys, - ); + ) + .unwrap(); // 5. Spend single ZSA note, mixed with native note (shielding) build_and_verify_bundle( @@ -360,24 +379,14 @@ fn zsa_issue_and_transfer() { asset: AssetId::native(), }, ], + vec![], anchor, 4, &keys, - ); + ) + .unwrap(); // 6. Spend single ZSA note, mixed with native note (shielded to shielded) - let native_note = create_native_note(&keys); - let (native_merkle_path1, native_merkle_path2, native_anchor) = - build_merkle_path_with_two_leaves(&native_note, &zsa_note1); - let native_spend: TestSpendInfo = TestSpendInfo { - note: native_note, - merkle_path: native_merkle_path1, - }; - let zsa_spend_with_native: TestSpendInfo = TestSpendInfo { - note: zsa_note1, - merkle_path: native_merkle_path2, - }; - build_and_verify_bundle( vec![&zsa_spend_with_native, &native_spend], vec![ @@ -390,21 +399,23 @@ fn zsa_issue_and_transfer() { asset: AssetId::native(), }, ], + vec![], native_anchor, 4, &keys, - ); + ) + .unwrap(); // 7. Spend ZSA notes of different asset types let (zsa_note_t7, _) = issue_zsa_notes("zsa_asset2", &keys); let (merkle_path_t7_1, merkle_path_t7_2, anchor_t7) = - build_merkle_path_with_two_leaves(&zsa_note_t7, &zsa_note2); + build_merkle_path_with_two_leaves(&zsa_note_t7, &zsa_note_2); let zsa_spend_t7_1: TestSpendInfo = TestSpendInfo { note: zsa_note_t7, merkle_path: merkle_path_t7_1, }; let zsa_spend_t7_2: TestSpendInfo = TestSpendInfo { - note: zsa_note2, + note: zsa_note_2, merkle_path: merkle_path_t7_2, }; @@ -420,10 +431,12 @@ fn zsa_issue_and_transfer() { asset: zsa_spend_t7_2.note.asset(), }, ], + vec![], anchor_t7, 4, &keys, - ); + ) + .unwrap(); // 8. Same but wrong denomination let result = std::panic::catch_unwind(|| { @@ -439,10 +452,54 @@ fn zsa_issue_and_transfer() { asset: zsa_spend_t7_2.note.asset(), }, ], + vec![], anchor_t7, 4, &keys, - ); + ) + .unwrap(); }); assert!(result.is_err()); + + // 9. Burn ZSA assets + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![], + vec![(zsa_spend_1.note.asset(), zsa_spend_1.note.value())], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 10. Burn a partial amount of the ZSA assets + let value_to_burn = 3; + let value_to_transfer = zsa_spend_1.note.value().inner() - value_to_burn; + + build_and_verify_bundle( + vec![&zsa_spend_1], + vec![TestOutputInfo { + value: NoteValue::from_raw(value_to_transfer), + asset: zsa_spend_1.note.asset(), + }], + vec![(zsa_spend_1.note.asset(), NoteValue::from_raw(value_to_burn))], + anchor, + 2, + &keys, + ) + .unwrap(); + + // 11. Try to burn native asset - should fail + let result = build_and_verify_bundle( + vec![&native_spend], + vec![], + vec![(AssetId::native(), native_spend.note.value())], + native_anchor, + 2, + &keys, + ); + match result { + Ok(_) => panic!("Test should fail"), + Err(error) => assert_eq!(error, "Burning is only possible for non-native assets"), + } } From 5a50fb8d11361d3f7d1f3b2f6c0a468f88c0db49 Mon Sep 17 00:00:00 2001 From: Alexey Koren Date: Sun, 18 Dec 2022 13:53:27 +0100 Subject: [PATCH 13/92] Create dummy spend in empty builder by default (#36) --- src/builder.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 4229cbb28..9dfaa9efb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -387,7 +387,7 @@ impl Builder { // Pair up the spends and recipients, extending with dummy values as necessary. for (asset, (mut spends, mut recipients)) in - partition_by_asset(&self.spends, &self.recipients) + partition_by_asset(&self.spends, &self.recipients, &mut rng) { let num_spends = spends.len(); let num_recipients = recipients.len(); @@ -475,10 +475,12 @@ impl Builder { } } -/// partition a list of spends and recipients by note types. +/// Partition a list of spends and recipients by note types. +/// Method creates single dummy ZEC note if spends and recipients are both empty. fn partition_by_asset( spends: &[SpendInfo], recipients: &[RecipientInfo], + rng: &mut impl RngCore, ) -> HashMap, Vec)> { let mut hm = HashMap::new(); @@ -496,6 +498,11 @@ fn partition_by_asset( .push(r.clone()) } + if hm.is_empty() { + let dummy_spend = SpendInfo::dummy(AssetId::native(), rng); + hm.insert(dummy_spend.note.asset(), (vec![dummy_spend], vec![])); + } + hm } From efbfc197a972ba799adc6fff19dbdd415270fcc6 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 20 Dec 2022 15:49:49 +0100 Subject: [PATCH 14/92] AssetID test vectors (#34) --- src/note/asset_id.rs | 17 + src/test_vectors.rs | 1 + src/test_vectors/asset_id.rs | 1032 +++++++++++++++++++++++++++ src/test_vectors/note_encryption.rs | 240 +++---- 4 files changed, 1170 insertions(+), 120 deletions(-) create mode 100644 src/test_vectors/asset_id.rs diff --git a/src/note/asset_id.rs b/src/note/asset_id.rs index 6d9466e05..074e59364 100644 --- a/src/note/asset_id.rs +++ b/src/note/asset_id.rs @@ -129,4 +129,21 @@ pub mod testing { AssetId::derive(&IssuanceValidatingKey::from(&isk), &str) } } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::asset_id::test_vectors(); + + for tv in test_vectors { + let description = std::str::from_utf8(&tv.description).unwrap(); + + let calculated_asset_id = AssetId::derive( + &IssuanceValidatingKey::from_bytes(&tv.key).unwrap(), + description, + ); + let test_vector_asset_id = AssetId::from_bytes(&tv.asset_id).unwrap(); + + assert_eq!(calculated_asset_id, test_vector_asset_id); + } + } } diff --git a/src/test_vectors.rs b/src/test_vectors.rs index 042f3b913..b70b56e56 100644 --- a/src/test_vectors.rs +++ b/src/test_vectors.rs @@ -1,3 +1,4 @@ +pub(crate) mod asset_id; pub(crate) mod commitment_tree; pub(crate) mod keys; pub(crate) mod merkle_path; diff --git a/src/test_vectors/asset_id.rs b/src/test_vectors/asset_id.rs new file mode 100644 index 000000000..c50c0f8f5 --- /dev/null +++ b/src/test_vectors/asset_id.rs @@ -0,0 +1,1032 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_asset_id) + +pub(crate) struct TestVector { + pub(crate) key: [u8; 32], + pub(crate) description: [u8; 512], + pub(crate) asset_id: [u8; 32], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + key: [ + 0x85, 0xc8, 0xb5, 0xcd, 0x1a, 0xc3, 0xec, 0x3a, 0xd7, 0x09, 0x21, 0x32, 0xf9, 0x7f, + 0x01, 0x78, 0xb0, 0x75, 0xc8, 0x1a, 0x13, 0x9f, 0xd4, 0x60, 0xbb, 0xe0, 0xdf, 0xcd, + 0x75, 0x51, 0x47, 0x24, + ], + description: [ + 0xc5, 0xb3, 0xc8, 0xbe, 0xc8, 0x8a, 0xc8, 0x98, 0xcd, 0xbb, 0xc2, 0xb7, 0xc2, 0xa3, + 0xc9, 0x8f, 0xc5, 0x94, 0xc2, 0xb5, 0xc8, 0x9d, 0x21, 0xc7, 0xbc, 0xc3, 0xb6, 0xc5, + 0xa5, 0xc7, 0xae, 0xc4, 0x9c, 0xc6, 0xa4, 0xc3, 0x81, 0xe2, 0xb1, 0xa5, 0xc6, 0xb6, + 0xc8, 0xb6, 0xc8, 0x88, 0xc3, 0x8c, 0xc6, 0x8e, 0x5d, 0x32, 0xc4, 0x9a, 0xc9, 0x84, + 0xc6, 0xbf, 0xc7, 0x9b, 0xc8, 0x99, 0xc7, 0x9d, 0xc8, 0xbc, 0xcd, 0xb2, 0xc4, 0x9e, + 0xc5, 0xa1, 0xc7, 0xa9, 0xc6, 0xbb, 0xc3, 0x80, 0xc8, 0xba, 0xc3, 0xa1, 0xc4, 0x84, + 0x5f, 0xc7, 0xaa, 0xc5, 0xad, 0xc3, 0x80, 0xc6, 0xaf, 0xc3, 0x85, 0xc6, 0xb1, 0xc7, + 0xbf, 0xc7, 0x93, 0xcd, 0xbc, 0xc3, 0xad, 0xc4, 0x94, 0xc5, 0xad, 0xc3, 0xb6, 0xc3, + 0xa4, 0xc7, 0x9e, 0xc7, 0x81, 0x50, 0xc3, 0xb5, 0xc7, 0x86, 0xcd, 0xbd, 0xe1, 0x9b, + 0x90, 0x23, 0xc6, 0x91, 0xc7, 0x85, 0xc6, 0x8a, 0xc6, 0x9a, 0xc7, 0x88, 0x4e, 0xe1, + 0x9b, 0x9f, 0xe1, 0x9b, 0x93, 0xe1, 0x9a, 0xaf, 0xc6, 0xa1, 0xc8, 0xb1, 0xc7, 0x8d, + 0xc5, 0x93, 0xc8, 0xa0, 0xc7, 0x86, 0x4e, 0xc6, 0xb4, 0xc3, 0x80, 0xce, 0x88, 0x77, + 0xe1, 0x9b, 0xa4, 0xc2, 0xaf, 0xc5, 0x91, 0xc7, 0xa9, 0xc8, 0x83, 0x4d, 0xc8, 0x8b, + 0x6b, 0xc7, 0x9b, 0xc7, 0x82, 0x57, 0xe2, 0xb1, 0xb3, 0xc5, 0x98, 0xc3, 0xb2, 0x61, + 0xc5, 0x9b, 0xc3, 0xbe, 0x3f, 0xc5, 0xb5, 0xc3, 0x88, 0x31, 0xc7, 0xb7, 0xc3, 0xa0, + 0xc5, 0xa2, 0x77, 0xc3, 0x94, 0xc7, 0xa7, 0xc3, 0xa4, 0x6c, 0xe1, 0x9b, 0x97, 0xe1, + 0x9b, 0x81, 0xc2, 0xa5, 0xc8, 0x99, 0xc3, 0xa6, 0xc4, 0x9f, 0xc5, 0x89, 0xc8, 0xa2, + 0xc4, 0xb3, 0xc5, 0x9a, 0xc6, 0x90, 0x48, 0xc3, 0x80, 0xc6, 0xb6, 0xc5, 0x92, 0xe1, + 0x9b, 0xa8, 0xc2, 0xa3, 0xc7, 0xba, 0xc2, 0xa2, 0xc8, 0x87, 0xc3, 0xb1, 0xc7, 0xbb, + 0x6d, 0xc8, 0xa2, 0xc7, 0xa2, 0xc6, 0xaf, 0xe1, 0x9b, 0xa3, 0xc3, 0x86, 0xe1, 0x9b, + 0xa1, 0x60, 0x37, 0xc7, 0x91, 0x56, 0xc5, 0x95, 0xc4, 0xbc, 0xc5, 0xbe, 0xc4, 0x97, + 0x5a, 0x31, 0xc5, 0x89, 0xc9, 0x83, 0xc8, 0xb4, 0xc6, 0xa4, 0xc7, 0xb5, 0xe1, 0x9b, + 0x9e, 0xc3, 0xab, 0xcd, 0xb0, 0x56, 0xc7, 0x86, 0xc6, 0x99, 0xe1, 0x9b, 0x96, 0xc7, + 0x90, 0xe1, 0x9b, 0x95, 0xc4, 0xaf, 0xc8, 0xac, 0xe2, 0xb1, 0xa7, 0xc3, 0x91, 0xc9, + 0x8b, 0xc6, 0xad, 0xc5, 0x87, 0x5f, 0xe2, 0xb1, 0xb4, 0xc2, 0xb4, 0xc9, 0x8b, 0xc8, + 0x9b, 0xc7, 0x80, 0xc6, 0xbb, 0xc2, 0xbd, 0xc8, 0xbb, 0xc4, 0xa2, 0x48, 0xc7, 0xa1, + 0xc2, 0xa4, 0xc4, 0x86, 0xe2, 0xb1, 0xa8, 0xc6, 0x87, 0xc7, 0xb9, 0xe1, 0x9a, 0xa0, + 0xc6, 0xb0, 0xc6, 0xad, 0xc9, 0x83, 0xc7, 0x99, 0xc4, 0x9e, 0xe1, 0x9a, 0xbf, 0xc7, + 0xa6, 0x67, 0xc8, 0x95, 0xc3, 0x83, 0xe1, 0x9a, 0xa2, 0xce, 0x8a, 0x57, 0xc3, 0xa3, + 0xc7, 0x81, 0xc6, 0xab, 0xc6, 0xbe, 0x7b, 0xc3, 0x9e, 0xc7, 0x88, 0xe1, 0x9a, 0xae, + 0xc3, 0x94, 0xc6, 0x8e, 0xce, 0x88, 0xe1, 0x9b, 0x96, 0xc3, 0x85, 0xc4, 0xa9, 0xe2, + 0xb1, 0xb4, 0xc7, 0xab, 0xe1, 0x9b, 0x8e, 0xc4, 0xa9, 0xe2, 0xb1, 0xa1, 0xe2, 0xb1, + 0xa0, 0xc7, 0x96, 0xc3, 0xbe, 0xe1, 0x9a, 0xa2, 0xc4, 0xba, 0xe1, 0x9b, 0x95, 0xe2, + 0xb1, 0xaa, 0xc5, 0x88, 0xc6, 0xa2, 0xe1, 0x9b, 0x99, 0xc2, 0xaa, 0xe1, 0x9a, 0xa7, + 0xc6, 0x98, 0x72, 0xe1, 0x9b, 0x88, 0xc6, 0xa0, 0xc5, 0x8f, 0xc2, 0xa6, 0xc2, 0xb8, + 0xc5, 0x8f, 0xc6, 0x9f, 0xc7, 0xb0, 0xc4, 0xb8, 0xc9, 0x8f, 0xc7, 0xac, 0x6e, 0x44, + 0xe1, 0x9a, 0xba, 0xc3, 0xb3, 0xc3, 0x99, 0x5a, + ], + asset_id: [ + 0x29, 0xb8, 0x07, 0x86, 0xde, 0xf6, 0x7e, 0xee, 0xe1, 0xfa, 0x1e, 0xb2, 0x4f, 0xd9, + 0xad, 0xf0, 0xab, 0xba, 0xe1, 0x70, 0x57, 0xeb, 0x4a, 0x04, 0x11, 0x13, 0xa4, 0x4e, + 0x9a, 0x1c, 0x92, 0x33, + ], + }, + TestVector { + key: [ + 0x43, 0x10, 0x6d, 0xe9, 0xa7, 0xec, 0x54, 0xdd, 0x36, 0xdf, 0xa7, 0x0b, 0xdb, 0xd9, + 0x07, 0x2d, 0xbd, 0xda, 0xb5, 0xe0, 0x66, 0xaa, 0xef, 0xfc, 0xf9, 0xbb, 0xa3, 0x20, + 0xd4, 0xff, 0xf7, 0x12, + ], + description: [ + 0x76, 0xc4, 0xb6, 0xc5, 0xb8, 0xe1, 0x9b, 0xa4, 0xc4, 0x9f, 0xc7, 0xb9, 0xc2, 0xb8, + 0xc7, 0x95, 0xc6, 0xbf, 0xc9, 0x87, 0xc5, 0xb3, 0xe1, 0x9b, 0xa1, 0xc5, 0xa9, 0xc3, + 0xa2, 0xc7, 0xb7, 0x77, 0xc6, 0xbf, 0xc6, 0xb5, 0xe1, 0x9a, 0xb6, 0xc3, 0xa2, 0xc5, + 0xbf, 0xe1, 0x9b, 0x82, 0xc4, 0x9c, 0xc6, 0xab, 0xc4, 0xbc, 0xc5, 0xb8, 0xe1, 0x9a, + 0xb6, 0xc7, 0xb7, 0xc2, 0xbe, 0xc7, 0x8e, 0xcd, 0xbd, 0xe1, 0x9a, 0xb4, 0xc8, 0x98, + 0xc8, 0x93, 0xc5, 0xb9, 0xc7, 0xb8, 0xc4, 0x8d, 0xe1, 0x9b, 0x86, 0xc7, 0x85, 0xc7, + 0x8e, 0xc4, 0x9f, 0xc5, 0xa3, 0x47, 0x7a, 0xc6, 0xa3, 0x5e, 0xe1, 0x9a, 0xa7, 0x66, + 0xc8, 0x9a, 0x45, 0xc4, 0x94, 0xc9, 0x8e, 0xc7, 0x9b, 0xc8, 0xbf, 0xe1, 0x9a, 0xa4, + 0x2b, 0xc6, 0xad, 0xc3, 0x9c, 0xc5, 0xbf, 0xc3, 0x91, 0xe1, 0x9b, 0xaf, 0xc5, 0x94, + 0xe1, 0x9b, 0x8d, 0xc2, 0xbb, 0xc4, 0xab, 0xc3, 0x88, 0xc4, 0xac, 0xe1, 0x9b, 0x96, + 0xcd, 0xb7, 0xc3, 0x97, 0x2b, 0x3c, 0xe1, 0x9b, 0x99, 0xc7, 0x91, 0xe1, 0x9a, 0xa4, + 0xc4, 0x8e, 0xc7, 0xa7, 0xe2, 0xb1, 0xac, 0xc2, 0xbc, 0xc4, 0x82, 0xc3, 0x81, 0xc6, + 0xb8, 0xe1, 0x9b, 0xa8, 0xe1, 0x9b, 0x95, 0xc4, 0xa4, 0xe1, 0x9b, 0xaa, 0xe1, 0x9a, + 0xa0, 0xc5, 0xbe, 0xe1, 0x9b, 0x8a, 0x34, 0xc7, 0x82, 0x7d, 0xe1, 0x9a, 0xbe, 0xc4, + 0x83, 0xe1, 0x9a, 0xa5, 0xc5, 0x8d, 0x51, 0xc8, 0xa9, 0xc9, 0x81, 0xc7, 0xa9, 0xc4, + 0x8f, 0xe2, 0xb1, 0xa2, 0x58, 0xc3, 0x9d, 0xc6, 0x94, 0xce, 0x85, 0xc7, 0xbe, 0xc4, + 0x89, 0x3c, 0xc2, 0xa3, 0xc7, 0xaf, 0xc3, 0x9b, 0xc7, 0xae, 0xc8, 0x89, 0xc9, 0x88, + 0xc5, 0xa8, 0xe2, 0xb1, 0xa9, 0xc5, 0xa3, 0x67, 0xc6, 0xa8, 0xe1, 0x9a, 0xb3, 0xc7, + 0x95, 0xc5, 0xa9, 0xc5, 0xa0, 0xc5, 0x84, 0xe1, 0x9a, 0xbf, 0xc7, 0xb4, 0xc9, 0x8a, + 0xc4, 0xbc, 0xc5, 0xbb, 0xc7, 0x99, 0xc3, 0x8e, 0xe1, 0x9a, 0xb0, 0xc5, 0x87, 0xe2, + 0xb1, 0xb0, 0xe1, 0x9a, 0xab, 0xc4, 0x8f, 0xc5, 0xb8, 0xc5, 0x90, 0xc5, 0xbc, 0xc3, + 0x80, 0xc3, 0xbc, 0xc4, 0x8a, 0xc5, 0xbb, 0x64, 0x3e, 0xc2, 0xa7, 0xc6, 0xb3, 0xe2, + 0xb1, 0xb6, 0xc8, 0xa4, 0x72, 0x71, 0xe1, 0x9b, 0x92, 0x3c, 0xc4, 0x99, 0xe2, 0xb1, + 0xb5, 0xc7, 0x81, 0xc4, 0xbd, 0xc8, 0xa6, 0xc4, 0xa8, 0xe1, 0x9a, 0xa1, 0xc3, 0x85, + 0xc6, 0x8f, 0xc2, 0xb9, 0xc7, 0x9b, 0xc7, 0xa7, 0xe1, 0x9a, 0xb3, 0xc8, 0x99, 0xc7, + 0xb4, 0xe1, 0x9b, 0xa6, 0xc3, 0x94, 0xe1, 0x9b, 0x91, 0xc6, 0xb7, 0x31, 0xc7, 0xb2, + 0xc3, 0x9e, 0xc7, 0xad, 0xc3, 0xa4, 0xc4, 0x97, 0xcd, 0xb5, 0xe1, 0x9a, 0xac, 0x63, + 0xc7, 0x96, 0xe2, 0xb1, 0xa3, 0xc8, 0x86, 0xc4, 0x97, 0x37, 0xc5, 0xa9, 0xc2, 0xa5, + 0xc4, 0xbf, 0xc7, 0x85, 0xc2, 0xa4, 0xe1, 0x9a, 0xa6, 0xc5, 0xba, 0xc6, 0xb3, 0xc5, + 0xb5, 0x36, 0x4e, 0x6e, 0xc5, 0x90, 0xc3, 0x80, 0xc7, 0xbd, 0xc6, 0x88, 0xc3, 0xb4, + 0xe2, 0xb1, 0xa6, 0xc8, 0xa4, 0xc8, 0xb0, 0xe1, 0x9a, 0xa0, 0xc3, 0x84, 0xc8, 0x8b, + 0xcd, 0xbe, 0xc5, 0x80, 0xc8, 0x9e, 0xc3, 0x99, 0xc4, 0x8a, 0xc3, 0x83, 0x3e, 0x28, + 0x4a, 0xe1, 0x9b, 0x85, 0xce, 0x87, 0xc5, 0x82, 0xc8, 0xbb, 0xc8, 0x8d, 0xc4, 0x88, + 0xc6, 0x9e, 0xc6, 0x98, 0xc5, 0xbf, 0x45, 0xc7, 0xb2, 0xe1, 0x9a, 0xbb, 0xe1, 0x9b, + 0x9a, 0xc4, 0xb5, 0xc2, 0xae, 0xc9, 0x80, 0xc6, 0x88, 0xc3, 0x8c, 0xc8, 0xa5, 0xc2, + 0xb8, 0x35, 0xc7, 0xba, 0xc6, 0xac, 0x58, 0xc4, 0x97, 0x7e, 0xc7, 0x98, 0xc3, 0xbd, + 0xc2, 0xb9, 0xc8, 0x99, 0xe1, 0x9b, 0x8c, 0x5a, + ], + asset_id: [ + 0x35, 0x52, 0x83, 0x87, 0xd4, 0x4d, 0x74, 0x21, 0xa9, 0x78, 0xad, 0x56, 0xe5, 0x33, + 0xf3, 0x6e, 0x85, 0xec, 0xac, 0x44, 0x9f, 0x3b, 0x3f, 0x68, 0xe7, 0xff, 0x39, 0x7f, + 0xae, 0x24, 0x5a, 0x99, + ], + }, + TestVector { + key: [ + 0x6b, 0xfb, 0xe5, 0xc2, 0x42, 0x23, 0x94, 0xdc, 0x23, 0x76, 0xad, 0x10, 0x69, 0x3a, + 0xbc, 0x1b, 0xf4, 0xa1, 0x6e, 0x18, 0x56, 0x5e, 0xbe, 0x79, 0x84, 0x1b, 0x95, 0x13, + 0x45, 0x02, 0x53, 0x01, + ], + description: [ + 0xc7, 0x8e, 0x4f, 0xc2, 0xbb, 0x39, 0xc3, 0xa4, 0xc4, 0x94, 0xc5, 0xbb, 0xc5, 0xa6, + 0xc2, 0xab, 0xc2, 0xba, 0xc7, 0x9e, 0xc5, 0x88, 0xc8, 0x9c, 0x57, 0xc3, 0xbc, 0xe2, + 0xb1, 0xb7, 0xe1, 0x9a, 0xa9, 0x3a, 0xc3, 0x84, 0xc5, 0x9b, 0xc8, 0xb5, 0xc5, 0x80, + 0xc9, 0x81, 0xc7, 0xa7, 0xc5, 0x92, 0xc6, 0x9b, 0xc7, 0x86, 0xc8, 0xba, 0xc6, 0x88, + 0xc9, 0x85, 0xc3, 0xab, 0xc8, 0x94, 0xc8, 0x92, 0xc7, 0xa2, 0xc7, 0x82, 0xc4, 0x91, + 0x74, 0x62, 0xc5, 0x9b, 0x42, 0xc8, 0xbe, 0xc3, 0xa7, 0xc4, 0xb8, 0xc2, 0xaf, 0xc6, + 0x8d, 0x39, 0xc7, 0xb3, 0xc8, 0x97, 0xc8, 0x91, 0xc2, 0xbb, 0xc4, 0x87, 0xe1, 0x9b, + 0x8a, 0xc2, 0xa7, 0xc7, 0xb4, 0xc4, 0xbb, 0xc2, 0xb2, 0xc8, 0x9a, 0xe1, 0x9a, 0xa3, + 0xc3, 0x92, 0x36, 0xe1, 0x9b, 0x9d, 0xc7, 0x8f, 0xc8, 0x90, 0xc8, 0xb3, 0x36, 0x49, + 0xc4, 0x92, 0xe1, 0x9b, 0x84, 0xc6, 0x94, 0xc8, 0xba, 0xc9, 0x8c, 0xc7, 0x85, 0xc6, + 0x94, 0xc6, 0x87, 0xc6, 0xb6, 0xc4, 0xba, 0xc5, 0xb4, 0x51, 0xe1, 0x9a, 0xb7, 0xc3, + 0xbb, 0xcd, 0xbb, 0xc7, 0x89, 0xc3, 0xba, 0xc6, 0x93, 0xc2, 0xa7, 0xc3, 0xa1, 0xc3, + 0x8f, 0x7b, 0xc7, 0xa9, 0xc6, 0x92, 0x4b, 0xe1, 0x9b, 0xb0, 0xc8, 0xb3, 0xc5, 0x9a, + 0xe1, 0x9a, 0xb8, 0x71, 0xc9, 0x88, 0x4c, 0x25, 0xc7, 0x9b, 0xe1, 0x9b, 0x9a, 0xc2, + 0xb7, 0xc4, 0xb1, 0xe1, 0x9b, 0x97, 0x64, 0xe1, 0x9b, 0xa3, 0xc5, 0xb4, 0xe2, 0xb1, + 0xb1, 0xc9, 0x8d, 0x60, 0xe1, 0x9b, 0xa7, 0xe1, 0x9b, 0xa3, 0xc5, 0x84, 0xc4, 0x94, + 0xc7, 0xb8, 0xc8, 0x9c, 0x7c, 0xc3, 0xaa, 0x36, 0xc2, 0xa4, 0xc3, 0xa8, 0xe1, 0x9b, + 0x9f, 0xc3, 0x95, 0xc8, 0xa1, 0xc3, 0xac, 0xc4, 0x99, 0xc7, 0xa4, 0xc8, 0x93, 0xc8, + 0xb0, 0xc8, 0xa2, 0xc6, 0xb4, 0xc6, 0xa4, 0xe1, 0x9a, 0xaa, 0xc9, 0x85, 0xc2, 0xa5, + 0xcd, 0xbd, 0xc4, 0x97, 0xc4, 0xb2, 0xc4, 0xa7, 0xc4, 0x91, 0xc7, 0xbe, 0xe2, 0xb1, + 0xb4, 0xc9, 0x87, 0xc5, 0xab, 0xc7, 0x84, 0xc5, 0x9c, 0xe2, 0xb1, 0xaf, 0x55, 0xe2, + 0xb1, 0xaf, 0x23, 0xc4, 0x8e, 0xc5, 0xba, 0xc5, 0xaf, 0xc8, 0xaf, 0xe2, 0xb1, 0xa0, + 0x56, 0xc7, 0xb2, 0xc6, 0xb7, 0xc6, 0x90, 0xc6, 0x8d, 0x5e, 0xc6, 0xb5, 0xe1, 0x9a, + 0xb7, 0xc3, 0x89, 0xc8, 0x91, 0xc6, 0x9a, 0x74, 0x4f, 0xc4, 0xb1, 0xc7, 0xae, 0xc4, + 0xaa, 0xc3, 0xae, 0xc6, 0x9f, 0xc3, 0x99, 0xc8, 0x87, 0xe1, 0x9b, 0x9d, 0xe1, 0x9a, + 0xa4, 0xe1, 0x9b, 0xad, 0xc8, 0x93, 0xc6, 0x94, 0xc8, 0x82, 0xc7, 0xa8, 0xc6, 0xba, + 0xc6, 0x90, 0xc3, 0x88, 0xc6, 0xbb, 0xc9, 0x88, 0xc2, 0xa5, 0xc6, 0xad, 0xe1, 0x9a, + 0xb0, 0xc4, 0xbb, 0x47, 0x2e, 0xc6, 0x92, 0xc6, 0x8b, 0xe1, 0x9a, 0xaa, 0xc7, 0x80, + 0xe1, 0x9a, 0xa0, 0xc6, 0xab, 0xc3, 0xaf, 0xc8, 0xb9, 0xe1, 0x9b, 0x8f, 0xe1, 0x9a, + 0xb9, 0xc3, 0xa9, 0xc5, 0x8e, 0x68, 0xc8, 0xaa, 0xc4, 0xb6, 0xe2, 0xb1, 0xbd, 0xe1, + 0x9b, 0xad, 0xc7, 0xa6, 0xc5, 0x96, 0xc6, 0x82, 0xc7, 0x84, 0x3f, 0xc3, 0x97, 0xc4, + 0xbe, 0xc8, 0x91, 0xc6, 0xaa, 0x41, 0xc4, 0xa9, 0xc6, 0x80, 0xc2, 0xb7, 0xe2, 0xb1, + 0xb1, 0xc2, 0xa3, 0xc6, 0xa8, 0xe1, 0x9a, 0xa7, 0xc2, 0xaf, 0xc8, 0x83, 0xe1, 0x9b, + 0xac, 0x37, 0xc4, 0x8f, 0xc5, 0xb9, 0xe2, 0xb1, 0xb8, 0xc3, 0x8f, 0xc6, 0xb1, 0xc4, + 0xaa, 0xc5, 0x97, 0xe2, 0xb1, 0xab, 0xe1, 0x9b, 0x80, 0x58, 0xe1, 0x9b, 0x8b, 0xc8, + 0xb8, 0x2c, 0x21, 0x36, 0xc5, 0xb3, 0xc6, 0xaa, 0xc7, 0x8a, 0xc4, 0xa3, 0xc4, 0xb6, + 0xc5, 0xa4, 0xc5, 0x92, 0xe1, 0x9a, 0xbf, 0x5a, + ], + asset_id: [ + 0xf5, 0x4b, 0x0c, 0x9b, 0xad, 0x5a, 0x85, 0x26, 0x2b, 0x8a, 0x3b, 0xa4, 0x13, 0x6a, + 0x5b, 0x4c, 0xf3, 0x23, 0x85, 0xca, 0x49, 0x2f, 0x09, 0x4a, 0x42, 0xb2, 0xf6, 0xad, + 0x65, 0xc1, 0x07, 0x33, + ], + }, + TestVector { + key: [ + 0xab, 0x90, 0x15, 0x62, 0x52, 0x72, 0xe1, 0xe7, 0xba, 0x69, 0x0a, 0xe0, 0x09, 0xa9, + 0x92, 0xe4, 0x9d, 0xe1, 0x9f, 0x33, 0xfc, 0xde, 0xb9, 0xf1, 0x71, 0xab, 0x1a, 0xaf, + 0x28, 0x88, 0xc6, 0x0e, + ], + description: [ + 0xce, 0x88, 0xcd, 0xb5, 0xc6, 0x9f, 0xc6, 0xa5, 0xc8, 0x9e, 0xc7, 0xb2, 0xc7, 0xbc, + 0x7d, 0xc3, 0xb9, 0xc5, 0x84, 0xc5, 0x8b, 0xc4, 0x9a, 0xc3, 0xb4, 0xc7, 0x9a, 0xe2, + 0xb1, 0xa1, 0xc7, 0xb4, 0xc3, 0x8d, 0xe1, 0x9a, 0xab, 0xc7, 0x92, 0xe1, 0x9b, 0xaa, + 0xc5, 0x88, 0x26, 0xc5, 0xba, 0xc4, 0xad, 0xc5, 0xb5, 0xc3, 0xa3, 0xc5, 0xa8, 0x30, + 0xc5, 0xaf, 0xc8, 0x96, 0xe1, 0x9b, 0xa6, 0xe1, 0x9b, 0xa9, 0xc2, 0xb2, 0xc7, 0xaa, + 0xc4, 0x93, 0xc8, 0x8f, 0xc5, 0xac, 0xe1, 0x9a, 0xa7, 0xc4, 0x89, 0xc8, 0xbc, 0xc3, + 0xb9, 0xc6, 0xb6, 0xe1, 0x9b, 0x99, 0xc7, 0xae, 0xc4, 0xa6, 0xc7, 0xb9, 0x7c, 0xce, + 0x88, 0xc3, 0xbe, 0xc5, 0x9c, 0xc8, 0x82, 0xc6, 0x88, 0xc7, 0x9a, 0xc6, 0xbb, 0xcd, + 0xb6, 0xc7, 0x8a, 0xc5, 0x88, 0xe1, 0x9a, 0xa2, 0x52, 0xc4, 0xae, 0xc2, 0xa9, 0xc5, + 0x9b, 0xc4, 0x83, 0x74, 0xc8, 0x9e, 0xc3, 0xb4, 0xc3, 0x82, 0x30, 0xc3, 0xbd, 0xc3, + 0x87, 0xc8, 0xba, 0xc5, 0xb1, 0xc8, 0x85, 0x6b, 0xc4, 0xb7, 0xc5, 0x9d, 0x57, 0xc7, + 0x90, 0xc6, 0xb9, 0x45, 0xc4, 0x9f, 0xc7, 0x8d, 0xc5, 0xa8, 0xc5, 0x8f, 0xc3, 0xaf, + 0xc3, 0xb3, 0xc3, 0xb3, 0xc3, 0xb1, 0xc2, 0xac, 0xc5, 0xb7, 0xe2, 0xb1, 0xa2, 0xc8, + 0xbb, 0xc7, 0xa7, 0xe1, 0x9a, 0xb9, 0xc5, 0xb2, 0xc5, 0xbd, 0xc6, 0xaf, 0xc3, 0xac, + 0xe1, 0x9b, 0xb0, 0xc7, 0x9d, 0xc4, 0x8a, 0xc6, 0xa9, 0xc5, 0xaa, 0xc3, 0x8e, 0xc2, + 0xa7, 0xc7, 0xaa, 0xc4, 0x90, 0x66, 0xe2, 0xb1, 0xb7, 0xe1, 0x9a, 0xbc, 0xc6, 0xbc, + 0xc5, 0x91, 0xc8, 0xbb, 0x44, 0xce, 0x8c, 0xc8, 0x84, 0xc8, 0x92, 0xe1, 0x9a, 0xbb, + 0xe1, 0x9a, 0xa2, 0xc6, 0x88, 0xc7, 0xb7, 0xc6, 0xa1, 0xe1, 0x9b, 0x90, 0xc4, 0xa2, + 0xc4, 0x92, 0x36, 0xc6, 0xb8, 0xc4, 0xaa, 0xc2, 0xb3, 0xe1, 0x9b, 0x81, 0xc9, 0x87, + 0xc7, 0xbc, 0x3b, 0xc8, 0xbc, 0xc8, 0x8e, 0xc3, 0xaa, 0xc9, 0x8a, 0xc6, 0x94, 0xe2, + 0xb1, 0xb4, 0xc5, 0x9a, 0xe1, 0x9b, 0x92, 0xc8, 0xa2, 0xc4, 0xb6, 0xc4, 0x91, 0xcd, + 0xbe, 0xc8, 0xac, 0xc4, 0xb5, 0xcd, 0xbc, 0x3d, 0xe1, 0x9b, 0xa7, 0xc2, 0xab, 0xc2, + 0xa8, 0xc6, 0xb0, 0xc4, 0x84, 0xc3, 0xb5, 0xe1, 0x9a, 0xb8, 0xc6, 0x96, 0xc3, 0x99, + 0x65, 0x56, 0xc3, 0xb9, 0xc8, 0xb0, 0xc4, 0xb2, 0xcd, 0xb6, 0x71, 0xc3, 0xb8, 0xc7, + 0xb6, 0xc8, 0x8b, 0xc3, 0xa3, 0xe1, 0x9b, 0x8f, 0x6c, 0xc4, 0xad, 0xc3, 0xa2, 0xc2, + 0xb2, 0xe1, 0x9a, 0xb6, 0xe1, 0x9b, 0x98, 0xe1, 0x9b, 0xae, 0xc8, 0xa2, 0xc2, 0xb6, + 0xc8, 0xb3, 0xc6, 0xbe, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0x90, 0xe1, 0x9b, 0x89, 0xc3, + 0xbc, 0xe2, 0xb1, 0xa2, 0xc5, 0xb3, 0xc3, 0x84, 0xc7, 0x95, 0xc5, 0x9d, 0xc4, 0xba, + 0xe2, 0xb1, 0xb6, 0xc2, 0xa8, 0x78, 0xc8, 0xad, 0xc3, 0xae, 0xc6, 0x88, 0xc3, 0x9e, + 0xc3, 0xa9, 0xc3, 0x9d, 0xe2, 0xb1, 0xaf, 0xc5, 0x8c, 0xe2, 0xb1, 0xa1, 0xc5, 0xbc, + 0xe1, 0x9a, 0xab, 0xc8, 0xbf, 0xc7, 0x8b, 0xc6, 0xb2, 0x21, 0xc3, 0x93, 0xc5, 0xa5, + 0x6d, 0xcd, 0xb2, 0xe1, 0x9b, 0x88, 0x5e, 0xe1, 0x9a, 0xb6, 0xc5, 0xb1, 0xc7, 0x87, + 0xc8, 0x9a, 0xc7, 0xa6, 0xc2, 0xaf, 0xe1, 0x9b, 0xa6, 0xc4, 0x86, 0xc2, 0xb1, 0x29, + 0xe1, 0x9a, 0xb9, 0xc7, 0x90, 0xc9, 0x8a, 0xc4, 0xab, 0xe1, 0x9b, 0x8e, 0xc7, 0x90, + 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0xa5, 0xc6, 0xb8, 0xc4, 0xa6, 0xe1, 0x9b, 0x8a, 0xc5, + 0xb2, 0xc6, 0xa8, 0xc6, 0x8e, 0xc2, 0xbe, 0xc8, 0xbd, 0xc8, 0xa5, 0xc5, 0xa5, 0xc6, + 0x90, 0x3f, 0xc7, 0xa8, 0xc4, 0xaf, 0xc2, 0xaa, + ], + asset_id: [ + 0xe2, 0xc6, 0x6a, 0x5e, 0x81, 0xaf, 0x85, 0x65, 0x05, 0x7c, 0x42, 0xab, 0x5a, 0x5b, + 0x5b, 0xb8, 0xc3, 0xca, 0x18, 0x13, 0xbe, 0x45, 0x76, 0xd8, 0xea, 0xe8, 0xb2, 0x50, + 0xfd, 0xe9, 0xfd, 0x95, + ], + }, + TestVector { + key: [ + 0x06, 0xd4, 0x75, 0x14, 0x97, 0x0d, 0x02, 0xd3, 0xf8, 0x43, 0xfb, 0x9b, 0x96, 0x51, + 0x08, 0x75, 0xa7, 0xa6, 0xc0, 0x15, 0x68, 0x1d, 0x06, 0xe0, 0xb1, 0x5b, 0x8a, 0x92, + 0x1f, 0xbd, 0x81, 0x30, + ], + description: [ + 0xe1, 0x9a, 0xa5, 0xe1, 0x9a, 0xb5, 0xc7, 0xb1, 0x2b, 0x72, 0xc6, 0x83, 0xc3, 0x82, + 0xe1, 0x9b, 0x8e, 0x34, 0xe1, 0x9b, 0x98, 0x3c, 0xc2, 0xa5, 0xc8, 0xbe, 0x2c, 0xc3, + 0x82, 0xc3, 0xa4, 0xe2, 0xb1, 0xa3, 0xc5, 0xab, 0xc3, 0xb4, 0xc7, 0xb8, 0xc2, 0xa2, + 0xc6, 0x86, 0xc6, 0xad, 0xc3, 0x9a, 0xc5, 0x93, 0xc7, 0xa3, 0xc2, 0xb7, 0xc6, 0x9a, + 0x5f, 0x55, 0xc9, 0x8c, 0xc9, 0x89, 0x58, 0xc6, 0x95, 0xe1, 0x9a, 0xba, 0xc7, 0x80, + 0xc2, 0xb4, 0xe1, 0x9b, 0x9b, 0xc4, 0x90, 0xe1, 0x9b, 0x8b, 0xe1, 0x9a, 0xae, 0xc8, + 0x92, 0xe1, 0x9b, 0xa8, 0xe2, 0xb1, 0xb2, 0xcd, 0xbd, 0xc3, 0x98, 0xe1, 0x9a, 0xba, + 0xe1, 0x9a, 0xb0, 0x48, 0xc6, 0xa4, 0x2f, 0xc5, 0x9d, 0xe1, 0x9b, 0x86, 0xe1, 0x9a, + 0xb5, 0x7c, 0xc5, 0xa5, 0xe1, 0x9a, 0xba, 0xc4, 0x86, 0xc8, 0xa6, 0xc6, 0xa6, 0xc6, + 0x84, 0xc3, 0xbb, 0xc5, 0xbe, 0x6e, 0xe1, 0x9b, 0xa6, 0xc5, 0x95, 0xe1, 0x9b, 0xaa, + 0xc7, 0xb7, 0xe2, 0xb1, 0xbd, 0xce, 0x8c, 0xc3, 0xa6, 0xc6, 0x9e, 0xc4, 0xb5, 0xe1, + 0x9a, 0xa4, 0xc3, 0xa8, 0xc7, 0x9c, 0xc4, 0x82, 0xc2, 0xa6, 0x31, 0xc3, 0xa6, 0xe2, + 0xb1, 0xae, 0xc7, 0xbb, 0x26, 0xc7, 0xa0, 0xc5, 0x9d, 0xc5, 0xb9, 0xe1, 0x9a, 0xb4, + 0xe1, 0x9b, 0xad, 0xc7, 0x88, 0x30, 0x42, 0xc6, 0x9f, 0xc3, 0x9b, 0x25, 0xc4, 0x9c, + 0xce, 0x87, 0xc5, 0x9c, 0xc5, 0x8c, 0xe1, 0x9b, 0x81, 0xce, 0x89, 0xc4, 0x9a, 0xc5, + 0xa7, 0xe1, 0x9a, 0xa9, 0xc3, 0x93, 0xc7, 0x9b, 0xc3, 0x8d, 0xc3, 0xbe, 0xc3, 0x93, + 0xc8, 0xbc, 0xc8, 0xb3, 0xc5, 0xaf, 0xc7, 0xb3, 0xe1, 0x9a, 0xa7, 0xc4, 0x80, 0xc4, + 0x80, 0xcd, 0xb2, 0xc7, 0x82, 0xc4, 0x83, 0xc7, 0x88, 0xc6, 0x84, 0xe1, 0x9b, 0x90, + 0xc3, 0xa4, 0xc3, 0xbc, 0xc5, 0xad, 0xc6, 0x8b, 0xc2, 0xac, 0xc4, 0xa1, 0xc3, 0xae, + 0xce, 0x86, 0xe1, 0x9b, 0x94, 0xc5, 0x9e, 0xc6, 0x92, 0xe1, 0x9b, 0xac, 0xc3, 0x8d, + 0xc5, 0xb9, 0xc3, 0x82, 0xc8, 0x81, 0xe2, 0xb1, 0xbb, 0xc8, 0xa0, 0xc2, 0xbd, 0xc5, + 0xa2, 0xc6, 0x86, 0xc3, 0xb7, 0xe1, 0x9a, 0xad, 0xc5, 0xbc, 0x2c, 0x51, 0xe1, 0x9a, + 0xab, 0xe1, 0x9b, 0x99, 0x77, 0xc3, 0x9c, 0xc6, 0x9c, 0x31, 0x60, 0xc5, 0x8e, 0xc3, + 0xb5, 0xc3, 0x85, 0xe1, 0x9b, 0xad, 0xc9, 0x8f, 0xc4, 0x8b, 0xc5, 0x93, 0xc2, 0xa2, + 0xc6, 0x8a, 0xe1, 0x9a, 0xa3, 0x4a, 0xc3, 0x9e, 0x30, 0xc8, 0xae, 0xc7, 0xbc, 0xcd, + 0xb3, 0xc7, 0x94, 0xe1, 0x9b, 0x93, 0xc3, 0x93, 0xc3, 0xaa, 0xc4, 0xad, 0xc8, 0x91, + 0xc5, 0xac, 0xe1, 0x9b, 0xa6, 0x26, 0x74, 0xc6, 0xbd, 0xe1, 0x9b, 0xa3, 0xc9, 0x8e, + 0xc8, 0x94, 0xc5, 0xad, 0xc6, 0xac, 0xc6, 0xb7, 0xc7, 0xa5, 0xc3, 0xa5, 0xc8, 0xb4, + 0xc6, 0x95, 0xc8, 0x93, 0xc8, 0xbc, 0xc8, 0xb9, 0xe1, 0x9b, 0x86, 0xc3, 0xb2, 0xc2, + 0xb5, 0xc5, 0x92, 0xe1, 0x9b, 0xa2, 0xe2, 0xb1, 0xb2, 0xc8, 0x80, 0xc4, 0x90, 0xe1, + 0x9a, 0xb9, 0xe2, 0xb1, 0xa7, 0xc5, 0xab, 0xc5, 0xa6, 0xc6, 0xaa, 0xc5, 0x98, 0xc4, + 0xb0, 0xc7, 0xb0, 0xe1, 0x9a, 0xbe, 0xe1, 0x9a, 0xaa, 0xc5, 0xb7, 0xc4, 0x96, 0xc7, + 0xa1, 0xc6, 0xbc, 0xe1, 0x9a, 0xb5, 0xc3, 0x87, 0xc8, 0xa5, 0x73, 0xc3, 0x84, 0xc4, + 0xa6, 0xc6, 0x9d, 0xc5, 0xa9, 0xc5, 0xaa, 0xc7, 0xa6, 0xc6, 0x9e, 0xc8, 0xbc, 0xe1, + 0x9a, 0xbf, 0xc6, 0xa3, 0xc3, 0x99, 0xc5, 0x97, 0xe2, 0xb1, 0xa0, 0xc4, 0x9e, 0x74, + 0xc4, 0x90, 0xc6, 0xa0, 0xe1, 0x9b, 0xaa, 0xc7, 0xaf, 0xc5, 0x8c, 0xc4, 0x91, 0xc7, + 0x93, 0xe1, 0x9b, 0xa3, 0xc5, 0xbd, 0xc8, 0xa3, + ], + asset_id: [ + 0x9e, 0xa8, 0x07, 0x5c, 0x02, 0xdf, 0xe4, 0x64, 0x18, 0x07, 0xe0, 0x7d, 0x2d, 0x8a, + 0x84, 0x6c, 0x1f, 0xfb, 0xaf, 0x66, 0x86, 0x85, 0x74, 0x5c, 0x04, 0x5a, 0xf9, 0xe3, + 0x6c, 0xbe, 0x91, 0xb9, + ], + }, + TestVector { + key: [ + 0x3d, 0x8b, 0xb6, 0x41, 0x5a, 0x53, 0x0b, 0xb2, 0x0f, 0x0d, 0x70, 0x2e, 0x8c, 0xb8, + 0x0b, 0xc1, 0xd5, 0xae, 0x41, 0x66, 0x5c, 0x53, 0x14, 0x4c, 0xfb, 0x60, 0x6e, 0x58, + 0x6a, 0xbc, 0x03, 0x33, + ], + description: [ + 0xc3, 0x92, 0xcd, 0xb4, 0xc2, 0xaa, 0xc2, 0xb7, 0x78, 0xc5, 0x8d, 0xc5, 0x8f, 0xc5, + 0x84, 0xe1, 0x9b, 0x9c, 0xc4, 0x8f, 0xc3, 0x9a, 0xc6, 0x8f, 0x42, 0xc4, 0x94, 0x50, + 0x3a, 0xc5, 0x9f, 0x60, 0xc8, 0xa5, 0x21, 0xc3, 0xa2, 0x3a, 0xe1, 0x9a, 0xb1, 0xc5, + 0x88, 0xc5, 0x81, 0xc6, 0x9d, 0xc7, 0x95, 0xc4, 0xa1, 0x55, 0x3f, 0x48, 0xc9, 0x8a, + 0xc4, 0x8d, 0xc3, 0xbf, 0xe1, 0x9b, 0x8e, 0xc6, 0x8e, 0xc4, 0xbb, 0xe1, 0x9b, 0x9f, + 0xe1, 0x9a, 0xb9, 0xc4, 0xb1, 0xe1, 0x9a, 0xb3, 0xe1, 0x9b, 0x9b, 0xc6, 0x84, 0xe1, + 0x9a, 0xac, 0x2b, 0x51, 0xc5, 0x99, 0xe1, 0x9a, 0xb3, 0xc3, 0xb8, 0xc6, 0x99, 0xc8, + 0x9b, 0xe1, 0x9a, 0xbc, 0xc8, 0xa4, 0xe1, 0x9b, 0x84, 0x6e, 0xc4, 0x83, 0x5e, 0xe1, + 0x9a, 0xa8, 0xc6, 0xad, 0xc5, 0x82, 0xc8, 0xa4, 0xc4, 0x8a, 0xe2, 0xb1, 0xab, 0xc6, + 0x89, 0xe1, 0x9b, 0x8c, 0xc8, 0x8d, 0xe1, 0x9a, 0xb2, 0xe2, 0xb1, 0xb1, 0xc5, 0x87, + 0xe2, 0xb1, 0xad, 0xc4, 0xab, 0x50, 0xc2, 0xb9, 0xc7, 0xae, 0xc5, 0x99, 0xc3, 0x8a, + 0xc3, 0xbc, 0xc4, 0xa9, 0xe1, 0x9b, 0xa6, 0xc8, 0x92, 0xc4, 0xa7, 0xc2, 0xbd, 0xc2, + 0xbb, 0xc8, 0xb2, 0xcd, 0xbd, 0xe1, 0x9b, 0xa0, 0xc2, 0xbe, 0x63, 0xc5, 0xae, 0x69, + 0xc4, 0x90, 0x2e, 0xc4, 0xb0, 0x53, 0xc3, 0x83, 0xc5, 0xa7, 0xc3, 0xb1, 0xc2, 0xb1, + 0xc6, 0x8a, 0xc8, 0x85, 0xc6, 0xb0, 0x46, 0xc2, 0xb6, 0xc9, 0x88, 0xc4, 0xa5, 0xc7, + 0xb9, 0xc5, 0xb5, 0xc8, 0x80, 0xc4, 0xa8, 0xc8, 0x87, 0xc5, 0x8d, 0xc4, 0x97, 0xc8, + 0x86, 0xc2, 0xa8, 0xc4, 0xa9, 0xc6, 0x99, 0xc3, 0x98, 0xc4, 0x97, 0xc8, 0xb1, 0xce, + 0x84, 0xe1, 0x9a, 0xb0, 0xc6, 0x86, 0xc4, 0x97, 0xc6, 0xab, 0xe2, 0xb1, 0xac, 0xc8, + 0xa5, 0xc8, 0xa9, 0xc5, 0x80, 0x65, 0x51, 0xc8, 0x87, 0xe1, 0x9b, 0x95, 0xc4, 0x88, + 0xe1, 0x9b, 0xb0, 0xc6, 0x9d, 0xc5, 0xa8, 0xc8, 0x8b, 0xc7, 0xb4, 0xc4, 0xb9, 0xc7, + 0xb2, 0xc4, 0xb4, 0xe1, 0x9b, 0x9c, 0xc2, 0xbb, 0xe2, 0xb1, 0xa9, 0xc4, 0xa7, 0xc7, + 0x86, 0xc8, 0xac, 0xe2, 0xb1, 0xb1, 0xe1, 0x9b, 0x81, 0x71, 0xc4, 0x8d, 0xc7, 0x97, + 0x33, 0xc3, 0x83, 0xc9, 0x8a, 0xc6, 0xb3, 0xc4, 0xb0, 0xc3, 0xb1, 0xe2, 0xb1, 0xac, + 0xe1, 0x9b, 0x91, 0xc6, 0x96, 0xc2, 0xb5, 0xc7, 0xac, 0x29, 0x6d, 0x36, 0xc6, 0x91, + 0xc4, 0xa8, 0xc4, 0xb1, 0xc7, 0x8d, 0xce, 0x8c, 0xc3, 0x88, 0x6b, 0xc7, 0xbd, 0xc7, + 0x98, 0xc8, 0x95, 0xc7, 0xa2, 0xe2, 0xb1, 0xa0, 0xc7, 0xa0, 0x46, 0x31, 0x2e, 0xc6, + 0x81, 0xc8, 0x96, 0xc8, 0x8f, 0xe1, 0x9b, 0x98, 0xc4, 0xb3, 0xc8, 0xb8, 0xe1, 0x9a, + 0xb2, 0xc8, 0x9e, 0xc5, 0x83, 0xc7, 0x87, 0xc6, 0xa1, 0xc2, 0xae, 0x43, 0xc8, 0xb3, + 0xc4, 0x89, 0xc3, 0x9e, 0xe1, 0x9b, 0x96, 0xc5, 0x84, 0x33, 0xc9, 0x87, 0x69, 0xce, + 0x88, 0xc8, 0xac, 0xc5, 0x87, 0xc5, 0x87, 0xe1, 0x9b, 0x8b, 0xc4, 0x89, 0xc5, 0xb0, + 0xc4, 0x9f, 0xe1, 0x9b, 0x97, 0xc7, 0xa8, 0xc8, 0xb3, 0xc7, 0x83, 0xc4, 0x91, 0xe1, + 0x9a, 0xba, 0xc7, 0x82, 0xc7, 0xb0, 0xc4, 0xbd, 0xc5, 0xab, 0xe1, 0x9b, 0xac, 0xe2, + 0xb1, 0xbe, 0xc4, 0x89, 0xc3, 0x8b, 0xe2, 0xb1, 0xae, 0xcd, 0xbe, 0xc4, 0x9b, 0xc4, + 0xab, 0xc6, 0xbc, 0xe1, 0x9b, 0xac, 0xc4, 0x84, 0xc5, 0x9f, 0xc7, 0xac, 0xc3, 0xba, + 0xc6, 0x83, 0xc3, 0x9b, 0xc6, 0xa6, 0xc6, 0xac, 0xc7, 0xb5, 0xc6, 0x8a, 0xc4, 0xbf, + 0xe2, 0xb1, 0xaa, 0xc3, 0x96, 0x42, 0xc4, 0x95, 0xc3, 0xa2, 0xc6, 0xa5, 0x5b, 0x2e, + 0xc3, 0xaf, 0xc3, 0x93, 0xc4, 0x9d, 0xc8, 0xa4, + ], + asset_id: [ + 0x02, 0xce, 0x39, 0x82, 0x1e, 0x86, 0x41, 0xcd, 0x79, 0x5c, 0x1e, 0x41, 0xf7, 0x48, + 0x3c, 0x59, 0x88, 0x81, 0xb5, 0x0f, 0x88, 0xe7, 0x36, 0xcb, 0x4f, 0xb0, 0x00, 0xbc, + 0xf0, 0x28, 0x62, 0x2b, + ], + }, + TestVector { + key: [ + 0x95, 0xa6, 0xa5, 0x7f, 0x8e, 0x85, 0x43, 0x72, 0xf9, 0xce, 0x7d, 0xb1, 0x34, 0xfd, + 0x9e, 0x87, 0x43, 0xbd, 0x39, 0x17, 0xe6, 0x50, 0x52, 0x93, 0x4c, 0xbd, 0xef, 0xa7, + 0x67, 0xb7, 0xc7, 0x18, + ], + description: [ + 0xc7, 0x84, 0xc3, 0xb8, 0xc7, 0xba, 0xc6, 0xbc, 0xc6, 0xa3, 0x28, 0xc5, 0xb4, 0xc7, + 0x8c, 0xc2, 0xba, 0xe1, 0x9b, 0xac, 0x3d, 0xc5, 0xb3, 0xc5, 0xbf, 0xc4, 0xb5, 0xce, + 0x8a, 0xc5, 0xab, 0xc7, 0xbe, 0xc7, 0xa0, 0xc4, 0x95, 0xe1, 0x9b, 0xa8, 0xc3, 0xab, + 0xc7, 0x99, 0xe1, 0x9a, 0xae, 0xcd, 0xb6, 0xe2, 0xb1, 0xb1, 0xc5, 0x8a, 0xe1, 0x9b, + 0xab, 0xc5, 0xaa, 0xc7, 0xb8, 0xc6, 0xb2, 0x48, 0xe1, 0x9b, 0x94, 0xc8, 0xb4, 0xc7, + 0x9e, 0xc8, 0x9b, 0x4f, 0xc7, 0xab, 0xc5, 0xa8, 0xc7, 0x9c, 0xc8, 0x9f, 0xc4, 0x8a, + 0xc8, 0x98, 0xe1, 0x9a, 0xa6, 0xc4, 0xb7, 0xc3, 0xb8, 0xe1, 0x9b, 0x97, 0xc7, 0xb6, + 0x57, 0xc4, 0xa0, 0xe1, 0x9b, 0x9f, 0xc5, 0x9a, 0xc2, 0xa7, 0x2c, 0xe1, 0x9a, 0xa4, + 0xc6, 0x84, 0xcd, 0xba, 0xc7, 0x90, 0xc4, 0xae, 0xc4, 0xaf, 0xc2, 0xb1, 0xce, 0x84, + 0xe1, 0x9a, 0xa0, 0xe1, 0x9b, 0xa9, 0xc4, 0xa0, 0xce, 0x86, 0xc3, 0x83, 0xc7, 0xab, + 0xcd, 0xb4, 0xc5, 0x83, 0xc8, 0xbd, 0xc8, 0x98, 0xce, 0x89, 0x73, 0xe1, 0x9a, 0xa6, + 0xc5, 0xa1, 0xc2, 0xa7, 0xc3, 0x81, 0xc9, 0x83, 0xc5, 0xbc, 0xc5, 0x9b, 0xc4, 0xbe, + 0x5f, 0xc6, 0xb8, 0xe1, 0x9b, 0x86, 0x74, 0xc3, 0xb4, 0x40, 0xc8, 0xbc, 0xc8, 0x93, + 0xc8, 0x9c, 0xc2, 0xa4, 0xe1, 0x9a, 0xb4, 0xc3, 0x98, 0xc5, 0x96, 0xe1, 0x9b, 0xa0, + 0x7c, 0xe2, 0xb1, 0xa0, 0xc4, 0xb2, 0xc2, 0xb7, 0xce, 0x85, 0xc3, 0x8c, 0xc2, 0xa2, + 0xc8, 0x9a, 0x4f, 0xc7, 0xae, 0xc4, 0xb5, 0xc7, 0x95, 0xc3, 0x8e, 0xc8, 0xa3, 0xe1, + 0x9a, 0xa3, 0xc3, 0xa7, 0xc7, 0xb7, 0xc6, 0xaa, 0xc6, 0xb6, 0xc8, 0xbb, 0xc2, 0xa9, + 0xe1, 0x9b, 0x8b, 0xc7, 0x9a, 0xc9, 0x84, 0xc3, 0xa2, 0x71, 0xc5, 0x83, 0xc3, 0x83, + 0xc8, 0x86, 0xcd, 0xb2, 0xc4, 0xa7, 0xe1, 0x9b, 0x80, 0x58, 0xc5, 0x96, 0xe2, 0xb1, + 0xb2, 0xe2, 0xb1, 0xbd, 0xc7, 0xbc, 0x4b, 0xcd, 0xbc, 0xc8, 0x88, 0xc4, 0x81, 0xc7, + 0xb8, 0xc4, 0x8f, 0xc8, 0x8d, 0x26, 0xc7, 0x92, 0xc3, 0xa0, 0xc5, 0x8c, 0xc5, 0xbd, + 0xc6, 0xb3, 0xc2, 0xa4, 0x67, 0xc8, 0x93, 0xc8, 0xac, 0xc9, 0x89, 0xc4, 0xbd, 0xc8, + 0x82, 0xe2, 0xb1, 0xa9, 0xe1, 0x9b, 0xa2, 0x79, 0x54, 0xe1, 0x9b, 0x94, 0xc7, 0x96, + 0xc8, 0xae, 0xc7, 0xba, 0xc8, 0xa3, 0xc6, 0xa3, 0xcd, 0xba, 0xc8, 0xa7, 0xc4, 0xa8, + 0x3b, 0xc7, 0xb9, 0xc6, 0x83, 0xc8, 0x98, 0xc2, 0xb0, 0xe1, 0x9a, 0xae, 0xc8, 0x8c, + 0xc3, 0xa3, 0xe1, 0x9a, 0xbd, 0x45, 0xc8, 0xb6, 0xc9, 0x80, 0x28, 0xe1, 0x9b, 0x81, + 0x2b, 0x6d, 0xc8, 0xb9, 0xc7, 0x80, 0xe2, 0xb1, 0xad, 0xc8, 0x8d, 0x6c, 0x7b, 0xc6, + 0x91, 0xc3, 0x93, 0xc8, 0xa9, 0xc7, 0xaf, 0xc5, 0x95, 0xe1, 0x9b, 0xa0, 0xc6, 0xbe, + 0x21, 0xc4, 0xac, 0xc4, 0xa8, 0xe1, 0x9a, 0xbe, 0xc9, 0x8e, 0xc3, 0x88, 0xc4, 0x9e, + 0xc4, 0xbe, 0xe1, 0x9b, 0x90, 0xc3, 0x99, 0xc7, 0x93, 0xc6, 0xa8, 0xe1, 0x9b, 0xa9, + 0xe1, 0x9b, 0xa5, 0xc7, 0xa4, 0xc6, 0x81, 0xe1, 0x9b, 0x9a, 0xc3, 0xa0, 0xc5, 0xab, + 0xc4, 0x86, 0xc8, 0xa4, 0x53, 0xce, 0x8c, 0xc9, 0x81, 0xc3, 0xb7, 0xc7, 0xaa, 0xc8, + 0x8a, 0xc3, 0xa9, 0x41, 0xe1, 0x9b, 0xaa, 0xcd, 0xb7, 0xc3, 0xac, 0xc3, 0xbf, 0xc8, + 0x8d, 0xc7, 0xa7, 0xc7, 0xa3, 0xe1, 0x9b, 0xa9, 0x5a, 0xc4, 0xb1, 0x68, 0xe2, 0xb1, + 0xbf, 0x2a, 0x5b, 0xc8, 0xb6, 0xc5, 0xa0, 0x39, 0xc4, 0x8b, 0xc8, 0xae, 0x6c, 0xe2, + 0xb1, 0xb5, 0xe1, 0x9b, 0x9b, 0xc5, 0x8c, 0xc5, 0x91, 0x68, 0xc6, 0xaf, 0xc9, 0x84, + 0x44, 0xc7, 0x93, 0xc2, 0xb5, 0xc8, 0x90, 0x67, + ], + asset_id: [ + 0x7a, 0x8e, 0xea, 0x55, 0xfb, 0xde, 0x77, 0x4d, 0x8a, 0x7a, 0x5c, 0x01, 0xfa, 0x8e, + 0xbc, 0x8c, 0x57, 0x5f, 0xf9, 0x33, 0xd9, 0xd1, 0x51, 0x9b, 0x62, 0xf3, 0x18, 0xf4, + 0x8c, 0xa2, 0xab, 0x94, + ], + }, + TestVector { + key: [ + 0xa3, 0x6d, 0xf3, 0x6a, 0xc7, 0xa2, 0xe2, 0xba, 0xab, 0xfd, 0x1e, 0x8d, 0xbf, 0x39, + 0x3b, 0xd8, 0x25, 0x32, 0xec, 0x3d, 0x52, 0x3b, 0xbe, 0x85, 0x7f, 0x71, 0x58, 0x0c, + 0xcd, 0x22, 0xdf, 0x08, + ], + description: [ + 0xc6, 0x81, 0xc4, 0x90, 0xe1, 0x9a, 0xa0, 0xe1, 0x9b, 0x8c, 0x40, 0xc8, 0x8d, 0xc7, + 0xaf, 0xcd, 0xb2, 0xc5, 0xae, 0xc7, 0xb1, 0xce, 0x84, 0xc2, 0xb6, 0xc7, 0x99, 0xe1, + 0x9a, 0xb4, 0xe1, 0x9b, 0xaf, 0xc6, 0x93, 0xc9, 0x83, 0x37, 0xe2, 0xb1, 0xb1, 0xc4, + 0x98, 0xe1, 0x9b, 0xa7, 0xc8, 0x8f, 0xc3, 0x83, 0xc3, 0x82, 0xc4, 0x98, 0xc7, 0x9c, + 0xc2, 0xae, 0xc8, 0x9a, 0xcd, 0xb5, 0xc3, 0xac, 0xc6, 0x9c, 0xc8, 0xab, 0xc6, 0xbd, + 0x71, 0xc4, 0xaf, 0xe1, 0x9a, 0xa0, 0xe1, 0x9a, 0xb1, 0x23, 0xc5, 0xa8, 0xc4, 0xb9, + 0x45, 0xe1, 0x9b, 0xa8, 0xc6, 0xb0, 0xc4, 0xa0, 0xc8, 0xa7, 0xe1, 0x9b, 0x9b, 0xc6, + 0xa7, 0x79, 0xc7, 0xa8, 0xc7, 0xa1, 0xc7, 0xbd, 0xc3, 0xa1, 0xe2, 0xb1, 0xa2, 0xc3, + 0x82, 0xc6, 0xa7, 0xc4, 0x9d, 0xc7, 0xbb, 0x64, 0xc2, 0xb0, 0xc4, 0x91, 0xe1, 0x9a, + 0xbe, 0xc7, 0xaf, 0xe2, 0xb1, 0xaa, 0xc8, 0xa3, 0xe2, 0xb1, 0xbe, 0x3f, 0xc8, 0xa7, + 0xe1, 0x9b, 0x9c, 0xe1, 0x9b, 0x88, 0xc8, 0xa0, 0xc8, 0x96, 0x28, 0xc6, 0xb7, 0xc7, + 0xa2, 0xc6, 0x99, 0x66, 0xc8, 0x8c, 0xc3, 0x93, 0xc5, 0x8b, 0xc8, 0xa2, 0xc5, 0x91, + 0xe2, 0xb1, 0xa6, 0xc3, 0xbd, 0xc3, 0xa4, 0xc6, 0x86, 0xe1, 0x9b, 0xa4, 0xc3, 0xbe, + 0xc4, 0xbf, 0xc9, 0x88, 0xc6, 0x97, 0xcd, 0xb5, 0xc4, 0xb1, 0xc7, 0x92, 0xc3, 0x86, + 0xc5, 0x80, 0xc5, 0x9c, 0xc5, 0x92, 0xc3, 0x80, 0xe1, 0x9a, 0xbd, 0xc6, 0x84, 0x46, + 0xc6, 0xb6, 0xc6, 0x87, 0xc4, 0x95, 0xc3, 0xbe, 0xc3, 0xbc, 0xc2, 0xaf, 0xc2, 0xa9, + 0xe1, 0x9a, 0xa1, 0xc3, 0xa4, 0xe1, 0x9b, 0xaf, 0xc5, 0x8f, 0xe1, 0x9b, 0x98, 0xc5, + 0x91, 0x55, 0xc3, 0x99, 0xc8, 0xbf, 0xc7, 0xb4, 0x63, 0xc5, 0xa0, 0xc8, 0xa1, 0xe2, + 0xb1, 0xb7, 0xc3, 0xaf, 0xc5, 0x8c, 0xc8, 0xab, 0xc8, 0x8b, 0x3c, 0xc3, 0x8d, 0xc6, + 0x80, 0xc8, 0xa1, 0xc7, 0xb9, 0xc3, 0xbf, 0xc2, 0xa4, 0x4f, 0xc8, 0x82, 0xe2, 0xb1, + 0xa8, 0xc2, 0xbd, 0x78, 0xe1, 0x9b, 0xac, 0xc5, 0x90, 0xc3, 0x94, 0xc3, 0xb8, 0xc7, + 0xb7, 0xc3, 0x84, 0xe2, 0xb1, 0xaf, 0xc6, 0x88, 0xc7, 0x83, 0xc9, 0x8d, 0xc5, 0x9f, + 0x78, 0xc3, 0xbb, 0xe2, 0xb1, 0xa7, 0xe2, 0xb1, 0xbc, 0xc5, 0x8d, 0xc6, 0xbd, 0xe2, + 0xb1, 0xa5, 0xc4, 0x94, 0xc7, 0x91, 0xc8, 0x97, 0x63, 0xc3, 0x99, 0xc2, 0xb6, 0xc7, + 0x99, 0xe1, 0x9a, 0xa2, 0xc7, 0xa0, 0xc8, 0xa6, 0xcd, 0xbc, 0xc6, 0x86, 0xe2, 0xb1, + 0xb5, 0x42, 0xc2, 0xa1, 0xc8, 0x97, 0xc8, 0xa6, 0xc5, 0x98, 0xc4, 0xba, 0xc4, 0x88, + 0xc3, 0x80, 0x59, 0xc8, 0xa0, 0xc6, 0xa7, 0xc4, 0xb5, 0xc8, 0x8e, 0xc3, 0xa1, 0x7c, + 0xc6, 0xae, 0xc2, 0xaa, 0x7c, 0xc8, 0xaa, 0xc2, 0xb8, 0xc4, 0xa9, 0xc7, 0xa8, 0xc3, + 0x98, 0xc9, 0x82, 0xc8, 0x87, 0xc3, 0x98, 0xc5, 0x9d, 0xc9, 0x8b, 0xc4, 0x87, 0xce, + 0x86, 0xc8, 0x96, 0xc2, 0xa5, 0x66, 0xe2, 0xb1, 0xbb, 0xc4, 0x9f, 0xc7, 0xaa, 0xc8, + 0x93, 0xc4, 0xbe, 0xe2, 0xb1, 0xac, 0x5c, 0xc3, 0x8f, 0x44, 0xcd, 0xb4, 0x53, 0x31, + 0xc8, 0xaf, 0xc2, 0xbd, 0xc4, 0x85, 0xc4, 0xa1, 0xc5, 0xaf, 0xc8, 0xa2, 0xc8, 0x95, + 0xc6, 0x95, 0xe1, 0x9b, 0xac, 0xc4, 0x95, 0x2b, 0x4e, 0x78, 0xc5, 0xbf, 0xc7, 0x89, + 0xc7, 0x9c, 0xc3, 0x9b, 0x72, 0xcd, 0xbc, 0xc8, 0x93, 0xc6, 0x93, 0xc3, 0xa5, 0x66, + 0xe1, 0x9a, 0xbf, 0xc3, 0xa6, 0xc5, 0x84, 0xc4, 0xbd, 0xe2, 0xb1, 0xaf, 0xc4, 0x92, + 0x4e, 0xc5, 0x8c, 0xe1, 0x9b, 0xae, 0xc3, 0xac, 0xce, 0x88, 0xc7, 0xb5, 0xc3, 0xa8, + 0xe1, 0x9a, 0xab, 0xc7, 0x95, 0xe2, 0xb1, 0xbd, + ], + asset_id: [ + 0xbe, 0x14, 0xb4, 0xa7, 0x43, 0x0a, 0x90, 0xa9, 0x50, 0xd5, 0x8d, 0xd7, 0xbb, 0x10, + 0x72, 0x0e, 0xb9, 0x50, 0xb2, 0x4e, 0x6f, 0x27, 0xce, 0x85, 0x4a, 0x80, 0xf6, 0x4a, + 0x19, 0x24, 0xcd, 0x28, + ], + }, + TestVector { + key: [ + 0x68, 0x89, 0x11, 0x8f, 0xa9, 0xe7, 0xda, 0xf2, 0x76, 0xfd, 0x62, 0xcb, 0x66, 0x5a, + 0xbf, 0x50, 0x72, 0x20, 0x15, 0xc2, 0xa0, 0x8b, 0x13, 0xf7, 0x7d, 0x20, 0x24, 0x75, + 0x96, 0x26, 0xc5, 0x03, + ], + description: [ + 0xc2, 0xaa, 0xc2, 0xb5, 0xc2, 0xa5, 0xc7, 0xbc, 0xc3, 0x9a, 0xc9, 0x83, 0xc3, 0x8f, + 0x25, 0xc5, 0x83, 0xc3, 0x86, 0xc4, 0xa4, 0xc3, 0xac, 0xc7, 0xbf, 0xc3, 0x93, 0xc6, + 0x95, 0x42, 0x3b, 0xe1, 0x9b, 0x96, 0xc7, 0x85, 0xc3, 0x84, 0x23, 0xc3, 0xb9, 0x53, + 0xc6, 0xb0, 0xc2, 0xac, 0xc4, 0x94, 0xe1, 0x9a, 0xba, 0xc9, 0x8c, 0xc8, 0x8e, 0xce, + 0x87, 0xc7, 0x8f, 0xc8, 0xbb, 0x79, 0xc3, 0xb4, 0x36, 0xc5, 0x9c, 0xc4, 0x9b, 0xe1, + 0x9a, 0xb4, 0x51, 0xc5, 0xb3, 0x2b, 0xc7, 0x93, 0xe1, 0x9b, 0xa7, 0xc5, 0x93, 0xe1, + 0x9b, 0x9b, 0xc6, 0x81, 0xc4, 0xa8, 0xc8, 0x9a, 0xe1, 0x9b, 0x90, 0xc8, 0x9b, 0xc3, + 0xa5, 0xc4, 0xbd, 0xc7, 0x8b, 0xe1, 0x9b, 0xad, 0xc5, 0xa0, 0xe1, 0x9a, 0xb5, 0x5e, + 0x69, 0x78, 0xc5, 0xbc, 0xc7, 0x8e, 0xc4, 0x8b, 0xc4, 0xa9, 0xc6, 0x91, 0xc5, 0xa8, + 0xc5, 0xbe, 0xc4, 0xb0, 0xc5, 0x96, 0xe1, 0x9a, 0xac, 0xe2, 0xb1, 0xbf, 0xc8, 0xae, + 0xc3, 0x97, 0xc6, 0x8a, 0xc4, 0x9b, 0xc8, 0x9b, 0xc7, 0x89, 0xe1, 0x9a, 0xbd, 0xe1, + 0x9b, 0x89, 0xc9, 0x86, 0xc7, 0x91, 0xe1, 0x9b, 0x96, 0xe1, 0x9a, 0xa4, 0xc8, 0xad, + 0xcd, 0xb0, 0xce, 0x87, 0xc5, 0xb7, 0x5d, 0xe1, 0x9b, 0x9b, 0xc9, 0x80, 0xc3, 0x9b, + 0xc3, 0x85, 0xc3, 0x9a, 0xc6, 0xb7, 0xe1, 0x9b, 0x89, 0xc2, 0xb6, 0xe1, 0x9a, 0xac, + 0xe1, 0x9b, 0x8f, 0xc2, 0xb3, 0xcd, 0xbd, 0xc3, 0x85, 0xc6, 0x90, 0x32, 0xc7, 0xab, + 0xe2, 0xb1, 0xac, 0xc8, 0x8a, 0xc4, 0x86, 0xc5, 0x98, 0xc5, 0x90, 0xc8, 0x9c, 0xc3, + 0x8e, 0xc8, 0x96, 0xc5, 0xa8, 0xc3, 0xa4, 0x7c, 0xc6, 0xb9, 0xc5, 0xa8, 0xc3, 0xa5, + 0x36, 0xc2, 0xa3, 0x7a, 0xc5, 0xb1, 0xc7, 0xb0, 0xc5, 0xb6, 0x61, 0xc5, 0x80, 0xc9, + 0x84, 0xc6, 0xb0, 0xc5, 0x8f, 0xe1, 0x9b, 0x9a, 0xc6, 0xb0, 0xcd, 0xb7, 0xe1, 0x9b, + 0x8a, 0xc6, 0xba, 0xe1, 0x9b, 0x9e, 0x3e, 0x57, 0xc8, 0x9c, 0xc6, 0x9b, 0x5e, 0xc8, + 0xa7, 0xc8, 0x98, 0xc5, 0xbc, 0xc3, 0x9d, 0xc3, 0xa4, 0xe1, 0x9a, 0xbd, 0xe1, 0x9b, + 0x81, 0xc6, 0xbf, 0x6c, 0xc4, 0xbd, 0xc4, 0xbe, 0xe1, 0x9b, 0x8a, 0x75, 0x6c, 0xc5, + 0x97, 0xc8, 0xbc, 0xc5, 0x9e, 0xc5, 0x94, 0xe1, 0x9a, 0xa5, 0xc9, 0x81, 0xc6, 0x88, + 0xe1, 0x9b, 0x85, 0xe2, 0xb1, 0xbe, 0x49, 0xc5, 0xa6, 0xc4, 0xb7, 0xc9, 0x88, 0xe1, + 0x9a, 0xa6, 0xc5, 0x91, 0xc5, 0xa5, 0xce, 0x8c, 0x56, 0xc3, 0x99, 0xc4, 0x9e, 0xc2, + 0xb4, 0xc3, 0x8b, 0x53, 0x2c, 0xc7, 0xb8, 0x3a, 0xc7, 0x81, 0xc6, 0xb3, 0xe1, 0x9b, + 0xaf, 0xc3, 0xaa, 0xc7, 0xa7, 0xc3, 0xbe, 0xe2, 0xb1, 0xb7, 0xe1, 0x9a, 0xb4, 0x5c, + 0x7c, 0xc2, 0xbf, 0xe1, 0x9a, 0xb3, 0xc8, 0xb6, 0xc6, 0x8e, 0xe1, 0x9b, 0xae, 0xc5, + 0xaf, 0xe1, 0x9b, 0x90, 0xc6, 0xab, 0xc5, 0xb2, 0xe1, 0x9b, 0x81, 0x49, 0xe1, 0x9b, + 0xa4, 0xc3, 0x80, 0x75, 0xc4, 0x9c, 0xc8, 0x96, 0xe1, 0x9a, 0xae, 0x5d, 0xc4, 0xba, + 0xe1, 0x9b, 0x86, 0x2b, 0xe2, 0xb1, 0xb0, 0xc4, 0x9d, 0xe2, 0xb1, 0xb9, 0xc6, 0xb5, + 0xc3, 0xb2, 0xc6, 0x87, 0xc5, 0x9c, 0xc5, 0x94, 0xc6, 0x92, 0xc3, 0x86, 0xc5, 0x82, + 0xc6, 0xb7, 0x47, 0xc6, 0x8b, 0xcd, 0xbd, 0xcd, 0xbd, 0xc7, 0xad, 0xc7, 0x97, 0xc2, + 0xa1, 0xc8, 0xa8, 0xe1, 0x9a, 0xbd, 0xc7, 0xad, 0xc4, 0xac, 0xc8, 0x99, 0x6c, 0x36, + 0x5f, 0xc5, 0x89, 0xc4, 0x87, 0xc4, 0x80, 0xc2, 0xbe, 0xe2, 0xb1, 0xbd, 0xc4, 0x8f, + 0xc4, 0xb1, 0xc3, 0x83, 0xc5, 0xbd, 0xc6, 0xa5, 0xc5, 0xb9, 0xc5, 0xa5, 0xc6, 0xba, + 0x6e, 0xc8, 0xaa, 0x6d, 0xc4, 0x80, 0x7c, 0x5a, + ], + asset_id: [ + 0xac, 0xa7, 0x66, 0x43, 0xac, 0xdd, 0x83, 0xe3, 0x8e, 0xe5, 0xcf, 0xe0, 0xe7, 0xd2, + 0x99, 0xd6, 0x35, 0x69, 0x0a, 0x82, 0xba, 0x96, 0x51, 0x47, 0xe2, 0xa4, 0x48, 0x24, + 0x9b, 0xee, 0xb2, 0x88, + ], + }, + TestVector { + key: [ + 0x7a, 0xb9, 0xe5, 0xa6, 0x04, 0x28, 0x8a, 0x55, 0x0b, 0x9e, 0x08, 0x7a, 0x00, 0x4b, + 0xb8, 0x8b, 0xe4, 0xb2, 0xb4, 0x8d, 0xb3, 0x3f, 0xb0, 0x80, 0x97, 0xf8, 0xbc, 0x64, + 0x60, 0x3e, 0xf8, 0x1f, + ], + description: [ + 0xc7, 0xad, 0x3b, 0xc8, 0x91, 0xc6, 0x96, 0xe1, 0x9a, 0xbd, 0xe1, 0x9a, 0xa6, 0xce, + 0x87, 0xc3, 0x83, 0xc3, 0x84, 0xe1, 0x9b, 0x84, 0xc9, 0x8a, 0xc4, 0x97, 0xc9, 0x87, + 0xe2, 0xb1, 0xba, 0xc6, 0x93, 0xc6, 0x98, 0xe2, 0xb1, 0xb7, 0xc6, 0x8e, 0xc8, 0x8f, + 0xc9, 0x84, 0xc2, 0xbe, 0x55, 0xc8, 0xb0, 0xc7, 0x82, 0xc2, 0xb2, 0xc6, 0x88, 0xcd, + 0xb3, 0xc6, 0xb2, 0x2e, 0x2e, 0xc3, 0x87, 0xc9, 0x80, 0xc7, 0x9c, 0xc8, 0x9f, 0xc5, + 0xb0, 0xc8, 0x9e, 0xc4, 0xbb, 0xc7, 0x81, 0x74, 0x6c, 0xc6, 0x8c, 0xc6, 0x8f, 0xe1, + 0x9a, 0xb4, 0xc8, 0x94, 0xc2, 0xac, 0xc4, 0x8f, 0xc5, 0xb6, 0xc8, 0xb5, 0xc3, 0xb7, + 0xcd, 0xb6, 0xc2, 0xb1, 0xc5, 0xb1, 0xc4, 0xa5, 0x40, 0x68, 0x58, 0x2b, 0xc5, 0xb7, + 0xc4, 0x91, 0xc6, 0xa1, 0xc7, 0xa7, 0x79, 0xe1, 0x9b, 0xa6, 0xe2, 0xb1, 0xac, 0xc6, + 0x99, 0x51, 0xc7, 0xaf, 0xcd, 0xb4, 0xe1, 0x9b, 0x8e, 0xe1, 0x9b, 0xad, 0xc8, 0x96, + 0xe1, 0x9b, 0xad, 0xc3, 0xa1, 0xc6, 0x95, 0xc5, 0x98, 0xc6, 0x95, 0xc2, 0xaf, 0xe2, + 0xb1, 0xac, 0xc4, 0xbe, 0xc5, 0xac, 0xc8, 0x85, 0xc5, 0xa9, 0xc4, 0x93, 0xc5, 0x9a, + 0x6c, 0xc3, 0xae, 0xe1, 0x9a, 0xba, 0xc6, 0x85, 0xc6, 0x92, 0xc5, 0xa7, 0xc4, 0xa5, + 0xc5, 0x80, 0xc6, 0xaa, 0xe2, 0xb1, 0xa5, 0xc4, 0xaa, 0xc8, 0x83, 0xc5, 0xad, 0xc9, + 0x88, 0x7c, 0xc7, 0xa6, 0xe1, 0x9a, 0xb9, 0xc3, 0xa4, 0xc9, 0x84, 0xc5, 0xa3, 0xc3, + 0xb6, 0xc5, 0x8c, 0xc8, 0xab, 0xc8, 0xa7, 0xc8, 0xb7, 0xc5, 0x9c, 0xc6, 0xb5, 0xc8, + 0x8d, 0xc2, 0xb7, 0xc5, 0x93, 0xc5, 0xb7, 0xc7, 0xac, 0xcd, 0xbe, 0xc3, 0xa2, 0xc5, + 0xa5, 0xc4, 0x8c, 0xe2, 0xb1, 0xbf, 0x66, 0xc5, 0xbf, 0xc6, 0x83, 0xc6, 0x99, 0xc2, + 0xa2, 0xe1, 0x9b, 0xad, 0x7c, 0xc4, 0x9e, 0xc6, 0xa2, 0xc3, 0xb8, 0xc6, 0xb6, 0xc6, + 0xaf, 0x72, 0xc6, 0xb1, 0xc6, 0x98, 0xc6, 0xb8, 0x49, 0xe1, 0x9a, 0xa6, 0x59, 0xe1, + 0x9b, 0xa1, 0xc8, 0xb6, 0xc4, 0xa6, 0xc6, 0xbe, 0xc8, 0xa1, 0xe2, 0xb1, 0xa5, 0xe1, + 0x9b, 0xa3, 0xc5, 0x8d, 0xc2, 0xb5, 0xc6, 0xa8, 0xc7, 0xbd, 0xc8, 0x8a, 0xe1, 0x9b, + 0xb0, 0xc5, 0xaf, 0x56, 0xc8, 0x8b, 0x34, 0xc4, 0x94, 0xc4, 0xbc, 0x67, 0xc6, 0xb5, + 0xc2, 0xb0, 0x63, 0xe1, 0x9b, 0x99, 0xc4, 0xa8, 0xc6, 0x9c, 0xe1, 0x9a, 0xbc, 0xe1, + 0x9b, 0x8a, 0xc6, 0x99, 0x4b, 0xc6, 0xb2, 0xe1, 0x9b, 0xa2, 0xc8, 0x9f, 0xc5, 0x88, + 0xc5, 0xb6, 0xc3, 0xb8, 0x6d, 0xe2, 0xb1, 0xa2, 0xc7, 0xb4, 0xcd, 0xb3, 0xc2, 0xa3, + 0xc7, 0xa1, 0xc4, 0x83, 0xc7, 0xb1, 0xc8, 0x98, 0xc8, 0x84, 0x6b, 0xc7, 0x84, 0xc6, + 0xb6, 0xe1, 0x9a, 0xb8, 0xc5, 0x93, 0xc8, 0x90, 0x79, 0xc8, 0xa3, 0xe1, 0x9a, 0xb0, + 0xe1, 0x9b, 0xad, 0xc8, 0xb0, 0xc4, 0x9e, 0xe1, 0x9b, 0x9a, 0xc7, 0x97, 0x32, 0xc6, + 0xb2, 0xc9, 0x83, 0xe1, 0x9b, 0x96, 0xc9, 0x8f, 0xc3, 0x8c, 0xe2, 0xb1, 0xad, 0xc4, + 0xbd, 0xc3, 0xbe, 0xe1, 0x9b, 0x8b, 0xc8, 0x9d, 0xc6, 0x95, 0xc8, 0x8f, 0xc8, 0x9e, + 0xc8, 0x83, 0x74, 0xc7, 0xbe, 0xe1, 0x9b, 0x8a, 0x3c, 0xc5, 0x93, 0x63, 0xc7, 0x98, + 0x31, 0xc4, 0x82, 0x56, 0xe2, 0xb1, 0xa3, 0x53, 0xe1, 0x9b, 0xa4, 0xc7, 0x94, 0xc7, + 0x9e, 0x2e, 0xcd, 0xbe, 0xc7, 0x9c, 0xc4, 0x90, 0xe2, 0xb1, 0xbe, 0xe2, 0xb1, 0xba, + 0xc7, 0x82, 0xc5, 0xb2, 0xe1, 0x9a, 0xa4, 0xc6, 0xb2, 0xcd, 0xb2, 0xc3, 0xa5, 0xe1, + 0x9b, 0xab, 0xc3, 0xa9, 0xc7, 0xa3, 0xc3, 0x8a, 0xc2, 0xa3, 0xc9, 0x82, 0x7b, 0xc6, + 0xb3, 0x4b, 0xc4, 0xb6, 0xc4, 0x85, 0xc7, 0x8c, + ], + asset_id: [ + 0x03, 0x74, 0x69, 0x16, 0xa8, 0xa6, 0xb8, 0xff, 0xa0, 0x4d, 0x71, 0x95, 0xbc, 0x06, + 0x74, 0x96, 0xa6, 0xce, 0xce, 0x35, 0x6a, 0x2a, 0x14, 0x6d, 0x69, 0x52, 0x9a, 0xea, + 0xac, 0x10, 0x1a, 0xb8, + ], + }, + TestVector { + key: [ + 0xa2, 0x4a, 0x5b, 0x4b, 0x0c, 0x62, 0xe0, 0xfb, 0x6f, 0x01, 0xdb, 0x56, 0x7c, 0x33, + 0x3e, 0x12, 0x82, 0xe3, 0x70, 0xa6, 0x6f, 0x16, 0x8a, 0xe7, 0xf7, 0x7a, 0x3f, 0x16, + 0xaf, 0x40, 0x8d, 0x12, + ], + description: [ + 0xe1, 0x9b, 0xad, 0xe1, 0x9a, 0xaf, 0x39, 0xc7, 0x92, 0xc4, 0x87, 0xc8, 0x8b, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9a, 0xbb, 0xe1, 0x9b, 0x97, 0xc6, 0x89, 0xc4, 0xb1, 0xc8, 0xa1, + 0xc7, 0xad, 0xc7, 0x8a, 0xe1, 0x9a, 0xb4, 0xe1, 0x9a, 0xa4, 0xc5, 0x99, 0xe1, 0x9b, + 0xa5, 0xcd, 0xb7, 0xc6, 0xa5, 0xc3, 0xb6, 0xe1, 0x9b, 0x9a, 0xe1, 0x9b, 0xab, 0xc5, + 0x9a, 0x4d, 0xe1, 0x9b, 0x81, 0xe1, 0x9b, 0x8a, 0xc2, 0xbe, 0xc5, 0x88, 0xc6, 0xbd, + 0xe2, 0xb1, 0xb8, 0xe2, 0xb1, 0xbb, 0xc5, 0x8d, 0xc2, 0xbc, 0xc6, 0x81, 0xc5, 0x9c, + 0xe2, 0xb1, 0xb5, 0xc8, 0x95, 0x6d, 0xc3, 0x9b, 0xc2, 0xb3, 0x36, 0xc4, 0x88, 0xc6, + 0xbf, 0xc7, 0xb6, 0xe1, 0x9b, 0xad, 0xc7, 0x8e, 0xe1, 0x9b, 0xa9, 0x69, 0xc3, 0xa5, + 0xe2, 0xb1, 0xb3, 0xc7, 0xbb, 0xc6, 0x9f, 0xc3, 0xa7, 0xc3, 0xbe, 0xce, 0x86, 0xc6, + 0xbd, 0xc6, 0x95, 0xc7, 0xa2, 0xc7, 0xbf, 0xc7, 0xad, 0xc4, 0x93, 0xc6, 0xb6, 0xc3, + 0x8b, 0xe2, 0xb1, 0xbb, 0xc3, 0x96, 0xc8, 0xaa, 0xc7, 0xa9, 0xc8, 0x8e, 0xc2, 0xb9, + 0xc8, 0x99, 0xc3, 0x93, 0xe1, 0x9b, 0x9c, 0xc2, 0xac, 0xc7, 0xbc, 0xc3, 0xb6, 0xc2, + 0xa7, 0xc3, 0xa9, 0xcd, 0xbc, 0xe2, 0xb1, 0xbf, 0xe1, 0x9a, 0xb1, 0xc2, 0xb8, 0xc3, + 0xb9, 0xe1, 0x9b, 0x9e, 0xc7, 0x88, 0xc5, 0x9e, 0xc6, 0xb9, 0xc4, 0x9e, 0xc6, 0x8e, + 0x3e, 0xc8, 0x93, 0x74, 0x37, 0xe2, 0xb1, 0xb2, 0x58, 0xcd, 0xbe, 0xc6, 0x9a, 0x5c, + 0xc8, 0x94, 0xe1, 0x9a, 0xb6, 0xc8, 0x90, 0xc5, 0x95, 0xe2, 0xb1, 0xa6, 0x23, 0xc5, + 0xa2, 0xc3, 0x9c, 0xe2, 0xb1, 0xb4, 0xc4, 0x94, 0xc3, 0x97, 0xc6, 0x9f, 0xc3, 0x92, + 0xcd, 0xbd, 0xc4, 0xbe, 0xc5, 0xba, 0xc6, 0xb0, 0x77, 0xc7, 0xba, 0xc5, 0xb0, 0xc3, + 0x9b, 0xc5, 0xbf, 0xc7, 0xa3, 0xc3, 0xad, 0xc6, 0xbf, 0xc3, 0xbe, 0xc5, 0xab, 0xc7, + 0xb9, 0xe1, 0x9b, 0xa9, 0xc5, 0xb3, 0xe1, 0x9a, 0xac, 0xe1, 0x9a, 0xa4, 0xc5, 0x9e, + 0xc2, 0xa7, 0xcd, 0xbe, 0x4e, 0xe2, 0xb1, 0xb5, 0xc4, 0xb8, 0xe1, 0x9a, 0xbd, 0xe1, + 0x9b, 0x83, 0xe2, 0xb1, 0xa2, 0xc6, 0xa4, 0xc6, 0xa6, 0xc7, 0xbc, 0xe1, 0x9b, 0x82, + 0x44, 0xe1, 0x9a, 0xa4, 0xc3, 0xb3, 0xc5, 0xb1, 0xc3, 0xa5, 0xc7, 0xaa, 0x5b, 0xc6, + 0x9c, 0xc7, 0x92, 0x2f, 0xc6, 0x86, 0xe1, 0x9b, 0xa5, 0xe1, 0x9a, 0xb5, 0x44, 0xc7, + 0xb1, 0xc4, 0xac, 0xc8, 0xae, 0xe1, 0x9a, 0xa1, 0xc8, 0xaa, 0xc5, 0x9a, 0xc3, 0xac, + 0xc8, 0xac, 0xe1, 0x9b, 0xa3, 0xc5, 0xab, 0xc7, 0x98, 0xe1, 0x9b, 0x93, 0x6e, 0xc7, + 0x8a, 0xc4, 0x9f, 0xe1, 0x9b, 0x9b, 0xc7, 0x86, 0xe2, 0xb1, 0xb8, 0xc6, 0xaa, 0xc8, + 0xa1, 0xc2, 0xbf, 0xc3, 0x97, 0xcd, 0xbd, 0xc8, 0x99, 0xc4, 0x98, 0xc3, 0x88, 0x3f, + 0x4a, 0xc7, 0x99, 0xc4, 0x8a, 0xc7, 0x9a, 0xc5, 0xa9, 0xc7, 0xb5, 0xc7, 0x9b, 0xc5, + 0xb1, 0xc5, 0xbf, 0xc7, 0x81, 0xc8, 0xb2, 0xc9, 0x89, 0xc5, 0xa4, 0xc8, 0x82, 0xc6, + 0x91, 0xe1, 0x9a, 0xa8, 0xc7, 0xac, 0x6c, 0x64, 0xc4, 0x86, 0xc8, 0x8b, 0xc5, 0x99, + 0xc6, 0x9a, 0xc3, 0x83, 0xc6, 0x8e, 0xc3, 0x9a, 0xc7, 0xa9, 0xc3, 0xb3, 0xe1, 0x9b, + 0x8a, 0xc7, 0x94, 0xc7, 0xbb, 0xe1, 0x9a, 0xbb, 0xc6, 0xb4, 0xc6, 0xaf, 0xe1, 0x9b, + 0xa8, 0xc2, 0xa1, 0x24, 0xe1, 0x9b, 0xab, 0xc8, 0xbb, 0xc3, 0xba, 0xe1, 0x9a, 0xb9, + 0xc8, 0x92, 0xc8, 0xb2, 0xc5, 0xa6, 0xc5, 0xb3, 0xc4, 0x8d, 0xc5, 0xad, 0xc5, 0xa0, + 0xc3, 0x9c, 0xe1, 0x9b, 0xae, 0xc7, 0xb2, 0xc4, 0x9b, 0xc6, 0xbb, 0xc5, 0xb0, 0xc7, + 0xbb, 0xc7, 0xba, 0xc5, 0xb7, 0xc8, 0xa4, 0x5a, + ], + asset_id: [ + 0x0f, 0x1a, 0x21, 0x20, 0x6c, 0x80, 0xdb, 0x63, 0x73, 0xde, 0x95, 0x66, 0xe9, 0x06, + 0xf1, 0x87, 0xe5, 0xea, 0x72, 0x84, 0x10, 0x86, 0x13, 0x86, 0x31, 0x77, 0x51, 0x0c, + 0xee, 0x14, 0xd7, 0xb1, + ], + }, + TestVector { + key: [ + 0xbe, 0xb4, 0x9a, 0x61, 0x01, 0x0b, 0x35, 0x51, 0xbc, 0x5c, 0xb2, 0xdb, 0xbc, 0xa6, + 0x0b, 0x20, 0xb5, 0x31, 0x6e, 0x42, 0x21, 0xdc, 0x9c, 0xed, 0xb8, 0xc3, 0xc4, 0x62, + 0xc1, 0xca, 0xcd, 0x02, + ], + description: [ + 0xc3, 0xa0, 0x26, 0xc8, 0xb0, 0xc3, 0x82, 0xc3, 0xb6, 0xc4, 0xa3, 0xc6, 0x85, 0xc3, + 0x8f, 0xc9, 0x8a, 0xc4, 0x99, 0xc8, 0xb8, 0xc6, 0xaa, 0xc4, 0xa4, 0xe1, 0x9b, 0x99, + 0xc6, 0x98, 0xe1, 0x9b, 0x99, 0xc6, 0x8a, 0x3c, 0xe1, 0x9b, 0x89, 0xc6, 0xa8, 0xc6, + 0xb4, 0x33, 0xe1, 0x9b, 0xa1, 0xc6, 0xb7, 0xcd, 0xb2, 0xc6, 0xbc, 0xc7, 0x86, 0xc6, + 0x9d, 0xc5, 0xac, 0xc2, 0xb7, 0xc6, 0x8a, 0xc7, 0xa5, 0xc3, 0x95, 0x35, 0xc3, 0x86, + 0x44, 0xc3, 0x89, 0xc5, 0xa1, 0xe1, 0x9b, 0xaf, 0xc6, 0xae, 0x41, 0xc4, 0x99, 0xc3, + 0xa8, 0x45, 0xe2, 0xb1, 0xb5, 0xc3, 0x83, 0x5f, 0x37, 0xc7, 0xbf, 0xe1, 0x9a, 0xa8, + 0xc7, 0x8f, 0xc5, 0x92, 0x7e, 0xc3, 0xad, 0xe2, 0xb1, 0xb9, 0xe1, 0x9a, 0xa9, 0xc6, + 0xa3, 0xc7, 0xbf, 0xcd, 0xb1, 0xc7, 0xb6, 0xe1, 0x9b, 0xa4, 0xe1, 0x9a, 0xb1, 0xe1, + 0x9a, 0xb8, 0x41, 0xc7, 0x90, 0xc5, 0x8e, 0xe1, 0x9b, 0xad, 0xc3, 0xb8, 0xc6, 0xae, + 0xc5, 0x9d, 0xc3, 0xb3, 0xc3, 0xbb, 0xc5, 0x97, 0xc7, 0x8f, 0xc8, 0xa4, 0xe1, 0x9b, + 0xb0, 0x63, 0x39, 0xe2, 0xb1, 0xa0, 0xc3, 0xbc, 0xc3, 0x97, 0xc8, 0x88, 0x5a, 0x30, + 0xc6, 0xb0, 0xe1, 0x9b, 0xa6, 0xc6, 0xbb, 0xc6, 0x86, 0xc6, 0xb8, 0xc6, 0x88, 0xe1, + 0x9a, 0xbc, 0xc5, 0xbb, 0xc5, 0xaa, 0xcd, 0xb6, 0xc6, 0xa0, 0xe2, 0xb1, 0xb7, 0xc3, + 0x8b, 0xc7, 0xa5, 0xc7, 0x9c, 0xe1, 0x9b, 0xa8, 0xe1, 0x9b, 0x82, 0xc6, 0xb4, 0xc8, + 0xa1, 0xc3, 0xb2, 0x77, 0xc3, 0xaf, 0xc2, 0xb9, 0xc6, 0x8d, 0xe2, 0xb1, 0xbf, 0xc4, + 0xb8, 0x33, 0xc3, 0xa4, 0xc8, 0xa5, 0xc7, 0xb5, 0xc7, 0x94, 0xc2, 0xaa, 0xc2, 0xbd, + 0x40, 0xe1, 0x9a, 0xba, 0xc8, 0x80, 0xc6, 0x9c, 0xc4, 0x96, 0x32, 0xe1, 0x9a, 0xb8, + 0xc3, 0xa2, 0xc7, 0xb1, 0xc4, 0x94, 0xc7, 0x88, 0xcd, 0xb4, 0xc4, 0x8d, 0x49, 0xc4, + 0xbd, 0xe1, 0x9a, 0xb4, 0xc7, 0x88, 0xe1, 0x9b, 0xac, 0xc4, 0x9a, 0xcd, 0xbe, 0xc5, + 0x96, 0xc8, 0x92, 0xe1, 0x9b, 0xaf, 0xc9, 0x89, 0xc5, 0xb5, 0x2f, 0x41, 0xcd, 0xbe, + 0xc4, 0x9d, 0xc3, 0x86, 0xc2, 0xbb, 0x25, 0xc3, 0xaa, 0xc3, 0x86, 0xc4, 0x97, 0xc8, + 0x9f, 0xcd, 0xb5, 0xc6, 0xb9, 0xc4, 0x83, 0x35, 0xe1, 0x9b, 0x9b, 0xc4, 0xa0, 0xc4, + 0x89, 0xc8, 0xa8, 0xc4, 0x84, 0xc4, 0xba, 0xc3, 0x80, 0xc4, 0xb4, 0x53, 0xc7, 0x81, + 0xc9, 0x85, 0xc6, 0xbc, 0xcd, 0xbb, 0xc6, 0xa8, 0xc5, 0x92, 0xce, 0x87, 0xe1, 0x9b, + 0x88, 0x34, 0xc8, 0xbc, 0xc6, 0xae, 0xc3, 0xbe, 0xc4, 0x9d, 0xc8, 0x81, 0xc4, 0xa4, + 0x60, 0xc7, 0x93, 0xce, 0x86, 0xc7, 0x94, 0xc7, 0x84, 0x78, 0xc8, 0x82, 0xcd, 0xb0, + 0xc6, 0xa4, 0xc6, 0x8a, 0x65, 0xc7, 0xba, 0xc6, 0xb7, 0xc4, 0xae, 0xc9, 0x82, 0xc5, + 0xaf, 0xc4, 0x84, 0xc8, 0x96, 0xc7, 0xb6, 0xc2, 0xb1, 0xc5, 0xaf, 0xc3, 0xac, 0xe1, + 0x9b, 0xa9, 0xc4, 0x87, 0x43, 0xc8, 0x84, 0xc9, 0x82, 0xc7, 0xb3, 0x6a, 0xc5, 0x89, + 0xc3, 0xb4, 0xc8, 0xa0, 0xe1, 0x9b, 0x8d, 0xc7, 0xbd, 0xc2, 0xb3, 0xc3, 0x80, 0xc6, + 0xa6, 0xc4, 0x84, 0x69, 0xc7, 0xa7, 0xc5, 0xb5, 0xc7, 0x95, 0x21, 0xc4, 0xad, 0xe1, + 0x9b, 0xaf, 0xe1, 0x9a, 0xa8, 0xc5, 0x85, 0xc7, 0xa8, 0xc9, 0x8c, 0xc5, 0x96, 0xe2, + 0xb1, 0xa1, 0x33, 0xe1, 0x9b, 0xa2, 0xc3, 0xbc, 0x2e, 0x63, 0x2b, 0xc3, 0x9f, 0x7c, + 0xc6, 0xa4, 0xc6, 0xbf, 0xc8, 0x8d, 0xc5, 0xa8, 0xc5, 0xb5, 0xc5, 0x96, 0xe1, 0x9b, + 0x98, 0xc8, 0xb3, 0xc6, 0x90, 0xc3, 0xa6, 0x3d, 0xc9, 0x8e, 0xc8, 0xb4, 0xc7, 0xbf, + 0xc2, 0xa6, 0xe1, 0x9a, 0xad, 0x41, 0x5e, 0x40, + ], + asset_id: [ + 0x8e, 0x95, 0x38, 0x48, 0xf3, 0xbd, 0xa6, 0xcd, 0xc0, 0x11, 0xdf, 0xd6, 0xe0, 0x1e, + 0x9f, 0x45, 0x71, 0xf9, 0x2c, 0xa1, 0x29, 0x4f, 0xd2, 0x69, 0xff, 0x98, 0x2b, 0xd2, + 0x1a, 0xac, 0xa0, 0xbc, + ], + }, + TestVector { + key: [ + 0xb7, 0x0b, 0xb2, 0x77, 0xc0, 0x83, 0xf2, 0x95, 0x37, 0x6a, 0x02, 0xb3, 0x98, 0x76, + 0xae, 0x35, 0xfb, 0x26, 0x62, 0x3d, 0x9d, 0x6a, 0x55, 0xa5, 0x63, 0xf7, 0x85, 0xa6, + 0x5b, 0xc5, 0xa8, 0x27, + ], + description: [ + 0xe1, 0x9b, 0x96, 0xe1, 0x9a, 0xb1, 0xc7, 0xb2, 0xc4, 0xb1, 0xc9, 0x81, 0xc2, 0xbe, + 0xc6, 0x84, 0xc4, 0x91, 0xc7, 0xb1, 0xc5, 0x83, 0xc2, 0xa3, 0xce, 0x8c, 0xce, 0x8c, + 0xc8, 0x8d, 0xc5, 0xaa, 0xc7, 0xa1, 0xe1, 0x9b, 0x9f, 0xc8, 0x8a, 0xc6, 0xbc, 0xc8, + 0xa3, 0xc8, 0xa8, 0xe1, 0x9b, 0x9b, 0xc8, 0xba, 0xc3, 0x88, 0xc7, 0x9f, 0x34, 0xc6, + 0xb9, 0xc2, 0xb9, 0xe1, 0x9a, 0xac, 0xc9, 0x88, 0xc5, 0x84, 0xc6, 0xa1, 0xe2, 0xb1, + 0xb6, 0xc2, 0xa8, 0xc6, 0xb4, 0xc7, 0xb3, 0x5a, 0x3d, 0xc7, 0xa1, 0xc8, 0x80, 0xc3, + 0x92, 0xc7, 0xa2, 0xc7, 0x93, 0xc7, 0xbb, 0xc8, 0xae, 0xc4, 0xb2, 0xc9, 0x83, 0xc6, + 0x88, 0xe2, 0xb1, 0xa2, 0xc8, 0x95, 0xc2, 0xb4, 0xc4, 0x86, 0xc5, 0xa5, 0x47, 0x70, + 0xe2, 0xb1, 0xb1, 0x62, 0xc3, 0x96, 0x5a, 0xe1, 0x9b, 0x97, 0xc5, 0x99, 0xc6, 0xb7, + 0xc3, 0xaa, 0xc5, 0x9d, 0xc7, 0x85, 0xc2, 0xa1, 0xc4, 0x93, 0xe1, 0x9a, 0xb8, 0xc3, + 0x8b, 0xe1, 0x9a, 0xad, 0xc7, 0xb3, 0xc7, 0x9a, 0xc7, 0xac, 0xe2, 0xb1, 0xaa, 0xc7, + 0xac, 0xc6, 0x91, 0xc2, 0xa9, 0xc5, 0xba, 0xc5, 0xa7, 0xc7, 0x9f, 0xc3, 0xad, 0xc8, + 0x81, 0xc8, 0x88, 0xc4, 0x86, 0xc9, 0x8d, 0xe1, 0x9b, 0xaf, 0xe1, 0x9b, 0xa1, 0xe2, + 0xb1, 0xb6, 0xc8, 0x8a, 0xc8, 0xa4, 0xc2, 0xaa, 0xe1, 0x9b, 0x9e, 0xc5, 0xa2, 0xc7, + 0x98, 0xc6, 0x93, 0xc4, 0xa8, 0xe1, 0x9b, 0x80, 0x2c, 0xc3, 0x8e, 0x25, 0x51, 0xe2, + 0xb1, 0xa7, 0xc8, 0xb3, 0xc3, 0xa4, 0xcd, 0xb6, 0xe2, 0xb1, 0xae, 0xc5, 0xb0, 0xe2, + 0xb1, 0xaa, 0xc7, 0xae, 0xc7, 0x8f, 0xc7, 0x9b, 0xc8, 0xa5, 0xc6, 0x9f, 0xc8, 0x8e, + 0x2e, 0x5a, 0xe1, 0x9a, 0xb9, 0xc2, 0xba, 0xc7, 0x8f, 0xc6, 0x90, 0xe1, 0x9a, 0xa9, + 0xc4, 0x85, 0xe1, 0x9b, 0x9f, 0x45, 0x3c, 0xc4, 0xbf, 0xc2, 0xa6, 0xc7, 0x9d, 0xe2, + 0xb1, 0xa8, 0xc7, 0x97, 0xc2, 0xbd, 0xc6, 0x8d, 0xcd, 0xb0, 0xc9, 0x83, 0x4a, 0xc8, + 0x80, 0xce, 0x89, 0xc9, 0x8f, 0xc3, 0xbb, 0xc4, 0xa7, 0xc7, 0x8c, 0x39, 0x7e, 0xc7, + 0x8f, 0xc5, 0xaa, 0x5a, 0xc3, 0x88, 0xc8, 0x93, 0xe1, 0x9b, 0xa6, 0xc5, 0x9e, 0xc8, + 0xaa, 0xc5, 0x90, 0x2e, 0xc8, 0xac, 0xe2, 0xb1, 0xb8, 0x7d, 0xc5, 0x9d, 0xc6, 0xaf, + 0xc8, 0x9d, 0xcd, 0xbe, 0xe2, 0xb1, 0xac, 0xc2, 0xbd, 0xc6, 0x9a, 0xc8, 0xb0, 0xe2, + 0xb1, 0xbc, 0xe1, 0x9b, 0x83, 0x29, 0x44, 0xe1, 0x9b, 0x9d, 0xc4, 0x87, 0xc6, 0x99, + 0xc7, 0xb6, 0xe1, 0x9b, 0x90, 0xcd, 0xb5, 0x3b, 0xc8, 0x92, 0xc6, 0x80, 0xc8, 0xa7, + 0xc9, 0x8e, 0xc2, 0xa8, 0xc7, 0x8b, 0xc2, 0xb1, 0xc5, 0xb4, 0xe2, 0xb1, 0xbf, 0xe1, + 0x9b, 0x86, 0xe1, 0x9a, 0xb8, 0x46, 0xe1, 0x9b, 0x81, 0x55, 0xc7, 0xa2, 0x26, 0xc5, + 0x99, 0x37, 0xe1, 0x9a, 0xa5, 0xc3, 0x93, 0xc7, 0x94, 0x6f, 0xe2, 0xb1, 0xba, 0xc7, + 0x86, 0xc2, 0xa9, 0xc5, 0x87, 0xc6, 0x9e, 0xc3, 0xae, 0xc8, 0xa7, 0xc3, 0x8c, 0x30, + 0xc7, 0x82, 0xc7, 0xaf, 0xc5, 0xa6, 0x77, 0xe1, 0x9b, 0x80, 0x5c, 0xcd, 0xbd, 0xc2, + 0xb5, 0xc7, 0x8f, 0x3c, 0xc3, 0x97, 0xc2, 0xb3, 0x58, 0xc6, 0x84, 0xc7, 0x86, 0xc6, + 0xaa, 0x61, 0xc5, 0x8c, 0xc5, 0xa1, 0xe2, 0xb1, 0xbf, 0xe1, 0x9b, 0xb0, 0xc3, 0x96, + 0xc8, 0x9e, 0xc8, 0xbb, 0xe1, 0x9a, 0xa0, 0xc6, 0x9d, 0xc4, 0xb3, 0xc8, 0x91, 0xc8, + 0xb2, 0xc8, 0xa5, 0xc8, 0x81, 0xc5, 0x80, 0xc8, 0x93, 0x62, 0x30, 0xe1, 0x9b, 0xa6, + 0xc5, 0x93, 0xc6, 0x81, 0xe1, 0x9a, 0xb3, 0x72, 0xc8, 0xa8, 0xc5, 0x90, 0xc8, 0x85, + 0xc3, 0x81, 0xc4, 0x97, 0xe1, 0x9b, 0x92, 0x5a, + ], + asset_id: [ + 0x08, 0xfe, 0xbb, 0x02, 0x39, 0x9f, 0x3d, 0x81, 0x83, 0x8b, 0x51, 0xbf, 0x9a, 0xb5, + 0x35, 0xe9, 0x5b, 0xba, 0x0f, 0x19, 0x9a, 0xda, 0x1c, 0x26, 0x65, 0xd4, 0x39, 0x4e, + 0xa0, 0xb2, 0xa7, 0x02, + ], + }, + TestVector { + key: [ + 0x70, 0x0d, 0xc0, 0x7a, 0xea, 0x5b, 0x17, 0xb5, 0xc0, 0x2b, 0xe3, 0x8c, 0x71, 0x1c, + 0x5d, 0x6d, 0x38, 0x13, 0xa4, 0x5e, 0xc2, 0x30, 0xda, 0x29, 0xfb, 0x37, 0x3c, 0x56, + 0x8c, 0x10, 0x44, 0x20, + ], + description: [ + 0xc3, 0x92, 0xe1, 0x9b, 0x95, 0xe1, 0x9a, 0xbf, 0xc4, 0xbc, 0x42, 0xc3, 0x88, 0xc7, + 0xb1, 0x42, 0xc8, 0xb4, 0xc4, 0x8b, 0xc4, 0xa9, 0xc4, 0xbe, 0xc2, 0xa4, 0xc2, 0xa3, + 0xc8, 0xaf, 0xc4, 0x87, 0xc4, 0xaa, 0xc3, 0x94, 0xcd, 0xb0, 0xc8, 0x87, 0xc5, 0xaa, + 0x3d, 0xc2, 0xbb, 0xc7, 0x9c, 0xc3, 0xb1, 0xc2, 0xb9, 0xc8, 0x94, 0xc4, 0x93, 0x5e, + 0xe1, 0x9b, 0xa1, 0xc8, 0x91, 0xc7, 0xb7, 0x41, 0x46, 0x44, 0xc4, 0xac, 0xc6, 0x83, + 0xc5, 0xbe, 0xc3, 0xa7, 0xc8, 0x9a, 0xe1, 0x9b, 0x86, 0xc3, 0xa5, 0xc3, 0x9f, 0xc6, + 0xb5, 0xe1, 0x9b, 0xa8, 0xe2, 0xb1, 0xbc, 0xc6, 0xaa, 0xe1, 0x9a, 0xa1, 0xc3, 0x81, + 0xce, 0x87, 0xc3, 0x8c, 0xc6, 0xa0, 0xe1, 0x9a, 0xa7, 0x38, 0xc4, 0x98, 0xc4, 0x99, + 0xc2, 0xbd, 0xc3, 0xa4, 0xc3, 0xab, 0xc4, 0xa7, 0xe1, 0x9a, 0xa3, 0xcd, 0xb4, 0x7b, + 0xe1, 0x9a, 0xb7, 0xc4, 0xbb, 0xe2, 0xb1, 0xb3, 0xe2, 0xb1, 0xa7, 0xc6, 0x97, 0xc3, + 0x9f, 0xc3, 0x91, 0xce, 0x8c, 0xc3, 0x84, 0xc7, 0xac, 0xcd, 0xb1, 0xe2, 0xb1, 0xb9, + 0xe2, 0xb1, 0xac, 0xc9, 0x87, 0xc3, 0x9a, 0xc7, 0xb9, 0xc5, 0x96, 0xc7, 0x8e, 0xc4, + 0x8e, 0xc7, 0xbb, 0xc4, 0x9b, 0xe1, 0x9b, 0x9c, 0xc4, 0xad, 0xc7, 0x81, 0xc4, 0xa4, + 0x39, 0xc6, 0x81, 0xc6, 0x89, 0xc7, 0xa9, 0xc2, 0xa3, 0xe2, 0xb1, 0xac, 0xc9, 0x80, + 0x51, 0xcd, 0xbd, 0xc6, 0xb8, 0xc9, 0x81, 0xc5, 0x93, 0xc8, 0xa0, 0x5d, 0xc4, 0x9c, + 0xc6, 0x90, 0x35, 0xc4, 0xb7, 0xc8, 0x9a, 0xc5, 0x90, 0xc8, 0x94, 0xc8, 0x95, 0xc8, + 0x92, 0xc9, 0x8c, 0xc4, 0xb5, 0x49, 0xc6, 0xbe, 0xc9, 0x84, 0xc2, 0xbf, 0xc6, 0xbb, + 0xc2, 0xab, 0xe1, 0x9b, 0xac, 0xc6, 0x87, 0x6a, 0xc6, 0xbc, 0xc4, 0xae, 0xe1, 0x9b, + 0x81, 0xc4, 0xb3, 0xe2, 0xb1, 0xb4, 0xc3, 0x96, 0x2f, 0xc4, 0x94, 0xc7, 0x8c, 0xc3, + 0xb2, 0xc2, 0xab, 0xc5, 0x80, 0xc5, 0xac, 0xe2, 0xb1, 0xad, 0xc4, 0x9c, 0xc4, 0xae, + 0xc7, 0xb7, 0x7d, 0xe1, 0x9b, 0x9d, 0xe1, 0x9a, 0xbd, 0xc4, 0xb3, 0xcd, 0xb3, 0xc2, + 0xa6, 0xe1, 0x9a, 0xbc, 0x33, 0xe2, 0xb1, 0xb8, 0xc7, 0xa8, 0xe1, 0x9a, 0xa1, 0xe1, + 0x9b, 0xad, 0xc5, 0xac, 0xce, 0x8a, 0xc4, 0x94, 0xc3, 0x80, 0xc7, 0xb4, 0xc7, 0xa9, + 0xc9, 0x84, 0xc2, 0xb1, 0xc5, 0x9c, 0xc7, 0x88, 0xe2, 0xb1, 0xb6, 0xcd, 0xb0, 0xc5, + 0x93, 0xc2, 0xb7, 0xe1, 0x9b, 0x8e, 0xe1, 0x9a, 0xa4, 0xc4, 0x87, 0xc4, 0x8c, 0xc6, + 0x92, 0xc3, 0xa9, 0xc5, 0xa7, 0xc7, 0x96, 0xc3, 0xbd, 0xc4, 0x83, 0xc3, 0xb4, 0x44, + 0xc3, 0x96, 0xc2, 0xb3, 0x7b, 0xe1, 0x9b, 0x8d, 0xc6, 0x86, 0xc6, 0x89, 0x61, 0xc7, + 0x90, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x94, 0xc6, 0xb5, 0xc7, 0xae, 0xe1, 0x9b, 0x8f, + 0xc7, 0xa6, 0xc8, 0xac, 0xc5, 0x92, 0xc5, 0xb3, 0xc5, 0xb3, 0xc8, 0x92, 0xc3, 0x8e, + 0xc4, 0x93, 0xc3, 0xb0, 0xc4, 0x9b, 0xc4, 0x8c, 0xc3, 0x83, 0xce, 0x89, 0xc6, 0x9b, + 0x79, 0xc2, 0xa5, 0xc7, 0xa9, 0xc4, 0xa3, 0xc2, 0xa2, 0xc3, 0x90, 0xc6, 0x9e, 0xc6, + 0x9d, 0xe1, 0x9a, 0xbb, 0xc4, 0x8c, 0xc5, 0xa8, 0xc8, 0xb2, 0xc3, 0xac, 0x5e, 0xc8, + 0xb2, 0x38, 0xc7, 0xa0, 0xc4, 0x9e, 0xc5, 0x8f, 0xc6, 0xa9, 0xe1, 0x9a, 0xb1, 0xe1, + 0x9b, 0x84, 0xcd, 0xbe, 0x61, 0xc7, 0x87, 0xce, 0x85, 0xc4, 0x89, 0xc8, 0x96, 0xc8, + 0xa3, 0xc8, 0x96, 0xc3, 0xab, 0xc6, 0xae, 0xce, 0x88, 0xe1, 0x9a, 0xbf, 0xc5, 0x91, + 0xe1, 0x9b, 0xab, 0xc7, 0x96, 0x33, 0xc3, 0xab, 0xe2, 0xb1, 0xb9, 0xe2, 0xb1, 0xac, + 0xe2, 0xb1, 0xbb, 0xe2, 0xb1, 0xae, 0xc2, 0xbf, + ], + asset_id: [ + 0xda, 0x5b, 0xdf, 0x78, 0xe8, 0x94, 0xa9, 0x67, 0xb8, 0x2b, 0xfe, 0xc3, 0x50, 0x04, + 0x41, 0x5e, 0xe1, 0xc8, 0xc3, 0xf2, 0x66, 0x22, 0xa2, 0xc2, 0x0c, 0xf5, 0x13, 0x9b, + 0x79, 0xf1, 0x08, 0xba, + ], + }, + TestVector { + key: [ + 0xf3, 0x2c, 0x7a, 0x80, 0xb6, 0x83, 0x45, 0xb2, 0x38, 0xc7, 0x73, 0x34, 0x67, 0xba, + 0x6c, 0xd9, 0x7c, 0xcd, 0xf4, 0xfd, 0x21, 0x29, 0x48, 0x13, 0x1b, 0xfb, 0xc4, 0x06, + 0x19, 0x68, 0x73, 0x26, + ], + description: [ + 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xb3, 0xc4, 0x8f, 0xe1, 0x9b, 0x97, 0x23, 0xe1, 0x9b, + 0xaf, 0x70, 0xc6, 0x9f, 0xc8, 0x82, 0xc4, 0x9c, 0xc7, 0x96, 0xc5, 0x81, 0xc3, 0x90, + 0xc5, 0xaf, 0xc6, 0x81, 0x33, 0xc8, 0xb2, 0x46, 0xc8, 0xba, 0x65, 0xcd, 0xb6, 0xe2, + 0xb1, 0xb7, 0xc8, 0xae, 0x5a, 0xc3, 0x87, 0xc6, 0xb3, 0xc6, 0x9f, 0x3d, 0xc3, 0x8a, + 0xc2, 0xb2, 0xc6, 0xab, 0xe1, 0x9b, 0x90, 0xc8, 0xbb, 0xe2, 0xb1, 0xab, 0xc3, 0x9f, + 0xc7, 0xb9, 0x67, 0xe2, 0xb1, 0xba, 0xe1, 0x9b, 0x88, 0xc4, 0x91, 0xc5, 0x9a, 0xe1, + 0x9b, 0x86, 0xe2, 0xb1, 0xbf, 0xc5, 0x9c, 0xc5, 0xad, 0x7d, 0xe2, 0xb1, 0xb1, 0xc4, + 0x9e, 0xc6, 0x90, 0xc5, 0x8b, 0xc4, 0xa3, 0xc5, 0x8c, 0xc3, 0xaf, 0xc4, 0x90, 0xc4, + 0xb2, 0x76, 0xc8, 0xbe, 0x33, 0xc9, 0x85, 0xc5, 0x80, 0xc7, 0x98, 0x6b, 0xe1, 0x9a, + 0xa8, 0x5e, 0xc4, 0xa3, 0xe1, 0x9b, 0x9c, 0xc7, 0x87, 0xc4, 0xbd, 0xce, 0x89, 0xc8, + 0xb4, 0x50, 0x3d, 0xc7, 0xa7, 0xc6, 0x97, 0xe1, 0x9b, 0xac, 0xc3, 0xb4, 0xe2, 0xb1, + 0xbc, 0xc6, 0x9f, 0xc4, 0xb5, 0xc5, 0xb7, 0xe1, 0x9a, 0xac, 0xc7, 0xa1, 0xe1, 0x9a, + 0xbe, 0xe2, 0xb1, 0xbb, 0xc6, 0x94, 0xc7, 0x90, 0xe1, 0x9b, 0x82, 0xe1, 0x9b, 0x80, + 0xc6, 0x98, 0xc4, 0x9f, 0xc7, 0xac, 0xc6, 0xab, 0xc5, 0xb2, 0x48, 0x6e, 0xc2, 0xa5, + 0xc4, 0x8c, 0xc9, 0x83, 0xc9, 0x86, 0x73, 0x29, 0x6b, 0xc3, 0xbd, 0xc2, 0xbf, 0xc4, + 0x9b, 0xe1, 0x9a, 0xbf, 0xc7, 0xbe, 0xe1, 0x9b, 0x83, 0xe2, 0xb1, 0xab, 0xc7, 0x8d, + 0xe2, 0xb1, 0xa2, 0x57, 0xc5, 0x84, 0xc6, 0xbc, 0xe1, 0x9b, 0xaf, 0xc5, 0xa3, 0xc8, + 0x8f, 0x25, 0xe2, 0xb1, 0xa3, 0x6d, 0x35, 0xc8, 0xae, 0x34, 0xe2, 0xb1, 0xb9, 0xe2, + 0xb1, 0xad, 0xc3, 0xb6, 0x71, 0xce, 0x84, 0xc8, 0x92, 0xc5, 0xa7, 0xc6, 0xb9, 0xce, + 0x87, 0xc4, 0xb8, 0xe1, 0x9b, 0xa8, 0xe1, 0x9b, 0x89, 0x76, 0xc4, 0xaf, 0xc4, 0x85, + 0xc2, 0xac, 0xc4, 0xbd, 0x7c, 0xc4, 0xba, 0xc4, 0x80, 0xc4, 0xa0, 0xc9, 0x82, 0xc3, + 0xb3, 0xe1, 0x9b, 0x9e, 0xc2, 0xaf, 0xc3, 0x86, 0x7e, 0xc6, 0xa0, 0xc4, 0x8d, 0xc6, + 0x8a, 0xc2, 0xba, 0xc4, 0xbd, 0xe1, 0x9b, 0x84, 0x75, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, + 0xbe, 0xc7, 0xa1, 0xc7, 0x90, 0xcd, 0xbb, 0x29, 0xc5, 0xa4, 0xc4, 0xb8, 0xc4, 0xbd, + 0xc9, 0x87, 0xc4, 0x9a, 0xc6, 0xa2, 0xe2, 0xb1, 0xa3, 0xc5, 0xae, 0xc2, 0xb4, 0xc5, + 0x89, 0xc7, 0x93, 0xc2, 0xa9, 0xc4, 0x9c, 0xe1, 0x9a, 0xa9, 0xc9, 0x81, 0xc6, 0x88, + 0xc3, 0x95, 0xc6, 0xb5, 0x56, 0x6b, 0x69, 0xc4, 0x86, 0xc4, 0xa5, 0xc4, 0xb3, 0xc3, + 0x85, 0xe2, 0xb1, 0xb0, 0xc4, 0x8e, 0x38, 0x5e, 0x3c, 0xc7, 0xb1, 0xc8, 0xa1, 0xc5, + 0x84, 0xc6, 0x85, 0xc8, 0xb9, 0xc6, 0x96, 0xc8, 0x94, 0xc3, 0x98, 0xc5, 0xb6, 0xc8, + 0x9a, 0xc8, 0x97, 0xc3, 0xa4, 0xc3, 0x81, 0xc3, 0xa9, 0x5c, 0xc7, 0xb7, 0xe1, 0x9b, + 0xac, 0xc8, 0x90, 0x2c, 0xe1, 0x9b, 0xa2, 0xc6, 0xb8, 0xc7, 0x93, 0xc4, 0x9e, 0xc4, + 0xbd, 0xc4, 0x90, 0xe1, 0x9a, 0xb7, 0xc9, 0x85, 0xc7, 0x9f, 0xc4, 0xbf, 0xc5, 0xba, + 0xc2, 0xa9, 0xe1, 0x9b, 0x9f, 0x76, 0xc3, 0xa3, 0xc8, 0xa6, 0xc5, 0x8c, 0xc6, 0xa0, + 0xc9, 0x8d, 0xc3, 0xa0, 0xc8, 0xa7, 0x2c, 0xc6, 0x80, 0xc8, 0xbf, 0x75, 0x2b, 0xc7, + 0xbe, 0xc5, 0xb5, 0xe1, 0x9b, 0x87, 0xc3, 0xbe, 0xcd, 0xba, 0xe1, 0x9b, 0x8f, 0xc6, + 0x82, 0xc7, 0xa7, 0xe1, 0x9b, 0x87, 0x62, 0xc3, 0x95, 0xc4, 0xbf, 0xe1, 0x9b, 0xaf, + 0xc4, 0xb3, 0xc7, 0xaf, 0xc3, 0x95, 0xc7, 0x9f, + ], + asset_id: [ + 0x4f, 0x20, 0x3c, 0x3a, 0x6f, 0x5b, 0x58, 0xbb, 0x4b, 0x01, 0x14, 0xf0, 0x2c, 0x1f, + 0x4e, 0xbb, 0x78, 0x4a, 0xa3, 0xa3, 0x7e, 0x5d, 0xae, 0x4a, 0x27, 0xf0, 0xea, 0xcc, + 0xf6, 0x8b, 0xab, 0x29, + ], + }, + TestVector { + key: [ + 0x98, 0xee, 0xc6, 0xfb, 0xdc, 0xa2, 0x77, 0x2a, 0x2a, 0x6b, 0xf9, 0x2f, 0x17, 0x18, + 0xdf, 0x59, 0xba, 0xb2, 0x5f, 0xd1, 0x05, 0x4c, 0x57, 0xad, 0xae, 0x0d, 0x72, 0x20, + 0xbf, 0xcd, 0x06, 0x38, + ], + description: [ + 0xc8, 0xb4, 0x34, 0xc3, 0x8c, 0xc7, 0x89, 0xc7, 0x86, 0x5e, 0xc5, 0xbb, 0xc7, 0xba, + 0xe1, 0x9b, 0x96, 0x5d, 0xc5, 0x88, 0x52, 0xcd, 0xb1, 0xe1, 0x9b, 0xad, 0xce, 0x88, + 0xc7, 0x80, 0xc5, 0x91, 0xc6, 0xba, 0xc6, 0x8f, 0xc6, 0x81, 0xc7, 0xa8, 0xc6, 0xb1, + 0x6b, 0xc6, 0x8c, 0xc5, 0x8f, 0xe2, 0xb1, 0xb3, 0xc5, 0x95, 0xc5, 0xa3, 0xc7, 0xaa, + 0xc5, 0xb5, 0xc7, 0xbe, 0xc6, 0xb2, 0xc6, 0x8d, 0x61, 0x23, 0xe2, 0xb1, 0xb3, 0xc4, + 0xbb, 0xc5, 0x96, 0xc6, 0x91, 0xc7, 0x99, 0x60, 0x2c, 0xe1, 0x9b, 0x82, 0xce, 0x86, + 0xc8, 0x92, 0xc4, 0xa1, 0xc4, 0xa2, 0xc7, 0xb4, 0x56, 0x23, 0xe1, 0x9b, 0xae, 0xc7, + 0x8d, 0xc3, 0xa0, 0xc6, 0xa4, 0xc4, 0x9b, 0xc9, 0x81, 0xc8, 0xb6, 0xe1, 0x9b, 0xa0, + 0xe2, 0xb1, 0xbc, 0xe1, 0x9b, 0x82, 0xc8, 0x98, 0xc3, 0xb7, 0xe1, 0x9b, 0x8b, 0xe1, + 0x9b, 0x80, 0xe1, 0x9a, 0xa5, 0x2a, 0xc3, 0x90, 0x5c, 0xc4, 0xb8, 0xc8, 0x9e, 0xc5, + 0x80, 0xc8, 0x9b, 0xe2, 0xb1, 0xaf, 0xc7, 0x9f, 0xc7, 0x97, 0xc3, 0x9d, 0xe1, 0x9b, + 0x9e, 0xc4, 0xaf, 0xc4, 0xb8, 0xc2, 0xb9, 0x3c, 0xc4, 0x9a, 0xc8, 0x80, 0xc6, 0x9d, + 0x2f, 0x47, 0xc6, 0xb0, 0xc6, 0xb4, 0xc7, 0xb9, 0xe2, 0xb1, 0xb6, 0xc8, 0xa5, 0xc7, + 0x91, 0xe1, 0x9b, 0x9d, 0xc6, 0x95, 0x74, 0xe1, 0x9b, 0x9b, 0xc4, 0xac, 0xc6, 0xa3, + 0xe1, 0x9b, 0xa8, 0xc4, 0x8d, 0xc6, 0x97, 0xc5, 0xb6, 0xc6, 0xb8, 0xe2, 0xb1, 0xa8, + 0xc2, 0xbb, 0xe1, 0x9b, 0x95, 0xc7, 0x91, 0xe1, 0x9a, 0xba, 0xc8, 0xbe, 0xc3, 0xa1, + 0xc2, 0xbf, 0xc6, 0x9d, 0xcd, 0xb2, 0x51, 0xc6, 0x8d, 0xe1, 0x9a, 0xb9, 0xc8, 0x8d, + 0xc5, 0xaf, 0xc4, 0xa9, 0xc6, 0xa4, 0xc5, 0x8b, 0xc6, 0xbd, 0xc3, 0xb6, 0xc4, 0x8d, + 0xc7, 0x80, 0xc6, 0x95, 0xc5, 0xb9, 0xc2, 0xae, 0xe1, 0x9a, 0xa4, 0x54, 0x69, 0xc3, + 0x9b, 0xc4, 0x8e, 0xc6, 0x9f, 0xc8, 0xb5, 0x65, 0xc5, 0x95, 0xcd, 0xb3, 0xc5, 0x9f, + 0xc7, 0xae, 0xc4, 0xa4, 0xc3, 0x83, 0xc3, 0x82, 0xe1, 0x9a, 0xa4, 0xc4, 0x93, 0xc7, + 0x88, 0x67, 0xc3, 0xaf, 0xc3, 0xb9, 0xc5, 0xb5, 0x46, 0xcd, 0xb1, 0x5e, 0x28, 0xe1, + 0x9a, 0xb6, 0xc6, 0x86, 0x67, 0xc3, 0xb9, 0xc5, 0xb2, 0xc5, 0x8c, 0xc4, 0xb5, 0xc3, + 0xba, 0xe1, 0x9a, 0xbe, 0xc6, 0x85, 0x5a, 0xcd, 0xb4, 0xe1, 0x9b, 0xa8, 0xc6, 0x86, + 0xc7, 0xb5, 0xc6, 0x83, 0xc3, 0x8d, 0xc4, 0xa0, 0xc7, 0x9d, 0xc6, 0xab, 0x57, 0xc4, + 0xa3, 0xc3, 0x9d, 0xc7, 0x88, 0x3f, 0xc8, 0x99, 0xc5, 0x98, 0xc4, 0x91, 0xe1, 0x9b, + 0x88, 0xe2, 0xb1, 0xa1, 0xc7, 0x97, 0xc5, 0x8d, 0xe1, 0x9a, 0xb8, 0xc8, 0xa8, 0xc2, + 0xac, 0x4d, 0xc6, 0xa2, 0xe2, 0xb1, 0xb8, 0x3f, 0xe2, 0xb1, 0xb8, 0xc8, 0xa4, 0xc7, + 0x98, 0xc7, 0x98, 0x63, 0xc6, 0xb3, 0xc5, 0x8f, 0xc8, 0x86, 0xc4, 0xbf, 0xe2, 0xb1, + 0xb8, 0xc8, 0xb6, 0xc4, 0x98, 0xc4, 0x8a, 0xc6, 0x93, 0xe1, 0x9b, 0x87, 0xc7, 0x93, + 0xc6, 0xbb, 0xc8, 0x84, 0xc7, 0x92, 0xc8, 0x97, 0xe2, 0xb1, 0xa2, 0xc6, 0x8b, 0xc5, + 0xa1, 0xc8, 0x8b, 0xc9, 0x8b, 0xc3, 0x9a, 0xe1, 0x9b, 0x81, 0xc2, 0xa2, 0xc6, 0x95, + 0xc8, 0x99, 0x38, 0xc4, 0xb2, 0x68, 0xc7, 0x83, 0xe1, 0x9a, 0xb2, 0xc4, 0xae, 0xc8, + 0x8d, 0xc5, 0xb6, 0xc5, 0x9e, 0x79, 0xc6, 0xa9, 0x45, 0xc6, 0x9f, 0xc7, 0x99, 0xc7, + 0x99, 0xe1, 0x9b, 0x9c, 0xe1, 0x9b, 0xa1, 0xc7, 0xbc, 0xc8, 0x88, 0xc6, 0xbe, 0xc4, + 0xb3, 0xc8, 0x90, 0x4c, 0xc8, 0xba, 0xc3, 0x9d, 0xe1, 0x9b, 0x8f, 0xe1, 0x9a, 0xb7, + 0xe2, 0xb1, 0xb6, 0xc4, 0x83, 0xc5, 0xa9, 0x5a, + ], + asset_id: [ + 0x61, 0xb6, 0x64, 0xff, 0x70, 0xb4, 0x5a, 0x10, 0x5a, 0x5e, 0x5e, 0x2a, 0x65, 0xbd, + 0x5b, 0x37, 0x7a, 0x0d, 0x89, 0xf0, 0x65, 0x6d, 0xb9, 0xe5, 0x72, 0x43, 0x2a, 0x3b, + 0x41, 0x09, 0xb8, 0xba, + ], + }, + TestVector { + key: [ + 0x3a, 0x86, 0x32, 0x5c, 0x89, 0x70, 0xca, 0x21, 0xb8, 0x3a, 0xb7, 0x59, 0x76, 0xa8, + 0xd8, 0x54, 0xff, 0xa0, 0xc7, 0x63, 0x1b, 0xd0, 0xf8, 0xa8, 0x8c, 0x0a, 0x09, 0x89, + 0xbd, 0xb7, 0x75, 0x19, + ], + description: [ + 0xc4, 0xae, 0xc6, 0x83, 0xc3, 0xb4, 0xe1, 0x9b, 0xa2, 0xc6, 0x93, 0xc9, 0x86, 0xc4, + 0xa7, 0xe2, 0xb1, 0xb9, 0xc8, 0x9b, 0x3d, 0xcd, 0xbd, 0x3f, 0x54, 0xc8, 0xa9, 0xce, + 0x84, 0xc8, 0x87, 0xc4, 0x8d, 0xe1, 0x9b, 0x83, 0xc6, 0xac, 0xe1, 0x9b, 0x9f, 0xc5, + 0x83, 0xc7, 0x89, 0x66, 0xc4, 0x86, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, 0x8f, 0xc6, 0x99, + 0xc5, 0xb0, 0xc4, 0x8e, 0xc4, 0x8b, 0xc7, 0x93, 0xc5, 0x9b, 0xc5, 0xb7, 0xc8, 0x89, + 0xc3, 0x9b, 0x6e, 0xc5, 0xbd, 0xc2, 0xbe, 0xc4, 0x9e, 0x5f, 0xe1, 0x9b, 0x9a, 0xc4, + 0x86, 0xe2, 0xb1, 0xa2, 0x7c, 0xcd, 0xb7, 0xc3, 0xab, 0x43, 0xc7, 0xa7, 0xe2, 0xb1, + 0xa0, 0xcd, 0xbc, 0xc8, 0x90, 0xc7, 0x9f, 0xc7, 0xb4, 0xc8, 0x9d, 0xc4, 0x9e, 0xe1, + 0x9a, 0xb3, 0x38, 0xc6, 0xaa, 0xe2, 0xb1, 0xb4, 0xc8, 0x97, 0xc8, 0x96, 0xc6, 0x90, + 0xc7, 0xaf, 0xc7, 0x97, 0x77, 0x5f, 0xc4, 0x9d, 0xc7, 0xa9, 0xc8, 0x9f, 0xe1, 0x9a, + 0xb0, 0xc3, 0x90, 0x35, 0x49, 0xc4, 0xb9, 0xc5, 0x96, 0xcd, 0xbc, 0xc7, 0xb3, 0xc8, + 0xa4, 0x37, 0x46, 0xc2, 0xba, 0xe1, 0x9b, 0x89, 0xc5, 0x86, 0xc6, 0x84, 0xc5, 0x9b, + 0xe1, 0x9b, 0x93, 0xc7, 0x81, 0xc5, 0x8d, 0x29, 0xc4, 0x9c, 0xc6, 0xbe, 0xc4, 0xad, + 0xc8, 0x83, 0xe1, 0x9b, 0x81, 0xc4, 0xa2, 0xc8, 0x9d, 0xc4, 0x9c, 0xc7, 0xae, 0xc7, + 0x80, 0x35, 0xe1, 0x9a, 0xa6, 0xe1, 0x9a, 0xac, 0xc4, 0xb7, 0xe1, 0x9b, 0xa2, 0xc7, + 0xa6, 0xe2, 0xb1, 0xad, 0xc5, 0x89, 0xc6, 0x95, 0xc4, 0x98, 0xc8, 0x8d, 0xe2, 0xb1, + 0xa3, 0xc6, 0xb3, 0xc7, 0xaf, 0xe1, 0x9a, 0xb7, 0xc4, 0xb8, 0xe2, 0xb1, 0xa8, 0xc8, + 0xa9, 0xc8, 0xba, 0xc3, 0x97, 0xe1, 0x9b, 0x89, 0xc3, 0x93, 0xc5, 0x9a, 0xc4, 0x8b, + 0xc5, 0xa6, 0xc4, 0xad, 0xc5, 0xb3, 0xe2, 0xb1, 0xb5, 0x66, 0xc6, 0x9c, 0x40, 0xc2, + 0xa1, 0xc8, 0x96, 0xe2, 0xb1, 0xa3, 0xc3, 0xbf, 0xc5, 0xa5, 0xcd, 0xb0, 0xc8, 0xb8, + 0xc6, 0xa1, 0x33, 0xe1, 0x9a, 0xb1, 0xe1, 0x9a, 0xbd, 0x33, 0xc3, 0xa2, 0xc6, 0xb7, + 0xc4, 0xb9, 0xc7, 0xba, 0x30, 0xc5, 0x9f, 0xc8, 0xad, 0xc5, 0x9c, 0xc4, 0xa5, 0xc2, + 0xbc, 0xce, 0x88, 0x4c, 0xc8, 0x9f, 0x7c, 0xc5, 0xbd, 0xc5, 0xa2, 0xe2, 0xb1, 0xae, + 0xc3, 0xb2, 0xc7, 0xb6, 0xc4, 0x96, 0xc5, 0xaa, 0xc6, 0x87, 0xc5, 0xb6, 0xe1, 0x9b, + 0x9a, 0xc3, 0xb1, 0xcd, 0xbb, 0xc6, 0xbd, 0xcd, 0xb5, 0x70, 0xce, 0x88, 0xc4, 0x8a, + 0xc2, 0xa8, 0xc4, 0xa6, 0xc2, 0xb0, 0xc4, 0xaf, 0xc6, 0xb5, 0xcd, 0xbd, 0x34, 0xc4, + 0x9a, 0xc4, 0x93, 0xc8, 0xbb, 0xc5, 0x99, 0xc7, 0x9d, 0xc2, 0xb4, 0xc9, 0x86, 0xe1, + 0x9b, 0x91, 0xc4, 0x9b, 0xc8, 0x94, 0xc7, 0xae, 0xe1, 0x9b, 0x9c, 0xc8, 0xab, 0xe1, + 0x9b, 0xa9, 0xc3, 0x99, 0xc8, 0x9c, 0xc3, 0x83, 0x7a, 0xe1, 0x9b, 0x87, 0xe1, 0x9a, + 0xad, 0xc5, 0x8c, 0xe1, 0x9a, 0xaa, 0xc7, 0xbe, 0x5f, 0xc8, 0xb5, 0xc6, 0x99, 0xe1, + 0x9b, 0xa7, 0xc7, 0xb1, 0xc6, 0x90, 0xc7, 0xb0, 0xc4, 0xac, 0xc3, 0x90, 0x77, 0xc7, + 0xb8, 0xc6, 0xa9, 0xc7, 0xa7, 0xce, 0x88, 0xe1, 0x9a, 0xa1, 0x36, 0xc4, 0xbb, 0xc4, + 0xa1, 0xc8, 0x8c, 0xc3, 0xb4, 0xc2, 0xa2, 0xe1, 0x9a, 0xb9, 0x68, 0xc7, 0x9a, 0xc5, + 0x9e, 0x75, 0xcd, 0xb5, 0xe1, 0x9b, 0x98, 0xc7, 0x82, 0xce, 0x88, 0xe1, 0x9b, 0x9c, + 0xc5, 0xa6, 0xc7, 0x98, 0xc5, 0xa7, 0x30, 0xc8, 0xbf, 0xcd, 0xb6, 0xc5, 0xbe, 0xc7, + 0x97, 0x6e, 0xc6, 0xab, 0xc8, 0x92, 0xc8, 0x88, 0xc5, 0x87, 0xc7, 0x95, 0xc3, 0x97, + 0xc4, 0xbb, 0xc7, 0x9c, 0xc5, 0x80, 0xc2, 0xb6, + ], + asset_id: [ + 0x8b, 0x7d, 0xde, 0x16, 0x1b, 0xad, 0x63, 0xb2, 0x3f, 0x2a, 0xa4, 0x2d, 0x23, 0xa3, + 0x7b, 0x5e, 0x0e, 0x33, 0x61, 0xa9, 0x85, 0x97, 0x47, 0x96, 0xf7, 0x10, 0xef, 0x46, + 0x4e, 0xa7, 0xa0, 0xaf, + ], + }, + TestVector { + key: [ + 0x4f, 0x50, 0xd9, 0x58, 0xf6, 0xb6, 0x79, 0x91, 0x33, 0x48, 0x49, 0xd1, 0x85, 0xf1, + 0xa3, 0x92, 0x0e, 0xfb, 0x46, 0x35, 0x1c, 0x70, 0x7d, 0xc3, 0x7d, 0x3e, 0xa9, 0xa1, + 0x79, 0xc0, 0x76, 0x27, + ], + description: [ + 0xc7, 0xa3, 0xc8, 0x83, 0xc6, 0xa9, 0xc6, 0x9c, 0xe1, 0x9b, 0x95, 0xc3, 0x94, 0xc2, + 0xa1, 0xc2, 0xa5, 0xc5, 0x92, 0xe2, 0xb1, 0xbe, 0xe1, 0x9a, 0xa9, 0x60, 0xc6, 0xbc, + 0x51, 0xe1, 0x9a, 0xa9, 0xe1, 0x9a, 0xb9, 0xe1, 0x9a, 0xae, 0xc8, 0xb1, 0xcd, 0xb7, + 0xc8, 0x9a, 0xc8, 0xa2, 0xc6, 0x91, 0xc5, 0x90, 0xc5, 0x8a, 0xc8, 0x94, 0xe1, 0x9a, + 0xbe, 0xce, 0x88, 0xc6, 0xb8, 0xc8, 0x8e, 0xc2, 0xbe, 0xce, 0x86, 0xc5, 0xb4, 0xe1, + 0x9a, 0xa1, 0xc5, 0xbe, 0xc2, 0xa1, 0x39, 0xc8, 0xbd, 0xc4, 0xbb, 0xc8, 0x96, 0xe1, + 0x9b, 0x98, 0x72, 0xc3, 0x98, 0xc8, 0x9e, 0x33, 0x40, 0xc3, 0x9c, 0xe1, 0x9b, 0x97, + 0xc8, 0x8e, 0xc7, 0xab, 0x4b, 0xc6, 0xa1, 0xc6, 0x91, 0xc3, 0x90, 0xc7, 0xa5, 0xc4, + 0x88, 0xc5, 0x96, 0xc5, 0xb2, 0xc9, 0x84, 0xc6, 0xa6, 0xe1, 0x9a, 0xb0, 0xe2, 0xb1, + 0xad, 0xc3, 0x99, 0x45, 0xc3, 0x9d, 0xc3, 0xaf, 0xc6, 0xb0, 0xc5, 0x9c, 0xc4, 0x83, + 0xc4, 0x86, 0xc5, 0x91, 0xc7, 0xbe, 0xc4, 0x98, 0xc4, 0xa8, 0x62, 0xc4, 0x9b, 0xc3, + 0xb0, 0xe1, 0x9a, 0xa3, 0xc6, 0xab, 0xc4, 0x95, 0xc8, 0x99, 0xc5, 0xa8, 0xe1, 0x9b, + 0x92, 0xc8, 0xae, 0x4d, 0xe1, 0x9a, 0xae, 0xcd, 0xb2, 0xc3, 0x95, 0xc4, 0x8f, 0xc6, + 0xa9, 0xc5, 0x83, 0xc2, 0xaf, 0xc2, 0xb6, 0x5b, 0xc9, 0x8b, 0xe1, 0x9a, 0xae, 0xc3, + 0x9e, 0xc5, 0xa1, 0xcd, 0xb0, 0xc6, 0x87, 0xe1, 0x9a, 0xaa, 0xe1, 0x9a, 0xb8, 0xc7, + 0x94, 0xc6, 0xbc, 0xc7, 0xb4, 0xe1, 0x9b, 0x98, 0xc3, 0xbf, 0xc4, 0xbc, 0xcd, 0xb6, + 0xc4, 0x9b, 0xc4, 0xb7, 0xc2, 0xa9, 0xc7, 0x8e, 0xc3, 0xa0, 0xc3, 0x82, 0xc8, 0x9a, + 0xce, 0x89, 0xc6, 0xac, 0xc4, 0x94, 0xc3, 0x84, 0xc7, 0xb5, 0xce, 0x85, 0xc8, 0xa8, + 0xc3, 0x8c, 0xc8, 0x8d, 0xc2, 0xa8, 0xc8, 0x9a, 0xc9, 0x8e, 0xc8, 0xaa, 0xc3, 0x90, + 0xc7, 0x9d, 0xc8, 0xb3, 0xc4, 0x92, 0xc6, 0x83, 0x77, 0xc5, 0xa8, 0x52, 0xc4, 0xa4, + 0xc8, 0x91, 0xc6, 0xbd, 0xe1, 0x9a, 0xb6, 0xc7, 0xa8, 0xc3, 0xbf, 0xc7, 0x93, 0xe1, + 0x9b, 0x87, 0xe1, 0x9b, 0xad, 0x6f, 0xc8, 0xaa, 0xc6, 0xbb, 0xc6, 0xa3, 0xc7, 0xbe, + 0xc5, 0xb4, 0xe1, 0x9a, 0xab, 0xc7, 0xaa, 0xc7, 0x88, 0xc8, 0x85, 0xc6, 0xaa, 0xce, + 0x8c, 0xe1, 0x9b, 0x94, 0xc5, 0xb4, 0xc3, 0xa5, 0x66, 0x45, 0xc7, 0x80, 0xc5, 0x8f, + 0xc2, 0xb4, 0xc9, 0x8f, 0x39, 0xc3, 0x90, 0xc5, 0xa8, 0xc3, 0x91, 0xc6, 0x9e, 0xc8, + 0xb5, 0x72, 0xc6, 0x99, 0x5d, 0x2b, 0xc8, 0xb4, 0xc7, 0xbb, 0x79, 0xc5, 0xb8, 0xc6, + 0xb9, 0xc7, 0x9d, 0xc7, 0xb0, 0xe1, 0x9b, 0xa9, 0xe1, 0x9b, 0x92, 0xcd, 0xb6, 0xce, + 0x85, 0x42, 0xc2, 0xba, 0xc7, 0x99, 0xc7, 0x9c, 0xc5, 0x89, 0xc6, 0xbc, 0x29, 0xc2, + 0xb4, 0xc3, 0x8a, 0xc8, 0x81, 0xc3, 0x84, 0xc8, 0x92, 0xc3, 0x97, 0xe1, 0x9b, 0x91, + 0xc8, 0xa7, 0xc6, 0x99, 0xc4, 0x88, 0xe1, 0x9b, 0x9e, 0xc5, 0xab, 0xce, 0x88, 0xc5, + 0x93, 0xcd, 0xb1, 0xe2, 0xb1, 0xbc, 0xc5, 0xa0, 0xe1, 0x9b, 0x83, 0xc9, 0x80, 0xc4, + 0xbb, 0x24, 0xc6, 0x90, 0xc3, 0x8c, 0xc7, 0xa0, 0xc8, 0x9d, 0xc3, 0x8a, 0xc4, 0xa0, + 0xc6, 0xac, 0x72, 0xe1, 0x9b, 0x82, 0xe1, 0x9a, 0xba, 0xc3, 0x8f, 0x6c, 0xe1, 0x9a, + 0xb4, 0xc4, 0xbe, 0xc4, 0xaf, 0xc4, 0x9a, 0xc5, 0xa7, 0x41, 0xe2, 0xb1, 0xbf, 0xe2, + 0xb1, 0xb3, 0xc5, 0x8a, 0xe1, 0x9b, 0xa7, 0xc3, 0xa0, 0xc5, 0xaf, 0xc9, 0x8e, 0x35, + 0x34, 0xc2, 0xa3, 0xc5, 0xa4, 0xc2, 0xb3, 0xcd, 0xb1, 0xc9, 0x85, 0xc4, 0xa3, 0xe1, + 0x9b, 0x9f, 0xe1, 0x9b, 0x84, 0xc7, 0xa6, 0x5a, + ], + asset_id: [ + 0x6e, 0x9c, 0x7f, 0x1a, 0x04, 0x56, 0x32, 0x4e, 0x21, 0x55, 0xab, 0x2b, 0x82, 0xd5, + 0x01, 0x11, 0x4a, 0x02, 0xc2, 0x93, 0x32, 0x96, 0x34, 0x29, 0x8e, 0x73, 0x8a, 0x62, + 0x62, 0x36, 0xb9, 0x9b, + ], + }, + TestVector { + key: [ + 0x42, 0x67, 0x81, 0x37, 0x2b, 0x07, 0xac, 0x22, 0x91, 0x58, 0x7f, 0x9f, 0x81, 0xb5, + 0x4f, 0x8b, 0x96, 0xb4, 0xc8, 0xdd, 0xf8, 0xcd, 0x5b, 0x0d, 0x7d, 0x21, 0xe7, 0xa7, + 0x46, 0xbb, 0x13, 0x3e, + ], + description: [ + 0xc2, 0xbd, 0x65, 0x3c, 0xe1, 0x9a, 0xb6, 0xe1, 0x9a, 0xa2, 0xc7, 0x9e, 0xe1, 0x9a, + 0xb5, 0x5f, 0xe1, 0x9b, 0x97, 0x65, 0xc2, 0xa4, 0xc8, 0xb9, 0xe1, 0x9a, 0xb8, 0xc7, + 0xbf, 0xc3, 0xb9, 0x52, 0x46, 0xc7, 0x9d, 0xc6, 0x9f, 0xe1, 0x9a, 0xbc, 0xc5, 0x9c, + 0xe2, 0xb1, 0xb1, 0xc6, 0x8b, 0xc2, 0xa3, 0xc4, 0xa8, 0xc8, 0x9e, 0xc6, 0xaa, 0xc3, + 0xa2, 0xc3, 0x84, 0xc3, 0x9d, 0xe1, 0x9b, 0x97, 0xc4, 0x81, 0xe2, 0xb1, 0xb0, 0xc5, + 0xb9, 0x29, 0xc9, 0x89, 0x60, 0xe1, 0x9a, 0xbd, 0x5c, 0xc4, 0xbe, 0xc4, 0xb4, 0xc7, + 0xa1, 0xc4, 0x93, 0xc4, 0x8c, 0xe1, 0x9a, 0xb9, 0xc2, 0xb0, 0xcd, 0xbd, 0xce, 0x8c, + 0xc7, 0x88, 0xc6, 0x8c, 0xc6, 0x93, 0xc5, 0xa8, 0xe2, 0xb1, 0xa4, 0xc6, 0x84, 0x39, + 0xc5, 0x81, 0x53, 0xc4, 0xa9, 0xc2, 0xa7, 0xc4, 0x8f, 0xe1, 0x9a, 0xba, 0xc4, 0xaf, + 0xe1, 0x9b, 0x9d, 0xc6, 0xbb, 0xc2, 0xbc, 0xc7, 0x95, 0xc6, 0xb0, 0xe1, 0x9b, 0x8f, + 0x42, 0xc2, 0xbe, 0xc6, 0xa7, 0xc8, 0xbc, 0xcd, 0xb7, 0xc8, 0xa7, 0xc8, 0x8b, 0xc8, + 0xb7, 0xc6, 0xa1, 0xc4, 0x87, 0xc7, 0xa7, 0xc3, 0xb5, 0xe2, 0xb1, 0xa1, 0xc2, 0xb2, + 0xe1, 0x9b, 0xa5, 0xc5, 0x87, 0xe1, 0x9a, 0xb3, 0xc7, 0xb3, 0x7a, 0xc6, 0x8b, 0xc4, + 0xbe, 0xc4, 0x8e, 0x56, 0x2d, 0xc9, 0x84, 0xc4, 0x84, 0xc7, 0xa3, 0xe2, 0xb1, 0xb6, + 0x5e, 0x46, 0xc3, 0x8f, 0xc7, 0x94, 0xc5, 0xa7, 0xc8, 0xa2, 0xc4, 0xa0, 0xc5, 0xa1, + 0xe1, 0x9b, 0xa4, 0xe1, 0x9b, 0x9f, 0xc3, 0x87, 0xc3, 0xb4, 0xc3, 0x81, 0xc4, 0x86, + 0xc7, 0xb7, 0xc4, 0xb3, 0xc2, 0xb5, 0xc6, 0x8c, 0xc8, 0xa0, 0xc4, 0x9c, 0xc7, 0x9e, + 0x30, 0xcd, 0xb4, 0xc3, 0xb7, 0xe1, 0x9a, 0xb1, 0xe1, 0x9b, 0x86, 0xc5, 0xab, 0xc6, + 0xa3, 0xc3, 0x9c, 0xc7, 0xbe, 0xc3, 0xbf, 0xc2, 0xa1, 0xe1, 0x9b, 0x89, 0xe1, 0x9a, + 0xb8, 0xc6, 0xb7, 0xc6, 0x85, 0xc8, 0x93, 0xc3, 0x9f, 0xc7, 0xbe, 0x2e, 0xce, 0x88, + 0xc9, 0x86, 0xe2, 0xb1, 0xa6, 0xc3, 0x94, 0x58, 0xc5, 0x84, 0xc4, 0xa1, 0x7d, 0xc7, + 0x92, 0xe1, 0x9b, 0x81, 0xc7, 0xbc, 0xe1, 0x9b, 0x9d, 0xc4, 0xb8, 0xe1, 0x9a, 0xa9, + 0xe1, 0x9a, 0xa1, 0xc3, 0x8d, 0xc6, 0xb6, 0x51, 0xc4, 0xbc, 0xc5, 0x91, 0xe1, 0x9a, + 0xb4, 0xc9, 0x8d, 0xe1, 0x9a, 0xaf, 0xc9, 0x84, 0xc7, 0xb7, 0xc6, 0x96, 0x38, 0xc3, + 0x89, 0xc6, 0xa6, 0xe1, 0x9b, 0x98, 0xc3, 0x83, 0xc3, 0x99, 0xc6, 0x99, 0xe2, 0xb1, + 0xa1, 0xcd, 0xbd, 0xc3, 0x8d, 0xc9, 0x8f, 0x3a, 0xc4, 0x81, 0xe1, 0x9a, 0xac, 0x4b, + 0xc6, 0x94, 0xc6, 0x9c, 0xe2, 0xb1, 0xaf, 0xe1, 0x9a, 0xb8, 0xc8, 0xb1, 0x6f, 0x70, + 0xc3, 0xae, 0xe1, 0x9b, 0x8a, 0xc7, 0xab, 0xc5, 0xad, 0x57, 0xc3, 0xb2, 0x55, 0xc6, + 0xb1, 0xc6, 0x84, 0xc3, 0xa4, 0x61, 0xc8, 0x9e, 0xc2, 0xb6, 0xc7, 0x8f, 0xc8, 0x95, + 0x30, 0x29, 0xe1, 0x9a, 0xb8, 0xc6, 0xa5, 0xc8, 0x97, 0xc7, 0xa9, 0xc9, 0x8d, 0xc8, + 0xa3, 0xc8, 0x98, 0xc2, 0xb4, 0xc7, 0x8d, 0xc7, 0x8b, 0xc7, 0xbc, 0xe2, 0xb1, 0xbf, + 0xc2, 0xa1, 0x2b, 0xe1, 0x9a, 0xac, 0xc2, 0xb4, 0xc4, 0xa6, 0xc2, 0xa5, 0x6e, 0xc5, + 0xa5, 0xe1, 0x9b, 0x8f, 0x2d, 0xe1, 0x9a, 0xae, 0x2c, 0x61, 0xe1, 0x9b, 0xb0, 0xc7, + 0x84, 0xc4, 0x8e, 0x44, 0xc7, 0xb0, 0xce, 0x86, 0xc6, 0x97, 0xc4, 0xa6, 0xc3, 0x94, + 0xc6, 0xbb, 0x2e, 0xc5, 0x95, 0xc4, 0x86, 0xc8, 0x8f, 0xc7, 0x94, 0xc9, 0x8b, 0x7b, + 0xc4, 0x9c, 0xc5, 0xb2, 0xc5, 0x8a, 0xc5, 0x8d, 0x4a, 0xe1, 0x9a, 0xbe, 0xc8, 0x90, + 0xc8, 0x9f, 0x70, 0xe1, 0x9b, 0x93, 0xc7, 0xbe, + ], + asset_id: [ + 0x54, 0xf5, 0xc9, 0x10, 0x86, 0xc5, 0x19, 0xcf, 0x5a, 0xa9, 0xc7, 0x4f, 0x07, 0x7c, + 0x07, 0xbc, 0xf7, 0xd7, 0x24, 0x35, 0x20, 0xe1, 0x4d, 0x2e, 0x27, 0x12, 0x79, 0x7c, + 0x74, 0xd2, 0x0e, 0x22, + ], + }, + TestVector { + key: [ + 0x76, 0xf4, 0x9c, 0xf8, 0xa3, 0x19, 0x21, 0x85, 0x61, 0x6a, 0x9a, 0x0d, 0xa0, 0xc7, + 0x6e, 0xc2, 0xc2, 0x75, 0x61, 0x59, 0xbc, 0xe1, 0x86, 0xa1, 0x86, 0x2b, 0x6e, 0x6e, + 0x59, 0x44, 0x2d, 0x11, + ], + description: [ + 0xc4, 0xaa, 0xe1, 0x9a, 0xb7, 0xc3, 0x99, 0xc6, 0x90, 0xc6, 0x96, 0xc3, 0x9b, 0x54, + 0xc9, 0x8c, 0xc8, 0x91, 0xc7, 0xba, 0xc2, 0xb9, 0xc7, 0x9b, 0xe2, 0xb1, 0xa8, 0xc3, + 0xa5, 0xc3, 0x87, 0xc9, 0x80, 0xc7, 0xbe, 0xe1, 0x9b, 0x97, 0xc5, 0x92, 0xc7, 0xa5, + 0xc8, 0x8e, 0xc7, 0x97, 0xe2, 0xb1, 0xb9, 0x49, 0xc8, 0xb4, 0xc7, 0xa8, 0x5e, 0xc5, + 0x8d, 0x5d, 0xc8, 0xbb, 0xce, 0x86, 0x29, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0x91, 0xc3, + 0x94, 0x46, 0xc8, 0x9a, 0xce, 0x84, 0xc7, 0x96, 0xe2, 0xb1, 0xb8, 0xc8, 0xa7, 0xc8, + 0xbb, 0xe2, 0xb1, 0xac, 0xe2, 0xb1, 0xbf, 0xc5, 0x80, 0xc2, 0xae, 0xc3, 0x85, 0xc6, + 0xaf, 0xc8, 0xbe, 0xc6, 0xb9, 0xe2, 0xb1, 0xb4, 0x66, 0xe1, 0x9a, 0xa1, 0x36, 0xc5, + 0x95, 0xc3, 0xb5, 0xe2, 0xb1, 0xbe, 0xc7, 0x89, 0xe1, 0x9a, 0xa5, 0xc7, 0xa0, 0x34, + 0xc9, 0x87, 0xe2, 0xb1, 0xac, 0xe2, 0xb1, 0xa9, 0xc7, 0x99, 0xc3, 0xa4, 0xe1, 0x9b, + 0x89, 0xc3, 0x9e, 0xc9, 0x89, 0xc3, 0xa5, 0xc3, 0xb1, 0xc3, 0x9e, 0xe2, 0xb1, 0xb4, + 0xc8, 0x87, 0x69, 0xc8, 0x81, 0xc3, 0x81, 0xc8, 0x9c, 0xc7, 0x80, 0xe1, 0x9b, 0x9a, + 0xe1, 0x9b, 0xa4, 0x49, 0xc7, 0x97, 0x6e, 0x6f, 0xe1, 0x9b, 0x80, 0xc7, 0xa5, 0x5d, + 0x3d, 0xc3, 0xab, 0xc5, 0x88, 0xc3, 0x8c, 0xe2, 0xb1, 0xb5, 0xc4, 0xa2, 0xe2, 0xb1, + 0xa7, 0xe1, 0x9b, 0xad, 0xc6, 0xb0, 0xe1, 0x9b, 0x8f, 0xc6, 0x97, 0xe2, 0xb1, 0xb8, + 0xc2, 0xa9, 0xc7, 0xb0, 0xe2, 0xb1, 0xbd, 0x65, 0xc3, 0xb3, 0xe2, 0xb1, 0xaa, 0xc6, + 0xb3, 0xc5, 0x96, 0xc5, 0xbd, 0xe2, 0xb1, 0xb6, 0xe2, 0xb1, 0xb5, 0xe1, 0x9a, 0xb2, + 0xc5, 0xb5, 0x61, 0x28, 0x58, 0xc5, 0x80, 0x74, 0x5b, 0xc8, 0xa8, 0xe2, 0xb1, 0xb7, + 0x30, 0x6a, 0xc3, 0xaa, 0xe1, 0x9b, 0x9e, 0xc8, 0x9b, 0x33, 0x54, 0xc6, 0xad, 0xc6, + 0x99, 0xc4, 0x9b, 0xc7, 0x87, 0xe1, 0x9b, 0xb0, 0xc7, 0x9a, 0xc7, 0x99, 0xc6, 0xa4, + 0xc6, 0xb8, 0xe2, 0xb1, 0xb7, 0xc7, 0x93, 0x60, 0xe1, 0x9b, 0x9e, 0xc7, 0x98, 0xc8, + 0xa8, 0xce, 0x86, 0xe1, 0x9a, 0xb2, 0xc6, 0xaf, 0xc3, 0xb7, 0xc3, 0x81, 0xc7, 0x89, + 0xc7, 0x93, 0x25, 0xc7, 0xaf, 0xc4, 0x9c, 0xe2, 0xb1, 0xba, 0xe1, 0x9b, 0x90, 0xe1, + 0x9b, 0xa8, 0xc7, 0xbe, 0xc3, 0xb9, 0xc7, 0xb4, 0xc5, 0xb1, 0xe2, 0xb1, 0xa3, 0xcd, + 0xb6, 0xc5, 0x8d, 0x76, 0xc5, 0xb9, 0xe2, 0xb1, 0xae, 0x4e, 0x36, 0xc8, 0xa1, 0x50, + 0xc6, 0x95, 0xc4, 0x84, 0xc8, 0x94, 0xe1, 0x9b, 0x9f, 0xc8, 0x9e, 0xc7, 0x85, 0xcd, + 0xb0, 0xc4, 0xb3, 0x58, 0xc6, 0x98, 0xc4, 0xb0, 0xc8, 0x99, 0xe2, 0xb1, 0xb6, 0xc5, + 0xa4, 0xc6, 0x84, 0xc6, 0xbd, 0xc6, 0x96, 0xe2, 0xb1, 0xb7, 0xc5, 0xb7, 0xc6, 0xaa, + 0xc8, 0x85, 0x70, 0xc7, 0xbe, 0xc4, 0xb4, 0xe1, 0x9a, 0xba, 0x30, 0xc8, 0xae, 0xe2, + 0xb1, 0xb3, 0x32, 0xc3, 0x89, 0xe2, 0xb1, 0xa1, 0xc3, 0x90, 0xc5, 0xba, 0xe1, 0x9b, + 0xa2, 0xc3, 0xb3, 0xe1, 0x9b, 0xa8, 0xce, 0x86, 0xc6, 0xb2, 0x29, 0x5e, 0xc8, 0xb7, + 0xc5, 0x8a, 0xc3, 0xa1, 0xc7, 0xac, 0xc5, 0x96, 0xc3, 0x8c, 0xc2, 0xaa, 0xc6, 0xb0, + 0xc8, 0x84, 0x5d, 0xc8, 0x8a, 0xc2, 0xaf, 0xc5, 0x90, 0x51, 0xe1, 0x9b, 0xa3, 0xc7, + 0x92, 0xc3, 0x9a, 0xc8, 0x81, 0xc8, 0xa5, 0x61, 0xc8, 0x95, 0xc7, 0x96, 0xe2, 0xb1, + 0xa3, 0xc8, 0xb5, 0xe1, 0x9a, 0xa6, 0xc4, 0xb1, 0xe1, 0x9b, 0xac, 0xc7, 0xaf, 0x2b, + 0xe1, 0x9b, 0x8b, 0xc4, 0xa0, 0xc7, 0xa1, 0xc7, 0xb6, 0xc6, 0x81, 0xc3, 0xb5, 0xe2, + 0xb1, 0xb4, 0xc2, 0xa1, 0xe2, 0xb1, 0xb2, 0x5a, + ], + asset_id: [ + 0x9d, 0xf4, 0x24, 0x6f, 0x24, 0x26, 0xa5, 0xd4, 0x87, 0xb1, 0xc9, 0x7d, 0x71, 0x92, + 0xf6, 0x90, 0x79, 0x85, 0x5d, 0x30, 0x08, 0xde, 0x89, 0x7b, 0xf0, 0x57, 0x06, 0xb4, + 0x5b, 0xe3, 0xe3, 0xae, + ], + }, + ] +} diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption.rs index 9501a79b1..f1c6126cc 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption.rs @@ -2192,9 +2192,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x09, 0xee, 0x7e, 0xf6, 0x3a, 0xb1, 0xcf, 0x24, 0x2b, 0xaa, 0x76, 0xfc, 0xbf, 0xfb, - 0xe5, 0x75, 0x5f, 0x13, 0x14, 0x2b, 0x38, 0xb1, 0xa0, 0x40, 0x4d, 0x7d, 0x5a, 0x3f, - 0x4f, 0x22, 0x1e, 0x96, + 0xba, 0x69, 0x9c, 0xe4, 0x21, 0x41, 0x85, 0x30, 0x94, 0xe2, 0x84, 0x00, 0x50, 0x17, + 0x2c, 0x3b, 0x94, 0x21, 0x3e, 0x86, 0x47, 0x3b, 0x5e, 0x2f, 0xdd, 0x70, 0x97, 0x80, + 0xbc, 0xca, 0x68, 0xb4, ], rho: [ 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, @@ -2314,9 +2314,9 @@ pub(crate) fn test_vectors() -> Vec { 0xfe, 0x3f, 0xbb, 0x0a, 0x4e, 0x48, ], ock: [ - 0x17, 0xeb, 0xb4, 0x82, 0xdf, 0x8d, 0x13, 0xc2, 0x0d, 0x9b, 0x4a, 0x03, 0x9f, 0x40, - 0x5a, 0x93, 0x69, 0x8a, 0xc2, 0x24, 0xf3, 0xea, 0x03, 0xfb, 0x55, 0x8d, 0x5b, 0x53, - 0x11, 0x46, 0xfb, 0xea, + 0xc6, 0x7c, 0x23, 0x33, 0xc3, 0xcf, 0x4a, 0xc4, 0x6e, 0xde, 0x34, 0xe3, 0xe3, 0xe0, + 0xdb, 0xff, 0x1e, 0x96, 0xb7, 0xa7, 0x8f, 0x16, 0xaa, 0xef, 0x1c, 0x74, 0xa3, 0xef, + 0x07, 0xc5, 0x97, 0x16, ], op: [ 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, @@ -2326,12 +2326,12 @@ pub(crate) fn test_vectors() -> Vec { 0xe0, 0xd2, 0x9b, 0x35, 0x9a, 0xc4, 0xfa, 0x2c, ], c_out: [ - 0x2d, 0x76, 0x57, 0x79, 0x67, 0x44, 0x5f, 0xb9, 0x17, 0xee, 0x72, 0xd3, 0x2d, 0x4b, - 0x75, 0x3b, 0x25, 0x10, 0xd8, 0x05, 0x5d, 0xec, 0x8b, 0xf1, 0x22, 0x0a, 0x75, 0xf0, - 0x65, 0xbd, 0x47, 0xe2, 0xcc, 0xb6, 0x03, 0x98, 0x84, 0x50, 0x23, 0x1b, 0xd3, 0x1c, - 0x15, 0x6f, 0xf2, 0xa7, 0x2a, 0xfd, 0x4a, 0x96, 0x0b, 0x6f, 0x6a, 0x78, 0x84, 0x65, - 0x13, 0x51, 0xe2, 0x4b, 0x47, 0x02, 0x87, 0xd5, 0x83, 0xba, 0x69, 0x71, 0x18, 0xec, - 0x07, 0xf6, 0x59, 0x2c, 0x4c, 0xd7, 0xcd, 0x6a, 0xc7, 0x7e, + 0xe4, 0xba, 0x0e, 0xa2, 0x92, 0x3b, 0x40, 0x19, 0xac, 0x8a, 0xbc, 0xd1, 0x9b, 0xe6, + 0x1c, 0x90, 0xf1, 0x8e, 0xef, 0xae, 0x87, 0xc4, 0xed, 0x8c, 0x76, 0x70, 0x85, 0xba, + 0xa8, 0x3b, 0x4d, 0x61, 0x0c, 0xf3, 0x63, 0x70, 0xda, 0x07, 0x90, 0x1e, 0xad, 0x6d, + 0x4f, 0x4b, 0x71, 0xdc, 0xae, 0x31, 0x1f, 0xa0, 0x36, 0x40, 0x6d, 0x64, 0x7b, 0x7e, + 0xe1, 0x41, 0x1e, 0xf5, 0xae, 0xe0, 0x34, 0x68, 0xb1, 0x09, 0x13, 0xc9, 0x90, 0xcb, + 0x61, 0x61, 0x22, 0xeb, 0xbe, 0x49, 0xda, 0x67, 0x81, 0xc2, ], asset: Some([ 0xa9, 0x71, 0x5e, 0x65, 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, @@ -2406,9 +2406,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x54, 0xb6, 0x99, 0x64, 0x13, 0x6b, 0x63, 0xd1, 0x7d, 0x62, 0x44, 0x1a, 0x69, 0x37, - 0x13, 0x9d, 0x2c, 0xe1, 0x4b, 0xb5, 0x5c, 0x42, 0x07, 0xfe, 0x74, 0xd7, 0x70, 0x83, - 0x53, 0x51, 0x5b, 0xa8, + 0x0a, 0x1f, 0x28, 0x15, 0xb7, 0xaf, 0xe2, 0x19, 0x06, 0x87, 0x15, 0xfc, 0x76, 0x6b, + 0x87, 0x2e, 0xf2, 0x17, 0x35, 0x43, 0xac, 0x81, 0x4c, 0x32, 0xb4, 0xb6, 0x9c, 0x9c, + 0x34, 0x5e, 0x46, 0x98, ], rho: [ 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, @@ -2528,9 +2528,9 @@ pub(crate) fn test_vectors() -> Vec { 0x49, 0xaa, 0x90, 0xe6, 0x02, 0xc8, ], ock: [ - 0x59, 0xf9, 0xcc, 0x26, 0x38, 0x4c, 0x6f, 0x73, 0xce, 0xa9, 0xb9, 0xe0, 0x94, 0x40, - 0xf8, 0xf0, 0x4c, 0x40, 0x25, 0xb5, 0x59, 0x04, 0x42, 0x3c, 0x35, 0x39, 0xc6, 0x6c, - 0x75, 0x11, 0x31, 0x23, + 0x2f, 0x88, 0x37, 0x27, 0xb5, 0x4d, 0x06, 0x25, 0xcf, 0xdc, 0x19, 0x5a, 0xce, 0x10, + 0xca, 0xc0, 0x26, 0x8a, 0xba, 0x3d, 0xe2, 0x8a, 0xd6, 0x08, 0x88, 0x06, 0x50, 0x6d, + 0x69, 0xc4, 0xdd, 0x8e, ], op: [ 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, @@ -2540,12 +2540,12 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0x3b, 0x57, 0xc3, 0x45, 0xa9, 0x87, 0x2f, ], c_out: [ - 0x21, 0xe3, 0xf8, 0x97, 0xe1, 0xb1, 0x36, 0xe1, 0x74, 0xd7, 0xae, 0x88, 0xd7, 0x85, - 0xa0, 0x61, 0xe6, 0x71, 0xef, 0xf1, 0x81, 0x98, 0x0a, 0x6f, 0xf5, 0x19, 0xb3, 0xbb, - 0x6b, 0xbd, 0xaf, 0xea, 0x9d, 0xf9, 0x92, 0xbc, 0xaa, 0xc0, 0x2b, 0xdb, 0xcd, 0x4d, - 0xb1, 0xc1, 0xd3, 0xf3, 0x2d, 0xef, 0xcd, 0xf7, 0xf4, 0xad, 0x54, 0x1b, 0x6b, 0xee, - 0xe8, 0x27, 0xdd, 0x43, 0x89, 0xb8, 0x57, 0xd1, 0x6d, 0xb8, 0x24, 0xe7, 0x72, 0xba, - 0x5a, 0xb5, 0xe2, 0x8d, 0xd6, 0xe9, 0x80, 0x82, 0x6b, 0xed, + 0x99, 0x96, 0x90, 0xd4, 0xcd, 0xd9, 0xe7, 0x6b, 0x07, 0x2c, 0x3c, 0x4c, 0x41, 0xbf, + 0xc7, 0x9a, 0xaa, 0xc6, 0x7f, 0xdc, 0x0f, 0x41, 0xe8, 0x0e, 0x95, 0x48, 0x80, 0x0e, + 0xef, 0xbc, 0x95, 0x74, 0xf1, 0x5d, 0x64, 0xa6, 0x9e, 0x44, 0x47, 0xc4, 0x5b, 0x07, + 0x0c, 0x6c, 0x9f, 0x50, 0x0a, 0xdd, 0xef, 0x6f, 0x57, 0x14, 0xa5, 0x76, 0x22, 0x1f, + 0x3f, 0xbc, 0x61, 0x22, 0x8d, 0x95, 0xc3, 0xac, 0xe4, 0x21, 0x4b, 0xb6, 0xcf, 0x5b, + 0xd9, 0x69, 0x84, 0xd7, 0x78, 0x96, 0x0d, 0xe9, 0x0c, 0x02, ], asset: Some([ 0xdf, 0xfd, 0x79, 0xa9, 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, @@ -2620,9 +2620,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x10, 0xb2, 0x33, 0xd2, 0x49, 0x94, 0x68, 0xe0, 0xb0, 0xdf, 0x47, 0x3d, 0x5a, 0x21, - 0xb9, 0x3f, 0x7d, 0x2b, 0x5d, 0x5f, 0x09, 0x95, 0xa9, 0x55, 0xd0, 0x86, 0x8a, 0x27, - 0x45, 0x3f, 0x96, 0x82, + 0xde, 0x2b, 0xfc, 0x89, 0x5b, 0xa8, 0xb5, 0x43, 0x03, 0x93, 0x43, 0x4e, 0x20, 0x92, + 0xce, 0xe7, 0x81, 0xe4, 0x00, 0x28, 0x5c, 0xc6, 0x66, 0xbc, 0x6c, 0x41, 0x89, 0xdb, + 0x2d, 0xda, 0x71, 0x92, ], rho: [ 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, @@ -2742,9 +2742,9 @@ pub(crate) fn test_vectors() -> Vec { 0xf1, 0xd7, 0xd3, 0x95, 0x8a, 0x54, ], ock: [ - 0xdb, 0x1e, 0xf1, 0x9a, 0xf6, 0xdd, 0x1b, 0x7b, 0xf0, 0x64, 0x89, 0xe7, 0xdb, 0x86, - 0xca, 0xae, 0x27, 0xf6, 0x70, 0x1e, 0x09, 0x16, 0x8c, 0x6e, 0x0d, 0x2b, 0x89, 0x78, - 0xdf, 0x14, 0xe0, 0x96, + 0x9c, 0xba, 0xd2, 0xf3, 0x8b, 0xf8, 0x8f, 0x39, 0x47, 0xce, 0xf6, 0x4d, 0xe7, 0xa6, + 0xf4, 0x3e, 0x4c, 0xbb, 0x41, 0xe6, 0xe0, 0x37, 0xf1, 0x42, 0x01, 0xae, 0xe8, 0xab, + 0xfd, 0xf8, 0xa2, 0x35, ], op: [ 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, @@ -2754,12 +2754,12 @@ pub(crate) fn test_vectors() -> Vec { 0x25, 0xec, 0xff, 0x47, 0x72, 0x16, 0x8c, 0x05, ], c_out: [ - 0x55, 0xdd, 0xba, 0xc4, 0x35, 0x64, 0x19, 0x54, 0xbd, 0xb1, 0xc9, 0x43, 0x4c, 0x36, - 0x79, 0x32, 0x19, 0x18, 0xbc, 0x1f, 0x29, 0x90, 0x7a, 0xc4, 0x24, 0x43, 0x55, 0x2d, - 0xfb, 0xe7, 0x05, 0xab, 0x26, 0x19, 0x1b, 0x4e, 0x2b, 0xae, 0xa4, 0xaa, 0xe0, 0x6d, - 0xa9, 0xf1, 0x38, 0x4e, 0x23, 0x7b, 0xee, 0xab, 0xb1, 0xa2, 0xd8, 0x22, 0x99, 0x5e, - 0xe7, 0xb9, 0x41, 0x0d, 0x6b, 0xe7, 0x59, 0x2a, 0xed, 0xa9, 0xf5, 0x2d, 0x56, 0xd8, - 0xc9, 0xf9, 0x3a, 0x0b, 0xe3, 0x8c, 0xfc, 0x8d, 0xc2, 0x94, + 0xf6, 0x25, 0xcd, 0x3d, 0x19, 0x97, 0xb0, 0xd3, 0xf2, 0x29, 0x5a, 0xac, 0xc0, 0x3a, + 0xe0, 0xc9, 0x47, 0x28, 0xb3, 0x3c, 0xc4, 0xf1, 0x6f, 0xd4, 0x28, 0xd6, 0x5f, 0x3c, + 0x78, 0x5e, 0x8c, 0x0b, 0xb4, 0x66, 0xc1, 0x33, 0xd4, 0x83, 0xdf, 0xc5, 0xb1, 0xb3, + 0x15, 0x1d, 0xa2, 0xd5, 0xf2, 0x4a, 0x2b, 0x32, 0x0d, 0x8e, 0x9c, 0xd3, 0x41, 0x5c, + 0x25, 0xb6, 0xf9, 0x76, 0x1f, 0x42, 0x70, 0x04, 0xce, 0xe5, 0x4f, 0x75, 0xf1, 0x25, + 0xbc, 0x50, 0x5e, 0xf6, 0x26, 0xef, 0xc9, 0xdd, 0x63, 0x66, ], asset: Some([ 0xa6, 0x33, 0x05, 0x44, 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, @@ -2834,9 +2834,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x7e, 0xfd, 0xf4, 0x17, 0xcf, 0xd6, 0x44, 0x7d, 0x96, 0x58, 0x1d, 0xd1, 0x7b, 0x82, - 0x12, 0xee, 0x53, 0x7b, 0x13, 0x4b, 0x05, 0xa5, 0x58, 0x67, 0x4a, 0x39, 0xe6, 0x66, - 0x97, 0xe6, 0x3a, 0x29, + 0x45, 0x37, 0x85, 0x3e, 0x18, 0xac, 0x2c, 0xe9, 0x37, 0x79, 0x8c, 0x9b, 0xce, 0xa9, + 0x80, 0x2d, 0x65, 0x00, 0x74, 0xdb, 0xd7, 0xe0, 0x6a, 0x48, 0x98, 0x03, 0x15, 0x30, + 0x78, 0xe9, 0x97, 0x0b, ], rho: [ 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, @@ -2956,9 +2956,9 @@ pub(crate) fn test_vectors() -> Vec { 0xcc, 0x22, 0xca, 0x1d, 0x09, 0xd5, ], ock: [ - 0xcf, 0x22, 0xd2, 0x83, 0x95, 0x98, 0x5d, 0x31, 0x6a, 0xf9, 0x50, 0x19, 0x21, 0xba, - 0xc1, 0x52, 0x57, 0x11, 0xbb, 0x3f, 0x3c, 0xc3, 0xc3, 0xc2, 0x82, 0xa3, 0xd1, 0x8e, - 0x43, 0xd4, 0x78, 0x05, + 0x97, 0x9b, 0x31, 0x5d, 0x3e, 0x1f, 0x5c, 0xa1, 0x8a, 0x92, 0x86, 0xd9, 0x2c, 0xc8, + 0x8e, 0x63, 0x62, 0x4b, 0x39, 0x9b, 0x29, 0x19, 0xbf, 0x4e, 0x67, 0xda, 0x7c, 0xd3, + 0x94, 0xf4, 0x5c, 0x49, ], op: [ 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, @@ -2968,12 +2968,12 @@ pub(crate) fn test_vectors() -> Vec { 0xaf, 0x2b, 0xd1, 0xa0, 0x8c, 0x67, 0xd9, 0x3f, ], c_out: [ - 0x7a, 0xe6, 0x91, 0xd9, 0xbc, 0xd5, 0x38, 0x42, 0x7b, 0x4f, 0x07, 0xe2, 0x38, 0x81, - 0x94, 0x18, 0xbb, 0xb8, 0x18, 0x31, 0x88, 0x89, 0x93, 0x08, 0xfd, 0x6a, 0xab, 0x2b, - 0xf4, 0xf0, 0x69, 0x9c, 0xc5, 0x61, 0x9c, 0x8d, 0x4f, 0xc9, 0x95, 0xc2, 0x11, 0x76, - 0xbf, 0xea, 0x13, 0xee, 0x04, 0x03, 0xc0, 0xce, 0x57, 0x4f, 0xc8, 0xfa, 0x16, 0x81, - 0xb3, 0x76, 0xcf, 0x33, 0xc9, 0xff, 0x27, 0xa5, 0xaa, 0x01, 0x58, 0x24, 0xe6, 0x78, - 0x6e, 0x16, 0xe3, 0x7b, 0x35, 0x5c, 0xf7, 0x54, 0x52, 0xdb, + 0x83, 0xf7, 0xa1, 0xda, 0x72, 0x4d, 0xd1, 0x54, 0xe7, 0xd9, 0x47, 0xc0, 0xfc, 0x83, + 0x42, 0x87, 0xf3, 0x3c, 0xd4, 0xb3, 0x4a, 0xfa, 0xc0, 0xda, 0x55, 0xe4, 0x37, 0xaf, + 0xae, 0x67, 0xa9, 0x9c, 0xbd, 0x89, 0x75, 0xc9, 0x54, 0xcf, 0x41, 0xaa, 0x1e, 0x9a, + 0x8f, 0x99, 0x98, 0x3d, 0x58, 0x6f, 0x5e, 0x35, 0x37, 0xda, 0xb7, 0x2a, 0xe1, 0x82, + 0x7a, 0xa5, 0xdf, 0xc9, 0xdd, 0xad, 0x06, 0x26, 0x78, 0x84, 0x6f, 0xf8, 0x09, 0x3d, + 0xfd, 0x15, 0xf6, 0x3d, 0x47, 0xe5, 0xa3, 0xbb, 0x74, 0x39, ], asset: Some([ 0x61, 0x16, 0xcf, 0xec, 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, @@ -3048,9 +3048,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0xf5, 0xc1, 0xcf, 0xbc, 0xb9, 0x2d, 0x34, 0xe4, 0x66, 0x1d, 0x58, 0x25, 0x42, 0xf7, - 0x0d, 0x05, 0x99, 0x09, 0x15, 0x20, 0xfe, 0x2a, 0xfa, 0xd8, 0xe8, 0x75, 0xca, 0x3b, - 0xcc, 0x70, 0x8a, 0x11, + 0x71, 0x00, 0xa7, 0x52, 0x93, 0xf4, 0xae, 0xfd, 0x89, 0xa1, 0x66, 0xa5, 0xf8, 0x4d, + 0x34, 0xda, 0xf4, 0xe5, 0x98, 0x34, 0xcd, 0x65, 0xd7, 0x9f, 0xfc, 0x41, 0xdd, 0xf0, + 0x68, 0x2d, 0xc2, 0xab, ], rho: [ 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, @@ -3170,9 +3170,9 @@ pub(crate) fn test_vectors() -> Vec { 0xcc, 0x53, 0x03, 0xc5, 0xf3, 0xf0, ], ock: [ - 0xe3, 0xf2, 0x74, 0x2e, 0xa1, 0x97, 0x55, 0xa7, 0x99, 0x73, 0x1a, 0xcf, 0xe9, 0x98, - 0x86, 0xfb, 0x9f, 0xbb, 0x80, 0x48, 0xb5, 0x3a, 0x77, 0x72, 0xa2, 0x80, 0xd8, 0x17, - 0x19, 0xff, 0xfd, 0x28, + 0x55, 0x0e, 0xbf, 0x98, 0x83, 0x6c, 0xce, 0x43, 0x52, 0x25, 0xa1, 0x4b, 0xa6, 0x52, + 0xa7, 0xd5, 0x58, 0xcf, 0x5f, 0x3f, 0x7a, 0xfb, 0x00, 0xb0, 0x24, 0x70, 0xe8, 0xe4, + 0xd2, 0x6d, 0xb7, 0x9c, ], op: [ 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, @@ -3182,12 +3182,12 @@ pub(crate) fn test_vectors() -> Vec { 0x44, 0x72, 0x83, 0xf9, 0x4e, 0xd5, 0x95, 0x3d, ], c_out: [ - 0x92, 0xe7, 0x7c, 0x9b, 0x69, 0x92, 0xee, 0x85, 0x06, 0x30, 0x6a, 0x96, 0xc8, 0xa5, - 0x1c, 0xc9, 0xa8, 0x96, 0x18, 0xc6, 0x36, 0x6f, 0xce, 0x78, 0xb2, 0x9a, 0xdb, 0x10, - 0x9b, 0x4a, 0x3b, 0x17, 0x48, 0x49, 0x13, 0x4f, 0x7a, 0xa2, 0x9c, 0x79, 0x1b, 0x91, - 0x5f, 0xd7, 0x5a, 0x6f, 0xfc, 0x57, 0x42, 0x78, 0xef, 0x50, 0x2b, 0x84, 0x02, 0x46, - 0x9a, 0xb5, 0xa7, 0xce, 0x77, 0x2b, 0x52, 0x2c, 0x4b, 0xaa, 0x12, 0x95, 0xd8, 0x8f, - 0x15, 0xdc, 0x75, 0x1d, 0xdf, 0x7d, 0x20, 0x8d, 0xd5, 0x17, + 0x9a, 0x01, 0xb7, 0x5e, 0x27, 0xea, 0x97, 0x51, 0x45, 0x5d, 0x54, 0xf2, 0xa5, 0x2b, + 0x88, 0x4b, 0x45, 0x6a, 0x6f, 0xc3, 0xda, 0xdb, 0xec, 0x79, 0xbf, 0x4d, 0x10, 0xbe, + 0x06, 0x7b, 0xef, 0x3e, 0xa2, 0xa5, 0xc0, 0x59, 0x81, 0xd4, 0x06, 0x05, 0x6a, 0x2f, + 0xf6, 0x4c, 0xb4, 0xc6, 0xfd, 0x46, 0x7d, 0xa8, 0x0b, 0xa1, 0x17, 0x48, 0xe9, 0xe2, + 0xae, 0x07, 0xb7, 0x62, 0xdf, 0x9d, 0x4a, 0x23, 0x58, 0x77, 0xf5, 0x8f, 0x43, 0x24, + 0xd8, 0x00, 0x3c, 0x32, 0x4f, 0xd9, 0xc6, 0x39, 0xbc, 0xa6, ], asset: Some([ 0x29, 0x8a, 0xc0, 0xaf, 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, @@ -3262,9 +3262,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x65, 0x73, 0x3c, 0x9d, 0x97, 0xea, 0x82, 0xf6, 0xde, 0xf3, 0xde, 0x1f, 0xe8, 0x7e, - 0x12, 0x37, 0x6a, 0x92, 0x49, 0xdc, 0x86, 0x14, 0x67, 0x2d, 0x5e, 0xda, 0x15, 0xf3, - 0xca, 0xf4, 0x5b, 0x8c, + 0x5d, 0xd1, 0x3d, 0xcf, 0x9a, 0xf3, 0x52, 0xf5, 0xfe, 0x0b, 0x2b, 0xcb, 0xd0, 0xdb, + 0xd7, 0xda, 0xfb, 0xbe, 0x53, 0xb0, 0xa9, 0x6b, 0x08, 0x1c, 0x90, 0xba, 0xde, 0xd9, + 0xbe, 0x4b, 0x4f, 0x87, ], rho: [ 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, @@ -3384,9 +3384,9 @@ pub(crate) fn test_vectors() -> Vec { 0x71, 0xb8, 0xaa, 0x9f, 0x69, 0xf0, ], ock: [ - 0x42, 0x46, 0x14, 0xa3, 0xb5, 0x79, 0x96, 0xef, 0xb1, 0x24, 0xb7, 0xf4, 0x50, 0xae, - 0x2a, 0xf7, 0xf6, 0xdc, 0x8c, 0x8c, 0xee, 0xa9, 0x4f, 0x17, 0x74, 0x77, 0x72, 0x1b, - 0x84, 0x61, 0x3b, 0x23, + 0x53, 0x29, 0x6e, 0xed, 0x43, 0xb4, 0xeb, 0x30, 0xa4, 0x3d, 0x88, 0x90, 0x2f, 0x74, + 0x04, 0x26, 0x62, 0x1d, 0x85, 0x21, 0x3a, 0x36, 0xc5, 0x20, 0xa1, 0x84, 0xa4, 0x3a, + 0xfb, 0xd4, 0x89, 0x6d, ], op: [ 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, @@ -3396,12 +3396,12 @@ pub(crate) fn test_vectors() -> Vec { 0x86, 0x48, 0x56, 0x2c, 0xbd, 0x86, 0x3f, 0x09, ], c_out: [ - 0x8b, 0x94, 0x8b, 0x33, 0xf5, 0x55, 0xcd, 0x45, 0x5f, 0xaa, 0x36, 0x51, 0x7b, 0x8e, - 0xab, 0x29, 0xe1, 0xa5, 0x1f, 0x6c, 0xec, 0x21, 0x79, 0xd9, 0xea, 0xe4, 0xea, 0xca, - 0x92, 0x50, 0xbb, 0x9b, 0x55, 0xe4, 0xb5, 0x49, 0x49, 0x15, 0xc1, 0xf0, 0x01, 0x65, - 0xf8, 0x9d, 0x7c, 0x02, 0xa0, 0x25, 0x45, 0xb9, 0xd5, 0x98, 0x08, 0x6e, 0xeb, 0x96, - 0x1e, 0x58, 0x7e, 0x43, 0xfd, 0xfc, 0x65, 0xfe, 0x52, 0xf1, 0xe0, 0xc6, 0xa0, 0x46, - 0x46, 0x48, 0xcd, 0x1f, 0xc8, 0x9e, 0x80, 0xbd, 0x78, 0x0f, + 0x38, 0xee, 0x14, 0xef, 0xb0, 0x63, 0x94, 0x64, 0x44, 0x6f, 0x5f, 0xb8, 0x79, 0x5d, + 0x23, 0xf8, 0x8c, 0xf5, 0x65, 0x37, 0xe6, 0x4e, 0x1a, 0x46, 0x63, 0x17, 0xb3, 0x6f, + 0x22, 0x2e, 0x00, 0x5b, 0x92, 0x4c, 0xc9, 0x10, 0xd6, 0x29, 0x06, 0x6e, 0x05, 0x07, + 0xcb, 0x91, 0x2b, 0x0b, 0xc1, 0xd3, 0x16, 0xc2, 0x00, 0xb1, 0xa9, 0x56, 0x49, 0xc0, + 0xc5, 0x30, 0xb4, 0xf3, 0xd0, 0x43, 0x06, 0x8e, 0xf6, 0xf4, 0x2d, 0xcb, 0xef, 0xd0, + 0x2a, 0x34, 0x80, 0xe3, 0x2a, 0xa4, 0x5e, 0x33, 0xce, 0x25, ], asset: Some([ 0xf9, 0x78, 0x1e, 0xbe, 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, @@ -3476,9 +3476,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x81, 0xa8, 0xbb, 0x76, 0xf2, 0x62, 0x73, 0x62, 0x8b, 0x9f, 0x9b, 0x66, 0x04, 0x94, - 0xb3, 0x45, 0xb7, 0x9d, 0x45, 0x16, 0x3c, 0x7b, 0x4c, 0xc5, 0x5a, 0x49, 0xff, 0x3f, - 0xc6, 0xb8, 0x1d, 0xaa, + 0x43, 0x94, 0x47, 0xab, 0x14, 0x5a, 0x6f, 0x0e, 0x5a, 0x3b, 0x43, 0x63, 0x04, 0x4c, + 0x73, 0x07, 0x93, 0xf4, 0x36, 0x33, 0x1f, 0xfe, 0x66, 0x30, 0xc7, 0xca, 0x2d, 0x9b, + 0x23, 0x2a, 0xe1, 0x98, ], rho: [ 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, @@ -3598,9 +3598,9 @@ pub(crate) fn test_vectors() -> Vec { 0xd8, 0x2e, 0x93, 0x3c, 0x89, 0xe1, ], ock: [ - 0x71, 0x5c, 0x9a, 0x01, 0x87, 0xab, 0x90, 0xb2, 0x4d, 0x3c, 0xbb, 0xa3, 0xf1, 0xab, - 0x30, 0x67, 0xc5, 0x63, 0x06, 0x04, 0x48, 0xc0, 0x0e, 0xf2, 0x74, 0xb7, 0xea, 0x66, - 0x11, 0x13, 0x0d, 0x26, + 0x2a, 0x2e, 0x0d, 0x99, 0x69, 0xf0, 0x2e, 0xbd, 0xb6, 0xd9, 0xc8, 0xe7, 0xe6, 0xfd, + 0xde, 0x20, 0x85, 0x12, 0x4b, 0x19, 0xad, 0x70, 0x90, 0xcc, 0x26, 0x15, 0x1d, 0x4d, + 0xa4, 0x2a, 0x00, 0x3e, ], op: [ 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, @@ -3610,12 +3610,12 @@ pub(crate) fn test_vectors() -> Vec { 0xa9, 0xec, 0x88, 0x17, 0x18, 0x65, 0x40, 0x33, ], c_out: [ - 0x22, 0xce, 0xb6, 0x94, 0x21, 0xab, 0x9e, 0xd0, 0x29, 0x97, 0x3f, 0xf2, 0x2e, 0xc9, - 0x5f, 0x23, 0x36, 0x56, 0xbe, 0x41, 0xd2, 0x25, 0x1a, 0x76, 0x77, 0xce, 0xb0, 0xd3, - 0x14, 0x22, 0x11, 0x6f, 0x8c, 0xa5, 0xf0, 0xae, 0x23, 0x12, 0xd4, 0xec, 0x60, 0x0c, - 0x5d, 0x7c, 0x56, 0x44, 0x5b, 0x6d, 0x8d, 0xc4, 0xb8, 0x0b, 0x47, 0x0b, 0xb1, 0xf6, - 0x51, 0xa5, 0x38, 0x28, 0x0d, 0xaa, 0x94, 0x20, 0x3a, 0xb5, 0x02, 0xa8, 0x15, 0x09, - 0xe4, 0x3a, 0x61, 0xa6, 0x98, 0x56, 0x57, 0xd9, 0xe8, 0x4e, + 0x74, 0x6a, 0xae, 0x9d, 0xa6, 0x1c, 0x02, 0xae, 0xaa, 0x8b, 0xed, 0xbe, 0x2b, 0x6c, + 0x84, 0x1b, 0xc4, 0x36, 0x17, 0x3c, 0x7c, 0x91, 0x13, 0x66, 0x3a, 0x39, 0xc1, 0x74, + 0x69, 0x29, 0x0b, 0xd2, 0x19, 0xea, 0xdc, 0x4a, 0x97, 0x5a, 0xd0, 0x52, 0xd0, 0x5d, + 0xc0, 0xa3, 0x08, 0xf3, 0x63, 0xf9, 0x22, 0x68, 0x2d, 0x75, 0x21, 0x9d, 0xaa, 0x33, + 0x6f, 0x69, 0xb5, 0x9e, 0x86, 0x7c, 0x85, 0xd9, 0x37, 0x34, 0x4c, 0x19, 0xd3, 0x88, + 0x01, 0x63, 0x19, 0xb3, 0xf6, 0x0f, 0x76, 0xd0, 0x28, 0x93, ], asset: Some([ 0x76, 0xba, 0x24, 0x3f, 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, @@ -3690,9 +3690,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x40, 0x21, 0x95, 0x68, 0x0e, 0x02, 0x27, 0x30, 0x2c, 0x3a, 0x75, 0x6a, 0x34, 0xdf, - 0xdb, 0x13, 0x6b, 0xbd, 0x28, 0x7d, 0x7d, 0xc1, 0x25, 0x81, 0xd0, 0x8e, 0x2a, 0x63, - 0xb9, 0xc3, 0x92, 0x3e, + 0xf4, 0x5c, 0xba, 0x14, 0x6a, 0xe7, 0x18, 0x85, 0xfd, 0x61, 0xb4, 0xa0, 0xf3, 0x6b, + 0x95, 0x26, 0xa6, 0xe9, 0x4a, 0x49, 0x70, 0x10, 0xe3, 0x2a, 0x8a, 0x76, 0xbc, 0xdf, + 0xa7, 0x20, 0xb8, 0xa6, ], rho: [ 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, @@ -3812,9 +3812,9 @@ pub(crate) fn test_vectors() -> Vec { 0x7e, 0x44, 0x16, 0x70, 0x64, 0xc9, ], ock: [ - 0xbc, 0x1b, 0xa7, 0xae, 0x73, 0xe7, 0x39, 0x7a, 0x64, 0xe0, 0xbd, 0x98, 0x63, 0xf1, - 0x33, 0x95, 0xdc, 0x0b, 0x15, 0xd4, 0x4e, 0x86, 0x70, 0xf1, 0x85, 0x5b, 0x68, 0xc2, - 0x9f, 0x97, 0x9a, 0xd2, + 0x67, 0x1c, 0xed, 0xd6, 0xf5, 0x73, 0xa4, 0x6f, 0xf1, 0xea, 0xd0, 0x48, 0x21, 0x98, + 0x56, 0x36, 0xe2, 0x3f, 0xb1, 0x5c, 0x6f, 0x48, 0x05, 0xfd, 0x57, 0x63, 0x12, 0xc2, + 0x07, 0x02, 0xa4, 0x24, ], op: [ 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, @@ -3824,12 +3824,12 @@ pub(crate) fn test_vectors() -> Vec { 0x6a, 0x72, 0xcb, 0x74, 0xfb, 0x18, 0xd1, 0x17, ], c_out: [ - 0xe2, 0x76, 0x3c, 0x2c, 0xd3, 0x04, 0x29, 0x45, 0x25, 0xf6, 0x6d, 0x17, 0xcd, 0xb4, - 0x2a, 0x6d, 0xaf, 0xd7, 0x47, 0x38, 0x37, 0x71, 0x52, 0x35, 0x62, 0xb2, 0x71, 0xbb, - 0xf5, 0xb2, 0x88, 0x41, 0xb5, 0xca, 0x65, 0xfd, 0xd3, 0x42, 0xee, 0x80, 0x2f, 0xee, - 0x12, 0x12, 0x47, 0x22, 0xcf, 0xf5, 0xe1, 0x99, 0xd6, 0xd9, 0x5c, 0x2f, 0x88, 0xc4, - 0xe2, 0x31, 0x31, 0xf4, 0xe7, 0x6b, 0xa7, 0x6b, 0x9d, 0x64, 0x66, 0x78, 0xd8, 0x53, - 0xd1, 0xdc, 0xaf, 0x81, 0xb8, 0x0e, 0x2e, 0xfd, 0xf0, 0x60, + 0x59, 0x97, 0x53, 0xe4, 0x0a, 0xda, 0xea, 0xff, 0x6f, 0xaa, 0xf5, 0xa6, 0xf3, 0x0e, + 0x39, 0x13, 0x8f, 0xde, 0x82, 0x0f, 0x7b, 0xec, 0x7c, 0x8d, 0x0f, 0xd8, 0x4b, 0x48, + 0x36, 0x94, 0xe5, 0x0c, 0x4b, 0xdd, 0xee, 0x2f, 0xb1, 0xa4, 0xf9, 0x95, 0xb1, 0xa3, + 0xba, 0x40, 0xf4, 0x66, 0xb4, 0x2e, 0x8b, 0x5d, 0x01, 0x38, 0xfd, 0x30, 0xbf, 0xf6, + 0xae, 0x8c, 0xb1, 0x55, 0xf4, 0x0c, 0xdc, 0x37, 0x39, 0xfa, 0xbf, 0x2f, 0x00, 0xda, + 0x3a, 0xc6, 0xa7, 0x36, 0x3b, 0xc2, 0xf4, 0xaa, 0x10, 0xfe, ], asset: Some([ 0x64, 0xd0, 0x87, 0x40, 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, @@ -3904,9 +3904,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x50, 0xaf, 0x90, 0x31, 0xf4, 0xe0, 0x4b, 0x79, 0xd7, 0xda, 0xb5, 0xe8, 0x5b, 0x51, - 0xee, 0x9b, 0xea, 0x56, 0xf7, 0xc5, 0x6b, 0x52, 0x22, 0x73, 0xd2, 0x30, 0xaa, 0x51, - 0x2b, 0xa9, 0xe7, 0x06, + 0x1a, 0xa2, 0x3d, 0x96, 0x79, 0xbc, 0x66, 0x04, 0xb6, 0x25, 0x2c, 0x4f, 0x48, 0x1b, + 0x3a, 0x2a, 0xf5, 0x46, 0x32, 0xf8, 0x30, 0x08, 0x14, 0x68, 0x29, 0x65, 0x94, 0x5e, + 0x7e, 0x33, 0x2a, 0x0d, ], rho: [ 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, @@ -4026,9 +4026,9 @@ pub(crate) fn test_vectors() -> Vec { 0xcc, 0xac, 0xba, 0xd9, 0xa2, 0xfa, ], ock: [ - 0xc7, 0x5b, 0x5b, 0xfa, 0x9f, 0x2e, 0xeb, 0xd9, 0x99, 0x80, 0x78, 0xf1, 0x8f, 0x0e, - 0x9b, 0x79, 0xf1, 0xe2, 0x13, 0xe8, 0x25, 0x61, 0x6f, 0xeb, 0x26, 0x08, 0xe9, 0xc7, - 0x81, 0xb5, 0x00, 0x95, + 0x57, 0x97, 0xef, 0x48, 0x70, 0xb0, 0x86, 0x50, 0xfa, 0x99, 0xad, 0xae, 0x58, 0x85, + 0x19, 0x9e, 0x3b, 0x04, 0x4b, 0x2a, 0x0a, 0x8c, 0xe1, 0x61, 0x43, 0x42, 0xb5, 0xdc, + 0xb2, 0x8e, 0x6e, 0x09, ], op: [ 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, @@ -4038,12 +4038,12 @@ pub(crate) fn test_vectors() -> Vec { 0xb9, 0x5f, 0xc8, 0x7e, 0xa7, 0x37, 0x3e, 0x2f, ], c_out: [ - 0xca, 0x4d, 0x6e, 0xb3, 0xea, 0x95, 0xc5, 0x5a, 0x91, 0x16, 0x85, 0x66, 0xe6, 0x67, - 0x63, 0xd1, 0x9e, 0x9c, 0x44, 0x33, 0x07, 0x3c, 0x08, 0x9a, 0x7d, 0xb9, 0x5b, 0x93, - 0xc8, 0xc4, 0x55, 0x0e, 0xb0, 0x8e, 0x28, 0xdd, 0xef, 0xba, 0x64, 0xe0, 0x58, 0xac, - 0x68, 0x44, 0xad, 0x77, 0x20, 0x67, 0xa1, 0x7c, 0x32, 0x53, 0xc3, 0x9a, 0x72, 0x4d, - 0xd8, 0x15, 0xf7, 0x29, 0x8c, 0x1d, 0x59, 0x09, 0x1f, 0x1b, 0x38, 0x7a, 0x26, 0x46, - 0xe7, 0xfe, 0x36, 0x3a, 0xde, 0x83, 0x63, 0xa9, 0x2a, 0xde, + 0xb8, 0xb4, 0x6c, 0x7e, 0xc4, 0xa8, 0x74, 0x2a, 0x22, 0xd3, 0xcd, 0x11, 0x74, 0x1c, + 0x23, 0x04, 0x22, 0x1c, 0xa5, 0x97, 0x29, 0x4e, 0x08, 0xa4, 0xc7, 0x1b, 0x17, 0xc7, + 0x26, 0x5d, 0x4d, 0xa7, 0x7c, 0xfe, 0x84, 0xb8, 0x7e, 0x76, 0xed, 0xaa, 0xec, 0xc2, + 0x24, 0xb8, 0x36, 0xde, 0x22, 0x4c, 0x73, 0x58, 0x13, 0x19, 0xa0, 0xba, 0x27, 0x88, + 0xdb, 0xf8, 0x3b, 0xcf, 0x47, 0xa4, 0x8e, 0xeb, 0x02, 0xb4, 0x3a, 0x18, 0x02, 0x7b, + 0x8f, 0x59, 0x11, 0x65, 0xc2, 0x86, 0xe8, 0xb6, 0x54, 0xec, ], asset: Some([ 0xc3, 0xcc, 0x4f, 0x43, 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, @@ -4118,9 +4118,9 @@ pub(crate) fn test_vectors() -> Vec { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ], cv_net: [ - 0x72, 0xd8, 0x2a, 0xd6, 0x89, 0xd2, 0x9f, 0x9b, 0x18, 0x9d, 0x5b, 0x44, 0x78, 0x9f, - 0x55, 0xfe, 0x1e, 0x9b, 0xab, 0x78, 0x8f, 0xf8, 0x7e, 0xbe, 0x9f, 0xc8, 0x59, 0x50, - 0x4f, 0xb2, 0x3c, 0x8a, + 0x91, 0x6d, 0xc3, 0x82, 0x2a, 0x4e, 0x3b, 0xb4, 0x1f, 0xa8, 0x33, 0xc2, 0x73, 0xa9, + 0xd3, 0x7d, 0x17, 0x17, 0xa4, 0x8d, 0x8f, 0x00, 0x6c, 0x1f, 0xf5, 0x86, 0x21, 0x46, + 0x29, 0x55, 0x39, 0x1c, ], rho: [ 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, @@ -4240,9 +4240,9 @@ pub(crate) fn test_vectors() -> Vec { 0xf4, 0x76, 0x11, 0x41, 0xd4, 0xa6, ], ock: [ - 0xdc, 0xf9, 0x34, 0xcf, 0x6a, 0x64, 0x90, 0x3f, 0x2d, 0x99, 0xa3, 0x07, 0xe1, 0x55, - 0xfb, 0x90, 0xe9, 0x7a, 0xc9, 0x0c, 0x38, 0x7f, 0x1b, 0xa5, 0xa6, 0xea, 0x43, 0xb5, - 0x91, 0xb0, 0x5d, 0x69, + 0x95, 0x83, 0xf1, 0x0f, 0xed, 0x70, 0xa4, 0x1e, 0x45, 0x8c, 0x65, 0x5c, 0xc0, 0x14, + 0xe2, 0x35, 0x5a, 0x7f, 0x99, 0xae, 0xbc, 0xfe, 0xf7, 0x4a, 0x55, 0x9a, 0xcd, 0x24, + 0x25, 0xfa, 0x21, 0xcf, ], op: [ 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, @@ -4252,12 +4252,12 @@ pub(crate) fn test_vectors() -> Vec { 0xc4, 0x69, 0x2d, 0x0c, 0x1b, 0x30, 0x33, 0x01, ], c_out: [ - 0x25, 0xf4, 0xbb, 0x9f, 0xb4, 0x45, 0x06, 0x78, 0x9c, 0xf5, 0x1d, 0xc3, 0xf6, 0x5f, - 0x17, 0xaf, 0xee, 0xe0, 0x34, 0x92, 0x79, 0xc7, 0x89, 0x28, 0x9b, 0x03, 0xd3, 0x8c, - 0x2e, 0x20, 0xd3, 0x12, 0x5d, 0xe7, 0xc5, 0x6e, 0x18, 0x29, 0x2d, 0xec, 0xc6, 0x41, - 0x81, 0xa7, 0xe9, 0xa7, 0xbc, 0x12, 0xeb, 0x97, 0x85, 0xf0, 0xdd, 0x51, 0xd5, 0x88, - 0x62, 0x00, 0xfb, 0x18, 0x7d, 0x2c, 0x16, 0x90, 0x65, 0xaf, 0x84, 0xcc, 0x02, 0x3d, - 0x6d, 0x63, 0xce, 0x05, 0x83, 0x28, 0xe2, 0x47, 0xb5, 0x98, + 0xb8, 0x3b, 0x74, 0x5c, 0x9c, 0x0b, 0x04, 0xdd, 0xc7, 0xf1, 0x38, 0x16, 0x94, 0x38, + 0x99, 0x55, 0x3a, 0x30, 0x6a, 0x4a, 0xd0, 0xf2, 0xf5, 0x70, 0x92, 0x2a, 0x89, 0x9b, + 0xab, 0xb9, 0xda, 0xca, 0xd2, 0xbb, 0xc9, 0x5c, 0xf6, 0x5b, 0x73, 0x08, 0x55, 0x0d, + 0xce, 0xdb, 0x64, 0x9e, 0xf1, 0x5e, 0x0b, 0x1a, 0x09, 0x1f, 0xad, 0x5a, 0x93, 0x92, + 0xd0, 0x71, 0xb7, 0x5a, 0xb5, 0x1a, 0x7e, 0x35, 0x06, 0xad, 0x58, 0xd1, 0x71, 0x95, + 0xc9, 0x9f, 0x29, 0x8a, 0xc3, 0x14, 0xec, 0x05, 0xa6, 0x6a, ], asset: Some([ 0x96, 0x86, 0xaa, 0x36, 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, From babf1da44b91a8030d9eb31f99bb8d22756bb72c Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Wed, 21 Dec 2022 11:40:08 +0200 Subject: [PATCH 15/92] CI-Badge (#37) Added CI badge to README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d4ac85eb..f761aa914 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) # +# orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) [![CI checks](https://github.com/QED-it/orchard/actions/workflows/ci.yml/badge.svg?branch=zsa1)](https://github.com/QED-it/orchard/actions/workflows/ci.yml) +# Requires Rust 1.61+. From 4681cc212a78104ea43387b37f85af7a437ca2cf Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 23 Dec 2022 11:29:01 +0100 Subject: [PATCH 16/92] Use different random nullifiers in dummy notes (#39) --- src/builder.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 9dfaa9efb..cd452b946 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -403,10 +403,13 @@ impl Builder { // || SpendInfo::dummy(asset, &mut rng), // |s| s.create_split_spend(), // ); - let dummy_spend = SpendInfo::dummy(asset, &mut rng); + // spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); // Extend the spends and recipients with dummy values. - spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); + spends.extend( + iter::repeat_with(|| SpendInfo::dummy(asset, &mut rng)) + .take(num_actions - num_spends), + ); recipients.extend( iter::repeat_with(|| RecipientInfo::dummy(&mut rng, asset)) From cec48d72a15ad44c0c5a8c6a7846946ba1347e79 Mon Sep 17 00:00:00 2001 From: Paul <3682187+PaulLaux@users.noreply.github.com> Date: Tue, 31 Jan 2023 15:51:29 +0200 Subject: [PATCH 17/92] V3 encryption (#38) Added `OrchardDomainV3` on top of the encryption generalization (QED-it/librustzcash#18). not for review: note_encryption.rs, note_encryptionv2v3.rs and src/test_vectors/note_encryption.rs. These files represent two possible approaches for backward compatibility and will be finalized down the road. (the files were excluded from the build). --- Cargo.toml | 3 + benches/note_decryption.rs | 8 +- src/action.rs | 4 +- src/builder.rs | 20 +- src/bundle.rs | 18 +- src/bundle/commitments.rs | 6 +- src/issuance.rs | 38 +- src/lib.rs | 3 +- src/note.rs | 27 +- src/note/asset_id.rs | 15 +- src/note_encryption.rs | 328 +- src/note_encryption_v2v3.rs | 717 ++++ src/note_encryption_v3.rs | 634 ++++ src/test_vectors.rs | 1 + src/test_vectors/note_encryption.rs | 2155 +----------- src/test_vectors/note_encryption_v3.rs | 4389 ++++++++++++++++++++++++ src/value.rs | 5 +- tests/builder.rs | 4 +- tests/zsa.rs | 4 +- 19 files changed, 6028 insertions(+), 2351 deletions(-) create mode 100644 src/note_encryption_v2v3.rs create mode 100644 src/note_encryption_v3.rs create mode 100644 src/test_vectors/note_encryption_v3.rs diff --git a/Cargo.toml b/Cargo.toml index cb7508702..b5461be1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,3 +84,6 @@ debug = true [profile.bench] debug = true + +[patch.crates-io] +zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", rev = "07c377ddedf71ab7c7a266d284b054a2dafc2ed4" } diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 1417a2b6c..244de4378 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -5,7 +5,7 @@ use orchard::{ circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note::AssetId, - note_encryption::{CompactAction, OrchardDomain}, + note_encryption_v3::{CompactAction, OrchardDomainV3}, value::NoteValue, Anchor, Bundle, }; @@ -79,7 +79,7 @@ fn bench_note_decryption(c: &mut Criterion) { }; let action = bundle.actions().first(); - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); let compact = { let mut group = c.benchmark_group("note-decryption"); @@ -120,12 +120,12 @@ fn bench_note_decryption(c: &mut Criterion) { let ivks = 2; let valid_ivks = vec![valid_ivk; ivks]; let actions: Vec<_> = (0..100) - .map(|_| (OrchardDomain::for_action(action), action.clone())) + .map(|_| (OrchardDomainV3::for_action(action), action.clone())) .collect(); let compact: Vec<_> = (0..100) .map(|_| { ( - OrchardDomain::for_action(action), + OrchardDomainV3::for_action(action), CompactAction::from(action), ) }) diff --git a/src/action.rs b/src/action.rs index 94fe4f3f4..ed3fe1661 100644 --- a/src/action.rs +++ b/src/action.rs @@ -158,7 +158,7 @@ pub(crate) mod testing { // FIXME: make a real one from the note. let encrypted_note = TransmittedNoteCiphertext { epk_bytes: [0u8; 32], - enc_ciphertext: [0u8; 580], + enc_ciphertext: [0u8; 612], out_ciphertext: [0u8; 80] }; Action { @@ -192,7 +192,7 @@ pub(crate) mod testing { // FIXME: make a real one from the note. let encrypted_note = TransmittedNoteCiphertext { epk_bytes: [0u8; 32], - enc_ciphertext: [0u8; 580], + enc_ciphertext: [0u8; 612], out_ciphertext: [0u8; 80] }; diff --git a/src/builder.rs b/src/builder.rs index cd452b946..d420d742e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -20,7 +20,7 @@ use crate::{ SpendingKey, }, note::{Note, TransmittedNoteCiphertext}, - note_encryption::OrchardNoteEncryption, + note_encryption_v3::OrchardNoteEncryption, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -79,7 +79,12 @@ impl SpendInfo { /// Returns `None` if the `fvk` does not own the `note`. /// /// [`Builder::add_spend`]: Builder::add_spend - pub fn new(fvk: FullViewingKey, note: Note, merkle_path: MerklePath) -> Option { + pub fn new( + fvk: FullViewingKey, + note: Note, + merkle_path: MerklePath, + split_flag: bool, + ) -> Option { let scope = fvk.scope_for_address(¬e.recipient())?; Some(SpendInfo { dummy_sk: None, @@ -87,7 +92,7 @@ impl SpendInfo { scope, note, merkle_path, - split_flag: false, + split_flag, }) } @@ -112,10 +117,7 @@ impl SpendInfo { /// Return a copy of this note with the split flag set to `true`. fn create_split_spend(&self) -> Self { - let mut split_spend = SpendInfo::new(self.fvk.clone(), self.note, self.merkle_path.clone()) - .expect("The spend info is valid"); - split_spend.split_flag = true; - split_spend + SpendInfo::new(self.fvk.clone(), self.note, self.merkle_path.clone(), true).unwrap() } } @@ -224,7 +226,7 @@ impl ActionInfo { let encrypted_note = TransmittedNoteCiphertext { epk_bytes: encryptor.epk().to_bytes().0, - enc_ciphertext: encryptor.encrypt_note_plaintext(), + enc_ciphertext: encryptor.encrypt_note_plaintext().0, out_ciphertext: encryptor.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut rng), }; @@ -278,7 +280,7 @@ impl Builder { /// Returns an error if the given Merkle path does not have the required anchor for /// the given note. /// - /// [`OrchardDomain`]: crate::note_encryption::OrchardDomain + /// [`OrchardDomain`]: crate::note_encryption_v3::OrchardDomainV3 /// [`MerkleHashOrchard`]: crate::tree::MerkleHashOrchard pub fn add_spend( &mut self, diff --git a/src/bundle.rs b/src/bundle.rs index cbc66e796..1d1363daf 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -20,7 +20,7 @@ use crate::{ circuit::{Instance, Proof, VerifyingKey}, keys::{IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey}, note::Note, - note_encryption::OrchardDomain, + note_encryption_v3::OrchardDomainV3, primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, value::{ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -305,7 +305,7 @@ impl Bundle { .iter() .enumerate() .filter_map(|(idx, action)| { - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); prepared_keys.iter().find_map(|(ivk, prepared_ivk)| { try_note_decryption(&domain, prepared_ivk, action) .map(|(n, a, m)| (idx, (*ivk).clone(), n, a, m)) @@ -324,7 +324,7 @@ impl Bundle { ) -> Option<(Note, Address, [u8; 512])> { let prepared_ivk = PreparedIncomingViewingKey::new(key); self.actions.get(action_idx).and_then(move |action| { - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); try_note_decryption(&domain, &prepared_ivk, action) }) } @@ -341,7 +341,7 @@ impl Bundle { .iter() .enumerate() .filter_map(|(idx, action)| { - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); keys.iter().find_map(move |key| { try_output_recovery_with_ovk( &domain, @@ -365,7 +365,7 @@ impl Bundle { key: &OutgoingViewingKey, ) -> Option<(Note, Address, [u8; 512])> { self.actions.get(action_idx).and_then(move |action| { - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); try_output_recovery_with_ovk( &domain, key, @@ -527,7 +527,7 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; pub use crate::action::testing::{arb_action, arb_unauthorized_action}; - use crate::note::asset_id::testing::zsa_asset_id; + use crate::note::asset_id::testing::arb_zsa_asset_id; use crate::note::AssetId; use crate::value::testing::arb_value_sum; @@ -591,7 +591,11 @@ pub mod testing { prop_compose! { /// Create an arbitrary vector of assets to burn. - pub fn arb_asset_to_burn()(asset_id in zsa_asset_id(), value in arb_value_sum()) -> (AssetId, ValueSum) { + pub fn arb_asset_to_burn() + ( + asset_id in arb_zsa_asset_id(), + value in arb_value_sum() + ) -> (AssetId, ValueSum) { (asset_id, value) } } diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 285ba31f7..dc6a0b65a 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -42,13 +42,13 @@ pub(crate) fn hash_bundle_txid_data>( ch.update(&action.nullifier().to_bytes()); ch.update(&action.cmx().to_bytes()); ch.update(&action.encrypted_note().epk_bytes); - ch.update(&action.encrypted_note().enc_ciphertext[..52]); + ch.update(&action.encrypted_note().enc_ciphertext[..84]); // TODO: make sure it is backward compatible with Orchard [..52] - mh.update(&action.encrypted_note().enc_ciphertext[52..564]); + mh.update(&action.encrypted_note().enc_ciphertext[84..596]); nh.update(&action.cv_net().to_bytes()); nh.update(&<[u8; 32]>::from(action.rk())); - nh.update(&action.encrypted_note().enc_ciphertext[564..]); + nh.update(&action.encrypted_note().enc_ciphertext[596..]); nh.update(&action.encrypted_note().out_ciphertext); } diff --git a/src/issuance.rs b/src/issuance.rs index 9f15d638f..74247f928 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -344,7 +344,7 @@ impl IssueBundle { /// * Asset description size is collect. /// * `AssetId` for the `IssueAction` has not been previously finalized. /// * For each `Note` inside an `IssueAction`: -/// * All notes have the same, correct `NoteType`. +/// * All notes have the same, correct `AssetId`. pub fn verify_issue_bundle( bundle: &IssueBundle, sighash: [u8; 32], @@ -356,7 +356,6 @@ pub fn verify_issue_bundle( let s = &mut HashSet::::new(); - // An IssueAction could have just one properly derived AssetId. let newly_finalized = bundle .actions() .iter() @@ -373,7 +372,7 @@ pub fn verify_issue_bundle( return Err(IssueActionPreviouslyFinalizedNoteType(asset)); } - // Add to finalization set, if needed. + // Add to the finalization set, if needed. if action.is_finalized() { newly_finalized.insert(asset); } @@ -1025,30 +1024,31 @@ mod tests { pub mod testing { use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized}; use crate::keys::testing::{arb_issuance_authorizing_key, arb_issuance_validating_key}; + use crate::note::asset_id::testing::zsa_asset_id; use crate::note::testing::arb_zsa_note; use proptest::collection::vec; use proptest::prelude::*; use proptest::prop_compose; - use proptest::string::string_regex; use rand::{rngs::StdRng, SeedableRng}; prop_compose! { - /// Generate an issue action given note value - pub fn arb_issue_action()( - note in arb_zsa_note(), - asset_descr in string_regex(".{1,512}").unwrap() - ) -> IssueAction { - IssueAction::new(asset_descr, ¬e) + /// Generate an issue action + pub fn arb_issue_action(asset_desc: String) + ( + asset in zsa_asset_id(asset_desc.clone()), + ) + ( + note in arb_zsa_note(asset), + )-> IssueAction { + IssueAction::new(asset_desc.clone(), ¬e) } } prop_compose! { - /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_issue_bundle`] + /// Generate an arbitrary issue bundle with fake authorization data. pub fn arb_unathorized_issue_bundle(n_actions: usize) ( - actions in vec(arb_issue_action(), n_actions), + actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), ik in arb_issuance_validating_key() ) -> IssueBundle { IssueBundle { @@ -1061,11 +1061,10 @@ pub mod testing { prop_compose! { /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_issue_bundle`] + /// necessarily respect consensus rules pub fn arb_prepared_issue_bundle(n_actions: usize) ( - actions in vec(arb_issue_action(), n_actions), + actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), ik in arb_issuance_validating_key(), fake_sighash in prop::array::uniform32(prop::num::u8::ANY) ) -> IssueBundle { @@ -1079,11 +1078,10 @@ pub mod testing { prop_compose! { /// Generate an arbitrary issue bundle with fake authorization data. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_issue_bundle`] + /// necessarily respect consensus rules pub fn arb_signed_issue_bundle(n_actions: usize) ( - actions in vec(arb_issue_action(), n_actions), + actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), ik in arb_issuance_validating_key(), isk in arb_issuance_authorizing_key(), rng_seed in prop::array::uniform32(prop::num::u8::ANY), diff --git a/src/lib.rs b/src/lib.rs index c0e63ce9b..76d9c41c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,8 @@ mod constants; pub mod issuance; pub mod keys; pub mod note; -pub mod note_encryption; +// pub mod note_encryption; // disabled until backward compatability is implemented. +pub mod note_encryption_v3; pub mod primitives; mod spec; pub mod tree; diff --git a/src/note.rs b/src/note.rs index d5a58a838..7eeffe096 100644 --- a/src/note.rs +++ b/src/note.rs @@ -279,7 +279,7 @@ pub struct TransmittedNoteCiphertext { /// The serialization of the ephemeral public key pub epk_bytes: [u8; 32], /// The encrypted note ciphertext - pub enc_ciphertext: [u8; 580], + pub enc_ciphertext: [u8; 612], /// An encrypted value that allows the holder of the outgoing cipher /// key for the note to recover the note plaintext. pub out_ciphertext: [u8; 80], @@ -302,7 +302,7 @@ pub mod testing { use proptest::prelude::*; use crate::note::asset_id::testing::arb_asset_id; - use crate::note::asset_id::testing::zsa_asset_id; + use crate::note::AssetId; use crate::value::testing::arb_note_value; use crate::{ address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, @@ -336,13 +336,30 @@ pub mod testing { } prop_compose! { - /// Generate an arbitrary ZSA note - pub fn arb_zsa_note()( + /// Generate an arbitrary native note + pub fn arb_native_note()( + recipient in arb_address(), + value in arb_note_value(), + rho in arb_nullifier(), + rseed in arb_rseed(), + ) -> Note { + Note { + recipient, + value, + asset: AssetId::native(), + rho, + rseed, + } + } + } + + prop_compose! { + /// Generate an arbitrary zsa note + pub fn arb_zsa_note(asset: AssetId)( recipient in arb_address(), value in arb_note_value(), rho in arb_nullifier(), rseed in arb_rseed(), - asset in zsa_asset_id(), ) -> Note { Note { recipient, diff --git a/src/note/asset_id.rs b/src/note/asset_id.rs index 074e59364..93993c47b 100644 --- a/src/note/asset_id.rs +++ b/src/note/asset_id.rs @@ -120,8 +120,8 @@ pub mod testing { } prop_compose! { - /// Generate the ZSA note type - pub fn zsa_asset_id()( + /// Generate an asset ID + pub fn arb_zsa_asset_id()( sk in arb_spending_key(), str in "[A-Za-z]{255}" ) -> AssetId { @@ -130,6 +130,17 @@ pub mod testing { } } + prop_compose! { + /// Generate an asset ID using a specific description + pub fn zsa_asset_id(asset_desc: String)( + sk in arb_spending_key(), + ) -> AssetId { + assert!(super::is_asset_desc_of_valid_size(&asset_desc)); + let isk = IssuanceAuthorizingKey::from(&sk); + AssetId::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) + } + } + #[test] fn test_vectors() { let test_vectors = crate::test_vectors::asset_id::test_vectors(); diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 48456e261..4beb99528 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -1,12 +1,11 @@ //! In-band secret distribution for Orchard bundles. use blake2b_simd::{Hash, Params}; -use core::fmt; use group::ff::PrimeField; +use std::fmt; use zcash_note_encryption::{ - BatchDomain, Domain, EphemeralKeyBytes, NotePlaintextBytes, OutPlaintextBytes, - OutgoingCipherKey, ShieldedOutput, COMPACT_NOTE_SIZE, ENC_CIPHERTEXT_SIZE, NOTE_PLAINTEXT_SIZE, - OUT_PLAINTEXT_SIZE, + BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, + AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; use crate::note::AssetId; @@ -24,14 +23,82 @@ use crate::{ const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; -/// The size of the encoding of a ZSA asset type. -const ZSA_TYPE_SIZE: usize = 32; -/// The size of the ZSA variant of COMPACT_NOTE_SIZE. -const COMPACT_ZSA_NOTE_SIZE: usize = COMPACT_NOTE_SIZE + ZSA_TYPE_SIZE; -/// The size of the memo. -const MEMO_SIZE: usize = NOTE_PLAINTEXT_SIZE - COMPACT_NOTE_SIZE; -/// The size of the ZSA variant of the memo. -const ZSA_MEMO_SIZE: usize = NOTE_PLAINTEXT_SIZE - COMPACT_ZSA_NOTE_SIZE; +/// The size of a v2 compact note. +pub const COMPACT_NOTE_SIZE_V2: usize = 1 + // version + 11 + // diversifier + 8 + // value + 32; // rseed (or rcm prior to ZIP 212) +/// The size of [`NotePlaintextBytes`] for V2. +pub const NOTE_PLAINTEXT_SIZE_V2: usize = COMPACT_NOTE_SIZE_V2 + MEMO_SIZE; +/// The size of an encrypted note plaintext. +pub const ENC_CIPHERTEXT_SIZE_V2: usize = NOTE_PLAINTEXT_SIZE_V2 + AEAD_TAG_SIZE; + +/// a type to represent the raw bytes of a note plaintext. +#[derive(Clone, Debug)] +pub struct NotePlaintextBytes(pub [u8; NOTE_PLAINTEXT_SIZE_V2]); + +/// a type to represent the raw bytes of an encrypted note plaintext. +#[derive(Clone, Debug)] +pub struct NoteCiphertextBytes(pub [u8; ENC_CIPHERTEXT_SIZE_V2]); + +/// a type to represent the raw bytes of a compact note. +#[derive(Clone, Debug)] +pub struct CompactNotePlaintextBytes(pub [u8; COMPACT_NOTE_SIZE_V2]); + +/// a type to represent the raw bytes of an encrypted compact note. +#[derive(Clone, Debug)] +pub struct CompactNoteCiphertextBytes(pub [u8; COMPACT_NOTE_SIZE_V2]); + +impl AsMut<[u8]> for NotePlaintextBytes { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl From<&[u8]> for NotePlaintextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + NotePlaintextBytes(s.try_into().unwrap()) + } +} + +impl AsRef<[u8]> for NoteCiphertextBytes { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +impl From<&[u8]> for NoteCiphertextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + NoteCiphertextBytes(s.try_into().unwrap()) + } +} + +impl AsMut<[u8]> for CompactNotePlaintextBytes { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl From<&[u8]> for CompactNotePlaintextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + CompactNotePlaintextBytes(s.try_into().unwrap()) + } +} + +impl AsRef<[u8]> for CompactNoteCiphertextBytes { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} /// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. /// @@ -58,59 +125,58 @@ pub(crate) fn prf_ock_orchard( ) } -/// Domain-specific requirements: -/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. +/// note_version will return the version of the note plaintext. +pub fn note_version(plaintext: &[u8]) -> Option { + match plaintext[0] { + 0x02 => Some(0x02), + 0x03 => Some(0x03), + _ => None, + } +} + fn orchard_parse_note_plaintext_without_memo( - domain: &OrchardDomain, - plaintext: &[u8], + domain: &OrchardDomainV2, + plaintext: &[u8], // TODO: replace with CompactNotePlaintextBytes get_validated_pk_d: F, ) -> Option<(Note, Address)> where F: FnOnce(&Diversifier) -> Option, { - assert!(plaintext.len() >= COMPACT_NOTE_SIZE); + assert!(plaintext.len() >= COMPACT_NOTE_SIZE_V2); // Check note plaintext version - // and parse the asset type accordingly. - let asset = parse_version_and_asset_type(plaintext)?; + if note_version(plaintext).unwrap() != 0x02 { + return None; + } // The unwraps below are guaranteed to succeed by the assertion above let diversifier = Diversifier::from_bytes(plaintext[1..12].try_into().unwrap()); let value = NoteValue::from_bytes(plaintext[12..20].try_into().unwrap()); let rseed = Option::from(RandomSeed::from_bytes( - plaintext[20..COMPACT_NOTE_SIZE].try_into().unwrap(), + plaintext[20..COMPACT_NOTE_SIZE_V2].try_into().unwrap(), &domain.rho, ))?; let pk_d = get_validated_pk_d(&diversifier)?; let recipient = Address::from_parts(diversifier, pk_d); - - let note = Option::from(Note::from_parts(recipient, value, asset, domain.rho, rseed))?; + let note = Option::from(Note::from_parts( + recipient, + value, + AssetId::native(), //V2 notes are always native. + domain.rho, + rseed, + ))?; Some((note, recipient)) } -fn parse_version_and_asset_type(plaintext: &[u8]) -> Option { - // TODO: make this constant-time? - match plaintext[0] { - 0x02 => Some(AssetId::native()), - 0x03 if plaintext.len() >= COMPACT_ZSA_NOTE_SIZE => { - let bytes = &plaintext[COMPACT_NOTE_SIZE..COMPACT_ZSA_NOTE_SIZE] - .try_into() - .unwrap(); - AssetId::from_bytes(bytes).into() - } - _ => None, - } -} - /// Orchard-specific note encryption logic. #[derive(Debug)] -pub struct OrchardDomain { +pub struct OrchardDomainV2 { rho: Nullifier, } -impl memuse::DynamicUsage for OrchardDomain { +impl memuse::DynamicUsage for OrchardDomainV2 { fn dynamic_usage(&self) -> usize { self.rho.dynamic_usage() } @@ -120,21 +186,21 @@ impl memuse::DynamicUsage for OrchardDomain { } } -impl OrchardDomain { +impl OrchardDomainV2 { /// Constructs a domain that can be used to trial-decrypt this action's output note. pub fn for_action(act: &Action) -> Self { - OrchardDomain { + OrchardDomainV2 { rho: *act.nullifier(), } } /// Constructs a domain from a nullifier. pub fn for_nullifier(nullifier: Nullifier) -> Self { - OrchardDomain { rho: nullifier } + OrchardDomainV2 { rho: nullifier } } } -impl Domain for OrchardDomain { +impl Domain for OrchardDomainV2 { type EphemeralSecretKey = EphemeralSecretKey; type EphemeralPublicKey = EphemeralPublicKey; type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; @@ -150,6 +216,11 @@ impl Domain for OrchardDomain { type ExtractedCommitmentBytes = [u8; 32]; type Memo = [u8; MEMO_SIZE]; // TODO use a more interesting type + type NotePlaintextBytes = NotePlaintextBytes; + type NoteCiphertextBytes = NoteCiphertextBytes; + type CompactNotePlaintextBytes = CompactNotePlaintextBytes; + type CompactNoteCiphertextBytes = CompactNoteCiphertextBytes; + fn derive_esk(note: &Self::Note) -> Option { Some(note.esk()) } @@ -192,23 +263,12 @@ impl Domain for OrchardDomain { _: &Self::Recipient, memo: &Self::Memo, ) -> NotePlaintextBytes { - let is_native: bool = note.asset().is_native().into(); - - let mut np = [0; NOTE_PLAINTEXT_SIZE]; - np[0] = if is_native { 0x02 } else { 0x03 }; + let mut np = [0; NOTE_PLAINTEXT_SIZE_V2]; + np[0] = 0x02; np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); np[12..20].copy_from_slice(¬e.value().to_bytes()); - // todo: add asset_id np[20..52].copy_from_slice(note.rseed().as_bytes()); - if is_native { - np[52..].copy_from_slice(memo); - } else { - let zsa_type = note.asset().to_bytes(); - np[52..84].copy_from_slice(&zsa_type); - let short_memo = &memo[0..memo.len() - ZSA_TYPE_SIZE]; - np[84..].copy_from_slice(short_memo); - // TODO: handle full-size memo or make short_memo explicit. - }; + np[52..].copy_from_slice(memo); NotePlaintextBytes(np) } @@ -246,9 +306,9 @@ impl Domain for OrchardDomain { fn parse_note_plaintext_without_memo_ivk( &self, ivk: &Self::IncomingViewingKey, - plaintext: &[u8], + plaintext: &CompactNotePlaintextBytes, ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { + orchard_parse_note_plaintext_without_memo(self, &plaintext.0, |diversifier| { Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) }) } @@ -258,7 +318,7 @@ impl Domain for OrchardDomain { pk_d: &Self::DiversifiedTransmissionKey, esk: &Self::EphemeralSecretKey, ephemeral_key: &EphemeralKeyBytes, - plaintext: &NotePlaintextBytes, + plaintext: &CompactNotePlaintextBytes, ) -> Option<(Self::Note, Self::Recipient)> { orchard_parse_note_plaintext_without_memo(self, &plaintext.0, |diversifier| { if esk @@ -274,21 +334,12 @@ impl Domain for OrchardDomain { }) } - fn extract_memo(&self, plaintext: &NotePlaintextBytes) -> Self::Memo { - let mut memo = [0; MEMO_SIZE]; - match get_note_plaintext_version(plaintext) { - 0x02 => { - let full_memo = &plaintext.0[COMPACT_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]; - memo.copy_from_slice(full_memo); - } - 0x03 => { - // ZSA note plaintexts have a shorter memo. - let short_memo = &plaintext.0[COMPACT_ZSA_NOTE_SIZE..NOTE_PLAINTEXT_SIZE]; - memo[..ZSA_MEMO_SIZE].copy_from_slice(short_memo); - } - _ => {} - }; - memo + fn extract_memo( + &self, + plaintext: &NotePlaintextBytes, + ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { + let (compact, memo) = plaintext.0.split_at(COMPACT_NOTE_SIZE_V2); + (compact.try_into().unwrap(), memo.try_into().unwrap()) } fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { @@ -301,7 +352,7 @@ impl Domain for OrchardDomain { } } -impl BatchDomain for OrchardDomain { +impl BatchDomain for OrchardDomainV2 { fn batch_kdf<'a>( items: impl Iterator, &'a EphemeralKeyBytes)>, ) -> Vec> { @@ -316,14 +367,10 @@ impl BatchDomain for OrchardDomain { } } -fn get_note_plaintext_version(plaintext: &NotePlaintextBytes) -> u8 { - plaintext.0[0] -} - /// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; +pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; -impl ShieldedOutput for Action { +impl ShieldedOutput for Action { fn ephemeral_key(&self) -> EphemeralKeyBytes { EphemeralKeyBytes(self.encrypted_note().epk_bytes) } @@ -332,8 +379,16 @@ impl ShieldedOutput for Action { self.cmx().to_bytes() } - fn enc_ciphertext(&self) -> &[u8; ENC_CIPHERTEXT_SIZE] { - &self.encrypted_note().enc_ciphertext + fn enc_ciphertext(&self) -> Option { + Some(NoteCiphertextBytes(self.encrypted_note().enc_ciphertext)) + } + + fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { + CompactNoteCiphertextBytes( + self.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V2] + .try_into() + .unwrap(), + ) } } @@ -342,7 +397,7 @@ pub struct CompactAction { nullifier: Nullifier, cmx: ExtractedNoteCommitment, ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: [u8; COMPACT_NOTE_SIZE], + enc_ciphertext: CompactNoteCiphertextBytes, } impl fmt::Debug for CompactAction { @@ -351,20 +406,25 @@ impl fmt::Debug for CompactAction { } } -impl From<&Action> for CompactAction { +impl From<&Action> for CompactAction +where + Action: ShieldedOutput, +{ fn from(action: &Action) -> Self { CompactAction { nullifier: *action.nullifier(), cmx: *action.cmx(), ephemeral_key: action.ephemeral_key(), - enc_ciphertext: action.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE] - .try_into() - .unwrap(), + enc_ciphertext: CompactNoteCiphertextBytes( + action.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V2] + .try_into() + .unwrap(), + ), } } } -impl ShieldedOutput for CompactAction { +impl ShieldedOutput for CompactAction { fn ephemeral_key(&self) -> EphemeralKeyBytes { EphemeralKeyBytes(self.ephemeral_key.0) } @@ -373,8 +433,12 @@ impl ShieldedOutput for CompactAction { self.cmx.to_bytes() } - fn enc_ciphertext(&self) -> &[u8; COMPACT_NOTE_SIZE] { - &self.enc_ciphertext + fn enc_ciphertext(&self) -> Option { + None + } + + fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { + self.enc_ciphertext.clone() } } @@ -384,7 +448,7 @@ impl CompactAction { nullifier: Nullifier, cmx: ExtractedNoteCommitment, ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: [u8; 52], + enc_ciphertext: CompactNoteCiphertextBytes, ) -> Self { Self { nullifier, @@ -402,14 +466,14 @@ impl CompactAction { #[cfg(test)] mod tests { - use proptest::prelude::*; + use proptest::proptest; use rand::rngs::OsRng; use zcash_note_encryption::{ try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; - use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; + use super::{prf_ock_orchard, CompactAction, OrchardDomainV2, OrchardNoteEncryption}; use crate::note::AssetId; use crate::{ action::Action, @@ -418,53 +482,46 @@ mod tests { OutgoingViewingKey, PreparedIncomingViewingKey, }, note::{ - testing::arb_note, ExtractedNoteCommitment, Nullifier, RandomSeed, + testing::arb_native_note, ExtractedNoteCommitment, Nullifier, RandomSeed, TransmittedNoteCiphertext, }, + note_encryption::{ + note_version, orchard_parse_note_plaintext_without_memo, NoteCiphertextBytes, + }, primitives::redpallas, value::{NoteValue, ValueCommitment}, Address, Note, }; - use super::{get_note_plaintext_version, orchard_parse_note_plaintext_without_memo}; - proptest! { - #[test] - fn test_encoding_roundtrip( - note in arb_note(NoteValue::from_raw(10)), - ) { - let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; - - // Encode. - let plaintext = OrchardDomain::note_plaintext_bytes(¬e, ¬e.recipient(), memo); - - // Decode. - let domain = OrchardDomain { rho: note.rho() }; - let parsed_version = get_note_plaintext_version(&plaintext); - let parsed_memo = domain.extract_memo(&plaintext); - - let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &plaintext.0, - |diversifier| { - assert_eq!(diversifier, ¬e.recipient().diversifier()); - Some(*note.recipient().pk_d()) - } - ).expect("Plaintext parsing failed"); - - // Check. - assert_eq!(parsed_note, note); - assert_eq!(parsed_recipient, note.recipient()); + #[test] + fn test_encoding_roundtrip( + note in arb_native_note(), + ) { + let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; + + // Encode. + let mut plaintext = OrchardDomainV2::note_plaintext_bytes(¬e, ¬e.recipient(), memo); + + // Decode. + let domain = OrchardDomainV2 { rho: note.rho() }; + let parsed_version = note_version(plaintext.as_mut()).unwrap(); + let (compact,parsed_memo) = domain.extract_memo(&plaintext); + + let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &compact.0, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); - if parsed_note.asset().is_native().into() { - assert_eq!(parsed_version, 0x02); + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); assert_eq!(&parsed_memo, memo); - } else { - assert_eq!(parsed_version, 0x03); - let mut short_memo = *memo; - short_memo[512 - 32..].copy_from_slice(&[0; 32]); - assert_eq!(parsed_memo, short_memo); + assert_eq!(parsed_version, 0x02); } } - } #[test] fn test_vectors() { @@ -509,13 +566,7 @@ mod tests { assert_eq!(ock.as_ref(), tv.ock); let recipient = Address::from_parts(d, pk_d); - - let asset = match tv.asset { - None => AssetId::native(), - Some(type_bytes) => AssetId::from_bytes(&type_bytes).unwrap(), - }; - - let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + let note = Note::from_parts(recipient, value, AssetId::native(), rho, rseed).unwrap(); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); let action = Action::from_parts( @@ -538,7 +589,7 @@ mod tests { // (Tested first because it only requires immutable references.) // - let domain = OrchardDomain { rho }; + let domain = OrchardDomainV2 { rho }; match try_note_decryption(&domain, &ivk, &action) { Some((decrypted_note, decrypted_to, decrypted_memo)) => { @@ -554,8 +605,7 @@ mod tests { assert_eq!(decrypted_note, note); assert_eq!(decrypted_to, recipient); } - None => assert!(tv.asset.is_some(), "Compact note decryption failed"), - // Ignore that ZSA notes are not detected in compact decryption. + None => panic!("Compact note decryption failed"), } match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { diff --git a/src/note_encryption_v2v3.rs b/src/note_encryption_v2v3.rs new file mode 100644 index 000000000..bef34e06e --- /dev/null +++ b/src/note_encryption_v2v3.rs @@ -0,0 +1,717 @@ +//! In-band secret distribution for Orchard bundles. + +use blake2b_simd::{Hash, Params}; +use core::fmt; +use group::ff::PrimeField; +use zcash_note_encryption::{ + BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, + AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, +}; + +use crate::note::AssetId; +use crate::{ + action::Action, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, + IncomingViewingKey, OutgoingViewingKey, SharedSecret, + }, + note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, + spec::diversify_hash, + value::{NoteValue, ValueCommitment}, + Address, Note, +}; + +const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; + +/// The size of a v2 compact note. +pub const COMPACT_NOTE_SIZE_V2: usize = 1 + // version + 11 + // diversifier + 8 + // value + 32; // rseed (or rcm prior to ZIP 212) +/// The size of [`NotePlaintextBytes`] for V2. +pub const NOTE_PLAINTEXT_SIZE_V2: usize = COMPACT_NOTE_SIZE_V2 + MEMO_SIZE; +/// The size of an encrypted note plaintext. +pub const ENC_CIPHERTEXT_SIZE_V2: usize = NOTE_PLAINTEXT_SIZE_V2 + AEAD_TAG_SIZE; + +/// The size of the encoding of a ZSA asset id. +const ZSA_ASSET_SIZE: usize = 32; +/// The size of a v3 compact note. +const COMPACT_NOTE_SIZE_V3: usize = COMPACT_NOTE_SIZE_V2 + ZSA_ASSET_SIZE; +/// The size of [`NotePlaintextBytes`] for V3. +const NOTE_PLAINTEXT_SIZE_V3: usize = COMPACT_NOTE_SIZE_V3 + MEMO_SIZE; +/// The size of the encrypted ciphertext of the ZSA variant of a note. +const ENC_CIPHERTEXT_SIZE_V3: usize = NOTE_PLAINTEXT_SIZE_V3 + AEAD_TAG_SIZE; + +/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. +/// +/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs +pub(crate) fn prf_ock_orchard( + ovk: &OutgoingViewingKey, + cv: &ValueCommitment, + cmx_bytes: &[u8; 32], + ephemeral_key: &EphemeralKeyBytes, +) -> OutgoingCipherKey { + OutgoingCipherKey( + Params::new() + .hash_length(32) + .personal(PRF_OCK_ORCHARD_PERSONALIZATION) + .to_state() + .update(ovk.as_ref()) + .update(&cv.to_bytes()) + .update(cmx_bytes) + .update(ephemeral_key.as_ref()) + .finalize() + .as_bytes() + .try_into() + .unwrap(), + ) +} + +// TODO: VA: Needs updating +/// Domain-specific requirements: +/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. +fn orchard_parse_note_plaintext_without_memo( + domain: &OrchardDomain, + plaintext: &CompactNotePlaintextBytes, + get_validated_pk_d: F, +) -> Option<(Note, Address)> +where + F: FnOnce(&Diversifier) -> Option, +{ + // Check note plaintext version + // and parse the asset type accordingly. + let asset = parse_version_and_asset_type(plaintext)?; + + let mut plaintext_inner = [0u8; COMPACT_NOTE_SIZE_V2]; + match plaintext { + CompactNotePlaintextBytes::V2(x) => { + plaintext_inner.copy_from_slice(&x[..COMPACT_NOTE_SIZE_V2]) + } + CompactNotePlaintextBytes::V3(x) => { + plaintext_inner.copy_from_slice(&x[..COMPACT_NOTE_SIZE_V2]) + } + } + + // The unwraps below are guaranteed to succeed by the assertion above + let diversifier = Diversifier::from_bytes(plaintext_inner[1..12].try_into().unwrap()); + let value = NoteValue::from_bytes(plaintext_inner[12..20].try_into().unwrap()); + let rseed = Option::from(RandomSeed::from_bytes( + plaintext_inner[20..COMPACT_NOTE_SIZE_V2] + .try_into() + .unwrap(), + &domain.rho, + ))?; + + let pk_d = get_validated_pk_d(&diversifier)?; + + let recipient = Address::from_parts(diversifier, pk_d); + let note = Option::from(Note::from_parts(recipient, value, asset, domain.rho, rseed))?; + Some((note, recipient)) +} + +fn parse_version_and_asset_type(plaintext: &CompactNotePlaintextBytes) -> Option { + match plaintext { + CompactNotePlaintextBytes::V2(x) if x[0] == 0x02 => Some(AssetId::native()), + CompactNotePlaintextBytes::V3(x) if x[0] == 0x03 => { + let bytes = x[COMPACT_NOTE_SIZE_V2..COMPACT_NOTE_SIZE_V3] + .try_into() + .unwrap(); + AssetId::from_bytes(bytes).into() + } + _ => None, + } +} + +/// Orchard-specific note encryption logic. +#[derive(Debug)] +pub struct OrchardDomain { + rho: Nullifier, +} + +/// Newtype for encoding the note plaintext post ZSA. +// pub struct NotePlaintextZSA (pub [u8; ZSA_NOTE_PLAINTEXT_SIZE]); +#[derive(Clone, Debug)] +pub enum NotePlaintextBytes { + /// Variant for old note plaintexts. + V2([u8; NOTE_PLAINTEXT_SIZE_V2]), + /// Variant for the new note plaintexts post ZSA. + V3([u8; NOTE_PLAINTEXT_SIZE_V3]), +} + +impl AsMut<[u8]> for NotePlaintextBytes { + fn as_mut(&mut self) -> &mut [u8] { + match self { + NotePlaintextBytes::V2(x) => x.as_mut(), + NotePlaintextBytes::V3(x) => x.as_mut(), + } + } +} + +impl From<&[u8]> for NotePlaintextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + match s.len() { + NOTE_PLAINTEXT_SIZE_V2 => NotePlaintextBytes::V2(s.try_into().unwrap()), + NOTE_PLAINTEXT_SIZE_V3 => NotePlaintextBytes::V3(s.try_into().unwrap()), + _ => panic!("Invalid note plaintext size"), + } + } +} + +/// Newtype for encoding the encrypted note ciphertext post ZSA. +// pub struct EncNoteCiphertextZSA (pub [u8; ZSA_ENC_CIPHERTEXT_SIZE]); +#[derive(Clone, Debug)] +pub enum NoteCiphertextBytes { + /// Variant for old encrypted note ciphertexts. + V2([u8; ENC_CIPHERTEXT_SIZE_V2]), + /// Variant for new encrypted note ciphertexts post ZSA. + V3([u8; ENC_CIPHERTEXT_SIZE_V3]), +} + +impl AsRef<[u8]> for NoteCiphertextBytes { + fn as_ref(&self) -> &[u8] { + match self { + NoteCiphertextBytes::V2(x) => x, + NoteCiphertextBytes::V3(x) => x, + } + } +} + +/// Panics if the given slice is not `ENC_CIPHERTEXT_SIZE_V2` or `ENC_CIPHERTEXT_SIZE_V3` bytes long. +impl From<&[u8]> for NoteCiphertextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + match s.len() { + ENC_CIPHERTEXT_SIZE_V2 => NoteCiphertextBytes::V2(s.try_into().unwrap()), + ENC_CIPHERTEXT_SIZE_V3 => NoteCiphertextBytes::V3(s.try_into().unwrap()), + _ => panic!("Invalid length for compact note plaintext"), + } + } +} + +/// Newtype for encoding a compact note +#[derive(Clone, Debug)] +pub enum CompactNotePlaintextBytes { + /// Variant for old compact notes. + V2([u8; COMPACT_NOTE_SIZE_V2]), + /// Variant for new compact notes post ZSA. + V3([u8; COMPACT_NOTE_SIZE_V3]), +} + +impl AsMut<[u8]> for CompactNotePlaintextBytes { + fn as_mut(&mut self) -> &mut [u8] { + match self { + CompactNotePlaintextBytes::V2(x) => x, + CompactNotePlaintextBytes::V3(x) => x, + } + } +} + +/// Panics if the given slice is not `COMPACT_NOTE_SIZE_V2` or `COMPACT_NOTE_SIZE_V3` bytes long. +impl From<&[u8]> for CompactNotePlaintextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + match s.len() { + COMPACT_NOTE_SIZE_V2 => CompactNotePlaintextBytes::V2(s.try_into().unwrap()), + COMPACT_NOTE_SIZE_V3 => CompactNotePlaintextBytes::V3(s.try_into().unwrap()), + _ => panic!("Invalid length for compact note plaintext"), + } + } +} + +/// Newtype for encoding a compact note +#[derive(Clone, Debug)] +pub enum CompactNoteCiphertextBytes { + /// Variant for old compact notes. + V2([u8; COMPACT_NOTE_SIZE_V2]), + /// Variant for new compact notes post ZSA. + V3([u8; COMPACT_NOTE_SIZE_V3]), +} + +impl AsRef<[u8]> for CompactNoteCiphertextBytes { + fn as_ref(&self) -> &[u8] { + match self { + CompactNoteCiphertextBytes::V2(x) => x, + CompactNoteCiphertextBytes::V3(x) => x, + } + } +} + +impl OrchardDomain { + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_action(act: &Action) -> Self { + OrchardDomain { + rho: *act.nullifier(), + } + } + + /// Constructs a domain from a nullifier. + pub fn for_nullifier(nullifier: Nullifier) -> Self { + OrchardDomain { rho: nullifier } + } +} + +impl Domain for OrchardDomain { + type EphemeralSecretKey = EphemeralSecretKey; + type EphemeralPublicKey = EphemeralPublicKey; + type PreparedEphemeralPublicKey = EphemeralPublicKey; + type SharedSecret = SharedSecret; + type SymmetricKey = Hash; + type Note = Note; + type Recipient = Address; + type DiversifiedTransmissionKey = DiversifiedTransmissionKey; + type IncomingViewingKey = IncomingViewingKey; + type OutgoingViewingKey = OutgoingViewingKey; + type ValueCommitment = ValueCommitment; + type ExtractedCommitment = ExtractedNoteCommitment; + type ExtractedCommitmentBytes = [u8; 32]; + type Memo = [u8; MEMO_SIZE]; // TODO use a more interesting type + + type NotePlaintextBytes = NotePlaintextBytes; + type NoteCiphertextBytes = NoteCiphertextBytes; + type CompactNotePlaintextBytes = CompactNotePlaintextBytes; + type CompactNoteCiphertextBytes = CompactNoteCiphertextBytes; + + fn derive_esk(note: &Self::Note) -> Option { + Some(note.esk()) + } + + fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { + *note.recipient().pk_d() + } + + fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { + epk + } + + fn ka_derive_public( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> Self::EphemeralPublicKey { + esk.derive_public(note.recipient().g_d()) + } + + fn ka_agree_enc( + esk: &Self::EphemeralSecretKey, + pk_d: &Self::DiversifiedTransmissionKey, + ) -> Self::SharedSecret { + esk.agree(pk_d) + } + + fn ka_agree_dec( + ivk: &Self::IncomingViewingKey, + epk: &Self::PreparedEphemeralPublicKey, + ) -> Self::SharedSecret { + epk.agree(ivk) + } + + fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { + secret.kdf_orchard(ephemeral_key) + } + + fn note_plaintext_bytes( + note: &Self::Note, + _: &Self::Recipient, + memo: &Self::Memo, + ) -> NotePlaintextBytes { + let mut np = [0u8; NOTE_PLAINTEXT_SIZE_V3]; + np[0] = 0x03; + np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); + np[12..20].copy_from_slice(¬e.value().to_bytes()); + np[20..52].copy_from_slice(note.rseed().as_bytes()); + let zsa_type = note.asset().to_bytes(); + np[52..84].copy_from_slice(&zsa_type); + np[84..].copy_from_slice(memo); + NotePlaintextBytes::V3(np) + } + + fn derive_ock( + ovk: &Self::OutgoingViewingKey, + cv: &Self::ValueCommitment, + cmstar_bytes: &Self::ExtractedCommitmentBytes, + ephemeral_key: &EphemeralKeyBytes, + ) -> OutgoingCipherKey { + prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) + } + + fn outgoing_plaintext_bytes( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> OutPlaintextBytes { + let mut op = [0; OUT_PLAINTEXT_SIZE]; + op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); + op[32..].copy_from_slice(&esk.0.to_repr()); + OutPlaintextBytes(op) + } + + fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { + epk.to_bytes() + } + + fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { + EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() + } + + fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { + note.commitment().into() + } + + fn parse_note_plaintext_without_memo_ivk( + &self, + ivk: &Self::IncomingViewingKey, + plaintext: &CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { + Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) + }) + } + + fn parse_note_plaintext_without_memo_ovk( + &self, + pk_d: &Self::DiversifiedTransmissionKey, + esk: &Self::EphemeralSecretKey, + ephemeral_key: &EphemeralKeyBytes, + plaintext: &CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { + if esk + .derive_public(diversify_hash(diversifier.as_array())) + .to_bytes() + .0 + == ephemeral_key.0 + { + Some(*pk_d) + } else { + None + } + }) + } + + fn extract_memo( + &self, + plaintext: &NotePlaintextBytes, + ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { + match plaintext { + NotePlaintextBytes::V2(np) => { + let (compact, memo) = np.split_at(COMPACT_NOTE_SIZE_V2); + ( + CompactNotePlaintextBytes::V2(compact.try_into().unwrap()), + memo.try_into().unwrap(), + ) + } + NotePlaintextBytes::V3(np) => { + let (compact, memo) = np.split_at(COMPACT_NOTE_SIZE_V3); + ( + CompactNotePlaintextBytes::V3(compact.try_into().unwrap()), + memo.try_into().unwrap(), + ) + } + } + } + + fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { + DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() + } + + fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { + EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) + .into() + } +} + +impl BatchDomain for OrchardDomain { + fn batch_kdf<'a>( + items: impl Iterator, &'a EphemeralKeyBytes)>, + ) -> Vec> { + let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); + + SharedSecret::batch_to_affine(shared_secrets) + .zip(ephemeral_keys.into_iter()) + .map(|(secret, ephemeral_key)| { + secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) + }) + .collect() + } +} + + +/// Implementation of in-band secret distribution for Orchard bundles. +pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; + +impl ShieldedOutput for Action { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.encrypted_note().epk_bytes) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx().to_bytes() + } + + fn enc_ciphertext(&self) -> Option { + let result = self.encrypted_note().enc_ciphertext.clone(); + Some(result) + } + + fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { + match self.encrypted_note().enc_ciphertext { + NoteCiphertextBytes::V2(ncx) => { + CompactNoteCiphertextBytes::V2(ncx[..COMPACT_NOTE_SIZE_V2].try_into().unwrap()) + } + NoteCiphertextBytes::V3(ncx) => { + CompactNoteCiphertextBytes::V3(ncx[..COMPACT_NOTE_SIZE_V3].try_into().unwrap()) + } + } + } +} + +/// A compact Action for light clients. +pub struct CompactAction { + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: CompactNoteCiphertextBytes, +} + +impl fmt::Debug for CompactAction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "CompactAction") + } +} + +impl From<&Action> for CompactAction { + fn from(action: &Action) -> Self { + let comp_ciphertext: CompactNoteCiphertextBytes = + match action.encrypted_note().enc_ciphertext { + NoteCiphertextBytes::V2(ncx) => { + CompactNoteCiphertextBytes::V2(ncx[..COMPACT_NOTE_SIZE_V2].try_into().unwrap()) + } + NoteCiphertextBytes::V3(ncx) => { + CompactNoteCiphertextBytes::V3(ncx[..COMPACT_NOTE_SIZE_V3].try_into().unwrap()) + } + }; + CompactAction { + nullifier: *action.nullifier(), + cmx: *action.cmx(), + ephemeral_key: action.ephemeral_key(), + enc_ciphertext: comp_ciphertext, + } + } +} + +impl ShieldedOutput for CompactAction { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.ephemeral_key.0) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx.to_bytes() + } + + fn enc_ciphertext(&self) -> Option { + None + } + + fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { + &self.enc_ciphertext + } +} + +impl CompactAction { + /// Create a CompactAction from its constituent parts + pub fn from_parts( + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: CompactNoteCiphertextBytes, + ) -> Self { + Self { + nullifier, + cmx, + ephemeral_key, + enc_ciphertext, + } + } + + ///Returns the nullifier of the note being spent. + pub fn nullifier(&self) -> Nullifier { + self.nullifier + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + use rand::rngs::OsRng; + use zcash_note_encryption::{ + try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, + EphemeralKeyBytes, + }; + + use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; + use crate::note::AssetId; + use crate::note_encryption::NoteCiphertextBytes; + use crate::{ + action::Action, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, + OutgoingViewingKey, + }, + note::{ + testing::arb_note, ExtractedNoteCommitment, Nullifier, RandomSeed, + TransmittedNoteCiphertext, + }, + primitives::redpallas, + value::{NoteValue, ValueCommitment}, + Address, Note, + }; + + use super::{version, orchard_parse_note_plaintext_without_memo}; + + proptest! { + #[test] + fn test_encoding_roundtrip( + note in arb_note(NoteValue::from_raw(100)), + ) { + let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; + + // Encode. + let mut plaintext = OrchardDomain::note_plaintext_bytes(¬e, ¬e.recipient(), memo); + + // Decode. + let domain = OrchardDomain { rho: note.rho() }; + let parsed_version = version(plaintext.as_mut()).unwrap(); + let (mut compact,parsed_memo) = domain.extract_memo(&plaintext); + + let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &compact.as_mut(), + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + assert_eq!(&parsed_memo, memo); + assert_eq!(parsed_version, 0x03); + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::note_encryption::test_vectors(); + + for tv in test_vectors { + // + // Load the test vector components + // + + // Recipient key material + let ivk = IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(); + let ovk = OutgoingViewingKey::from(tv.ovk); + let d = Diversifier::from_bytes(tv.default_d); + let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); + + // Received Action + let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); + let rho = Nullifier::from_bytes(&tv.rho).unwrap(); + let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); + + let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); + let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); + + // Details about the expected note + let value = NoteValue::from_raw(tv.v); + let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); + + // + // Test the individual components + // + + let shared_secret = esk.agree(&pk_d); + assert_eq!(shared_secret.to_bytes(), tv.shared_secret); + + let k_enc = shared_secret.kdf_orchard(&ephemeral_key); + assert_eq!(k_enc.as_bytes(), tv.k_enc); + + let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); + assert_eq!(ock.as_ref(), tv.ock); + + let recipient = Address::from_parts(d, pk_d); + + let asset = match tv.asset { + None => AssetId::native(), + Some(type_bytes) => AssetId::from_bytes(&type_bytes).unwrap(), + }; + + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); + + let action = Action::from_parts( + // rho is the nullifier in the receiving Action. + rho, + // We don't need a valid rk for this test. + redpallas::VerificationKey::dummy(), + cmx, + TransmittedNoteCiphertext { + epk_bytes: ephemeral_key.0, + enc_ciphertext: NoteCiphertextBytes::V3(tv.c_enc), // TODO: VA: Would need a mix of V2 and V3 eventually + out_ciphertext: tv.c_out, + }, + cv_net.clone(), + (), + ); + + // + // Test decryption + // (Tested first because it only requires immutable references.) + // + + let domain = OrchardDomain { rho }; + + match try_note_decryption(&domain, &ivk, &action) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Note decryption failed"), + } + + match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { + Some((decrypted_note, decrypted_to)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + } + None => panic!("Compact note decryption failed"), + } + + match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Output recovery failed"), + } + + // + // Test encryption + // + + let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, recipient, tv.memo); + + // assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); + assert_eq!( + &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], + &tv.c_out[..] + ); + } + } +} diff --git a/src/note_encryption_v3.rs b/src/note_encryption_v3.rs new file mode 100644 index 000000000..c8a772ffe --- /dev/null +++ b/src/note_encryption_v3.rs @@ -0,0 +1,634 @@ +//! In-band secret distribution for Orchard bundles. + +use blake2b_simd::{Hash, Params}; +use core::fmt; +use group::ff::PrimeField; +use zcash_note_encryption::{ + BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, + AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, +}; + +use crate::note::AssetId; +use crate::{ + action::Action, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, + OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, + }, + note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, + spec::diversify_hash, + value::{NoteValue, ValueCommitment}, + Address, Note, +}; + +const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; + +/// The size of a v2 compact note. +pub const COMPACT_NOTE_SIZE_V2: usize = 1 + // version + 11 + // diversifier + 8 + // value + 32; // rseed (or rcm prior to ZIP 212) +/// The size of [`NotePlaintextBytes`] for V2. + +/// The size of the encoding of a ZSA asset id. +const ZSA_ASSET_SIZE: usize = 32; +/// The size of a v3 compact note. +pub const COMPACT_NOTE_SIZE_V3: usize = COMPACT_NOTE_SIZE_V2 + ZSA_ASSET_SIZE; +/// The size of [`NotePlaintextBytes`] for V3. +pub const NOTE_PLAINTEXT_SIZE_V3: usize = COMPACT_NOTE_SIZE_V3 + MEMO_SIZE; +/// The size of the encrypted ciphertext of the ZSA variant of a note. +pub const ENC_CIPHERTEXT_SIZE_V3: usize = NOTE_PLAINTEXT_SIZE_V3 + AEAD_TAG_SIZE; + +/// a type to represent the raw bytes of a note plaintext. +#[derive(Clone, Debug)] +pub struct NotePlaintextBytes(pub [u8; NOTE_PLAINTEXT_SIZE_V3]); + +/// a type to represent the raw bytes of an encrypted note plaintext. +#[derive(Clone, Debug)] +pub struct NoteCiphertextBytes(pub [u8; ENC_CIPHERTEXT_SIZE_V3]); + +/// a type to represent the raw bytes of a compact note. +#[derive(Clone, Debug)] +pub struct CompactNotePlaintextBytes(pub [u8; COMPACT_NOTE_SIZE_V3]); + +/// a type to represent the raw bytes of an encrypted compact note. +#[derive(Clone, Debug)] +pub struct CompactNoteCiphertextBytes(pub [u8; COMPACT_NOTE_SIZE_V3]); + +impl AsMut<[u8]> for NotePlaintextBytes { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl From<&[u8]> for NotePlaintextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + NotePlaintextBytes(s.try_into().unwrap()) + } +} + +impl AsRef<[u8]> for NoteCiphertextBytes { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +impl From<&[u8]> for NoteCiphertextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + NoteCiphertextBytes(s.try_into().unwrap()) + } +} + +impl AsMut<[u8]> for CompactNotePlaintextBytes { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl From<&[u8]> for CompactNotePlaintextBytes { + fn from(s: &[u8]) -> Self + where + Self: Sized, + { + CompactNotePlaintextBytes(s.try_into().unwrap()) + } +} + +impl AsRef<[u8]> for CompactNoteCiphertextBytes { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. +/// +/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs +pub(crate) fn prf_ock_orchard( + ovk: &OutgoingViewingKey, + cv: &ValueCommitment, + cmx_bytes: &[u8; 32], + ephemeral_key: &EphemeralKeyBytes, +) -> OutgoingCipherKey { + OutgoingCipherKey( + Params::new() + .hash_length(32) + .personal(PRF_OCK_ORCHARD_PERSONALIZATION) + .to_state() + .update(ovk.as_ref()) + .update(&cv.to_bytes()) + .update(cmx_bytes) + .update(ephemeral_key.as_ref()) + .finalize() + .as_bytes() + .try_into() + .unwrap(), + ) +} + +/// note_version will return the version of the note plaintext. +pub fn note_version(plaintext: &[u8]) -> Option { + match plaintext[0] { + 0x02 => Some(0x02), + 0x03 => Some(0x03), + _ => None, + } +} + +/// Domain-specific requirements: +/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. +fn orchard_parse_note_plaintext_without_memo( + domain: &OrchardDomainV3, + plaintext: &CompactNotePlaintextBytes, + get_validated_pk_d: F, +) -> Option<(Note, Address)> +where + F: FnOnce(&Diversifier) -> Option, +{ + // The unwraps below are guaranteed to succeed by the assertion above + let diversifier = Diversifier::from_bytes(plaintext.0[1..12].try_into().unwrap()); + let value = NoteValue::from_bytes(plaintext.0[12..20].try_into().unwrap()); + let rseed = Option::from(RandomSeed::from_bytes( + plaintext.0[20..COMPACT_NOTE_SIZE_V2].try_into().unwrap(), + &domain.rho, + ))?; + let pk_d = get_validated_pk_d(&diversifier)?; + let recipient = Address::from_parts(diversifier, pk_d); + + let asset = match note_version(plaintext.0.as_ref())? { + 0x02 => AssetId::native(), + 0x03 => { + let bytes = plaintext.0[COMPACT_NOTE_SIZE_V2..COMPACT_NOTE_SIZE_V3] + .try_into() + .unwrap(); + AssetId::from_bytes(bytes).unwrap() + } + _ => panic!("invalid note version"), + }; + + let note = Option::from(Note::from_parts(recipient, value, asset, domain.rho, rseed))?; + Some((note, recipient)) +} + +/// Orchard-specific note encryption logic. +#[derive(Debug)] +pub struct OrchardDomainV3 { + rho: Nullifier, +} + +impl OrchardDomainV3 { + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_action(act: &Action) -> Self { + OrchardDomainV3 { + rho: *act.nullifier(), + } + } + + /// Constructs a domain from a nullifier. + pub fn for_nullifier(nullifier: Nullifier) -> Self { + OrchardDomainV3 { rho: nullifier } + } +} + +impl Domain for OrchardDomainV3 { + type EphemeralSecretKey = EphemeralSecretKey; + type EphemeralPublicKey = EphemeralPublicKey; + type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; + type SharedSecret = SharedSecret; + type SymmetricKey = Hash; + type Note = Note; + type Recipient = Address; + type DiversifiedTransmissionKey = DiversifiedTransmissionKey; + type IncomingViewingKey = PreparedIncomingViewingKey; + type OutgoingViewingKey = OutgoingViewingKey; + type ValueCommitment = ValueCommitment; + type ExtractedCommitment = ExtractedNoteCommitment; + type ExtractedCommitmentBytes = [u8; 32]; + type Memo = [u8; MEMO_SIZE]; + + type NotePlaintextBytes = NotePlaintextBytes; + type NoteCiphertextBytes = NoteCiphertextBytes; + type CompactNotePlaintextBytes = CompactNotePlaintextBytes; + type CompactNoteCiphertextBytes = CompactNoteCiphertextBytes; + + fn derive_esk(note: &Self::Note) -> Option { + Some(note.esk()) + } + + fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { + *note.recipient().pk_d() + } + + fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { + PreparedEphemeralPublicKey::new(epk) + } + + fn ka_derive_public( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> Self::EphemeralPublicKey { + esk.derive_public(note.recipient().g_d()) + } + + fn ka_agree_enc( + esk: &Self::EphemeralSecretKey, + pk_d: &Self::DiversifiedTransmissionKey, + ) -> Self::SharedSecret { + esk.agree(pk_d) + } + + fn ka_agree_dec( + ivk: &Self::IncomingViewingKey, + epk: &Self::PreparedEphemeralPublicKey, + ) -> Self::SharedSecret { + epk.agree(ivk) + } + + fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { + secret.kdf_orchard(ephemeral_key) + } + + fn note_plaintext_bytes( + note: &Self::Note, + _: &Self::Recipient, + memo: &Self::Memo, + ) -> NotePlaintextBytes { + let mut np = [0u8; NOTE_PLAINTEXT_SIZE_V3]; + np[0] = 0x03; + np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); + np[12..20].copy_from_slice(¬e.value().to_bytes()); + np[20..52].copy_from_slice(note.rseed().as_bytes()); + np[52..84].copy_from_slice(¬e.asset().to_bytes()); + np[84..].copy_from_slice(memo); + NotePlaintextBytes(np) + } + + fn derive_ock( + ovk: &Self::OutgoingViewingKey, + cv: &Self::ValueCommitment, + cmstar_bytes: &Self::ExtractedCommitmentBytes, + ephemeral_key: &EphemeralKeyBytes, + ) -> OutgoingCipherKey { + prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) + } + + fn outgoing_plaintext_bytes( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> OutPlaintextBytes { + let mut op = [0; OUT_PLAINTEXT_SIZE]; + op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); + op[32..].copy_from_slice(&esk.0.to_repr()); + OutPlaintextBytes(op) + } + + fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { + epk.to_bytes() + } + + fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { + EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() + } + + fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { + note.commitment().into() + } + + fn parse_note_plaintext_without_memo_ivk( + &self, + ivk: &Self::IncomingViewingKey, + plaintext: &CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { + Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) + }) + } + + fn parse_note_plaintext_without_memo_ovk( + &self, + pk_d: &Self::DiversifiedTransmissionKey, + esk: &Self::EphemeralSecretKey, + ephemeral_key: &EphemeralKeyBytes, + plaintext: &CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { + if esk + .derive_public(diversify_hash(diversifier.as_array())) + .to_bytes() + .0 + == ephemeral_key.0 + { + Some(*pk_d) + } else { + None + } + }) + } + + fn extract_memo( + &self, + plaintext: &NotePlaintextBytes, + ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { + let (compact, memo) = plaintext.0.split_at(COMPACT_NOTE_SIZE_V3); + ( + CompactNotePlaintextBytes(compact.try_into().unwrap()), + memo.try_into().unwrap(), + ) + } + + fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { + DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() + } + + fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { + EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) + .into() + } +} + +impl BatchDomain for OrchardDomainV3 { + fn batch_kdf<'a>( + items: impl Iterator, &'a EphemeralKeyBytes)>, + ) -> Vec> { + let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); + + SharedSecret::batch_to_affine(shared_secrets) + .zip(ephemeral_keys.into_iter()) + .map(|(secret, ephemeral_key)| { + secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) + }) + .collect() + } +} + +/// Implementation of in-band secret distribution for Orchard bundles. +pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; + +impl ShieldedOutput for Action { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.encrypted_note().epk_bytes) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx().to_bytes() + } + + fn enc_ciphertext(&self) -> Option { + Some(NoteCiphertextBytes(self.encrypted_note().enc_ciphertext)) + } + + fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { + CompactNoteCiphertextBytes( + self.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V3] + .try_into() + .unwrap(), + ) + } +} + +/// A compact Action for light clients. +pub struct CompactAction { + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: CompactNoteCiphertextBytes, +} + +impl fmt::Debug for CompactAction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "CompactAction") + } +} + +impl From<&Action> for CompactAction +where + Action: ShieldedOutput, +{ + fn from(action: &Action) -> Self { + CompactAction { + nullifier: *action.nullifier(), + cmx: *action.cmx(), + ephemeral_key: action.ephemeral_key(), + enc_ciphertext: CompactNoteCiphertextBytes( + action.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V3] + .try_into() + .unwrap(), + ), + } + } +} + +impl ShieldedOutput for CompactAction { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.ephemeral_key.0) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx.to_bytes() + } + + fn enc_ciphertext(&self) -> Option { + None + } + + fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { + self.enc_ciphertext.clone() + } +} + +impl CompactAction { + /// Create a CompactAction from its constituent parts + pub fn from_parts( + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: CompactNoteCiphertextBytes, + ) -> Self { + Self { + nullifier, + cmx, + ephemeral_key, + enc_ciphertext, + } + } + + ///Returns the nullifier of the note being spent. + pub fn nullifier(&self) -> Nullifier { + self.nullifier + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + use rand::rngs::OsRng; + use zcash_note_encryption::{ + try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, + EphemeralKeyBytes, + }; + + use super::{ + note_version, orchard_parse_note_plaintext_without_memo, prf_ock_orchard, CompactAction, + OrchardDomainV3, OrchardNoteEncryption, + }; + use crate::{ + action::Action, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, + OutgoingViewingKey, PreparedIncomingViewingKey, + }, + note::{ + testing::arb_note, AssetId, ExtractedNoteCommitment, Nullifier, RandomSeed, + TransmittedNoteCiphertext, + }, + primitives::redpallas, + value::{NoteValue, ValueCommitment}, + Address, Note, + }; + + proptest! { + #[test] + fn test_encoding_roundtrip( + note in arb_note(NoteValue::from_raw(100)), + ) { + let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; + + // Encode. + let mut plaintext = OrchardDomainV3::note_plaintext_bytes(¬e, ¬e.recipient(), memo); + + // Decode. + let domain = OrchardDomainV3 { rho: note.rho() }; + let parsed_version = note_version(plaintext.as_mut()).unwrap(); + let (compact,parsed_memo) = domain.extract_memo(&plaintext); + + let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &compact, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + assert_eq!(&parsed_memo, memo); + assert_eq!(parsed_version, 0x03); + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::note_encryption_v3::test_vectors(); + + for tv in test_vectors { + // + // Load the test vector components + // + + // Recipient key material + let ivk = PreparedIncomingViewingKey::new( + &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), + ); + let ovk = OutgoingViewingKey::from(tv.ovk); + let d = Diversifier::from_bytes(tv.default_d); + let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); + + // Received Action + let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); + let rho = Nullifier::from_bytes(&tv.rho).unwrap(); + let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); + + let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); + let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); + + // Details about the expected note + let value = NoteValue::from_raw(tv.v); + let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); + + // + // Test the individual components + // + + let shared_secret = esk.agree(&pk_d); + assert_eq!(shared_secret.to_bytes(), tv.shared_secret); + + let k_enc = shared_secret.kdf_orchard(&ephemeral_key); + assert_eq!(k_enc.as_bytes(), tv.k_enc); + + let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); + assert_eq!(ock.as_ref(), tv.ock); + + let recipient = Address::from_parts(d, pk_d); + + let asset = AssetId::from_bytes(&tv.asset).unwrap(); + + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); + + let action = Action::from_parts( + // rho is the nullifier in the receiving Action. + rho, + // We don't need a valid rk for this test. + redpallas::VerificationKey::dummy(), + cmx, + TransmittedNoteCiphertext { + epk_bytes: ephemeral_key.0, + enc_ciphertext: tv.c_enc, + out_ciphertext: tv.c_out, + }, + cv_net.clone(), + (), + ); + + // + // Test decryption + // (Tested first because it only requires immutable references.) + // + + let domain = OrchardDomainV3 { rho }; + + match try_note_decryption(&domain, &ivk, &action) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Note decryption failed"), + } + + match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { + Some((decrypted_note, decrypted_to)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + } + None => panic!("Compact note decryption failed"), + } + + match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Output recovery failed"), + } + + // + // Test encryption + // + + let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, recipient, tv.memo); + + assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); + assert_eq!( + &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], + &tv.c_out[..] + ); + } + } +} diff --git a/src/test_vectors.rs b/src/test_vectors.rs index b70b56e56..945cfc2b7 100644 --- a/src/test_vectors.rs +++ b/src/test_vectors.rs @@ -3,3 +3,4 @@ pub(crate) mod commitment_tree; pub(crate) mod keys; pub(crate) mod merkle_path; pub(crate) mod note_encryption; +pub(crate) mod note_encryption_v3; diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption.rs index f1c6126cc..7a5a73a56 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption.rs @@ -1,6 +1,5 @@ -// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_note_encryption) - pub(crate) struct TestVector { + // make all fields public so we can use them in the test pub(crate) incoming_viewing_key: [u8; 64], pub(crate) ovk: [u8; 32], pub(crate) default_d: [u8; 11], @@ -20,9 +19,9 @@ pub(crate) struct TestVector { pub(crate) ock: [u8; 32], pub(crate) op: [u8; 64], pub(crate) c_out: [u8; 80], - pub(crate) asset: Option<[u8; 32]>, } +// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_note_encryption.py pub(crate) fn test_vectors() -> Vec { vec![ TestVector { @@ -233,7 +232,6 @@ pub(crate) fn test_vectors() -> Vec { 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -443,7 +441,6 @@ pub(crate) fn test_vectors() -> Vec { 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -653,7 +650,6 @@ pub(crate) fn test_vectors() -> Vec { 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -863,7 +859,6 @@ pub(crate) fn test_vectors() -> Vec { 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -1073,7 +1068,6 @@ pub(crate) fn test_vectors() -> Vec { 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -1283,7 +1277,6 @@ pub(crate) fn test_vectors() -> Vec { 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -1493,7 +1486,6 @@ pub(crate) fn test_vectors() -> Vec { 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -1703,7 +1695,6 @@ pub(crate) fn test_vectors() -> Vec { 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -1913,7 +1904,6 @@ pub(crate) fn test_vectors() -> Vec { 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, ], - asset: None, }, TestVector { incoming_viewing_key: [ @@ -2123,2147 +2113,6 @@ pub(crate) fn test_vectors() -> Vec { 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, ], - asset: None, - }, - TestVector { - incoming_viewing_key: [ - 0xdc, 0x10, 0x95, 0x20, 0x57, 0xc4, 0xbe, 0xaa, 0xd8, 0xaf, 0x37, 0xce, 0x4e, 0xee, - 0x9b, 0x10, 0xed, 0x84, 0xf4, 0x6b, 0xad, 0xd4, 0x8e, 0x0a, 0x22, 0x9b, 0xe8, 0x41, - 0x54, 0xa9, 0xbf, 0x75, 0x6b, 0xe0, 0x2e, 0xcf, 0xa9, 0xad, 0x6d, 0x9c, 0x02, 0xc8, - 0xf9, 0x54, 0xcb, 0x15, 0x71, 0x7b, 0x79, 0x46, 0x1f, 0x00, 0x4b, 0xf1, 0xbc, 0x5c, - 0x7e, 0x3f, 0xda, 0x73, 0x53, 0x7c, 0x1a, 0x0a, - ], - ovk: [ - 0x97, 0x74, 0x85, 0xcd, 0xdf, 0xbe, 0xd5, 0x93, 0x2f, 0x50, 0x7b, 0x79, 0x94, 0x7a, - 0xdb, 0x2f, 0xad, 0x37, 0x61, 0x5a, 0xa7, 0x17, 0xdb, 0x5f, 0x29, 0x80, 0x99, 0xf2, - 0x0f, 0x26, 0x3b, 0x35, - ], - default_d: [ - 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, - ], - default_pk_d: [ - 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, - 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, - 0xe6, 0x84, 0x45, 0xbb, - ], - v: 2111628168871420429, - rseed: [ - 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, - 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, - 0x3b, 0xd5, 0xbc, 0x87, - ], - memo: [ - 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, - 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, - 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, - 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, - 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, - 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, - 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, - 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, - 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, - 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, - 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, - 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, - 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, - 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, - 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, - 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, - 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, - 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, - 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, - 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, - 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, - 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, - 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, - 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, - 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, - 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, - 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, - 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, - 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, - 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, - 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, - 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, - 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, - 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, - 0xd8, 0x02, 0xf7, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0xba, 0x69, 0x9c, 0xe4, 0x21, 0x41, 0x85, 0x30, 0x94, 0xe2, 0x84, 0x00, 0x50, 0x17, - 0x2c, 0x3b, 0x94, 0x21, 0x3e, 0x86, 0x47, 0x3b, 0x5e, 0x2f, 0xdd, 0x70, 0x97, 0x80, - 0xbc, 0xca, 0x68, 0xb4, - ], - rho: [ - 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, - 0xa9, 0x4a, 0x06, 0x04, 0xb8, 0x00, 0x6c, 0xc7, 0x94, 0xbc, 0xab, 0x57, 0x73, 0x49, - 0xbc, 0xf8, 0x63, 0x37, - ], - cmx: [ - 0x85, 0xec, 0x16, 0xe8, 0x78, 0x77, 0x33, 0x37, 0x07, 0x9a, 0xec, 0xf3, 0x2c, 0x45, - 0x5e, 0xbf, 0x16, 0x96, 0x8d, 0xa1, 0xd4, 0x34, 0x51, 0xb7, 0xa3, 0x06, 0x87, 0x6c, - 0xa3, 0x08, 0xea, 0x3c, - ], - esk: [ - 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, 0x39, 0x16, 0x0f, 0xe5, - 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, 0xe0, 0xd2, 0x9b, 0x35, - 0x9a, 0xc4, 0xfa, 0x2c, - ], - ephemeral_key: [ - 0x10, 0x0d, 0xf0, 0x1d, 0x49, 0x86, 0x01, 0x21, 0x8a, 0x28, 0x6b, 0x8f, 0x4e, 0x54, - 0xda, 0x9b, 0x3f, 0x14, 0x5c, 0x34, 0x70, 0xa9, 0xdb, 0xc4, 0x14, 0x48, 0x0a, 0xa8, - 0xf2, 0xf4, 0x90, 0x9c, - ], - shared_secret: [ - 0x93, 0x68, 0xdd, 0x4f, 0x2a, 0xf6, 0x23, 0x34, 0xb8, 0x85, 0xb9, 0x6b, 0xc4, 0xc3, - 0x8f, 0x10, 0x3a, 0xec, 0x25, 0x6b, 0xed, 0xc2, 0x8b, 0x5e, 0x2e, 0x10, 0x36, 0x4c, - 0xdd, 0xf3, 0x84, 0xa4, - ], - k_enc: [ - 0x7a, 0xff, 0xfc, 0x6e, 0xae, 0x5d, 0x56, 0xb2, 0x7b, 0x86, 0xdb, 0x9e, 0xc8, 0xae, - 0xc2, 0x70, 0xbb, 0x0a, 0xb7, 0x31, 0x23, 0xfd, 0x2a, 0x0b, 0x83, 0xf4, 0xef, 0x84, - 0xc6, 0x98, 0xe1, 0x67, - ], - p_enc: [ - 0x03, 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, 0x0d, 0x22, - 0x4a, 0xb7, 0xa1, 0x02, 0x4e, 0x1d, 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, - 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, - 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, 0x3b, 0xd5, 0xbc, 0x87, 0xa9, 0x71, 0x5e, 0x65, - 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, 0x84, 0xef, 0xd9, 0x2c, - 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, 0x4f, 0x95, 0x22, 0xb2, - 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, - 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, - 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, - 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, - 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, - 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, - 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, - 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, - 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, - 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, - 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, - 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, - 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, - 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, - 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, - 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, - 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, - 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, - 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, - 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, - 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, - 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, - 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, - 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, - 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, - 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, - 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, - 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, - 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, - 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, - 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, - 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, - 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, - 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, - 0xd8, 0x02, 0xf7, 0x73, - ], - c_enc: [ - 0x45, 0x6b, 0x2b, 0xb8, 0x03, 0xc7, 0xdf, 0xf7, 0xac, 0x82, 0xe6, 0x42, 0xf4, 0xd8, - 0x46, 0x1e, 0x0b, 0x7a, 0x3b, 0x3c, 0x95, 0xa4, 0xcb, 0xf1, 0xc0, 0x6f, 0xeb, 0x93, - 0xa1, 0x8b, 0xeb, 0xa2, 0x9f, 0x2b, 0x8f, 0x12, 0x1a, 0x61, 0x5c, 0xa5, 0x3f, 0xc2, - 0xa7, 0x60, 0x63, 0xb8, 0x0d, 0xaa, 0x71, 0x01, 0x8b, 0x66, 0x3b, 0x7c, 0x46, 0x6d, - 0xb2, 0x63, 0xf9, 0x04, 0x27, 0xd0, 0x11, 0x7f, 0x0b, 0x89, 0x90, 0x6e, 0x98, 0x41, - 0x7f, 0x3e, 0xe8, 0x5a, 0xcc, 0xed, 0xb1, 0x41, 0xfb, 0x10, 0x26, 0xa3, 0xb3, 0xf7, - 0xa4, 0xfd, 0x10, 0x24, 0xf9, 0xc8, 0x08, 0x9a, 0x2e, 0xbe, 0x1a, 0x27, 0x82, 0xf8, - 0xb0, 0xbf, 0x5c, 0x40, 0xb6, 0xd5, 0x2f, 0xfe, 0x38, 0x37, 0xf4, 0xe4, 0x42, 0x52, - 0x13, 0x41, 0xc2, 0x4d, 0x3e, 0x89, 0x55, 0x95, 0x08, 0x86, 0x27, 0x85, 0xea, 0x63, - 0x56, 0xb4, 0xe4, 0x66, 0xc3, 0x25, 0x9c, 0xeb, 0x0d, 0x28, 0x2e, 0x07, 0xbb, 0x35, - 0xdc, 0xf2, 0xd9, 0xa8, 0x62, 0xc7, 0x47, 0x58, 0xd3, 0x83, 0xaa, 0xa2, 0x82, 0xfa, - 0xc4, 0xfa, 0xcf, 0xe5, 0x39, 0xe4, 0xe1, 0xbb, 0xd5, 0x46, 0x8a, 0xcf, 0x25, 0xec, - 0x2b, 0x4b, 0xa5, 0x11, 0x9d, 0xea, 0xed, 0x01, 0x1d, 0x4f, 0x30, 0xb0, 0xc5, 0x82, - 0x01, 0xfe, 0xe1, 0xc6, 0xe4, 0xf6, 0xb5, 0x2e, 0x41, 0xad, 0xfa, 0x5d, 0x6f, 0xda, - 0x94, 0xa5, 0x23, 0x20, 0xe8, 0x3b, 0x80, 0xc6, 0xfc, 0xee, 0xb8, 0x97, 0x89, 0xd8, - 0x79, 0x94, 0xb7, 0xa0, 0x16, 0xec, 0x64, 0xe4, 0x70, 0x78, 0x07, 0xf8, 0xf2, 0xd2, - 0x30, 0x63, 0x10, 0x74, 0x10, 0x9f, 0xc5, 0x9d, 0xe3, 0xe4, 0x37, 0x10, 0xca, 0xe8, - 0x9c, 0xb1, 0x89, 0xa0, 0xa4, 0x64, 0x8b, 0x37, 0x54, 0x5d, 0x25, 0x49, 0x47, 0x95, - 0xa8, 0xdf, 0x3f, 0xfc, 0x7a, 0x3a, 0x21, 0xe3, 0xb9, 0x1c, 0x95, 0x96, 0xe0, 0xd5, - 0x10, 0x5d, 0xf8, 0xad, 0xa9, 0xcf, 0xe9, 0x31, 0x10, 0xb1, 0x9f, 0xf2, 0xaf, 0x83, - 0x03, 0xb5, 0xd2, 0x79, 0x3f, 0xff, 0xd0, 0x4d, 0x8e, 0x02, 0xf7, 0xb9, 0x30, 0x14, - 0x80, 0xdf, 0xd9, 0x35, 0x50, 0x2d, 0x98, 0xe2, 0xf3, 0xc3, 0xe9, 0xe9, 0x5e, 0x64, - 0xe4, 0x96, 0xeb, 0x7d, 0x15, 0xcf, 0x2c, 0x70, 0x11, 0x94, 0xe6, 0x25, 0xde, 0x52, - 0x1a, 0x02, 0x55, 0x20, 0xdf, 0x67, 0xac, 0x2b, 0xa4, 0x3b, 0x9c, 0x4a, 0x6d, 0x77, - 0xb8, 0x6a, 0x40, 0x18, 0x2d, 0x70, 0x31, 0x8b, 0x8f, 0xa3, 0x48, 0xb1, 0x86, 0x47, - 0xd8, 0x4e, 0x0e, 0xe5, 0xf0, 0x56, 0x07, 0xa2, 0xb8, 0xf2, 0x69, 0xe1, 0x86, 0xc7, - 0x94, 0x28, 0xbe, 0xa6, 0x7c, 0xbf, 0x71, 0xda, 0xcc, 0x98, 0xe9, 0xcc, 0x72, 0x5e, - 0x50, 0x53, 0xa4, 0x40, 0xca, 0xa6, 0xca, 0xd2, 0x41, 0xa5, 0x06, 0x28, 0x18, 0x3a, - 0xe9, 0xef, 0x9f, 0x0c, 0xbd, 0xfe, 0xf7, 0x0a, 0x42, 0xe5, 0xb7, 0x97, 0xbc, 0x99, - 0xd9, 0x22, 0xfc, 0xc2, 0x81, 0x37, 0x84, 0xea, 0xe4, 0x48, 0x60, 0x18, 0x0e, 0xf8, - 0xe8, 0x1f, 0x7b, 0x94, 0xf2, 0xad, 0x62, 0x12, 0x8b, 0xb6, 0x1f, 0x10, 0xd5, 0x0c, - 0x9c, 0xad, 0x9d, 0x80, 0x48, 0xd9, 0x78, 0x01, 0x8a, 0x1f, 0x3b, 0xc9, 0x24, 0x28, - 0xf8, 0x9d, 0x7d, 0xdc, 0xe5, 0x45, 0x4b, 0xc4, 0x49, 0x1f, 0xb4, 0xc2, 0xcb, 0x66, - 0x88, 0x35, 0xb2, 0x2f, 0xcc, 0x4d, 0xf2, 0x08, 0xf2, 0x16, 0x64, 0xf7, 0x12, 0x94, - 0xc5, 0xce, 0xd3, 0x3c, 0x8e, 0x11, 0xd4, 0x25, 0xd1, 0x39, 0x85, 0x23, 0xc2, 0x79, - 0x88, 0x3a, 0x38, 0x2f, 0x70, 0xfe, 0xfe, 0xc8, 0x25, 0xc5, 0xe3, 0x50, 0x85, 0xaf, - 0x82, 0xd0, 0xa0, 0xa9, 0xbf, 0x45, 0x11, 0x65, 0x0a, 0x2b, 0xfb, 0xf0, 0xb2, 0x18, - 0x82, 0x10, 0x5e, 0xc6, 0xe5, 0x99, 0x74, 0xd8, 0xd6, 0xce, 0x73, 0x07, 0x8f, 0xb4, - 0xb5, 0x63, 0x4e, 0x85, 0xd7, 0xe2, 0x0a, 0x97, 0xff, 0xb6, 0x5d, 0x4f, 0x5e, 0xaf, - 0x42, 0x63, 0x9b, 0x09, 0xf5, 0xed, 0xa5, 0x9a, 0xb1, 0x04, 0x97, 0x69, 0x95, 0x41, - 0xd1, 0xc8, 0x22, 0x8e, 0xb5, 0xdf, 0x47, 0xa6, 0x67, 0xc4, 0x6d, 0x4c, 0xff, 0xeb, - 0xfe, 0x3f, 0xbb, 0x0a, 0x4e, 0x48, - ], - ock: [ - 0xc6, 0x7c, 0x23, 0x33, 0xc3, 0xcf, 0x4a, 0xc4, 0x6e, 0xde, 0x34, 0xe3, 0xe3, 0xe0, - 0xdb, 0xff, 0x1e, 0x96, 0xb7, 0xa7, 0x8f, 0x16, 0xaa, 0xef, 0x1c, 0x74, 0xa3, 0xef, - 0x07, 0xc5, 0x97, 0x16, - ], - op: [ - 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, - 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, - 0xe6, 0x84, 0x45, 0xbb, 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, - 0x39, 0x16, 0x0f, 0xe5, 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, - 0xe0, 0xd2, 0x9b, 0x35, 0x9a, 0xc4, 0xfa, 0x2c, - ], - c_out: [ - 0xe4, 0xba, 0x0e, 0xa2, 0x92, 0x3b, 0x40, 0x19, 0xac, 0x8a, 0xbc, 0xd1, 0x9b, 0xe6, - 0x1c, 0x90, 0xf1, 0x8e, 0xef, 0xae, 0x87, 0xc4, 0xed, 0x8c, 0x76, 0x70, 0x85, 0xba, - 0xa8, 0x3b, 0x4d, 0x61, 0x0c, 0xf3, 0x63, 0x70, 0xda, 0x07, 0x90, 0x1e, 0xad, 0x6d, - 0x4f, 0x4b, 0x71, 0xdc, 0xae, 0x31, 0x1f, 0xa0, 0x36, 0x40, 0x6d, 0x64, 0x7b, 0x7e, - 0xe1, 0x41, 0x1e, 0xf5, 0xae, 0xe0, 0x34, 0x68, 0xb1, 0x09, 0x13, 0xc9, 0x90, 0xcb, - 0x61, 0x61, 0x22, 0xeb, 0xbe, 0x49, 0xda, 0x67, 0x81, 0xc2, - ], - asset: Some([ - 0xa9, 0x71, 0x5e, 0x65, 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, - 0x84, 0xef, 0xd9, 0x2c, 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, - 0x4f, 0x95, 0x22, 0xb2, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0xb6, 0x6c, 0x73, 0x33, 0x75, 0xda, 0xc6, 0xff, 0xcc, 0x98, 0xf5, 0x0f, 0x3a, 0xf0, - 0xb0, 0x76, 0x05, 0x53, 0xfe, 0x98, 0xed, 0x61, 0xff, 0xa4, 0x93, 0xea, 0xe6, 0x8d, - 0xf0, 0xb3, 0x33, 0x4e, 0xe8, 0xd4, 0x39, 0x37, 0xb7, 0xdb, 0x8e, 0xbb, 0xfe, 0xbd, - 0x54, 0x8a, 0x28, 0x02, 0x51, 0xea, 0x87, 0xaa, 0x5d, 0x8c, 0xa5, 0x36, 0x86, 0x1b, - 0x38, 0x4f, 0x20, 0x86, 0x9f, 0x8f, 0xe8, 0x01, - ], - ovk: [ - 0xe9, 0x4c, 0x15, 0x24, 0x5f, 0x1a, 0x95, 0x88, 0x40, 0xba, 0x3f, 0x38, 0x0a, 0x4d, - 0x20, 0xf1, 0x18, 0x4e, 0x77, 0x82, 0x7d, 0xe3, 0xff, 0x8f, 0x3d, 0x73, 0x45, 0x9a, - 0xfe, 0x24, 0x1f, 0x72, - ], - default_d: [ - 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, - ], - default_pk_d: [ - 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, - 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, - 0x25, 0xc8, 0xd6, 0xae, - ], - v: 16065731808124965111, - rseed: [ - 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, - 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, - 0x71, 0x8c, 0x29, 0xdd, - ], - memo: [ - 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, - 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, - 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, - 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, - 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, - 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, - 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, - 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, - 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, - 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, - 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, - 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, - 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, - 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, - 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, - 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, - 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, - 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, - 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, - 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, - 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, - 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, - 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, - 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, - 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, - 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, - 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, - 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, - 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, - 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, - 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, - 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, - 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, - 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, - 0xb6, 0x50, 0x82, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x0a, 0x1f, 0x28, 0x15, 0xb7, 0xaf, 0xe2, 0x19, 0x06, 0x87, 0x15, 0xfc, 0x76, 0x6b, - 0x87, 0x2e, 0xf2, 0x17, 0x35, 0x43, 0xac, 0x81, 0x4c, 0x32, 0xb4, 0xb6, 0x9c, 0x9c, - 0x34, 0x5e, 0x46, 0x98, - ], - rho: [ - 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, - 0x51, 0x1c, 0x9b, 0xab, 0x65, 0xb6, 0xd8, 0xd5, 0xc5, 0xbd, 0x1e, 0x32, 0x77, 0x1a, - 0xb6, 0xf6, 0x4c, 0x26, - ], - cmx: [ - 0x40, 0x8f, 0x59, 0x4f, 0xdd, 0xc5, 0x0c, 0x67, 0xf5, 0x47, 0xe1, 0xeb, 0x3e, 0xa2, - 0x99, 0xa3, 0x1f, 0x69, 0xf5, 0x7f, 0xc9, 0x92, 0x03, 0x01, 0x42, 0x90, 0x35, 0xa6, - 0xc2, 0x49, 0x79, 0x1a, - ], - esk: [ - 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, 0xef, 0x08, 0xbd, 0xf6, - 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, 0xf5, 0x3b, 0x57, 0xc3, - 0x45, 0xa9, 0x87, 0x2f, - ], - ephemeral_key: [ - 0xa5, 0xc8, 0x0a, 0x29, 0xf2, 0xec, 0xdd, 0xd7, 0x01, 0x96, 0xef, 0x45, 0x9e, 0xd5, - 0x03, 0xc4, 0xb3, 0xc2, 0x22, 0x8d, 0x10, 0xcc, 0xbc, 0xad, 0x9a, 0x28, 0x23, 0x30, - 0x07, 0x7b, 0xca, 0x0c, - ], - shared_secret: [ - 0x37, 0x14, 0x15, 0xfc, 0x1e, 0x98, 0x42, 0xa1, 0x26, 0xa3, 0x7a, 0xa7, 0x7b, 0x8f, - 0x0f, 0x1a, 0xb6, 0x48, 0xa3, 0xf7, 0x43, 0x57, 0x34, 0x89, 0x6f, 0x07, 0x59, 0x52, - 0xe7, 0xd1, 0x60, 0x17, - ], - k_enc: [ - 0xd7, 0x36, 0xf0, 0x3c, 0x81, 0x2d, 0x9b, 0xf9, 0x54, 0xff, 0xd2, 0x41, 0x84, 0x07, - 0xf3, 0x36, 0xa5, 0xf9, 0x69, 0x8b, 0x62, 0x85, 0x23, 0x2f, 0x5c, 0x85, 0xf0, 0xd1, - 0x1d, 0x5e, 0x9d, 0x0a, - ], - p_enc: [ - 0x03, 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, 0xf7, 0x90, - 0xfb, 0xa7, 0xf5, 0xf1, 0xf4, 0xde, 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, - 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, - 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, 0x71, 0x8c, 0x29, 0xdd, 0xdf, 0xfd, 0x79, 0xa9, - 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, 0x01, 0xe2, 0x99, 0x0a, - 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, 0xfd, 0x7d, 0x05, 0x8a, - 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, - 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, - 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, - 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, - 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, - 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, - 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, - 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, - 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, - 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, - 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, - 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, - 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, - 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, - 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, - 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, - 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, - 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, - 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, - 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, - 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, - 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, - 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, - 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, - 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, - 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, - 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, - 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, - 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, - 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, - 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, - 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, - 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, - 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, - 0xb6, 0x50, 0x82, 0xa6, - ], - c_enc: [ - 0xfc, 0x90, 0xcb, 0xe1, 0xcd, 0x9f, 0x59, 0x9a, 0x1a, 0x24, 0xc7, 0xa3, 0xea, 0xf6, - 0x07, 0xd9, 0x13, 0xbf, 0x48, 0xbd, 0xc1, 0xa4, 0x6d, 0xf7, 0xb1, 0x74, 0x7f, 0x12, - 0x60, 0x64, 0x49, 0x4b, 0xf5, 0x39, 0x61, 0xe9, 0xa5, 0xa2, 0xb9, 0x69, 0x80, 0x57, - 0x63, 0x44, 0x2e, 0x2c, 0x38, 0x8d, 0x21, 0x2d, 0x74, 0x84, 0x6e, 0x57, 0x27, 0x87, - 0x2d, 0x06, 0x3f, 0xc9, 0x94, 0xa4, 0x4f, 0x9e, 0xb6, 0x55, 0x25, 0xd6, 0x8f, 0x98, - 0x24, 0xa6, 0x03, 0x75, 0xfe, 0x43, 0xc0, 0x5f, 0x08, 0xfe, 0x45, 0x42, 0xa7, 0xe4, - 0x0c, 0x03, 0x8d, 0xe7, 0x10, 0x85, 0x01, 0x17, 0x95, 0x1b, 0x9a, 0x32, 0x1e, 0xea, - 0x4f, 0x8c, 0x91, 0xc0, 0x1d, 0x39, 0xdb, 0xb5, 0xd4, 0x12, 0x40, 0xf8, 0xb1, 0xb1, - 0xdb, 0xb3, 0x3f, 0x45, 0x87, 0x87, 0xdb, 0x8c, 0xda, 0x06, 0x9b, 0x64, 0x5a, 0x76, - 0x38, 0xc2, 0xec, 0xca, 0xd3, 0xd9, 0xa7, 0x39, 0xd6, 0x4c, 0x9a, 0xd5, 0xd5, 0xb3, - 0xa0, 0x24, 0x55, 0xa4, 0xec, 0xd6, 0x96, 0x7c, 0xf3, 0xb3, 0x3b, 0xf0, 0x4e, 0xf6, - 0xdd, 0x88, 0x10, 0xe1, 0x0c, 0x25, 0x86, 0xf7, 0x89, 0x32, 0x44, 0xea, 0x72, 0x80, - 0xd1, 0x34, 0xcf, 0x37, 0xb3, 0xdc, 0x0c, 0x32, 0x82, 0x3b, 0x1a, 0x29, 0xc5, 0x0c, - 0xa6, 0x48, 0x31, 0xd8, 0x4e, 0xbd, 0xf5, 0xe0, 0x1c, 0x14, 0xca, 0x36, 0x05, 0xbe, - 0x02, 0xf1, 0x5f, 0x31, 0x57, 0x90, 0xf7, 0x4e, 0x20, 0x57, 0x7f, 0x92, 0x39, 0x51, - 0x2f, 0xbd, 0xdd, 0x67, 0x63, 0x77, 0xae, 0x50, 0xc3, 0xfe, 0x71, 0xc9, 0x30, 0xa8, - 0x29, 0x57, 0xd1, 0x54, 0x70, 0xeb, 0x1b, 0x55, 0xb2, 0x0c, 0xe5, 0x02, 0x35, 0x64, - 0xfe, 0xa7, 0xe1, 0x81, 0xbe, 0x04, 0xa9, 0x33, 0xa7, 0xa3, 0xa1, 0x11, 0x89, 0x4d, - 0xec, 0xf7, 0x2a, 0x56, 0x54, 0xcb, 0x4e, 0xac, 0x32, 0xe1, 0xd5, 0x96, 0xad, 0x99, - 0x1a, 0x2f, 0x4c, 0x62, 0xe8, 0xe2, 0x82, 0x57, 0x13, 0x7b, 0xcb, 0xa5, 0x03, 0xdc, - 0x91, 0xed, 0x9e, 0x90, 0xb3, 0x08, 0xcd, 0xa5, 0xcc, 0xcc, 0xc9, 0xd1, 0x4e, 0xa6, - 0xd0, 0x3b, 0x3d, 0xec, 0xa1, 0x57, 0xd5, 0x30, 0xde, 0x63, 0x1e, 0x1e, 0x45, 0x8f, - 0x6a, 0x60, 0x8e, 0x1f, 0x9d, 0x57, 0x9b, 0x6e, 0xe6, 0x00, 0x5c, 0xd0, 0xa8, 0xc3, - 0xe2, 0xdf, 0x89, 0x46, 0x8a, 0xcf, 0xb4, 0x36, 0xcb, 0x59, 0x84, 0x56, 0xf0, 0x38, - 0x95, 0x5d, 0xc6, 0xb4, 0x07, 0xec, 0x33, 0x00, 0xa5, 0xcf, 0xcd, 0xc8, 0x45, 0x47, - 0xe3, 0xef, 0xe9, 0xfc, 0xa1, 0x7e, 0xd2, 0xc2, 0x74, 0xf0, 0x03, 0x0b, 0x63, 0xcc, - 0x42, 0xe2, 0x38, 0x94, 0xa5, 0xf2, 0x53, 0x66, 0xcb, 0xc3, 0xbf, 0xcb, 0x77, 0x2d, - 0x04, 0x17, 0xf6, 0x24, 0x4b, 0x2f, 0xd8, 0x17, 0xc4, 0xc6, 0x79, 0x06, 0xc3, 0x38, - 0x4d, 0x69, 0xd7, 0x93, 0xef, 0xca, 0x6e, 0x5d, 0x6a, 0xf2, 0x5e, 0x4e, 0xbc, 0x0f, - 0x53, 0x56, 0xeb, 0x74, 0x28, 0x85, 0x19, 0xe8, 0xf4, 0x49, 0x38, 0xeb, 0xf9, 0xb2, - 0x5b, 0xe5, 0x85, 0xe1, 0x35, 0x1f, 0x62, 0x59, 0x6c, 0x31, 0x79, 0xca, 0xe4, 0x5e, - 0x75, 0x49, 0xd7, 0xfb, 0xb5, 0x91, 0x3b, 0xe9, 0xc3, 0xba, 0xa5, 0x7c, 0xab, 0x7c, - 0xd4, 0xb5, 0x67, 0x12, 0x8d, 0x1b, 0xa5, 0x20, 0x31, 0xd7, 0xd5, 0xa5, 0xbd, 0x69, - 0xde, 0x61, 0x4a, 0xbb, 0x8c, 0xa3, 0x8a, 0x94, 0x51, 0xcd, 0x1b, 0xad, 0xd9, 0x71, - 0xb3, 0xf1, 0xb0, 0xb5, 0x0c, 0x7f, 0x21, 0xbf, 0xc4, 0x23, 0x04, 0xa4, 0xa5, 0x3e, - 0x0d, 0x55, 0x92, 0x0d, 0xa0, 0x53, 0x27, 0x14, 0x79, 0x13, 0x45, 0xfb, 0x07, 0x4c, - 0x66, 0xc4, 0xb7, 0xc9, 0x89, 0x28, 0x30, 0xf9, 0x62, 0x09, 0xb8, 0x1c, 0x26, 0xd1, - 0x74, 0xf8, 0xa9, 0x33, 0xc3, 0x77, 0x9d, 0x97, 0x88, 0x55, 0x3f, 0x6e, 0xeb, 0x21, - 0xf7, 0xdb, 0x57, 0x78, 0xf4, 0xf8, 0x17, 0x4c, 0xb4, 0x6f, 0x71, 0xfd, 0xdc, 0x4b, - 0xe4, 0xd8, 0x70, 0x3e, 0xbf, 0xbc, 0xd2, 0xa7, 0x72, 0x89, 0xee, 0xfa, 0x72, 0x76, - 0x56, 0x74, 0xdb, 0xf0, 0xe0, 0x65, 0xff, 0xcb, 0xf6, 0xbb, 0xa0, 0x18, 0x09, 0x1e, - 0x49, 0xaa, 0x90, 0xe6, 0x02, 0xc8, - ], - ock: [ - 0x2f, 0x88, 0x37, 0x27, 0xb5, 0x4d, 0x06, 0x25, 0xcf, 0xdc, 0x19, 0x5a, 0xce, 0x10, - 0xca, 0xc0, 0x26, 0x8a, 0xba, 0x3d, 0xe2, 0x8a, 0xd6, 0x08, 0x88, 0x06, 0x50, 0x6d, - 0x69, 0xc4, 0xdd, 0x8e, - ], - op: [ - 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, - 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, - 0x25, 0xc8, 0xd6, 0xae, 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, - 0xef, 0x08, 0xbd, 0xf6, 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, - 0xf5, 0x3b, 0x57, 0xc3, 0x45, 0xa9, 0x87, 0x2f, - ], - c_out: [ - 0x99, 0x96, 0x90, 0xd4, 0xcd, 0xd9, 0xe7, 0x6b, 0x07, 0x2c, 0x3c, 0x4c, 0x41, 0xbf, - 0xc7, 0x9a, 0xaa, 0xc6, 0x7f, 0xdc, 0x0f, 0x41, 0xe8, 0x0e, 0x95, 0x48, 0x80, 0x0e, - 0xef, 0xbc, 0x95, 0x74, 0xf1, 0x5d, 0x64, 0xa6, 0x9e, 0x44, 0x47, 0xc4, 0x5b, 0x07, - 0x0c, 0x6c, 0x9f, 0x50, 0x0a, 0xdd, 0xef, 0x6f, 0x57, 0x14, 0xa5, 0x76, 0x22, 0x1f, - 0x3f, 0xbc, 0x61, 0x22, 0x8d, 0x95, 0xc3, 0xac, 0xe4, 0x21, 0x4b, 0xb6, 0xcf, 0x5b, - 0xd9, 0x69, 0x84, 0xd7, 0x78, 0x96, 0x0d, 0xe9, 0x0c, 0x02, - ], - asset: Some([ - 0xdf, 0xfd, 0x79, 0xa9, 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, - 0x01, 0xe2, 0x99, 0x0a, 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, - 0xfd, 0x7d, 0x05, 0x8a, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0x8c, 0x45, 0x43, 0xe1, 0x1f, 0x9f, 0x30, 0x7e, 0xc9, 0x04, 0x31, 0x61, 0x29, 0x46, - 0xfb, 0x01, 0x81, 0xb3, 0x6e, 0x1b, 0x52, 0xdb, 0x43, 0x1e, 0x6d, 0xf9, 0x38, 0x8c, - 0xac, 0xd3, 0x08, 0xe8, 0x99, 0xd9, 0x3f, 0x70, 0xad, 0x2a, 0xea, 0xec, 0x99, 0x5e, - 0xcc, 0xe1, 0x80, 0x1c, 0x61, 0x56, 0xe2, 0x3e, 0xc4, 0x1b, 0x1a, 0xe1, 0xcd, 0x2f, - 0xd6, 0xe3, 0x9b, 0x69, 0x98, 0x2f, 0x46, 0x33, - ], - ovk: [ - 0x01, 0x76, 0xae, 0x33, 0x93, 0x25, 0xd5, 0xa5, 0x88, 0xda, 0x57, 0x96, 0xfa, 0xae, - 0x5b, 0xab, 0x7c, 0x82, 0x97, 0x7c, 0x0f, 0xf7, 0x97, 0x09, 0x3e, 0x2c, 0x1f, 0x3a, - 0xe8, 0x55, 0xf6, 0x5a, - ], - default_d: [ - 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, - ], - default_pk_d: [ - 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, - 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, - 0x36, 0x34, 0xb0, 0x23, - ], - v: 3775288302605163507, - rseed: [ - 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, - 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, - 0x3e, 0xcd, 0xd7, 0x99, - ], - memo: [ - 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, - 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, - 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, - 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, - 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, - 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, - 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, - 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, - 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, - 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, - 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, - 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, - 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, - 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, - 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, - 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, - 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, - 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, - 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, - 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, - 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, - 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, - 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, - 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, - 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, - 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, - 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, - 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, - 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, - 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, - 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, - 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, - 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, - 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, - 0x6e, 0x67, 0x57, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0xde, 0x2b, 0xfc, 0x89, 0x5b, 0xa8, 0xb5, 0x43, 0x03, 0x93, 0x43, 0x4e, 0x20, 0x92, - 0xce, 0xe7, 0x81, 0xe4, 0x00, 0x28, 0x5c, 0xc6, 0x66, 0xbc, 0x6c, 0x41, 0x89, 0xdb, - 0x2d, 0xda, 0x71, 0x92, - ], - rho: [ - 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, - 0xe0, 0xe8, 0x14, 0x11, 0x94, 0x7e, 0x9e, 0x69, 0xb7, 0x19, 0xfa, 0xb7, 0x41, 0x72, - 0x1d, 0x40, 0x9b, 0x33, - ], - cmx: [ - 0x9e, 0x3d, 0x61, 0x35, 0x6b, 0x0d, 0x88, 0x95, 0x9e, 0x3f, 0x0f, 0xcc, 0x4a, 0x93, - 0x2e, 0x93, 0x2e, 0xac, 0xbc, 0x80, 0x1d, 0x48, 0xc0, 0x19, 0x5b, 0x9c, 0x8b, 0xd1, - 0x05, 0x5a, 0x8e, 0x2e, - ], - esk: [ - 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, 0xa9, 0x19, 0xa2, 0x06, - 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, 0x25, 0xec, 0xff, 0x47, - 0x72, 0x16, 0x8c, 0x05, - ], - ephemeral_key: [ - 0xc1, 0xce, 0x25, 0xfb, 0x89, 0xe5, 0xca, 0x89, 0x97, 0xf9, 0xb4, 0xbb, 0x0e, 0x1e, - 0xfb, 0xcc, 0x1a, 0x8c, 0xbf, 0x44, 0xec, 0xfd, 0x33, 0x2c, 0x6c, 0x5c, 0x17, 0x3b, - 0xb1, 0x1f, 0xb5, 0x87, - ], - shared_secret: [ - 0x2e, 0xe5, 0x69, 0xce, 0xb3, 0xfd, 0xb8, 0x67, 0xa5, 0xd8, 0x4c, 0x92, 0x68, 0x24, - 0xef, 0x54, 0x9f, 0x2d, 0xd2, 0x8f, 0x8b, 0x04, 0x8d, 0x67, 0xd0, 0x28, 0x81, 0x7d, - 0xbf, 0xf5, 0xd2, 0xb1, - ], - k_enc: [ - 0x41, 0x4d, 0x80, 0x67, 0xc9, 0xfe, 0xbd, 0x5e, 0xbc, 0xd9, 0xae, 0x8c, 0x05, 0x99, - 0x4e, 0x3b, 0x06, 0x85, 0xc8, 0x86, 0x6f, 0x88, 0x95, 0x94, 0xc3, 0x74, 0xb3, 0x75, - 0xac, 0x2c, 0x6d, 0x24, - ], - p_enc: [ - 0x03, 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, 0xf3, 0xdb, - 0x77, 0x79, 0xb5, 0x84, 0x64, 0x34, 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, - 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, - 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, 0x3e, 0xcd, 0xd7, 0x99, 0xa6, 0x33, 0x05, 0x44, - 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, 0x5a, 0x31, 0xf6, 0x2e, - 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, 0xb4, 0x42, 0x68, 0x3c, - 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, - 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, - 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, - 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, - 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, - 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, - 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, - 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, - 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, - 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, - 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, - 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, - 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, - 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, - 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, - 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, - 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, - 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, - 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, - 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, - 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, - 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, - 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, - 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, - 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, - 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, - 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, - 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, - 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, - 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, - 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, - 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, - 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, - 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, - 0x6e, 0x67, 0x57, 0x61, - ], - c_enc: [ - 0xbc, 0x8a, 0x16, 0xfd, 0x57, 0xbc, 0x03, 0x60, 0x59, 0xe5, 0x4d, 0xc2, 0xbc, 0xfa, - 0xad, 0x9c, 0xc1, 0xfa, 0xe8, 0xcb, 0x2b, 0xe2, 0xa0, 0xc8, 0x5e, 0x81, 0x6c, 0x67, - 0xfd, 0xcd, 0x0b, 0x93, 0xe6, 0xa1, 0xed, 0xc8, 0x3b, 0xfa, 0xc4, 0x1e, 0xb4, 0x19, - 0x1c, 0x56, 0x4b, 0xac, 0x58, 0x01, 0x62, 0x92, 0x2d, 0x88, 0x25, 0x30, 0x28, 0xeb, - 0x88, 0xed, 0x46, 0xbf, 0x24, 0x2d, 0x82, 0x28, 0x6c, 0xb0, 0xa5, 0x66, 0xce, 0x01, - 0x18, 0x09, 0x4c, 0x90, 0x8f, 0xc2, 0x68, 0xb3, 0x2b, 0xcb, 0xdc, 0x4c, 0x22, 0x82, - 0xc5, 0x24, 0x2a, 0x65, 0x15, 0x48, 0x8b, 0x83, 0x3d, 0x29, 0x8e, 0x49, 0xda, 0x33, - 0x3a, 0xdd, 0x96, 0xc9, 0x9b, 0x98, 0xac, 0x06, 0x7f, 0x21, 0x41, 0x28, 0x9a, 0xcd, - 0x89, 0x49, 0x64, 0xfc, 0xf8, 0x94, 0xc9, 0x26, 0xf1, 0x81, 0xb1, 0x19, 0x85, 0x68, - 0xb1, 0xdd, 0x6f, 0x5e, 0xd1, 0x22, 0xdc, 0x70, 0x44, 0xad, 0x96, 0x76, 0xa7, 0xc5, - 0xae, 0x8e, 0xa9, 0x0f, 0x64, 0xbc, 0x59, 0x09, 0x36, 0xe0, 0xdf, 0x53, 0x1c, 0x1b, - 0x94, 0xb7, 0x35, 0xcd, 0x7b, 0x18, 0x73, 0xc8, 0x51, 0x6f, 0xea, 0x83, 0x64, 0x91, - 0x40, 0xbc, 0xbb, 0x9b, 0x42, 0xea, 0x6c, 0xb7, 0xaf, 0x67, 0xdc, 0x2d, 0xdb, 0xb4, - 0x7a, 0xb2, 0x25, 0xe7, 0x98, 0x29, 0xcd, 0xaf, 0x77, 0x04, 0xfb, 0x56, 0x5b, 0x43, - 0x91, 0x76, 0xf3, 0x35, 0xe4, 0x2b, 0x64, 0xc1, 0x6d, 0xdf, 0xe0, 0x88, 0x45, 0x38, - 0xbf, 0x43, 0x33, 0xe3, 0x2c, 0xa1, 0xe6, 0x27, 0x41, 0xc3, 0xe7, 0x4c, 0x8f, 0xaa, - 0xde, 0x0d, 0x89, 0xfa, 0x10, 0x30, 0xcd, 0x8e, 0xfd, 0x20, 0x22, 0x3e, 0x41, 0xc3, - 0xfc, 0xca, 0xaa, 0xe7, 0x76, 0xe6, 0x8e, 0xe8, 0x40, 0x56, 0x6f, 0x4d, 0x13, 0xc1, - 0xc9, 0xd5, 0xcb, 0xbe, 0xcf, 0xa7, 0x49, 0x9d, 0x43, 0x12, 0x7c, 0xe8, 0xfd, 0x83, - 0xdb, 0x6e, 0x89, 0x67, 0x90, 0x32, 0x25, 0x24, 0x87, 0x21, 0x40, 0x0d, 0x5e, 0x3e, - 0xc0, 0xc1, 0x8e, 0x10, 0xf5, 0xe6, 0x6e, 0x10, 0x17, 0x0c, 0xb3, 0x74, 0x48, 0x22, - 0x4a, 0xde, 0x39, 0x9f, 0x1d, 0x74, 0xa2, 0x16, 0x7d, 0x9f, 0xdb, 0xfe, 0x36, 0xe1, - 0x28, 0xe4, 0x8c, 0x01, 0x62, 0x61, 0x16, 0xc1, 0xa2, 0xdf, 0x3c, 0xb0, 0x23, 0xd8, - 0x0a, 0xed, 0x9b, 0xfc, 0x02, 0x71, 0xb8, 0x1f, 0xf9, 0x79, 0x81, 0x01, 0x6f, 0xff, - 0x19, 0x61, 0x08, 0x88, 0x8b, 0xcb, 0xca, 0x84, 0x5b, 0x5d, 0x97, 0x1b, 0xd5, 0x4f, - 0x49, 0x7d, 0x3f, 0x3a, 0x09, 0x29, 0x9e, 0x56, 0x50, 0xd3, 0x26, 0xd8, 0x9b, 0x9a, - 0x5e, 0xff, 0x3e, 0xbd, 0x27, 0x39, 0x34, 0xc4, 0x9f, 0x81, 0x46, 0x7e, 0xb8, 0x4f, - 0x56, 0x98, 0x90, 0xcf, 0x89, 0x05, 0xb7, 0x4c, 0xd3, 0xed, 0xa6, 0x3c, 0x53, 0x88, - 0xd5, 0x51, 0x5e, 0x3f, 0xd8, 0x1c, 0x70, 0xc1, 0x5e, 0x2a, 0x98, 0x2d, 0x59, 0x0e, - 0x87, 0xb8, 0x64, 0x45, 0x4b, 0xcd, 0xf5, 0xf8, 0x4d, 0x9f, 0x11, 0xcb, 0x9c, 0xf2, - 0xb5, 0xde, 0x3c, 0x5e, 0x0e, 0x2a, 0x6c, 0x48, 0x16, 0x61, 0x64, 0x96, 0x6f, 0xb9, - 0x0d, 0xac, 0xf8, 0x67, 0x4f, 0x9f, 0x1a, 0x34, 0xd2, 0xcd, 0xc7, 0xc9, 0x48, 0xab, - 0x99, 0xc3, 0x58, 0xa1, 0x95, 0x47, 0x0a, 0xdd, 0x06, 0x5e, 0xaf, 0x79, 0x24, 0xfa, - 0xed, 0x63, 0x27, 0xa6, 0x10, 0xf5, 0x2e, 0xd5, 0xd3, 0xa8, 0x7e, 0x11, 0xb5, 0x97, - 0x4f, 0xa0, 0x60, 0x45, 0xa4, 0x08, 0x95, 0xcd, 0xad, 0x60, 0x1c, 0xae, 0x01, 0xed, - 0xda, 0x17, 0x52, 0x81, 0x62, 0xd7, 0x21, 0x24, 0xf2, 0x05, 0x6b, 0x9a, 0xb8, 0xc0, - 0xc0, 0xf5, 0xc6, 0xdd, 0xaa, 0x0f, 0x5e, 0x33, 0xfb, 0x04, 0x23, 0x0b, 0x61, 0x1b, - 0xff, 0xd8, 0xbd, 0xdc, 0x63, 0x4c, 0x79, 0x60, 0xa3, 0xd4, 0xe6, 0x8f, 0x21, 0xe7, - 0x83, 0x04, 0xe4, 0xc4, 0xd2, 0xdc, 0xd6, 0xa1, 0x9c, 0xfc, 0x04, 0x57, 0x97, 0x09, - 0xf0, 0x33, 0xf1, 0x95, 0x78, 0xae, 0x7f, 0x0b, 0xc6, 0x46, 0x32, 0xa6, 0xd7, 0xda, - 0x40, 0xdc, 0x0c, 0x38, 0x3b, 0xca, 0xa8, 0x68, 0x6a, 0xc8, 0x49, 0x3b, 0x2c, 0xb8, - 0xf1, 0xd7, 0xd3, 0x95, 0x8a, 0x54, - ], - ock: [ - 0x9c, 0xba, 0xd2, 0xf3, 0x8b, 0xf8, 0x8f, 0x39, 0x47, 0xce, 0xf6, 0x4d, 0xe7, 0xa6, - 0xf4, 0x3e, 0x4c, 0xbb, 0x41, 0xe6, 0xe0, 0x37, 0xf1, 0x42, 0x01, 0xae, 0xe8, 0xab, - 0xfd, 0xf8, 0xa2, 0x35, - ], - op: [ - 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, - 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, - 0x36, 0x34, 0xb0, 0x23, 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, - 0xa9, 0x19, 0xa2, 0x06, 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, - 0x25, 0xec, 0xff, 0x47, 0x72, 0x16, 0x8c, 0x05, - ], - c_out: [ - 0xf6, 0x25, 0xcd, 0x3d, 0x19, 0x97, 0xb0, 0xd3, 0xf2, 0x29, 0x5a, 0xac, 0xc0, 0x3a, - 0xe0, 0xc9, 0x47, 0x28, 0xb3, 0x3c, 0xc4, 0xf1, 0x6f, 0xd4, 0x28, 0xd6, 0x5f, 0x3c, - 0x78, 0x5e, 0x8c, 0x0b, 0xb4, 0x66, 0xc1, 0x33, 0xd4, 0x83, 0xdf, 0xc5, 0xb1, 0xb3, - 0x15, 0x1d, 0xa2, 0xd5, 0xf2, 0x4a, 0x2b, 0x32, 0x0d, 0x8e, 0x9c, 0xd3, 0x41, 0x5c, - 0x25, 0xb6, 0xf9, 0x76, 0x1f, 0x42, 0x70, 0x04, 0xce, 0xe5, 0x4f, 0x75, 0xf1, 0x25, - 0xbc, 0x50, 0x5e, 0xf6, 0x26, 0xef, 0xc9, 0xdd, 0x63, 0x66, - ], - asset: Some([ - 0xa6, 0x33, 0x05, 0x44, 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, - 0x5a, 0x31, 0xf6, 0x2e, 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, - 0xb4, 0x42, 0x68, 0x3c, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0x47, 0x30, 0x68, 0xbf, 0x68, 0xe5, 0x0b, 0xe3, 0x85, 0x7d, 0xec, 0xb2, 0xef, 0xd5, - 0xde, 0x20, 0xea, 0xc8, 0x1b, 0x37, 0x5b, 0xd0, 0xbb, 0xe8, 0x36, 0x86, 0x6e, 0x99, - 0x36, 0x3b, 0x37, 0x50, 0x9d, 0x53, 0x8f, 0xcc, 0xa9, 0x33, 0x37, 0xad, 0xbc, 0x24, - 0x81, 0xe2, 0x70, 0x26, 0x18, 0x4c, 0x3f, 0x4f, 0x48, 0xcc, 0x5d, 0x5a, 0x0e, 0x4a, - 0x4c, 0xfa, 0x4d, 0x6a, 0x24, 0x7f, 0x2e, 0x39, - ], - ovk: [ - 0x25, 0xb4, 0xc2, 0x6e, 0xb0, 0x3f, 0x71, 0x66, 0x46, 0x61, 0x9a, 0xf0, 0x24, 0x56, - 0xae, 0x69, 0x59, 0x62, 0xfe, 0x5e, 0x93, 0x1a, 0x63, 0xb5, 0xc7, 0x90, 0x52, 0xec, - 0xd3, 0x33, 0xe1, 0x84, - ], - default_d: [ - 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, - ], - default_pk_d: [ - 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, - 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, - 0x34, 0xeb, 0x90, 0x2c, - ], - v: 15119422206032203650, - rseed: [ - 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, - 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, - 0x2d, 0x9b, 0x4c, 0x8f, - ], - memo: [ - 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, - 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, - 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, - 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, - 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, - 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, - 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, - 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, - 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, - 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, - 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, - 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, - 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, - 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, - 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, - 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, - 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, - 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, - 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, - 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, - 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, - 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, - 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, - 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, - 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, - 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, - 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, - 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, - 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, - 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, - 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, - 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, - 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, - 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, - 0x08, 0x74, 0x86, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x45, 0x37, 0x85, 0x3e, 0x18, 0xac, 0x2c, 0xe9, 0x37, 0x79, 0x8c, 0x9b, 0xce, 0xa9, - 0x80, 0x2d, 0x65, 0x00, 0x74, 0xdb, 0xd7, 0xe0, 0x6a, 0x48, 0x98, 0x03, 0x15, 0x30, - 0x78, 0xe9, 0x97, 0x0b, - ], - rho: [ - 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, - 0x85, 0x72, 0xa3, 0x05, 0xfa, 0x3b, 0x70, 0x68, 0xa3, 0x78, 0x38, 0x27, 0xaf, 0xe2, - 0x14, 0x7a, 0x27, 0x10, - ], - cmx: [ - 0xf2, 0x04, 0x22, 0x51, 0xa0, 0x59, 0xa2, 0xf5, 0x8a, 0xb8, 0xe9, 0x0b, 0x52, 0x64, - 0xd0, 0xa4, 0x3f, 0x96, 0xd7, 0x7e, 0xdd, 0x54, 0xf8, 0x0f, 0xf4, 0x9d, 0x43, 0x86, - 0x81, 0x4d, 0x73, 0x2e, - ], - esk: [ - 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, 0x1d, 0xa4, 0xb1, 0x44, - 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, 0xaf, 0x2b, 0xd1, 0xa0, - 0x8c, 0x67, 0xd9, 0x3f, - ], - ephemeral_key: [ - 0x46, 0x73, 0x1f, 0xff, 0xc5, 0x9a, 0xf4, 0xc1, 0x28, 0x82, 0xbc, 0xca, 0xea, 0xa7, - 0xb8, 0xed, 0x39, 0x0b, 0x14, 0x66, 0x72, 0xe1, 0x36, 0x51, 0xc3, 0x2e, 0x57, 0x80, - 0x62, 0x68, 0x65, 0xa7, - ], - shared_secret: [ - 0x9d, 0x56, 0xbd, 0x96, 0x00, 0x39, 0x62, 0x5e, 0x11, 0x7d, 0x7b, 0xfe, 0xd4, 0x3a, - 0x57, 0x3b, 0x11, 0x51, 0x7f, 0xfa, 0x76, 0x14, 0xea, 0x2d, 0xa7, 0x7e, 0xdf, 0x62, - 0x7f, 0x6f, 0x13, 0xaa, - ], - k_enc: [ - 0x04, 0x2f, 0x92, 0x82, 0x13, 0x44, 0xde, 0x97, 0x7c, 0xee, 0x89, 0x9e, 0xd2, 0x1b, - 0xc8, 0x48, 0xf5, 0xc4, 0xfe, 0xdc, 0x39, 0xf2, 0xdf, 0xed, 0xad, 0x62, 0xcc, 0x7a, - 0x92, 0x7f, 0x74, 0xfd, - ], - p_enc: [ - 0x03, 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, 0x82, 0xcf, - 0xb3, 0xe7, 0x63, 0xfa, 0xd2, 0xd1, 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, - 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, - 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, 0x2d, 0x9b, 0x4c, 0x8f, 0x61, 0x16, 0xcf, 0xec, - 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, 0x6a, 0xe8, 0xf7, 0xcc, - 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, 0x38, 0xe1, 0x73, 0x29, - 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, - 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, - 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, - 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, - 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, - 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, - 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, - 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, - 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, - 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, - 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, - 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, - 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, - 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, - 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, - 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, - 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, - 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, - 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, - 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, - 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, - 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, - 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, - 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, - 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, - 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, - 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, - 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, - 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, - 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, - 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, - 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, - 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, - 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, - 0x08, 0x74, 0x86, 0x9c, - ], - c_enc: [ - 0x16, 0x76, 0x72, 0x3a, 0x18, 0xff, 0x58, 0x77, 0x70, 0x15, 0x8d, 0x6b, 0x85, 0x09, - 0x3c, 0x49, 0x20, 0x16, 0xf8, 0x7e, 0xc3, 0xfa, 0xe8, 0xb0, 0xb4, 0x7c, 0xd9, 0x29, - 0x8f, 0xa2, 0x07, 0xc4, 0xb6, 0x09, 0xc6, 0x92, 0xdd, 0xb9, 0x10, 0x19, 0x72, 0xc9, - 0x4c, 0x71, 0x87, 0x84, 0x85, 0x42, 0x1e, 0xfb, 0x70, 0x1c, 0xf5, 0x15, 0xa2, 0x3f, - 0xbf, 0x36, 0xfe, 0x93, 0x54, 0x0d, 0x82, 0xd6, 0x9a, 0x72, 0x62, 0x4e, 0x25, 0x4f, - 0xe3, 0xa0, 0x11, 0xc5, 0xdb, 0xdb, 0xd2, 0xbd, 0xff, 0xb8, 0x83, 0x8a, 0xf3, 0x7d, - 0x03, 0xce, 0x69, 0x12, 0x6b, 0x2f, 0x68, 0x21, 0x25, 0xb7, 0xa9, 0xb2, 0xa3, 0xee, - 0x11, 0x8a, 0xe5, 0xad, 0xb4, 0x60, 0xa4, 0x68, 0x7c, 0x24, 0x30, 0x18, 0x7b, 0xfd, - 0x0f, 0x6c, 0x2a, 0x3d, 0x5d, 0x74, 0x30, 0x1c, 0xbd, 0x8f, 0xd0, 0x26, 0xc8, 0x64, - 0x4f, 0xbf, 0xa2, 0x65, 0x69, 0x88, 0xe9, 0x58, 0x59, 0x0b, 0x81, 0x6a, 0x1e, 0x64, - 0x0e, 0x46, 0x71, 0x0e, 0x46, 0xfa, 0x15, 0x94, 0xff, 0x2a, 0x61, 0xd6, 0xf6, 0xe7, - 0xb4, 0xa9, 0xf6, 0xe0, 0xde, 0x68, 0x3d, 0x95, 0xe5, 0x9d, 0x43, 0x57, 0xf7, 0x9a, - 0xc4, 0x93, 0x86, 0x6d, 0xab, 0x06, 0x57, 0x76, 0xc0, 0xb1, 0x43, 0x6b, 0x8e, 0x04, - 0x47, 0x68, 0x43, 0xc2, 0x8b, 0x48, 0x45, 0xea, 0xff, 0x17, 0x83, 0xa8, 0x50, 0xc2, - 0x4a, 0x90, 0x65, 0xc3, 0x36, 0x51, 0xc4, 0xb3, 0xdd, 0x19, 0x92, 0xf4, 0xf2, 0x08, - 0xb8, 0x51, 0xbf, 0xff, 0xe9, 0xb7, 0xbb, 0x7a, 0xad, 0x76, 0x7c, 0x23, 0x60, 0xb0, - 0x5c, 0x11, 0x23, 0x09, 0x66, 0xda, 0x55, 0x7e, 0x31, 0x3a, 0xe6, 0x1c, 0x95, 0x42, - 0x97, 0x66, 0x10, 0x6b, 0x4b, 0x1b, 0x35, 0x47, 0x64, 0xe4, 0xe1, 0xe4, 0xdf, 0x90, - 0xc1, 0x2d, 0x24, 0x37, 0x9d, 0x67, 0xba, 0xc6, 0x66, 0x97, 0xaf, 0x23, 0x44, 0x97, - 0xf2, 0xd6, 0xf9, 0xa6, 0x12, 0x85, 0x0d, 0xd7, 0x1d, 0x1c, 0x98, 0xce, 0x65, 0xd8, - 0x50, 0x7f, 0xa3, 0x46, 0x35, 0x83, 0x12, 0x39, 0xe2, 0x10, 0xf7, 0xdb, 0xb3, 0x05, - 0x04, 0x2d, 0x47, 0x50, 0xd9, 0x5a, 0xdf, 0xff, 0xc9, 0x8d, 0xeb, 0x0f, 0x17, 0x13, - 0xbc, 0x01, 0xaf, 0x5d, 0xb5, 0x99, 0x29, 0x89, 0x76, 0xab, 0xba, 0xdb, 0x0f, 0x4d, - 0xed, 0x1a, 0x2f, 0xe4, 0xcf, 0x90, 0x60, 0x0e, 0x0d, 0x28, 0xd3, 0x07, 0xc6, 0x41, - 0xf7, 0x52, 0x3c, 0x16, 0x66, 0x40, 0x1d, 0x78, 0x6f, 0xd2, 0x4a, 0xe1, 0x68, 0x0f, - 0xe9, 0x26, 0x70, 0x4c, 0xb6, 0xe2, 0xaf, 0x80, 0x1a, 0x0d, 0x82, 0x75, 0x9d, 0xd8, - 0x7a, 0x8c, 0xd8, 0x7b, 0x85, 0xbb, 0x07, 0x51, 0xa7, 0x08, 0xc9, 0xf4, 0xa7, 0xd3, - 0x24, 0xe5, 0xc9, 0x3a, 0xd2, 0x2b, 0x86, 0x43, 0xdf, 0xfa, 0x5f, 0x50, 0x79, 0xfc, - 0x6f, 0x01, 0x6d, 0x94, 0x3c, 0x99, 0x09, 0x27, 0x5c, 0x96, 0xf5, 0xfe, 0x7b, 0x56, - 0x33, 0x3c, 0x24, 0x01, 0x99, 0x73, 0xd9, 0x4f, 0x06, 0xeb, 0xf6, 0xc0, 0xf6, 0xef, - 0xdd, 0x42, 0xea, 0xb0, 0x63, 0x49, 0xd5, 0xe8, 0xb9, 0x60, 0xba, 0x8c, 0x68, 0xee, - 0xfd, 0x44, 0x49, 0x99, 0xf6, 0xfa, 0x3d, 0x6a, 0x3a, 0xe3, 0x1a, 0xe8, 0x54, 0x6e, - 0xdc, 0x62, 0x78, 0x25, 0x63, 0x7e, 0x1e, 0x86, 0x39, 0x8d, 0x0e, 0xd3, 0xd8, 0x8b, - 0xfa, 0xea, 0x8b, 0x4b, 0x08, 0x50, 0xd8, 0xa8, 0x28, 0x6e, 0xa9, 0xf3, 0xd1, 0x3f, - 0xa8, 0xf4, 0x16, 0x53, 0x45, 0x1b, 0x97, 0xb3, 0x8b, 0x06, 0x3a, 0x5f, 0xc6, 0xdb, - 0xe4, 0xe9, 0x19, 0x94, 0x87, 0xc9, 0x73, 0xef, 0x8f, 0x2c, 0x26, 0x3f, 0x85, 0x05, - 0xf4, 0xc3, 0xbe, 0xc9, 0xd1, 0x79, 0xbb, 0xd6, 0x5d, 0x1e, 0xdc, 0x58, 0x95, 0xa1, - 0x6c, 0xc7, 0x98, 0x6b, 0xcf, 0xc4, 0xba, 0xe8, 0x7e, 0xc0, 0xb2, 0x9b, 0xf1, 0xb3, - 0x97, 0x61, 0x5c, 0x95, 0x13, 0xfa, 0x52, 0xeb, 0xe1, 0xe9, 0xfc, 0xfb, 0xf1, 0x92, - 0xed, 0x49, 0x26, 0x27, 0x27, 0xa0, 0x8a, 0xd3, 0xc2, 0x95, 0x5b, 0x3d, 0xf2, 0xee, - 0xad, 0x30, 0x24, 0x3e, 0x06, 0x66, 0xf2, 0x3c, 0x7f, 0x97, 0xe7, 0x84, 0xbe, 0x68, - 0xcc, 0x22, 0xca, 0x1d, 0x09, 0xd5, - ], - ock: [ - 0x97, 0x9b, 0x31, 0x5d, 0x3e, 0x1f, 0x5c, 0xa1, 0x8a, 0x92, 0x86, 0xd9, 0x2c, 0xc8, - 0x8e, 0x63, 0x62, 0x4b, 0x39, 0x9b, 0x29, 0x19, 0xbf, 0x4e, 0x67, 0xda, 0x7c, 0xd3, - 0x94, 0xf4, 0x5c, 0x49, - ], - op: [ - 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, - 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, - 0x34, 0xeb, 0x90, 0x2c, 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, - 0x1d, 0xa4, 0xb1, 0x44, 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, - 0xaf, 0x2b, 0xd1, 0xa0, 0x8c, 0x67, 0xd9, 0x3f, - ], - c_out: [ - 0x83, 0xf7, 0xa1, 0xda, 0x72, 0x4d, 0xd1, 0x54, 0xe7, 0xd9, 0x47, 0xc0, 0xfc, 0x83, - 0x42, 0x87, 0xf3, 0x3c, 0xd4, 0xb3, 0x4a, 0xfa, 0xc0, 0xda, 0x55, 0xe4, 0x37, 0xaf, - 0xae, 0x67, 0xa9, 0x9c, 0xbd, 0x89, 0x75, 0xc9, 0x54, 0xcf, 0x41, 0xaa, 0x1e, 0x9a, - 0x8f, 0x99, 0x98, 0x3d, 0x58, 0x6f, 0x5e, 0x35, 0x37, 0xda, 0xb7, 0x2a, 0xe1, 0x82, - 0x7a, 0xa5, 0xdf, 0xc9, 0xdd, 0xad, 0x06, 0x26, 0x78, 0x84, 0x6f, 0xf8, 0x09, 0x3d, - 0xfd, 0x15, 0xf6, 0x3d, 0x47, 0xe5, 0xa3, 0xbb, 0x74, 0x39, - ], - asset: Some([ - 0x61, 0x16, 0xcf, 0xec, 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, - 0x6a, 0xe8, 0xf7, 0xcc, 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, - 0x38, 0xe1, 0x73, 0x29, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0xfc, 0x8c, 0x64, 0x1c, 0x0b, 0x28, 0xbe, 0xbf, 0x85, 0x24, 0x25, 0xae, 0x95, 0x5f, - 0xe6, 0x40, 0x1c, 0xfd, 0x9e, 0x60, 0x63, 0xf2, 0x50, 0x11, 0x3d, 0xa0, 0xb5, 0x8b, - 0x2a, 0x0f, 0x49, 0xb9, 0x12, 0x0b, 0x89, 0x9f, 0x08, 0x10, 0x6b, 0x30, 0x86, 0xb2, - 0xf4, 0x11, 0x63, 0x6f, 0x50, 0xab, 0x48, 0x7c, 0xfb, 0x28, 0x81, 0x89, 0x77, 0x8f, - 0xe4, 0xe5, 0xa1, 0x91, 0x8b, 0x98, 0xd5, 0x0a, - ], - ovk: [ - 0xbe, 0xd1, 0x7d, 0xf5, 0xf8, 0x88, 0xc8, 0xca, 0x14, 0x67, 0xae, 0x17, 0xdb, 0xbc, - 0xde, 0x31, 0xc1, 0x10, 0x5c, 0xb5, 0xbd, 0xa8, 0x8a, 0xc6, 0xc6, 0x27, 0x00, 0x2c, - 0xe2, 0x1c, 0x02, 0x14, - ], - default_d: [ - 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, - ], - default_pk_d: [ - 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, - 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, - 0x89, 0xcf, 0xf9, 0x1e, - ], - v: 7555450289479839818, - rseed: [ - 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, - 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, - 0x03, 0xaa, 0xe0, 0x4b, - ], - memo: [ - 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, - 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, - 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, - 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, - 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, - 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, - 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, - 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, - 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, - 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, - 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, - 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, - 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, - 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, - 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, - 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, - 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, - 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, - 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, - 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, - 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, - 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, - 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, - 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, - 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, - 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, - 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, - 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, - 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, - 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, - 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, - 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, - 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, - 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, - 0x6b, 0x21, 0x43, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x71, 0x00, 0xa7, 0x52, 0x93, 0xf4, 0xae, 0xfd, 0x89, 0xa1, 0x66, 0xa5, 0xf8, 0x4d, - 0x34, 0xda, 0xf4, 0xe5, 0x98, 0x34, 0xcd, 0x65, 0xd7, 0x9f, 0xfc, 0x41, 0xdd, 0xf0, - 0x68, 0x2d, 0xc2, 0xab, - ], - rho: [ - 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, - 0x4d, 0x4b, 0x32, 0x36, 0xdb, 0x1f, 0x32, 0xac, 0xa7, 0x94, 0x5c, 0xf2, 0x6e, 0xc8, - 0xb9, 0xd0, 0xb7, 0x32, - ], - cmx: [ - 0xe1, 0xc7, 0x67, 0xf3, 0x30, 0x15, 0xb5, 0xe2, 0x4a, 0x9a, 0xa5, 0x8b, 0x64, 0x7b, - 0x6b, 0x61, 0x32, 0x3c, 0xd3, 0x47, 0xe7, 0x21, 0x4c, 0x29, 0x1d, 0x09, 0x95, 0xc0, - 0xf5, 0xa6, 0x93, 0x2f, - ], - esk: [ - 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, 0x58, 0x93, 0x20, 0x26, - 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, 0x44, 0x72, 0x83, 0xf9, - 0x4e, 0xd5, 0x95, 0x3d, - ], - ephemeral_key: [ - 0xce, 0x67, 0x94, 0x31, 0x5f, 0x46, 0x2d, 0xed, 0xf3, 0xc5, 0x77, 0x4a, 0xac, 0x7f, - 0x3c, 0x7b, 0x70, 0xba, 0x7d, 0x72, 0x43, 0xbb, 0x0c, 0xc3, 0xb0, 0x67, 0xdc, 0x28, - 0x38, 0xf1, 0x11, 0xa3, - ], - shared_secret: [ - 0xea, 0x22, 0x6b, 0x69, 0xec, 0x2d, 0x9f, 0xcf, 0x91, 0x9c, 0xe5, 0x70, 0x06, 0x09, - 0x89, 0x94, 0xf7, 0x14, 0xb3, 0x9c, 0x34, 0x61, 0x52, 0xbc, 0x11, 0x51, 0xa0, 0xc6, - 0x9e, 0xe0, 0x04, 0x06, - ], - k_enc: [ - 0xb4, 0x56, 0x1b, 0xdb, 0xe0, 0xea, 0x44, 0x20, 0x75, 0xe7, 0xe6, 0x6f, 0xb3, 0xc0, - 0xfa, 0xd3, 0xaf, 0xc2, 0x85, 0x6e, 0xf4, 0xf3, 0x61, 0xb4, 0xac, 0x33, 0xaa, 0xe0, - 0x15, 0x52, 0xfd, 0x49, - ], - p_enc: [ - 0x03, 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, 0x4a, 0x70, - 0x91, 0xfe, 0x01, 0x5a, 0xda, 0x68, 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, - 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, - 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, 0x03, 0xaa, 0xe0, 0x4b, 0x29, 0x8a, 0xc0, 0xaf, - 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, 0x62, 0xcd, 0x1c, 0xa0, - 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, 0x82, 0x1a, 0x41, 0x84, - 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, - 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, - 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, - 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, - 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, - 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, - 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, - 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, - 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, - 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, - 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, - 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, - 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, - 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, - 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, - 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, - 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, - 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, - 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, - 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, - 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, - 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, - 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, - 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, - 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, - 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, - 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, - 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, - 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, - 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, - 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, - 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, - 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, - 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, - 0x6b, 0x21, 0x43, 0x0f, - ], - c_enc: [ - 0x59, 0x9a, 0x4d, 0x9f, 0x53, 0x3c, 0x46, 0xa9, 0x6f, 0x92, 0xaf, 0x8c, 0x08, 0xae, - 0x59, 0x71, 0x10, 0x23, 0x0e, 0xb8, 0x41, 0xc2, 0xf7, 0xc9, 0xd4, 0xf1, 0x45, 0x87, - 0x76, 0x36, 0xc8, 0x9d, 0xd8, 0xf3, 0x84, 0xa9, 0x40, 0xdc, 0x89, 0x72, 0x55, 0x53, - 0x57, 0xbc, 0x07, 0x48, 0x2a, 0x0a, 0x32, 0x3d, 0x87, 0xae, 0x10, 0xeb, 0x99, 0x82, - 0x5a, 0xe4, 0xe0, 0x06, 0x0e, 0x25, 0x6c, 0x3c, 0x3b, 0xeb, 0xa3, 0x2f, 0xa2, 0xb2, - 0xd2, 0x7f, 0x04, 0x6f, 0x7a, 0x93, 0x6d, 0xf8, 0xa9, 0x61, 0xc8, 0x18, 0x4e, 0xe3, - 0xc6, 0x8e, 0xbc, 0xe9, 0x80, 0x64, 0x45, 0xb4, 0x3e, 0x66, 0x67, 0x19, 0x95, 0xa2, - 0x43, 0x7a, 0x7f, 0x70, 0x91, 0x47, 0x14, 0x8a, 0x76, 0x03, 0x6d, 0x25, 0x5e, 0xba, - 0xc4, 0xd0, 0xd8, 0x34, 0x82, 0x93, 0x23, 0x9a, 0x78, 0x64, 0xe7, 0x9b, 0xef, 0xf7, - 0x6f, 0x61, 0x50, 0xe0, 0xc4, 0xf4, 0x7a, 0x85, 0x26, 0xe3, 0xed, 0x06, 0x75, 0xfa, - 0xc6, 0xac, 0xcc, 0x30, 0xa4, 0xd6, 0x73, 0xca, 0x80, 0x85, 0x95, 0x96, 0xfe, 0xc9, - 0xcd, 0x6a, 0x93, 0xfb, 0xa0, 0xe8, 0x9e, 0xf5, 0x3f, 0x3e, 0x26, 0x74, 0xd3, 0x2a, - 0x4b, 0x43, 0xf9, 0xa4, 0x38, 0x7d, 0xce, 0x33, 0xac, 0xa1, 0xe4, 0xff, 0xdc, 0x6d, - 0x2d, 0x31, 0x89, 0xc6, 0x23, 0xca, 0x56, 0x4d, 0x03, 0xac, 0x5b, 0x35, 0xb1, 0xa7, - 0x47, 0xff, 0x44, 0x6b, 0xc2, 0x5e, 0xd2, 0x2d, 0x09, 0x68, 0x2c, 0xef, 0x3a, 0x30, - 0xff, 0xa5, 0xc4, 0x0e, 0x27, 0x70, 0xf1, 0x84, 0x98, 0xb1, 0x2f, 0x86, 0x8b, 0xa9, - 0x2a, 0x13, 0xaa, 0x4f, 0xa2, 0x14, 0xb0, 0x62, 0xe3, 0x64, 0x9c, 0xf9, 0xc8, 0x5e, - 0x7a, 0x8a, 0x55, 0xf5, 0xf3, 0xdd, 0x68, 0x84, 0x2a, 0xea, 0x7c, 0x92, 0x79, 0x2a, - 0x52, 0x60, 0x0f, 0x86, 0x6c, 0x34, 0xa1, 0x0c, 0x51, 0x14, 0x13, 0x62, 0x02, 0x24, - 0xfb, 0x85, 0xaf, 0xc6, 0x06, 0xdd, 0x4f, 0x7b, 0x2f, 0x76, 0xbe, 0x76, 0x0c, 0xa1, - 0x94, 0xb6, 0xd4, 0x88, 0x2e, 0x5a, 0x4a, 0x76, 0x3d, 0x75, 0x0d, 0xb7, 0xe1, 0x68, - 0xa4, 0x18, 0x11, 0x92, 0x35, 0xda, 0xf9, 0xcb, 0x1b, 0xdb, 0x07, 0xff, 0x46, 0x83, - 0x3a, 0x87, 0xa3, 0x92, 0x6b, 0x14, 0xa5, 0x26, 0x4f, 0x10, 0x4f, 0x7f, 0x89, 0xf7, - 0x6f, 0x10, 0x10, 0x8f, 0x2b, 0x6e, 0xa5, 0x05, 0xd4, 0xf0, 0xd2, 0x6d, 0x58, 0x31, - 0x1c, 0xc7, 0x21, 0x9c, 0x6b, 0xc4, 0x38, 0xd0, 0xe1, 0xb3, 0x17, 0x60, 0x18, 0x73, - 0x9e, 0x6f, 0x75, 0xd0, 0x73, 0x59, 0xf5, 0xe8, 0x95, 0x7e, 0x12, 0xc3, 0x03, 0xaa, - 0x52, 0x9b, 0x11, 0xa1, 0x81, 0x66, 0x25, 0xa1, 0x20, 0xf3, 0x6d, 0xcd, 0xdd, 0xff, - 0x9c, 0x65, 0xbc, 0xac, 0x8f, 0x10, 0x67, 0xc7, 0xfe, 0x88, 0xf6, 0x44, 0x85, 0x94, - 0xcf, 0x1d, 0xff, 0x8e, 0x29, 0x00, 0xae, 0x84, 0xd2, 0xa7, 0xc8, 0x1b, 0x90, 0x6d, - 0xd0, 0xbc, 0x86, 0x96, 0xe3, 0x70, 0x98, 0x07, 0x4b, 0x75, 0xd8, 0x38, 0xd8, 0xab, - 0xdc, 0x90, 0x46, 0x08, 0x2b, 0xe4, 0xa6, 0x09, 0x95, 0xc4, 0xf4, 0xed, 0x80, 0xe2, - 0xd7, 0x87, 0x38, 0x25, 0x77, 0x3b, 0xa6, 0x3e, 0xe4, 0xcb, 0x97, 0x36, 0x9a, 0x50, - 0x70, 0xb5, 0x72, 0x5c, 0x5f, 0xeb, 0x32, 0x62, 0x45, 0x87, 0x80, 0x1e, 0x5a, 0xc0, - 0x30, 0xe6, 0x45, 0xbd, 0xf2, 0xe5, 0x86, 0xcf, 0x98, 0x66, 0xea, 0xfb, 0x76, 0xf5, - 0x59, 0x76, 0xa3, 0x3d, 0x62, 0xae, 0xdc, 0x76, 0x27, 0x78, 0x3b, 0x48, 0x48, 0x93, - 0x61, 0xf9, 0x9c, 0xae, 0xb1, 0xb1, 0x9c, 0x55, 0x22, 0x58, 0x9f, 0xd2, 0x1d, 0x51, - 0x45, 0x49, 0xd7, 0x4a, 0xb1, 0x92, 0x25, 0xed, 0x6e, 0x4c, 0x20, 0x3a, 0xdd, 0xfa, - 0x55, 0xfc, 0x9e, 0xc9, 0x89, 0xb6, 0x69, 0x02, 0x3c, 0xf3, 0x05, 0xb4, 0x2b, 0x33, - 0x0f, 0xc2, 0x30, 0x80, 0xab, 0xe4, 0x25, 0x01, 0xe5, 0x9c, 0x85, 0x1c, 0x54, 0xc7, - 0x49, 0x66, 0xf6, 0x0b, 0xe9, 0xdc, 0x56, 0x1a, 0x2d, 0x91, 0xf5, 0xd3, 0x2a, 0xdd, - 0x19, 0xb8, 0x9a, 0xca, 0x7a, 0x73, 0x85, 0x39, 0x59, 0x33, 0x48, 0x6f, 0xab, 0x00, - 0xcc, 0x53, 0x03, 0xc5, 0xf3, 0xf0, - ], - ock: [ - 0x55, 0x0e, 0xbf, 0x98, 0x83, 0x6c, 0xce, 0x43, 0x52, 0x25, 0xa1, 0x4b, 0xa6, 0x52, - 0xa7, 0xd5, 0x58, 0xcf, 0x5f, 0x3f, 0x7a, 0xfb, 0x00, 0xb0, 0x24, 0x70, 0xe8, 0xe4, - 0xd2, 0x6d, 0xb7, 0x9c, - ], - op: [ - 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, - 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, - 0x89, 0xcf, 0xf9, 0x1e, 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, - 0x58, 0x93, 0x20, 0x26, 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, - 0x44, 0x72, 0x83, 0xf9, 0x4e, 0xd5, 0x95, 0x3d, - ], - c_out: [ - 0x9a, 0x01, 0xb7, 0x5e, 0x27, 0xea, 0x97, 0x51, 0x45, 0x5d, 0x54, 0xf2, 0xa5, 0x2b, - 0x88, 0x4b, 0x45, 0x6a, 0x6f, 0xc3, 0xda, 0xdb, 0xec, 0x79, 0xbf, 0x4d, 0x10, 0xbe, - 0x06, 0x7b, 0xef, 0x3e, 0xa2, 0xa5, 0xc0, 0x59, 0x81, 0xd4, 0x06, 0x05, 0x6a, 0x2f, - 0xf6, 0x4c, 0xb4, 0xc6, 0xfd, 0x46, 0x7d, 0xa8, 0x0b, 0xa1, 0x17, 0x48, 0xe9, 0xe2, - 0xae, 0x07, 0xb7, 0x62, 0xdf, 0x9d, 0x4a, 0x23, 0x58, 0x77, 0xf5, 0x8f, 0x43, 0x24, - 0xd8, 0x00, 0x3c, 0x32, 0x4f, 0xd9, 0xc6, 0x39, 0xbc, 0xa6, - ], - asset: Some([ - 0x29, 0x8a, 0xc0, 0xaf, 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, - 0x62, 0xcd, 0x1c, 0xa0, 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, - 0x82, 0x1a, 0x41, 0x84, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0x53, 0x3d, 0xc3, 0xd4, 0x93, 0xf2, 0xb8, 0x7a, 0x03, 0x3d, 0xf5, 0x07, 0x05, 0xf2, - 0x90, 0x54, 0x16, 0x38, 0xe9, 0x08, 0x7d, 0xcd, 0xbc, 0xfe, 0x52, 0x7e, 0x77, 0x5a, - 0xaf, 0x09, 0x30, 0x29, 0xac, 0xec, 0x74, 0xdd, 0xe6, 0x02, 0xfc, 0x7c, 0x73, 0xcb, - 0x38, 0x50, 0xbd, 0xfb, 0xf2, 0x61, 0x79, 0x4c, 0x9c, 0x29, 0x9d, 0x0b, 0x98, 0xee, - 0x0f, 0x20, 0x71, 0xd6, 0xd4, 0xe3, 0x7b, 0x05, - ], - ovk: [ - 0x32, 0x4d, 0xce, 0x2a, 0x1e, 0xa1, 0xe4, 0x30, 0x4f, 0x49, 0xe4, 0x3a, 0xe0, 0x65, - 0xe3, 0xfb, 0x19, 0x6f, 0x76, 0xd9, 0xb8, 0x79, 0xc7, 0x20, 0x08, 0x62, 0xea, 0xd1, - 0x8d, 0xea, 0x5f, 0xb6, - ], - default_d: [ - 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, - ], - default_pk_d: [ - 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, - 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, - 0xab, 0x00, 0xa0, 0x28, - ], - v: 12711846894898776584, - rseed: [ - 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, - 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, - 0xad, 0xe8, 0x24, 0xf3, - ], - memo: [ - 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, - 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, - 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, - 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, - 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, - 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, - 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, - 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, - 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, - 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, - 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, - 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, - 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, - 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, - 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, - 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, - 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, - 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, - 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, - 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, - 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, - 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, - 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, - 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, - 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, - 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, - 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, - 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, - 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, - 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, - 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, - 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, - 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, - 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, - 0x66, 0x17, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x5d, 0xd1, 0x3d, 0xcf, 0x9a, 0xf3, 0x52, 0xf5, 0xfe, 0x0b, 0x2b, 0xcb, 0xd0, 0xdb, - 0xd7, 0xda, 0xfb, 0xbe, 0x53, 0xb0, 0xa9, 0x6b, 0x08, 0x1c, 0x90, 0xba, 0xde, 0xd9, - 0xbe, 0x4b, 0x4f, 0x87, - ], - rho: [ - 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, - 0x4f, 0xfb, 0xc2, 0x36, 0x9c, 0xb1, 0x48, 0xeb, 0x76, 0xf1, 0xed, 0xf1, 0xb5, 0xc7, - 0x41, 0x84, 0x28, 0x2a, - ], - cmx: [ - 0xd7, 0x60, 0xac, 0xdb, 0xca, 0xda, 0xd1, 0x88, 0x08, 0x4f, 0xe4, 0x1a, 0x5c, 0x03, - 0xc2, 0xc8, 0xce, 0x34, 0xe1, 0x5f, 0x9d, 0xf4, 0x7b, 0x86, 0x9c, 0x44, 0xc7, 0x21, - 0x13, 0xa4, 0x0c, 0x3d, - ], - esk: [ - 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, 0xdf, 0x7c, 0xe2, 0xd2, - 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, 0x86, 0x48, 0x56, 0x2c, - 0xbd, 0x86, 0x3f, 0x09, - ], - ephemeral_key: [ - 0x5a, 0x48, 0x58, 0x15, 0xc4, 0xa7, 0x47, 0x06, 0xe9, 0xde, 0x87, 0xfa, 0x60, 0xa2, - 0x81, 0x6f, 0x89, 0x0b, 0xe3, 0xdb, 0x54, 0xeb, 0x3f, 0x4b, 0xaf, 0x37, 0xdb, 0xc9, - 0xbd, 0xe5, 0xfe, 0x9d, - ], - shared_secret: [ - 0x96, 0x8d, 0xf2, 0xe8, 0x5d, 0x7b, 0xd1, 0x08, 0xf5, 0x72, 0x12, 0x53, 0x93, 0x76, - 0xaf, 0x25, 0x83, 0x2e, 0xf4, 0xdb, 0xd6, 0x40, 0x2a, 0x41, 0x4d, 0x73, 0xc5, 0x6b, - 0xee, 0xe4, 0xf2, 0xa8, - ], - k_enc: [ - 0xf7, 0x73, 0x91, 0x24, 0x3f, 0xdb, 0x35, 0xb2, 0x26, 0x94, 0xdb, 0x91, 0xde, 0xbd, - 0x78, 0x55, 0x79, 0x3c, 0xa7, 0x1e, 0x82, 0xbd, 0xc2, 0xee, 0x74, 0xc9, 0xb7, 0xb6, - 0x97, 0xc0, 0x24, 0x71, - ], - p_enc: [ - 0x03, 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, 0x08, 0x0a, - 0x98, 0x91, 0x66, 0x8d, 0x69, 0xb0, 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, - 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, - 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, 0xad, 0xe8, 0x24, 0xf3, 0xf9, 0x78, 0x1e, 0xbe, - 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, 0xf1, 0xb1, 0xaa, 0x9b, - 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, 0xe3, 0x81, 0x93, 0xbc, - 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, - 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, - 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, - 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, - 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, - 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, - 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, - 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, - 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, - 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, - 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, - 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, - 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, - 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, - 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, - 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, - 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, - 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, - 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, - 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, - 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, - 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, - 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, - 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, - 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, - 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, - 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, - 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, - 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, - 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, - 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, - 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, - 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, - 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, - 0x66, 0x17, 0x00, 0x8c, - ], - c_enc: [ - 0xf9, 0x09, 0x97, 0x73, 0x8b, 0x14, 0xd8, 0xa8, 0x4e, 0x32, 0x74, 0xbb, 0x70, 0x76, - 0x31, 0x15, 0xb7, 0x2e, 0x0a, 0x3d, 0xde, 0x8e, 0xa4, 0x70, 0x91, 0x1f, 0xb4, 0x58, - 0x70, 0xb0, 0x14, 0x8e, 0x7d, 0x37, 0x2b, 0xf2, 0x26, 0x8b, 0x3e, 0xe8, 0xda, 0xe5, - 0xfd, 0xe5, 0xea, 0x9b, 0x61, 0x59, 0x8e, 0xf1, 0x1b, 0x73, 0x14, 0x4f, 0x75, 0x53, - 0xb2, 0x13, 0xa0, 0x4c, 0x85, 0xf2, 0x5c, 0x54, 0x6c, 0x8a, 0x38, 0xa6, 0x0e, 0x50, - 0x86, 0x08, 0xb9, 0xca, 0x59, 0x3b, 0x94, 0xd8, 0x68, 0x8d, 0x6e, 0xff, 0xa5, 0x36, - 0x04, 0xd4, 0xdb, 0xc0, 0xf3, 0x45, 0x03, 0xaa, 0xe4, 0x6f, 0x3c, 0x8a, 0x8d, 0x2e, - 0x46, 0xa8, 0x1f, 0x09, 0x12, 0x6c, 0x45, 0x36, 0xfd, 0x02, 0x58, 0xf5, 0x97, 0x40, - 0xad, 0x0d, 0xb8, 0x02, 0xcc, 0x02, 0x42, 0x53, 0x4d, 0xdf, 0x52, 0xa6, 0xbf, 0x6a, - 0x03, 0x4d, 0xe6, 0x26, 0xf0, 0x18, 0x84, 0x4a, 0xdc, 0xb2, 0x6d, 0xcd, 0xc2, 0x85, - 0x16, 0x37, 0x16, 0xdd, 0x54, 0x65, 0x1c, 0x88, 0x73, 0x53, 0xf1, 0xff, 0xef, 0xa0, - 0x37, 0x71, 0x2a, 0xc0, 0xdf, 0x3a, 0x92, 0x98, 0x19, 0x06, 0x87, 0x54, 0x9d, 0x79, - 0xc6, 0xa3, 0x60, 0x0c, 0xc1, 0xc7, 0x29, 0xa3, 0x93, 0xd4, 0x4f, 0xec, 0xe5, 0x7f, - 0xd4, 0xcb, 0x0c, 0x0f, 0xb0, 0xc7, 0x86, 0x1b, 0x92, 0x5b, 0x94, 0xcd, 0x6a, 0x26, - 0x90, 0xf0, 0x02, 0xc4, 0x3a, 0x16, 0x6e, 0x56, 0x77, 0x72, 0x9f, 0x35, 0x52, 0xae, - 0xe0, 0xf2, 0xc1, 0x95, 0xaa, 0x91, 0xb2, 0xdd, 0xe3, 0x65, 0xdd, 0x14, 0xf2, 0xf0, - 0x7b, 0x3c, 0x38, 0x34, 0x7f, 0x6c, 0x0d, 0xab, 0x82, 0x84, 0x1e, 0xba, 0xde, 0x1e, - 0xf8, 0x13, 0xf2, 0xcd, 0x88, 0x5b, 0x57, 0x84, 0x37, 0x44, 0x45, 0x24, 0x93, 0x6a, - 0x65, 0x46, 0xc4, 0x55, 0xd6, 0xc9, 0x2e, 0x6d, 0x3d, 0xc5, 0x38, 0xb6, 0xcd, 0x9f, - 0x6d, 0x4c, 0xc0, 0xd7, 0x4d, 0x7b, 0xc2, 0x46, 0x7e, 0x21, 0x5b, 0xe8, 0xc3, 0xd4, - 0xff, 0x91, 0x8a, 0x2d, 0x98, 0x71, 0x00, 0xff, 0x34, 0x02, 0x4c, 0x88, 0x62, 0x79, - 0xd6, 0x4c, 0xaf, 0xdf, 0xd9, 0x0f, 0x1c, 0x04, 0xc4, 0x6b, 0xc9, 0xd5, 0xe9, 0xe2, - 0xaf, 0xd0, 0x3a, 0xb7, 0x55, 0xe4, 0x0f, 0x08, 0x7e, 0xb5, 0x1e, 0xe3, 0xd1, 0x02, - 0xb6, 0xb0, 0x69, 0xb6, 0x50, 0xf5, 0xd8, 0x55, 0x03, 0x35, 0x47, 0x1b, 0x24, 0x46, - 0x5d, 0x93, 0x4d, 0x63, 0x34, 0x39, 0xb1, 0x08, 0xd9, 0x04, 0x2b, 0x37, 0xf9, 0xf7, - 0x2e, 0x74, 0xfd, 0x6b, 0xa0, 0x01, 0x58, 0x5b, 0x08, 0x62, 0xdb, 0x99, 0x4a, 0x5e, - 0xc1, 0x2d, 0xc9, 0x1e, 0x01, 0x48, 0x6a, 0x8d, 0xc6, 0x8a, 0xb9, 0xa3, 0x41, 0x93, - 0x52, 0x61, 0x73, 0xec, 0xc0, 0xd1, 0x55, 0xb5, 0xcd, 0xd6, 0xbc, 0x07, 0xe6, 0x3e, - 0x41, 0xaf, 0x9e, 0x52, 0x4c, 0xd3, 0xe6, 0x55, 0x5d, 0x38, 0xb4, 0x6d, 0xb2, 0xd9, - 0x9e, 0x5b, 0xa4, 0xa4, 0x95, 0xff, 0x30, 0xfe, 0xf2, 0x54, 0xc9, 0xfe, 0x7b, 0x79, - 0x0c, 0xe5, 0x6a, 0x40, 0xf4, 0x00, 0x27, 0xbb, 0x62, 0x05, 0x86, 0x38, 0xc4, 0x94, - 0x17, 0x7b, 0x7f, 0x5c, 0x8f, 0x29, 0x44, 0x9e, 0x9e, 0xc3, 0xbd, 0xb3, 0xab, 0x04, - 0x16, 0x0d, 0x96, 0xd0, 0xd4, 0x04, 0x79, 0x5d, 0x54, 0x28, 0x40, 0x82, 0xb6, 0x35, - 0x7d, 0x58, 0x1d, 0xc2, 0x64, 0x81, 0x13, 0x67, 0xbb, 0xb1, 0x31, 0x9a, 0x31, 0xf7, - 0x66, 0x4a, 0x4e, 0xca, 0x93, 0x2a, 0xbb, 0xd7, 0x33, 0xa7, 0x1a, 0x31, 0xaf, 0x23, - 0x11, 0xc4, 0x9a, 0xc9, 0xaf, 0x22, 0xf8, 0x16, 0x7b, 0x25, 0x51, 0xac, 0xf5, 0x73, - 0xd9, 0x1b, 0x40, 0x98, 0xc4, 0xde, 0xa8, 0xa9, 0x79, 0x9d, 0x9d, 0x54, 0x52, 0x0c, - 0xc6, 0x3e, 0x55, 0x71, 0x8a, 0x24, 0x85, 0xbf, 0x6f, 0x63, 0x16, 0x30, 0x7c, 0xea, - 0x21, 0x5e, 0x22, 0x22, 0x8d, 0x45, 0x34, 0x9a, 0x03, 0x50, 0x31, 0xa4, 0xcb, 0x67, - 0x7b, 0x52, 0x3a, 0x3a, 0x51, 0x25, 0x2c, 0x6c, 0x61, 0xd0, 0xe2, 0x43, 0x2b, 0x94, - 0xac, 0x9c, 0x0d, 0xb5, 0x40, 0xf3, 0x5b, 0x1d, 0xde, 0x91, 0xa3, 0xaf, 0x37, 0xa6, - 0x71, 0xb8, 0xaa, 0x9f, 0x69, 0xf0, - ], - ock: [ - 0x53, 0x29, 0x6e, 0xed, 0x43, 0xb4, 0xeb, 0x30, 0xa4, 0x3d, 0x88, 0x90, 0x2f, 0x74, - 0x04, 0x26, 0x62, 0x1d, 0x85, 0x21, 0x3a, 0x36, 0xc5, 0x20, 0xa1, 0x84, 0xa4, 0x3a, - 0xfb, 0xd4, 0x89, 0x6d, - ], - op: [ - 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, - 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, - 0xab, 0x00, 0xa0, 0x28, 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, - 0xdf, 0x7c, 0xe2, 0xd2, 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, - 0x86, 0x48, 0x56, 0x2c, 0xbd, 0x86, 0x3f, 0x09, - ], - c_out: [ - 0x38, 0xee, 0x14, 0xef, 0xb0, 0x63, 0x94, 0x64, 0x44, 0x6f, 0x5f, 0xb8, 0x79, 0x5d, - 0x23, 0xf8, 0x8c, 0xf5, 0x65, 0x37, 0xe6, 0x4e, 0x1a, 0x46, 0x63, 0x17, 0xb3, 0x6f, - 0x22, 0x2e, 0x00, 0x5b, 0x92, 0x4c, 0xc9, 0x10, 0xd6, 0x29, 0x06, 0x6e, 0x05, 0x07, - 0xcb, 0x91, 0x2b, 0x0b, 0xc1, 0xd3, 0x16, 0xc2, 0x00, 0xb1, 0xa9, 0x56, 0x49, 0xc0, - 0xc5, 0x30, 0xb4, 0xf3, 0xd0, 0x43, 0x06, 0x8e, 0xf6, 0xf4, 0x2d, 0xcb, 0xef, 0xd0, - 0x2a, 0x34, 0x80, 0xe3, 0x2a, 0xa4, 0x5e, 0x33, 0xce, 0x25, - ], - asset: Some([ - 0xf9, 0x78, 0x1e, 0xbe, 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, - 0xf1, 0xb1, 0xaa, 0x9b, 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, - 0xe3, 0x81, 0x93, 0xbc, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0x77, 0x5c, 0x7f, 0x5c, 0xab, 0x43, 0x86, 0x88, 0x64, 0x3d, 0xdd, 0x15, 0x8d, 0xda, - 0xed, 0xf9, 0xa0, 0xea, 0xef, 0x61, 0x4b, 0x54, 0x90, 0x60, 0xf1, 0xe4, 0xd7, 0xcc, - 0x3e, 0x7e, 0x8b, 0x64, 0x49, 0x9a, 0x81, 0x8a, 0x6d, 0x0e, 0x33, 0x57, 0x68, 0x6e, - 0x65, 0xbc, 0x27, 0x4e, 0x3f, 0x7d, 0x45, 0x5b, 0x91, 0x1f, 0x13, 0x9f, 0x19, 0xf0, - 0x81, 0x61, 0x57, 0x51, 0x91, 0x3e, 0xb4, 0x12, - ], - ovk: [ - 0x45, 0xe1, 0x59, 0x6c, 0xbf, 0x46, 0x70, 0xb7, 0xe0, 0x5d, 0xfd, 0xaf, 0xbb, 0x0c, - 0xf3, 0xdd, 0xee, 0x28, 0xd7, 0x6a, 0x82, 0x42, 0x8e, 0x8a, 0xba, 0x43, 0x64, 0xe8, - 0x4b, 0xac, 0x37, 0x92, - ], - default_d: [ - 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, - ], - default_pk_d: [ - 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, - 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, - 0x96, 0xdc, 0xe6, 0xb7, - ], - v: 10238534295395242511, - rseed: [ - 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, - 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, - 0xa5, 0xfa, 0x38, 0x5d, - ], - memo: [ - 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, - 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, - 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, - 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, - 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, - 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, - 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, - 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, - 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, - 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, - 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, - 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, - 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, - 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, - 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, - 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, - 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, - 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, - 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, - 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, - 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, - 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, - 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, - 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, - 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, - 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, - 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, - 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, - 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, - 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, - 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, - 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, - 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, - 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, - 0xee, 0xfc, 0x52, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x43, 0x94, 0x47, 0xab, 0x14, 0x5a, 0x6f, 0x0e, 0x5a, 0x3b, 0x43, 0x63, 0x04, 0x4c, - 0x73, 0x07, 0x93, 0xf4, 0x36, 0x33, 0x1f, 0xfe, 0x66, 0x30, 0xc7, 0xca, 0x2d, 0x9b, - 0x23, 0x2a, 0xe1, 0x98, - ], - rho: [ - 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, - 0x53, 0xb9, 0x3b, 0xcb, 0xb4, 0x37, 0x57, 0x1c, 0x62, 0xf3, 0x75, 0x60, 0x7e, 0x90, - 0x4e, 0xb3, 0xa2, 0x08, - ], - cmx: [ - 0x8f, 0x56, 0xd1, 0x3f, 0xd9, 0xc8, 0x3e, 0xb7, 0x1b, 0x95, 0x87, 0x7a, 0x4f, 0x29, - 0x39, 0x64, 0xbf, 0x3f, 0x73, 0x1d, 0x8d, 0xf2, 0x04, 0x32, 0x2c, 0xed, 0xcb, 0x38, - 0x68, 0x21, 0x90, 0x3c, - ], - esk: [ - 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, 0x44, 0xb0, 0xb0, 0x4f, - 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, 0xa9, 0xec, 0x88, 0x17, - 0x18, 0x65, 0x40, 0x33, - ], - ephemeral_key: [ - 0x51, 0x66, 0x26, 0x31, 0x6e, 0xea, 0x63, 0xa6, 0x45, 0xae, 0x56, 0x23, 0x81, 0x5a, - 0x31, 0x74, 0xb3, 0xed, 0x36, 0x64, 0xc3, 0x3e, 0x6a, 0x51, 0x81, 0xa9, 0xf5, 0xb5, - 0x42, 0x76, 0x7a, 0x2d, - ], - shared_secret: [ - 0xf6, 0x04, 0x23, 0x98, 0x7f, 0x0e, 0x67, 0x6d, 0x1a, 0x3b, 0xb6, 0xef, 0xe0, 0x39, - 0x42, 0x1d, 0xbb, 0xc8, 0x24, 0xb6, 0x90, 0xc1, 0x94, 0xa4, 0x90, 0xe4, 0x17, 0x1d, - 0xde, 0x21, 0x58, 0x19, - ], - k_enc: [ - 0x20, 0x98, 0x25, 0x7e, 0x2b, 0x9b, 0x7f, 0xc0, 0x62, 0x82, 0x38, 0x03, 0x38, 0x59, - 0x7d, 0xcb, 0x62, 0x7d, 0xdf, 0x47, 0x3e, 0x83, 0xa7, 0x2e, 0x61, 0xb0, 0xf2, 0x2c, - 0xcf, 0xaf, 0xbe, 0x4e, - ], - p_enc: [ - 0x03, 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, 0x0f, 0x12, - 0xb0, 0x11, 0xb2, 0x94, 0x16, 0x8e, 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, - 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, - 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, 0xa5, 0xfa, 0x38, 0x5d, 0x76, 0xba, 0x24, 0x3f, - 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, 0xc4, 0xbd, 0x4f, 0xc9, - 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, 0xf6, 0x99, 0x03, 0x18, - 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, - 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, - 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, - 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, - 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, - 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, - 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, - 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, - 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, - 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, - 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, - 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, - 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, - 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, - 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, - 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, - 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, - 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, - 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, - 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, - 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, - 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, - 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, - 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, - 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, - 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, - 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, - 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, - 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, - 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, - 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, - 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, - 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, - 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, - 0xee, 0xfc, 0x52, 0x7b, - ], - c_enc: [ - 0xa4, 0x01, 0xab, 0x60, 0x1f, 0x8d, 0x69, 0xd9, 0x38, 0x0c, 0x3d, 0xef, 0x1f, 0x1a, - 0x34, 0xbe, 0x6c, 0xfa, 0x4d, 0x83, 0x8b, 0xf8, 0x7f, 0x00, 0xe3, 0x6b, 0xe6, 0xbe, - 0x68, 0x60, 0xbe, 0xa8, 0x3d, 0xab, 0xdd, 0x00, 0xab, 0xe7, 0xe0, 0xd1, 0x21, 0x90, - 0xfb, 0x54, 0xb0, 0xf2, 0xad, 0xcf, 0xef, 0x9e, 0xf4, 0x2b, 0xa2, 0x31, 0x77, 0x6a, - 0xd3, 0xee, 0x09, 0x86, 0xdb, 0x3f, 0x4f, 0xc0, 0xa8, 0xa1, 0xc6, 0xa7, 0xfe, 0x54, - 0xa6, 0x6b, 0xd7, 0x68, 0xa9, 0xde, 0xd2, 0x5b, 0xb1, 0x89, 0xd5, 0x87, 0x1c, 0xaf, - 0x4d, 0xf8, 0x95, 0x6c, 0x2f, 0x30, 0x70, 0x15, 0x89, 0xa4, 0xdc, 0xdb, 0x68, 0x11, - 0x6d, 0x0f, 0x50, 0x9b, 0x34, 0x1e, 0x8f, 0x25, 0x8e, 0x17, 0x38, 0xb5, 0x51, 0x9c, - 0x99, 0xf1, 0xdb, 0xd0, 0x86, 0x31, 0x56, 0x2f, 0x90, 0xd1, 0x5e, 0x72, 0x8a, 0x85, - 0x25, 0xa1, 0x1b, 0xfe, 0x53, 0x95, 0x24, 0x5d, 0x71, 0x79, 0xcf, 0x8e, 0x97, 0xa8, - 0x3f, 0xaa, 0x4c, 0xf3, 0xb2, 0xa8, 0xb5, 0xef, 0x62, 0x13, 0xe3, 0x30, 0x89, 0xb4, - 0xeb, 0x03, 0xe7, 0xc2, 0xf0, 0x12, 0x11, 0xfc, 0x53, 0xbc, 0x01, 0x16, 0x40, 0x05, - 0x01, 0x5d, 0xbf, 0x33, 0xc6, 0x50, 0xa3, 0xf8, 0x33, 0xba, 0x67, 0x77, 0xcf, 0xf1, - 0xd7, 0x38, 0xe2, 0x1c, 0x58, 0xdc, 0x05, 0xc3, 0xb4, 0xec, 0xb9, 0x7a, 0x6c, 0xe0, - 0xb0, 0xc5, 0xee, 0x94, 0x4c, 0x24, 0xb3, 0x3b, 0xb0, 0xce, 0x32, 0xbe, 0x02, 0x3e, - 0x21, 0x3f, 0xf7, 0xc9, 0xd4, 0x12, 0x4f, 0xc9, 0xdc, 0x4a, 0xa7, 0xca, 0x47, 0x13, - 0x86, 0x48, 0xe2, 0xbb, 0x80, 0x7c, 0xea, 0x7a, 0x58, 0xe7, 0x67, 0xd3, 0x27, 0x07, - 0x4a, 0xe5, 0xe3, 0x9c, 0x3c, 0x17, 0xb7, 0x7c, 0x09, 0x0a, 0xf9, 0x42, 0x5b, 0xc6, - 0x40, 0xd2, 0x1d, 0xd6, 0x81, 0xa6, 0x37, 0x45, 0xe9, 0x02, 0x59, 0xe2, 0xd1, 0x09, - 0x0c, 0x88, 0x48, 0x8e, 0x21, 0x48, 0xb9, 0xee, 0x24, 0x31, 0xc5, 0xae, 0xf5, 0x10, - 0x95, 0xb3, 0x5a, 0x37, 0x7c, 0xfa, 0x76, 0x5d, 0x82, 0x24, 0x98, 0x83, 0x00, 0x04, - 0x71, 0x79, 0xa5, 0x09, 0x40, 0x28, 0xbe, 0x52, 0x7d, 0x5d, 0xe1, 0xc2, 0x69, 0xff, - 0x45, 0x2c, 0x0a, 0xaf, 0x5a, 0x47, 0x7e, 0x93, 0x90, 0xa0, 0xf0, 0xa8, 0x68, 0x11, - 0x3c, 0x7c, 0xd1, 0x9e, 0x2e, 0xac, 0x54, 0x0d, 0xc6, 0x59, 0xda, 0x29, 0x60, 0x06, - 0x77, 0x6e, 0xda, 0x0d, 0xf9, 0x81, 0xc4, 0x11, 0xc1, 0x50, 0x01, 0xa9, 0x8b, 0x6a, - 0xd6, 0x58, 0xd9, 0xa6, 0x4c, 0x12, 0x6a, 0xbe, 0xfc, 0x73, 0x9a, 0xa1, 0xf4, 0x44, - 0xbb, 0x83, 0xf3, 0xf1, 0x4d, 0x11, 0x3d, 0x02, 0x8f, 0xae, 0x10, 0xe4, 0xc5, 0xdb, - 0xe7, 0x78, 0x51, 0x96, 0x83, 0xcd, 0xf4, 0xc2, 0xf4, 0x6c, 0x4a, 0x52, 0xae, 0x12, - 0x09, 0xe1, 0x12, 0x7f, 0x9d, 0xc4, 0xed, 0x86, 0x7d, 0x8e, 0xda, 0x02, 0x4a, 0x68, - 0x9f, 0x6b, 0x15, 0xb8, 0x05, 0x38, 0x03, 0x02, 0x44, 0x02, 0xa1, 0xce, 0x6f, 0x1c, - 0x63, 0x6f, 0x2e, 0xfc, 0xf9, 0xd0, 0x60, 0x51, 0x5c, 0xd6, 0x14, 0x71, 0x8d, 0x51, - 0x52, 0x7d, 0x26, 0x7a, 0xd8, 0x95, 0xfa, 0xd8, 0xec, 0xfb, 0x23, 0x51, 0xf8, 0x92, - 0x45, 0x0d, 0xc8, 0x74, 0xe8, 0x74, 0x39, 0x2c, 0x91, 0xed, 0x3a, 0xf1, 0x18, 0x38, - 0xc4, 0xb5, 0x48, 0x2e, 0x8c, 0x92, 0xeb, 0xc7, 0xa0, 0x08, 0x8e, 0x49, 0xd2, 0xb0, - 0xb4, 0xa1, 0xbd, 0x33, 0x3b, 0x38, 0x7f, 0x49, 0xe3, 0x0f, 0xd2, 0x1a, 0x6e, 0xdc, - 0x89, 0x94, 0x83, 0x4f, 0x28, 0xe9, 0xf2, 0x52, 0x9a, 0x7e, 0x27, 0x24, 0x21, 0x6d, - 0x9e, 0x1a, 0xe5, 0xb4, 0x6e, 0xb1, 0x9a, 0x53, 0xea, 0x2b, 0x97, 0x99, 0x65, 0xf7, - 0x5b, 0x83, 0xf6, 0x86, 0xed, 0xc0, 0x1d, 0x25, 0x7a, 0x06, 0x58, 0xd7, 0x4e, 0x25, - 0xc0, 0xe1, 0xa8, 0xb0, 0x65, 0x60, 0x43, 0x1f, 0x85, 0x10, 0x5c, 0xf9, 0x8a, 0x1f, - 0xfe, 0x28, 0x40, 0x8a, 0x64, 0xf4, 0xc0, 0x27, 0x8d, 0x36, 0xed, 0xea, 0x76, 0x40, - 0xa2, 0x18, 0x26, 0xc3, 0x5d, 0x13, 0x20, 0x25, 0x08, 0x07, 0x2b, 0x68, 0x82, 0xf4, - 0xd8, 0x2e, 0x93, 0x3c, 0x89, 0xe1, - ], - ock: [ - 0x2a, 0x2e, 0x0d, 0x99, 0x69, 0xf0, 0x2e, 0xbd, 0xb6, 0xd9, 0xc8, 0xe7, 0xe6, 0xfd, - 0xde, 0x20, 0x85, 0x12, 0x4b, 0x19, 0xad, 0x70, 0x90, 0xcc, 0x26, 0x15, 0x1d, 0x4d, - 0xa4, 0x2a, 0x00, 0x3e, - ], - op: [ - 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, - 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, - 0x96, 0xdc, 0xe6, 0xb7, 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, - 0x44, 0xb0, 0xb0, 0x4f, 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, - 0xa9, 0xec, 0x88, 0x17, 0x18, 0x65, 0x40, 0x33, - ], - c_out: [ - 0x74, 0x6a, 0xae, 0x9d, 0xa6, 0x1c, 0x02, 0xae, 0xaa, 0x8b, 0xed, 0xbe, 0x2b, 0x6c, - 0x84, 0x1b, 0xc4, 0x36, 0x17, 0x3c, 0x7c, 0x91, 0x13, 0x66, 0x3a, 0x39, 0xc1, 0x74, - 0x69, 0x29, 0x0b, 0xd2, 0x19, 0xea, 0xdc, 0x4a, 0x97, 0x5a, 0xd0, 0x52, 0xd0, 0x5d, - 0xc0, 0xa3, 0x08, 0xf3, 0x63, 0xf9, 0x22, 0x68, 0x2d, 0x75, 0x21, 0x9d, 0xaa, 0x33, - 0x6f, 0x69, 0xb5, 0x9e, 0x86, 0x7c, 0x85, 0xd9, 0x37, 0x34, 0x4c, 0x19, 0xd3, 0x88, - 0x01, 0x63, 0x19, 0xb3, 0xf6, 0x0f, 0x76, 0xd0, 0x28, 0x93, - ], - asset: Some([ - 0x76, 0xba, 0x24, 0x3f, 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, - 0xc4, 0xbd, 0x4f, 0xc9, 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, - 0xf6, 0x99, 0x03, 0x18, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0x9c, 0xe9, 0x20, 0x37, 0x6a, 0x6a, 0x54, 0x1e, 0x6a, 0xad, 0x66, 0x0e, 0xfa, 0x09, - 0x8d, 0xc5, 0x4c, 0x18, 0xfc, 0xeb, 0x13, 0xd0, 0x99, 0x9f, 0xbc, 0xc7, 0xfd, 0x45, - 0xa5, 0x7c, 0xcc, 0x10, 0xb8, 0xaa, 0x86, 0xc4, 0x54, 0x0d, 0x0a, 0x9f, 0xc6, 0x6d, - 0xf8, 0x5d, 0xad, 0xd6, 0x21, 0x56, 0x36, 0x5e, 0x28, 0xa3, 0xe9, 0x80, 0xb9, 0x8d, - 0x13, 0x1b, 0x50, 0x3a, 0xa0, 0x6a, 0x6c, 0x19, - ], - ovk: [ - 0xf8, 0x1a, 0xd6, 0x17, 0xfa, 0x26, 0xf0, 0xdf, 0xb8, 0x36, 0x55, 0xb8, 0xa2, 0x9a, - 0x7f, 0x83, 0x42, 0x32, 0x42, 0x5e, 0x8c, 0x47, 0x45, 0x88, 0xf1, 0x8d, 0xd3, 0x26, - 0xaa, 0x39, 0x6c, 0x3e, - ], - default_d: [ - 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, - ], - default_pk_d: [ - 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, - 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, - 0x43, 0x4b, 0x1e, 0xb0, - ], - v: 2690686290017047047, - rseed: [ - 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, - 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, - 0xee, 0xba, 0xe6, 0xfa, - ], - memo: [ - 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, - 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, - 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, - 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, - 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, - 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, - 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, - 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, - 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, - 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, - 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, - 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, - 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, - 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, - 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, - 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, - 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, - 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, - 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, - 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, - 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, - 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, - 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, - 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, - 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, - 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, - 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, - 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, - 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, - 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, - 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, - 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, - 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, - 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, - 0xe8, 0xba, 0x4f, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0xf4, 0x5c, 0xba, 0x14, 0x6a, 0xe7, 0x18, 0x85, 0xfd, 0x61, 0xb4, 0xa0, 0xf3, 0x6b, - 0x95, 0x26, 0xa6, 0xe9, 0x4a, 0x49, 0x70, 0x10, 0xe3, 0x2a, 0x8a, 0x76, 0xbc, 0xdf, - 0xa7, 0x20, 0xb8, 0xa6, - ], - rho: [ - 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, - 0xa5, 0xed, 0x09, 0xc6, 0xee, 0x3b, 0x7f, 0x39, 0x34, 0x14, 0xe1, 0x1c, 0xd4, 0x20, - 0x4c, 0x3f, 0x8d, 0x26, - ], - cmx: [ - 0x69, 0x4b, 0x6f, 0x3a, 0xb8, 0x37, 0xa9, 0x26, 0xd6, 0x77, 0x3e, 0xc4, 0xa6, 0x76, - 0x5d, 0xef, 0x82, 0x89, 0x33, 0x74, 0x2d, 0x93, 0x29, 0xfc, 0x88, 0x67, 0x1c, 0xcd, - 0x81, 0x21, 0xa4, 0x23, - ], - esk: [ - 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, 0xa5, 0xd8, 0x9a, 0xa8, - 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, 0x6a, 0x72, 0xcb, 0x74, - 0xfb, 0x18, 0xd1, 0x17, - ], - ephemeral_key: [ - 0x3c, 0x04, 0xbe, 0x6e, 0x42, 0xa6, 0xca, 0x7f, 0x5d, 0xda, 0x0d, 0x82, 0xdf, 0x30, - 0x7b, 0xd9, 0x6b, 0xb7, 0xb1, 0xae, 0x8d, 0x62, 0x31, 0x87, 0xe3, 0x9c, 0x00, 0xa4, - 0x8c, 0x25, 0xaa, 0x9d, - ], - shared_secret: [ - 0x3a, 0x60, 0x2b, 0xaf, 0xb8, 0xa2, 0x66, 0x5a, 0x74, 0xdf, 0x34, 0xab, 0x6e, 0x3c, - 0x48, 0x8b, 0x09, 0xe2, 0x28, 0x4e, 0xa1, 0x7d, 0x56, 0x02, 0x62, 0xe2, 0x1f, 0x7f, - 0x3c, 0xba, 0xa3, 0x95, - ], - k_enc: [ - 0x1b, 0x6d, 0xd1, 0x03, 0x49, 0x63, 0x67, 0xc9, 0x2b, 0x36, 0x8f, 0xc2, 0xf1, 0xc6, - 0x2e, 0x56, 0xc8, 0xc9, 0xfb, 0xe3, 0x4a, 0x35, 0x84, 0x1f, 0xe1, 0xa3, 0x70, 0x96, - 0x43, 0xe1, 0x35, 0xe1, - ], - p_enc: [ - 0x03, 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, 0x07, 0xd2, - 0x7a, 0xc6, 0xec, 0x3c, 0x57, 0x25, 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, - 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, - 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, 0xee, 0xba, 0xe6, 0xfa, 0x64, 0xd0, 0x87, 0x40, - 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, 0xc3, 0x93, 0x11, 0x78, - 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, 0xe5, 0xf5, 0xd4, 0xbc, - 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, - 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, - 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, - 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, - 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, - 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, - 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, - 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, - 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, - 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, - 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, - 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, - 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, - 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, - 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, - 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, - 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, - 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, - 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, - 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, - 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, - 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, - 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, - 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, - 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, - 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, - 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, - 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, - 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, - 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, - 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, - 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, - 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, - 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, - 0xe8, 0xba, 0x4f, 0x52, - ], - c_enc: [ - 0xb4, 0x15, 0x88, 0x23, 0x1d, 0x6b, 0xa2, 0x9c, 0xc5, 0xb9, 0xaa, 0xf0, 0xc1, 0xf0, - 0xba, 0x44, 0x16, 0x6e, 0xdb, 0x8a, 0x27, 0x29, 0xca, 0xba, 0x53, 0x71, 0xe7, 0xac, - 0x36, 0x90, 0x0f, 0xaa, 0x64, 0xf5, 0x76, 0x0d, 0xce, 0x55, 0x20, 0xda, 0x82, 0x8d, - 0x5e, 0x25, 0xbd, 0x83, 0x51, 0x95, 0x11, 0x64, 0x12, 0x11, 0x80, 0x9d, 0xff, 0xd8, - 0xcf, 0xeb, 0xff, 0xf3, 0xcd, 0xdc, 0xd2, 0x75, 0x88, 0x1e, 0x39, 0xb6, 0x3d, 0xac, - 0x4d, 0x98, 0x6b, 0x10, 0xc0, 0xe4, 0xc5, 0x52, 0x63, 0xde, 0x3e, 0x02, 0x54, 0x94, - 0x81, 0x8a, 0x38, 0x08, 0xd9, 0xab, 0xc6, 0xec, 0x38, 0x8f, 0x95, 0x26, 0x73, 0x95, - 0x0a, 0xa2, 0xd0, 0xe4, 0xba, 0x00, 0x53, 0x75, 0xac, 0x60, 0x5d, 0xc8, 0x25, 0xde, - 0x4d, 0xd8, 0x93, 0x8b, 0x94, 0x7f, 0xf7, 0x19, 0x4c, 0xfe, 0x7c, 0x1d, 0x79, 0xa1, - 0x27, 0x15, 0x5d, 0x11, 0xcb, 0xe3, 0x43, 0xf3, 0x2f, 0xd1, 0x0c, 0x7d, 0xae, 0x39, - 0x1f, 0x00, 0xb4, 0x4f, 0xbe, 0x30, 0x1c, 0x63, 0xfd, 0x4b, 0xf1, 0xc0, 0xdf, 0xb6, - 0xc9, 0xec, 0xb4, 0xc3, 0xf3, 0xfe, 0xf5, 0x40, 0xb6, 0x7e, 0xb9, 0x23, 0x13, 0x71, - 0x9c, 0x5a, 0x30, 0x7a, 0xd3, 0x95, 0x6b, 0xb9, 0x4e, 0x29, 0x86, 0x85, 0x2a, 0x64, - 0x5a, 0x95, 0xd6, 0xdc, 0x75, 0xaa, 0x27, 0x4c, 0xcf, 0xd2, 0x71, 0xd0, 0xea, 0xe2, - 0x65, 0x81, 0xf5, 0xf5, 0x5d, 0x64, 0x74, 0xaa, 0xad, 0x37, 0x4c, 0x86, 0x45, 0x05, - 0xe6, 0x92, 0x37, 0xf6, 0x66, 0x99, 0xee, 0x39, 0xe9, 0xfc, 0xf5, 0xb1, 0xb7, 0x03, - 0x35, 0x1e, 0x71, 0xf6, 0x3b, 0x02, 0x33, 0x40, 0x82, 0xee, 0xbe, 0xd8, 0x68, 0xb5, - 0x61, 0x2a, 0x33, 0x95, 0x78, 0x5a, 0x33, 0x2a, 0x52, 0x43, 0xe4, 0x98, 0x6e, 0x1f, - 0xf5, 0xb4, 0x2d, 0x06, 0x69, 0xc1, 0x5c, 0x45, 0xff, 0x81, 0xe2, 0x2e, 0xea, 0xe4, - 0xde, 0x7d, 0x9a, 0x4f, 0x57, 0x24, 0xc8, 0x96, 0x03, 0x94, 0x92, 0x5b, 0xa1, 0xa1, - 0x90, 0x0f, 0xa2, 0xb5, 0x59, 0x3d, 0x55, 0x45, 0x5e, 0x0b, 0xe0, 0x31, 0x8c, 0x80, - 0x23, 0x81, 0xec, 0x9c, 0x0a, 0x83, 0xc2, 0xe5, 0xf9, 0x33, 0x9f, 0x02, 0x9c, 0x44, - 0x24, 0x72, 0x8f, 0x91, 0x9d, 0x18, 0x4f, 0x36, 0x16, 0x50, 0xba, 0x65, 0xd6, 0x98, - 0xa8, 0xd1, 0x67, 0xbe, 0xd9, 0xdd, 0x01, 0xfa, 0x70, 0x74, 0xe4, 0x6a, 0xf6, 0x57, - 0x16, 0xdd, 0xd9, 0x7e, 0x7b, 0xb6, 0x00, 0x13, 0x05, 0x96, 0x8c, 0xd5, 0xb4, 0x87, - 0x0d, 0xf2, 0x00, 0x42, 0xe7, 0x69, 0xe0, 0x2d, 0xf1, 0x8b, 0x9f, 0xde, 0x9f, 0xda, - 0xa7, 0x6b, 0x00, 0xca, 0x26, 0x45, 0x9d, 0x54, 0x37, 0x19, 0x19, 0x72, 0xd7, 0x08, - 0xde, 0xda, 0xbf, 0x1d, 0x61, 0x7f, 0x73, 0x3a, 0x60, 0xeb, 0xfe, 0xc6, 0xac, 0xf0, - 0x0b, 0xb1, 0xdf, 0xbf, 0x11, 0x2d, 0x3a, 0xaa, 0xc9, 0xfb, 0xd2, 0x30, 0xcc, 0xaa, - 0x9c, 0xf3, 0x58, 0x45, 0x93, 0x54, 0xac, 0x5b, 0x29, 0xbd, 0xb7, 0x3a, 0x45, 0x27, - 0x1b, 0x1f, 0x9e, 0xd0, 0x0e, 0x3e, 0x20, 0xb1, 0x2f, 0xed, 0x5c, 0xd5, 0x6a, 0xbb, - 0xb0, 0xb9, 0x4a, 0x9e, 0xee, 0x5f, 0xf8, 0xf9, 0x36, 0x1d, 0xfd, 0x6c, 0x94, 0x08, - 0x5d, 0x28, 0x98, 0xe5, 0x46, 0xeb, 0x92, 0xe6, 0xdb, 0xe9, 0xf0, 0x2e, 0xb5, 0xbf, - 0x7d, 0x12, 0x67, 0x5d, 0x3c, 0x6a, 0xc7, 0x18, 0x4b, 0x26, 0x01, 0xe4, 0xf4, 0x05, - 0x37, 0x3a, 0x4f, 0x1c, 0x5d, 0xf7, 0x6b, 0x3c, 0xb5, 0x29, 0x99, 0xd8, 0x0f, 0x59, - 0xb3, 0x94, 0xbc, 0xed, 0x9f, 0x66, 0xbc, 0xf7, 0xdc, 0x37, 0xc2, 0xb4, 0xc6, 0xf7, - 0x74, 0x5b, 0xc6, 0xf0, 0x37, 0x74, 0xfa, 0xc6, 0x24, 0x5d, 0x7c, 0x63, 0x6d, 0xfc, - 0x5f, 0x76, 0x58, 0xb2, 0xd2, 0xfd, 0x84, 0xac, 0xa9, 0xe0, 0xef, 0xcd, 0xe0, 0x09, - 0x3e, 0x62, 0x29, 0x38, 0xb7, 0x5d, 0xae, 0x66, 0xcf, 0x63, 0xf6, 0xd2, 0x35, 0x17, - 0x2e, 0x5a, 0x0b, 0xbe, 0xcd, 0x15, 0x56, 0x6c, 0x61, 0xfe, 0x5a, 0x58, 0x94, 0x7c, - 0x18, 0xb9, 0xb5, 0xa1, 0x21, 0x11, 0x25, 0x94, 0x3b, 0x09, 0x32, 0x24, 0x96, 0x7b, - 0x7e, 0x44, 0x16, 0x70, 0x64, 0xc9, - ], - ock: [ - 0x67, 0x1c, 0xed, 0xd6, 0xf5, 0x73, 0xa4, 0x6f, 0xf1, 0xea, 0xd0, 0x48, 0x21, 0x98, - 0x56, 0x36, 0xe2, 0x3f, 0xb1, 0x5c, 0x6f, 0x48, 0x05, 0xfd, 0x57, 0x63, 0x12, 0xc2, - 0x07, 0x02, 0xa4, 0x24, - ], - op: [ - 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, - 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, - 0x43, 0x4b, 0x1e, 0xb0, 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, - 0xa5, 0xd8, 0x9a, 0xa8, 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, - 0x6a, 0x72, 0xcb, 0x74, 0xfb, 0x18, 0xd1, 0x17, - ], - c_out: [ - 0x59, 0x97, 0x53, 0xe4, 0x0a, 0xda, 0xea, 0xff, 0x6f, 0xaa, 0xf5, 0xa6, 0xf3, 0x0e, - 0x39, 0x13, 0x8f, 0xde, 0x82, 0x0f, 0x7b, 0xec, 0x7c, 0x8d, 0x0f, 0xd8, 0x4b, 0x48, - 0x36, 0x94, 0xe5, 0x0c, 0x4b, 0xdd, 0xee, 0x2f, 0xb1, 0xa4, 0xf9, 0x95, 0xb1, 0xa3, - 0xba, 0x40, 0xf4, 0x66, 0xb4, 0x2e, 0x8b, 0x5d, 0x01, 0x38, 0xfd, 0x30, 0xbf, 0xf6, - 0xae, 0x8c, 0xb1, 0x55, 0xf4, 0x0c, 0xdc, 0x37, 0x39, 0xfa, 0xbf, 0x2f, 0x00, 0xda, - 0x3a, 0xc6, 0xa7, 0x36, 0x3b, 0xc2, 0xf4, 0xaa, 0x10, 0xfe, - ], - asset: Some([ - 0x64, 0xd0, 0x87, 0x40, 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, - 0xc3, 0x93, 0x11, 0x78, 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, - 0xe5, 0xf5, 0xd4, 0xbc, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0xb4, 0x9e, 0x3c, 0x5b, 0xb9, 0x9e, 0x47, 0xc5, 0x3d, 0x6e, 0x5c, 0x34, 0x7c, 0x99, - 0x8f, 0x30, 0x2d, 0x3f, 0xf4, 0x75, 0x23, 0xe7, 0xc3, 0xd7, 0xb6, 0x4c, 0x82, 0x98, - 0xdc, 0x7b, 0x10, 0xe9, 0x54, 0xdf, 0x06, 0x00, 0x0b, 0xc0, 0xcc, 0x30, 0xec, 0xf6, - 0x75, 0x5d, 0x92, 0x7e, 0xee, 0xce, 0xe6, 0xec, 0x9e, 0x8e, 0x0c, 0xba, 0xa3, 0x1b, - 0x71, 0xe0, 0xa4, 0x33, 0x4a, 0xd6, 0x42, 0x1b, - ], - ovk: [ - 0x97, 0x9f, 0x06, 0x58, 0x66, 0x73, 0xbc, 0x6f, 0xf1, 0xc5, 0xd3, 0xb3, 0x20, 0xf3, - 0x49, 0xa5, 0xb3, 0xa8, 0xb3, 0x55, 0x59, 0x22, 0x96, 0xaa, 0xf6, 0x1c, 0x5b, 0x72, - 0x52, 0xf7, 0x3e, 0xc0, - ], - default_d: [ - 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, - ], - default_pk_d: [ - 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, - 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, - 0xf4, 0x1a, 0x1f, 0x88, - ], - v: 5531329397987978327, - rseed: [ - 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, - 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, - 0xd0, 0x11, 0x8b, 0xbd, - ], - memo: [ - 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, - 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, - 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, - 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, - 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, - 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, - 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, - 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, - 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, - 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, - 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, - 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, - 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, - 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, - 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, - 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, - 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, - 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, - 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, - 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, - 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, - 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, - 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, - 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, - 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, - 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, - 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, - 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, - 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, - 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, - 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, - 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, - 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, - 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, - 0x09, 0x5d, 0x98, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x1a, 0xa2, 0x3d, 0x96, 0x79, 0xbc, 0x66, 0x04, 0xb6, 0x25, 0x2c, 0x4f, 0x48, 0x1b, - 0x3a, 0x2a, 0xf5, 0x46, 0x32, 0xf8, 0x30, 0x08, 0x14, 0x68, 0x29, 0x65, 0x94, 0x5e, - 0x7e, 0x33, 0x2a, 0x0d, - ], - rho: [ - 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, - 0x67, 0x93, 0xc3, 0xfe, 0xfa, 0xda, 0xee, 0xa8, 0xe2, 0x3c, 0x44, 0xd5, 0xe0, 0x18, - 0x4b, 0xc8, 0x45, 0x10, - ], - cmx: [ - 0x76, 0xf1, 0xbd, 0x50, 0xf9, 0xb9, 0x06, 0xcb, 0x9f, 0xf2, 0xdd, 0x91, 0x8a, 0x36, - 0x7e, 0x5f, 0xb1, 0xa2, 0xef, 0x39, 0xf1, 0x4f, 0x6c, 0xe9, 0x4f, 0xf9, 0xf0, 0x91, - 0x55, 0xf8, 0xc2, 0x11, - ], - esk: [ - 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, 0xa1, 0xe6, 0xfb, 0x57, - 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, 0xb9, 0x5f, 0xc8, 0x7e, - 0xa7, 0x37, 0x3e, 0x2f, - ], - ephemeral_key: [ - 0xda, 0x72, 0x84, 0xa0, 0xe0, 0xde, 0x52, 0x09, 0x3c, 0xc2, 0xe1, 0x9c, 0x0a, 0xf1, - 0x93, 0xbd, 0xb4, 0x2c, 0x80, 0xc9, 0xc7, 0xf9, 0xf2, 0x36, 0x00, 0xe6, 0x08, 0x01, - 0x72, 0xc5, 0xf5, 0x39, - ], - shared_secret: [ - 0x9b, 0xcf, 0xb9, 0x6f, 0x4c, 0xf1, 0x83, 0xc1, 0x7f, 0xb1, 0x99, 0xda, 0x16, 0x5f, - 0xbf, 0x8a, 0x47, 0x47, 0x7e, 0x00, 0x36, 0x6d, 0x1c, 0xb7, 0x3b, 0x32, 0xec, 0x0e, - 0x3a, 0xc1, 0x98, 0x0f, - ], - k_enc: [ - 0x21, 0xe0, 0x97, 0x87, 0x0a, 0xee, 0xc0, 0x19, 0x76, 0x86, 0xee, 0x37, 0x22, 0x78, - 0xfe, 0x4a, 0xa2, 0x23, 0x8d, 0x87, 0x65, 0x32, 0x63, 0x84, 0x8a, 0x2f, 0xf5, 0x27, - 0x9f, 0x2b, 0x1d, 0x9b, - ], - p_enc: [ - 0x03, 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, 0x57, 0xac, - 0xbf, 0xfe, 0xc7, 0x3a, 0xc3, 0x4c, 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, - 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, - 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, 0xd0, 0x11, 0x8b, 0xbd, 0xc3, 0xcc, 0x4f, 0x43, - 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, 0xe3, 0x7a, 0x83, 0xec, - 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, 0x29, 0x03, 0x35, 0xaa, - 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, - 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, - 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, - 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, - 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, - 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, - 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, - 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, - 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, - 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, - 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, - 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, - 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, - 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, - 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, - 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, - 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, - 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, - 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, - 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, - 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, - 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, - 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, - 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, - 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, - 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, - 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, - 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, - 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, - 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, - 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, - 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, - 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, - 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, - 0x09, 0x5d, 0x98, 0x77, - ], - c_enc: [ - 0x13, 0xd7, 0xdf, 0xcd, 0x1d, 0x75, 0x4d, 0xcd, 0x16, 0x52, 0x32, 0x83, 0x8f, 0x14, - 0xdd, 0x80, 0x5e, 0x12, 0xcc, 0x7e, 0x75, 0x15, 0x43, 0xd2, 0xa6, 0x8e, 0x23, 0x7a, - 0x92, 0x3b, 0xce, 0xeb, 0xa3, 0x5a, 0x62, 0x43, 0xc6, 0xa4, 0xc5, 0xf0, 0xd2, 0xa4, - 0xc3, 0x86, 0x07, 0xa6, 0xf1, 0x1b, 0x17, 0xfd, 0xd6, 0xc6, 0x92, 0x66, 0xf2, 0xc9, - 0x6a, 0xdc, 0x44, 0x6f, 0x2e, 0x2d, 0x07, 0x3e, 0xe9, 0xea, 0xe2, 0x9a, 0x37, 0xef, - 0x5d, 0x03, 0xf6, 0x78, 0xf5, 0x56, 0x29, 0x45, 0xb2, 0x08, 0x27, 0x76, 0xce, 0x9f, - 0x39, 0x08, 0x87, 0x3a, 0x99, 0xa6, 0xa2, 0x8b, 0xae, 0xdc, 0x7f, 0x54, 0x89, 0xce, - 0x4b, 0x30, 0xd8, 0x43, 0x66, 0xc5, 0x46, 0xb4, 0x36, 0x67, 0x91, 0x44, 0xf9, 0x27, - 0xf7, 0x1c, 0x65, 0x09, 0x69, 0xda, 0x22, 0x42, 0x28, 0x5a, 0x86, 0x27, 0x96, 0x54, - 0x89, 0xb7, 0x0b, 0x35, 0x6c, 0xf7, 0x4e, 0x07, 0x8a, 0xa2, 0x7d, 0xa8, 0xf9, 0x2f, - 0xb3, 0x09, 0x57, 0x12, 0x62, 0xf2, 0xd4, 0xc3, 0x36, 0xf7, 0x12, 0x15, 0x9b, 0x3e, - 0x9b, 0x43, 0x24, 0x38, 0x5b, 0xb3, 0x26, 0x2a, 0xc5, 0xf3, 0x13, 0x57, 0xaf, 0x9e, - 0x1a, 0xaa, 0x75, 0xd0, 0x1c, 0x06, 0x31, 0xbf, 0xdd, 0x34, 0xc5, 0x9b, 0x27, 0xd5, - 0x3b, 0xeb, 0xf1, 0xaa, 0x54, 0xe9, 0xc4, 0xaa, 0x98, 0x0f, 0x24, 0x7b, 0xf4, 0x22, - 0xa0, 0xe6, 0xdb, 0xf5, 0x54, 0x6e, 0xdc, 0x10, 0x0f, 0xce, 0x6c, 0xce, 0xc8, 0x32, - 0x7e, 0xb4, 0x8a, 0x9a, 0x39, 0xe4, 0xc2, 0xa9, 0x12, 0xb2, 0x98, 0x85, 0xe0, 0xc3, - 0xe7, 0x33, 0x55, 0x58, 0xbd, 0x85, 0x84, 0x38, 0xd0, 0x35, 0xd2, 0xf2, 0xbe, 0x1d, - 0x35, 0x66, 0xe4, 0x22, 0xfe, 0x37, 0xc0, 0xcb, 0x2e, 0x05, 0x8d, 0xad, 0x8c, 0xc6, - 0x45, 0x62, 0xa5, 0x50, 0x1b, 0x54, 0xa4, 0x4f, 0x9a, 0x77, 0x77, 0xc6, 0xd2, 0x77, - 0x04, 0xa4, 0xce, 0xad, 0x26, 0xa1, 0xc2, 0x56, 0x01, 0x8d, 0xc1, 0xbb, 0xfa, 0x58, - 0x84, 0xa0, 0x6c, 0xc7, 0x25, 0x23, 0xaf, 0xfb, 0x43, 0xf5, 0xc5, 0xbc, 0x2f, 0x1d, - 0x36, 0x04, 0x0f, 0x85, 0xf7, 0xe8, 0xc0, 0x62, 0xc1, 0xf2, 0x26, 0x50, 0x9d, 0x20, - 0xf9, 0xa4, 0x88, 0x5e, 0x15, 0x70, 0x4f, 0x73, 0x01, 0xdf, 0x60, 0x3d, 0xa1, 0xfc, - 0x5b, 0xca, 0x84, 0xf8, 0x55, 0xc1, 0x17, 0xcb, 0x30, 0x55, 0xc5, 0x70, 0x83, 0x45, - 0x7e, 0x1d, 0x14, 0x85, 0x7c, 0x2b, 0xf9, 0x41, 0xe8, 0x20, 0x73, 0x5c, 0x58, 0x8a, - 0xae, 0x6f, 0x66, 0x45, 0xdc, 0x3f, 0xbd, 0x30, 0x65, 0xab, 0xa1, 0x7f, 0xd2, 0x48, - 0x2a, 0x1b, 0x37, 0xb2, 0xf3, 0x88, 0x07, 0x5e, 0x46, 0xbb, 0x9d, 0x37, 0x27, 0xcc, - 0x73, 0xdb, 0xae, 0x0e, 0x96, 0xa8, 0x44, 0x5f, 0xda, 0x8f, 0x87, 0x64, 0xf9, 0x68, - 0x0b, 0xf6, 0xc5, 0x91, 0xa8, 0x48, 0x10, 0xfa, 0x0c, 0x1b, 0x5a, 0x2f, 0x2a, 0xa9, - 0xad, 0xbb, 0x88, 0x64, 0x22, 0x31, 0x72, 0x1e, 0xd6, 0xea, 0x12, 0x16, 0xab, 0x9b, - 0xfa, 0x0e, 0x12, 0x4c, 0xe4, 0x74, 0x94, 0x44, 0x53, 0x4d, 0x68, 0x70, 0x19, 0x74, - 0x60, 0xf7, 0x49, 0xef, 0xb0, 0x28, 0x8f, 0x96, 0x28, 0x3f, 0xc9, 0x37, 0xef, 0xbb, - 0x14, 0x59, 0xaa, 0x73, 0xc2, 0x7b, 0x6b, 0x2b, 0x5c, 0x57, 0x7d, 0x46, 0x60, 0xf9, - 0x8e, 0x81, 0x8c, 0xaa, 0xad, 0xbe, 0x45, 0x4e, 0xcd, 0x16, 0xc1, 0xd8, 0xa9, 0x9b, - 0x77, 0x97, 0x8e, 0x93, 0xd6, 0x9d, 0xcb, 0x8b, 0xf0, 0xe8, 0x4a, 0x0a, 0x91, 0x3f, - 0x55, 0xcc, 0x16, 0x50, 0xc2, 0xb9, 0x2d, 0x4c, 0x9d, 0xcd, 0xb1, 0x2e, 0xe2, 0x36, - 0x7e, 0xd9, 0x79, 0xb9, 0x53, 0x5f, 0xe1, 0x5c, 0x87, 0xd1, 0x7f, 0x37, 0xa3, 0x24, - 0x84, 0x7f, 0x16, 0x45, 0x39, 0x75, 0x7d, 0x83, 0x00, 0x87, 0xf6, 0x39, 0xeb, 0x6c, - 0x3e, 0xfb, 0x8d, 0xa4, 0xff, 0xa5, 0xd7, 0xca, 0x58, 0x34, 0x4d, 0x65, 0x81, 0x76, - 0x64, 0xa7, 0x4e, 0xaf, 0xa1, 0xa4, 0x7f, 0x69, 0xf1, 0xc8, 0x10, 0x6b, 0x6f, 0x5f, - 0x96, 0x4f, 0x4c, 0x73, 0x68, 0xed, 0x11, 0x06, 0x29, 0x54, 0xd2, 0xe8, 0xd3, 0x0c, - 0xcc, 0xac, 0xba, 0xd9, 0xa2, 0xfa, - ], - ock: [ - 0x57, 0x97, 0xef, 0x48, 0x70, 0xb0, 0x86, 0x50, 0xfa, 0x99, 0xad, 0xae, 0x58, 0x85, - 0x19, 0x9e, 0x3b, 0x04, 0x4b, 0x2a, 0x0a, 0x8c, 0xe1, 0x61, 0x43, 0x42, 0xb5, 0xdc, - 0xb2, 0x8e, 0x6e, 0x09, - ], - op: [ - 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, - 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, - 0xf4, 0x1a, 0x1f, 0x88, 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, - 0xa1, 0xe6, 0xfb, 0x57, 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, - 0xb9, 0x5f, 0xc8, 0x7e, 0xa7, 0x37, 0x3e, 0x2f, - ], - c_out: [ - 0xb8, 0xb4, 0x6c, 0x7e, 0xc4, 0xa8, 0x74, 0x2a, 0x22, 0xd3, 0xcd, 0x11, 0x74, 0x1c, - 0x23, 0x04, 0x22, 0x1c, 0xa5, 0x97, 0x29, 0x4e, 0x08, 0xa4, 0xc7, 0x1b, 0x17, 0xc7, - 0x26, 0x5d, 0x4d, 0xa7, 0x7c, 0xfe, 0x84, 0xb8, 0x7e, 0x76, 0xed, 0xaa, 0xec, 0xc2, - 0x24, 0xb8, 0x36, 0xde, 0x22, 0x4c, 0x73, 0x58, 0x13, 0x19, 0xa0, 0xba, 0x27, 0x88, - 0xdb, 0xf8, 0x3b, 0xcf, 0x47, 0xa4, 0x8e, 0xeb, 0x02, 0xb4, 0x3a, 0x18, 0x02, 0x7b, - 0x8f, 0x59, 0x11, 0x65, 0xc2, 0x86, 0xe8, 0xb6, 0x54, 0xec, - ], - asset: Some([ - 0xc3, 0xcc, 0x4f, 0x43, 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, - 0xe3, 0x7a, 0x83, 0xec, 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, - 0x29, 0x03, 0x35, 0xaa, - ]), - }, - TestVector { - incoming_viewing_key: [ - 0xa6, 0x68, 0x13, 0x52, 0xa3, 0x52, 0x26, 0x91, 0x10, 0x0f, 0x53, 0xfc, 0x34, 0xab, - 0x73, 0x32, 0x8a, 0xf1, 0xb9, 0xf3, 0xa4, 0xa0, 0x6d, 0xbd, 0x3a, 0x14, 0x99, 0x67, - 0x09, 0xe6, 0xf2, 0x84, 0x31, 0xee, 0x72, 0xf2, 0x69, 0xae, 0xd7, 0x5d, 0x36, 0x34, - 0x89, 0x36, 0x90, 0x5e, 0xbb, 0x91, 0x80, 0x7d, 0x74, 0xd5, 0x0c, 0xb2, 0x7f, 0xcd, - 0x8b, 0x4f, 0xb6, 0xf4, 0x48, 0xc3, 0x62, 0x03, - ], - ovk: [ - 0x78, 0xf1, 0x45, 0xea, 0x29, 0xd2, 0x71, 0xb9, 0x40, 0xc6, 0x99, 0x41, 0xe4, 0xc3, - 0xfd, 0x2d, 0x71, 0xf3, 0xb1, 0x90, 0x69, 0x0e, 0xe1, 0x6f, 0x5d, 0x14, 0xac, 0x22, - 0x24, 0xe6, 0xfc, 0x89, - ], - default_d: [ - 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, - ], - default_pk_d: [ - 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, - 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, - 0x3a, 0x56, 0x6a, 0xaa, - ], - v: 15093716717054627455, - rseed: [ - 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, - 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, - 0x24, 0x57, 0x16, 0xa4, - ], - memo: [ - 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, - 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, - 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, - 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, - 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, - 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, - 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, - 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, - 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, - 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, - 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, - 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, - 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, - 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, - 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, - 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, - 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, - 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, - 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, - 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, - 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, - 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, - 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, - 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, - 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, - 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, - 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, - 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, - 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, - 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, - 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, - 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, - 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, - 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, - 0x70, 0xe0, 0x90, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ], - cv_net: [ - 0x91, 0x6d, 0xc3, 0x82, 0x2a, 0x4e, 0x3b, 0xb4, 0x1f, 0xa8, 0x33, 0xc2, 0x73, 0xa9, - 0xd3, 0x7d, 0x17, 0x17, 0xa4, 0x8d, 0x8f, 0x00, 0x6c, 0x1f, 0xf5, 0x86, 0x21, 0x46, - 0x29, 0x55, 0x39, 0x1c, - ], - rho: [ - 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, - 0xd0, 0x28, 0x44, 0x22, 0x13, 0x50, 0x86, 0x4e, 0xed, 0x56, 0x3d, 0xab, 0x30, 0x22, - 0x7f, 0x28, 0x4b, 0x2e, - ], - cmx: [ - 0x89, 0xe6, 0xa2, 0xb9, 0x70, 0x84, 0xe3, 0xd3, 0x34, 0x4f, 0xee, 0xb4, 0x64, 0x65, - 0x05, 0x72, 0x51, 0xb1, 0x9d, 0xa0, 0xce, 0xdf, 0x79, 0x71, 0x94, 0xc5, 0x97, 0xf9, - 0xf7, 0x7e, 0xf2, 0x1f, - ], - esk: [ - 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, 0x02, 0xf5, 0x10, 0xe9, - 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, 0xc4, 0x69, 0x2d, 0x0c, - 0x1b, 0x30, 0x33, 0x01, - ], - ephemeral_key: [ - 0x27, 0xcb, 0x40, 0x68, 0x0f, 0xb1, 0xd9, 0x19, 0x64, 0x6e, 0x74, 0x20, 0xe6, 0xa8, - 0xb5, 0x20, 0xe1, 0x9a, 0x17, 0x3f, 0x1e, 0x79, 0x4d, 0x2b, 0x49, 0x2b, 0xfa, 0xbb, - 0x83, 0xce, 0x6c, 0xa0, - ], - shared_secret: [ - 0x1c, 0xd0, 0x66, 0x91, 0x6c, 0x19, 0xfa, 0x33, 0x69, 0xaa, 0x3c, 0x6a, 0x53, 0x76, - 0x97, 0xf4, 0xb4, 0x26, 0x44, 0xda, 0x20, 0xca, 0x46, 0x79, 0x93, 0x2b, 0x7c, 0x90, - 0x5f, 0x2d, 0x69, 0x00, - ], - k_enc: [ - 0xce, 0x9d, 0x22, 0x0d, 0x3a, 0xfe, 0xc6, 0x23, 0x21, 0xdd, 0xf1, 0x97, 0xa6, 0x36, - 0xdc, 0xb3, 0x45, 0x58, 0x83, 0xb7, 0x35, 0x82, 0x8c, 0x65, 0xe7, 0x16, 0x6c, 0x15, - 0xd8, 0xcc, 0xfc, 0xf9, - ], - p_enc: [ - 0x03, 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, 0x7f, 0x8e, - 0x6a, 0x5c, 0x62, 0xa7, 0x77, 0xd1, 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, - 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, - 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, 0x24, 0x57, 0x16, 0xa4, 0x96, 0x86, 0xaa, 0x36, - 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, 0xab, 0xcf, 0xac, 0x88, - 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, 0x07, 0x2d, 0x2d, 0x18, - 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, - 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, - 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, - 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, - 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, - 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, - 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, - 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, - 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, - 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, - 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, - 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, - 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, - 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, - 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, - 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, - 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, - 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, - 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, - 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, - 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, - 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, - 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, - 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, - 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, - 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, - 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, - 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, - 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, - 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, - 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, - 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, - 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, - 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, - 0x70, 0xe0, 0x90, 0x3a, - ], - c_enc: [ - 0xb1, 0x69, 0x64, 0x77, 0xe6, 0x58, 0xb6, 0xf8, 0xe2, 0x4e, 0x02, 0x55, 0x52, 0xb4, - 0x8d, 0xd4, 0x84, 0x58, 0xf2, 0xcd, 0x75, 0x70, 0xc0, 0xe8, 0xce, 0xc4, 0xed, 0x4c, - 0xf7, 0x9b, 0xd5, 0xb6, 0x9e, 0xa8, 0x54, 0x12, 0x3b, 0x4e, 0xaf, 0x97, 0x8b, 0x14, - 0x2e, 0xb3, 0xef, 0x53, 0xaa, 0xfc, 0x78, 0x90, 0xdd, 0xa2, 0x8a, 0xfa, 0x25, 0xf1, - 0x45, 0xc8, 0xb9, 0x7f, 0x7b, 0x94, 0x50, 0xc1, 0xd5, 0xe0, 0xc3, 0x7d, 0xaf, 0x5e, - 0xd4, 0xec, 0xd9, 0xb6, 0x3d, 0xbc, 0xd2, 0x15, 0x11, 0x23, 0x13, 0x9b, 0xbc, 0x2b, - 0x65, 0x1a, 0x8f, 0x69, 0xcf, 0xbf, 0xb7, 0xcb, 0x60, 0x44, 0x78, 0xf3, 0xf2, 0x64, - 0xd9, 0xdd, 0x75, 0xcf, 0x31, 0x9e, 0x3e, 0xcd, 0xf5, 0xb3, 0x34, 0x26, 0x54, 0x85, - 0x7c, 0x52, 0xa1, 0xfc, 0x61, 0x40, 0x55, 0xa2, 0x46, 0xf5, 0x26, 0x3e, 0x85, 0x36, - 0x83, 0xef, 0x54, 0x41, 0x3b, 0xac, 0x99, 0x1a, 0xe6, 0x35, 0x01, 0x50, 0xe1, 0x34, - 0x52, 0xa3, 0xa6, 0x20, 0xc5, 0x3f, 0x80, 0xda, 0xcc, 0x7a, 0xf0, 0x59, 0x26, 0xd9, - 0xc5, 0x9a, 0x94, 0xe4, 0x78, 0x9a, 0xcc, 0x68, 0xd8, 0x51, 0x05, 0x6b, 0x75, 0xa7, - 0x4e, 0x2e, 0x1b, 0x38, 0xbf, 0xcb, 0x6d, 0xba, 0xab, 0x37, 0xa3, 0x8a, 0xe0, 0x2c, - 0x9c, 0x35, 0x25, 0x9e, 0x52, 0x84, 0xe4, 0xfe, 0x83, 0xdd, 0xb2, 0x29, 0x24, 0xa1, - 0xc4, 0x0a, 0xa2, 0x5e, 0xd1, 0xf5, 0xc0, 0x6d, 0xa1, 0x58, 0x31, 0xf0, 0x41, 0x50, - 0xa3, 0x7c, 0x1b, 0xa3, 0xd1, 0x17, 0x04, 0x93, 0xca, 0x29, 0xf3, 0x43, 0x4a, 0xfa, - 0x06, 0x9b, 0x46, 0xaf, 0xdc, 0x87, 0x0a, 0x29, 0x6f, 0xdc, 0x0e, 0xb6, 0x1b, 0x55, - 0x70, 0x77, 0xa1, 0xda, 0x1f, 0xe8, 0x22, 0xb6, 0xce, 0x24, 0x7c, 0x8e, 0x19, 0x9f, - 0xc4, 0x85, 0x14, 0x6f, 0x38, 0x4a, 0xcf, 0x5c, 0x52, 0x69, 0x7e, 0xfa, 0xcc, 0x5b, - 0xfe, 0x42, 0x02, 0xe8, 0x5f, 0x06, 0x4b, 0xc8, 0xe1, 0x2e, 0xee, 0x39, 0x79, 0x6d, - 0xfd, 0x13, 0x99, 0xb1, 0xc1, 0xe8, 0xc7, 0x4b, 0x5e, 0xc3, 0xc3, 0x1d, 0x2c, 0xfa, - 0x44, 0x87, 0x02, 0x5c, 0xeb, 0x5d, 0xb3, 0x55, 0x9d, 0x4b, 0x7b, 0xac, 0x02, 0x73, - 0xf1, 0x33, 0x51, 0xd2, 0xd1, 0x3c, 0xec, 0x0a, 0x44, 0x8c, 0x00, 0x11, 0x09, 0x45, - 0x2c, 0x40, 0x92, 0xc8, 0x11, 0x91, 0xa0, 0xda, 0xa9, 0x79, 0xe2, 0x6a, 0x96, 0x24, - 0xe4, 0x0c, 0xa4, 0xac, 0xcb, 0x63, 0x46, 0xaa, 0xe1, 0x88, 0xca, 0x09, 0x39, 0xdd, - 0x9f, 0x6b, 0x6e, 0x45, 0xe4, 0x1b, 0xca, 0xeb, 0xdc, 0x1d, 0xa8, 0x01, 0xcc, 0xd4, - 0xdc, 0x93, 0x32, 0x26, 0x6f, 0xb3, 0xeb, 0x23, 0x7b, 0x07, 0x72, 0x45, 0xa7, 0x91, - 0xec, 0xb4, 0x0e, 0x5c, 0x40, 0x56, 0xad, 0xd6, 0xb1, 0xb5, 0xf7, 0xf8, 0xfa, 0x10, - 0x4f, 0xba, 0x61, 0x3e, 0xd9, 0x29, 0xe1, 0xfa, 0xd2, 0x26, 0x47, 0x50, 0x35, 0xb6, - 0x1a, 0x9f, 0x85, 0xaf, 0xba, 0xfb, 0x16, 0x6b, 0x24, 0xc2, 0x4d, 0x2c, 0x28, 0x93, - 0x7b, 0x17, 0x70, 0xba, 0x26, 0x9c, 0x15, 0xeb, 0x2d, 0x9b, 0xdc, 0x2b, 0x83, 0xea, - 0xd8, 0xa0, 0x1d, 0xdb, 0x11, 0x08, 0x3b, 0x13, 0xd6, 0x2d, 0x57, 0x2c, 0xf7, 0x8d, - 0x5c, 0xba, 0x6f, 0x36, 0x52, 0xca, 0xc4, 0xd2, 0x4c, 0x71, 0xc5, 0x47, 0x27, 0x26, - 0x24, 0xc0, 0x78, 0xe0, 0xb9, 0x69, 0x68, 0xfe, 0x09, 0xd8, 0x3e, 0xf7, 0x30, 0x20, - 0x62, 0xbb, 0x5d, 0x3a, 0x2c, 0xcf, 0x73, 0x4e, 0x0f, 0xd3, 0x51, 0x01, 0xfd, 0x58, - 0x64, 0x73, 0x3f, 0x44, 0xd0, 0x75, 0xc3, 0x8b, 0x73, 0xf6, 0xbf, 0xb8, 0xc3, 0x9c, - 0x7b, 0x6b, 0x3d, 0xbc, 0xd1, 0x9a, 0x05, 0x89, 0x91, 0x86, 0x37, 0xf7, 0x5b, 0xbe, - 0x40, 0x15, 0x7b, 0x80, 0xe5, 0x9e, 0x55, 0x58, 0x50, 0x28, 0xa5, 0xec, 0x20, 0x1e, - 0x00, 0x8f, 0xf6, 0xf5, 0x12, 0xe2, 0x53, 0xcc, 0x9a, 0xcf, 0x62, 0x7d, 0x94, 0x35, - 0xdb, 0x6b, 0x14, 0xb9, 0x82, 0x48, 0x79, 0xf4, 0xe4, 0x0a, 0x36, 0xd5, 0xec, 0x94, - 0x2b, 0xff, 0x04, 0xfd, 0x90, 0xa6, 0xaf, 0x8c, 0x58, 0x1d, 0xf6, 0x09, 0xc4, 0x11, - 0xf4, 0x76, 0x11, 0x41, 0xd4, 0xa6, - ], - ock: [ - 0x95, 0x83, 0xf1, 0x0f, 0xed, 0x70, 0xa4, 0x1e, 0x45, 0x8c, 0x65, 0x5c, 0xc0, 0x14, - 0xe2, 0x35, 0x5a, 0x7f, 0x99, 0xae, 0xbc, 0xfe, 0xf7, 0x4a, 0x55, 0x9a, 0xcd, 0x24, - 0x25, 0xfa, 0x21, 0xcf, - ], - op: [ - 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, - 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, - 0x3a, 0x56, 0x6a, 0xaa, 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, - 0x02, 0xf5, 0x10, 0xe9, 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, - 0xc4, 0x69, 0x2d, 0x0c, 0x1b, 0x30, 0x33, 0x01, - ], - c_out: [ - 0xb8, 0x3b, 0x74, 0x5c, 0x9c, 0x0b, 0x04, 0xdd, 0xc7, 0xf1, 0x38, 0x16, 0x94, 0x38, - 0x99, 0x55, 0x3a, 0x30, 0x6a, 0x4a, 0xd0, 0xf2, 0xf5, 0x70, 0x92, 0x2a, 0x89, 0x9b, - 0xab, 0xb9, 0xda, 0xca, 0xd2, 0xbb, 0xc9, 0x5c, 0xf6, 0x5b, 0x73, 0x08, 0x55, 0x0d, - 0xce, 0xdb, 0x64, 0x9e, 0xf1, 0x5e, 0x0b, 0x1a, 0x09, 0x1f, 0xad, 0x5a, 0x93, 0x92, - 0xd0, 0x71, 0xb7, 0x5a, 0xb5, 0x1a, 0x7e, 0x35, 0x06, 0xad, 0x58, 0xd1, 0x71, 0x95, - 0xc9, 0x9f, 0x29, 0x8a, 0xc3, 0x14, 0xec, 0x05, 0xa6, 0x6a, - ], - asset: Some([ - 0x96, 0x86, 0xaa, 0x36, 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, - 0xab, 0xcf, 0xac, 0x88, 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, - 0x07, 0x2d, 0x2d, 0x18, - ]), }, ] } diff --git a/src/test_vectors/note_encryption_v3.rs b/src/test_vectors/note_encryption_v3.rs new file mode 100644 index 000000000..0ea5da482 --- /dev/null +++ b/src/test_vectors/note_encryption_v3.rs @@ -0,0 +1,4389 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_note_encryption) + +pub(crate) struct TestVector { + pub(crate) incoming_viewing_key: [u8; 64], + pub(crate) ovk: [u8; 32], + pub(crate) default_d: [u8; 11], + pub(crate) default_pk_d: [u8; 32], + pub(crate) v: u64, + pub(crate) rseed: [u8; 32], + pub(crate) asset: [u8; 32], + pub(crate) memo: [u8; 512], + pub(crate) cv_net: [u8; 32], + pub(crate) rho: [u8; 32], + pub(crate) cmx: [u8; 32], + pub(crate) esk: [u8; 32], + pub(crate) ephemeral_key: [u8; 32], + pub(crate) shared_secret: [u8; 32], + pub(crate) k_enc: [u8; 32], + pub(crate) p_enc: [u8; 596], + pub(crate) c_enc: [u8; 612], + pub(crate) ock: [u8; 32], + pub(crate) op: [u8; 64], + pub(crate) c_out: [u8; 80], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + incoming_viewing_key: [ + 0x10, 0x39, 0xd8, 0xe6, 0x4a, 0x80, 0x90, 0x2e, 0x10, 0x59, 0x47, 0x81, 0x7d, 0xf3, + 0xbd, 0xfb, 0x7d, 0xf7, 0x03, 0x0e, 0x68, 0x73, 0x9f, 0x9c, 0x53, 0x3a, 0x36, 0xbf, + 0x5a, 0x6a, 0x80, 0x72, 0x43, 0x10, 0x6d, 0xe9, 0xa7, 0xec, 0x54, 0xdd, 0x36, 0xdf, + 0xa7, 0x0b, 0xdb, 0xd9, 0x07, 0x2d, 0xbd, 0xda, 0xb5, 0xe0, 0x66, 0xaa, 0xef, 0xfc, + 0xf9, 0xbb, 0xa3, 0x20, 0xd4, 0xff, 0xf7, 0x12, + ], + ovk: [ + 0x5d, 0x7a, 0x8f, 0x73, 0x9a, 0x2d, 0x9e, 0x94, 0x5b, 0x0c, 0xe1, 0x52, 0xa8, 0x04, + 0x9e, 0x29, 0x4c, 0x4d, 0x6e, 0x66, 0xb1, 0x64, 0x93, 0x9d, 0xaf, 0xfa, 0x2e, 0xf6, + 0xee, 0x69, 0x21, 0x48, + ], + default_d: [ + 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, + ], + default_pk_d: [ + 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, + 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, + 0x49, 0x50, 0x69, 0x2c, + ], + v: 8567075990963576717, + rseed: [ + 0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb, + 0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e, + 0x30, 0xa7, 0x35, 0x94, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, + 0x25, 0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, + 0x91, 0x2a, 0x63, 0x81, 0xce, 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, + 0xd7, 0x55, 0x1d, 0xb5, 0xfd, 0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, + 0xd4, 0x77, 0x08, 0x37, 0x56, 0xd5, 0x9a, 0xf8, 0x0d, 0x06, 0xa7, 0x45, 0xf4, 0x4a, + 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, + 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, 0xcc, 0xb8, 0xf6, 0x76, 0x49, + 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef, 0xc2, + 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d, 0x94, + 0x90, 0x3d, 0x3c, 0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, + 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, + 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, + 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, + 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, + 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d, 0x13, 0x09, 0x13, + 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, 0x47, 0xf1, 0xe1, + 0x91, 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, + 0xa9, 0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, + 0xda, 0xe6, 0x9c, 0xe8, 0xfc, 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, + 0x93, 0x1d, 0xe5, 0x18, 0x85, 0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, + 0xc9, 0x37, 0x83, 0x65, 0xc8, 0xf7, 0x39, 0x3c, 0x94, 0xe2, 0x88, 0x53, 0x15, 0xeb, + 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f, 0xe5, 0x3e, 0x29, 0xfe, 0xf2, + 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, + 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, 0x3f, + 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, + 0x59, 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, + 0xec, 0x89, 0x26, 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, + 0x1e, 0x98, 0x5d, 0x99, 0x58, 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, + 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, + 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d, 0xed, 0x42, 0x43, 0x5e, 0x92, 0x47, 0x69, + 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72, 0x7b, 0x89, 0xe0, + 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6, 0xf2, 0x65, 0x72, + 0x50, 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, + 0xbc, 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, + 0xe7, 0x1a, 0x02, 0xaf, 0x11, 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, + 0xb1, 0xfc, 0xe4, 0x67, 0x50, 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, + 0xc3, 0x82, 0x85, 0x7d, 0xee, 0xcc, 0x40, 0xa9, + ], + cv_net: [ + 0xdd, 0xba, 0x24, 0xf3, 0x9f, 0x70, 0x8e, 0xd7, 0xa7, 0x48, 0x57, 0x13, 0x71, 0x11, + 0x42, 0xc2, 0x38, 0x51, 0x38, 0x15, 0x30, 0x2d, 0xf0, 0xf4, 0x83, 0x04, 0x21, 0xa6, + 0xc1, 0x3e, 0x71, 0x01, + ], + rho: [ + 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, + 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, + 0x05, 0xee, 0xf3, 0x27, + ], + cmx: [ + 0x23, 0x75, 0x7c, 0x51, 0x58, 0x21, 0xcb, 0xc1, 0x84, 0x3c, 0x9a, 0x45, 0x7b, 0x7e, + 0x6a, 0xe6, 0x01, 0xad, 0xd2, 0xea, 0x10, 0xb9, 0xc8, 0x6d, 0x6b, 0x31, 0x7c, 0xe2, + 0xf1, 0x7b, 0xd9, 0x21, + ], + esk: [ + 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, 0x8b, 0xfe, 0x9b, 0x38, + 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, 0x8e, 0x33, 0x35, 0x4f, + 0xff, 0xf1, 0xbd, 0x1a, + ], + ephemeral_key: [ + 0x8a, 0x5e, 0x13, 0x2c, 0x3a, 0x07, 0x04, 0xf2, 0x45, 0x6f, 0xbd, 0x77, 0x7a, 0x13, + 0xd6, 0xec, 0x57, 0x65, 0x56, 0x71, 0xdb, 0x07, 0x2a, 0x7d, 0x27, 0x6a, 0xd9, 0x69, + 0xf5, 0xec, 0x45, 0x17, + ], + shared_secret: [ + 0x36, 0xd5, 0x4c, 0xab, 0xc6, 0x7f, 0x6c, 0xc7, 0x26, 0xa7, 0x30, 0xf3, 0xa0, 0xce, + 0xed, 0x58, 0x53, 0xf0, 0x8c, 0xd3, 0x81, 0x46, 0xc8, 0x34, 0x25, 0x98, 0x98, 0x7c, + 0x21, 0x50, 0x48, 0xa5, + ], + k_enc: [ + 0x82, 0xc4, 0x32, 0x65, 0x33, 0x7f, 0x1a, 0xb3, 0x7b, 0x18, 0xdf, 0x27, 0x75, 0x48, + 0x61, 0x82, 0x63, 0xb8, 0x02, 0x4d, 0x9b, 0x14, 0x5a, 0x05, 0xad, 0xe2, 0xeb, 0x54, + 0x79, 0x18, 0x03, 0x20, + ], + p_enc: [ + 0x03, 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, 0x8d, 0x5f, + 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, + 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb, 0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, + 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e, 0x30, 0xa7, 0x35, 0x94, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, + 0x25, 0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, + 0x91, 0x2a, 0x63, 0x81, 0xce, 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, + 0xd7, 0x55, 0x1d, 0xb5, 0xfd, 0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, + 0xd4, 0x77, 0x08, 0x37, 0x56, 0xd5, 0x9a, 0xf8, 0x0d, 0x06, 0xa7, 0x45, 0xf4, 0x4a, + 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, + 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, 0xcc, 0xb8, 0xf6, 0x76, 0x49, + 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef, 0xc2, + 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d, 0x94, + 0x90, 0x3d, 0x3c, 0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, + 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, + 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, + 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, + 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, + 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d, 0x13, 0x09, 0x13, + 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, 0x47, 0xf1, 0xe1, + 0x91, 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, + 0xa9, 0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, + 0xda, 0xe6, 0x9c, 0xe8, 0xfc, 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, + 0x93, 0x1d, 0xe5, 0x18, 0x85, 0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, + 0xc9, 0x37, 0x83, 0x65, 0xc8, 0xf7, 0x39, 0x3c, 0x94, 0xe2, 0x88, 0x53, 0x15, 0xeb, + 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f, 0xe5, 0x3e, 0x29, 0xfe, 0xf2, + 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, + 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, 0x3f, + 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, + 0x59, 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, + 0xec, 0x89, 0x26, 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, + 0x1e, 0x98, 0x5d, 0x99, 0x58, 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, + 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, + 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d, 0xed, 0x42, 0x43, 0x5e, 0x92, 0x47, 0x69, + 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72, 0x7b, 0x89, 0xe0, + 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6, 0xf2, 0x65, 0x72, + 0x50, 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, + 0xbc, 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, + 0xe7, 0x1a, 0x02, 0xaf, 0x11, 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, + 0xb1, 0xfc, 0xe4, 0x67, 0x50, 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, + 0xc3, 0x82, 0x85, 0x7d, 0xee, 0xcc, 0x40, 0xa9, + ], + c_enc: [ + 0x92, 0xe0, 0x48, 0x74, 0xb5, 0x83, 0x7c, 0x26, 0x1d, 0xaf, 0x1a, 0x27, 0xb7, 0x83, + 0xec, 0x48, 0x65, 0xd3, 0xbb, 0x72, 0x8e, 0xb1, 0x61, 0xda, 0xed, 0xb8, 0x44, 0x6a, + 0xb3, 0x8f, 0x07, 0x8e, 0xa8, 0x66, 0x2e, 0x4d, 0x2e, 0x9d, 0x00, 0xa3, 0x95, 0x27, + 0xdc, 0xde, 0x51, 0x7a, 0xc3, 0xdb, 0xf9, 0xd2, 0x7e, 0x3c, 0xe1, 0x06, 0x21, 0xb8, + 0x97, 0xe9, 0x79, 0x10, 0xba, 0xa5, 0x63, 0xd0, 0xb4, 0xc3, 0x8f, 0x87, 0x77, 0xf9, + 0xdf, 0xb5, 0x5a, 0x4d, 0x0c, 0xa6, 0x49, 0x80, 0x7a, 0x6e, 0x7e, 0x3b, 0x63, 0x7b, + 0xe7, 0x83, 0x5c, 0x0c, 0x07, 0x6e, 0x6f, 0x06, 0xee, 0x5c, 0x8a, 0xac, 0x6a, 0xd2, + 0x13, 0x00, 0xf8, 0xe1, 0xcd, 0x39, 0x5f, 0x69, 0x2d, 0xc5, 0x72, 0xab, 0x07, 0xfd, + 0x4b, 0xe1, 0xf2, 0xc6, 0x52, 0x09, 0x64, 0xed, 0xec, 0x3b, 0xe5, 0x56, 0x22, 0xac, + 0x4d, 0x23, 0x85, 0x8c, 0x39, 0x8d, 0xf6, 0x6d, 0x6a, 0x6e, 0x54, 0x60, 0x18, 0xf9, + 0x81, 0x66, 0x89, 0x24, 0xbe, 0x96, 0x3b, 0x7c, 0xbb, 0x0c, 0x7f, 0x10, 0x4d, 0x16, + 0x07, 0xfb, 0xcb, 0xc0, 0x18, 0x49, 0xd9, 0x93, 0x72, 0xcb, 0x8e, 0x64, 0xb2, 0xca, + 0x15, 0xd7, 0xf8, 0xc5, 0x37, 0x20, 0x05, 0xa8, 0x89, 0xd6, 0xa9, 0x31, 0x23, 0x59, + 0x42, 0x09, 0xe4, 0xd2, 0x59, 0x7b, 0x6e, 0x83, 0x78, 0x2e, 0x5d, 0x1a, 0xb0, 0xc5, + 0xd6, 0x42, 0xbe, 0x32, 0xe7, 0xb4, 0x89, 0x85, 0xaa, 0x07, 0x7e, 0x9a, 0x76, 0xbd, + 0xe2, 0x7d, 0xf4, 0x26, 0x74, 0x8b, 0xf3, 0x25, 0x52, 0x01, 0x56, 0x88, 0xb3, 0x6e, + 0x34, 0xff, 0x9d, 0x22, 0x11, 0xd8, 0x72, 0xfb, 0x23, 0x6a, 0x18, 0x2f, 0xe4, 0xf2, + 0x87, 0xa5, 0x5b, 0xfc, 0xee, 0xa3, 0xed, 0x99, 0xfd, 0xc2, 0x91, 0xf9, 0x1d, 0x6e, + 0xf8, 0xd2, 0x9a, 0x27, 0x8f, 0xa6, 0x46, 0xe8, 0xe7, 0xdc, 0x66, 0xd4, 0x9b, 0x38, + 0x62, 0x26, 0x7e, 0xd5, 0x8b, 0x31, 0x66, 0x09, 0x97, 0xa5, 0x8f, 0x29, 0x73, 0x5c, + 0xc6, 0xe5, 0x98, 0x65, 0x54, 0x2f, 0x5d, 0x90, 0x8c, 0xe5, 0x2d, 0x9f, 0x5b, 0x29, + 0xc9, 0x78, 0x24, 0xd1, 0x4d, 0x4d, 0x64, 0xcd, 0xbe, 0x56, 0x93, 0xb5, 0x1b, 0x7e, + 0xc7, 0x31, 0xc9, 0x92, 0x4b, 0x4f, 0x47, 0x5a, 0x14, 0xd0, 0x58, 0x7b, 0xe6, 0x45, + 0x44, 0x8a, 0x07, 0x55, 0x4f, 0x15, 0xbc, 0x9d, 0xaf, 0xa1, 0xf7, 0x38, 0x6a, 0xe8, + 0x6f, 0x71, 0x48, 0x2b, 0x35, 0x6e, 0xa7, 0x9c, 0xdc, 0x44, 0x73, 0x2c, 0xfa, 0x41, + 0x46, 0xe6, 0xca, 0x51, 0x04, 0xf0, 0xa4, 0x60, 0x7b, 0xd6, 0x4b, 0x58, 0x39, 0x6e, + 0x44, 0x3f, 0xad, 0x2c, 0xfc, 0x36, 0xdd, 0xd3, 0xae, 0x9a, 0xa4, 0xbe, 0xa8, 0x7a, + 0xde, 0xd5, 0xec, 0x35, 0x17, 0x42, 0xfc, 0x5a, 0x90, 0x6a, 0xd0, 0x54, 0xd3, 0x59, + 0x43, 0x16, 0xcc, 0x54, 0xb8, 0x74, 0xbb, 0xce, 0xc2, 0xa8, 0x14, 0x31, 0x50, 0x18, + 0xbc, 0x7e, 0x1d, 0x3c, 0x74, 0x84, 0x72, 0xbd, 0x96, 0x77, 0x76, 0x5d, 0xcf, 0x59, + 0xb1, 0x6d, 0x55, 0xa3, 0xf1, 0x86, 0x4f, 0x75, 0x1a, 0x69, 0x3d, 0x76, 0x9c, 0xc7, + 0x6b, 0x8e, 0x32, 0x8a, 0x9a, 0xc8, 0x3b, 0xe1, 0x78, 0x39, 0x1b, 0xeb, 0x5f, 0x28, + 0xab, 0x69, 0x2b, 0x6f, 0x02, 0xa3, 0xf7, 0x49, 0x8a, 0x4b, 0xc5, 0x51, 0xf8, 0x48, + 0x7d, 0xae, 0xba, 0x3b, 0xe0, 0x2e, 0xb0, 0x20, 0xc1, 0x60, 0xf8, 0x78, 0x53, 0x91, + 0xaa, 0x03, 0xde, 0x44, 0x7b, 0x37, 0xf9, 0x5b, 0xec, 0xfe, 0x3e, 0xca, 0x95, 0xae, + 0x62, 0xab, 0xa0, 0x82, 0x20, 0xee, 0x87, 0xd2, 0x48, 0x16, 0xb0, 0x99, 0x5f, 0x27, + 0x30, 0xe8, 0xff, 0x9a, 0xca, 0x21, 0x8b, 0x88, 0xe3, 0x1b, 0x1f, 0xb7, 0x78, 0x3a, + 0x29, 0x80, 0xf7, 0xb2, 0x98, 0x44, 0xc1, 0x06, 0x26, 0xa2, 0x13, 0xa9, 0x81, 0x41, + 0x7d, 0x90, 0xdf, 0xf9, 0xfb, 0x2a, 0xba, 0xfe, 0xc8, 0x38, 0x23, 0x0e, 0x1a, 0x55, + 0xcf, 0xc5, 0xf7, 0xf8, 0x19, 0xab, 0xf6, 0xe5, 0xb0, 0xa7, 0x48, 0x3b, 0xf1, 0xbc, + 0xeb, 0x15, 0xe8, 0x5b, 0xfe, 0x12, 0xfd, 0x55, 0x02, 0x81, 0xe5, 0x28, 0x20, 0xd0, + 0xbd, 0xb2, 0xa5, 0xba, 0x34, 0xe3, 0x74, 0xca, 0x2f, 0xfd, 0xac, 0x56, 0xce, 0x51, + 0x3c, 0xf3, 0xdd, 0x23, 0xde, 0x9f, 0xb4, 0xa1, 0xd2, 0xff, 0x4f, 0xfe, 0x74, 0x9b, + 0xd8, 0xcb, 0x30, 0x8f, 0x9a, 0xf7, 0xb6, 0xfe, 0xa2, 0x39, + ], + ock: [ + 0xb3, 0x25, 0xeb, 0xe5, 0x7a, 0x2c, 0x40, 0xa8, 0xb2, 0x11, 0xcf, 0xdf, 0x72, 0xa1, + 0xa2, 0x44, 0xf1, 0x53, 0x42, 0x85, 0x98, 0x88, 0xa3, 0x64, 0x52, 0x3e, 0xfd, 0x2a, + 0xc6, 0x6a, 0x1a, 0xd6, + ], + op: [ + 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, + 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, + 0x49, 0x50, 0x69, 0x2c, 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, + 0x8b, 0xfe, 0x9b, 0x38, 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, + 0x8e, 0x33, 0x35, 0x4f, 0xff, 0xf1, 0xbd, 0x1a, + ], + c_out: [ + 0x55, 0xb8, 0x90, 0x7c, 0x6d, 0x45, 0x4b, 0x83, 0x63, 0x4f, 0x1b, 0x9a, 0x1a, 0xa3, + 0xc3, 0xc9, 0x8a, 0xdc, 0x77, 0xd9, 0x6c, 0x2f, 0x62, 0x49, 0xec, 0x66, 0xdb, 0xae, + 0x4d, 0x0c, 0xc9, 0x40, 0xd7, 0x26, 0xbc, 0xd1, 0xec, 0x91, 0x18, 0x9f, 0xd3, 0x04, + 0x9a, 0x33, 0xf2, 0xea, 0x7d, 0x8b, 0x74, 0xaa, 0xc1, 0x7c, 0xda, 0x38, 0x83, 0x80, + 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, + 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xfd, 0x9e, 0x9a, 0x1f, 0x38, 0x1c, 0xbe, 0x75, 0xcd, 0x8d, 0x6a, 0xe1, 0x2f, 0xca, + 0x87, 0x2e, 0x94, 0x00, 0xf0, 0x02, 0x72, 0xb0, 0x29, 0x65, 0x2e, 0x65, 0x6c, 0x8f, + 0x3c, 0x4b, 0xf0, 0x37, 0xee, 0xef, 0x96, 0x42, 0x1b, 0x2f, 0xab, 0x2f, 0xb3, 0xad, + 0x1e, 0x0a, 0xd8, 0x50, 0x2d, 0x74, 0xe6, 0xf0, 0x8f, 0x0d, 0xd5, 0x18, 0xf8, 0xfa, + 0x82, 0x2a, 0x65, 0xbe, 0x27, 0x40, 0xc0, 0x21, + ], + ovk: [ + 0xe7, 0x30, 0x81, 0xef, 0x8d, 0x62, 0xcb, 0x78, 0x0a, 0xb6, 0x88, 0x3a, 0x50, 0xa0, + 0xd4, 0x70, 0x19, 0x0d, 0xfb, 0xa1, 0x0a, 0x85, 0x7f, 0x82, 0x84, 0x2d, 0x38, 0x25, + 0xb3, 0xd6, 0xda, 0x05, + ], + default_d: [ + 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, + ], + default_pk_d: [ + 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, + 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, + 0x4a, 0xd7, 0xc7, 0x84, + ], + v: 9072946746592546880, + rseed: [ + 0xae, 0xab, 0x01, 0x6b, 0x6b, 0xc1, 0xec, 0x14, 0x4b, 0x4e, 0x55, 0x3a, 0xcf, 0xd6, + 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, 0x06, 0x77, 0xe3, 0x1b, 0xa4, 0x59, 0xb4, + 0x4e, 0x30, 0x77, 0x68, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x95, 0x8f, 0xe3, 0x78, 0x9d, 0x41, 0xc2, 0xb1, 0xff, 0x43, 0x4c, 0xb3, 0x0e, + 0x15, 0x91, 0x4f, 0x01, 0xbc, 0x6b, 0xc2, 0x30, 0x7b, 0x48, 0x8d, 0x25, 0x56, 0xd7, + 0xb7, 0x38, 0x0e, 0xa4, 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, + 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, + 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, + 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, 0x0d, 0x02, 0xe0, 0xf0, + 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, 0x29, 0x6e, 0xfa, 0xa7, + 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, + 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, + 0x84, 0x1e, 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, 0x90, 0x5a, 0xae, 0x08, 0x03, 0xfd, + 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, 0x92, 0xee, + 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, 0x64, 0x0a, + 0x69, 0x30, 0x1a, 0x52, 0xa3, 0x8d, 0x4d, 0x9f, 0x9f, 0x95, 0x7a, 0xe3, 0x5a, 0xf7, + 0x16, 0x71, 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, + 0x15, 0x81, 0xa1, 0x55, 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, 0x2e, 0x65, 0x0b, 0x38, + 0x6a, 0xd3, 0xa0, 0x8c, 0xb6, 0xb8, 0x31, 0x31, 0xac, 0x30, 0x0b, 0x08, 0x46, 0x35, + 0x4a, 0x7e, 0xef, 0x9c, 0x41, 0x0e, 0x4b, 0x62, 0xc4, 0x7c, 0x54, 0x26, 0x90, 0x7d, + 0xfc, 0x66, 0x85, 0xc5, 0xc9, 0x9b, 0x71, 0x41, 0xac, 0x62, 0x6a, 0xb4, 0x76, 0x1f, + 0xd3, 0xf4, 0x1e, 0x72, 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, + 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, 0x99, 0xc7, + 0x1f, 0x18, 0x93, 0x41, 0xac, 0x9b, 0x78, 0xa2, 0x69, 0x16, 0x42, 0x06, 0xa0, 0xea, + 0x1c, 0xe7, 0x3b, 0xfb, 0x2a, 0x94, 0x2e, 0x73, 0x70, 0xb2, 0x47, 0xc0, 0x46, 0xf8, + 0xe7, 0x5e, 0xf8, 0xe3, 0xf8, 0xbd, 0x82, 0x1c, 0xf5, 0x77, 0x49, 0x18, 0x64, 0xe2, + 0x0e, 0x6d, 0x08, 0xfd, 0x2e, 0x32, 0xb5, 0x55, 0xc9, 0x2c, 0x66, 0x1f, 0x19, 0x58, + 0x8b, 0x72, 0xa8, 0x95, 0x99, 0x71, 0x0a, 0x88, 0x06, 0x12, 0x53, 0xca, 0x28, 0x5b, + 0x63, 0x04, 0xb3, 0x7d, 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, 0x54, 0xa8, 0x94, 0x32, + 0x28, 0x48, 0xcc, 0xbd, 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, 0x68, 0xaf, 0xac, 0x87, + 0xff, 0xa0, 0x05, 0xc3, 0x12, 0x24, 0x1c, 0x2d, 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, + 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, + 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, 0xcd, 0xdb, 0x41, 0x87, 0x2c, 0xfc, + 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, 0x3d, 0xbf, 0xf9, 0x30, + 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, 0x33, 0x92, + 0xde, 0xb8, 0x7c, 0x53, 0x04, 0x35, 0x31, 0x2e, 0xdc, 0xed, 0xc6, 0xa9, 0x61, 0x13, + 0x33, 0x38, 0xd7, 0x86, 0xc4, 0xa3, 0xe1, 0x03, 0xf6, 0x01, 0x10, 0xa1, 0x6b, 0x13, + 0x37, 0x12, 0x97, 0x04, 0xbf, 0x47, 0x54, 0xff, 0x6b, 0xa9, 0xfb, 0xe6, 0x59, 0x51, + 0xe6, 0x10, 0x62, 0x0f, 0x71, 0xcd, 0xa8, 0xfc, 0x87, 0x76, 0x25, 0xf2, 0xc5, 0xbb, + 0x04, 0xcb, 0xe1, 0x22, 0x8b, 0x1e, 0x88, 0x6f, + ], + cv_net: [ + 0x15, 0x49, 0x70, 0x7e, 0x1e, 0xd2, 0xb2, 0xeb, 0x66, 0x15, 0x65, 0x0b, 0xec, 0x45, + 0xa2, 0x17, 0x64, 0x10, 0x4a, 0x23, 0xea, 0xf6, 0xba, 0x49, 0x6c, 0xb9, 0xb8, 0xe8, + 0x25, 0x7a, 0xd8, 0xb3, + ], + rho: [ + 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, + 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, + 0x4d, 0xb2, 0xc7, 0x31, + ], + cmx: [ + 0x59, 0xb6, 0xf3, 0xd4, 0x03, 0x22, 0x3d, 0x6c, 0xe4, 0x3d, 0xed, 0xae, 0xe2, 0x35, + 0xfc, 0xa9, 0x5c, 0xc8, 0xb2, 0x49, 0x94, 0x1c, 0xcd, 0xb6, 0x6f, 0x3f, 0x61, 0x1c, + 0xc5, 0xe9, 0xf9, 0x0f, + ], + esk: [ + 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, 0xdd, 0x73, 0x4d, 0x0e, + 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, 0x22, 0xc0, 0x61, 0xe0, + 0xbd, 0xc9, 0xce, 0x14, + ], + ephemeral_key: [ + 0xd2, 0x9e, 0x0d, 0x00, 0x1e, 0xe7, 0x1e, 0x05, 0x99, 0x08, 0x65, 0x04, 0xd8, 0x62, + 0xc7, 0xf5, 0x2b, 0x08, 0x60, 0x77, 0x0d, 0x8a, 0x4b, 0x42, 0xa8, 0x68, 0x11, 0xac, + 0x31, 0x69, 0x85, 0x8c, + ], + shared_secret: [ + 0x11, 0xa0, 0xac, 0x79, 0x9a, 0x29, 0xb0, 0xed, 0x19, 0x5e, 0xd8, 0x7b, 0x13, 0x83, + 0x22, 0x26, 0x3b, 0xbb, 0x9c, 0x31, 0x00, 0x8c, 0x29, 0x59, 0xaf, 0x2f, 0xc6, 0x36, + 0x68, 0x7e, 0xd9, 0xb0, + ], + k_enc: [ + 0x4b, 0xbf, 0x80, 0xe7, 0xa1, 0x70, 0x3a, 0xc1, 0x4a, 0xd7, 0xb5, 0x44, 0x8a, 0x2e, + 0x8e, 0x79, 0x49, 0x30, 0x49, 0xd1, 0x9a, 0x6a, 0x51, 0x31, 0x67, 0xd5, 0x5b, 0xdd, + 0x58, 0x6a, 0xc0, 0xd9, + ], + p_enc: [ + 0x03, 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, 0x40, 0x50, + 0xaf, 0xd8, 0xfe, 0x94, 0xe9, 0x7d, 0xae, 0xab, 0x01, 0x6b, 0x6b, 0xc1, 0xec, 0x14, + 0x4b, 0x4e, 0x55, 0x3a, 0xcf, 0xd6, 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, 0x06, + 0x77, 0xe3, 0x1b, 0xa4, 0x59, 0xb4, 0x4e, 0x30, 0x77, 0x68, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x95, 0x8f, 0xe3, 0x78, 0x9d, 0x41, 0xc2, 0xb1, 0xff, 0x43, 0x4c, 0xb3, 0x0e, + 0x15, 0x91, 0x4f, 0x01, 0xbc, 0x6b, 0xc2, 0x30, 0x7b, 0x48, 0x8d, 0x25, 0x56, 0xd7, + 0xb7, 0x38, 0x0e, 0xa4, 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, + 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, + 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, + 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, 0x0d, 0x02, 0xe0, 0xf0, + 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, 0x29, 0x6e, 0xfa, 0xa7, + 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, + 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, + 0x84, 0x1e, 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, 0x90, 0x5a, 0xae, 0x08, 0x03, 0xfd, + 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, 0x92, 0xee, + 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, 0x64, 0x0a, + 0x69, 0x30, 0x1a, 0x52, 0xa3, 0x8d, 0x4d, 0x9f, 0x9f, 0x95, 0x7a, 0xe3, 0x5a, 0xf7, + 0x16, 0x71, 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, + 0x15, 0x81, 0xa1, 0x55, 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, 0x2e, 0x65, 0x0b, 0x38, + 0x6a, 0xd3, 0xa0, 0x8c, 0xb6, 0xb8, 0x31, 0x31, 0xac, 0x30, 0x0b, 0x08, 0x46, 0x35, + 0x4a, 0x7e, 0xef, 0x9c, 0x41, 0x0e, 0x4b, 0x62, 0xc4, 0x7c, 0x54, 0x26, 0x90, 0x7d, + 0xfc, 0x66, 0x85, 0xc5, 0xc9, 0x9b, 0x71, 0x41, 0xac, 0x62, 0x6a, 0xb4, 0x76, 0x1f, + 0xd3, 0xf4, 0x1e, 0x72, 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, + 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, 0x99, 0xc7, + 0x1f, 0x18, 0x93, 0x41, 0xac, 0x9b, 0x78, 0xa2, 0x69, 0x16, 0x42, 0x06, 0xa0, 0xea, + 0x1c, 0xe7, 0x3b, 0xfb, 0x2a, 0x94, 0x2e, 0x73, 0x70, 0xb2, 0x47, 0xc0, 0x46, 0xf8, + 0xe7, 0x5e, 0xf8, 0xe3, 0xf8, 0xbd, 0x82, 0x1c, 0xf5, 0x77, 0x49, 0x18, 0x64, 0xe2, + 0x0e, 0x6d, 0x08, 0xfd, 0x2e, 0x32, 0xb5, 0x55, 0xc9, 0x2c, 0x66, 0x1f, 0x19, 0x58, + 0x8b, 0x72, 0xa8, 0x95, 0x99, 0x71, 0x0a, 0x88, 0x06, 0x12, 0x53, 0xca, 0x28, 0x5b, + 0x63, 0x04, 0xb3, 0x7d, 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, 0x54, 0xa8, 0x94, 0x32, + 0x28, 0x48, 0xcc, 0xbd, 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, 0x68, 0xaf, 0xac, 0x87, + 0xff, 0xa0, 0x05, 0xc3, 0x12, 0x24, 0x1c, 0x2d, 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, + 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, + 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, 0xcd, 0xdb, 0x41, 0x87, 0x2c, 0xfc, + 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, 0x3d, 0xbf, 0xf9, 0x30, + 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, 0x33, 0x92, + 0xde, 0xb8, 0x7c, 0x53, 0x04, 0x35, 0x31, 0x2e, 0xdc, 0xed, 0xc6, 0xa9, 0x61, 0x13, + 0x33, 0x38, 0xd7, 0x86, 0xc4, 0xa3, 0xe1, 0x03, 0xf6, 0x01, 0x10, 0xa1, 0x6b, 0x13, + 0x37, 0x12, 0x97, 0x04, 0xbf, 0x47, 0x54, 0xff, 0x6b, 0xa9, 0xfb, 0xe6, 0x59, 0x51, + 0xe6, 0x10, 0x62, 0x0f, 0x71, 0xcd, 0xa8, 0xfc, 0x87, 0x76, 0x25, 0xf2, 0xc5, 0xbb, + 0x04, 0xcb, 0xe1, 0x22, 0x8b, 0x1e, 0x88, 0x6f, + ], + c_enc: [ + 0x1a, 0x42, 0x34, 0x80, 0xbf, 0x37, 0x67, 0xf5, 0xeb, 0xfc, 0x40, 0xb8, 0xc8, 0x9c, + 0xc5, 0x34, 0xf1, 0x65, 0xc3, 0x5d, 0x19, 0xc8, 0xda, 0x6c, 0x32, 0x10, 0xe9, 0x52, + 0xca, 0xd8, 0x23, 0xa7, 0x84, 0x60, 0x21, 0xc3, 0xde, 0x4a, 0x86, 0x93, 0xb7, 0x1e, + 0x28, 0x7f, 0x46, 0x86, 0xac, 0x0a, 0xdd, 0xce, 0xd9, 0x4e, 0x22, 0x57, 0x7c, 0x40, + 0x9d, 0xa2, 0xdc, 0xa2, 0xef, 0xc2, 0xb3, 0xf8, 0x86, 0x97, 0xf5, 0xed, 0x20, 0x5a, + 0xb2, 0xf9, 0xea, 0x29, 0x85, 0xdd, 0x8b, 0x91, 0xb3, 0x2c, 0x1d, 0x7a, 0x8d, 0xa3, + 0xe8, 0x60, 0x57, 0xe8, 0x70, 0x8c, 0x7e, 0xb1, 0x32, 0x32, 0xaf, 0x56, 0x5d, 0xa5, + 0xa3, 0x5d, 0xe5, 0x06, 0x26, 0x29, 0x6a, 0xa6, 0x07, 0x1a, 0xa0, 0x0a, 0x2c, 0xf2, + 0x47, 0x3f, 0xa8, 0x0b, 0xfd, 0xbb, 0x95, 0x89, 0x48, 0x2a, 0x83, 0x5d, 0x56, 0xd2, + 0x27, 0xe6, 0x29, 0xe3, 0x5b, 0x2f, 0xb0, 0xf3, 0xdd, 0x38, 0xf1, 0x3b, 0xaa, 0x24, + 0xe5, 0x88, 0x26, 0x66, 0x25, 0x31, 0x07, 0x6a, 0xab, 0x9f, 0x4e, 0x3d, 0xe2, 0xc0, + 0xd0, 0x03, 0xe8, 0xd1, 0x0a, 0x8a, 0x70, 0x64, 0x3f, 0xe2, 0x4b, 0x1e, 0x4a, 0x2b, + 0x6d, 0x42, 0x74, 0xbc, 0xc5, 0xfc, 0xe0, 0x49, 0x3a, 0xec, 0x37, 0xe3, 0x24, 0xe9, + 0xb5, 0x13, 0x47, 0xe3, 0x20, 0xa8, 0xa0, 0x0d, 0xd6, 0xd6, 0xcd, 0x3a, 0x46, 0x70, + 0x4b, 0x90, 0xaf, 0x0d, 0x30, 0xe1, 0xda, 0x33, 0x7a, 0x2a, 0x82, 0x98, 0x26, 0xce, + 0x70, 0xf4, 0xf8, 0xa7, 0xcd, 0x31, 0x37, 0x59, 0x42, 0xda, 0x53, 0x4b, 0x68, 0x8b, + 0xf0, 0xbe, 0x8b, 0x6b, 0x90, 0x52, 0x6b, 0x18, 0x1d, 0x9f, 0x07, 0x2f, 0x60, 0x83, + 0x42, 0xb2, 0x4c, 0x89, 0xda, 0xd7, 0xf7, 0xf3, 0x07, 0x9f, 0xe9, 0x9b, 0x6c, 0xfc, + 0x73, 0x38, 0xc2, 0x86, 0x94, 0x2c, 0xab, 0x60, 0x72, 0x95, 0x3f, 0x08, 0x6d, 0x59, + 0xa1, 0xd6, 0x60, 0x00, 0xa4, 0xea, 0x6a, 0xe6, 0x3f, 0xbb, 0xfc, 0x5d, 0xc7, 0x6e, + 0x23, 0x14, 0x29, 0x88, 0x72, 0x5d, 0xea, 0x47, 0x43, 0x52, 0x2b, 0x92, 0x2c, 0xeb, + 0x89, 0xf1, 0x94, 0x8c, 0xe9, 0x43, 0xd5, 0x73, 0x66, 0x10, 0x30, 0xfe, 0x0c, 0xec, + 0x60, 0x7b, 0xd2, 0x47, 0xc9, 0xb5, 0x91, 0x84, 0x3d, 0x3e, 0x38, 0xa9, 0x47, 0x29, + 0x29, 0x8e, 0x60, 0x05, 0xdf, 0xd9, 0xf4, 0xf0, 0xf4, 0x86, 0xcb, 0xa7, 0xb6, 0x51, + 0xd5, 0xb9, 0xd3, 0xd7, 0xae, 0x64, 0x48, 0xe3, 0x9d, 0x19, 0xd7, 0x77, 0x41, 0x79, + 0x2d, 0x60, 0x9c, 0x2e, 0xb9, 0x7f, 0xa9, 0xba, 0x6e, 0x0b, 0x33, 0xdf, 0x17, 0xff, + 0x0f, 0x3c, 0x61, 0x16, 0x38, 0x9f, 0x3d, 0xa3, 0xb0, 0xd6, 0x56, 0xb9, 0x15, 0x3e, + 0xb3, 0x3f, 0x1b, 0xb5, 0x03, 0x94, 0xd7, 0x37, 0xb6, 0x78, 0x15, 0x35, 0xe9, 0x2b, + 0xcc, 0x8a, 0x7e, 0x56, 0xe6, 0x08, 0x02, 0x33, 0x3f, 0xea, 0x10, 0xde, 0xb6, 0xc7, + 0x9b, 0x66, 0x3d, 0xdd, 0x92, 0x82, 0x84, 0x91, 0x46, 0x23, 0x3f, 0x07, 0x8a, 0xbb, + 0x6d, 0x38, 0xec, 0x80, 0x7c, 0x45, 0x79, 0x4d, 0xf4, 0xaa, 0xfe, 0xe8, 0xd7, 0x58, + 0xb9, 0xda, 0xb4, 0xf3, 0x9a, 0xbd, 0x9a, 0xce, 0x42, 0xea, 0x39, 0x88, 0x9d, 0x5f, + 0x40, 0x24, 0x12, 0x24, 0xa9, 0xe1, 0x17, 0x1b, 0xad, 0xcf, 0x4c, 0x5a, 0x75, 0x9e, + 0x3b, 0xb9, 0xc7, 0x9e, 0x3d, 0x1c, 0x72, 0xb4, 0xaf, 0x65, 0x81, 0xe0, 0x7b, 0xde, + 0xdf, 0xc1, 0x7f, 0xe6, 0x82, 0x70, 0x79, 0x9c, 0x3b, 0xb0, 0x8b, 0x11, 0xfe, 0xfe, + 0xb1, 0xed, 0xb2, 0xbb, 0xa0, 0xf1, 0x14, 0x6b, 0x54, 0x01, 0x2a, 0xd3, 0x17, 0x57, + 0x10, 0x2c, 0xaa, 0x5d, 0xee, 0x1f, 0xcf, 0x1f, 0x97, 0x13, 0x34, 0x0d, 0xa2, 0x52, + 0xbd, 0x41, 0xed, 0x4a, 0xe2, 0x11, 0xf3, 0x5f, 0x88, 0x99, 0x1e, 0x1f, 0xe3, 0x47, + 0xd7, 0x0f, 0x52, 0xcd, 0x12, 0xd7, 0x36, 0x13, 0xcd, 0x13, 0xcf, 0xb1, 0x2e, 0xb2, + 0x5f, 0x83, 0x2b, 0x34, 0xc8, 0xb6, 0x69, 0x3a, 0x85, 0xb4, 0x00, 0xfc, 0xe3, 0x03, + 0xdc, 0xcb, 0x3f, 0x8d, 0x90, 0xf5, 0xb7, 0x0c, 0x1e, 0x00, 0xd1, 0xb5, 0x41, 0xe0, + 0xe1, 0x37, 0x3c, 0xc0, 0xc4, 0x05, 0x00, 0x72, 0x18, 0x76, 0x90, 0xf1, 0x38, 0xfd, + 0x25, 0x03, 0x27, 0x2a, 0x3f, 0x9e, 0xc5, 0x72, 0x0d, 0xd3, 0xe5, 0xb1, 0xda, 0x59, + 0x51, 0x4d, 0x4c, 0xb5, 0x0b, 0x1a, 0x44, 0x5a, 0x9d, 0x66, + ], + ock: [ + 0xab, 0xd0, 0xc2, 0x46, 0x97, 0xe4, 0x5b, 0x8b, 0xc4, 0x83, 0x0f, 0xb1, 0x46, 0x53, + 0x2e, 0xa0, 0xac, 0x84, 0x55, 0x81, 0xca, 0x35, 0x39, 0xd3, 0x41, 0x24, 0x73, 0x54, + 0x09, 0xd0, 0x15, 0xac, + ], + op: [ + 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, + 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, + 0x4a, 0xd7, 0xc7, 0x84, 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, + 0xdd, 0x73, 0x4d, 0x0e, 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, + 0x22, 0xc0, 0x61, 0xe0, 0xbd, 0xc9, 0xce, 0x14, + ], + c_out: [ + 0xea, 0xdf, 0x7e, 0xeb, 0x10, 0x2d, 0xb1, 0x88, 0x58, 0x54, 0xc2, 0x9e, 0xb7, 0xb0, + 0x5c, 0x7c, 0x96, 0xbb, 0xb8, 0x90, 0x00, 0x2c, 0x4e, 0xd1, 0x14, 0xed, 0x62, 0xf5, + 0xf9, 0xcc, 0xb4, 0x41, 0x6b, 0x5e, 0xdd, 0xd9, 0xad, 0xb5, 0x5c, 0xe9, 0xc7, 0xa0, + 0xd8, 0x44, 0x2b, 0xbc, 0x8a, 0xfa, 0x5c, 0x77, 0xb9, 0x90, 0xad, 0x6d, 0x46, 0x12, + 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, + 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x91, 0xee, 0x20, 0x54, 0x48, 0xc9, 0x8b, 0x69, 0xa3, 0x3e, 0xbf, 0x29, 0x35, 0x09, + 0x5d, 0x79, 0xc2, 0x53, 0x02, 0x9e, 0x5e, 0x5d, 0xc0, 0x2d, 0xf5, 0x8a, 0x10, 0x03, + 0xd1, 0xd8, 0x5c, 0x27, 0xf2, 0xde, 0xf5, 0xb1, 0x10, 0xfd, 0x43, 0xd7, 0x15, 0xe8, + 0xd5, 0x9e, 0xc4, 0xad, 0x0f, 0x41, 0x02, 0x0e, 0xc6, 0x60, 0xcd, 0x97, 0x33, 0xe7, + 0x79, 0xb5, 0x1a, 0x7a, 0xc2, 0xd5, 0xa6, 0x31, + ], + ovk: [ + 0x18, 0x2f, 0x20, 0x7b, 0x31, 0x75, 0x96, 0x1f, 0x64, 0x11, 0xa4, 0x93, 0xbf, 0xfd, + 0x04, 0x8e, 0x7d, 0x0d, 0x87, 0xd8, 0x2f, 0xe6, 0xf9, 0x90, 0xa2, 0xb0, 0xa2, 0x5f, + 0x5a, 0xa0, 0x11, 0x1a, + ], + default_d: [ + 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, + ], + default_pk_d: [ + 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, + 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, + 0x15, 0x37, 0x14, 0x0d, + ], + v: 14400879385556610631, + rseed: [ + 0xd5, 0x07, 0xcd, 0xfe, 0x6f, 0xbd, 0xaa, 0x86, 0x16, 0x3e, 0x9c, 0xf5, 0xde, 0x31, + 0x00, 0xfb, 0xca, 0x7e, 0x8d, 0xa0, 0x47, 0xb0, 0x90, 0xdb, 0x9f, 0x37, 0x95, 0x2f, + 0xbf, 0xee, 0x76, 0xaf, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x61, 0x66, 0x81, 0x90, 0xbd, 0x52, 0xed, 0x49, 0x0e, 0x67, 0x7b, 0x51, 0x5d, + 0x01, 0x43, 0x84, 0xaf, 0x07, 0x21, 0x9c, 0x7c, 0x0e, 0xe7, 0xfc, 0x7b, 0xfc, 0x79, + 0xf3, 0x25, 0x64, 0x4e, 0x4d, 0xf4, 0xc0, 0xd7, 0xdb, 0x08, 0xe9, 0xf0, 0xbd, 0x02, + 0x49, 0x43, 0xc7, 0x05, 0xab, 0xff, 0x89, 0x94, 0xbf, 0xa6, 0x05, 0xcf, 0xbc, 0x7e, + 0xd7, 0x46, 0xa7, 0xd3, 0xf7, 0xc3, 0x7d, 0x9e, 0x8b, 0xdc, 0x43, 0x3b, 0x7d, 0x79, + 0xe0, 0x8a, 0x12, 0xf7, 0x38, 0xa8, 0xf0, 0xdb, 0xdd, 0xfe, 0xf2, 0xf2, 0x65, 0x7e, + 0xf3, 0xe4, 0x7d, 0x1b, 0x0f, 0xd1, 0x1e, 0x6a, 0x13, 0x31, 0x1f, 0xb7, 0x99, 0xc7, + 0x9c, 0x64, 0x1d, 0x9d, 0xa4, 0x3b, 0x33, 0xe7, 0xad, 0x01, 0x2e, 0x28, 0x25, 0x53, + 0x98, 0x78, 0x92, 0x62, 0x27, 0x5f, 0x11, 0x75, 0xbe, 0x84, 0x62, 0xc0, 0x14, 0x91, + 0xc4, 0xd8, 0x42, 0x40, 0x6d, 0x0e, 0xc4, 0x28, 0x2c, 0x95, 0x26, 0x17, 0x4a, 0x09, + 0x87, 0x8f, 0xe8, 0xfd, 0xde, 0x33, 0xa2, 0x96, 0x04, 0xe5, 0xe5, 0xe7, 0xb2, 0xa0, + 0x25, 0xd6, 0x65, 0x0b, 0x97, 0xdb, 0xb5, 0x2b, 0xef, 0xb5, 0x9b, 0x1d, 0x30, 0xa5, + 0x74, 0x33, 0xb0, 0xa3, 0x51, 0x47, 0x44, 0x44, 0x09, 0x9d, 0xaa, 0x37, 0x10, 0x46, + 0x61, 0x32, 0x60, 0xcf, 0x33, 0x54, 0xcf, 0xcd, 0xad, 0xa6, 0x63, 0xec, 0xe8, 0x24, + 0xff, 0xd7, 0xe4, 0x43, 0x93, 0x88, 0x6a, 0x86, 0x16, 0x5d, 0xdd, 0xdf, 0x2b, 0x4c, + 0x41, 0x77, 0x35, 0x54, 0xc8, 0x69, 0x95, 0x26, 0x94, 0x08, 0xb1, 0x1e, 0x67, 0x37, + 0xa4, 0xc4, 0x47, 0x58, 0x6f, 0x69, 0x17, 0x34, 0x46, 0xd8, 0xe4, 0x8b, 0xf8, 0x4c, + 0xbc, 0x00, 0x0a, 0x80, 0x78, 0x99, 0x97, 0x3e, 0xb9, 0x3c, 0x5e, 0x81, 0x9a, 0xad, + 0x66, 0x94, 0x13, 0xf8, 0x38, 0x79, 0x33, 0xad, 0x15, 0x84, 0xaa, 0x35, 0xe4, 0x3f, + 0x4e, 0xcd, 0x1e, 0x2d, 0x04, 0x07, 0xc0, 0xb1, 0xb8, 0x99, 0x20, 0xff, 0xdf, 0xdb, + 0x9b, 0xea, 0x51, 0xac, 0x95, 0xb5, 0x57, 0xaf, 0x71, 0xb8, 0x9f, 0x90, 0x3f, 0x5d, + 0x98, 0x48, 0xf1, 0x4f, 0xcb, 0xeb, 0x18, 0x37, 0x57, 0x0f, 0x54, 0x4d, 0x63, 0x59, + 0xeb, 0x23, 0xfa, 0xf3, 0x8a, 0x08, 0x22, 0xda, 0x36, 0xce, 0x42, 0x6c, 0x4a, 0x2f, + 0xbe, 0xff, 0xeb, 0x0a, 0x8a, 0x2e, 0x29, 0x7a, 0x9d, 0x19, 0xba, 0x15, 0x02, 0x45, + 0x90, 0xe3, 0x32, 0x9d, 0x9f, 0xa9, 0x26, 0x1f, 0x99, 0x38, 0xa4, 0x03, 0x2d, 0xd3, + 0x46, 0x06, 0xc9, 0xcf, 0x9f, 0x3d, 0xd3, 0x3e, 0x57, 0x6f, 0x05, 0xcd, 0x1d, 0xd6, + 0x81, 0x1c, 0x62, 0x98, 0x75, 0x7d, 0x77, 0xd9, 0xe8, 0x10, 0xab, 0xdb, 0x22, 0x6a, + 0xfc, 0xaa, 0x43, 0x46, 0xa6, 0x56, 0x0f, 0x89, 0x32, 0xb3, 0x18, 0x1f, 0xd3, 0x55, + 0xd5, 0xd3, 0x91, 0x97, 0x61, 0x83, 0xf8, 0xd9, 0x93, 0x88, 0x83, 0x96, 0x32, 0xd6, + 0x35, 0x4f, 0x66, 0x6d, 0x09, 0xd3, 0xe5, 0x62, 0x9e, 0xa1, 0x97, 0x37, 0x38, 0x86, + 0x13, 0xd3, 0x8a, 0x34, 0xfd, 0x0f, 0x6e, 0x50, 0xee, 0x5a, 0x0c, 0xc9, 0x67, 0x71, + 0x77, 0xf5, 0x00, 0x28, 0xc1, 0x41, 0x37, 0x81, 0x87, 0xbd, 0x28, 0x19, 0x40, 0x3f, + 0xc5, 0x34, 0xf8, 0x00, 0x76, 0xe9, 0x38, 0x0c, 0xb4, 0x96, 0x4d, 0x3b, 0x6b, 0x45, + 0x81, 0x9d, 0x3b, 0x8e, 0x9c, 0xaf, 0x54, 0xf0, 0x51, 0x85, 0x2d, 0x67, 0x1b, 0xf8, + 0xc1, 0xff, 0xde, 0x2d, 0x15, 0x10, 0x75, 0x64, 0x18, 0xcb, 0x48, 0x10, 0x93, 0x6a, + 0xa5, 0x7e, 0x69, 0x65, 0xd6, 0xfb, 0x65, 0x6a, 0x76, 0x0b, 0x7f, 0x19, 0xad, 0xf9, + 0x6c, 0x17, 0x34, 0x88, 0x55, 0x21, 0x93, 0xb1, + ], + cv_net: [ + 0xc3, 0x94, 0x68, 0x5d, 0x92, 0x95, 0x59, 0x7e, 0x21, 0x55, 0x7f, 0x21, 0x9f, 0x3c, + 0x9d, 0x5e, 0x64, 0x07, 0x19, 0xbc, 0xa5, 0xc8, 0xed, 0x49, 0x99, 0x97, 0x34, 0xe6, + 0xc5, 0xb3, 0x73, 0x3e, + ], + rho: [ + 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, + 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, + 0x25, 0xb9, 0xff, 0x16, + ], + cmx: [ + 0x0b, 0x74, 0x59, 0x61, 0x6f, 0xc6, 0x93, 0x95, 0xe6, 0x44, 0x36, 0xcf, 0x4a, 0xe9, + 0x44, 0x1d, 0x37, 0x4b, 0x29, 0x04, 0x9e, 0x4c, 0x86, 0x22, 0x3a, 0x03, 0x83, 0xf4, + 0xe0, 0x24, 0x69, 0x05, + ], + esk: [ + 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, 0xa1, 0xc4, 0x12, 0xbc, + 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, 0x95, 0x72, 0x92, 0x93, + 0x59, 0xe0, 0x4c, 0x3a, + ], + ephemeral_key: [ + 0x0e, 0x04, 0xd8, 0x52, 0x5d, 0xd6, 0x8f, 0x7a, 0xe8, 0x68, 0xca, 0x81, 0x1e, 0x88, + 0x33, 0xa7, 0xf4, 0x7d, 0x7a, 0xad, 0xd3, 0x76, 0x03, 0xac, 0xe6, 0x07, 0xee, 0x6c, + 0x86, 0x6b, 0xce, 0x23, + ], + shared_secret: [ + 0x4a, 0x7a, 0x54, 0xac, 0x00, 0x41, 0x95, 0x98, 0xb0, 0x76, 0x01, 0x53, 0xe2, 0x6a, + 0xcc, 0xd2, 0x15, 0x05, 0x24, 0x16, 0x65, 0x17, 0x13, 0xee, 0xa1, 0x89, 0x19, 0xf3, + 0xe2, 0x62, 0xd3, 0xb6, + ], + k_enc: [ + 0x30, 0x62, 0x6d, 0x92, 0xeb, 0x62, 0x0f, 0xd4, 0xa9, 0x28, 0xb4, 0x3f, 0xd5, 0x50, + 0x69, 0x74, 0x71, 0x76, 0x7d, 0xe4, 0x49, 0x6c, 0xfd, 0xad, 0xb1, 0xda, 0x18, 0xfc, + 0x0c, 0xdd, 0x5a, 0xa6, + ], + p_enc: [ + 0x03, 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, 0x47, 0xee, + 0x58, 0x85, 0x80, 0x33, 0xda, 0xc7, 0xd5, 0x07, 0xcd, 0xfe, 0x6f, 0xbd, 0xaa, 0x86, + 0x16, 0x3e, 0x9c, 0xf5, 0xde, 0x31, 0x00, 0xfb, 0xca, 0x7e, 0x8d, 0xa0, 0x47, 0xb0, + 0x90, 0xdb, 0x9f, 0x37, 0x95, 0x2f, 0xbf, 0xee, 0x76, 0xaf, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x61, 0x66, 0x81, 0x90, 0xbd, 0x52, 0xed, 0x49, 0x0e, 0x67, 0x7b, 0x51, 0x5d, + 0x01, 0x43, 0x84, 0xaf, 0x07, 0x21, 0x9c, 0x7c, 0x0e, 0xe7, 0xfc, 0x7b, 0xfc, 0x79, + 0xf3, 0x25, 0x64, 0x4e, 0x4d, 0xf4, 0xc0, 0xd7, 0xdb, 0x08, 0xe9, 0xf0, 0xbd, 0x02, + 0x49, 0x43, 0xc7, 0x05, 0xab, 0xff, 0x89, 0x94, 0xbf, 0xa6, 0x05, 0xcf, 0xbc, 0x7e, + 0xd7, 0x46, 0xa7, 0xd3, 0xf7, 0xc3, 0x7d, 0x9e, 0x8b, 0xdc, 0x43, 0x3b, 0x7d, 0x79, + 0xe0, 0x8a, 0x12, 0xf7, 0x38, 0xa8, 0xf0, 0xdb, 0xdd, 0xfe, 0xf2, 0xf2, 0x65, 0x7e, + 0xf3, 0xe4, 0x7d, 0x1b, 0x0f, 0xd1, 0x1e, 0x6a, 0x13, 0x31, 0x1f, 0xb7, 0x99, 0xc7, + 0x9c, 0x64, 0x1d, 0x9d, 0xa4, 0x3b, 0x33, 0xe7, 0xad, 0x01, 0x2e, 0x28, 0x25, 0x53, + 0x98, 0x78, 0x92, 0x62, 0x27, 0x5f, 0x11, 0x75, 0xbe, 0x84, 0x62, 0xc0, 0x14, 0x91, + 0xc4, 0xd8, 0x42, 0x40, 0x6d, 0x0e, 0xc4, 0x28, 0x2c, 0x95, 0x26, 0x17, 0x4a, 0x09, + 0x87, 0x8f, 0xe8, 0xfd, 0xde, 0x33, 0xa2, 0x96, 0x04, 0xe5, 0xe5, 0xe7, 0xb2, 0xa0, + 0x25, 0xd6, 0x65, 0x0b, 0x97, 0xdb, 0xb5, 0x2b, 0xef, 0xb5, 0x9b, 0x1d, 0x30, 0xa5, + 0x74, 0x33, 0xb0, 0xa3, 0x51, 0x47, 0x44, 0x44, 0x09, 0x9d, 0xaa, 0x37, 0x10, 0x46, + 0x61, 0x32, 0x60, 0xcf, 0x33, 0x54, 0xcf, 0xcd, 0xad, 0xa6, 0x63, 0xec, 0xe8, 0x24, + 0xff, 0xd7, 0xe4, 0x43, 0x93, 0x88, 0x6a, 0x86, 0x16, 0x5d, 0xdd, 0xdf, 0x2b, 0x4c, + 0x41, 0x77, 0x35, 0x54, 0xc8, 0x69, 0x95, 0x26, 0x94, 0x08, 0xb1, 0x1e, 0x67, 0x37, + 0xa4, 0xc4, 0x47, 0x58, 0x6f, 0x69, 0x17, 0x34, 0x46, 0xd8, 0xe4, 0x8b, 0xf8, 0x4c, + 0xbc, 0x00, 0x0a, 0x80, 0x78, 0x99, 0x97, 0x3e, 0xb9, 0x3c, 0x5e, 0x81, 0x9a, 0xad, + 0x66, 0x94, 0x13, 0xf8, 0x38, 0x79, 0x33, 0xad, 0x15, 0x84, 0xaa, 0x35, 0xe4, 0x3f, + 0x4e, 0xcd, 0x1e, 0x2d, 0x04, 0x07, 0xc0, 0xb1, 0xb8, 0x99, 0x20, 0xff, 0xdf, 0xdb, + 0x9b, 0xea, 0x51, 0xac, 0x95, 0xb5, 0x57, 0xaf, 0x71, 0xb8, 0x9f, 0x90, 0x3f, 0x5d, + 0x98, 0x48, 0xf1, 0x4f, 0xcb, 0xeb, 0x18, 0x37, 0x57, 0x0f, 0x54, 0x4d, 0x63, 0x59, + 0xeb, 0x23, 0xfa, 0xf3, 0x8a, 0x08, 0x22, 0xda, 0x36, 0xce, 0x42, 0x6c, 0x4a, 0x2f, + 0xbe, 0xff, 0xeb, 0x0a, 0x8a, 0x2e, 0x29, 0x7a, 0x9d, 0x19, 0xba, 0x15, 0x02, 0x45, + 0x90, 0xe3, 0x32, 0x9d, 0x9f, 0xa9, 0x26, 0x1f, 0x99, 0x38, 0xa4, 0x03, 0x2d, 0xd3, + 0x46, 0x06, 0xc9, 0xcf, 0x9f, 0x3d, 0xd3, 0x3e, 0x57, 0x6f, 0x05, 0xcd, 0x1d, 0xd6, + 0x81, 0x1c, 0x62, 0x98, 0x75, 0x7d, 0x77, 0xd9, 0xe8, 0x10, 0xab, 0xdb, 0x22, 0x6a, + 0xfc, 0xaa, 0x43, 0x46, 0xa6, 0x56, 0x0f, 0x89, 0x32, 0xb3, 0x18, 0x1f, 0xd3, 0x55, + 0xd5, 0xd3, 0x91, 0x97, 0x61, 0x83, 0xf8, 0xd9, 0x93, 0x88, 0x83, 0x96, 0x32, 0xd6, + 0x35, 0x4f, 0x66, 0x6d, 0x09, 0xd3, 0xe5, 0x62, 0x9e, 0xa1, 0x97, 0x37, 0x38, 0x86, + 0x13, 0xd3, 0x8a, 0x34, 0xfd, 0x0f, 0x6e, 0x50, 0xee, 0x5a, 0x0c, 0xc9, 0x67, 0x71, + 0x77, 0xf5, 0x00, 0x28, 0xc1, 0x41, 0x37, 0x81, 0x87, 0xbd, 0x28, 0x19, 0x40, 0x3f, + 0xc5, 0x34, 0xf8, 0x00, 0x76, 0xe9, 0x38, 0x0c, 0xb4, 0x96, 0x4d, 0x3b, 0x6b, 0x45, + 0x81, 0x9d, 0x3b, 0x8e, 0x9c, 0xaf, 0x54, 0xf0, 0x51, 0x85, 0x2d, 0x67, 0x1b, 0xf8, + 0xc1, 0xff, 0xde, 0x2d, 0x15, 0x10, 0x75, 0x64, 0x18, 0xcb, 0x48, 0x10, 0x93, 0x6a, + 0xa5, 0x7e, 0x69, 0x65, 0xd6, 0xfb, 0x65, 0x6a, 0x76, 0x0b, 0x7f, 0x19, 0xad, 0xf9, + 0x6c, 0x17, 0x34, 0x88, 0x55, 0x21, 0x93, 0xb1, + ], + c_enc: [ + 0x80, 0x56, 0x2d, 0xbe, 0xf7, 0xbb, 0x35, 0x3a, 0x62, 0xe7, 0xc8, 0x1e, 0xbe, 0x68, + 0x15, 0x6c, 0xb7, 0x5c, 0x5c, 0x7e, 0x3d, 0x96, 0xbb, 0xcd, 0x7d, 0xaf, 0xf5, 0x0c, + 0xb0, 0x95, 0x7d, 0x33, 0xdd, 0x99, 0x77, 0x9f, 0x7d, 0x3d, 0x72, 0xb1, 0x8d, 0xeb, + 0x7a, 0x69, 0x75, 0x10, 0xe0, 0x13, 0x5b, 0x8d, 0xf4, 0x83, 0x3c, 0xf5, 0x82, 0xa1, + 0x4f, 0x08, 0xfc, 0xa9, 0xb3, 0x7a, 0xac, 0x85, 0x1f, 0xf9, 0xf5, 0x80, 0x5c, 0x57, + 0x74, 0x8a, 0x3f, 0xe8, 0x1b, 0x88, 0xc9, 0x8c, 0x96, 0xfd, 0x2a, 0x75, 0xc4, 0xf6, + 0x66, 0xb6, 0x1d, 0x20, 0x74, 0x06, 0x5c, 0xf4, 0x4a, 0x30, 0xa1, 0x98, 0xa2, 0x98, + 0xb7, 0xda, 0x42, 0x7c, 0x18, 0x60, 0x8a, 0x8f, 0x13, 0x83, 0x63, 0xf0, 0x55, 0x40, + 0x42, 0xd3, 0xe3, 0xa7, 0xe3, 0x22, 0x94, 0x51, 0x51, 0xc6, 0x3b, 0xb2, 0x37, 0xb3, + 0x20, 0xbc, 0x78, 0x0a, 0x8f, 0x9e, 0x01, 0xc6, 0x01, 0xf0, 0x34, 0xbc, 0xf0, 0x37, + 0x67, 0xd5, 0xd7, 0x50, 0x40, 0x2a, 0x23, 0x80, 0x0f, 0x46, 0xec, 0x08, 0x78, 0x0a, + 0x8f, 0x78, 0xe9, 0xa2, 0x37, 0xa9, 0xcb, 0x83, 0x06, 0x26, 0x1d, 0x1b, 0xb4, 0xc3, + 0xf6, 0x2e, 0xf4, 0xcb, 0x0f, 0x70, 0x34, 0x65, 0x32, 0x24, 0xfe, 0x77, 0x17, 0x9a, + 0x4d, 0x12, 0x15, 0x9a, 0x87, 0x66, 0xff, 0xc5, 0x9b, 0xee, 0x68, 0xd9, 0x74, 0xd2, + 0x27, 0x73, 0xe5, 0xca, 0x4f, 0x34, 0xf4, 0x62, 0x73, 0xa4, 0x46, 0x33, 0x69, 0xb1, + 0x76, 0xa6, 0x1f, 0x1e, 0x47, 0x8c, 0x2d, 0x3c, 0x4e, 0x42, 0x70, 0x13, 0xe5, 0xd8, + 0x69, 0x75, 0xea, 0x91, 0x93, 0x05, 0x0e, 0x52, 0xa7, 0x02, 0x6f, 0x76, 0x96, 0x4c, + 0xa0, 0x18, 0x15, 0x9b, 0xdc, 0x19, 0x6c, 0x44, 0xca, 0xd2, 0xd2, 0x62, 0x3d, 0x33, + 0x50, 0x7e, 0xf0, 0xfe, 0xc1, 0x0f, 0x9d, 0x80, 0xb2, 0x08, 0xe3, 0xc3, 0x3f, 0x7d, + 0x50, 0x76, 0x41, 0x63, 0xb3, 0xf0, 0x33, 0x29, 0xad, 0x41, 0xeb, 0x5a, 0x4f, 0xb4, + 0xf3, 0xab, 0x8e, 0xef, 0x2d, 0xa5, 0xcb, 0x3a, 0x7c, 0x86, 0x22, 0x16, 0x48, 0x70, + 0xa8, 0x2c, 0x63, 0x5d, 0x23, 0x51, 0x53, 0x9b, 0x97, 0x3c, 0x40, 0xd5, 0x8e, 0x91, + 0x79, 0x43, 0x6b, 0x9c, 0x0b, 0x74, 0xfd, 0x5e, 0xab, 0x81, 0x49, 0x59, 0xd2, 0x80, + 0xea, 0x3f, 0x8e, 0x09, 0xd8, 0x44, 0x2f, 0xea, 0x4a, 0xdc, 0x8c, 0xc9, 0xc2, 0xfe, + 0x50, 0xef, 0xad, 0x2e, 0xe1, 0x9a, 0xb5, 0x85, 0x7a, 0x2d, 0x2f, 0xb1, 0xd1, 0x13, + 0x67, 0x08, 0x22, 0xb9, 0x57, 0x95, 0xa3, 0x4d, 0x20, 0xf7, 0xc6, 0x37, 0xf8, 0xdc, + 0xcf, 0xe7, 0x35, 0x52, 0xfd, 0x34, 0x17, 0x6a, 0xbf, 0x0f, 0x8e, 0x3c, 0xfa, 0x70, + 0xbe, 0xc8, 0x84, 0x4b, 0x87, 0xb1, 0x44, 0xcb, 0x99, 0xb0, 0xb0, 0x9b, 0x47, 0xc6, + 0x62, 0xdd, 0x70, 0x5e, 0x4d, 0x74, 0xc1, 0x5d, 0x47, 0x42, 0x98, 0x33, 0xe7, 0x80, + 0x5d, 0x88, 0x40, 0x46, 0xc0, 0xd9, 0x36, 0xc8, 0x72, 0x32, 0xcd, 0xc9, 0x53, 0xbf, + 0x6e, 0x61, 0x93, 0xb4, 0xcf, 0x67, 0x81, 0x12, 0x8e, 0xbe, 0x7a, 0x51, 0xdb, 0x9b, + 0x36, 0x67, 0x38, 0x08, 0xad, 0x77, 0x18, 0xe2, 0x50, 0xcb, 0x51, 0x15, 0x85, 0xf6, + 0xbc, 0x09, 0x78, 0xbd, 0x17, 0xe4, 0x71, 0x7e, 0xa4, 0x19, 0x3d, 0x09, 0x5d, 0x22, + 0x2b, 0xa1, 0xb2, 0xf9, 0xd8, 0x18, 0x98, 0x1d, 0xf1, 0x72, 0xa4, 0x91, 0xd8, 0x41, + 0xbc, 0x73, 0xec, 0x17, 0x93, 0x41, 0xa2, 0x8f, 0x03, 0x8a, 0xa3, 0xe4, 0xc8, 0x65, + 0x24, 0x11, 0xf1, 0x85, 0xa6, 0x49, 0x92, 0xa6, 0xce, 0xa6, 0xc4, 0x5c, 0x70, 0xe9, + 0xd6, 0x64, 0x69, 0x4b, 0xc9, 0x44, 0x1f, 0x29, 0xc4, 0x81, 0x81, 0x5a, 0x82, 0xb3, + 0xa3, 0x30, 0xc9, 0x6c, 0x05, 0xfc, 0x9c, 0x48, 0x5a, 0xe8, 0xd9, 0x96, 0xb6, 0xf9, + 0xf6, 0x87, 0xf3, 0x90, 0x1f, 0x74, 0x0a, 0xc8, 0x9a, 0xb2, 0x42, 0xf2, 0xaa, 0x0c, + 0xe7, 0xb0, 0xeb, 0x14, 0xb4, 0x2d, 0x65, 0xba, 0xd9, 0xfe, 0x5c, 0xe2, 0x91, 0xa2, + 0x2c, 0xb1, 0xff, 0xdf, 0xdf, 0x27, 0x30, 0xd6, 0x8f, 0x68, 0x2d, 0xe0, 0xf9, 0xf3, + 0xa3, 0x04, 0xf5, 0x0c, 0x4f, 0xfd, 0xf9, 0x58, 0x30, 0x6c, 0x11, 0xa2, 0x91, 0x70, + 0xdd, 0xae, 0x90, 0x65, 0xcc, 0xc9, 0xd4, 0xd2, 0x77, 0x62, 0x6e, 0x78, 0x81, 0x72, + 0x3a, 0xe1, 0x72, 0xff, 0x09, 0xdb, 0x09, 0x38, 0x6f, 0x9e, + ], + ock: [ + 0xb6, 0x36, 0xc3, 0x9a, 0x6b, 0xad, 0x22, 0x63, 0xb2, 0x44, 0x1e, 0xd5, 0xbb, 0xdb, + 0x01, 0x35, 0x88, 0xfb, 0x46, 0x27, 0x01, 0xe6, 0xf8, 0x76, 0x64, 0x6c, 0x8c, 0x17, + 0xfa, 0x2e, 0xfd, 0xe8, + ], + op: [ + 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, + 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, + 0x15, 0x37, 0x14, 0x0d, 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, + 0xa1, 0xc4, 0x12, 0xbc, 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, + 0x95, 0x72, 0x92, 0x93, 0x59, 0xe0, 0x4c, 0x3a, + ], + c_out: [ + 0x46, 0xba, 0x14, 0xf8, 0x3f, 0xf5, 0xab, 0x76, 0x0f, 0x14, 0x20, 0xeb, 0xde, 0xd9, + 0x86, 0xfd, 0x93, 0x78, 0x27, 0xbc, 0x05, 0x69, 0x2e, 0xca, 0xdb, 0x65, 0x2e, 0xbb, + 0xc8, 0xf6, 0xd9, 0xb5, 0x2e, 0xc3, 0x97, 0x87, 0xd8, 0xeb, 0xdd, 0x50, 0x6c, 0xa1, + 0xa8, 0x5d, 0xc3, 0xd5, 0xba, 0x4c, 0x5b, 0x41, 0x52, 0x61, 0xb0, 0x75, 0x3a, 0xc1, + 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, + 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xf1, 0x90, 0x42, 0xb9, 0xd1, 0x0c, 0xc4, 0x80, 0xa0, 0x8c, 0x04, 0x32, 0x2d, 0xb6, + 0xec, 0x4e, 0x41, 0x2e, 0xaa, 0x84, 0xc9, 0x71, 0x82, 0x8c, 0xcc, 0xd7, 0x33, 0xa1, + 0x1f, 0x25, 0x3e, 0xda, 0x8a, 0xc3, 0x0b, 0xa3, 0x1f, 0xbc, 0x89, 0x5d, 0x60, 0xb9, + 0x83, 0x06, 0x2a, 0x5f, 0x45, 0x33, 0x90, 0x79, 0x32, 0x26, 0xff, 0xd9, 0x21, 0xbd, + 0x64, 0xac, 0x39, 0x07, 0x03, 0x85, 0x6a, 0x0b, + ], + ovk: [ + 0xda, 0xdc, 0x96, 0x6c, 0x8a, 0x54, 0x66, 0xb6, 0x1f, 0xc9, 0x98, 0xc3, 0x1f, 0x10, + 0x70, 0xd9, 0xa5, 0xc9, 0xa6, 0xd2, 0x68, 0xd3, 0x04, 0xfe, 0x6b, 0x8f, 0xd3, 0xb4, + 0x01, 0x03, 0x48, 0x61, + ], + default_d: [ + 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, + ], + default_pk_d: [ + 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, + 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, + 0x14, 0x93, 0x16, 0x36, + ], + v: 17936016275122962426, + rseed: [ + 0x49, 0x95, 0x0a, 0xfc, 0xb0, 0xef, 0x46, 0x2a, 0x2a, 0xe0, 0x24, 0xb0, 0xf0, 0x22, + 0x4d, 0xfd, 0x73, 0x68, 0x4b, 0x88, 0xc7, 0xfb, 0xe9, 0x2d, 0x02, 0xb6, 0x8f, 0x75, + 0x9c, 0x47, 0x52, 0x66, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x3c, 0xd7, 0xb9, 0x7a, 0x14, 0x94, 0x36, 0x49, 0x30, 0x55, 0x21, 0x32, 0x6b, + 0xde, 0x08, 0x56, 0x30, 0x86, 0x46, 0x29, 0x29, 0x1b, 0xae, 0x25, 0xff, 0x88, 0x22, + 0xa1, 0x4c, 0x4b, 0x66, 0x6a, 0x92, 0x59, 0xad, 0x0d, 0xc4, 0x2a, 0x82, 0x90, 0xac, + 0x7b, 0xc7, 0xf5, 0x3a, 0x16, 0xf3, 0x79, 0xf7, 0x58, 0xe5, 0xde, 0x75, 0x0f, 0x04, + 0xfd, 0x7c, 0xad, 0x47, 0x70, 0x1c, 0x85, 0x97, 0xf9, 0x78, 0x88, 0xbe, 0xa6, 0xfa, + 0x0b, 0xf2, 0x99, 0x99, 0x56, 0xfb, 0xfd, 0x0e, 0xe6, 0x8e, 0xc3, 0x6e, 0x46, 0x88, + 0x80, 0x9a, 0xe2, 0x31, 0xeb, 0x8b, 0xc4, 0x36, 0x9f, 0x5f, 0xe1, 0x57, 0x3f, 0x57, + 0xe0, 0x99, 0xd9, 0xc0, 0x99, 0x01, 0xbf, 0x39, 0xca, 0xac, 0x48, 0xdc, 0x11, 0x95, + 0x6a, 0x8a, 0xe9, 0x05, 0xea, 0xd8, 0x69, 0x54, 0x54, 0x7c, 0x44, 0x8a, 0xe4, 0x3d, + 0x31, 0x5e, 0x66, 0x9c, 0x42, 0x42, 0xda, 0x56, 0x59, 0x38, 0xf4, 0x17, 0xbf, 0x43, + 0xce, 0x7b, 0x2b, 0x30, 0xb1, 0xcd, 0x40, 0x18, 0x38, 0x8e, 0x1a, 0x91, 0x0f, 0x0f, + 0xc4, 0x1f, 0xb0, 0x87, 0x7a, 0x59, 0x25, 0xe4, 0x66, 0x81, 0x9d, 0x37, 0x5b, 0x0a, + 0x91, 0x2d, 0x4f, 0xe8, 0x43, 0xb7, 0x6e, 0xf6, 0xf2, 0x23, 0xf0, 0xf7, 0xc8, 0x94, + 0xf3, 0x8f, 0x7a, 0xb7, 0x80, 0xdf, 0xd7, 0x5f, 0x66, 0x9c, 0x8c, 0x06, 0xcf, 0xfa, + 0x43, 0xeb, 0x47, 0x56, 0x5a, 0x50, 0xe3, 0xb1, 0xfa, 0x45, 0xad, 0x61, 0xce, 0x9a, + 0x1c, 0x47, 0x27, 0xb7, 0xaa, 0xa5, 0x35, 0x62, 0xf5, 0x23, 0xe7, 0x39, 0x52, 0xbb, + 0xf3, 0x3d, 0x8a, 0x41, 0x04, 0x07, 0x8a, 0xde, 0x3e, 0xaa, 0xa4, 0x96, 0x99, 0xa6, + 0x9f, 0xdf, 0x1c, 0x5a, 0xc7, 0x73, 0x21, 0x46, 0xee, 0x5e, 0x1d, 0x6b, 0x6c, 0xa9, + 0xb9, 0x18, 0x0f, 0x96, 0x4c, 0xc9, 0xd0, 0x87, 0x8a, 0xe1, 0x37, 0x35, 0x24, 0xd7, + 0xd5, 0x10, 0xe5, 0x82, 0x27, 0xdf, 0x6d, 0xe9, 0xd3, 0x0d, 0x27, 0x18, 0x67, 0x64, + 0x01, 0x77, 0xb0, 0xf1, 0x85, 0x6e, 0x28, 0xd5, 0xc8, 0xaf, 0xb0, 0x95, 0xef, 0x61, + 0x84, 0xfe, 0xd6, 0x51, 0x58, 0x90, 0x22, 0xee, 0xae, 0xa4, 0xc0, 0xce, 0x1f, 0xa6, + 0xf0, 0x85, 0x09, 0x2b, 0x04, 0x97, 0x94, 0x89, 0x17, 0x2b, 0x3e, 0xf8, 0x19, 0x4a, + 0x79, 0x8d, 0xf5, 0x72, 0x4d, 0x6b, 0x05, 0xf1, 0xae, 0x00, 0x00, 0x13, 0xa0, 0x8d, + 0x61, 0x2b, 0xca, 0x8a, 0x8c, 0x31, 0x44, 0x3c, 0x10, 0x34, 0x6d, 0xbf, 0x61, 0xde, + 0x84, 0x75, 0xc0, 0xbb, 0xec, 0x51, 0x04, 0xb4, 0x75, 0x56, 0xaf, 0x3d, 0x51, 0x44, + 0x58, 0xe2, 0x32, 0x1d, 0x14, 0x60, 0x71, 0x78, 0x9d, 0x23, 0x35, 0x93, 0x4a, 0x68, + 0x06, 0x14, 0xe8, 0x35, 0x62, 0xf8, 0x2d, 0xfd, 0x40, 0x5b, 0x54, 0xa4, 0x5e, 0xb3, + 0x2c, 0x16, 0x54, 0x48, 0xd4, 0xd5, 0xd6, 0x1c, 0xa2, 0x85, 0x95, 0x85, 0x36, 0x9f, + 0x53, 0xf1, 0xa1, 0x37, 0xe9, 0xe8, 0x2b, 0x67, 0xb8, 0xfd, 0xaf, 0x01, 0xbd, 0xa5, + 0x4a, 0x31, 0x73, 0x11, 0x89, 0x6a, 0xe1, 0x02, 0x80, 0xa0, 0x32, 0x44, 0x0c, 0x42, + 0x0a, 0x42, 0x1e, 0x94, 0x4d, 0x1e, 0x95, 0x2b, 0x70, 0xd5, 0x82, 0x6c, 0xd3, 0xb0, + 0x8b, 0x7d, 0xb9, 0x63, 0x0f, 0xe4, 0xfd, 0x5f, 0x22, 0x12, 0x5d, 0xe8, 0x40, 0xfc, + 0xc4, 0x0b, 0x98, 0x03, 0x8a, 0xf1, 0x1d, 0x55, 0xbe, 0x25, 0x43, 0x25, 0x97, 0xb4, + 0xb6, 0x5b, 0x9e, 0xc1, 0xc7, 0xa8, 0xbb, 0xfd, 0x05, 0x2c, 0xbf, 0x7e, 0x1c, 0x17, + 0x85, 0x31, 0x49, 0x34, 0xb2, 0x62, 0xd5, 0x85, 0x37, 0x54, 0xf1, 0xf1, 0x77, 0x71, + 0xcf, 0xb7, 0x50, 0x30, 0x72, 0x65, 0x57, 0x53, + ], + cv_net: [ + 0xd4, 0x51, 0xb4, 0x62, 0x89, 0xba, 0x99, 0x8c, 0x0c, 0xce, 0xd1, 0xcc, 0x15, 0xb3, + 0xfa, 0xde, 0x94, 0xfa, 0x0b, 0x46, 0xe3, 0xb1, 0xa5, 0x73, 0x34, 0x99, 0x34, 0xe2, + 0x32, 0xb5, 0x0e, 0x96, + ], + rho: [ + 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, + 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, + 0xf5, 0x0e, 0x92, 0x37, + ], + cmx: [ + 0x05, 0xb5, 0xe3, 0x20, 0x76, 0xda, 0xe0, 0x94, 0x83, 0x35, 0xac, 0x3d, 0x65, 0x1c, + 0x6d, 0xbe, 0xa6, 0x4c, 0xe9, 0x11, 0x42, 0x3e, 0x2f, 0x2c, 0x7c, 0x1b, 0xdf, 0xa6, + 0xb1, 0x41, 0x41, 0x30, + ], + esk: [ + 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, 0xfe, 0x47, 0x9a, 0x1e, + 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, 0x92, 0x3a, 0x5d, 0x00, + 0xcb, 0x52, 0xa6, 0x13, + ], + ephemeral_key: [ + 0x86, 0xee, 0x66, 0xa6, 0xc7, 0xd9, 0xb5, 0xc4, 0xf0, 0xe2, 0xd2, 0xa0, 0xe1, 0x56, + 0x1e, 0x2a, 0xfa, 0x55, 0x41, 0xa7, 0x24, 0xee, 0x02, 0x7f, 0xc7, 0x0b, 0xb7, 0xe8, + 0x0a, 0x2c, 0x60, 0x98, + ], + shared_secret: [ + 0x88, 0xd1, 0x38, 0x2c, 0x14, 0x42, 0x02, 0xd0, 0xd7, 0x55, 0x75, 0x87, 0xb0, 0xd5, + 0xd0, 0x21, 0x69, 0x29, 0x2a, 0x25, 0x05, 0x43, 0xcb, 0x0a, 0x06, 0xc3, 0x4f, 0x45, + 0x2f, 0x7b, 0x3b, 0x36, + ], + k_enc: [ + 0xe3, 0x73, 0xd8, 0x6e, 0xc9, 0xdd, 0xdd, 0x64, 0x5d, 0x9a, 0x6d, 0x06, 0xef, 0xce, + 0x22, 0xb8, 0x96, 0x42, 0x1d, 0x57, 0xa4, 0x4d, 0x37, 0xa6, 0x50, 0x4a, 0x5d, 0x19, + 0xdf, 0x21, 0x73, 0x73, + ], + p_enc: [ + 0x03, 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, 0xfa, 0x3f, + 0x54, 0xec, 0xc5, 0x87, 0xe9, 0xf8, 0x49, 0x95, 0x0a, 0xfc, 0xb0, 0xef, 0x46, 0x2a, + 0x2a, 0xe0, 0x24, 0xb0, 0xf0, 0x22, 0x4d, 0xfd, 0x73, 0x68, 0x4b, 0x88, 0xc7, 0xfb, + 0xe9, 0x2d, 0x02, 0xb6, 0x8f, 0x75, 0x9c, 0x47, 0x52, 0x66, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x3c, 0xd7, 0xb9, 0x7a, 0x14, 0x94, 0x36, 0x49, 0x30, 0x55, 0x21, 0x32, 0x6b, + 0xde, 0x08, 0x56, 0x30, 0x86, 0x46, 0x29, 0x29, 0x1b, 0xae, 0x25, 0xff, 0x88, 0x22, + 0xa1, 0x4c, 0x4b, 0x66, 0x6a, 0x92, 0x59, 0xad, 0x0d, 0xc4, 0x2a, 0x82, 0x90, 0xac, + 0x7b, 0xc7, 0xf5, 0x3a, 0x16, 0xf3, 0x79, 0xf7, 0x58, 0xe5, 0xde, 0x75, 0x0f, 0x04, + 0xfd, 0x7c, 0xad, 0x47, 0x70, 0x1c, 0x85, 0x97, 0xf9, 0x78, 0x88, 0xbe, 0xa6, 0xfa, + 0x0b, 0xf2, 0x99, 0x99, 0x56, 0xfb, 0xfd, 0x0e, 0xe6, 0x8e, 0xc3, 0x6e, 0x46, 0x88, + 0x80, 0x9a, 0xe2, 0x31, 0xeb, 0x8b, 0xc4, 0x36, 0x9f, 0x5f, 0xe1, 0x57, 0x3f, 0x57, + 0xe0, 0x99, 0xd9, 0xc0, 0x99, 0x01, 0xbf, 0x39, 0xca, 0xac, 0x48, 0xdc, 0x11, 0x95, + 0x6a, 0x8a, 0xe9, 0x05, 0xea, 0xd8, 0x69, 0x54, 0x54, 0x7c, 0x44, 0x8a, 0xe4, 0x3d, + 0x31, 0x5e, 0x66, 0x9c, 0x42, 0x42, 0xda, 0x56, 0x59, 0x38, 0xf4, 0x17, 0xbf, 0x43, + 0xce, 0x7b, 0x2b, 0x30, 0xb1, 0xcd, 0x40, 0x18, 0x38, 0x8e, 0x1a, 0x91, 0x0f, 0x0f, + 0xc4, 0x1f, 0xb0, 0x87, 0x7a, 0x59, 0x25, 0xe4, 0x66, 0x81, 0x9d, 0x37, 0x5b, 0x0a, + 0x91, 0x2d, 0x4f, 0xe8, 0x43, 0xb7, 0x6e, 0xf6, 0xf2, 0x23, 0xf0, 0xf7, 0xc8, 0x94, + 0xf3, 0x8f, 0x7a, 0xb7, 0x80, 0xdf, 0xd7, 0x5f, 0x66, 0x9c, 0x8c, 0x06, 0xcf, 0xfa, + 0x43, 0xeb, 0x47, 0x56, 0x5a, 0x50, 0xe3, 0xb1, 0xfa, 0x45, 0xad, 0x61, 0xce, 0x9a, + 0x1c, 0x47, 0x27, 0xb7, 0xaa, 0xa5, 0x35, 0x62, 0xf5, 0x23, 0xe7, 0x39, 0x52, 0xbb, + 0xf3, 0x3d, 0x8a, 0x41, 0x04, 0x07, 0x8a, 0xde, 0x3e, 0xaa, 0xa4, 0x96, 0x99, 0xa6, + 0x9f, 0xdf, 0x1c, 0x5a, 0xc7, 0x73, 0x21, 0x46, 0xee, 0x5e, 0x1d, 0x6b, 0x6c, 0xa9, + 0xb9, 0x18, 0x0f, 0x96, 0x4c, 0xc9, 0xd0, 0x87, 0x8a, 0xe1, 0x37, 0x35, 0x24, 0xd7, + 0xd5, 0x10, 0xe5, 0x82, 0x27, 0xdf, 0x6d, 0xe9, 0xd3, 0x0d, 0x27, 0x18, 0x67, 0x64, + 0x01, 0x77, 0xb0, 0xf1, 0x85, 0x6e, 0x28, 0xd5, 0xc8, 0xaf, 0xb0, 0x95, 0xef, 0x61, + 0x84, 0xfe, 0xd6, 0x51, 0x58, 0x90, 0x22, 0xee, 0xae, 0xa4, 0xc0, 0xce, 0x1f, 0xa6, + 0xf0, 0x85, 0x09, 0x2b, 0x04, 0x97, 0x94, 0x89, 0x17, 0x2b, 0x3e, 0xf8, 0x19, 0x4a, + 0x79, 0x8d, 0xf5, 0x72, 0x4d, 0x6b, 0x05, 0xf1, 0xae, 0x00, 0x00, 0x13, 0xa0, 0x8d, + 0x61, 0x2b, 0xca, 0x8a, 0x8c, 0x31, 0x44, 0x3c, 0x10, 0x34, 0x6d, 0xbf, 0x61, 0xde, + 0x84, 0x75, 0xc0, 0xbb, 0xec, 0x51, 0x04, 0xb4, 0x75, 0x56, 0xaf, 0x3d, 0x51, 0x44, + 0x58, 0xe2, 0x32, 0x1d, 0x14, 0x60, 0x71, 0x78, 0x9d, 0x23, 0x35, 0x93, 0x4a, 0x68, + 0x06, 0x14, 0xe8, 0x35, 0x62, 0xf8, 0x2d, 0xfd, 0x40, 0x5b, 0x54, 0xa4, 0x5e, 0xb3, + 0x2c, 0x16, 0x54, 0x48, 0xd4, 0xd5, 0xd6, 0x1c, 0xa2, 0x85, 0x95, 0x85, 0x36, 0x9f, + 0x53, 0xf1, 0xa1, 0x37, 0xe9, 0xe8, 0x2b, 0x67, 0xb8, 0xfd, 0xaf, 0x01, 0xbd, 0xa5, + 0x4a, 0x31, 0x73, 0x11, 0x89, 0x6a, 0xe1, 0x02, 0x80, 0xa0, 0x32, 0x44, 0x0c, 0x42, + 0x0a, 0x42, 0x1e, 0x94, 0x4d, 0x1e, 0x95, 0x2b, 0x70, 0xd5, 0x82, 0x6c, 0xd3, 0xb0, + 0x8b, 0x7d, 0xb9, 0x63, 0x0f, 0xe4, 0xfd, 0x5f, 0x22, 0x12, 0x5d, 0xe8, 0x40, 0xfc, + 0xc4, 0x0b, 0x98, 0x03, 0x8a, 0xf1, 0x1d, 0x55, 0xbe, 0x25, 0x43, 0x25, 0x97, 0xb4, + 0xb6, 0x5b, 0x9e, 0xc1, 0xc7, 0xa8, 0xbb, 0xfd, 0x05, 0x2c, 0xbf, 0x7e, 0x1c, 0x17, + 0x85, 0x31, 0x49, 0x34, 0xb2, 0x62, 0xd5, 0x85, 0x37, 0x54, 0xf1, 0xf1, 0x77, 0x71, + 0xcf, 0xb7, 0x50, 0x30, 0x72, 0x65, 0x57, 0x53, + ], + c_enc: [ + 0xe6, 0x67, 0x81, 0xae, 0x63, 0x84, 0x1f, 0xff, 0xea, 0x30, 0x21, 0x96, 0x15, 0x94, + 0xc2, 0x2a, 0x87, 0x20, 0xc7, 0xd8, 0xaa, 0x80, 0x8b, 0xc8, 0x6e, 0x71, 0xa3, 0x6a, + 0xd7, 0xf8, 0x6f, 0xf8, 0x7c, 0x07, 0xd3, 0xc6, 0x50, 0xa0, 0x8e, 0x23, 0xe9, 0xb5, + 0x4f, 0x00, 0xb4, 0x0b, 0xa0, 0x15, 0x91, 0x69, 0xdf, 0xca, 0xac, 0xbe, 0x6e, 0x4d, + 0x87, 0xe9, 0x2a, 0xae, 0x2f, 0xe4, 0xe5, 0x8e, 0x78, 0x48, 0x69, 0xa9, 0x70, 0x68, + 0x4c, 0x9b, 0x87, 0xc9, 0xa1, 0xa0, 0xcc, 0x39, 0xb3, 0xbc, 0xce, 0xf4, 0x7c, 0xd7, + 0x6c, 0x23, 0x97, 0xb1, 0x43, 0x39, 0x5a, 0xd5, 0xbd, 0x5f, 0xe4, 0x22, 0x2c, 0x05, + 0xee, 0xb7, 0xc2, 0x0a, 0x5d, 0x0c, 0x35, 0xf0, 0x3a, 0xa2, 0xa6, 0xba, 0xfa, 0xdf, + 0x36, 0x3b, 0x1b, 0xa1, 0x5f, 0x8e, 0x75, 0x17, 0x79, 0x32, 0x03, 0xba, 0x09, 0x0e, + 0xda, 0x67, 0x1a, 0xcf, 0x48, 0xba, 0xaf, 0x8a, 0x6c, 0x1d, 0x55, 0xac, 0x76, 0x0b, + 0x10, 0xa0, 0x85, 0xb2, 0xe8, 0x33, 0xeb, 0x03, 0xb2, 0xbb, 0xd5, 0x21, 0x46, 0xd2, + 0x73, 0x19, 0xcc, 0x97, 0x13, 0x70, 0x14, 0xe7, 0x83, 0xac, 0xb6, 0x40, 0x27, 0xb6, + 0xea, 0x33, 0xa7, 0x1e, 0x54, 0xab, 0xb0, 0xe3, 0xf6, 0x05, 0x39, 0x10, 0xce, 0x33, + 0xa1, 0xc2, 0xde, 0x27, 0xd5, 0x80, 0x1a, 0x0d, 0xfc, 0x95, 0x28, 0xf8, 0x17, 0xb1, + 0x24, 0x88, 0x05, 0x62, 0xb7, 0x1f, 0xb9, 0x91, 0xd4, 0x1d, 0x2b, 0x4a, 0x20, 0x3b, + 0x3b, 0x20, 0x97, 0x55, 0xb6, 0x16, 0x8a, 0x99, 0x8c, 0xea, 0xb0, 0x2b, 0x21, 0x1e, + 0x49, 0xfe, 0x6a, 0xb1, 0x3a, 0x9a, 0x38, 0x83, 0xfe, 0xca, 0xfa, 0x87, 0x6d, 0xb2, + 0xbe, 0x99, 0x1a, 0x0a, 0xab, 0xb9, 0xf1, 0x50, 0xd5, 0xf1, 0xbf, 0xfc, 0x75, 0xbf, + 0x4d, 0xd0, 0xcf, 0x15, 0x09, 0xe5, 0x6b, 0x7e, 0xc8, 0x37, 0xdb, 0x74, 0xd1, 0xcb, + 0x2a, 0x10, 0x45, 0x1e, 0x1c, 0x04, 0xdd, 0xf9, 0x5b, 0x17, 0x20, 0x00, 0x94, 0x52, + 0xc5, 0x55, 0x86, 0x96, 0x35, 0x0e, 0xfd, 0xbf, 0x38, 0xc3, 0xde, 0x29, 0x98, 0x09, + 0x7c, 0xa7, 0xac, 0xd7, 0x09, 0x9a, 0x73, 0x94, 0x73, 0xc2, 0x07, 0x85, 0x89, 0xe7, + 0x18, 0xf9, 0x20, 0xad, 0xeb, 0xd6, 0xcb, 0x6e, 0xb1, 0x2e, 0x3f, 0xd2, 0x29, 0x47, + 0xa7, 0x6d, 0x19, 0x17, 0x45, 0xa6, 0xa9, 0x73, 0xc8, 0xb8, 0x4e, 0x9c, 0xd3, 0x30, + 0x7e, 0x47, 0x88, 0x81, 0xe9, 0x79, 0x8f, 0xd6, 0x66, 0x57, 0xec, 0xe5, 0xe0, 0x89, + 0xd6, 0x62, 0x71, 0x18, 0xc1, 0x1b, 0xa4, 0x01, 0xb0, 0x17, 0xdb, 0x2d, 0x6f, 0xf4, + 0x42, 0x10, 0xdb, 0x3e, 0x05, 0xaf, 0xe3, 0x10, 0x18, 0x79, 0xd9, 0x6f, 0x20, 0x2b, + 0x04, 0x93, 0x67, 0x2b, 0x55, 0x01, 0x3b, 0x26, 0x47, 0xad, 0x71, 0x7f, 0x8e, 0xf2, + 0x6f, 0x3d, 0x43, 0xb7, 0x75, 0x9e, 0xf5, 0xd6, 0x72, 0xcb, 0x14, 0x17, 0xf9, 0x78, + 0x81, 0xc3, 0x28, 0x80, 0x61, 0x2e, 0x6b, 0x00, 0xcc, 0x63, 0xfd, 0xa8, 0xd0, 0x29, + 0x88, 0xc4, 0x03, 0xee, 0x95, 0x6f, 0xfe, 0x72, 0xa2, 0xe1, 0xd1, 0x64, 0x29, 0x10, + 0xe3, 0xdf, 0x2c, 0xb8, 0xe0, 0xce, 0x90, 0x6f, 0x66, 0x2a, 0x96, 0x37, 0x5b, 0x78, + 0x64, 0xe1, 0x7f, 0x2a, 0x3d, 0x12, 0x19, 0x68, 0x47, 0x57, 0x03, 0x3c, 0xeb, 0x0c, + 0xb7, 0xea, 0x10, 0xd9, 0x90, 0x2d, 0x56, 0x55, 0x53, 0x15, 0xa8, 0x0f, 0x99, 0x7f, + 0xb7, 0xc3, 0xa6, 0xb7, 0x0e, 0x30, 0x7f, 0x33, 0x18, 0x44, 0x60, 0x1e, 0xf5, 0x70, + 0x13, 0xe3, 0xd3, 0x35, 0xfe, 0x48, 0x29, 0x81, 0xef, 0x72, 0x1f, 0xf0, 0xc3, 0x4f, + 0xb8, 0x8a, 0xcd, 0xae, 0x2f, 0xa0, 0xc1, 0x80, 0x1a, 0xd1, 0xe9, 0x67, 0x56, 0x25, + 0x66, 0xf7, 0xea, 0x6c, 0x65, 0x67, 0xfe, 0x06, 0x6d, 0x33, 0xd0, 0x84, 0x1b, 0x33, + 0xb5, 0x60, 0xe2, 0xf8, 0x43, 0x58, 0xd4, 0x1a, 0xfc, 0x3e, 0x43, 0x6d, 0x86, 0x8e, + 0x02, 0x1a, 0x1e, 0xde, 0xb3, 0x69, 0xa9, 0x84, 0x06, 0xa5, 0x76, 0xed, 0x48, 0x38, + 0xc7, 0x30, 0xad, 0xef, 0xd6, 0x94, 0x24, 0xc2, 0x35, 0xdb, 0x4f, 0xb1, 0xf6, 0xf6, + 0x2e, 0x9b, 0x51, 0x80, 0x5c, 0xdb, 0x43, 0xea, 0xf2, 0xa6, 0xb4, 0x5f, 0x81, 0x4d, + 0xaf, 0x53, 0x0a, 0xfb, 0xd0, 0xb3, 0x0b, 0xbb, 0xbb, 0xa9, 0x66, 0x05, 0x9a, 0x08, + 0xd3, 0x1d, 0x13, 0x7b, 0xbf, 0x5e, 0xc5, 0x80, 0x58, 0xd3, + ], + ock: [ + 0x85, 0x6e, 0x1a, 0x97, 0x09, 0xb0, 0xc4, 0x16, 0x93, 0x3f, 0x59, 0x70, 0x71, 0x5c, + 0x56, 0xe2, 0xe0, 0x5c, 0x2e, 0xa9, 0x7d, 0x81, 0x51, 0x25, 0x70, 0x14, 0x79, 0xc3, + 0x3a, 0x5d, 0x91, 0xcb, + ], + op: [ + 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, + 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, + 0x14, 0x93, 0x16, 0x36, 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, + 0xfe, 0x47, 0x9a, 0x1e, 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, + 0x92, 0x3a, 0x5d, 0x00, 0xcb, 0x52, 0xa6, 0x13, + ], + c_out: [ + 0x72, 0x36, 0xea, 0xb9, 0xf0, 0x12, 0x98, 0xc8, 0x4f, 0x38, 0x28, 0xf6, 0xac, 0x15, + 0x42, 0x76, 0xb5, 0xb7, 0x64, 0x62, 0xf5, 0x74, 0x2d, 0x69, 0xdc, 0x47, 0x7a, 0x10, + 0x5d, 0xc2, 0x71, 0x1b, 0x12, 0xe9, 0xb5, 0x82, 0x8c, 0x01, 0x76, 0xfe, 0xf4, 0x4a, + 0x54, 0x0f, 0x60, 0x95, 0x8e, 0x5a, 0x3e, 0xd6, 0xa2, 0xcc, 0x5e, 0xdd, 0xe9, 0x13, + 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, + 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x0b, 0xb5, 0x6c, 0x49, 0xc0, 0x63, 0x2d, 0x4c, 0xc7, 0xe4, 0x85, 0x51, 0xdb, 0x46, + 0x42, 0x8f, 0x1b, 0x1a, 0x52, 0x66, 0x1e, 0x07, 0xe0, 0xc3, 0xbc, 0xc2, 0x31, 0x74, + 0xcc, 0xbb, 0xbd, 0xa1, 0xfa, 0x19, 0x24, 0xf4, 0x16, 0xcd, 0x48, 0x39, 0x0e, 0x2b, + 0x11, 0xc6, 0xe7, 0x82, 0x56, 0xd4, 0xc4, 0xc5, 0x64, 0x1a, 0xca, 0xd9, 0xa2, 0x0c, + 0x24, 0xfb, 0xe6, 0xcb, 0x4e, 0xe7, 0x81, 0x25, + ], + ovk: [ + 0x21, 0xe9, 0x1a, 0x3c, 0x4a, 0xa3, 0xf2, 0x7f, 0xa1, 0xb6, 0x33, 0x96, 0xe2, 0xb4, + 0x1d, 0xb9, 0x08, 0xfd, 0xab, 0x8b, 0x18, 0xcc, 0x73, 0x04, 0xe9, 0x4e, 0x97, 0x05, + 0x68, 0xf9, 0x42, 0x1c, + ], + default_d: [ + 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, + ], + default_pk_d: [ + 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, + 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, + 0x03, 0x8e, 0x3d, 0xb3, + ], + v: 12119135386131850622, + rseed: [ + 0xc3, 0x6d, 0xcf, 0xd3, 0x4a, 0x0c, 0xb6, 0x63, 0x78, 0x76, 0x10, 0x5e, 0x79, 0xbf, + 0x3b, 0xd5, 0x8e, 0xc1, 0x48, 0xcb, 0x64, 0x97, 0x0e, 0x32, 0x23, 0xa9, 0x1f, 0x71, + 0xdf, 0xcf, 0xd5, 0xa0, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x4b, 0x66, 0x7f, 0xba, 0xf3, 0xd4, 0xb3, 0xb9, 0x08, 0xb9, 0x82, 0x88, 0x20, + 0xdf, 0xec, 0xdd, 0x75, 0x37, 0x50, 0xb5, 0xf9, 0xd2, 0x21, 0x6e, 0x56, 0xc6, 0x15, + 0x27, 0x2f, 0x85, 0x44, 0x64, 0xc0, 0xca, 0x4b, 0x1e, 0x85, 0xae, 0xdd, 0x03, 0x82, + 0x92, 0xc4, 0xe1, 0xa5, 0x77, 0x44, 0xeb, 0xba, 0x01, 0x0b, 0x9e, 0xbf, 0xbb, 0x01, + 0x1b, 0xd6, 0xf0, 0xb7, 0x88, 0x05, 0x02, 0x5d, 0x27, 0xf3, 0xc1, 0x77, 0x46, 0xba, + 0xe1, 0x16, 0xc1, 0x5d, 0x9f, 0x47, 0x1f, 0x0f, 0x62, 0x88, 0xa1, 0x50, 0x64, 0x7b, + 0x2a, 0xfe, 0x9d, 0xf7, 0xcc, 0xcf, 0x01, 0xf5, 0xcd, 0xe5, 0xf0, 0x46, 0x80, 0xbb, + 0xfe, 0xd8, 0x7f, 0x6c, 0xf4, 0x29, 0xfb, 0x27, 0xad, 0x6b, 0xab, 0xe7, 0x91, 0x76, + 0x66, 0x11, 0xcf, 0x5b, 0xc2, 0x0e, 0x48, 0xbe, 0xf1, 0x19, 0x25, 0x9b, 0x9b, 0x8a, + 0x0e, 0x39, 0xc3, 0xdf, 0x28, 0xcb, 0x95, 0x82, 0xea, 0x33, 0x86, 0x01, 0xcd, 0xc4, + 0x81, 0xb3, 0x2f, 0xb8, 0x2a, 0xde, 0xeb, 0xb3, 0xda, 0xde, 0x25, 0xd1, 0xa3, 0xdf, + 0x20, 0xc3, 0x7e, 0x71, 0x25, 0x06, 0xb5, 0xd9, 0x96, 0xc4, 0x9a, 0x9f, 0x0f, 0x30, + 0xdd, 0xcb, 0x91, 0xfe, 0x90, 0x04, 0xe1, 0xe8, 0x32, 0x94, 0xa6, 0xc9, 0x20, 0x3d, + 0x94, 0xe8, 0xdc, 0x2c, 0xbb, 0x44, 0x9d, 0xe4, 0x15, 0x50, 0x32, 0x60, 0x4e, 0x47, + 0x99, 0x70, 0x16, 0xb3, 0x04, 0xfd, 0x43, 0x7d, 0x82, 0x35, 0x04, 0x5e, 0x25, 0x5a, + 0x19, 0xb7, 0x43, 0xa0, 0xa9, 0xf2, 0xe3, 0x36, 0xb4, 0x4c, 0xae, 0x30, 0x7b, 0xb3, + 0x98, 0x7b, 0xd3, 0xe4, 0xe7, 0x77, 0xfb, 0xb3, 0x4c, 0x0a, 0xb8, 0xcc, 0x3d, 0x67, + 0x46, 0x6c, 0x0a, 0x88, 0xdd, 0x4c, 0xca, 0xd1, 0x8a, 0x07, 0xa8, 0xd1, 0x06, 0x8d, + 0xf5, 0xb6, 0x29, 0xe5, 0x71, 0x8d, 0x0f, 0x6d, 0xf5, 0xc9, 0x57, 0xcf, 0x71, 0xbb, + 0x00, 0xa5, 0x17, 0x8f, 0x17, 0x5c, 0xac, 0xa9, 0x44, 0xe6, 0x35, 0xc5, 0x15, 0x9f, + 0x73, 0x8e, 0x24, 0x02, 0xa2, 0xd2, 0x1a, 0xa0, 0x81, 0xe1, 0x0e, 0x45, 0x6a, 0xfb, + 0x00, 0xb9, 0xf6, 0x24, 0x16, 0xc8, 0xb9, 0xc0, 0xf7, 0x22, 0x8f, 0x51, 0x07, 0x29, + 0xe0, 0xbe, 0x3f, 0x30, 0x53, 0x13, 0xd7, 0x7f, 0x73, 0x79, 0xdc, 0x2a, 0xf2, 0x48, + 0x69, 0xc6, 0xc7, 0x4e, 0xe4, 0x47, 0x14, 0x98, 0x86, 0x1d, 0x19, 0x2f, 0x0f, 0xf0, + 0xf5, 0x08, 0x28, 0x5d, 0xab, 0x6b, 0x6a, 0x36, 0xcc, 0xf7, 0xd1, 0x22, 0x56, 0xcc, + 0x76, 0xb9, 0x55, 0x03, 0x72, 0x0a, 0xc6, 0x72, 0xd0, 0x82, 0x68, 0xd2, 0xcf, 0x77, + 0x73, 0xb6, 0xba, 0x2a, 0x5f, 0x66, 0x48, 0x47, 0xbf, 0x70, 0x7f, 0x2f, 0xc1, 0x0c, + 0x98, 0xf2, 0xf0, 0x06, 0xec, 0x22, 0xcc, 0xb5, 0xa8, 0xc8, 0xb7, 0xc4, 0x0c, 0x7c, + 0x2d, 0x49, 0xa6, 0x63, 0x9b, 0x9f, 0x2c, 0xe3, 0x3c, 0x25, 0xc0, 0x4b, 0xc4, 0x61, + 0xe7, 0x44, 0xdf, 0xa5, 0x36, 0xb0, 0x0d, 0x94, 0xba, 0xdd, 0xf4, 0xf4, 0xd1, 0x40, + 0x44, 0xc6, 0x95, 0xa3, 0x38, 0x81, 0x47, 0x7d, 0xf1, 0x24, 0xf0, 0xfc, 0xf2, 0x06, + 0xa9, 0xfb, 0x2e, 0x65, 0xe3, 0x04, 0xcd, 0xbf, 0x0c, 0x4d, 0x23, 0x90, 0x17, 0x0c, + 0x13, 0x0a, 0xb8, 0x49, 0xc2, 0xf2, 0x2b, 0x5c, 0xdd, 0x39, 0x21, 0x64, 0x0c, 0x8c, + 0xf1, 0x97, 0x6a, 0xe1, 0x01, 0x0b, 0x0d, 0xfd, 0x9c, 0xb2, 0x54, 0x3e, 0x45, 0xf9, + 0x97, 0x49, 0xcc, 0x4d, 0x61, 0xf2, 0xe8, 0xaa, 0xbf, 0xe9, 0x8b, 0xd9, 0x05, 0xfa, + 0x39, 0x95, 0x1b, 0x33, 0xea, 0x76, 0x9c, 0x45, 0xab, 0x95, 0x31, 0xc5, 0x72, 0x09, + 0x86, 0x2a, 0xd1, 0x2f, 0xd7, 0x6b, 0xa4, 0x80, + ], + cv_net: [ + 0xca, 0xf6, 0x40, 0x8d, 0xef, 0x1f, 0x0f, 0x2b, 0xaa, 0x17, 0xb1, 0x30, 0xc3, 0xae, + 0x72, 0x95, 0x89, 0xbe, 0x69, 0xd8, 0x28, 0xbe, 0x54, 0x30, 0x69, 0x16, 0x41, 0x3c, + 0xd2, 0x50, 0x21, 0x17, + ], + rho: [ + 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, + 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, + 0x3c, 0xfb, 0xf1, 0x31, + ], + cmx: [ + 0xea, 0x7c, 0x13, 0xf7, 0xe1, 0x20, 0x5e, 0x78, 0xc8, 0xce, 0x4e, 0xe4, 0xfd, 0xcd, + 0xb7, 0xee, 0x76, 0x92, 0x8d, 0xdf, 0x6d, 0xbe, 0x1b, 0x2d, 0x6f, 0x69, 0x81, 0xb7, + 0xc9, 0x65, 0x79, 0x10, + ], + esk: [ + 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, 0x73, 0xe9, 0x05, 0x99, + 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, 0x89, 0xcc, 0x63, 0x00, + 0x06, 0x15, 0xb2, 0x0d, + ], + ephemeral_key: [ + 0x89, 0xfd, 0x2c, 0xf3, 0x79, 0x56, 0xba, 0xaf, 0x11, 0x27, 0xbb, 0x0e, 0x33, 0x40, + 0x01, 0x09, 0xdb, 0x03, 0x50, 0xf4, 0xab, 0xb7, 0xd6, 0xd8, 0x1f, 0xa5, 0x84, 0x8e, + 0x1b, 0xb1, 0x69, 0x26, + ], + shared_secret: [ + 0xdb, 0xa6, 0x37, 0x94, 0xb6, 0x7c, 0x49, 0x6d, 0x01, 0x1c, 0xfb, 0x6b, 0xba, 0x29, + 0x7c, 0xa5, 0x7d, 0x18, 0xc7, 0xa9, 0xad, 0xdf, 0xfb, 0xc8, 0x37, 0x17, 0x6a, 0xcf, + 0x3a, 0x30, 0x1e, 0x23, + ], + k_enc: [ + 0x80, 0xe7, 0x52, 0x2c, 0xb0, 0x32, 0x51, 0xc8, 0x55, 0x34, 0x1f, 0x06, 0xf9, 0x41, + 0x33, 0x41, 0xe1, 0x6e, 0x83, 0xb4, 0x89, 0xe1, 0x5a, 0x0a, 0x00, 0x65, 0xc3, 0x3b, + 0xf3, 0x81, 0x58, 0xc4, + ], + p_enc: [ + 0x03, 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, 0x7e, 0x65, + 0x41, 0x7b, 0x6c, 0xd1, 0x2f, 0xa8, 0xc3, 0x6d, 0xcf, 0xd3, 0x4a, 0x0c, 0xb6, 0x63, + 0x78, 0x76, 0x10, 0x5e, 0x79, 0xbf, 0x3b, 0xd5, 0x8e, 0xc1, 0x48, 0xcb, 0x64, 0x97, + 0x0e, 0x32, 0x23, 0xa9, 0x1f, 0x71, 0xdf, 0xcf, 0xd5, 0xa0, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x4b, 0x66, 0x7f, 0xba, 0xf3, 0xd4, 0xb3, 0xb9, 0x08, 0xb9, 0x82, 0x88, 0x20, + 0xdf, 0xec, 0xdd, 0x75, 0x37, 0x50, 0xb5, 0xf9, 0xd2, 0x21, 0x6e, 0x56, 0xc6, 0x15, + 0x27, 0x2f, 0x85, 0x44, 0x64, 0xc0, 0xca, 0x4b, 0x1e, 0x85, 0xae, 0xdd, 0x03, 0x82, + 0x92, 0xc4, 0xe1, 0xa5, 0x77, 0x44, 0xeb, 0xba, 0x01, 0x0b, 0x9e, 0xbf, 0xbb, 0x01, + 0x1b, 0xd6, 0xf0, 0xb7, 0x88, 0x05, 0x02, 0x5d, 0x27, 0xf3, 0xc1, 0x77, 0x46, 0xba, + 0xe1, 0x16, 0xc1, 0x5d, 0x9f, 0x47, 0x1f, 0x0f, 0x62, 0x88, 0xa1, 0x50, 0x64, 0x7b, + 0x2a, 0xfe, 0x9d, 0xf7, 0xcc, 0xcf, 0x01, 0xf5, 0xcd, 0xe5, 0xf0, 0x46, 0x80, 0xbb, + 0xfe, 0xd8, 0x7f, 0x6c, 0xf4, 0x29, 0xfb, 0x27, 0xad, 0x6b, 0xab, 0xe7, 0x91, 0x76, + 0x66, 0x11, 0xcf, 0x5b, 0xc2, 0x0e, 0x48, 0xbe, 0xf1, 0x19, 0x25, 0x9b, 0x9b, 0x8a, + 0x0e, 0x39, 0xc3, 0xdf, 0x28, 0xcb, 0x95, 0x82, 0xea, 0x33, 0x86, 0x01, 0xcd, 0xc4, + 0x81, 0xb3, 0x2f, 0xb8, 0x2a, 0xde, 0xeb, 0xb3, 0xda, 0xde, 0x25, 0xd1, 0xa3, 0xdf, + 0x20, 0xc3, 0x7e, 0x71, 0x25, 0x06, 0xb5, 0xd9, 0x96, 0xc4, 0x9a, 0x9f, 0x0f, 0x30, + 0xdd, 0xcb, 0x91, 0xfe, 0x90, 0x04, 0xe1, 0xe8, 0x32, 0x94, 0xa6, 0xc9, 0x20, 0x3d, + 0x94, 0xe8, 0xdc, 0x2c, 0xbb, 0x44, 0x9d, 0xe4, 0x15, 0x50, 0x32, 0x60, 0x4e, 0x47, + 0x99, 0x70, 0x16, 0xb3, 0x04, 0xfd, 0x43, 0x7d, 0x82, 0x35, 0x04, 0x5e, 0x25, 0x5a, + 0x19, 0xb7, 0x43, 0xa0, 0xa9, 0xf2, 0xe3, 0x36, 0xb4, 0x4c, 0xae, 0x30, 0x7b, 0xb3, + 0x98, 0x7b, 0xd3, 0xe4, 0xe7, 0x77, 0xfb, 0xb3, 0x4c, 0x0a, 0xb8, 0xcc, 0x3d, 0x67, + 0x46, 0x6c, 0x0a, 0x88, 0xdd, 0x4c, 0xca, 0xd1, 0x8a, 0x07, 0xa8, 0xd1, 0x06, 0x8d, + 0xf5, 0xb6, 0x29, 0xe5, 0x71, 0x8d, 0x0f, 0x6d, 0xf5, 0xc9, 0x57, 0xcf, 0x71, 0xbb, + 0x00, 0xa5, 0x17, 0x8f, 0x17, 0x5c, 0xac, 0xa9, 0x44, 0xe6, 0x35, 0xc5, 0x15, 0x9f, + 0x73, 0x8e, 0x24, 0x02, 0xa2, 0xd2, 0x1a, 0xa0, 0x81, 0xe1, 0x0e, 0x45, 0x6a, 0xfb, + 0x00, 0xb9, 0xf6, 0x24, 0x16, 0xc8, 0xb9, 0xc0, 0xf7, 0x22, 0x8f, 0x51, 0x07, 0x29, + 0xe0, 0xbe, 0x3f, 0x30, 0x53, 0x13, 0xd7, 0x7f, 0x73, 0x79, 0xdc, 0x2a, 0xf2, 0x48, + 0x69, 0xc6, 0xc7, 0x4e, 0xe4, 0x47, 0x14, 0x98, 0x86, 0x1d, 0x19, 0x2f, 0x0f, 0xf0, + 0xf5, 0x08, 0x28, 0x5d, 0xab, 0x6b, 0x6a, 0x36, 0xcc, 0xf7, 0xd1, 0x22, 0x56, 0xcc, + 0x76, 0xb9, 0x55, 0x03, 0x72, 0x0a, 0xc6, 0x72, 0xd0, 0x82, 0x68, 0xd2, 0xcf, 0x77, + 0x73, 0xb6, 0xba, 0x2a, 0x5f, 0x66, 0x48, 0x47, 0xbf, 0x70, 0x7f, 0x2f, 0xc1, 0x0c, + 0x98, 0xf2, 0xf0, 0x06, 0xec, 0x22, 0xcc, 0xb5, 0xa8, 0xc8, 0xb7, 0xc4, 0x0c, 0x7c, + 0x2d, 0x49, 0xa6, 0x63, 0x9b, 0x9f, 0x2c, 0xe3, 0x3c, 0x25, 0xc0, 0x4b, 0xc4, 0x61, + 0xe7, 0x44, 0xdf, 0xa5, 0x36, 0xb0, 0x0d, 0x94, 0xba, 0xdd, 0xf4, 0xf4, 0xd1, 0x40, + 0x44, 0xc6, 0x95, 0xa3, 0x38, 0x81, 0x47, 0x7d, 0xf1, 0x24, 0xf0, 0xfc, 0xf2, 0x06, + 0xa9, 0xfb, 0x2e, 0x65, 0xe3, 0x04, 0xcd, 0xbf, 0x0c, 0x4d, 0x23, 0x90, 0x17, 0x0c, + 0x13, 0x0a, 0xb8, 0x49, 0xc2, 0xf2, 0x2b, 0x5c, 0xdd, 0x39, 0x21, 0x64, 0x0c, 0x8c, + 0xf1, 0x97, 0x6a, 0xe1, 0x01, 0x0b, 0x0d, 0xfd, 0x9c, 0xb2, 0x54, 0x3e, 0x45, 0xf9, + 0x97, 0x49, 0xcc, 0x4d, 0x61, 0xf2, 0xe8, 0xaa, 0xbf, 0xe9, 0x8b, 0xd9, 0x05, 0xfa, + 0x39, 0x95, 0x1b, 0x33, 0xea, 0x76, 0x9c, 0x45, 0xab, 0x95, 0x31, 0xc5, 0x72, 0x09, + 0x86, 0x2a, 0xd1, 0x2f, 0xd7, 0x6b, 0xa4, 0x80, + ], + c_enc: [ + 0x3e, 0x4e, 0x9b, 0x18, 0x56, 0xe7, 0xbf, 0xba, 0x7a, 0xbb, 0xc9, 0x4a, 0x72, 0xb4, + 0xab, 0xb1, 0xd8, 0x46, 0x26, 0x79, 0x30, 0x77, 0xe8, 0x37, 0xda, 0xf3, 0x3f, 0xff, + 0xa2, 0x7c, 0x7a, 0x33, 0x97, 0x8a, 0x54, 0x32, 0x51, 0x0d, 0x99, 0x3c, 0x7d, 0x92, + 0x24, 0xc0, 0x97, 0xac, 0xc5, 0x25, 0x88, 0x1c, 0x76, 0x08, 0xa4, 0x13, 0xfa, 0x5f, + 0x49, 0xaf, 0xc6, 0x58, 0x93, 0x94, 0xab, 0x86, 0x59, 0x0c, 0x43, 0x78, 0x5a, 0x58, + 0x0b, 0xd2, 0x86, 0x0b, 0xe3, 0xb8, 0x07, 0x99, 0xc1, 0x47, 0xf4, 0xe6, 0xc7, 0x50, + 0x31, 0x36, 0x76, 0x9a, 0xe4, 0xc6, 0x2c, 0xd9, 0x16, 0x9d, 0xd3, 0x66, 0xb8, 0x99, + 0xa5, 0x44, 0x8c, 0xdb, 0xc4, 0x0c, 0x8d, 0x89, 0x60, 0x38, 0x6c, 0x0f, 0x0e, 0x3e, + 0x74, 0x03, 0xd2, 0x6e, 0x66, 0xa5, 0x99, 0x40, 0xe7, 0x6a, 0xc7, 0x9d, 0xd1, 0xea, + 0xea, 0x55, 0xd0, 0xc0, 0x9f, 0x3b, 0xf6, 0xd9, 0xdc, 0xea, 0xe1, 0xee, 0x87, 0x41, + 0x38, 0x39, 0x1a, 0x0c, 0x93, 0x3e, 0x7b, 0x72, 0x75, 0xd7, 0x3b, 0x8e, 0xf4, 0x9b, + 0x8c, 0x39, 0x5c, 0x87, 0xfd, 0x32, 0x09, 0xe1, 0xf5, 0xa9, 0xc5, 0x52, 0xe6, 0x11, + 0x2b, 0xd9, 0xf3, 0xea, 0xb6, 0xbd, 0x4f, 0x26, 0xab, 0xa6, 0x4d, 0xb8, 0x27, 0xa7, + 0x1b, 0x86, 0x53, 0x9c, 0xf9, 0x72, 0x96, 0xfe, 0xca, 0x46, 0x27, 0x3e, 0xf4, 0x56, + 0xfe, 0x16, 0x0b, 0x31, 0xc7, 0x72, 0xcf, 0xf6, 0x82, 0xa6, 0xed, 0x06, 0x10, 0x93, + 0x14, 0x6e, 0xa6, 0x57, 0xf4, 0x61, 0xb5, 0x6f, 0xb2, 0x3c, 0x20, 0x64, 0xd8, 0x98, + 0xec, 0x25, 0x70, 0x34, 0x3c, 0x56, 0x6a, 0xdc, 0x1f, 0x2d, 0x1d, 0x86, 0x48, 0x41, + 0x42, 0x2e, 0x96, 0x4a, 0x4a, 0xb8, 0x3c, 0x18, 0x95, 0x0f, 0x82, 0xfa, 0x97, 0x4c, + 0x83, 0x3c, 0xf7, 0x62, 0x3d, 0xa9, 0xb8, 0xbe, 0xec, 0x7a, 0x1e, 0xbf, 0x5c, 0xeb, + 0x22, 0x25, 0xc1, 0xf2, 0xda, 0x30, 0xd0, 0x47, 0x9d, 0xbb, 0xa1, 0x68, 0x1f, 0x6e, + 0x75, 0xf2, 0xfa, 0xce, 0x30, 0x70, 0xe7, 0xa8, 0x13, 0xaa, 0x88, 0x34, 0x72, 0xae, + 0x47, 0x7c, 0x47, 0xbc, 0x2e, 0xc2, 0xe5, 0xc6, 0xcd, 0x85, 0x5d, 0x12, 0x25, 0x7c, + 0x54, 0xbd, 0xea, 0xdc, 0x44, 0x3b, 0xe7, 0xd6, 0xb6, 0x7d, 0x11, 0xad, 0xd4, 0x1f, + 0x49, 0xa9, 0xb4, 0xd8, 0x13, 0x8f, 0xd8, 0x7c, 0x0d, 0xee, 0x7f, 0x5f, 0xae, 0x0c, + 0xd8, 0x83, 0x7c, 0x39, 0xdb, 0x19, 0x9e, 0xea, 0x34, 0x48, 0xa9, 0x41, 0x05, 0x1f, + 0x78, 0x5c, 0x1f, 0x8a, 0xd0, 0xb2, 0x65, 0xd8, 0x78, 0x7c, 0x70, 0x1d, 0xe0, 0x5b, + 0xf1, 0xc6, 0x6a, 0x3d, 0x65, 0x94, 0xf5, 0x22, 0x19, 0xcc, 0xb3, 0x1e, 0x05, 0x03, + 0x9c, 0x83, 0x02, 0x2a, 0xa8, 0x61, 0x21, 0x1c, 0x50, 0xc2, 0xf0, 0xcf, 0xb1, 0xbe, + 0x94, 0x45, 0xcd, 0xb9, 0x6d, 0xf0, 0x0a, 0x16, 0x67, 0x57, 0x1a, 0x68, 0xb7, 0xf2, + 0x19, 0x45, 0xb1, 0xfa, 0xef, 0x4e, 0xbc, 0xcf, 0xa1, 0xc5, 0x83, 0xc4, 0x66, 0xb0, + 0xef, 0x58, 0x8a, 0xcd, 0xfd, 0x47, 0x8c, 0x7f, 0x21, 0x22, 0x61, 0x12, 0x8a, 0xf4, + 0x25, 0xa2, 0xe0, 0xa3, 0xa2, 0x7e, 0x17, 0x48, 0x7f, 0xff, 0x08, 0xb9, 0xfb, 0x80, + 0xd8, 0xaa, 0x71, 0x8f, 0xe2, 0x67, 0xda, 0xbc, 0x70, 0xd3, 0x6b, 0x8f, 0x62, 0xe0, + 0xe9, 0x04, 0x33, 0x47, 0x01, 0x4e, 0x02, 0xa2, 0x7a, 0x85, 0x79, 0x97, 0xe1, 0xcf, + 0x3e, 0x72, 0x33, 0xe2, 0x51, 0x3f, 0x83, 0x2e, 0x60, 0x35, 0x91, 0x68, 0xe1, 0x73, + 0xfc, 0x03, 0x07, 0x9e, 0x99, 0x83, 0xa1, 0x34, 0x1d, 0x68, 0xbb, 0x3a, 0x3c, 0x53, + 0x3a, 0x31, 0x84, 0xf4, 0xaa, 0x41, 0x75, 0xa9, 0xfe, 0xc1, 0xf0, 0x1f, 0xe3, 0xf8, + 0xb4, 0xfa, 0xeb, 0xed, 0x30, 0xb7, 0xe7, 0x18, 0x0e, 0x7e, 0xd7, 0xfc, 0x80, 0x7d, + 0x51, 0x0c, 0x06, 0x01, 0x42, 0x8d, 0xd6, 0x96, 0x41, 0xa3, 0x07, 0x29, 0xcd, 0x64, + 0x45, 0xde, 0x66, 0x0f, 0xb1, 0xbe, 0x2f, 0xb9, 0x6e, 0x56, 0xbb, 0x67, 0xb6, 0xef, + 0x88, 0xe0, 0x7d, 0x14, 0xae, 0xda, 0xa0, 0xbd, 0x23, 0x27, 0xe9, 0xd5, 0x27, 0xb7, + 0xe3, 0x30, 0x07, 0xf8, 0xca, 0xb5, 0x10, 0xad, 0xc2, 0x53, 0xca, 0xe6, 0x68, 0x7f, + 0xfd, 0xc9, 0x60, 0x40, 0x30, 0x40, 0x15, 0x9a, 0x7e, 0x98, 0xda, 0xa8, 0xa7, 0x7b, + 0x2a, 0x3f, 0xdf, 0x4f, 0x79, 0xd5, 0xbd, 0xbe, 0x9e, 0x2b, + ], + ock: [ + 0xe6, 0xb7, 0x05, 0x50, 0xe1, 0xd7, 0xa2, 0xbe, 0x73, 0x04, 0x39, 0x64, 0x41, 0xec, + 0x6a, 0xc0, 0x47, 0x45, 0x99, 0xf9, 0xea, 0xd7, 0x55, 0xc2, 0xcf, 0x27, 0x6b, 0x87, + 0x50, 0xc5, 0xcf, 0x2d, + ], + op: [ + 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, + 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, + 0x03, 0x8e, 0x3d, 0xb3, 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, + 0x73, 0xe9, 0x05, 0x99, 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, + 0x89, 0xcc, 0x63, 0x00, 0x06, 0x15, 0xb2, 0x0d, + ], + c_out: [ + 0x02, 0xb1, 0x37, 0x3e, 0xb1, 0x89, 0x56, 0x32, 0x2b, 0x47, 0xa1, 0x70, 0x0d, 0xb7, + 0x43, 0x31, 0x6e, 0xde, 0x46, 0x44, 0xd6, 0x59, 0x3c, 0xd7, 0x94, 0x22, 0xd7, 0x51, + 0x3d, 0x1b, 0x80, 0xe6, 0x85, 0x05, 0xdf, 0xe9, 0xd6, 0x86, 0x2e, 0x79, 0x4e, 0x30, + 0x28, 0x8b, 0xae, 0xa8, 0xb0, 0xbc, 0xb3, 0x8b, 0x35, 0x49, 0x77, 0xaa, 0xee, 0x57, + 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, + 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xeb, 0xd4, 0x80, 0x6d, 0x81, 0x25, 0x49, 0x89, 0xfa, 0xdb, 0xa8, 0xcd, 0x58, 0x96, + 0x7d, 0x6f, 0xd8, 0x73, 0x83, 0xbc, 0x09, 0x38, 0x63, 0xd5, 0xab, 0xfc, 0xdd, 0xd3, + 0x8f, 0x15, 0x39, 0xfa, 0xb7, 0xe5, 0xd4, 0xf0, 0x61, 0x91, 0x67, 0xb8, 0xd4, 0x82, + 0xcb, 0x54, 0x8c, 0xb5, 0x59, 0x83, 0x49, 0x6f, 0x77, 0xd3, 0xdc, 0xaf, 0xf5, 0x6e, + 0x32, 0x41, 0x0b, 0xfe, 0xc1, 0xf2, 0x68, 0x11, + ], + ovk: [ + 0xb2, 0x5f, 0x30, 0x3f, 0x58, 0x15, 0xc4, 0x53, 0x31, 0x24, 0xac, 0xf9, 0xd1, 0x89, + 0x40, 0xe7, 0x75, 0x22, 0xac, 0x5d, 0xc4, 0xb9, 0x57, 0x0a, 0xae, 0x8f, 0x47, 0xb7, + 0xf5, 0x7f, 0xd8, 0x76, + ], + default_d: [ + 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, + ], + default_pk_d: [ + 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, + 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, + 0x67, 0xa8, 0x60, 0x9e, + ], + v: 9624581763228770449, + rseed: [ + 0x4a, 0x95, 0xb2, 0x05, 0x52, 0x6c, 0xfc, 0xb4, 0xc4, 0xe1, 0xcc, 0x95, 0x51, 0x75, + 0xb3, 0xe8, 0xde, 0x1f, 0x5d, 0x81, 0xb1, 0x86, 0x69, 0x69, 0x23, 0x50, 0xaa, 0xa1, + 0xa1, 0xd7, 0x97, 0x61, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x75, 0x82, 0xe5, 0x4d, 0x7a, 0x5b, 0x57, 0xa6, 0x83, 0xb3, 0x2f, 0xb1, 0x09, + 0x80, 0x62, 0xda, 0xd7, 0xb0, 0xc2, 0xeb, 0x51, 0x8f, 0x68, 0x62, 0xe8, 0x3d, 0xb2, + 0x5e, 0x3d, 0xba, 0xf7, 0xae, 0xd5, 0x04, 0xde, 0x93, 0x2a, 0xcb, 0x99, 0xd7, 0x35, + 0x99, 0x2c, 0xe6, 0x2b, 0xae, 0x9e, 0xf8, 0x93, 0xff, 0x6a, 0xcc, 0x0f, 0xfc, 0xf8, + 0xe3, 0x48, 0x3e, 0x14, 0x6b, 0x9d, 0x49, 0xdd, 0x8c, 0x78, 0x35, 0xf4, 0x3a, 0x37, + 0xdc, 0xa0, 0x78, 0x7e, 0x3e, 0xc9, 0xf6, 0x60, 0x52, 0x23, 0xd5, 0xba, 0x7a, 0xe0, + 0xab, 0x90, 0x25, 0xb7, 0x3b, 0xc0, 0x3f, 0x7f, 0xac, 0x36, 0xc0, 0x09, 0xa5, 0x6d, + 0x4d, 0x95, 0xd1, 0xe8, 0x1d, 0x3b, 0x3e, 0xbc, 0xa7, 0xe5, 0x4c, 0xc1, 0xa1, 0x2d, + 0x12, 0x7b, 0x57, 0xc8, 0x13, 0x89, 0x76, 0xe7, 0x91, 0x01, 0x3b, 0x01, 0x5f, 0x06, + 0xa6, 0x24, 0xf5, 0x21, 0xb6, 0xee, 0x04, 0xec, 0x98, 0x08, 0x93, 0xc7, 0xe5, 0xe0, + 0x1a, 0x33, 0x62, 0x03, 0x59, 0x40, 0x94, 0xf8, 0x28, 0x33, 0xd7, 0x44, 0x5f, 0xe2, + 0xd0, 0x91, 0x30, 0xf6, 0x35, 0x11, 0xda, 0x54, 0x83, 0x2d, 0xe9, 0x13, 0x6b, 0x39, + 0xf4, 0x59, 0x9f, 0x5a, 0xa5, 0xdf, 0xbb, 0x45, 0xda, 0x60, 0xcd, 0xce, 0xab, 0x7e, + 0xef, 0xde, 0x89, 0xbe, 0x63, 0xf3, 0xf7, 0xc0, 0xd2, 0x32, 0x48, 0x47, 0xcc, 0xe1, + 0x40, 0x5d, 0xef, 0x7c, 0x46, 0x9b, 0x0e, 0x27, 0x24, 0x94, 0xe5, 0xdf, 0x54, 0xf5, + 0x68, 0x65, 0x6c, 0xb9, 0xc8, 0x81, 0x8d, 0x92, 0xb7, 0x2b, 0x8b, 0xc3, 0x4d, 0xb7, + 0xbb, 0x31, 0x12, 0x48, 0x7e, 0x74, 0x6e, 0xef, 0xe4, 0xe8, 0x08, 0xbb, 0xb2, 0x87, + 0xd9, 0x9b, 0xf0, 0x7d, 0x00, 0xda, 0xbe, 0xde, 0xdc, 0x5e, 0x5f, 0x07, 0x4f, 0xfe, + 0xae, 0x0c, 0xba, 0x7d, 0xa3, 0xa5, 0x16, 0xc1, 0x73, 0xbe, 0x1c, 0x51, 0x33, 0x23, + 0xe1, 0x19, 0xf6, 0x35, 0xe8, 0x20, 0x9a, 0x07, 0x4b, 0x21, 0x6b, 0x70, 0x23, 0xfa, + 0xdc, 0x2d, 0x25, 0x94, 0x9c, 0x90, 0x03, 0x7e, 0x71, 0xe3, 0xe5, 0x50, 0x72, 0x6d, + 0x21, 0x0a, 0x2c, 0x68, 0x83, 0x42, 0xe5, 0x24, 0x40, 0x63, 0x5e, 0x9c, 0xc1, 0x4a, + 0xfe, 0x10, 0x10, 0x26, 0x21, 0xa9, 0xc9, 0xac, 0xcb, 0x78, 0x2e, 0x9e, 0x4a, 0x5f, + 0xa8, 0x7f, 0x0a, 0x95, 0x6f, 0x5b, 0x85, 0x50, 0x99, 0x60, 0x28, 0x5c, 0x22, 0x62, + 0x7c, 0x59, 0x48, 0x3a, 0x5a, 0x4c, 0x28, 0xcc, 0xe4, 0xb1, 0x56, 0xe5, 0x51, 0x40, + 0x6a, 0x7e, 0xe8, 0x35, 0x56, 0x56, 0xa2, 0x1e, 0x43, 0xe3, 0x8c, 0xe1, 0x29, 0xfd, + 0xad, 0xb7, 0x59, 0xed, 0xdf, 0xa0, 0x8f, 0x00, 0xfc, 0x8e, 0x56, 0x7c, 0xef, 0x93, + 0xc6, 0x79, 0x2d, 0x01, 0xdf, 0x05, 0xe6, 0xd5, 0x80, 0xf4, 0xd5, 0xd4, 0x8d, 0xf0, + 0x42, 0x45, 0x1a, 0x33, 0x59, 0x0d, 0x3e, 0x8c, 0xf4, 0x9b, 0x26, 0x27, 0x21, 0x8f, + 0x0c, 0x29, 0x2f, 0xa6, 0x6a, 0xda, 0x94, 0x5f, 0xa5, 0x5b, 0xb2, 0x35, 0x48, 0xe3, + 0x3a, 0x83, 0xa5, 0x62, 0x95, 0x7a, 0x31, 0x49, 0xa9, 0x93, 0xcc, 0x47, 0x23, 0x62, + 0x29, 0x87, 0x36, 0xa8, 0xb7, 0x78, 0xd9, 0x7c, 0xe4, 0x23, 0x01, 0x3d, 0x64, 0xb3, + 0x2c, 0xd1, 0x72, 0xef, 0xa5, 0x51, 0xbf, 0x7f, 0x36, 0x8f, 0x04, 0xbd, 0xae, 0xc6, + 0x09, 0x1a, 0x30, 0x04, 0xa7, 0x57, 0x59, 0x8b, 0x80, 0x1d, 0xcf, 0x67, 0x5c, 0xb8, + 0x3e, 0x43, 0xa5, 0x3a, 0xe8, 0xb2, 0x54, 0xd3, 0x33, 0xbc, 0xda, 0x20, 0xd4, 0x81, + 0x7d, 0x34, 0x77, 0xab, 0xfb, 0xa2, 0x5b, 0xb8, 0x3d, 0xf5, 0x94, 0x9c, 0x12, 0x6f, + 0x14, 0x9b, 0x1d, 0x99, 0x34, 0x1e, 0x4e, 0x6f, + ], + cv_net: [ + 0xd2, 0xf9, 0xad, 0xff, 0x53, 0x1b, 0x65, 0x43, 0x2b, 0xa2, 0xd7, 0xda, 0xa6, 0xd8, + 0x6e, 0x62, 0xe4, 0xed, 0xc7, 0x86, 0xd9, 0xe0, 0xb2, 0x7d, 0x26, 0x62, 0x8b, 0x79, + 0xda, 0x6b, 0x15, 0x14, + ], + rho: [ + 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, + 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, + 0x21, 0x38, 0xab, 0x29, + ], + cmx: [ + 0x18, 0xfc, 0xbd, 0x40, 0xac, 0xf1, 0xa7, 0xf4, 0xd6, 0x09, 0x87, 0x9a, 0x5f, 0x5e, + 0x3b, 0x39, 0x70, 0x09, 0x4f, 0xf8, 0xbe, 0x84, 0x18, 0x60, 0x70, 0x16, 0xc6, 0xa6, + 0x97, 0xf8, 0x9c, 0x20, + ], + esk: [ + 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, 0x6b, 0x8d, 0x6f, 0xea, + 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, 0xd5, 0xcb, 0xab, 0x1a, + 0xcc, 0xd5, 0x4e, 0x3a, + ], + ephemeral_key: [ + 0xcf, 0xe0, 0x3e, 0xb2, 0xd3, 0x36, 0x76, 0xb7, 0x73, 0x83, 0x7d, 0xa8, 0x39, 0x17, + 0x2d, 0x33, 0x33, 0x31, 0x88, 0xc9, 0xdf, 0xef, 0x05, 0xc8, 0x32, 0xa2, 0x5c, 0x86, + 0xd3, 0xbf, 0x0e, 0x8f, + ], + shared_secret: [ + 0xd2, 0xc2, 0x88, 0x9e, 0x03, 0x7e, 0xac, 0x60, 0x60, 0x58, 0x68, 0x2b, 0xaa, 0x38, + 0x86, 0xa4, 0xc2, 0xdd, 0x44, 0xea, 0xdf, 0x8b, 0x2c, 0xe4, 0x39, 0x95, 0xde, 0xd7, + 0x61, 0xfd, 0xaf, 0xb5, + ], + k_enc: [ + 0xfe, 0xe3, 0xe3, 0xb5, 0xfd, 0x6c, 0xd8, 0x54, 0x44, 0x2b, 0x2a, 0xc2, 0x97, 0x70, + 0xfb, 0x0e, 0x39, 0x32, 0xf4, 0x71, 0x52, 0x43, 0x26, 0xda, 0x4a, 0x57, 0xc2, 0x56, + 0x18, 0x06, 0x9e, 0x99, + ], + p_enc: [ + 0x03, 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, 0x91, 0x20, + 0xf4, 0xd4, 0x1e, 0x62, 0x91, 0x85, 0x4a, 0x95, 0xb2, 0x05, 0x52, 0x6c, 0xfc, 0xb4, + 0xc4, 0xe1, 0xcc, 0x95, 0x51, 0x75, 0xb3, 0xe8, 0xde, 0x1f, 0x5d, 0x81, 0xb1, 0x86, + 0x69, 0x69, 0x23, 0x50, 0xaa, 0xa1, 0xa1, 0xd7, 0x97, 0x61, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x75, 0x82, 0xe5, 0x4d, 0x7a, 0x5b, 0x57, 0xa6, 0x83, 0xb3, 0x2f, 0xb1, 0x09, + 0x80, 0x62, 0xda, 0xd7, 0xb0, 0xc2, 0xeb, 0x51, 0x8f, 0x68, 0x62, 0xe8, 0x3d, 0xb2, + 0x5e, 0x3d, 0xba, 0xf7, 0xae, 0xd5, 0x04, 0xde, 0x93, 0x2a, 0xcb, 0x99, 0xd7, 0x35, + 0x99, 0x2c, 0xe6, 0x2b, 0xae, 0x9e, 0xf8, 0x93, 0xff, 0x6a, 0xcc, 0x0f, 0xfc, 0xf8, + 0xe3, 0x48, 0x3e, 0x14, 0x6b, 0x9d, 0x49, 0xdd, 0x8c, 0x78, 0x35, 0xf4, 0x3a, 0x37, + 0xdc, 0xa0, 0x78, 0x7e, 0x3e, 0xc9, 0xf6, 0x60, 0x52, 0x23, 0xd5, 0xba, 0x7a, 0xe0, + 0xab, 0x90, 0x25, 0xb7, 0x3b, 0xc0, 0x3f, 0x7f, 0xac, 0x36, 0xc0, 0x09, 0xa5, 0x6d, + 0x4d, 0x95, 0xd1, 0xe8, 0x1d, 0x3b, 0x3e, 0xbc, 0xa7, 0xe5, 0x4c, 0xc1, 0xa1, 0x2d, + 0x12, 0x7b, 0x57, 0xc8, 0x13, 0x89, 0x76, 0xe7, 0x91, 0x01, 0x3b, 0x01, 0x5f, 0x06, + 0xa6, 0x24, 0xf5, 0x21, 0xb6, 0xee, 0x04, 0xec, 0x98, 0x08, 0x93, 0xc7, 0xe5, 0xe0, + 0x1a, 0x33, 0x62, 0x03, 0x59, 0x40, 0x94, 0xf8, 0x28, 0x33, 0xd7, 0x44, 0x5f, 0xe2, + 0xd0, 0x91, 0x30, 0xf6, 0x35, 0x11, 0xda, 0x54, 0x83, 0x2d, 0xe9, 0x13, 0x6b, 0x39, + 0xf4, 0x59, 0x9f, 0x5a, 0xa5, 0xdf, 0xbb, 0x45, 0xda, 0x60, 0xcd, 0xce, 0xab, 0x7e, + 0xef, 0xde, 0x89, 0xbe, 0x63, 0xf3, 0xf7, 0xc0, 0xd2, 0x32, 0x48, 0x47, 0xcc, 0xe1, + 0x40, 0x5d, 0xef, 0x7c, 0x46, 0x9b, 0x0e, 0x27, 0x24, 0x94, 0xe5, 0xdf, 0x54, 0xf5, + 0x68, 0x65, 0x6c, 0xb9, 0xc8, 0x81, 0x8d, 0x92, 0xb7, 0x2b, 0x8b, 0xc3, 0x4d, 0xb7, + 0xbb, 0x31, 0x12, 0x48, 0x7e, 0x74, 0x6e, 0xef, 0xe4, 0xe8, 0x08, 0xbb, 0xb2, 0x87, + 0xd9, 0x9b, 0xf0, 0x7d, 0x00, 0xda, 0xbe, 0xde, 0xdc, 0x5e, 0x5f, 0x07, 0x4f, 0xfe, + 0xae, 0x0c, 0xba, 0x7d, 0xa3, 0xa5, 0x16, 0xc1, 0x73, 0xbe, 0x1c, 0x51, 0x33, 0x23, + 0xe1, 0x19, 0xf6, 0x35, 0xe8, 0x20, 0x9a, 0x07, 0x4b, 0x21, 0x6b, 0x70, 0x23, 0xfa, + 0xdc, 0x2d, 0x25, 0x94, 0x9c, 0x90, 0x03, 0x7e, 0x71, 0xe3, 0xe5, 0x50, 0x72, 0x6d, + 0x21, 0x0a, 0x2c, 0x68, 0x83, 0x42, 0xe5, 0x24, 0x40, 0x63, 0x5e, 0x9c, 0xc1, 0x4a, + 0xfe, 0x10, 0x10, 0x26, 0x21, 0xa9, 0xc9, 0xac, 0xcb, 0x78, 0x2e, 0x9e, 0x4a, 0x5f, + 0xa8, 0x7f, 0x0a, 0x95, 0x6f, 0x5b, 0x85, 0x50, 0x99, 0x60, 0x28, 0x5c, 0x22, 0x62, + 0x7c, 0x59, 0x48, 0x3a, 0x5a, 0x4c, 0x28, 0xcc, 0xe4, 0xb1, 0x56, 0xe5, 0x51, 0x40, + 0x6a, 0x7e, 0xe8, 0x35, 0x56, 0x56, 0xa2, 0x1e, 0x43, 0xe3, 0x8c, 0xe1, 0x29, 0xfd, + 0xad, 0xb7, 0x59, 0xed, 0xdf, 0xa0, 0x8f, 0x00, 0xfc, 0x8e, 0x56, 0x7c, 0xef, 0x93, + 0xc6, 0x79, 0x2d, 0x01, 0xdf, 0x05, 0xe6, 0xd5, 0x80, 0xf4, 0xd5, 0xd4, 0x8d, 0xf0, + 0x42, 0x45, 0x1a, 0x33, 0x59, 0x0d, 0x3e, 0x8c, 0xf4, 0x9b, 0x26, 0x27, 0x21, 0x8f, + 0x0c, 0x29, 0x2f, 0xa6, 0x6a, 0xda, 0x94, 0x5f, 0xa5, 0x5b, 0xb2, 0x35, 0x48, 0xe3, + 0x3a, 0x83, 0xa5, 0x62, 0x95, 0x7a, 0x31, 0x49, 0xa9, 0x93, 0xcc, 0x47, 0x23, 0x62, + 0x29, 0x87, 0x36, 0xa8, 0xb7, 0x78, 0xd9, 0x7c, 0xe4, 0x23, 0x01, 0x3d, 0x64, 0xb3, + 0x2c, 0xd1, 0x72, 0xef, 0xa5, 0x51, 0xbf, 0x7f, 0x36, 0x8f, 0x04, 0xbd, 0xae, 0xc6, + 0x09, 0x1a, 0x30, 0x04, 0xa7, 0x57, 0x59, 0x8b, 0x80, 0x1d, 0xcf, 0x67, 0x5c, 0xb8, + 0x3e, 0x43, 0xa5, 0x3a, 0xe8, 0xb2, 0x54, 0xd3, 0x33, 0xbc, 0xda, 0x20, 0xd4, 0x81, + 0x7d, 0x34, 0x77, 0xab, 0xfb, 0xa2, 0x5b, 0xb8, 0x3d, 0xf5, 0x94, 0x9c, 0x12, 0x6f, + 0x14, 0x9b, 0x1d, 0x99, 0x34, 0x1e, 0x4e, 0x6f, + ], + c_enc: [ + 0xbf, 0x1d, 0xff, 0xd3, 0x37, 0x0c, 0x67, 0x56, 0x69, 0xcc, 0x9a, 0xe1, 0xd0, 0x30, + 0x2d, 0x7f, 0x90, 0x6d, 0x25, 0x23, 0x09, 0x3c, 0x24, 0xf4, 0x25, 0x7a, 0x83, 0xbc, + 0x4f, 0x36, 0x62, 0x3a, 0x08, 0x2c, 0xe6, 0xeb, 0x45, 0x21, 0x95, 0x71, 0x91, 0xd5, + 0x7e, 0x14, 0x11, 0xed, 0xe7, 0x1d, 0x44, 0xb5, 0x6c, 0x57, 0x53, 0x14, 0xfa, 0x95, + 0x27, 0xae, 0xc5, 0xaf, 0xd5, 0x06, 0xc2, 0x42, 0xac, 0xdc, 0xa9, 0xd3, 0xc9, 0xa5, + 0x53, 0xcf, 0xef, 0x49, 0x9e, 0x87, 0x30, 0xf7, 0x55, 0x6a, 0xd0, 0xba, 0xc0, 0xff, + 0xb6, 0xd0, 0x8e, 0x7c, 0xac, 0x9b, 0x6e, 0x71, 0xf6, 0x6d, 0x19, 0x17, 0xfc, 0x52, + 0xdc, 0x91, 0x33, 0xae, 0x12, 0x4a, 0x40, 0x9d, 0xda, 0x38, 0x75, 0xcb, 0xae, 0xb5, + 0xf2, 0x96, 0xd5, 0x3a, 0x9f, 0x17, 0xb0, 0x28, 0x7d, 0xaa, 0x31, 0xd6, 0x89, 0xa7, + 0xde, 0xaf, 0x05, 0x2d, 0xab, 0xa6, 0xd0, 0xe8, 0x87, 0xcd, 0x1a, 0x3a, 0x6d, 0xd4, + 0x67, 0x17, 0xe5, 0xda, 0x63, 0xe5, 0x59, 0x67, 0x95, 0xf8, 0xe1, 0xdb, 0x6a, 0x45, + 0x8e, 0xab, 0x64, 0xa7, 0xd0, 0x68, 0xe1, 0x67, 0xef, 0xf1, 0x9b, 0xf2, 0x3b, 0x1b, + 0xe7, 0x72, 0x87, 0xf9, 0x0e, 0xe5, 0xcd, 0x34, 0x13, 0x85, 0xad, 0xc9, 0xda, 0xb7, + 0xd0, 0xef, 0x05, 0xc3, 0x61, 0x7d, 0x9f, 0x4b, 0xd7, 0xa2, 0x78, 0xb0, 0xa7, 0xc7, + 0x57, 0x73, 0x57, 0x89, 0xd3, 0xff, 0x0e, 0x91, 0xfb, 0xe1, 0x31, 0x78, 0xae, 0x76, + 0xeb, 0x91, 0xd8, 0x35, 0xd0, 0x65, 0xd7, 0xb3, 0x83, 0x18, 0xf5, 0x64, 0xb7, 0x69, + 0xe8, 0xd9, 0x68, 0x97, 0xb7, 0xab, 0xc8, 0xaa, 0xf3, 0x41, 0x7a, 0x49, 0xe6, 0x8f, + 0x35, 0xcd, 0x7f, 0x45, 0x1d, 0x99, 0x4a, 0xd8, 0x7d, 0xd4, 0xbc, 0x55, 0xc4, 0x5d, + 0xb3, 0x21, 0xf8, 0x49, 0xce, 0xb9, 0x54, 0x30, 0xe8, 0xe6, 0xe2, 0xe4, 0x8c, 0x3b, + 0xbf, 0x8f, 0x7a, 0x1a, 0xaf, 0x1c, 0x52, 0xf2, 0x3f, 0xca, 0x52, 0xca, 0xcc, 0xfb, + 0x26, 0xa4, 0x58, 0x40, 0x42, 0x73, 0xe5, 0x69, 0x7f, 0xcc, 0xf5, 0xa5, 0x9a, 0x61, + 0xb3, 0xea, 0xd6, 0x6a, 0x03, 0xfd, 0xaf, 0x31, 0xb2, 0xeb, 0x2d, 0x32, 0xa9, 0x02, + 0x40, 0x50, 0x98, 0xa7, 0x67, 0xbb, 0x6d, 0x30, 0xbf, 0x1b, 0x48, 0x7d, 0xcc, 0x5d, + 0x38, 0xfb, 0x9d, 0x54, 0x9c, 0xc5, 0x21, 0x30, 0x75, 0xe1, 0x2d, 0x04, 0x34, 0x71, + 0xc3, 0xab, 0x03, 0x5b, 0x1d, 0xff, 0xd6, 0xe8, 0xaa, 0x61, 0x99, 0xc8, 0x0c, 0xe9, + 0x9d, 0x66, 0xa5, 0x07, 0x3b, 0x91, 0x73, 0xc3, 0x25, 0x4b, 0xd2, 0x4a, 0xf5, 0x9c, + 0x96, 0x27, 0xb9, 0x8c, 0xdb, 0x06, 0x0f, 0x07, 0x34, 0x04, 0xb4, 0xfb, 0xf6, 0x5b, + 0xdd, 0x1a, 0xcb, 0x1c, 0xb6, 0xc0, 0xa4, 0xc1, 0x8d, 0x55, 0x4f, 0x7a, 0x4c, 0x5a, + 0x1a, 0x93, 0x94, 0xb3, 0x85, 0xe8, 0xdf, 0xf4, 0xbb, 0xd1, 0x4a, 0x1a, 0x20, 0x1f, + 0xa8, 0x33, 0x20, 0x37, 0x34, 0x5a, 0x62, 0x29, 0x3d, 0x8c, 0xfc, 0x5c, 0xd9, 0x4c, + 0x0c, 0x21, 0xa9, 0xc8, 0x06, 0x52, 0x1c, 0xe2, 0x28, 0x01, 0xdb, 0xa5, 0xb5, 0xa3, + 0xb3, 0xf6, 0x9a, 0xbd, 0x01, 0xd4, 0x4c, 0xcb, 0xc2, 0x3b, 0x06, 0x3f, 0x41, 0x2c, + 0xa1, 0xa9, 0xd4, 0xfd, 0x17, 0xda, 0xbe, 0x54, 0x9f, 0x8b, 0x89, 0x11, 0x21, 0xe0, + 0x79, 0xb8, 0x2b, 0x5e, 0x6e, 0xa7, 0x43, 0xe6, 0x37, 0xb9, 0xd2, 0xd1, 0x1e, 0x86, + 0xa0, 0xc2, 0x76, 0x9a, 0xe3, 0xdc, 0xde, 0xcd, 0x74, 0xcb, 0xec, 0xe5, 0x6e, 0x52, + 0x74, 0xca, 0x1f, 0x23, 0x25, 0xc3, 0x93, 0xe5, 0xef, 0x18, 0xef, 0x99, 0x03, 0x04, + 0x22, 0x39, 0xe2, 0x5c, 0x2f, 0x10, 0x62, 0x21, 0x2a, 0x04, 0x67, 0x0d, 0xd3, 0xea, + 0xd5, 0xa9, 0x55, 0xf7, 0x8b, 0x6a, 0x00, 0xdd, 0x9f, 0x12, 0xc1, 0xdc, 0x0b, 0x3a, + 0x58, 0xaf, 0x82, 0x3b, 0x78, 0x73, 0x22, 0xaa, 0x8f, 0x2e, 0xde, 0xc8, 0x48, 0x41, + 0x99, 0x15, 0xb0, 0x6b, 0x60, 0xd9, 0x5a, 0xf2, 0xd4, 0x41, 0xba, 0xd4, 0x35, 0x7b, + 0xed, 0x8a, 0xdb, 0xf0, 0xd0, 0x5f, 0xc6, 0x37, 0xcb, 0xaa, 0xff, 0x15, 0x58, 0x26, + 0x8c, 0x9c, 0x92, 0x41, 0x9e, 0x97, 0x51, 0xc4, 0x18, 0xa6, 0x7a, 0xe3, 0x86, 0x29, + 0xf0, 0xcd, 0xf7, 0x7d, 0xaa, 0xd6, 0xf0, 0xac, 0xc9, 0x32, 0x98, 0x51, 0xcd, 0x17, + 0xda, 0x6a, 0xd7, 0xbb, 0x73, 0xf3, 0x5d, 0x23, 0xba, 0xc7, + ], + ock: [ + 0xeb, 0x3e, 0xd9, 0xfc, 0xb3, 0xaa, 0x91, 0xc4, 0xf5, 0xec, 0xfd, 0x43, 0xdb, 0xda, + 0x40, 0x33, 0x06, 0x93, 0xc3, 0xa6, 0x56, 0x75, 0x45, 0xfd, 0x23, 0x6a, 0xf1, 0x90, + 0x8e, 0x29, 0x42, 0xa3, + ], + op: [ + 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, + 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, + 0x67, 0xa8, 0x60, 0x9e, 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, + 0x6b, 0x8d, 0x6f, 0xea, 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, + 0xd5, 0xcb, 0xab, 0x1a, 0xcc, 0xd5, 0x4e, 0x3a, + ], + c_out: [ + 0x60, 0xf3, 0xe8, 0x94, 0xe3, 0x86, 0x4e, 0xfb, 0x48, 0xcc, 0xae, 0x50, 0xe1, 0x0d, + 0xa7, 0x73, 0xdc, 0xcf, 0x85, 0x62, 0x45, 0x5d, 0x1b, 0x73, 0x1a, 0xad, 0x44, 0xe1, + 0x5e, 0x3e, 0x40, 0x18, 0x31, 0xce, 0x6f, 0x92, 0xf4, 0x53, 0x2d, 0x90, 0x83, 0x92, + 0x59, 0xce, 0x9c, 0xb1, 0x44, 0x62, 0x1f, 0x12, 0x01, 0x77, 0x8f, 0x61, 0x5d, 0x09, + 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, + 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xc3, 0x7c, 0x7d, 0xbb, 0xe5, 0x51, 0xd9, 0xd3, 0xb1, 0xa4, 0x96, 0x88, 0x7d, 0xb2, + 0xe8, 0x42, 0xdc, 0x94, 0x52, 0x01, 0xf4, 0x08, 0x10, 0xdf, 0x4d, 0x76, 0x39, 0x32, + 0xed, 0x5c, 0x76, 0x39, 0x8b, 0x35, 0x73, 0xfe, 0x23, 0xf1, 0xe8, 0xb7, 0xe7, 0x9f, + 0x1c, 0x16, 0x95, 0xc0, 0x97, 0xc1, 0x24, 0xff, 0x1f, 0x7d, 0x6e, 0x61, 0xf2, 0xc5, + 0x8f, 0x14, 0x39, 0xa7, 0x56, 0x96, 0x9d, 0x19, + ], + ovk: [ + 0xa6, 0x68, 0xa0, 0xae, 0x2b, 0xb9, 0x34, 0xc8, 0x2c, 0x41, 0x42, 0xda, 0x69, 0xd1, + 0x2c, 0xa7, 0xde, 0x9a, 0x7d, 0xf7, 0x06, 0x40, 0x0e, 0xc7, 0x98, 0x78, 0xd8, 0x68, + 0xe1, 0x7e, 0x8f, 0x71, + ], + default_d: [ + 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, + ], + default_pk_d: [ + 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, + 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, + 0x6b, 0x80, 0xbb, 0xb7, + ], + v: 11137853725062838288, + rseed: [ + 0x25, 0x37, 0xb8, 0x71, 0xb4, 0x29, 0x4a, 0x65, 0xd3, 0xe0, 0x55, 0xff, 0x71, 0x8d, + 0xd9, 0xdc, 0x8c, 0x75, 0xe7, 0xe5, 0xb2, 0xef, 0xe4, 0x42, 0x63, 0x73, 0x71, 0xb7, + 0xc4, 0x8f, 0x6e, 0xe9, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x9e, 0x3e, 0xa3, 0x8a, 0x4b, 0x0f, 0x2f, 0x67, 0xfc, 0x2b, 0x90, 0x8c, 0xda, + 0x65, 0x7e, 0xae, 0x75, 0x4e, 0x03, 0x7e, 0x26, 0x2e, 0x9a, 0x9f, 0x9b, 0xd7, 0xec, + 0x42, 0x67, 0xed, 0x8e, 0x96, 0x93, 0x0e, 0x10, 0x84, 0x78, 0x3c, 0x37, 0xd6, 0xf9, + 0xdd, 0x15, 0xfd, 0x29, 0xf4, 0xcc, 0x47, 0x7e, 0x66, 0xf1, 0x30, 0xd6, 0x30, 0x43, + 0x0d, 0xcc, 0x01, 0x04, 0x89, 0x9b, 0x4f, 0x9f, 0x46, 0xeb, 0x09, 0x0e, 0xf7, 0xfc, + 0x90, 0xb4, 0x79, 0xab, 0xf6, 0x1f, 0x93, 0x95, 0x5e, 0xe0, 0x0e, 0x6a, 0x18, 0x48, + 0xf1, 0xab, 0x14, 0xad, 0x33, 0x4f, 0x2b, 0x68, 0x03, 0x58, 0x08, 0xcd, 0xf1, 0xbb, + 0x9e, 0x9d, 0x9a, 0x81, 0x6b, 0xaf, 0x72, 0x8a, 0x95, 0x5b, 0x96, 0x0b, 0x77, 0x01, + 0xfa, 0x62, 0x66, 0x87, 0xdc, 0x3c, 0x9c, 0xba, 0x64, 0x63, 0x37, 0xb5, 0x3e, 0x29, + 0x81, 0x6e, 0x94, 0x82, 0xdd, 0xf5, 0x57, 0x8a, 0x87, 0x68, 0xaa, 0xe4, 0x77, 0xfc, + 0xe4, 0x10, 0xac, 0x2d, 0x5d, 0xe6, 0x09, 0x58, 0x61, 0xc1, 0x11, 0xd7, 0xfe, 0xb3, + 0xe6, 0xbb, 0x4f, 0xbb, 0x5a, 0x54, 0x95, 0x54, 0x95, 0x97, 0x27, 0x98, 0x35, 0x0a, + 0x25, 0x3f, 0x05, 0xf6, 0x6c, 0x2e, 0xcf, 0xcb, 0xc0, 0xed, 0x43, 0xf5, 0xec, 0x2e, + 0x6d, 0x8d, 0xba, 0x15, 0xa5, 0x12, 0x54, 0xd9, 0x7b, 0x18, 0x21, 0x10, 0x7c, 0x07, + 0xdd, 0x9a, 0x16, 0xef, 0x84, 0x06, 0xf9, 0x43, 0xe2, 0x82, 0xb9, 0x5d, 0x4b, 0x36, + 0x25, 0x30, 0xc9, 0x13, 0xd6, 0xba, 0x42, 0x1d, 0xf6, 0x02, 0x7d, 0xe5, 0xaf, 0x1e, + 0x47, 0x45, 0xd5, 0x86, 0x81, 0x06, 0x95, 0x4b, 0xe6, 0xc1, 0x96, 0x27, 0x80, 0xa2, + 0x94, 0x10, 0x72, 0xe9, 0x51, 0x31, 0xb1, 0x67, 0x9d, 0xf0, 0x63, 0x76, 0x25, 0x04, + 0x2c, 0x37, 0xd4, 0x8f, 0xfb, 0x15, 0x2e, 0x5e, 0xbc, 0x18, 0x5c, 0x8a, 0x2b, 0x7d, + 0x43, 0x85, 0xf1, 0xc9, 0x5a, 0xf9, 0x37, 0xdf, 0x78, 0xdf, 0xd8, 0x75, 0x7f, 0xab, + 0x43, 0x49, 0x68, 0xb0, 0xb5, 0x7c, 0x66, 0x57, 0x44, 0x68, 0xf1, 0x60, 0xb4, 0x47, + 0xac, 0x82, 0x21, 0xe5, 0x06, 0x06, 0x76, 0xa8, 0x42, 0xa1, 0xc6, 0xb7, 0x17, 0x2d, + 0xd3, 0x34, 0x0f, 0x76, 0x40, 0x70, 0xab, 0x1f, 0xe0, 0x91, 0xc5, 0xc7, 0x4c, 0x95, + 0xa5, 0xdc, 0x04, 0x33, 0x90, 0x72, 0x3a, 0x4c, 0x12, 0x7d, 0xa1, 0x4c, 0xdd, 0xe1, + 0xdc, 0x26, 0x75, 0xa6, 0x23, 0x40, 0xb3, 0xe6, 0xaf, 0xd0, 0x52, 0x2a, 0x31, 0xde, + 0x26, 0xe7, 0xd1, 0xec, 0x3a, 0x9c, 0x8a, 0x09, 0x1f, 0xfd, 0xc7, 0x5b, 0x7e, 0xcf, + 0xdc, 0x7c, 0x12, 0x99, 0x5a, 0x5e, 0x37, 0xce, 0x34, 0x88, 0xbd, 0x29, 0xf8, 0x62, + 0x9d, 0x68, 0xf6, 0x96, 0x49, 0x24, 0x48, 0xdd, 0x52, 0x66, 0x97, 0x47, 0x6d, 0xc0, + 0x61, 0x34, 0x6e, 0xbe, 0x3f, 0x67, 0x72, 0x17, 0xff, 0x9c, 0x60, 0xef, 0xce, 0x94, + 0x3a, 0xf2, 0x8d, 0xfd, 0x3f, 0x9e, 0x59, 0x69, 0x25, 0x98, 0xa6, 0x04, 0x7c, 0x23, + 0xc4, 0xc0, 0x14, 0x00, 0xf1, 0xab, 0x57, 0x30, 0xea, 0xc0, 0xae, 0x8d, 0x58, 0x43, + 0xd5, 0x05, 0x1c, 0x37, 0x62, 0x40, 0x17, 0x2a, 0xf2, 0x18, 0xd7, 0xa1, 0xec, 0xfe, + 0x65, 0xb4, 0xf7, 0x51, 0x00, 0x63, 0x89, 0x83, 0xc1, 0x4d, 0xe4, 0x97, 0x47, 0x55, + 0xda, 0xde, 0x80, 0x18, 0xc9, 0xb8, 0xf4, 0x54, 0x3f, 0xb0, 0x95, 0x96, 0x15, 0x13, + 0xe6, 0x7c, 0x61, 0xdb, 0xc5, 0x9c, 0x60, 0x7f, 0x9b, 0x51, 0xf8, 0xd0, 0x9b, 0xdc, + 0xad, 0x28, 0xbc, 0xfb, 0x9e, 0x5d, 0x27, 0x44, 0xea, 0x88, 0x48, 0xb2, 0x62, 0x3a, + 0xc0, 0x7f, 0x8e, 0xf6, 0x1a, 0x81, 0xa3, 0x59, + ], + cv_net: [ + 0xb2, 0x7f, 0x48, 0x59, 0x15, 0x0d, 0x48, 0x45, 0xab, 0x57, 0x78, 0x82, 0x61, 0x50, + 0x0a, 0x12, 0x01, 0x2d, 0x63, 0xc0, 0x09, 0xc6, 0x77, 0x44, 0xba, 0xe0, 0xd5, 0x83, + 0x88, 0xff, 0xee, 0x2f, + ], + rho: [ + 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, + 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, + 0x92, 0xd7, 0xa0, 0x24, + ], + cmx: [ + 0x1d, 0x51, 0xea, 0x92, 0xfa, 0x43, 0x55, 0x0a, 0x0e, 0xdd, 0xea, 0x23, 0x6e, 0x17, + 0xa0, 0x16, 0x93, 0xc2, 0x2d, 0x8d, 0xd8, 0x1c, 0x9c, 0x9e, 0xc8, 0x76, 0xa2, 0x4e, + 0x67, 0xd4, 0x93, 0x0b, + ], + esk: [ + 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, 0x14, 0xb0, 0xdf, 0x85, + 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, 0xc4, 0x84, 0xa9, 0xf4, + 0xc7, 0xda, 0x74, 0x36, + ], + ephemeral_key: [ + 0x8f, 0xbe, 0xb6, 0xb3, 0x03, 0x8e, 0x69, 0x49, 0x91, 0x6a, 0x2c, 0x06, 0x0e, 0xf9, + 0xa4, 0xb1, 0xfe, 0xf1, 0x3a, 0xce, 0x2f, 0xee, 0x00, 0x25, 0xda, 0x32, 0xc3, 0x6d, + 0x23, 0x1a, 0x61, 0x34, + ], + shared_secret: [ + 0x67, 0xd6, 0x8a, 0x5a, 0x05, 0x93, 0xfd, 0x16, 0x7d, 0x38, 0x08, 0x2e, 0x49, 0xd2, + 0x30, 0x30, 0x86, 0xe5, 0x5a, 0x43, 0xc1, 0x24, 0xd5, 0xaa, 0xa8, 0x20, 0xab, 0x0c, + 0x3f, 0x5c, 0xc5, 0x37, + ], + k_enc: [ + 0x6b, 0x8d, 0x83, 0xf2, 0xf1, 0xfd, 0x1e, 0xad, 0x7d, 0x45, 0x42, 0xb3, 0x63, 0x09, + 0x34, 0x07, 0xc5, 0x0a, 0x20, 0xed, 0x7f, 0x0e, 0x8c, 0xf2, 0xdb, 0x53, 0x6d, 0xb1, + 0xbe, 0x25, 0xe9, 0x8d, + ], + p_enc: [ + 0x03, 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, 0x10, 0xb8, + 0xa1, 0xba, 0xf3, 0x9a, 0x91, 0x9a, 0x25, 0x37, 0xb8, 0x71, 0xb4, 0x29, 0x4a, 0x65, + 0xd3, 0xe0, 0x55, 0xff, 0x71, 0x8d, 0xd9, 0xdc, 0x8c, 0x75, 0xe7, 0xe5, 0xb2, 0xef, + 0xe4, 0x42, 0x63, 0x73, 0x71, 0xb7, 0xc4, 0x8f, 0x6e, 0xe9, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x9e, 0x3e, 0xa3, 0x8a, 0x4b, 0x0f, 0x2f, 0x67, 0xfc, 0x2b, 0x90, 0x8c, 0xda, + 0x65, 0x7e, 0xae, 0x75, 0x4e, 0x03, 0x7e, 0x26, 0x2e, 0x9a, 0x9f, 0x9b, 0xd7, 0xec, + 0x42, 0x67, 0xed, 0x8e, 0x96, 0x93, 0x0e, 0x10, 0x84, 0x78, 0x3c, 0x37, 0xd6, 0xf9, + 0xdd, 0x15, 0xfd, 0x29, 0xf4, 0xcc, 0x47, 0x7e, 0x66, 0xf1, 0x30, 0xd6, 0x30, 0x43, + 0x0d, 0xcc, 0x01, 0x04, 0x89, 0x9b, 0x4f, 0x9f, 0x46, 0xeb, 0x09, 0x0e, 0xf7, 0xfc, + 0x90, 0xb4, 0x79, 0xab, 0xf6, 0x1f, 0x93, 0x95, 0x5e, 0xe0, 0x0e, 0x6a, 0x18, 0x48, + 0xf1, 0xab, 0x14, 0xad, 0x33, 0x4f, 0x2b, 0x68, 0x03, 0x58, 0x08, 0xcd, 0xf1, 0xbb, + 0x9e, 0x9d, 0x9a, 0x81, 0x6b, 0xaf, 0x72, 0x8a, 0x95, 0x5b, 0x96, 0x0b, 0x77, 0x01, + 0xfa, 0x62, 0x66, 0x87, 0xdc, 0x3c, 0x9c, 0xba, 0x64, 0x63, 0x37, 0xb5, 0x3e, 0x29, + 0x81, 0x6e, 0x94, 0x82, 0xdd, 0xf5, 0x57, 0x8a, 0x87, 0x68, 0xaa, 0xe4, 0x77, 0xfc, + 0xe4, 0x10, 0xac, 0x2d, 0x5d, 0xe6, 0x09, 0x58, 0x61, 0xc1, 0x11, 0xd7, 0xfe, 0xb3, + 0xe6, 0xbb, 0x4f, 0xbb, 0x5a, 0x54, 0x95, 0x54, 0x95, 0x97, 0x27, 0x98, 0x35, 0x0a, + 0x25, 0x3f, 0x05, 0xf6, 0x6c, 0x2e, 0xcf, 0xcb, 0xc0, 0xed, 0x43, 0xf5, 0xec, 0x2e, + 0x6d, 0x8d, 0xba, 0x15, 0xa5, 0x12, 0x54, 0xd9, 0x7b, 0x18, 0x21, 0x10, 0x7c, 0x07, + 0xdd, 0x9a, 0x16, 0xef, 0x84, 0x06, 0xf9, 0x43, 0xe2, 0x82, 0xb9, 0x5d, 0x4b, 0x36, + 0x25, 0x30, 0xc9, 0x13, 0xd6, 0xba, 0x42, 0x1d, 0xf6, 0x02, 0x7d, 0xe5, 0xaf, 0x1e, + 0x47, 0x45, 0xd5, 0x86, 0x81, 0x06, 0x95, 0x4b, 0xe6, 0xc1, 0x96, 0x27, 0x80, 0xa2, + 0x94, 0x10, 0x72, 0xe9, 0x51, 0x31, 0xb1, 0x67, 0x9d, 0xf0, 0x63, 0x76, 0x25, 0x04, + 0x2c, 0x37, 0xd4, 0x8f, 0xfb, 0x15, 0x2e, 0x5e, 0xbc, 0x18, 0x5c, 0x8a, 0x2b, 0x7d, + 0x43, 0x85, 0xf1, 0xc9, 0x5a, 0xf9, 0x37, 0xdf, 0x78, 0xdf, 0xd8, 0x75, 0x7f, 0xab, + 0x43, 0x49, 0x68, 0xb0, 0xb5, 0x7c, 0x66, 0x57, 0x44, 0x68, 0xf1, 0x60, 0xb4, 0x47, + 0xac, 0x82, 0x21, 0xe5, 0x06, 0x06, 0x76, 0xa8, 0x42, 0xa1, 0xc6, 0xb7, 0x17, 0x2d, + 0xd3, 0x34, 0x0f, 0x76, 0x40, 0x70, 0xab, 0x1f, 0xe0, 0x91, 0xc5, 0xc7, 0x4c, 0x95, + 0xa5, 0xdc, 0x04, 0x33, 0x90, 0x72, 0x3a, 0x4c, 0x12, 0x7d, 0xa1, 0x4c, 0xdd, 0xe1, + 0xdc, 0x26, 0x75, 0xa6, 0x23, 0x40, 0xb3, 0xe6, 0xaf, 0xd0, 0x52, 0x2a, 0x31, 0xde, + 0x26, 0xe7, 0xd1, 0xec, 0x3a, 0x9c, 0x8a, 0x09, 0x1f, 0xfd, 0xc7, 0x5b, 0x7e, 0xcf, + 0xdc, 0x7c, 0x12, 0x99, 0x5a, 0x5e, 0x37, 0xce, 0x34, 0x88, 0xbd, 0x29, 0xf8, 0x62, + 0x9d, 0x68, 0xf6, 0x96, 0x49, 0x24, 0x48, 0xdd, 0x52, 0x66, 0x97, 0x47, 0x6d, 0xc0, + 0x61, 0x34, 0x6e, 0xbe, 0x3f, 0x67, 0x72, 0x17, 0xff, 0x9c, 0x60, 0xef, 0xce, 0x94, + 0x3a, 0xf2, 0x8d, 0xfd, 0x3f, 0x9e, 0x59, 0x69, 0x25, 0x98, 0xa6, 0x04, 0x7c, 0x23, + 0xc4, 0xc0, 0x14, 0x00, 0xf1, 0xab, 0x57, 0x30, 0xea, 0xc0, 0xae, 0x8d, 0x58, 0x43, + 0xd5, 0x05, 0x1c, 0x37, 0x62, 0x40, 0x17, 0x2a, 0xf2, 0x18, 0xd7, 0xa1, 0xec, 0xfe, + 0x65, 0xb4, 0xf7, 0x51, 0x00, 0x63, 0x89, 0x83, 0xc1, 0x4d, 0xe4, 0x97, 0x47, 0x55, + 0xda, 0xde, 0x80, 0x18, 0xc9, 0xb8, 0xf4, 0x54, 0x3f, 0xb0, 0x95, 0x96, 0x15, 0x13, + 0xe6, 0x7c, 0x61, 0xdb, 0xc5, 0x9c, 0x60, 0x7f, 0x9b, 0x51, 0xf8, 0xd0, 0x9b, 0xdc, + 0xad, 0x28, 0xbc, 0xfb, 0x9e, 0x5d, 0x27, 0x44, 0xea, 0x88, 0x48, 0xb2, 0x62, 0x3a, + 0xc0, 0x7f, 0x8e, 0xf6, 0x1a, 0x81, 0xa3, 0x59, + ], + c_enc: [ + 0x76, 0xc6, 0xef, 0xc8, 0xb5, 0x42, 0xa7, 0x07, 0xc0, 0xa5, 0xcf, 0x5c, 0xe3, 0xf3, + 0xb9, 0x6d, 0xe1, 0x91, 0x95, 0x7c, 0x9f, 0xa6, 0xe9, 0xbb, 0x4b, 0x8d, 0x89, 0x9e, + 0x1f, 0x19, 0xe0, 0x20, 0xba, 0x7b, 0xb3, 0xfe, 0xf1, 0x67, 0x81, 0xc8, 0x8c, 0xc5, + 0xd4, 0x4a, 0x5e, 0xf8, 0x17, 0x31, 0x47, 0xdc, 0x3d, 0x1b, 0xc9, 0xb7, 0x31, 0x44, + 0x93, 0x2b, 0x1e, 0xeb, 0x8c, 0x2a, 0x84, 0xf9, 0x3d, 0x9b, 0xdf, 0x53, 0x78, 0x67, + 0xab, 0x82, 0x4c, 0xc3, 0xa4, 0xc5, 0xdc, 0x5b, 0xeb, 0xd8, 0x95, 0x26, 0xba, 0x5c, + 0x2b, 0x5a, 0x76, 0x76, 0x4b, 0x33, 0x2f, 0x2d, 0xdc, 0x0f, 0x48, 0x2f, 0xd4, 0x57, + 0xb3, 0x6d, 0x16, 0x05, 0xca, 0xea, 0xe2, 0xc7, 0xf1, 0x5a, 0x05, 0x91, 0xfa, 0x40, + 0xa4, 0x57, 0x49, 0xa7, 0x58, 0xcb, 0x88, 0xaa, 0xd5, 0xd0, 0x85, 0x92, 0x11, 0x4e, + 0x75, 0x7b, 0x19, 0x37, 0xf4, 0x99, 0x73, 0xe5, 0xba, 0x72, 0x8c, 0xa4, 0xb0, 0x9c, + 0x71, 0xe2, 0x25, 0x54, 0xf8, 0x89, 0x34, 0x8d, 0xbe, 0x7b, 0x7d, 0x7b, 0xd5, 0x02, + 0x84, 0x71, 0x20, 0xe1, 0xfe, 0xb6, 0xaf, 0x86, 0xeb, 0x19, 0x1a, 0xb2, 0x1d, 0x21, + 0x20, 0xa6, 0xbd, 0x2c, 0x38, 0x04, 0x22, 0x28, 0xa7, 0xb0, 0xda, 0xc3, 0x16, 0xe3, + 0x39, 0x05, 0x4f, 0xb4, 0x30, 0xce, 0xac, 0x6c, 0xea, 0xa8, 0xd3, 0x18, 0x10, 0xa7, + 0x99, 0x7f, 0xfb, 0xc1, 0x58, 0xfc, 0x7b, 0x2c, 0xb6, 0x2b, 0x13, 0x5e, 0xde, 0x3f, + 0x65, 0x6e, 0x4b, 0x13, 0x57, 0xac, 0x31, 0x48, 0x96, 0xf1, 0x35, 0x58, 0xec, 0x32, + 0x90, 0x8e, 0x9d, 0xd6, 0x85, 0xb4, 0xee, 0x9a, 0x7d, 0x81, 0x4d, 0xdc, 0x50, 0x2c, + 0xe7, 0xac, 0xa1, 0xda, 0x00, 0xee, 0xda, 0xe4, 0x96, 0x03, 0x35, 0xe5, 0x75, 0x6a, + 0x42, 0xd6, 0xf4, 0x4f, 0x85, 0x2c, 0x8a, 0x7a, 0xd0, 0x0e, 0xf7, 0x9a, 0x4d, 0xb1, + 0x4e, 0xae, 0xc9, 0x56, 0x2a, 0xba, 0xc3, 0x08, 0x01, 0x1e, 0xbf, 0x00, 0x57, 0x6e, + 0x6c, 0xa3, 0xea, 0x16, 0xe5, 0x01, 0xbf, 0x35, 0x0f, 0x82, 0x14, 0xb6, 0x84, 0x04, + 0xdb, 0x24, 0x2e, 0x9f, 0x85, 0x3d, 0x82, 0xbe, 0x44, 0x25, 0x0d, 0xf0, 0xa8, 0x1d, + 0xe7, 0x0e, 0x10, 0x40, 0xfa, 0xde, 0x44, 0x69, 0x1e, 0xca, 0x6e, 0x03, 0xc4, 0x6c, + 0x4b, 0x57, 0xc7, 0x89, 0xc9, 0x74, 0x8e, 0x0e, 0x2e, 0xf4, 0x11, 0x9d, 0xbd, 0x7b, + 0x39, 0x3d, 0x63, 0x3c, 0x6e, 0xc8, 0xf0, 0xd0, 0x4d, 0x97, 0x1d, 0x2b, 0xd5, 0xab, + 0xed, 0x9f, 0x36, 0xc9, 0xb4, 0xb4, 0x6e, 0x3b, 0x32, 0x56, 0x9d, 0x31, 0x89, 0x45, + 0x6e, 0x65, 0x51, 0x67, 0x7e, 0xe7, 0x71, 0xb0, 0xf0, 0xa2, 0x6f, 0x84, 0xc2, 0x9f, + 0xdc, 0xa3, 0xd6, 0x42, 0x82, 0x60, 0x05, 0x37, 0x34, 0x7b, 0xd7, 0xf6, 0x0c, 0xe4, + 0x27, 0xbf, 0x55, 0xe9, 0xb1, 0xbf, 0xd4, 0xb7, 0x56, 0x4f, 0x9f, 0xb1, 0x93, 0x02, + 0xdc, 0x41, 0xe7, 0xde, 0xde, 0x7f, 0x4f, 0xc0, 0x0f, 0x57, 0x3e, 0x33, 0xf4, 0xbe, + 0x41, 0x40, 0xdd, 0xc9, 0x76, 0x93, 0xaf, 0x52, 0x48, 0x95, 0x87, 0xf0, 0xd0, 0x81, + 0x0f, 0x3d, 0x9c, 0x35, 0x6f, 0x32, 0xe9, 0x3d, 0x47, 0x56, 0x0c, 0x01, 0x1c, 0x0c, + 0x94, 0xe1, 0xa6, 0x49, 0x7e, 0x87, 0x45, 0x8e, 0xad, 0x8a, 0x34, 0x67, 0x84, 0xbc, + 0x42, 0x66, 0x16, 0x7f, 0x87, 0x7e, 0x38, 0x92, 0xa8, 0x98, 0x77, 0x4c, 0xe3, 0xad, + 0x3b, 0x82, 0x8d, 0x9d, 0xd1, 0xd2, 0xe4, 0x0a, 0x89, 0xf1, 0xfc, 0xe4, 0x9d, 0x6b, + 0x20, 0x18, 0x9e, 0x0c, 0x22, 0xe0, 0x17, 0xab, 0x55, 0x5b, 0x68, 0xa7, 0x4e, 0x66, + 0xb4, 0xeb, 0x31, 0xee, 0x78, 0xaf, 0xbe, 0x63, 0x25, 0xcb, 0xad, 0xd5, 0xa8, 0x38, + 0x29, 0x49, 0xf3, 0xc7, 0x48, 0xa9, 0xe7, 0x22, 0xfc, 0x58, 0xeb, 0xab, 0xdc, 0x69, + 0x64, 0x22, 0x4c, 0x48, 0x58, 0x6e, 0x94, 0x3c, 0x60, 0x2f, 0x70, 0x5e, 0x55, 0x4b, + 0xc0, 0x1c, 0x58, 0x90, 0x4d, 0x2f, 0xa7, 0x1e, 0x4c, 0x44, 0xe3, 0x8c, 0x3d, 0x19, + 0x04, 0x7d, 0xa9, 0x39, 0xaf, 0x3b, 0x3f, 0xba, 0x89, 0xad, 0x1b, 0x83, 0xb5, 0xb3, + 0xb4, 0xbd, 0x8c, 0xe5, 0x99, 0xeb, 0x69, 0x7a, 0xb6, 0x5d, 0x37, 0x04, 0x5e, 0xa9, + 0x15, 0x98, 0xdb, 0x59, 0x18, 0x75, 0xf6, 0xcc, 0x18, 0x02, 0x79, 0x0a, 0x3c, 0x1f, + 0x40, 0xeb, 0x68, 0x8e, 0x7c, 0xb8, 0xbb, 0x3d, 0x07, 0xde, + ], + ock: [ + 0xb4, 0xf8, 0x8a, 0x29, 0x2d, 0x09, 0xd9, 0x35, 0xb4, 0x77, 0x5a, 0x29, 0x30, 0xeb, + 0x38, 0xce, 0xbd, 0x5a, 0xf6, 0xff, 0x3f, 0x39, 0xef, 0x5b, 0xb2, 0x4c, 0xd5, 0x72, + 0x81, 0xf0, 0x8c, 0xfb, + ], + op: [ + 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, + 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, + 0x6b, 0x80, 0xbb, 0xb7, 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, + 0x14, 0xb0, 0xdf, 0x85, 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, + 0xc4, 0x84, 0xa9, 0xf4, 0xc7, 0xda, 0x74, 0x36, + ], + c_out: [ + 0x94, 0xe3, 0x7f, 0xd6, 0x62, 0x82, 0xc0, 0x2e, 0x90, 0xe7, 0x69, 0x91, 0x4c, 0xaf, + 0x95, 0xa4, 0x95, 0xf4, 0x89, 0x7f, 0x55, 0xa5, 0xae, 0x95, 0xad, 0xe8, 0xbf, 0x67, + 0x61, 0xe3, 0x1b, 0xa5, 0xd1, 0xcf, 0xeb, 0x30, 0x6f, 0x4e, 0x22, 0x01, 0x42, 0x51, + 0xcb, 0xe3, 0xf8, 0x72, 0x4b, 0xe7, 0x69, 0x21, 0xe2, 0xad, 0xa4, 0x6e, 0x3b, 0x14, + 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, + 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x74, 0xa8, 0x41, 0x1a, 0x20, 0xbc, 0x3c, 0x53, 0xf7, 0xe7, 0xab, 0xb9, 0x31, 0x6c, + 0x44, 0x2b, 0x4b, 0x09, 0xcf, 0x88, 0xbb, 0xed, 0x4a, 0x90, 0xb9, 0x2f, 0x5a, 0x1c, + 0xed, 0x93, 0x16, 0x2b, 0xc3, 0x37, 0x34, 0x67, 0x20, 0xec, 0x0c, 0xd0, 0xea, 0x73, + 0x5d, 0x9e, 0x32, 0x3f, 0x20, 0xdb, 0x77, 0x8a, 0xd1, 0x8a, 0x84, 0xc7, 0x9e, 0xe6, + 0x28, 0x77, 0x99, 0xef, 0x02, 0x76, 0x41, 0x07, + ], + ovk: [ + 0x0c, 0x81, 0x1e, 0x4c, 0x31, 0xfb, 0xb4, 0x9f, 0x3a, 0x90, 0xbb, 0xd0, 0x5d, 0xce, + 0x62, 0xf3, 0x44, 0xe7, 0x07, 0x75, 0x93, 0x15, 0x9a, 0xe3, 0x50, 0x50, 0xb0, 0x4c, + 0x9e, 0x6b, 0x86, 0xbc, + ], + default_d: [ + 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, + ], + default_pk_d: [ + 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, + 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, + 0x17, 0x5b, 0xa9, 0x8b, + ], + v: 7387862906040043846, + rseed: [ + 0x25, 0x01, 0xe5, 0x1b, 0x01, 0x2a, 0xea, 0x94, 0x46, 0xa2, 0x10, 0x4e, 0x93, 0xf8, + 0x15, 0xa0, 0xb3, 0xa2, 0x9b, 0x45, 0x83, 0x14, 0xf3, 0xd8, 0xbe, 0x2b, 0x98, 0x23, + 0xd3, 0x42, 0xf4, 0x62, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x13, 0xe9, 0x42, 0xa7, 0xe1, 0x9a, 0x46, 0xe9, 0x70, 0xb5, 0xc5, 0x06, 0x70, + 0x84, 0x30, 0x31, 0x7b, 0x1b, 0xb3, 0xb3, 0x5d, 0xf6, 0x8a, 0xe3, 0x3a, 0x49, 0x26, + 0xa0, 0x3e, 0x6b, 0xfe, 0xb5, 0x51, 0x04, 0x16, 0xfc, 0xbb, 0x05, 0x24, 0xc9, 0xca, + 0x50, 0x74, 0x15, 0x6c, 0xc5, 0xa5, 0xd6, 0xfe, 0x1c, 0x99, 0x5e, 0xdc, 0x60, 0xa2, + 0xf5, 0x50, 0x41, 0x1a, 0xa4, 0x1e, 0x3d, 0xa3, 0xbd, 0xcf, 0x64, 0xbc, 0xf0, 0x4a, + 0x05, 0x10, 0x57, 0x1b, 0x93, 0x6d, 0x47, 0xe5, 0x5c, 0xec, 0x03, 0x30, 0xee, 0x8d, + 0xfe, 0x73, 0x56, 0x34, 0x04, 0xf0, 0x47, 0xd7, 0xf3, 0xa8, 0xa3, 0xd7, 0x74, 0x3b, + 0xc5, 0x54, 0x95, 0x52, 0x10, 0xf1, 0xeb, 0x0d, 0x08, 0x59, 0x9e, 0xa7, 0x7d, 0x5f, + 0x97, 0x4d, 0x87, 0x17, 0x6d, 0x37, 0xd9, 0x8b, 0x9c, 0x0a, 0xd4, 0x40, 0x40, 0x72, + 0x09, 0xed, 0x6a, 0x9f, 0x08, 0x46, 0x4d, 0x56, 0x55, 0x93, 0xe1, 0xa6, 0x3b, 0x93, + 0x85, 0x36, 0xb4, 0x92, 0x44, 0xe9, 0x7d, 0x88, 0x01, 0x73, 0xb6, 0x40, 0xf2, 0xdd, + 0xb7, 0x4d, 0x06, 0x8e, 0xcb, 0x46, 0xcf, 0x28, 0x9b, 0x7d, 0x89, 0x13, 0x07, 0xbb, + 0xa3, 0x70, 0x54, 0xcf, 0x91, 0xb3, 0x1f, 0xc8, 0x2f, 0x74, 0xd5, 0xfc, 0xc0, 0x00, + 0x94, 0x2e, 0xde, 0x91, 0x18, 0x25, 0xf5, 0x3f, 0xe6, 0x09, 0x68, 0x6f, 0x46, 0x32, + 0x23, 0xb1, 0xe9, 0xbc, 0x03, 0xbd, 0xe8, 0x95, 0xd1, 0x23, 0x8f, 0xad, 0x04, 0xa3, + 0xbf, 0xce, 0x68, 0xa0, 0x75, 0xe8, 0xa3, 0x7c, 0x0e, 0x87, 0xbf, 0x46, 0xdd, 0x01, + 0x55, 0x45, 0xf9, 0xb4, 0xfb, 0x0e, 0xec, 0x64, 0x5f, 0xfc, 0xbb, 0xe0, 0xca, 0x5f, + 0x8c, 0x56, 0x1b, 0x25, 0x7d, 0x52, 0xd6, 0x02, 0xd8, 0xc9, 0x4c, 0x50, 0x28, 0x73, + 0xa0, 0x1d, 0x92, 0x51, 0xd8, 0xc8, 0x60, 0xc0, 0x41, 0x52, 0x5b, 0x3b, 0xf4, 0xe3, + 0xa2, 0xeb, 0x92, 0x72, 0x81, 0x5c, 0x75, 0x86, 0x76, 0x84, 0x28, 0xb4, 0xc2, 0xb2, + 0x5e, 0x37, 0x45, 0xf0, 0x09, 0xc5, 0xdc, 0xe2, 0x0b, 0x69, 0xd5, 0xd7, 0xc4, 0x3c, + 0xeb, 0x73, 0x6b, 0x68, 0x31, 0xe8, 0xc1, 0x10, 0xf1, 0x6c, 0xfd, 0xb3, 0xa4, 0x67, + 0xe9, 0x41, 0x4c, 0x00, 0xec, 0xf1, 0x37, 0x31, 0x50, 0x08, 0x94, 0x55, 0x56, 0x78, + 0xc4, 0x97, 0xfa, 0xba, 0x9a, 0x95, 0xd0, 0x1c, 0xc4, 0x64, 0x39, 0x0f, 0xc4, 0xa7, + 0x6b, 0xfa, 0x8b, 0x0e, 0x1c, 0x68, 0xa5, 0x25, 0xd7, 0x06, 0xd6, 0x60, 0x4b, 0x23, + 0x30, 0xb6, 0xb3, 0x48, 0x52, 0x15, 0xf6, 0x06, 0xf1, 0x88, 0x3a, 0x75, 0x15, 0x88, + 0xc7, 0xef, 0xa5, 0x06, 0xc3, 0xe8, 0xd0, 0xc6, 0x01, 0x92, 0xe8, 0x47, 0x6b, 0xd1, + 0x17, 0x5d, 0x95, 0x62, 0x08, 0x7b, 0xdb, 0x81, 0x8e, 0x66, 0x21, 0x62, 0x86, 0xba, + 0xfe, 0x47, 0xff, 0x4d, 0xbc, 0xce, 0xd5, 0x14, 0x44, 0x48, 0x0a, 0x9a, 0x56, 0x73, + 0xec, 0xe7, 0xfa, 0xc7, 0x3a, 0x0e, 0xd4, 0x1a, 0xb0, 0x05, 0x17, 0x53, 0xa7, 0xca, + 0xa8, 0x9b, 0xe3, 0x13, 0x9a, 0xfd, 0x97, 0x93, 0xb3, 0xe0, 0x2f, 0x27, 0xf0, 0x40, + 0x04, 0x65, 0x95, 0xac, 0xd4, 0x7b, 0xf1, 0x3f, 0xd0, 0xda, 0x27, 0xf0, 0x9e, 0xda, + 0x48, 0x03, 0x6d, 0x3e, 0xe4, 0x37, 0xf2, 0xee, 0x8f, 0x86, 0x06, 0xea, 0x97, 0x34, + 0x3c, 0x33, 0x58, 0x46, 0x57, 0xf4, 0x6d, 0xba, 0x99, 0xdb, 0x5c, 0xfe, 0x6c, 0xa1, + 0x76, 0xfa, 0xb7, 0xb0, 0xf3, 0xbf, 0xa0, 0xab, 0x61, 0xe3, 0x40, 0xc3, 0x4e, 0xb9, + 0xf1, 0x7c, 0x7e, 0xc2, 0xbe, 0x03, 0xb1, 0x80, 0xf0, 0xbb, 0x6f, 0x43, 0x4c, 0x2a, + 0x65, 0x42, 0xe0, 0x0e, 0x84, 0x37, 0x3f, 0x4f, + ], + cv_net: [ + 0x47, 0x35, 0xa6, 0xfd, 0x21, 0x5c, 0x7b, 0x95, 0x03, 0x3d, 0xab, 0x62, 0xcc, 0xf9, + 0xcd, 0x51, 0x00, 0x89, 0x08, 0xa6, 0xcd, 0xd0, 0xaa, 0x02, 0x1b, 0x88, 0x8b, 0x98, + 0xe2, 0x3c, 0x39, 0x11, + ], + rho: [ + 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, + 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, + 0x3e, 0xe8, 0xed, 0x20, + ], + cmx: [ + 0xbe, 0x43, 0xee, 0x84, 0x70, 0x70, 0x75, 0xac, 0x48, 0x08, 0xd0, 0x97, 0x54, 0x07, + 0xc0, 0x27, 0x36, 0xd7, 0x66, 0x64, 0xf4, 0xe7, 0xae, 0xce, 0x01, 0xd9, 0xcc, 0x68, + 0x32, 0x4a, 0xe9, 0x04, + ], + esk: [ + 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, 0x14, 0x49, 0x72, 0x62, + 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, 0xe2, 0x63, 0xf3, 0xe3, + 0x99, 0x07, 0xea, 0x0c, + ], + ephemeral_key: [ + 0xfa, 0x19, 0xa1, 0x52, 0x7b, 0x76, 0x04, 0x8f, 0xf3, 0x7f, 0xa4, 0xf8, 0x27, 0x89, + 0xfe, 0x80, 0xb0, 0xcd, 0xd3, 0x5d, 0x5d, 0xa9, 0xc2, 0xec, 0x3f, 0xe3, 0x04, 0x38, + 0x05, 0xc0, 0x61, 0x23, + ], + shared_secret: [ + 0x2d, 0xb5, 0xb8, 0x92, 0xb6, 0x1b, 0x9c, 0x55, 0x3b, 0x6c, 0x9b, 0x7a, 0xcc, 0x7d, + 0x71, 0x05, 0xc1, 0xdd, 0x4c, 0x28, 0xc6, 0x7f, 0x97, 0x8b, 0x6d, 0x79, 0xc7, 0x1b, + 0x98, 0xa0, 0xd0, 0x00, + ], + k_enc: [ + 0x16, 0xe3, 0xf9, 0x85, 0xc0, 0x7f, 0xef, 0xe5, 0x30, 0xd9, 0xe6, 0x94, 0x5e, 0xde, + 0xc1, 0x90, 0x3b, 0xb1, 0xca, 0x8d, 0xa5, 0xa2, 0x5b, 0xe9, 0x59, 0x78, 0x63, 0x7a, + 0x40, 0x8c, 0x2e, 0xfe, + ], + p_enc: [ + 0x03, 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, 0x46, 0x49, + 0xcd, 0xa3, 0x2b, 0xf6, 0x86, 0x66, 0x25, 0x01, 0xe5, 0x1b, 0x01, 0x2a, 0xea, 0x94, + 0x46, 0xa2, 0x10, 0x4e, 0x93, 0xf8, 0x15, 0xa0, 0xb3, 0xa2, 0x9b, 0x45, 0x83, 0x14, + 0xf3, 0xd8, 0xbe, 0x2b, 0x98, 0x23, 0xd3, 0x42, 0xf4, 0x62, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x13, 0xe9, 0x42, 0xa7, 0xe1, 0x9a, 0x46, 0xe9, 0x70, 0xb5, 0xc5, 0x06, 0x70, + 0x84, 0x30, 0x31, 0x7b, 0x1b, 0xb3, 0xb3, 0x5d, 0xf6, 0x8a, 0xe3, 0x3a, 0x49, 0x26, + 0xa0, 0x3e, 0x6b, 0xfe, 0xb5, 0x51, 0x04, 0x16, 0xfc, 0xbb, 0x05, 0x24, 0xc9, 0xca, + 0x50, 0x74, 0x15, 0x6c, 0xc5, 0xa5, 0xd6, 0xfe, 0x1c, 0x99, 0x5e, 0xdc, 0x60, 0xa2, + 0xf5, 0x50, 0x41, 0x1a, 0xa4, 0x1e, 0x3d, 0xa3, 0xbd, 0xcf, 0x64, 0xbc, 0xf0, 0x4a, + 0x05, 0x10, 0x57, 0x1b, 0x93, 0x6d, 0x47, 0xe5, 0x5c, 0xec, 0x03, 0x30, 0xee, 0x8d, + 0xfe, 0x73, 0x56, 0x34, 0x04, 0xf0, 0x47, 0xd7, 0xf3, 0xa8, 0xa3, 0xd7, 0x74, 0x3b, + 0xc5, 0x54, 0x95, 0x52, 0x10, 0xf1, 0xeb, 0x0d, 0x08, 0x59, 0x9e, 0xa7, 0x7d, 0x5f, + 0x97, 0x4d, 0x87, 0x17, 0x6d, 0x37, 0xd9, 0x8b, 0x9c, 0x0a, 0xd4, 0x40, 0x40, 0x72, + 0x09, 0xed, 0x6a, 0x9f, 0x08, 0x46, 0x4d, 0x56, 0x55, 0x93, 0xe1, 0xa6, 0x3b, 0x93, + 0x85, 0x36, 0xb4, 0x92, 0x44, 0xe9, 0x7d, 0x88, 0x01, 0x73, 0xb6, 0x40, 0xf2, 0xdd, + 0xb7, 0x4d, 0x06, 0x8e, 0xcb, 0x46, 0xcf, 0x28, 0x9b, 0x7d, 0x89, 0x13, 0x07, 0xbb, + 0xa3, 0x70, 0x54, 0xcf, 0x91, 0xb3, 0x1f, 0xc8, 0x2f, 0x74, 0xd5, 0xfc, 0xc0, 0x00, + 0x94, 0x2e, 0xde, 0x91, 0x18, 0x25, 0xf5, 0x3f, 0xe6, 0x09, 0x68, 0x6f, 0x46, 0x32, + 0x23, 0xb1, 0xe9, 0xbc, 0x03, 0xbd, 0xe8, 0x95, 0xd1, 0x23, 0x8f, 0xad, 0x04, 0xa3, + 0xbf, 0xce, 0x68, 0xa0, 0x75, 0xe8, 0xa3, 0x7c, 0x0e, 0x87, 0xbf, 0x46, 0xdd, 0x01, + 0x55, 0x45, 0xf9, 0xb4, 0xfb, 0x0e, 0xec, 0x64, 0x5f, 0xfc, 0xbb, 0xe0, 0xca, 0x5f, + 0x8c, 0x56, 0x1b, 0x25, 0x7d, 0x52, 0xd6, 0x02, 0xd8, 0xc9, 0x4c, 0x50, 0x28, 0x73, + 0xa0, 0x1d, 0x92, 0x51, 0xd8, 0xc8, 0x60, 0xc0, 0x41, 0x52, 0x5b, 0x3b, 0xf4, 0xe3, + 0xa2, 0xeb, 0x92, 0x72, 0x81, 0x5c, 0x75, 0x86, 0x76, 0x84, 0x28, 0xb4, 0xc2, 0xb2, + 0x5e, 0x37, 0x45, 0xf0, 0x09, 0xc5, 0xdc, 0xe2, 0x0b, 0x69, 0xd5, 0xd7, 0xc4, 0x3c, + 0xeb, 0x73, 0x6b, 0x68, 0x31, 0xe8, 0xc1, 0x10, 0xf1, 0x6c, 0xfd, 0xb3, 0xa4, 0x67, + 0xe9, 0x41, 0x4c, 0x00, 0xec, 0xf1, 0x37, 0x31, 0x50, 0x08, 0x94, 0x55, 0x56, 0x78, + 0xc4, 0x97, 0xfa, 0xba, 0x9a, 0x95, 0xd0, 0x1c, 0xc4, 0x64, 0x39, 0x0f, 0xc4, 0xa7, + 0x6b, 0xfa, 0x8b, 0x0e, 0x1c, 0x68, 0xa5, 0x25, 0xd7, 0x06, 0xd6, 0x60, 0x4b, 0x23, + 0x30, 0xb6, 0xb3, 0x48, 0x52, 0x15, 0xf6, 0x06, 0xf1, 0x88, 0x3a, 0x75, 0x15, 0x88, + 0xc7, 0xef, 0xa5, 0x06, 0xc3, 0xe8, 0xd0, 0xc6, 0x01, 0x92, 0xe8, 0x47, 0x6b, 0xd1, + 0x17, 0x5d, 0x95, 0x62, 0x08, 0x7b, 0xdb, 0x81, 0x8e, 0x66, 0x21, 0x62, 0x86, 0xba, + 0xfe, 0x47, 0xff, 0x4d, 0xbc, 0xce, 0xd5, 0x14, 0x44, 0x48, 0x0a, 0x9a, 0x56, 0x73, + 0xec, 0xe7, 0xfa, 0xc7, 0x3a, 0x0e, 0xd4, 0x1a, 0xb0, 0x05, 0x17, 0x53, 0xa7, 0xca, + 0xa8, 0x9b, 0xe3, 0x13, 0x9a, 0xfd, 0x97, 0x93, 0xb3, 0xe0, 0x2f, 0x27, 0xf0, 0x40, + 0x04, 0x65, 0x95, 0xac, 0xd4, 0x7b, 0xf1, 0x3f, 0xd0, 0xda, 0x27, 0xf0, 0x9e, 0xda, + 0x48, 0x03, 0x6d, 0x3e, 0xe4, 0x37, 0xf2, 0xee, 0x8f, 0x86, 0x06, 0xea, 0x97, 0x34, + 0x3c, 0x33, 0x58, 0x46, 0x57, 0xf4, 0x6d, 0xba, 0x99, 0xdb, 0x5c, 0xfe, 0x6c, 0xa1, + 0x76, 0xfa, 0xb7, 0xb0, 0xf3, 0xbf, 0xa0, 0xab, 0x61, 0xe3, 0x40, 0xc3, 0x4e, 0xb9, + 0xf1, 0x7c, 0x7e, 0xc2, 0xbe, 0x03, 0xb1, 0x80, 0xf0, 0xbb, 0x6f, 0x43, 0x4c, 0x2a, + 0x65, 0x42, 0xe0, 0x0e, 0x84, 0x37, 0x3f, 0x4f, + ], + c_enc: [ + 0x2c, 0x40, 0x4a, 0x68, 0x81, 0xa6, 0xee, 0x76, 0x0c, 0xb5, 0x3b, 0x9c, 0xc2, 0x71, + 0x5c, 0xa7, 0x6a, 0x3a, 0x2f, 0xc9, 0x69, 0x3b, 0x1a, 0xbb, 0xcd, 0xc7, 0x5c, 0xb6, + 0xd6, 0xc3, 0x6e, 0xcf, 0x84, 0xd6, 0x93, 0x67, 0x2c, 0x53, 0xce, 0xd8, 0x79, 0x8c, + 0xc8, 0xf1, 0xe5, 0x3b, 0x8a, 0x9d, 0xe7, 0xbb, 0xb5, 0xe8, 0x5d, 0xf4, 0x7c, 0x42, + 0xbd, 0x4e, 0xe2, 0x7d, 0xa0, 0xd6, 0xf9, 0x5a, 0xa4, 0xf1, 0x10, 0xd4, 0x5a, 0xe2, + 0x8e, 0x6f, 0xea, 0x40, 0xe4, 0x7b, 0xc6, 0x08, 0x1b, 0x78, 0xe2, 0xcb, 0xa1, 0x78, + 0xf5, 0x3b, 0x2c, 0x0f, 0xfd, 0x71, 0xf1, 0x52, 0x54, 0x55, 0x70, 0x8a, 0x92, 0x50, + 0xb0, 0x28, 0x17, 0x90, 0x70, 0xc7, 0xd3, 0xbe, 0x38, 0xdc, 0x67, 0x3f, 0xc1, 0x20, + 0x6c, 0xce, 0x64, 0xd5, 0x13, 0xed, 0x14, 0x3e, 0xbf, 0x45, 0x76, 0x3c, 0xa5, 0xea, + 0x12, 0x6e, 0xc1, 0x4d, 0x01, 0xda, 0xcb, 0x64, 0x60, 0xa5, 0xdc, 0xd2, 0x26, 0xd1, + 0xa9, 0x5c, 0x8d, 0xf9, 0xc4, 0x64, 0xd9, 0x35, 0xb6, 0xaa, 0x60, 0x7f, 0xff, 0x2d, + 0x3d, 0x72, 0x55, 0x83, 0xf8, 0x82, 0x1a, 0xe9, 0xb4, 0x7f, 0xce, 0x87, 0x5e, 0xa8, + 0x7c, 0xea, 0x41, 0x21, 0xec, 0xc8, 0x5b, 0x93, 0xa6, 0x38, 0xf5, 0x6f, 0x48, 0xf7, + 0x0a, 0xc8, 0x85, 0xb4, 0x89, 0x03, 0x02, 0xdf, 0x12, 0x5f, 0x80, 0x20, 0x16, 0x4d, + 0xd0, 0x13, 0xc7, 0x3f, 0xd2, 0xb4, 0x0f, 0x38, 0xc6, 0x9b, 0xe8, 0xcf, 0x0a, 0x3b, + 0xaf, 0xa6, 0x3b, 0x2b, 0xa0, 0x4d, 0x98, 0x65, 0xa2, 0x55, 0xc2, 0x34, 0x60, 0x83, + 0x33, 0x04, 0xf6, 0xe7, 0xf6, 0xec, 0xd4, 0x7d, 0xa7, 0x8b, 0x29, 0xfa, 0x95, 0x15, + 0xba, 0x60, 0xed, 0x15, 0x78, 0x78, 0x02, 0xe7, 0xa9, 0xf6, 0x63, 0xe9, 0xad, 0xda, + 0x54, 0x64, 0x77, 0xf7, 0xa9, 0x94, 0xc1, 0x6b, 0x81, 0x41, 0xf4, 0x54, 0xc4, 0x34, + 0xd5, 0x7f, 0x8b, 0xd3, 0xb8, 0xc0, 0xe7, 0x21, 0x1c, 0x91, 0x5f, 0xc3, 0xfe, 0xb5, + 0xdd, 0xe3, 0xb9, 0x1c, 0xed, 0x14, 0x93, 0x7a, 0x00, 0xff, 0xfc, 0xba, 0x37, 0x2e, + 0x69, 0x28, 0x70, 0xca, 0x44, 0xd0, 0x0c, 0x24, 0xc0, 0x0d, 0x61, 0x0a, 0x75, 0xa5, + 0x18, 0xca, 0x83, 0x62, 0xcd, 0xb3, 0xcf, 0xb6, 0xdc, 0x10, 0x5a, 0xa6, 0x86, 0x37, + 0x69, 0x52, 0x03, 0x45, 0xae, 0x51, 0x3d, 0x60, 0x89, 0x85, 0xba, 0x9b, 0xab, 0x2f, + 0x61, 0x4c, 0xd8, 0xad, 0xfc, 0xe6, 0x07, 0x15, 0x6d, 0x04, 0xe7, 0x70, 0xe6, 0x3e, + 0x2c, 0xd4, 0x7a, 0xb8, 0x5f, 0x8e, 0x74, 0x51, 0x8e, 0x19, 0x70, 0x7d, 0x83, 0xe3, + 0xc4, 0x86, 0xad, 0x9e, 0x0a, 0x28, 0x34, 0xc5, 0x8b, 0x4b, 0x72, 0x7a, 0x9b, 0xb0, + 0xc3, 0x7e, 0x8f, 0xcb, 0xdd, 0x9a, 0x49, 0xe8, 0x23, 0x74, 0xd5, 0x24, 0x44, 0x42, + 0x9b, 0x6e, 0x9a, 0x0d, 0xf2, 0xaf, 0x47, 0xe9, 0xd4, 0x58, 0x1d, 0xbe, 0xc7, 0xc6, + 0x0f, 0xb9, 0x33, 0x79, 0x4e, 0xc6, 0x88, 0x16, 0xbe, 0xd4, 0x2e, 0x97, 0xfb, 0xbc, + 0x91, 0xbd, 0x5e, 0x25, 0x69, 0x07, 0xb3, 0x9d, 0x24, 0xad, 0x54, 0xb5, 0x06, 0x4a, + 0x46, 0xb4, 0x01, 0x83, 0x38, 0x26, 0xfe, 0x4d, 0xff, 0x2e, 0x9f, 0xcc, 0xca, 0x8c, + 0x54, 0xf7, 0x83, 0x25, 0x4d, 0x28, 0x05, 0xe9, 0x56, 0x04, 0x41, 0x72, 0xa7, 0x65, + 0x81, 0xff, 0xfd, 0x45, 0x8b, 0x6a, 0x64, 0x69, 0xdc, 0x40, 0xf9, 0x4e, 0x60, 0x65, + 0xf9, 0x9c, 0x3f, 0x63, 0xda, 0x89, 0xf3, 0x26, 0x0a, 0xfe, 0xde, 0x0f, 0xfa, 0x0c, + 0xd3, 0x3a, 0xb0, 0x89, 0xb1, 0x31, 0xed, 0x55, 0x40, 0x29, 0x06, 0xba, 0xf8, 0x0b, + 0xcc, 0x64, 0x3d, 0xf9, 0x34, 0x1c, 0xce, 0x9a, 0x55, 0x3b, 0x5a, 0xe5, 0x11, 0xe5, + 0xdc, 0xd2, 0x83, 0x5c, 0x3b, 0xf5, 0x71, 0xe8, 0xaa, 0xd1, 0x61, 0x8c, 0xf7, 0x06, + 0xd9, 0x14, 0xe6, 0xa3, 0x99, 0xd1, 0x8d, 0xeb, 0xf5, 0x6b, 0x3b, 0x46, 0xc5, 0xd4, + 0x56, 0x2f, 0x1c, 0x7d, 0x24, 0x2d, 0xdc, 0x53, 0xa5, 0x73, 0x63, 0x6e, 0x75, 0x3c, + 0x91, 0x52, 0x4c, 0xb9, 0x3f, 0xcd, 0x88, 0xa2, 0x3b, 0xe9, 0xb3, 0x4e, 0xca, 0xb4, + 0xbf, 0x89, 0x71, 0x01, 0x34, 0xfc, 0xe8, 0x34, 0x5b, 0xcd, 0x6a, 0x5a, 0x3d, 0x72, + 0x1e, 0xa8, 0xb6, 0x20, 0x7c, 0x2f, 0xcf, 0x81, 0x75, 0x80, 0xe0, 0xa6, 0x3d, 0xb4, + 0x37, 0x7c, 0x86, 0xe4, 0x15, 0x1e, 0xd8, 0xd3, 0x0a, 0x71, + ], + ock: [ + 0x8b, 0x0d, 0x29, 0x8e, 0xe8, 0xb4, 0x25, 0x34, 0xa4, 0x2f, 0xb9, 0x63, 0x5b, 0xa7, + 0x58, 0xea, 0x9f, 0x91, 0x8b, 0x83, 0x16, 0xc0, 0xe8, 0x94, 0xa9, 0x08, 0x48, 0x89, + 0x01, 0xd9, 0xfb, 0xa3, + ], + op: [ + 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, + 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, + 0x17, 0x5b, 0xa9, 0x8b, 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, + 0x14, 0x49, 0x72, 0x62, 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, + 0xe2, 0x63, 0xf3, 0xe3, 0x99, 0x07, 0xea, 0x0c, + ], + c_out: [ + 0xf3, 0xbf, 0x90, 0x76, 0xf3, 0xdb, 0x66, 0x32, 0x6d, 0xa6, 0x0c, 0xc7, 0x94, 0x3c, + 0x85, 0x4d, 0x8d, 0xe9, 0x9f, 0x57, 0x53, 0xf7, 0x0c, 0x32, 0xed, 0x01, 0xfb, 0x2e, + 0x84, 0x9c, 0x9d, 0xc7, 0x3f, 0x80, 0xb5, 0xcb, 0xaa, 0xb4, 0x99, 0x2d, 0xd7, 0xe7, + 0x38, 0xb9, 0x61, 0xfd, 0x75, 0x3f, 0x7c, 0x5b, 0x29, 0x24, 0xd1, 0xd9, 0x63, 0x06, + 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, + 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x73, 0xa2, 0x5e, 0xba, 0x9b, 0xd7, 0xa8, 0xed, 0x2b, 0x5b, 0x1b, 0x8d, 0x5a, 0x05, + 0x6b, 0xde, 0x8d, 0x05, 0xe6, 0xa2, 0x80, 0x67, 0xb3, 0x84, 0x57, 0x91, 0xbe, 0xbf, + 0xa7, 0xae, 0x2a, 0xcd, 0x36, 0x32, 0x6f, 0xe6, 0x27, 0xbe, 0xe8, 0x0e, 0x32, 0x92, + 0xe0, 0xe5, 0x13, 0x2d, 0xe1, 0x6c, 0xa4, 0xf8, 0x1e, 0x5a, 0x6f, 0xc0, 0x9c, 0x95, + 0xff, 0x13, 0xb5, 0x2e, 0x96, 0xb7, 0x89, 0x0f, + ], + ovk: [ + 0xf5, 0xe8, 0xde, 0xd8, 0x18, 0x92, 0x51, 0x1c, 0xc2, 0x85, 0x1b, 0x00, 0xb8, 0x32, + 0x71, 0x2a, 0x6d, 0x3b, 0xa5, 0x66, 0x65, 0x17, 0xbc, 0xd3, 0x56, 0x76, 0x21, 0xa7, + 0xcf, 0x84, 0x45, 0x58, + ], + default_d: [ + 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, + ], + default_pk_d: [ + 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, + 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, + 0x01, 0x70, 0x89, 0x1a, + ], + v: 17209482587585417762, + rseed: [ + 0xfc, 0x54, 0x88, 0x62, 0xf5, 0xa0, 0x70, 0x94, 0xfd, 0x42, 0x8a, 0x7b, 0xbc, 0x15, + 0xd7, 0xb3, 0x8d, 0x05, 0x36, 0x2c, 0x9c, 0xa9, 0x85, 0xf5, 0x8a, 0x76, 0x64, 0x7d, + 0x2b, 0xe4, 0xc2, 0xcd, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0x6b, 0x3d, 0x17, 0xd6, 0x87, 0x09, 0x71, 0xd7, 0xa0, 0x98, 0xba, 0xf7, 0x2c, + 0x6f, 0x6f, 0x12, 0x14, 0xcf, 0x1f, 0xaa, 0xe4, 0x88, 0xbd, 0x7d, 0xe2, 0x59, 0xd3, + 0x41, 0x5c, 0x2f, 0x0d, 0xde, 0xc7, 0x45, 0x70, 0x04, 0xf3, 0x57, 0x08, 0xd1, 0xec, + 0xcc, 0xcc, 0x0d, 0xf6, 0x5a, 0x04, 0x94, 0x3a, 0xd5, 0xcb, 0xc1, 0x3f, 0x29, 0x5f, + 0x00, 0x0f, 0xe0, 0x56, 0xc4, 0x0b, 0x2d, 0x88, 0xf2, 0x7d, 0xc3, 0x4c, 0xfe, 0xb8, + 0x03, 0xbe, 0x34, 0x83, 0xa9, 0xeb, 0xf9, 0xb5, 0xa9, 0x02, 0x60, 0x57, 0x72, 0x5d, + 0x63, 0xea, 0xd2, 0xc0, 0xc0, 0xff, 0x1f, 0xe2, 0x6a, 0xc1, 0xe7, 0xbd, 0xfc, 0xd6, + 0xfa, 0xd8, 0x75, 0x84, 0x2d, 0x19, 0x4f, 0x33, 0x17, 0x50, 0x46, 0x2c, 0x06, 0xb8, + 0xd7, 0x98, 0x2d, 0x67, 0x99, 0x5e, 0xd5, 0xd3, 0xae, 0x96, 0xa0, 0x5a, 0xe0, 0x06, + 0x7f, 0x4e, 0xb1, 0xc7, 0xc9, 0x32, 0x31, 0xbd, 0x39, 0x77, 0x3c, 0xbe, 0x0a, 0x9d, + 0x66, 0xb0, 0xc9, 0xaa, 0x8c, 0xff, 0x6a, 0x37, 0x6e, 0x1f, 0x37, 0x2e, 0xac, 0x6a, + 0xc4, 0xe4, 0x6c, 0xc0, 0x94, 0x22, 0x45, 0xd4, 0xc2, 0xdc, 0xf0, 0x2d, 0x76, 0x40, + 0xff, 0xcc, 0x5a, 0x6a, 0xc3, 0xa8, 0x7f, 0x5c, 0x41, 0x15, 0x51, 0xbc, 0xc2, 0xf2, + 0x6c, 0xb9, 0x49, 0x61, 0xd5, 0x3f, 0x95, 0xdd, 0xb1, 0x9a, 0xe9, 0x30, 0xc8, 0xd7, + 0x0f, 0x03, 0x1b, 0x29, 0xa5, 0xdf, 0x99, 0xff, 0x36, 0x69, 0x5e, 0x80, 0x2c, 0xbc, + 0xb6, 0xb5, 0x8c, 0x1b, 0xa7, 0xed, 0x5e, 0xac, 0xfa, 0x76, 0x41, 0x4a, 0x41, 0xad, + 0x4a, 0x44, 0xf7, 0x1f, 0x1b, 0x58, 0x0d, 0x34, 0xc3, 0xa9, 0x52, 0x92, 0x0b, 0x25, + 0x4a, 0x14, 0x5f, 0xea, 0x51, 0x7f, 0x5b, 0x42, 0xb2, 0xf6, 0x5e, 0xcd, 0x0f, 0x82, + 0x59, 0x54, 0x78, 0xd8, 0x0a, 0xe5, 0xc8, 0xce, 0xea, 0x12, 0xa1, 0x61, 0xcc, 0xbb, + 0x5e, 0xac, 0x09, 0x99, 0x0f, 0xc6, 0x19, 0xa4, 0x60, 0x80, 0x43, 0x6d, 0xbd, 0x08, + 0xd7, 0x47, 0x84, 0xaf, 0x00, 0x2d, 0x58, 0xe0, 0x6f, 0xaf, 0x7f, 0x3c, 0xea, 0xe7, + 0xd3, 0x41, 0x9b, 0x1f, 0xca, 0x26, 0x5a, 0x55, 0x59, 0xcf, 0x9e, 0x2d, 0x3b, 0x60, + 0x97, 0x8d, 0x81, 0xa6, 0x78, 0xb9, 0xed, 0x8e, 0x44, 0x86, 0xb4, 0xd1, 0x46, 0x09, + 0xd6, 0xc1, 0x27, 0xc0, 0xc2, 0xfb, 0xff, 0xe3, 0x0a, 0x60, 0xf7, 0xbf, 0xf1, 0xd9, + 0xfb, 0x83, 0x00, 0xed, 0x00, 0x92, 0x53, 0xba, 0x9b, 0x99, 0x6f, 0xa0, 0x52, 0x41, + 0xb1, 0x0f, 0x5a, 0xc9, 0xa8, 0x40, 0x8e, 0x92, 0x5b, 0x62, 0x6b, 0xb2, 0x1a, 0x47, + 0x1f, 0xe3, 0xbe, 0xde, 0x52, 0xbb, 0xa0, 0x97, 0xb2, 0xa9, 0x9a, 0x9b, 0xa5, 0xa8, + 0x66, 0x58, 0xc3, 0xfd, 0x9e, 0xc5, 0x5b, 0xfa, 0x9b, 0x32, 0x85, 0x67, 0x25, 0x4a, + 0xb3, 0x6d, 0x2c, 0x7f, 0x44, 0xd2, 0xc7, 0xe1, 0x3e, 0xb5, 0x4b, 0xeb, 0x70, 0xea, + 0x8f, 0xa9, 0x4b, 0x6c, 0x6e, 0x01, 0x2d, 0x79, 0xe3, 0xf5, 0x36, 0x89, 0xc2, 0xb1, + 0xa1, 0x8e, 0xaf, 0x2d, 0x47, 0x1d, 0x13, 0xc1, 0xab, 0x39, 0xd9, 0x19, 0x4a, 0xe8, + 0x43, 0xab, 0x1d, 0x28, 0xff, 0xa8, 0xf6, 0x9d, 0xc7, 0xe1, 0x5c, 0xc3, 0x8b, 0x12, + 0xe8, 0xfc, 0xd7, 0x92, 0x55, 0xb7, 0x21, 0x60, 0x56, 0xd9, 0xed, 0xb7, 0x48, 0x2f, + 0xb9, 0x8a, 0xa0, 0x33, 0xb6, 0x5e, 0x51, 0xc1, 0xa0, 0x8b, 0x8a, 0x11, 0xd8, 0x4d, + 0x04, 0x09, 0xb7, 0x34, 0xf4, 0x52, 0xaa, 0xf0, 0xd6, 0xb1, 0x8f, 0x50, 0x25, 0x86, + 0x83, 0xd3, 0xf9, 0xa7, 0x6d, 0x39, 0x9f, 0xd0, 0x47, 0xee, 0xe2, 0x88, 0xbb, 0x45, + 0x85, 0x85, 0x1d, 0xc9, 0x3e, 0xcc, 0xc6, 0x23, + ], + cv_net: [ + 0xe8, 0x06, 0x5c, 0x40, 0x96, 0xd3, 0x54, 0x33, 0x40, 0x01, 0x1f, 0x58, 0x90, 0xb1, + 0x7e, 0xed, 0xd2, 0xa7, 0x06, 0x44, 0x07, 0x34, 0x78, 0x41, 0x01, 0xae, 0x2d, 0x8e, + 0x87, 0xe5, 0x05, 0xad, + ], + rho: [ + 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, + 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, + 0x45, 0x89, 0x35, 0x14, + ], + cmx: [ + 0x6d, 0x29, 0x97, 0xd1, 0xce, 0x0a, 0x94, 0x9a, 0x63, 0x70, 0x0f, 0x46, 0x1b, 0x57, + 0x12, 0xae, 0xeb, 0x43, 0xd4, 0x55, 0x04, 0xe3, 0x5b, 0xda, 0x16, 0x52, 0x97, 0x77, + 0xc7, 0x4d, 0x19, 0x1b, + ], + esk: [ + 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, 0x6b, 0xa0, 0x02, 0x0c, + 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, 0x57, 0x32, 0x63, 0xf4, + 0x99, 0xbd, 0x4c, 0x13, + ], + ephemeral_key: [ + 0xe4, 0x76, 0x95, 0x86, 0x30, 0x4a, 0x6a, 0x9b, 0x3a, 0x2a, 0xef, 0x3a, 0xf5, 0x8b, + 0x97, 0xda, 0xc2, 0xcc, 0x4a, 0xeb, 0x38, 0x9f, 0x68, 0xc1, 0x28, 0x87, 0x73, 0x1e, + 0x0e, 0x12, 0xbc, 0x1e, + ], + shared_secret: [ + 0xf6, 0xba, 0x4b, 0x1f, 0xbe, 0x01, 0xfa, 0x2f, 0x1d, 0xd4, 0x09, 0x3c, 0x5c, 0xc4, + 0x85, 0xa9, 0xbf, 0xd9, 0xef, 0x0f, 0x57, 0x89, 0x49, 0xd6, 0xe1, 0x00, 0xb0, 0x05, + 0x5c, 0xb8, 0xf3, 0x31, + ], + k_enc: [ + 0xd3, 0xc2, 0x20, 0x51, 0x00, 0x3e, 0x88, 0x2a, 0x5d, 0xdd, 0xfb, 0x48, 0x23, 0xd6, + 0x77, 0x26, 0x96, 0xa7, 0xe9, 0x9f, 0x26, 0xb1, 0xa6, 0xac, 0xd2, 0x4b, 0xee, 0xd5, + 0xf2, 0x2f, 0x9f, 0xf8, + ], + p_enc: [ + 0x03, 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, 0x22, 0x92, + 0x4c, 0xd1, 0x3b, 0x5d, 0xd4, 0xee, 0xfc, 0x54, 0x88, 0x62, 0xf5, 0xa0, 0x70, 0x94, + 0xfd, 0x42, 0x8a, 0x7b, 0xbc, 0x15, 0xd7, 0xb3, 0x8d, 0x05, 0x36, 0x2c, 0x9c, 0xa9, + 0x85, 0xf5, 0x8a, 0x76, 0x64, 0x7d, 0x2b, 0xe4, 0xc2, 0xcd, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0x6b, 0x3d, 0x17, 0xd6, 0x87, 0x09, 0x71, 0xd7, 0xa0, 0x98, 0xba, 0xf7, 0x2c, + 0x6f, 0x6f, 0x12, 0x14, 0xcf, 0x1f, 0xaa, 0xe4, 0x88, 0xbd, 0x7d, 0xe2, 0x59, 0xd3, + 0x41, 0x5c, 0x2f, 0x0d, 0xde, 0xc7, 0x45, 0x70, 0x04, 0xf3, 0x57, 0x08, 0xd1, 0xec, + 0xcc, 0xcc, 0x0d, 0xf6, 0x5a, 0x04, 0x94, 0x3a, 0xd5, 0xcb, 0xc1, 0x3f, 0x29, 0x5f, + 0x00, 0x0f, 0xe0, 0x56, 0xc4, 0x0b, 0x2d, 0x88, 0xf2, 0x7d, 0xc3, 0x4c, 0xfe, 0xb8, + 0x03, 0xbe, 0x34, 0x83, 0xa9, 0xeb, 0xf9, 0xb5, 0xa9, 0x02, 0x60, 0x57, 0x72, 0x5d, + 0x63, 0xea, 0xd2, 0xc0, 0xc0, 0xff, 0x1f, 0xe2, 0x6a, 0xc1, 0xe7, 0xbd, 0xfc, 0xd6, + 0xfa, 0xd8, 0x75, 0x84, 0x2d, 0x19, 0x4f, 0x33, 0x17, 0x50, 0x46, 0x2c, 0x06, 0xb8, + 0xd7, 0x98, 0x2d, 0x67, 0x99, 0x5e, 0xd5, 0xd3, 0xae, 0x96, 0xa0, 0x5a, 0xe0, 0x06, + 0x7f, 0x4e, 0xb1, 0xc7, 0xc9, 0x32, 0x31, 0xbd, 0x39, 0x77, 0x3c, 0xbe, 0x0a, 0x9d, + 0x66, 0xb0, 0xc9, 0xaa, 0x8c, 0xff, 0x6a, 0x37, 0x6e, 0x1f, 0x37, 0x2e, 0xac, 0x6a, + 0xc4, 0xe4, 0x6c, 0xc0, 0x94, 0x22, 0x45, 0xd4, 0xc2, 0xdc, 0xf0, 0x2d, 0x76, 0x40, + 0xff, 0xcc, 0x5a, 0x6a, 0xc3, 0xa8, 0x7f, 0x5c, 0x41, 0x15, 0x51, 0xbc, 0xc2, 0xf2, + 0x6c, 0xb9, 0x49, 0x61, 0xd5, 0x3f, 0x95, 0xdd, 0xb1, 0x9a, 0xe9, 0x30, 0xc8, 0xd7, + 0x0f, 0x03, 0x1b, 0x29, 0xa5, 0xdf, 0x99, 0xff, 0x36, 0x69, 0x5e, 0x80, 0x2c, 0xbc, + 0xb6, 0xb5, 0x8c, 0x1b, 0xa7, 0xed, 0x5e, 0xac, 0xfa, 0x76, 0x41, 0x4a, 0x41, 0xad, + 0x4a, 0x44, 0xf7, 0x1f, 0x1b, 0x58, 0x0d, 0x34, 0xc3, 0xa9, 0x52, 0x92, 0x0b, 0x25, + 0x4a, 0x14, 0x5f, 0xea, 0x51, 0x7f, 0x5b, 0x42, 0xb2, 0xf6, 0x5e, 0xcd, 0x0f, 0x82, + 0x59, 0x54, 0x78, 0xd8, 0x0a, 0xe5, 0xc8, 0xce, 0xea, 0x12, 0xa1, 0x61, 0xcc, 0xbb, + 0x5e, 0xac, 0x09, 0x99, 0x0f, 0xc6, 0x19, 0xa4, 0x60, 0x80, 0x43, 0x6d, 0xbd, 0x08, + 0xd7, 0x47, 0x84, 0xaf, 0x00, 0x2d, 0x58, 0xe0, 0x6f, 0xaf, 0x7f, 0x3c, 0xea, 0xe7, + 0xd3, 0x41, 0x9b, 0x1f, 0xca, 0x26, 0x5a, 0x55, 0x59, 0xcf, 0x9e, 0x2d, 0x3b, 0x60, + 0x97, 0x8d, 0x81, 0xa6, 0x78, 0xb9, 0xed, 0x8e, 0x44, 0x86, 0xb4, 0xd1, 0x46, 0x09, + 0xd6, 0xc1, 0x27, 0xc0, 0xc2, 0xfb, 0xff, 0xe3, 0x0a, 0x60, 0xf7, 0xbf, 0xf1, 0xd9, + 0xfb, 0x83, 0x00, 0xed, 0x00, 0x92, 0x53, 0xba, 0x9b, 0x99, 0x6f, 0xa0, 0x52, 0x41, + 0xb1, 0x0f, 0x5a, 0xc9, 0xa8, 0x40, 0x8e, 0x92, 0x5b, 0x62, 0x6b, 0xb2, 0x1a, 0x47, + 0x1f, 0xe3, 0xbe, 0xde, 0x52, 0xbb, 0xa0, 0x97, 0xb2, 0xa9, 0x9a, 0x9b, 0xa5, 0xa8, + 0x66, 0x58, 0xc3, 0xfd, 0x9e, 0xc5, 0x5b, 0xfa, 0x9b, 0x32, 0x85, 0x67, 0x25, 0x4a, + 0xb3, 0x6d, 0x2c, 0x7f, 0x44, 0xd2, 0xc7, 0xe1, 0x3e, 0xb5, 0x4b, 0xeb, 0x70, 0xea, + 0x8f, 0xa9, 0x4b, 0x6c, 0x6e, 0x01, 0x2d, 0x79, 0xe3, 0xf5, 0x36, 0x89, 0xc2, 0xb1, + 0xa1, 0x8e, 0xaf, 0x2d, 0x47, 0x1d, 0x13, 0xc1, 0xab, 0x39, 0xd9, 0x19, 0x4a, 0xe8, + 0x43, 0xab, 0x1d, 0x28, 0xff, 0xa8, 0xf6, 0x9d, 0xc7, 0xe1, 0x5c, 0xc3, 0x8b, 0x12, + 0xe8, 0xfc, 0xd7, 0x92, 0x55, 0xb7, 0x21, 0x60, 0x56, 0xd9, 0xed, 0xb7, 0x48, 0x2f, + 0xb9, 0x8a, 0xa0, 0x33, 0xb6, 0x5e, 0x51, 0xc1, 0xa0, 0x8b, 0x8a, 0x11, 0xd8, 0x4d, + 0x04, 0x09, 0xb7, 0x34, 0xf4, 0x52, 0xaa, 0xf0, 0xd6, 0xb1, 0x8f, 0x50, 0x25, 0x86, + 0x83, 0xd3, 0xf9, 0xa7, 0x6d, 0x39, 0x9f, 0xd0, 0x47, 0xee, 0xe2, 0x88, 0xbb, 0x45, + 0x85, 0x85, 0x1d, 0xc9, 0x3e, 0xcc, 0xc6, 0x23, + ], + c_enc: [ + 0x73, 0x29, 0xa0, 0xa5, 0x6a, 0x14, 0x4b, 0x04, 0x2c, 0x1e, 0xad, 0x91, 0x80, 0xac, + 0x54, 0xda, 0xc6, 0xc5, 0x5c, 0xf4, 0xc2, 0x2f, 0xbe, 0x7c, 0xde, 0x99, 0x96, 0x0b, + 0xc6, 0x20, 0xd4, 0xdd, 0x60, 0xe4, 0xbf, 0x18, 0xa0, 0xea, 0x7a, 0xd9, 0x09, 0x3b, + 0xcd, 0x3f, 0xf6, 0xd1, 0x61, 0x1c, 0x56, 0x5f, 0x88, 0xe7, 0xad, 0xc7, 0x88, 0x7c, + 0x34, 0x4d, 0x78, 0x79, 0x73, 0x3d, 0x26, 0x30, 0xbd, 0x45, 0x07, 0x25, 0xcd, 0xfc, + 0xef, 0x8f, 0xe4, 0x0f, 0xf0, 0xdc, 0x6f, 0x45, 0x9e, 0xc6, 0x67, 0x38, 0x5a, 0x94, + 0xfb, 0x63, 0x44, 0x5a, 0x61, 0xc7, 0x3d, 0x9d, 0x16, 0x1b, 0x77, 0x06, 0xf6, 0xb3, + 0x26, 0xf4, 0x07, 0xc2, 0xde, 0x59, 0xe3, 0xe6, 0x01, 0xdb, 0xa0, 0x00, 0xe7, 0x73, + 0x81, 0x5d, 0xb0, 0x97, 0x22, 0xe9, 0xbd, 0x23, 0x07, 0x4d, 0x20, 0x6d, 0xbe, 0xfd, + 0x0b, 0x7f, 0x8b, 0x55, 0x14, 0xee, 0x62, 0x46, 0xb5, 0xde, 0x97, 0x68, 0xad, 0x50, + 0x18, 0x17, 0xa4, 0x42, 0x04, 0x87, 0x07, 0x78, 0x61, 0xa0, 0x6c, 0xf5, 0xfa, 0xa0, + 0xae, 0x0d, 0xf9, 0x03, 0x02, 0x51, 0xa9, 0xe3, 0x9e, 0x7c, 0xde, 0x48, 0x3e, 0xd8, + 0x28, 0xd8, 0xb2, 0x7e, 0xbd, 0x6d, 0xa9, 0xca, 0x96, 0x54, 0xaf, 0xc1, 0xdf, 0x94, + 0x00, 0xb2, 0xbe, 0xc7, 0x60, 0xfb, 0x26, 0x00, 0xa4, 0x53, 0x67, 0x3f, 0x6e, 0x7c, + 0x89, 0x4b, 0x9c, 0xcd, 0x8a, 0x57, 0x2d, 0x24, 0xa5, 0x47, 0x31, 0x22, 0xfe, 0x40, + 0x06, 0xe8, 0x0c, 0x9a, 0x97, 0x5e, 0x93, 0xbe, 0xc5, 0x7e, 0xbc, 0x4c, 0x44, 0xb2, + 0x8e, 0xb0, 0x1f, 0xbc, 0xb2, 0xb2, 0xde, 0x55, 0x9b, 0xf0, 0x2d, 0x7b, 0x2c, 0xe4, + 0xf3, 0xd1, 0x1e, 0x86, 0xcb, 0xaa, 0x10, 0x00, 0xee, 0xbd, 0x0d, 0x1b, 0x58, 0x8c, + 0x99, 0xd7, 0xf9, 0xd9, 0x57, 0xc6, 0x4e, 0x0a, 0x1e, 0x59, 0x67, 0x66, 0xe7, 0x6c, + 0x0e, 0xdc, 0xc6, 0xd9, 0xef, 0x34, 0x58, 0x74, 0x52, 0x04, 0x46, 0x39, 0x48, 0xd9, + 0x78, 0xd1, 0x3c, 0x4b, 0xc0, 0xf4, 0x2c, 0xc9, 0xb8, 0x93, 0x65, 0x27, 0x71, 0xf6, + 0xd1, 0x17, 0x7c, 0x78, 0x58, 0xf5, 0x77, 0x03, 0xec, 0x38, 0x3c, 0x3b, 0xad, 0x82, + 0x1b, 0x2f, 0x82, 0x87, 0x9c, 0x3e, 0x1d, 0x39, 0x91, 0xd2, 0x09, 0xb5, 0xc8, 0x94, + 0xc4, 0x65, 0xdd, 0x5e, 0xd9, 0x57, 0x19, 0x27, 0x2f, 0x9f, 0x03, 0x4c, 0xd9, 0x41, + 0xa0, 0x32, 0x33, 0xe1, 0x10, 0xd5, 0x80, 0xc1, 0x93, 0xc1, 0x9a, 0x92, 0x91, 0x19, + 0x45, 0x5a, 0xa6, 0x2e, 0x10, 0x35, 0x78, 0xa2, 0xd6, 0x46, 0x06, 0x26, 0xba, 0x04, + 0x37, 0x82, 0xb8, 0xd1, 0x3a, 0x31, 0x4e, 0x51, 0xf4, 0xa2, 0x81, 0x59, 0x32, 0x5f, + 0xbb, 0x35, 0xbe, 0xbb, 0xba, 0xf5, 0x27, 0x25, 0x64, 0xa7, 0xf5, 0x3f, 0x4c, 0x38, + 0xb0, 0xf6, 0xea, 0xed, 0x1a, 0xfc, 0x71, 0x31, 0x59, 0x87, 0xac, 0xbc, 0x95, 0x91, + 0x82, 0xab, 0xd3, 0xee, 0x9d, 0x87, 0x18, 0xc2, 0x26, 0x2f, 0x53, 0x1b, 0xfb, 0x57, + 0x1b, 0xb7, 0x4e, 0x9a, 0xf3, 0x63, 0x61, 0x36, 0x75, 0xce, 0xed, 0x6f, 0x97, 0xbe, + 0x67, 0x4c, 0x43, 0xf2, 0xad, 0x13, 0xdf, 0x86, 0x8d, 0xf6, 0xd4, 0x6f, 0x80, 0x72, + 0x6b, 0xe7, 0x88, 0x79, 0x04, 0xdf, 0x5b, 0x6b, 0xb5, 0x15, 0x7a, 0x87, 0x42, 0x06, + 0xe1, 0x77, 0x8a, 0x5d, 0x08, 0x4f, 0xd7, 0x60, 0x98, 0x6d, 0xb8, 0x39, 0xb0, 0xd9, + 0x6c, 0xcd, 0x41, 0x34, 0x38, 0xef, 0x02, 0xc7, 0x9e, 0xba, 0xc9, 0xe7, 0x49, 0xf8, + 0x93, 0x60, 0xb7, 0x5d, 0xcd, 0x1e, 0xb7, 0x73, 0x94, 0x73, 0xe3, 0x1f, 0xa9, 0xca, + 0xe4, 0x94, 0x30, 0x6e, 0xa4, 0x82, 0x4a, 0xb4, 0xa9, 0xbf, 0x92, 0x5d, 0xb7, 0x4c, + 0xf3, 0xdb, 0xac, 0x38, 0x93, 0xe7, 0xf0, 0x71, 0x00, 0x77, 0xff, 0x37, 0x90, 0x2d, + 0x18, 0x7f, 0xce, 0xbe, 0xf9, 0x76, 0xd6, 0x2c, 0xae, 0xfd, 0xcc, 0x14, 0x8c, 0x68, + 0xd7, 0x7e, 0x3e, 0xb2, 0x1d, 0xd5, 0x0c, 0x34, 0x01, 0x08, 0x34, 0x23, 0xf0, 0x38, + 0x11, 0x73, 0x0b, 0xc5, 0xf8, 0x14, 0xe0, 0x99, 0x02, 0xf0, 0x60, 0x80, 0xbf, 0xb4, + 0x8b, 0x34, 0x1e, 0xce, 0x80, 0xac, 0x29, 0xcb, 0x41, 0xe3, 0x20, 0x9d, 0x07, 0x9a, + 0xc8, 0x4e, 0x85, 0x1b, 0xfb, 0x26, 0xdd, 0x39, 0xd9, 0x66, 0x2a, 0x11, 0x90, 0x28, + 0x17, 0xb0, 0x8d, 0xa3, 0x89, 0x7a, 0x5c, 0x87, 0x62, 0x22, + ], + ock: [ + 0x1b, 0xa4, 0xac, 0xd7, 0x75, 0x10, 0xc4, 0xf0, 0xc7, 0x66, 0xad, 0xf7, 0xc7, 0xdf, + 0x1d, 0x1c, 0x54, 0xd5, 0xbc, 0xe3, 0xd6, 0x0a, 0xf3, 0x5e, 0x8d, 0xd4, 0x8f, 0xdd, + 0x04, 0xa7, 0x8c, 0x0b, + ], + op: [ + 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, + 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, + 0x01, 0x70, 0x89, 0x1a, 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, + 0x6b, 0xa0, 0x02, 0x0c, 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, + 0x57, 0x32, 0x63, 0xf4, 0x99, 0xbd, 0x4c, 0x13, + ], + c_out: [ + 0x43, 0x0d, 0xaa, 0x6b, 0x75, 0x63, 0x22, 0x80, 0xd5, 0xe6, 0xda, 0xcb, 0xd2, 0xa0, + 0xff, 0xe2, 0xaf, 0x98, 0x60, 0xc8, 0x3a, 0x3d, 0x2a, 0x87, 0xf1, 0x79, 0x62, 0x88, + 0xeb, 0xed, 0x64, 0xd0, 0xcd, 0xc4, 0x60, 0xe2, 0xc8, 0x61, 0xc4, 0xf9, 0x38, 0x7d, + 0x92, 0x59, 0xfc, 0x60, 0x01, 0xac, 0xd0, 0xe7, 0x6f, 0x3b, 0x0f, 0xdb, 0x5d, 0xac, + 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, + 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xa4, 0xd7, 0x9c, 0x81, 0x9a, 0x6c, 0x5e, 0x01, 0x67, 0xfc, 0xa9, 0x8c, 0xe2, 0x62, + 0x98, 0x15, 0xf9, 0xba, 0xc9, 0x26, 0xb6, 0x27, 0x18, 0xcf, 0xbe, 0x50, 0x45, 0xd9, + 0x2d, 0xd7, 0x1c, 0xd3, 0x36, 0x75, 0xd5, 0x56, 0xe0, 0x77, 0x1e, 0x40, 0xcc, 0x3d, + 0x61, 0x8d, 0x9b, 0xda, 0x13, 0x2f, 0x13, 0x95, 0x3d, 0x82, 0x43, 0x2e, 0x81, 0x59, + 0x4a, 0x97, 0x1e, 0x98, 0xb0, 0x71, 0x40, 0x39, + ], + ovk: [ + 0x67, 0x79, 0x9a, 0x90, 0x01, 0xa2, 0xed, 0x36, 0x76, 0xa8, 0xb4, 0x03, 0xae, 0x25, + 0xff, 0xd7, 0x72, 0xf7, 0x08, 0x1e, 0x9a, 0x32, 0xbc, 0xc1, 0xc5, 0xe2, 0xed, 0xd4, + 0xe2, 0xa6, 0x57, 0x6b, + ], + default_d: [ + 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, + ], + default_pk_d: [ + 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, + 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, + 0x44, 0x6d, 0xf4, 0x39, + ], + v: 7122345086698755501, + rseed: [ + 0x2d, 0xd4, 0x17, 0xdf, 0x26, 0xdc, 0xd2, 0x20, 0xf2, 0xb7, 0x31, 0x77, 0x2b, 0x43, + 0x9e, 0x96, 0xd6, 0x14, 0xe1, 0xfa, 0xcb, 0x48, 0x6c, 0x7a, 0x7d, 0x51, 0x71, 0xb1, + 0xde, 0x35, 0x9f, 0x6a, + ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], + memo: [ + 0xff, 0xd3, 0xa9, 0x6f, 0x64, 0x9c, 0x96, 0x91, 0x02, 0xa1, 0x96, 0x4f, 0xb4, 0xb4, + 0xa1, 0xa4, 0x27, 0x9c, 0x68, 0xe6, 0xc3, 0x72, 0xe4, 0x21, 0x87, 0xd7, 0x54, 0xe8, + 0x04, 0xa6, 0x16, 0x53, 0x09, 0x20, 0x69, 0xfb, 0x9b, 0x6d, 0x25, 0x26, 0x68, 0x90, + 0x80, 0x8b, 0x01, 0x5d, 0xf2, 0x8c, 0x80, 0x10, 0x65, 0xda, 0x6f, 0xeb, 0xdc, 0x1a, + 0x56, 0xbf, 0xd0, 0x02, 0x62, 0x5a, 0xcf, 0xaa, 0x53, 0x73, 0xfd, 0xe1, 0x49, 0xc1, + 0xcf, 0xc3, 0x64, 0x9b, 0x48, 0x69, 0x69, 0x6d, 0x44, 0xec, 0xb1, 0x24, 0x79, 0xc5, + 0xeb, 0xef, 0x99, 0x5f, 0x10, 0x02, 0x9f, 0x8b, 0x53, 0x0e, 0xeb, 0x3f, 0xdc, 0x2e, + 0x50, 0xe8, 0x75, 0x7f, 0xc0, 0xbb, 0x9e, 0x26, 0x30, 0x23, 0xdb, 0x82, 0xf8, 0x78, + 0xd9, 0xac, 0x7f, 0xfb, 0x0b, 0xd4, 0x39, 0x1d, 0xf1, 0xd8, 0x79, 0x89, 0x9a, 0x3e, + 0xf5, 0x7b, 0xfd, 0x0d, 0x1f, 0x77, 0x55, 0x64, 0x8e, 0xdd, 0x85, 0xbb, 0x05, 0x2a, + 0x6e, 0xdf, 0x71, 0xcd, 0x26, 0x28, 0xc9, 0x87, 0x42, 0x9f, 0x36, 0xdc, 0x50, 0x5c, + 0xcc, 0x43, 0xf3, 0x0e, 0x7a, 0x86, 0x9c, 0x9e, 0x25, 0x5e, 0x2a, 0xf9, 0xfc, 0xf3, + 0x0c, 0x12, 0x17, 0x96, 0xd1, 0x90, 0x00, 0x09, 0x60, 0xcb, 0x6f, 0xe2, 0xf1, 0xbf, + 0x24, 0x61, 0x18, 0xb4, 0x98, 0xf3, 0x24, 0x7f, 0x9d, 0x48, 0x4c, 0x73, 0xcf, 0x09, + 0x39, 0x30, 0x39, 0xe4, 0x53, 0x26, 0xb8, 0xff, 0xff, 0xb3, 0xe7, 0xe6, 0x15, 0x9c, + 0x46, 0x69, 0x9f, 0x10, 0x07, 0x92, 0xd4, 0x67, 0x29, 0x50, 0x34, 0x8a, 0x90, 0x55, + 0x2e, 0x45, 0x94, 0x3b, 0xee, 0xac, 0xf0, 0x3f, 0x32, 0x16, 0xf9, 0x4e, 0x27, 0x4d, + 0x63, 0xd6, 0x37, 0xd9, 0xf1, 0x90, 0xe8, 0xa2, 0x66, 0xcd, 0xee, 0xf1, 0x53, 0x53, + 0x0b, 0xee, 0x5c, 0xb8, 0x35, 0x52, 0x60, 0x50, 0x5c, 0x2c, 0x2e, 0x5d, 0x99, 0x0f, + 0xff, 0xdc, 0x34, 0xec, 0x0f, 0xf7, 0xf1, 0xaf, 0x81, 0xb2, 0x4c, 0xed, 0x0e, 0xfa, + 0x62, 0x13, 0xda, 0x6c, 0x7c, 0x60, 0xc4, 0x87, 0xf5, 0xf7, 0xb0, 0x3f, 0x81, 0x60, + 0xa0, 0x57, 0xf4, 0x6d, 0x05, 0xbf, 0x82, 0x18, 0xb3, 0xad, 0xd9, 0xc0, 0x68, 0x93, + 0xbd, 0x02, 0xdb, 0x9b, 0x61, 0x19, 0x1d, 0xfb, 0x13, 0x3b, 0xfa, 0xbe, 0x48, 0x58, + 0xe4, 0x7a, 0x4c, 0xc3, 0x2e, 0x41, 0x6e, 0xc0, 0x8b, 0x8a, 0xc7, 0x91, 0x5a, 0x43, + 0x73, 0x3f, 0x44, 0x06, 0xe9, 0xd9, 0x67, 0xc5, 0x60, 0xf3, 0x44, 0xd7, 0xe9, 0x04, + 0xa2, 0x80, 0x45, 0xd9, 0x9f, 0x3a, 0xf8, 0xc8, 0x2e, 0x97, 0xe1, 0xb9, 0xc1, 0xb2, + 0x05, 0xe5, 0x85, 0xfb, 0xeb, 0xb4, 0x8f, 0xaf, 0x58, 0xf1, 0xb6, 0x5d, 0xca, 0x24, + 0x97, 0xe0, 0x9a, 0x70, 0xaa, 0xd4, 0x86, 0x5f, 0x85, 0x71, 0x5a, 0x28, 0x0e, 0x18, + 0x6f, 0x3f, 0xc1, 0x74, 0x0d, 0x81, 0x84, 0xd3, 0x3e, 0x83, 0x22, 0x16, 0x95, 0x21, + 0xcd, 0xc1, 0x32, 0x21, 0x29, 0x39, 0xc8, 0x4a, 0x10, 0x89, 0x64, 0xe2, 0xde, 0x74, + 0xb6, 0xea, 0x55, 0xb4, 0xcb, 0x8f, 0x6f, 0x9b, 0xee, 0x98, 0xb1, 0x0d, 0x41, 0x51, + 0x09, 0x45, 0x5f, 0x48, 0xb7, 0x76, 0x08, 0x2d, 0xc3, 0x0b, 0x4b, 0xc7, 0x34, 0x77, + 0x07, 0x55, 0x11, 0x70, 0x03, 0x08, 0x15, 0x8c, 0xe2, 0xf2, 0xf9, 0xbf, 0x0f, 0x69, + 0x1b, 0x2c, 0xe5, 0x3e, 0x61, 0x14, 0x2c, 0xb7, 0x40, 0xc1, 0x5b, 0x7b, 0x62, 0x3c, + 0xf4, 0x8b, 0x3f, 0x7b, 0xfe, 0xfa, 0x31, 0xbc, 0xdc, 0x66, 0x5c, 0x6d, 0x71, 0x23, + 0xe9, 0x53, 0x50, 0x81, 0x13, 0x75, 0x94, 0x7b, 0x05, 0x5a, 0x43, 0xdb, 0x07, 0xe0, + 0x3f, 0x33, 0x62, 0x7d, 0xf5, 0xc6, 0x38, 0xbf, + ], + cv_net: [ + 0x00, 0x55, 0xf3, 0x5c, 0x6c, 0x82, 0x62, 0xac, 0x74, 0xfe, 0x27, 0xd7, 0x2a, 0x33, + 0xbd, 0xb9, 0x6f, 0x1c, 0xe0, 0x57, 0xc3, 0x30, 0xd1, 0xcc, 0xba, 0x2f, 0x7d, 0xa8, + 0x71, 0x55, 0x00, 0xb5, + ], + rho: [ + 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, + 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, + 0xa3, 0x18, 0x53, 0x3e, + ], + cmx: [ + 0x6a, 0xba, 0x28, 0x10, 0x5b, 0xc0, 0x72, 0xc5, 0x2a, 0xb8, 0xa3, 0x14, 0x79, 0x7f, + 0xf8, 0x66, 0x66, 0xdf, 0xb7, 0xcd, 0x8a, 0x2a, 0xe1, 0x7c, 0x58, 0x5f, 0xb7, 0xb6, + 0x51, 0x5b, 0x97, 0x1c, + ], + esk: [ + 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, 0xd5, 0x64, 0x6b, 0xc4, + 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, 0x15, 0x5b, 0xef, 0x4d, + 0x46, 0x1e, 0xec, 0x29, + ], + ephemeral_key: [ + 0x95, 0x9b, 0xea, 0x8e, 0x11, 0x96, 0x8b, 0x0f, 0x34, 0x3c, 0x04, 0xcd, 0x6d, 0x50, + 0x16, 0xfc, 0xd4, 0x33, 0x90, 0x75, 0x36, 0xa2, 0x46, 0xba, 0x1c, 0x5d, 0x3e, 0x88, + 0x97, 0xf3, 0x23, 0x1c, + ], + shared_secret: [ + 0xe2, 0x69, 0x19, 0xb4, 0x0c, 0x70, 0xaf, 0x74, 0x1d, 0xf9, 0x04, 0x51, 0x72, 0x55, + 0x03, 0x58, 0x89, 0xee, 0x5a, 0x44, 0x42, 0x6d, 0x6a, 0xb8, 0x5c, 0x07, 0x4b, 0x86, + 0x2b, 0xa0, 0x63, 0x08, + ], + k_enc: [ + 0x09, 0xda, 0xc6, 0x51, 0x1c, 0x38, 0x44, 0x58, 0x7f, 0x82, 0x9c, 0x2f, 0x1e, 0xa0, + 0x37, 0xa8, 0x1a, 0x8d, 0x54, 0x85, 0xed, 0x04, 0xea, 0xf2, 0x75, 0x80, 0x05, 0xb3, + 0x2a, 0x20, 0x47, 0x0b, + ], + p_enc: [ + 0x03, 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, 0xad, 0x95, + 0x6d, 0xdc, 0x1e, 0xa7, 0xd7, 0x62, 0x2d, 0xd4, 0x17, 0xdf, 0x26, 0xdc, 0xd2, 0x20, + 0xf2, 0xb7, 0x31, 0x77, 0x2b, 0x43, 0x9e, 0x96, 0xd6, 0x14, 0xe1, 0xfa, 0xcb, 0x48, + 0x6c, 0x7a, 0x7d, 0x51, 0x71, 0xb1, 0xde, 0x35, 0x9f, 0x6a, 0x67, 0x43, 0xf9, 0x3a, + 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, + 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, + 0xff, 0xd3, 0xa9, 0x6f, 0x64, 0x9c, 0x96, 0x91, 0x02, 0xa1, 0x96, 0x4f, 0xb4, 0xb4, + 0xa1, 0xa4, 0x27, 0x9c, 0x68, 0xe6, 0xc3, 0x72, 0xe4, 0x21, 0x87, 0xd7, 0x54, 0xe8, + 0x04, 0xa6, 0x16, 0x53, 0x09, 0x20, 0x69, 0xfb, 0x9b, 0x6d, 0x25, 0x26, 0x68, 0x90, + 0x80, 0x8b, 0x01, 0x5d, 0xf2, 0x8c, 0x80, 0x10, 0x65, 0xda, 0x6f, 0xeb, 0xdc, 0x1a, + 0x56, 0xbf, 0xd0, 0x02, 0x62, 0x5a, 0xcf, 0xaa, 0x53, 0x73, 0xfd, 0xe1, 0x49, 0xc1, + 0xcf, 0xc3, 0x64, 0x9b, 0x48, 0x69, 0x69, 0x6d, 0x44, 0xec, 0xb1, 0x24, 0x79, 0xc5, + 0xeb, 0xef, 0x99, 0x5f, 0x10, 0x02, 0x9f, 0x8b, 0x53, 0x0e, 0xeb, 0x3f, 0xdc, 0x2e, + 0x50, 0xe8, 0x75, 0x7f, 0xc0, 0xbb, 0x9e, 0x26, 0x30, 0x23, 0xdb, 0x82, 0xf8, 0x78, + 0xd9, 0xac, 0x7f, 0xfb, 0x0b, 0xd4, 0x39, 0x1d, 0xf1, 0xd8, 0x79, 0x89, 0x9a, 0x3e, + 0xf5, 0x7b, 0xfd, 0x0d, 0x1f, 0x77, 0x55, 0x64, 0x8e, 0xdd, 0x85, 0xbb, 0x05, 0x2a, + 0x6e, 0xdf, 0x71, 0xcd, 0x26, 0x28, 0xc9, 0x87, 0x42, 0x9f, 0x36, 0xdc, 0x50, 0x5c, + 0xcc, 0x43, 0xf3, 0x0e, 0x7a, 0x86, 0x9c, 0x9e, 0x25, 0x5e, 0x2a, 0xf9, 0xfc, 0xf3, + 0x0c, 0x12, 0x17, 0x96, 0xd1, 0x90, 0x00, 0x09, 0x60, 0xcb, 0x6f, 0xe2, 0xf1, 0xbf, + 0x24, 0x61, 0x18, 0xb4, 0x98, 0xf3, 0x24, 0x7f, 0x9d, 0x48, 0x4c, 0x73, 0xcf, 0x09, + 0x39, 0x30, 0x39, 0xe4, 0x53, 0x26, 0xb8, 0xff, 0xff, 0xb3, 0xe7, 0xe6, 0x15, 0x9c, + 0x46, 0x69, 0x9f, 0x10, 0x07, 0x92, 0xd4, 0x67, 0x29, 0x50, 0x34, 0x8a, 0x90, 0x55, + 0x2e, 0x45, 0x94, 0x3b, 0xee, 0xac, 0xf0, 0x3f, 0x32, 0x16, 0xf9, 0x4e, 0x27, 0x4d, + 0x63, 0xd6, 0x37, 0xd9, 0xf1, 0x90, 0xe8, 0xa2, 0x66, 0xcd, 0xee, 0xf1, 0x53, 0x53, + 0x0b, 0xee, 0x5c, 0xb8, 0x35, 0x52, 0x60, 0x50, 0x5c, 0x2c, 0x2e, 0x5d, 0x99, 0x0f, + 0xff, 0xdc, 0x34, 0xec, 0x0f, 0xf7, 0xf1, 0xaf, 0x81, 0xb2, 0x4c, 0xed, 0x0e, 0xfa, + 0x62, 0x13, 0xda, 0x6c, 0x7c, 0x60, 0xc4, 0x87, 0xf5, 0xf7, 0xb0, 0x3f, 0x81, 0x60, + 0xa0, 0x57, 0xf4, 0x6d, 0x05, 0xbf, 0x82, 0x18, 0xb3, 0xad, 0xd9, 0xc0, 0x68, 0x93, + 0xbd, 0x02, 0xdb, 0x9b, 0x61, 0x19, 0x1d, 0xfb, 0x13, 0x3b, 0xfa, 0xbe, 0x48, 0x58, + 0xe4, 0x7a, 0x4c, 0xc3, 0x2e, 0x41, 0x6e, 0xc0, 0x8b, 0x8a, 0xc7, 0x91, 0x5a, 0x43, + 0x73, 0x3f, 0x44, 0x06, 0xe9, 0xd9, 0x67, 0xc5, 0x60, 0xf3, 0x44, 0xd7, 0xe9, 0x04, + 0xa2, 0x80, 0x45, 0xd9, 0x9f, 0x3a, 0xf8, 0xc8, 0x2e, 0x97, 0xe1, 0xb9, 0xc1, 0xb2, + 0x05, 0xe5, 0x85, 0xfb, 0xeb, 0xb4, 0x8f, 0xaf, 0x58, 0xf1, 0xb6, 0x5d, 0xca, 0x24, + 0x97, 0xe0, 0x9a, 0x70, 0xaa, 0xd4, 0x86, 0x5f, 0x85, 0x71, 0x5a, 0x28, 0x0e, 0x18, + 0x6f, 0x3f, 0xc1, 0x74, 0x0d, 0x81, 0x84, 0xd3, 0x3e, 0x83, 0x22, 0x16, 0x95, 0x21, + 0xcd, 0xc1, 0x32, 0x21, 0x29, 0x39, 0xc8, 0x4a, 0x10, 0x89, 0x64, 0xe2, 0xde, 0x74, + 0xb6, 0xea, 0x55, 0xb4, 0xcb, 0x8f, 0x6f, 0x9b, 0xee, 0x98, 0xb1, 0x0d, 0x41, 0x51, + 0x09, 0x45, 0x5f, 0x48, 0xb7, 0x76, 0x08, 0x2d, 0xc3, 0x0b, 0x4b, 0xc7, 0x34, 0x77, + 0x07, 0x55, 0x11, 0x70, 0x03, 0x08, 0x15, 0x8c, 0xe2, 0xf2, 0xf9, 0xbf, 0x0f, 0x69, + 0x1b, 0x2c, 0xe5, 0x3e, 0x61, 0x14, 0x2c, 0xb7, 0x40, 0xc1, 0x5b, 0x7b, 0x62, 0x3c, + 0xf4, 0x8b, 0x3f, 0x7b, 0xfe, 0xfa, 0x31, 0xbc, 0xdc, 0x66, 0x5c, 0x6d, 0x71, 0x23, + 0xe9, 0x53, 0x50, 0x81, 0x13, 0x75, 0x94, 0x7b, 0x05, 0x5a, 0x43, 0xdb, 0x07, 0xe0, + 0x3f, 0x33, 0x62, 0x7d, 0xf5, 0xc6, 0x38, 0xbf, + ], + c_enc: [ + 0x7a, 0x59, 0x87, 0x78, 0xa7, 0x28, 0x4d, 0x52, 0xa7, 0x47, 0x77, 0x4c, 0x54, 0xbd, + 0x92, 0x57, 0xb3, 0xf1, 0x7a, 0xf1, 0x3e, 0xcc, 0x72, 0xc0, 0xe3, 0xcd, 0x95, 0xeb, + 0xfa, 0xfa, 0xa3, 0x7d, 0x16, 0x65, 0x15, 0x53, 0xdd, 0x27, 0xf0, 0x1c, 0x9c, 0xf2, + 0x4b, 0x62, 0xd7, 0xdc, 0xfd, 0x52, 0xfa, 0x4b, 0x2b, 0x3b, 0xd2, 0x1c, 0xf9, 0xbe, + 0xf6, 0xc6, 0xc5, 0x47, 0x62, 0xfa, 0x2a, 0x61, 0x45, 0x53, 0xcd, 0x9b, 0x45, 0x3e, + 0x23, 0xbe, 0x78, 0x88, 0x56, 0x69, 0x77, 0xf6, 0xc4, 0xe0, 0xe7, 0x7c, 0x90, 0xe6, + 0x1b, 0x01, 0x1a, 0xe9, 0x95, 0x5e, 0x62, 0x87, 0x04, 0xd6, 0x20, 0x36, 0x6e, 0xda, + 0xef, 0xcc, 0x17, 0x13, 0xc7, 0x48, 0xc5, 0xb3, 0x6a, 0x32, 0x76, 0x51, 0xaf, 0x94, + 0xcf, 0x94, 0x82, 0x10, 0xb6, 0x10, 0x8b, 0xe4, 0x82, 0x5b, 0xe5, 0x75, 0x2e, 0x7f, + 0xcd, 0xe1, 0x2d, 0x1a, 0x03, 0x74, 0xa3, 0x85, 0xeb, 0x58, 0xfa, 0xde, 0x07, 0x3e, + 0x04, 0x87, 0xdc, 0x92, 0x17, 0x6c, 0x48, 0xc3, 0x6b, 0x7a, 0x2b, 0x34, 0x7a, 0x0f, + 0x96, 0x87, 0x5a, 0x31, 0x2a, 0xd5, 0x17, 0x9d, 0xa3, 0xfc, 0x81, 0x9c, 0xf0, 0xd4, + 0x8a, 0xb1, 0x46, 0xec, 0x2a, 0x2d, 0xd1, 0x45, 0xd7, 0x8d, 0x9d, 0x9f, 0x88, 0x84, + 0x82, 0x16, 0x55, 0x7d, 0x6e, 0x28, 0x30, 0x33, 0x56, 0xea, 0xfb, 0x2d, 0xbb, 0xe4, + 0xfd, 0x12, 0x24, 0x71, 0x37, 0x31, 0x73, 0x0e, 0xae, 0x6f, 0x52, 0x62, 0x5a, 0x59, + 0xe5, 0xb6, 0x06, 0xd2, 0xb2, 0x77, 0xe4, 0x09, 0x7e, 0x4f, 0x54, 0x24, 0x56, 0x84, + 0xeb, 0x3b, 0x64, 0xf5, 0x4d, 0xf6, 0x69, 0x7d, 0x6f, 0x39, 0x82, 0xba, 0xc4, 0x98, + 0xdf, 0x5a, 0x14, 0x43, 0x4f, 0x2e, 0x51, 0xab, 0x4c, 0xc2, 0x9d, 0x6f, 0x31, 0x28, + 0x8f, 0xf6, 0x67, 0x80, 0xb7, 0x89, 0xa8, 0x30, 0x6b, 0x20, 0xc6, 0x55, 0x3a, 0x52, + 0x46, 0x35, 0xb6, 0xec, 0xb6, 0x79, 0xe5, 0x03, 0x09, 0x54, 0x02, 0x96, 0xed, 0xef, + 0x53, 0x83, 0x31, 0x63, 0xc4, 0xa2, 0x86, 0x00, 0xd1, 0xca, 0xa8, 0x43, 0x7e, 0x6f, + 0xb9, 0xce, 0xc4, 0xb9, 0xea, 0xf5, 0x66, 0xe1, 0x7b, 0xe8, 0xf8, 0xcc, 0x34, 0xcd, + 0xdb, 0x35, 0x88, 0xce, 0xb2, 0xbf, 0xe8, 0x8c, 0xc3, 0xee, 0xb4, 0x1b, 0x92, 0x63, + 0x1f, 0x13, 0xc5, 0xeb, 0xa6, 0x86, 0x30, 0xbf, 0xa5, 0x35, 0x31, 0x30, 0x06, 0x57, + 0x49, 0x44, 0x83, 0x3c, 0xea, 0x59, 0xd9, 0xb2, 0xd1, 0x94, 0xd8, 0xc1, 0xac, 0xc1, + 0xa4, 0x17, 0x62, 0xf8, 0x98, 0x09, 0xf7, 0x8d, 0xab, 0xe9, 0x9b, 0x95, 0xb5, 0xdd, + 0xbe, 0xd1, 0xd0, 0x01, 0x03, 0x26, 0x84, 0x4f, 0x23, 0x04, 0x85, 0x84, 0xaa, 0x14, + 0x66, 0x0f, 0xe2, 0x54, 0x9c, 0xbe, 0xe9, 0xaf, 0x4b, 0x63, 0xdd, 0xde, 0x1c, 0xec, + 0x9f, 0x8d, 0x7c, 0xcb, 0xa6, 0x2a, 0x39, 0xf2, 0xf4, 0x48, 0x04, 0x96, 0xa1, 0x0f, + 0x17, 0xe9, 0xf9, 0x12, 0xc6, 0xc0, 0xa1, 0x3d, 0xbd, 0x90, 0x32, 0x60, 0x42, 0x89, + 0x4b, 0xcd, 0xf6, 0xa8, 0x07, 0x32, 0xc5, 0xfb, 0x03, 0x09, 0xee, 0xbd, 0xc4, 0x34, + 0x0c, 0x5e, 0xb5, 0x66, 0x41, 0x7c, 0xc6, 0xc8, 0xa6, 0xa6, 0x09, 0xdf, 0x5b, 0x41, + 0xc6, 0xc2, 0x95, 0xd6, 0x47, 0x3d, 0xab, 0xc7, 0x4c, 0xbb, 0x34, 0xb5, 0x5b, 0xa7, + 0x9a, 0x89, 0x46, 0x35, 0xa9, 0x00, 0x93, 0x27, 0xcc, 0x1e, 0x6d, 0x3e, 0x42, 0xba, + 0x3c, 0xba, 0xfb, 0x32, 0x1b, 0xc0, 0xb2, 0xee, 0x28, 0xe4, 0x1e, 0xf3, 0xba, 0xec, + 0xbe, 0x50, 0x46, 0x72, 0xf6, 0xe9, 0x35, 0x08, 0x66, 0x90, 0x87, 0xd5, 0x03, 0x34, + 0x36, 0x41, 0xb5, 0x9b, 0x90, 0x6a, 0x56, 0x4b, 0x7b, 0x67, 0x53, 0xd6, 0x19, 0xee, + 0xc4, 0xf5, 0xe8, 0x10, 0x62, 0x0e, 0x7b, 0x50, 0x65, 0x1a, 0xb6, 0x5e, 0x0a, 0x3d, + 0xbb, 0x1d, 0x0a, 0xb7, 0x72, 0x1c, 0x5b, 0xf0, 0xd5, 0x40, 0xe1, 0x30, 0x2d, 0x8c, + 0xce, 0x27, 0x07, 0x71, 0x91, 0x99, 0xfa, 0xa5, 0x32, 0x11, 0x06, 0xab, 0x06, 0x81, + 0x6a, 0x8c, 0x04, 0x6e, 0x47, 0x8b, 0xd5, 0xc3, 0xb4, 0x8f, 0xe6, 0x65, 0xc8, 0xd5, + 0x92, 0xfb, 0x30, 0x6b, 0xa9, 0x37, 0x10, 0x23, 0x30, 0xe4, 0x56, 0x48, 0xf1, 0xc1, + 0x6f, 0x3d, 0x1a, 0x96, 0x0f, 0x2f, 0x5f, 0x8c, 0x4d, 0x00, 0x12, 0x07, 0x8f, 0x9c, + 0xfd, 0xf6, 0xb6, 0x6d, 0xe9, 0x61, 0xca, 0x2e, 0x14, 0x0d, + ], + ock: [ + 0x4a, 0x25, 0x25, 0x4c, 0xcc, 0x44, 0x4e, 0xc6, 0x1c, 0x2b, 0xac, 0xeb, 0x2e, 0xe3, + 0x97, 0x7a, 0x63, 0x32, 0x44, 0x9a, 0x3a, 0x53, 0xad, 0xd2, 0x31, 0xab, 0xf3, 0xd1, + 0x8b, 0xb3, 0x29, 0x3d, + ], + op: [ + 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, + 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, + 0x44, 0x6d, 0xf4, 0x39, 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, + 0xd5, 0x64, 0x6b, 0xc4, 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, + 0x15, 0x5b, 0xef, 0x4d, 0x46, 0x1e, 0xec, 0x29, + ], + c_out: [ + 0x7b, 0xf4, 0x12, 0x7d, 0x22, 0xcc, 0x57, 0x35, 0x87, 0x51, 0x2f, 0xf8, 0x1e, 0x55, + 0x3e, 0x3c, 0x98, 0x23, 0x5f, 0x51, 0xc7, 0x23, 0x7e, 0x9e, 0x76, 0x1a, 0x08, 0xf2, + 0xe1, 0xe8, 0x0d, 0x04, 0x26, 0x98, 0xfc, 0x3b, 0x1d, 0x03, 0x18, 0xf1, 0xfd, 0xca, + 0x8e, 0x41, 0xa3, 0x16, 0xd6, 0xaf, 0x3a, 0xc0, 0xc4, 0x0c, 0xe1, 0x99, 0x47, 0xa2, + 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, + 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xdc, 0x10, 0x95, 0x20, 0x57, 0xc4, 0xbe, 0xaa, 0xd8, 0xaf, 0x37, 0xce, 0x4e, 0xee, + 0x9b, 0x10, 0xed, 0x84, 0xf4, 0x6b, 0xad, 0xd4, 0x8e, 0x0a, 0x22, 0x9b, 0xe8, 0x41, + 0x54, 0xa9, 0xbf, 0x75, 0x6b, 0xe0, 0x2e, 0xcf, 0xa9, 0xad, 0x6d, 0x9c, 0x02, 0xc8, + 0xf9, 0x54, 0xcb, 0x15, 0x71, 0x7b, 0x79, 0x46, 0x1f, 0x00, 0x4b, 0xf1, 0xbc, 0x5c, + 0x7e, 0x3f, 0xda, 0x73, 0x53, 0x7c, 0x1a, 0x0a, + ], + ovk: [ + 0x97, 0x74, 0x85, 0xcd, 0xdf, 0xbe, 0xd5, 0x93, 0x2f, 0x50, 0x7b, 0x79, 0x94, 0x7a, + 0xdb, 0x2f, 0xad, 0x37, 0x61, 0x5a, 0xa7, 0x17, 0xdb, 0x5f, 0x29, 0x80, 0x99, 0xf2, + 0x0f, 0x26, 0x3b, 0x35, + ], + default_d: [ + 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, + ], + default_pk_d: [ + 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, + 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, + 0xe6, 0x84, 0x45, 0xbb, + ], + v: 2111628168871420429, + rseed: [ + 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, + 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, + 0x3b, 0xd5, 0xbc, 0x87, + ], + asset: [ + 0xa9, 0x71, 0x5e, 0x65, 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, + 0x84, 0xef, 0xd9, 0x2c, 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, + 0x4f, 0x95, 0x22, 0xb2, + ], + memo: [ + 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, + 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, + 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, + 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, + 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, + 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, + 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, + 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, + 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, + 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, + 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, + 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, + 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, + 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, + 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, + 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, + 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, + 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, + 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, + 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, + 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, + 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, + 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, + 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, + 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, + 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, + 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, + 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, + 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, + 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, + 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, + 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, + 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, + 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, + 0xd8, 0x02, 0xf7, 0x73, 0x33, 0x49, 0x4a, 0x7a, 0xe1, 0x30, 0xfe, 0x86, 0xe8, 0xf8, + 0x18, 0xf9, 0x26, 0x1a, 0x2d, 0xad, 0xb4, 0x12, 0x52, 0x29, 0xba, 0x0f, 0xfc, 0x0e, + 0x70, 0x90, 0x32, 0x44, 0x30, 0xb5, 0x21, 0xa9, + ], + cv_net: [ + 0xba, 0x69, 0x9c, 0xe4, 0x21, 0x41, 0x85, 0x30, 0x94, 0xe2, 0x84, 0x00, 0x50, 0x17, + 0x2c, 0x3b, 0x94, 0x21, 0x3e, 0x86, 0x47, 0x3b, 0x5e, 0x2f, 0xdd, 0x70, 0x97, 0x80, + 0xbc, 0xca, 0x68, 0xb4, + ], + rho: [ + 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, + 0xa9, 0x4a, 0x06, 0x04, 0xb8, 0x00, 0x6c, 0xc7, 0x94, 0xbc, 0xab, 0x57, 0x73, 0x49, + 0xbc, 0xf8, 0x63, 0x37, + ], + cmx: [ + 0x85, 0xec, 0x16, 0xe8, 0x78, 0x77, 0x33, 0x37, 0x07, 0x9a, 0xec, 0xf3, 0x2c, 0x45, + 0x5e, 0xbf, 0x16, 0x96, 0x8d, 0xa1, 0xd4, 0x34, 0x51, 0xb7, 0xa3, 0x06, 0x87, 0x6c, + 0xa3, 0x08, 0xea, 0x3c, + ], + esk: [ + 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, 0x39, 0x16, 0x0f, 0xe5, + 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, 0xe0, 0xd2, 0x9b, 0x35, + 0x9a, 0xc4, 0xfa, 0x2c, + ], + ephemeral_key: [ + 0x10, 0x0d, 0xf0, 0x1d, 0x49, 0x86, 0x01, 0x21, 0x8a, 0x28, 0x6b, 0x8f, 0x4e, 0x54, + 0xda, 0x9b, 0x3f, 0x14, 0x5c, 0x34, 0x70, 0xa9, 0xdb, 0xc4, 0x14, 0x48, 0x0a, 0xa8, + 0xf2, 0xf4, 0x90, 0x9c, + ], + shared_secret: [ + 0x93, 0x68, 0xdd, 0x4f, 0x2a, 0xf6, 0x23, 0x34, 0xb8, 0x85, 0xb9, 0x6b, 0xc4, 0xc3, + 0x8f, 0x10, 0x3a, 0xec, 0x25, 0x6b, 0xed, 0xc2, 0x8b, 0x5e, 0x2e, 0x10, 0x36, 0x4c, + 0xdd, 0xf3, 0x84, 0xa4, + ], + k_enc: [ + 0x7a, 0xff, 0xfc, 0x6e, 0xae, 0x5d, 0x56, 0xb2, 0x7b, 0x86, 0xdb, 0x9e, 0xc8, 0xae, + 0xc2, 0x70, 0xbb, 0x0a, 0xb7, 0x31, 0x23, 0xfd, 0x2a, 0x0b, 0x83, 0xf4, 0xef, 0x84, + 0xc6, 0x98, 0xe1, 0x67, + ], + p_enc: [ + 0x03, 0xf6, 0xb0, 0x18, 0xdf, 0xa7, 0x26, 0x31, 0x5b, 0x44, 0xcf, 0x9e, 0x0d, 0x22, + 0x4a, 0xb7, 0xa1, 0x02, 0x4e, 0x1d, 0xcc, 0x57, 0x9a, 0x7a, 0x8f, 0xff, 0x7c, 0xa7, + 0xcf, 0x14, 0x5d, 0xfc, 0x13, 0xea, 0xfc, 0x34, 0x15, 0x3b, 0x2c, 0x3e, 0x8a, 0xfb, + 0xe5, 0x34, 0x44, 0xd0, 0xc7, 0x3b, 0x3b, 0xd5, 0xbc, 0x87, 0xa9, 0x71, 0x5e, 0x65, + 0xaf, 0x82, 0x67, 0x37, 0x3d, 0x34, 0x51, 0x67, 0x4f, 0xf0, 0x84, 0xef, 0xd9, 0x2c, + 0xcf, 0x3b, 0xcc, 0x7a, 0xca, 0x14, 0x67, 0xb6, 0x32, 0x7e, 0x4f, 0x95, 0x22, 0xb2, + 0xff, 0x0b, 0x01, 0xcd, 0x45, 0x79, 0x11, 0xe3, 0x56, 0x31, 0x3f, 0xd1, 0xda, 0xfb, + 0x4c, 0x81, 0x51, 0x63, 0x4a, 0x01, 0xaf, 0xf7, 0xcf, 0x11, 0x6d, 0x43, 0x3c, 0x3d, + 0x2b, 0x3a, 0xdd, 0xa9, 0xce, 0xbe, 0x18, 0xf7, 0xd1, 0x72, 0x44, 0x3e, 0x5e, 0x7b, + 0x5a, 0xc9, 0xab, 0xe8, 0xdb, 0x22, 0x56, 0xd7, 0xeb, 0xe2, 0xff, 0x28, 0x02, 0x09, + 0x39, 0x50, 0x38, 0x70, 0x59, 0x7b, 0x9a, 0x95, 0x58, 0x92, 0xc7, 0x38, 0x96, 0x50, + 0xa2, 0xd4, 0x2e, 0xc9, 0x2b, 0xe7, 0x23, 0xfe, 0xdf, 0x2f, 0x2e, 0xde, 0x5a, 0x47, + 0x2a, 0xa1, 0xe7, 0x4f, 0x33, 0xad, 0x41, 0x90, 0x15, 0x44, 0xed, 0xbb, 0xe3, 0xac, + 0x46, 0x4c, 0xf4, 0x39, 0x19, 0x60, 0x15, 0xf4, 0xf2, 0x2a, 0xc2, 0xb8, 0xfc, 0x01, + 0x49, 0x6b, 0xea, 0xb4, 0xd4, 0x59, 0x07, 0xf4, 0x79, 0x81, 0x2a, 0x25, 0x94, 0x31, + 0xa2, 0xcb, 0xc9, 0x3d, 0x4f, 0x3b, 0x84, 0xe4, 0xdd, 0x36, 0x60, 0x20, 0x27, 0x3a, + 0x67, 0x52, 0xe5, 0x01, 0xaf, 0x6f, 0xf1, 0xb7, 0x8d, 0xdc, 0x81, 0x7e, 0x6e, 0xa3, + 0x51, 0xd6, 0x00, 0x6b, 0xec, 0xf8, 0xd2, 0xff, 0xb0, 0x39, 0x90, 0xf6, 0x77, 0x74, + 0xa8, 0x1e, 0x05, 0xb7, 0xf4, 0xbb, 0xad, 0x85, 0x77, 0xfa, 0x27, 0xc9, 0xde, 0x64, + 0xe1, 0xb1, 0x1d, 0xcf, 0x38, 0x4f, 0x59, 0x56, 0x44, 0x37, 0x48, 0x75, 0x5a, 0x9f, + 0xc6, 0xf2, 0xa0, 0x0b, 0x10, 0xc3, 0x65, 0x7e, 0xba, 0xc0, 0x3b, 0xfc, 0x0b, 0x58, + 0x7b, 0xef, 0x2f, 0x45, 0xec, 0x8a, 0xcd, 0xaa, 0x51, 0xc1, 0x43, 0xb0, 0xcb, 0x25, + 0xb9, 0x14, 0x2c, 0x61, 0xbd, 0x79, 0x0a, 0x80, 0xd7, 0xc2, 0x3f, 0x90, 0xcc, 0x03, + 0x49, 0x5b, 0x51, 0xe4, 0xd2, 0x84, 0x3e, 0x55, 0x7f, 0x9e, 0x25, 0x45, 0x10, 0x8c, + 0x6c, 0x6f, 0xae, 0x35, 0x9f, 0x64, 0x5c, 0x27, 0x68, 0x91, 0xc0, 0xdc, 0xab, 0x3f, + 0xaf, 0x18, 0x77, 0x00, 0xc0, 0x82, 0xdc, 0x47, 0x77, 0x40, 0xfb, 0x3f, 0x2c, 0xd7, + 0xbb, 0x59, 0xfb, 0x35, 0x85, 0x54, 0xe9, 0x4c, 0x7e, 0x67, 0x8c, 0xe0, 0x1a, 0xeb, + 0xf9, 0x4e, 0x51, 0x5e, 0x49, 0x72, 0x29, 0x67, 0x99, 0x5a, 0xea, 0x85, 0x8d, 0x64, + 0xe7, 0x78, 0x9f, 0xf3, 0x06, 0x36, 0x95, 0x77, 0x22, 0x81, 0x80, 0x32, 0x6a, 0x5b, + 0x0a, 0xf4, 0x75, 0xe2, 0x7a, 0x54, 0xb2, 0x07, 0xb4, 0x1f, 0x92, 0xe3, 0x76, 0x17, + 0x0e, 0x3f, 0xb0, 0x05, 0x02, 0x82, 0x61, 0xc9, 0x9c, 0x2d, 0xbd, 0x0e, 0xed, 0xee, + 0x87, 0x1c, 0x1c, 0x0f, 0x48, 0xb8, 0xe9, 0xb8, 0xe4, 0xbe, 0x77, 0xd1, 0xb7, 0x37, + 0xfe, 0x21, 0xf0, 0xfa, 0x5a, 0x18, 0xeb, 0xb5, 0x27, 0x55, 0xb5, 0xa6, 0xcf, 0x61, + 0x30, 0xfb, 0x56, 0x94, 0x4c, 0xfa, 0xb8, 0x75, 0x27, 0xc2, 0x50, 0xd1, 0x13, 0xb2, + 0x9b, 0xca, 0xc9, 0xaa, 0xa1, 0x0c, 0x2e, 0x7d, 0xe4, 0x15, 0xed, 0xb0, 0x80, 0x6c, + 0x6d, 0xa0, 0x30, 0x20, 0xa1, 0x34, 0xca, 0x7e, 0xcd, 0xc8, 0xda, 0x1b, 0xd5, 0x7a, + 0x37, 0xf5, 0x5a, 0x46, 0x94, 0x0b, 0x45, 0xb2, 0x41, 0xb1, 0xc1, 0x6e, 0xe1, 0x00, + 0x92, 0x7d, 0x1b, 0xd8, 0x60, 0xd4, 0x45, 0xa9, 0xde, 0x50, 0xd4, 0xc3, 0x84, 0xd6, + 0xe1, 0xd0, 0x01, 0x08, 0x02, 0x6c, 0x0e, 0xa5, 0xeb, 0xbf, 0x0b, 0x72, 0xfb, 0xf5, + 0xc3, 0x70, 0xbc, 0xe1, 0x8d, 0x3a, 0xcb, 0xc4, 0x65, 0x99, 0x09, 0x9b, 0xaa, 0xe1, + 0xd8, 0x02, 0xf7, 0x73, 0x33, 0x49, 0x4a, 0x7a, 0xe1, 0x30, 0xfe, 0x86, 0xe8, 0xf8, + 0x18, 0xf9, 0x26, 0x1a, 0x2d, 0xad, 0xb4, 0x12, 0x52, 0x29, 0xba, 0x0f, 0xfc, 0x0e, + 0x70, 0x90, 0x32, 0x44, 0x30, 0xb5, 0x21, 0xa9, + ], + c_enc: [ + 0x45, 0x6b, 0x2b, 0xb8, 0x03, 0xc7, 0xdf, 0xf7, 0xac, 0x82, 0xe6, 0x42, 0xf4, 0xd8, + 0x46, 0x1e, 0x0b, 0x7a, 0x3b, 0x3c, 0x95, 0xa4, 0xcb, 0xf1, 0xc0, 0x6f, 0xeb, 0x93, + 0xa1, 0x8b, 0xeb, 0xa2, 0x9f, 0x2b, 0x8f, 0x12, 0x1a, 0x61, 0x5c, 0xa5, 0x3f, 0xc2, + 0xa7, 0x60, 0x63, 0xb8, 0x0d, 0xaa, 0x71, 0x01, 0x8b, 0x66, 0x3b, 0x7c, 0x46, 0x6d, + 0xb2, 0x63, 0xf9, 0x04, 0x27, 0xd0, 0x11, 0x7f, 0x0b, 0x89, 0x90, 0x6e, 0x98, 0x41, + 0x7f, 0x3e, 0xe8, 0x5a, 0xcc, 0xed, 0xb1, 0x41, 0xfb, 0x10, 0x26, 0xa3, 0xb3, 0xf7, + 0xa4, 0xfd, 0x10, 0x24, 0xf9, 0xc8, 0x08, 0x9a, 0x2e, 0xbe, 0x1a, 0x27, 0x82, 0xf8, + 0xb0, 0xbf, 0x5c, 0x40, 0xb6, 0xd5, 0x2f, 0xfe, 0x38, 0x37, 0xf4, 0xe4, 0x42, 0x52, + 0x13, 0x41, 0xc2, 0x4d, 0x3e, 0x89, 0x55, 0x95, 0x08, 0x86, 0x27, 0x85, 0xea, 0x63, + 0x56, 0xb4, 0xe4, 0x66, 0xc3, 0x25, 0x9c, 0xeb, 0x0d, 0x28, 0x2e, 0x07, 0xbb, 0x35, + 0xdc, 0xf2, 0xd9, 0xa8, 0x62, 0xc7, 0x47, 0x58, 0xd3, 0x83, 0xaa, 0xa2, 0x82, 0xfa, + 0xc4, 0xfa, 0xcf, 0xe5, 0x39, 0xe4, 0xe1, 0xbb, 0xd5, 0x46, 0x8a, 0xcf, 0x25, 0xec, + 0x2b, 0x4b, 0xa5, 0x11, 0x9d, 0xea, 0xed, 0x01, 0x1d, 0x4f, 0x30, 0xb0, 0xc5, 0x82, + 0x01, 0xfe, 0xe1, 0xc6, 0xe4, 0xf6, 0xb5, 0x2e, 0x41, 0xad, 0xfa, 0x5d, 0x6f, 0xda, + 0x94, 0xa5, 0x23, 0x20, 0xe8, 0x3b, 0x80, 0xc6, 0xfc, 0xee, 0xb8, 0x97, 0x89, 0xd8, + 0x79, 0x94, 0xb7, 0xa0, 0x16, 0xec, 0x64, 0xe4, 0x70, 0x78, 0x07, 0xf8, 0xf2, 0xd2, + 0x30, 0x63, 0x10, 0x74, 0x10, 0x9f, 0xc5, 0x9d, 0xe3, 0xe4, 0x37, 0x10, 0xca, 0xe8, + 0x9c, 0xb1, 0x89, 0xa0, 0xa4, 0x64, 0x8b, 0x37, 0x54, 0x5d, 0x25, 0x49, 0x47, 0x95, + 0xa8, 0xdf, 0x3f, 0xfc, 0x7a, 0x3a, 0x21, 0xe3, 0xb9, 0x1c, 0x95, 0x96, 0xe0, 0xd5, + 0x10, 0x5d, 0xf8, 0xad, 0xa9, 0xcf, 0xe9, 0x31, 0x10, 0xb1, 0x9f, 0xf2, 0xaf, 0x83, + 0x03, 0xb5, 0xd2, 0x79, 0x3f, 0xff, 0xd0, 0x4d, 0x8e, 0x02, 0xf7, 0xb9, 0x30, 0x14, + 0x80, 0xdf, 0xd9, 0x35, 0x50, 0x2d, 0x98, 0xe2, 0xf3, 0xc3, 0xe9, 0xe9, 0x5e, 0x64, + 0xe4, 0x96, 0xeb, 0x7d, 0x15, 0xcf, 0x2c, 0x70, 0x11, 0x94, 0xe6, 0x25, 0xde, 0x52, + 0x1a, 0x02, 0x55, 0x20, 0xdf, 0x67, 0xac, 0x2b, 0xa4, 0x3b, 0x9c, 0x4a, 0x6d, 0x77, + 0xb8, 0x6a, 0x40, 0x18, 0x2d, 0x70, 0x31, 0x8b, 0x8f, 0xa3, 0x48, 0xb1, 0x86, 0x47, + 0xd8, 0x4e, 0x0e, 0xe5, 0xf0, 0x56, 0x07, 0xa2, 0xb8, 0xf2, 0x69, 0xe1, 0x86, 0xc7, + 0x94, 0x28, 0xbe, 0xa6, 0x7c, 0xbf, 0x71, 0xda, 0xcc, 0x98, 0xe9, 0xcc, 0x72, 0x5e, + 0x50, 0x53, 0xa4, 0x40, 0xca, 0xa6, 0xca, 0xd2, 0x41, 0xa5, 0x06, 0x28, 0x18, 0x3a, + 0xe9, 0xef, 0x9f, 0x0c, 0xbd, 0xfe, 0xf7, 0x0a, 0x42, 0xe5, 0xb7, 0x97, 0xbc, 0x99, + 0xd9, 0x22, 0xfc, 0xc2, 0x81, 0x37, 0x84, 0xea, 0xe4, 0x48, 0x60, 0x18, 0x0e, 0xf8, + 0xe8, 0x1f, 0x7b, 0x94, 0xf2, 0xad, 0x62, 0x12, 0x8b, 0xb6, 0x1f, 0x10, 0xd5, 0x0c, + 0x9c, 0xad, 0x9d, 0x80, 0x48, 0xd9, 0x78, 0x01, 0x8a, 0x1f, 0x3b, 0xc9, 0x24, 0x28, + 0xf8, 0x9d, 0x7d, 0xdc, 0xe5, 0x45, 0x4b, 0xc4, 0x49, 0x1f, 0xb4, 0xc2, 0xcb, 0x66, + 0x88, 0x35, 0xb2, 0x2f, 0xcc, 0x4d, 0xf2, 0x08, 0xf2, 0x16, 0x64, 0xf7, 0x12, 0x94, + 0xc5, 0xce, 0xd3, 0x3c, 0x8e, 0x11, 0xd4, 0x25, 0xd1, 0x39, 0x85, 0x23, 0xc2, 0x79, + 0x88, 0x3a, 0x38, 0x2f, 0x70, 0xfe, 0xfe, 0xc8, 0x25, 0xc5, 0xe3, 0x50, 0x85, 0xaf, + 0x82, 0xd0, 0xa0, 0xa9, 0xbf, 0x45, 0x11, 0x65, 0x0a, 0x2b, 0xfb, 0xf0, 0xb2, 0x18, + 0x82, 0x10, 0x5e, 0xc6, 0xe5, 0x99, 0x74, 0xd8, 0xd6, 0xce, 0x73, 0x07, 0x8f, 0xb4, + 0xb5, 0x63, 0x4e, 0x85, 0xd7, 0xe2, 0x0a, 0x97, 0xff, 0xb6, 0x5d, 0x4f, 0x5e, 0xaf, + 0x42, 0x63, 0x9b, 0x09, 0xf5, 0xed, 0xa5, 0x9a, 0xb1, 0x04, 0x97, 0x69, 0x95, 0x41, + 0xd1, 0xc8, 0x22, 0x8e, 0xca, 0x31, 0x3f, 0xd0, 0x0a, 0x21, 0xb3, 0x02, 0x7b, 0x40, + 0xd0, 0xc1, 0xfd, 0x4c, 0x2f, 0x0d, 0x97, 0xf1, 0xa9, 0x58, 0xe9, 0x2b, 0x45, 0xd5, + 0xd4, 0xbf, 0xc2, 0xef, 0x18, 0xef, 0xd6, 0xb2, 0x5b, 0x47, 0xa9, 0x4d, 0xae, 0x73, + 0xc3, 0xcf, 0xc9, 0xca, 0xd8, 0xdb, 0x82, 0x3f, 0xbd, 0x74, + ], + ock: [ + 0xc6, 0x7c, 0x23, 0x33, 0xc3, 0xcf, 0x4a, 0xc4, 0x6e, 0xde, 0x34, 0xe3, 0xe3, 0xe0, + 0xdb, 0xff, 0x1e, 0x96, 0xb7, 0xa7, 0x8f, 0x16, 0xaa, 0xef, 0x1c, 0x74, 0xa3, 0xef, + 0x07, 0xc5, 0x97, 0x16, + ], + op: [ + 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, + 0x59, 0x25, 0x23, 0x5a, 0x75, 0x29, 0x85, 0x44, 0x6e, 0x11, 0x69, 0x5f, 0x36, 0xc2, + 0xe6, 0x84, 0x45, 0xbb, 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, + 0x39, 0x16, 0x0f, 0xe5, 0x67, 0x75, 0x1e, 0xb8, 0x4a, 0xa2, 0x1d, 0x33, 0xa6, 0x90, + 0xe0, 0xd2, 0x9b, 0x35, 0x9a, 0xc4, 0xfa, 0x2c, + ], + c_out: [ + 0xe4, 0xba, 0x0e, 0xa2, 0x92, 0x3b, 0x40, 0x19, 0xac, 0x8a, 0xbc, 0xd1, 0x9b, 0xe6, + 0x1c, 0x90, 0xf1, 0x8e, 0xef, 0xae, 0x87, 0xc4, 0xed, 0x8c, 0x76, 0x70, 0x85, 0xba, + 0xa8, 0x3b, 0x4d, 0x61, 0x0c, 0xf3, 0x63, 0x70, 0xda, 0x07, 0x90, 0x1e, 0xad, 0x6d, + 0x4f, 0x4b, 0x71, 0xdc, 0xae, 0x31, 0x1f, 0xa0, 0x36, 0x40, 0x6d, 0x64, 0x7b, 0x7e, + 0xe1, 0x41, 0x1e, 0xf5, 0xae, 0xe0, 0x34, 0x68, 0xb1, 0x09, 0x13, 0xc9, 0x90, 0xcb, + 0x61, 0x61, 0x22, 0xeb, 0xbe, 0x49, 0xda, 0x67, 0x81, 0xc2, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xb6, 0x6c, 0x73, 0x33, 0x75, 0xda, 0xc6, 0xff, 0xcc, 0x98, 0xf5, 0x0f, 0x3a, 0xf0, + 0xb0, 0x76, 0x05, 0x53, 0xfe, 0x98, 0xed, 0x61, 0xff, 0xa4, 0x93, 0xea, 0xe6, 0x8d, + 0xf0, 0xb3, 0x33, 0x4e, 0xe8, 0xd4, 0x39, 0x37, 0xb7, 0xdb, 0x8e, 0xbb, 0xfe, 0xbd, + 0x54, 0x8a, 0x28, 0x02, 0x51, 0xea, 0x87, 0xaa, 0x5d, 0x8c, 0xa5, 0x36, 0x86, 0x1b, + 0x38, 0x4f, 0x20, 0x86, 0x9f, 0x8f, 0xe8, 0x01, + ], + ovk: [ + 0xe9, 0x4c, 0x15, 0x24, 0x5f, 0x1a, 0x95, 0x88, 0x40, 0xba, 0x3f, 0x38, 0x0a, 0x4d, + 0x20, 0xf1, 0x18, 0x4e, 0x77, 0x82, 0x7d, 0xe3, 0xff, 0x8f, 0x3d, 0x73, 0x45, 0x9a, + 0xfe, 0x24, 0x1f, 0x72, + ], + default_d: [ + 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, + ], + default_pk_d: [ + 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, + 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, + 0x25, 0xc8, 0xd6, 0xae, + ], + v: 16065731808124965111, + rseed: [ + 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, + 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, + 0x71, 0x8c, 0x29, 0xdd, + ], + asset: [ + 0xdf, 0xfd, 0x79, 0xa9, 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, + 0x01, 0xe2, 0x99, 0x0a, 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, + 0xfd, 0x7d, 0x05, 0x8a, + ], + memo: [ + 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, + 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, + 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, + 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, + 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, + 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, + 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, + 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, + 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, + 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, + 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, + 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, + 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, + 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, + 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, + 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, + 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, + 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, + 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, + 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, + 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, + 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, + 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, + 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, + 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, + 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, + 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, + 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, + 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, + 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, + 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, + 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, + 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, + 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, + 0xb6, 0x50, 0x82, 0xa6, 0x22, 0xa7, 0xc2, 0xe0, 0x01, 0x3e, 0xa4, 0x7d, 0x0b, 0xdd, + 0x42, 0xd6, 0x99, 0x04, 0x66, 0x64, 0x9a, 0x90, 0x5c, 0x68, 0x4c, 0x32, 0x51, 0x71, + 0x6d, 0x61, 0xf7, 0x60, 0xd5, 0x3d, 0xe6, 0xe3, + ], + cv_net: [ + 0x0a, 0x1f, 0x28, 0x15, 0xb7, 0xaf, 0xe2, 0x19, 0x06, 0x87, 0x15, 0xfc, 0x76, 0x6b, + 0x87, 0x2e, 0xf2, 0x17, 0x35, 0x43, 0xac, 0x81, 0x4c, 0x32, 0xb4, 0xb6, 0x9c, 0x9c, + 0x34, 0x5e, 0x46, 0x98, + ], + rho: [ + 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, + 0x51, 0x1c, 0x9b, 0xab, 0x65, 0xb6, 0xd8, 0xd5, 0xc5, 0xbd, 0x1e, 0x32, 0x77, 0x1a, + 0xb6, 0xf6, 0x4c, 0x26, + ], + cmx: [ + 0x40, 0x8f, 0x59, 0x4f, 0xdd, 0xc5, 0x0c, 0x67, 0xf5, 0x47, 0xe1, 0xeb, 0x3e, 0xa2, + 0x99, 0xa3, 0x1f, 0x69, 0xf5, 0x7f, 0xc9, 0x92, 0x03, 0x01, 0x42, 0x90, 0x35, 0xa6, + 0xc2, 0x49, 0x79, 0x1a, + ], + esk: [ + 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, 0xef, 0x08, 0xbd, 0xf6, + 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, 0xf5, 0x3b, 0x57, 0xc3, + 0x45, 0xa9, 0x87, 0x2f, + ], + ephemeral_key: [ + 0xa5, 0xc8, 0x0a, 0x29, 0xf2, 0xec, 0xdd, 0xd7, 0x01, 0x96, 0xef, 0x45, 0x9e, 0xd5, + 0x03, 0xc4, 0xb3, 0xc2, 0x22, 0x8d, 0x10, 0xcc, 0xbc, 0xad, 0x9a, 0x28, 0x23, 0x30, + 0x07, 0x7b, 0xca, 0x0c, + ], + shared_secret: [ + 0x37, 0x14, 0x15, 0xfc, 0x1e, 0x98, 0x42, 0xa1, 0x26, 0xa3, 0x7a, 0xa7, 0x7b, 0x8f, + 0x0f, 0x1a, 0xb6, 0x48, 0xa3, 0xf7, 0x43, 0x57, 0x34, 0x89, 0x6f, 0x07, 0x59, 0x52, + 0xe7, 0xd1, 0x60, 0x17, + ], + k_enc: [ + 0xd7, 0x36, 0xf0, 0x3c, 0x81, 0x2d, 0x9b, 0xf9, 0x54, 0xff, 0xd2, 0x41, 0x84, 0x07, + 0xf3, 0x36, 0xa5, 0xf9, 0x69, 0x8b, 0x62, 0x85, 0x23, 0x2f, 0x5c, 0x85, 0xf0, 0xd1, + 0x1d, 0x5e, 0x9d, 0x0a, + ], + p_enc: [ + 0x03, 0x7c, 0x51, 0xbe, 0xc6, 0xee, 0x28, 0x46, 0xfd, 0x85, 0x12, 0x64, 0xf7, 0x90, + 0xfb, 0xa7, 0xf5, 0xf1, 0xf4, 0xde, 0x26, 0xf2, 0x84, 0x38, 0xe5, 0x78, 0x2f, 0x45, + 0xac, 0x1d, 0x07, 0xf6, 0xf6, 0xf5, 0xed, 0x73, 0x74, 0x1d, 0x57, 0x85, 0x83, 0x7a, + 0x6b, 0x84, 0x4b, 0x47, 0x47, 0x75, 0x71, 0x8c, 0x29, 0xdd, 0xdf, 0xfd, 0x79, 0xa9, + 0xde, 0xd0, 0x5e, 0x88, 0x89, 0x58, 0x19, 0x9e, 0xea, 0x45, 0x01, 0xe2, 0x99, 0x0a, + 0x53, 0xa5, 0xcd, 0x2a, 0x46, 0xa4, 0x01, 0x57, 0x65, 0x88, 0xfd, 0x7d, 0x05, 0x8a, + 0xff, 0x99, 0x08, 0x4e, 0x9f, 0x88, 0xef, 0x15, 0x3a, 0x83, 0x29, 0xf5, 0x32, 0xa6, + 0x90, 0x17, 0xdc, 0x3a, 0x97, 0xed, 0x75, 0x43, 0x67, 0x72, 0x30, 0x98, 0xe5, 0x76, + 0x58, 0x40, 0xb0, 0x22, 0x89, 0x72, 0x44, 0x74, 0x5f, 0xbb, 0xbb, 0x30, 0xa7, 0xcb, + 0x54, 0xfa, 0x05, 0x11, 0x16, 0x6e, 0x95, 0x44, 0x12, 0x20, 0x00, 0x61, 0x0b, 0xd2, + 0xaa, 0xcb, 0xd8, 0x23, 0x25, 0xa5, 0x9b, 0x95, 0x15, 0x4e, 0xcd, 0x82, 0xc8, 0x8d, + 0x23, 0xab, 0xd1, 0xe2, 0x07, 0x70, 0xff, 0xb8, 0xaa, 0xbf, 0x83, 0xfc, 0x07, 0x34, + 0x96, 0x4c, 0xcd, 0x41, 0x1d, 0x1c, 0x93, 0x57, 0x14, 0xe2, 0x4a, 0xab, 0x56, 0x6f, + 0x4f, 0x08, 0x42, 0x40, 0x14, 0xc4, 0xec, 0xa9, 0x1b, 0x59, 0x0f, 0x08, 0x2b, 0x47, + 0x3f, 0x36, 0x1c, 0x87, 0x41, 0x5d, 0x37, 0xbd, 0x20, 0xd7, 0x0f, 0xd0, 0xb5, 0x2b, + 0x6d, 0xdf, 0x18, 0x65, 0xf7, 0x66, 0x70, 0x2e, 0x32, 0xb0, 0x5b, 0x3c, 0xf1, 0x63, + 0x0e, 0xe8, 0x59, 0x7a, 0xae, 0x19, 0x63, 0x3f, 0x35, 0x16, 0xa8, 0x55, 0x5a, 0xc5, + 0xbe, 0x32, 0xc6, 0x75, 0xbe, 0x18, 0x17, 0xef, 0xbf, 0xfd, 0x93, 0x69, 0x04, 0x1a, + 0x08, 0x9c, 0x28, 0x3f, 0x19, 0x64, 0x99, 0x68, 0xc2, 0x49, 0x8c, 0xde, 0x56, 0xf5, + 0x00, 0x43, 0x4f, 0x28, 0x0d, 0x77, 0xa9, 0xc6, 0x2e, 0x43, 0xcb, 0xd3, 0xf1, 0x36, + 0xa4, 0xc6, 0xa0, 0x0a, 0x43, 0xe6, 0xed, 0x53, 0x0c, 0xb2, 0xe8, 0xae, 0x83, 0x88, + 0x60, 0xad, 0xc8, 0x8a, 0xac, 0xc7, 0xbd, 0x6a, 0x00, 0xae, 0x0c, 0x19, 0xff, 0x45, + 0x33, 0xa4, 0x85, 0xef, 0xde, 0x08, 0x2b, 0x5f, 0x4d, 0x1f, 0x7a, 0x8e, 0xbe, 0x7e, + 0xd8, 0x2b, 0x7b, 0x05, 0xa8, 0xcf, 0xe1, 0xe3, 0x73, 0x45, 0x9f, 0x1b, 0xdc, 0xbf, + 0x95, 0x25, 0x74, 0x7e, 0x8c, 0x95, 0x08, 0xa5, 0x55, 0xfa, 0xcb, 0x79, 0x87, 0x40, + 0xe0, 0xbd, 0xf9, 0x94, 0xd9, 0x73, 0x9b, 0xbe, 0x55, 0x38, 0xa0, 0xae, 0x0f, 0x07, + 0x6c, 0x58, 0x2c, 0x0f, 0x5b, 0xa8, 0x78, 0xb9, 0x9b, 0x82, 0x49, 0xdb, 0x1d, 0x7e, + 0x95, 0x05, 0x6c, 0x98, 0xaf, 0x08, 0x3d, 0x98, 0xcb, 0x0e, 0xd9, 0xe3, 0xf7, 0x43, + 0x6e, 0x1c, 0x76, 0x43, 0x76, 0x6f, 0x96, 0x6b, 0x83, 0xe9, 0x99, 0x20, 0x6e, 0xbd, + 0x13, 0x93, 0xb9, 0xb2, 0xa7, 0xf4, 0x14, 0x48, 0x0f, 0xa0, 0x17, 0x48, 0x00, 0x69, + 0xf8, 0x5c, 0x77, 0x49, 0xc4, 0x35, 0xae, 0x2f, 0xba, 0x2d, 0xdc, 0x10, 0x38, 0xd5, + 0x47, 0xd8, 0x48, 0x54, 0x81, 0x7e, 0xf3, 0x96, 0x35, 0xc2, 0x98, 0x27, 0xaa, 0xd8, + 0x67, 0x26, 0xc9, 0xad, 0xe3, 0xb2, 0x65, 0xb9, 0x08, 0x6c, 0x8b, 0x5b, 0x75, 0xef, + 0x56, 0xfe, 0x4b, 0xd8, 0xb4, 0xd6, 0x28, 0x93, 0x89, 0x5b, 0x3f, 0xd2, 0x73, 0x4f, + 0xda, 0xc4, 0x64, 0x15, 0x6d, 0x7e, 0x5e, 0xbc, 0x7e, 0xcf, 0x1d, 0x83, 0xb8, 0x6f, + 0x65, 0x96, 0x37, 0xe3, 0xb1, 0x42, 0xc1, 0x64, 0x96, 0x3b, 0x8c, 0xdc, 0xf4, 0xba, + 0x4f, 0x40, 0x35, 0xdf, 0xfc, 0x5a, 0x78, 0x94, 0x58, 0x84, 0x77, 0x81, 0x91, 0x8a, + 0xc7, 0x2f, 0xc1, 0x8b, 0xbb, 0xf5, 0x11, 0x00, 0x32, 0xe6, 0x6d, 0x75, 0xb3, 0x17, + 0x1e, 0xf4, 0xb5, 0x13, 0x29, 0x01, 0x64, 0xa7, 0x7b, 0x42, 0xb0, 0xa4, 0xcf, 0xb8, + 0x96, 0x39, 0xab, 0x23, 0x84, 0x5e, 0x1a, 0xa2, 0xa4, 0x52, 0xf3, 0x73, 0x1c, 0x8c, + 0xb6, 0x50, 0x82, 0xa6, 0x22, 0xa7, 0xc2, 0xe0, 0x01, 0x3e, 0xa4, 0x7d, 0x0b, 0xdd, + 0x42, 0xd6, 0x99, 0x04, 0x66, 0x64, 0x9a, 0x90, 0x5c, 0x68, 0x4c, 0x32, 0x51, 0x71, + 0x6d, 0x61, 0xf7, 0x60, 0xd5, 0x3d, 0xe6, 0xe3, + ], + c_enc: [ + 0xfc, 0x90, 0xcb, 0xe1, 0xcd, 0x9f, 0x59, 0x9a, 0x1a, 0x24, 0xc7, 0xa3, 0xea, 0xf6, + 0x07, 0xd9, 0x13, 0xbf, 0x48, 0xbd, 0xc1, 0xa4, 0x6d, 0xf7, 0xb1, 0x74, 0x7f, 0x12, + 0x60, 0x64, 0x49, 0x4b, 0xf5, 0x39, 0x61, 0xe9, 0xa5, 0xa2, 0xb9, 0x69, 0x80, 0x57, + 0x63, 0x44, 0x2e, 0x2c, 0x38, 0x8d, 0x21, 0x2d, 0x74, 0x84, 0x6e, 0x57, 0x27, 0x87, + 0x2d, 0x06, 0x3f, 0xc9, 0x94, 0xa4, 0x4f, 0x9e, 0xb6, 0x55, 0x25, 0xd6, 0x8f, 0x98, + 0x24, 0xa6, 0x03, 0x75, 0xfe, 0x43, 0xc0, 0x5f, 0x08, 0xfe, 0x45, 0x42, 0xa7, 0xe4, + 0x0c, 0x03, 0x8d, 0xe7, 0x10, 0x85, 0x01, 0x17, 0x95, 0x1b, 0x9a, 0x32, 0x1e, 0xea, + 0x4f, 0x8c, 0x91, 0xc0, 0x1d, 0x39, 0xdb, 0xb5, 0xd4, 0x12, 0x40, 0xf8, 0xb1, 0xb1, + 0xdb, 0xb3, 0x3f, 0x45, 0x87, 0x87, 0xdb, 0x8c, 0xda, 0x06, 0x9b, 0x64, 0x5a, 0x76, + 0x38, 0xc2, 0xec, 0xca, 0xd3, 0xd9, 0xa7, 0x39, 0xd6, 0x4c, 0x9a, 0xd5, 0xd5, 0xb3, + 0xa0, 0x24, 0x55, 0xa4, 0xec, 0xd6, 0x96, 0x7c, 0xf3, 0xb3, 0x3b, 0xf0, 0x4e, 0xf6, + 0xdd, 0x88, 0x10, 0xe1, 0x0c, 0x25, 0x86, 0xf7, 0x89, 0x32, 0x44, 0xea, 0x72, 0x80, + 0xd1, 0x34, 0xcf, 0x37, 0xb3, 0xdc, 0x0c, 0x32, 0x82, 0x3b, 0x1a, 0x29, 0xc5, 0x0c, + 0xa6, 0x48, 0x31, 0xd8, 0x4e, 0xbd, 0xf5, 0xe0, 0x1c, 0x14, 0xca, 0x36, 0x05, 0xbe, + 0x02, 0xf1, 0x5f, 0x31, 0x57, 0x90, 0xf7, 0x4e, 0x20, 0x57, 0x7f, 0x92, 0x39, 0x51, + 0x2f, 0xbd, 0xdd, 0x67, 0x63, 0x77, 0xae, 0x50, 0xc3, 0xfe, 0x71, 0xc9, 0x30, 0xa8, + 0x29, 0x57, 0xd1, 0x54, 0x70, 0xeb, 0x1b, 0x55, 0xb2, 0x0c, 0xe5, 0x02, 0x35, 0x64, + 0xfe, 0xa7, 0xe1, 0x81, 0xbe, 0x04, 0xa9, 0x33, 0xa7, 0xa3, 0xa1, 0x11, 0x89, 0x4d, + 0xec, 0xf7, 0x2a, 0x56, 0x54, 0xcb, 0x4e, 0xac, 0x32, 0xe1, 0xd5, 0x96, 0xad, 0x99, + 0x1a, 0x2f, 0x4c, 0x62, 0xe8, 0xe2, 0x82, 0x57, 0x13, 0x7b, 0xcb, 0xa5, 0x03, 0xdc, + 0x91, 0xed, 0x9e, 0x90, 0xb3, 0x08, 0xcd, 0xa5, 0xcc, 0xcc, 0xc9, 0xd1, 0x4e, 0xa6, + 0xd0, 0x3b, 0x3d, 0xec, 0xa1, 0x57, 0xd5, 0x30, 0xde, 0x63, 0x1e, 0x1e, 0x45, 0x8f, + 0x6a, 0x60, 0x8e, 0x1f, 0x9d, 0x57, 0x9b, 0x6e, 0xe6, 0x00, 0x5c, 0xd0, 0xa8, 0xc3, + 0xe2, 0xdf, 0x89, 0x46, 0x8a, 0xcf, 0xb4, 0x36, 0xcb, 0x59, 0x84, 0x56, 0xf0, 0x38, + 0x95, 0x5d, 0xc6, 0xb4, 0x07, 0xec, 0x33, 0x00, 0xa5, 0xcf, 0xcd, 0xc8, 0x45, 0x47, + 0xe3, 0xef, 0xe9, 0xfc, 0xa1, 0x7e, 0xd2, 0xc2, 0x74, 0xf0, 0x03, 0x0b, 0x63, 0xcc, + 0x42, 0xe2, 0x38, 0x94, 0xa5, 0xf2, 0x53, 0x66, 0xcb, 0xc3, 0xbf, 0xcb, 0x77, 0x2d, + 0x04, 0x17, 0xf6, 0x24, 0x4b, 0x2f, 0xd8, 0x17, 0xc4, 0xc6, 0x79, 0x06, 0xc3, 0x38, + 0x4d, 0x69, 0xd7, 0x93, 0xef, 0xca, 0x6e, 0x5d, 0x6a, 0xf2, 0x5e, 0x4e, 0xbc, 0x0f, + 0x53, 0x56, 0xeb, 0x74, 0x28, 0x85, 0x19, 0xe8, 0xf4, 0x49, 0x38, 0xeb, 0xf9, 0xb2, + 0x5b, 0xe5, 0x85, 0xe1, 0x35, 0x1f, 0x62, 0x59, 0x6c, 0x31, 0x79, 0xca, 0xe4, 0x5e, + 0x75, 0x49, 0xd7, 0xfb, 0xb5, 0x91, 0x3b, 0xe9, 0xc3, 0xba, 0xa5, 0x7c, 0xab, 0x7c, + 0xd4, 0xb5, 0x67, 0x12, 0x8d, 0x1b, 0xa5, 0x20, 0x31, 0xd7, 0xd5, 0xa5, 0xbd, 0x69, + 0xde, 0x61, 0x4a, 0xbb, 0x8c, 0xa3, 0x8a, 0x94, 0x51, 0xcd, 0x1b, 0xad, 0xd9, 0x71, + 0xb3, 0xf1, 0xb0, 0xb5, 0x0c, 0x7f, 0x21, 0xbf, 0xc4, 0x23, 0x04, 0xa4, 0xa5, 0x3e, + 0x0d, 0x55, 0x92, 0x0d, 0xa0, 0x53, 0x27, 0x14, 0x79, 0x13, 0x45, 0xfb, 0x07, 0x4c, + 0x66, 0xc4, 0xb7, 0xc9, 0x89, 0x28, 0x30, 0xf9, 0x62, 0x09, 0xb8, 0x1c, 0x26, 0xd1, + 0x74, 0xf8, 0xa9, 0x33, 0xc3, 0x77, 0x9d, 0x97, 0x88, 0x55, 0x3f, 0x6e, 0xeb, 0x21, + 0xf7, 0xdb, 0x57, 0x78, 0xf4, 0xf8, 0x17, 0x4c, 0xb4, 0x6f, 0x71, 0xfd, 0xdc, 0x4b, + 0xe4, 0xd8, 0x70, 0x3e, 0xbf, 0xbc, 0xd2, 0xa7, 0x72, 0x89, 0xee, 0xfa, 0x72, 0x76, + 0x56, 0x74, 0xdb, 0xf0, 0x43, 0xd4, 0x25, 0x8c, 0xcc, 0x4a, 0x2f, 0x16, 0x5c, 0x02, + 0xdc, 0xdb, 0x57, 0x2a, 0x70, 0x9d, 0x58, 0x45, 0x83, 0xe9, 0xde, 0x07, 0x8f, 0x1b, + 0x6c, 0x0c, 0x67, 0xf2, 0x8f, 0x17, 0xae, 0x52, 0x30, 0x19, 0x83, 0xf7, 0x9c, 0x28, + 0x83, 0x95, 0xa3, 0x99, 0x63, 0x65, 0xa2, 0x0c, 0x22, 0x9e, + ], + ock: [ + 0x2f, 0x88, 0x37, 0x27, 0xb5, 0x4d, 0x06, 0x25, 0xcf, 0xdc, 0x19, 0x5a, 0xce, 0x10, + 0xca, 0xc0, 0x26, 0x8a, 0xba, 0x3d, 0xe2, 0x8a, 0xd6, 0x08, 0x88, 0x06, 0x50, 0x6d, + 0x69, 0xc4, 0xdd, 0x8e, + ], + op: [ + 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, + 0xc4, 0x6f, 0x93, 0xd4, 0xaf, 0xd5, 0xc9, 0xb0, 0x4d, 0x2b, 0x26, 0x4e, 0x81, 0x0f, + 0x25, 0xc8, 0xd6, 0xae, 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, + 0xef, 0x08, 0xbd, 0xf6, 0xf8, 0x57, 0xe7, 0x1a, 0xab, 0x45, 0x0e, 0x6c, 0xd6, 0x13, + 0xf5, 0x3b, 0x57, 0xc3, 0x45, 0xa9, 0x87, 0x2f, + ], + c_out: [ + 0x99, 0x96, 0x90, 0xd4, 0xcd, 0xd9, 0xe7, 0x6b, 0x07, 0x2c, 0x3c, 0x4c, 0x41, 0xbf, + 0xc7, 0x9a, 0xaa, 0xc6, 0x7f, 0xdc, 0x0f, 0x41, 0xe8, 0x0e, 0x95, 0x48, 0x80, 0x0e, + 0xef, 0xbc, 0x95, 0x74, 0xf1, 0x5d, 0x64, 0xa6, 0x9e, 0x44, 0x47, 0xc4, 0x5b, 0x07, + 0x0c, 0x6c, 0x9f, 0x50, 0x0a, 0xdd, 0xef, 0x6f, 0x57, 0x14, 0xa5, 0x76, 0x22, 0x1f, + 0x3f, 0xbc, 0x61, 0x22, 0x8d, 0x95, 0xc3, 0xac, 0xe4, 0x21, 0x4b, 0xb6, 0xcf, 0x5b, + 0xd9, 0x69, 0x84, 0xd7, 0x78, 0x96, 0x0d, 0xe9, 0x0c, 0x02, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x8c, 0x45, 0x43, 0xe1, 0x1f, 0x9f, 0x30, 0x7e, 0xc9, 0x04, 0x31, 0x61, 0x29, 0x46, + 0xfb, 0x01, 0x81, 0xb3, 0x6e, 0x1b, 0x52, 0xdb, 0x43, 0x1e, 0x6d, 0xf9, 0x38, 0x8c, + 0xac, 0xd3, 0x08, 0xe8, 0x99, 0xd9, 0x3f, 0x70, 0xad, 0x2a, 0xea, 0xec, 0x99, 0x5e, + 0xcc, 0xe1, 0x80, 0x1c, 0x61, 0x56, 0xe2, 0x3e, 0xc4, 0x1b, 0x1a, 0xe1, 0xcd, 0x2f, + 0xd6, 0xe3, 0x9b, 0x69, 0x98, 0x2f, 0x46, 0x33, + ], + ovk: [ + 0x01, 0x76, 0xae, 0x33, 0x93, 0x25, 0xd5, 0xa5, 0x88, 0xda, 0x57, 0x96, 0xfa, 0xae, + 0x5b, 0xab, 0x7c, 0x82, 0x97, 0x7c, 0x0f, 0xf7, 0x97, 0x09, 0x3e, 0x2c, 0x1f, 0x3a, + 0xe8, 0x55, 0xf6, 0x5a, + ], + default_d: [ + 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, + ], + default_pk_d: [ + 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, + 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, + 0x36, 0x34, 0xb0, 0x23, + ], + v: 3775288302605163507, + rseed: [ + 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, + 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, + 0x3e, 0xcd, 0xd7, 0x99, + ], + asset: [ + 0xa6, 0x33, 0x05, 0x44, 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, + 0x5a, 0x31, 0xf6, 0x2e, 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, + 0xb4, 0x42, 0x68, 0x3c, + ], + memo: [ + 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, + 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, + 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, + 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, + 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, + 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, + 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, + 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, + 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, + 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, + 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, + 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, + 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, + 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, + 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, + 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, + 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, + 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, + 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, + 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, + 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, + 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, + 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, + 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, + 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, + 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, + 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, + 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, + 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, + 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, + 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, + 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, + 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, + 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, + 0x6e, 0x67, 0x57, 0x61, 0x00, 0x8b, 0x0d, 0xad, 0xde, 0xec, 0xaa, 0x60, 0x44, 0x70, + 0xbb, 0xe0, 0xfa, 0xda, 0x25, 0x5d, 0x29, 0x0e, 0x92, 0xb1, 0x90, 0xc2, 0xc2, 0xd8, + 0xc2, 0xde, 0xe5, 0x45, 0x5d, 0x1f, 0xa9, 0xa9, + ], + cv_net: [ + 0xde, 0x2b, 0xfc, 0x89, 0x5b, 0xa8, 0xb5, 0x43, 0x03, 0x93, 0x43, 0x4e, 0x20, 0x92, + 0xce, 0xe7, 0x81, 0xe4, 0x00, 0x28, 0x5c, 0xc6, 0x66, 0xbc, 0x6c, 0x41, 0x89, 0xdb, + 0x2d, 0xda, 0x71, 0x92, + ], + rho: [ + 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, + 0xe0, 0xe8, 0x14, 0x11, 0x94, 0x7e, 0x9e, 0x69, 0xb7, 0x19, 0xfa, 0xb7, 0x41, 0x72, + 0x1d, 0x40, 0x9b, 0x33, + ], + cmx: [ + 0x9e, 0x3d, 0x61, 0x35, 0x6b, 0x0d, 0x88, 0x95, 0x9e, 0x3f, 0x0f, 0xcc, 0x4a, 0x93, + 0x2e, 0x93, 0x2e, 0xac, 0xbc, 0x80, 0x1d, 0x48, 0xc0, 0x19, 0x5b, 0x9c, 0x8b, 0xd1, + 0x05, 0x5a, 0x8e, 0x2e, + ], + esk: [ + 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, 0xa9, 0x19, 0xa2, 0x06, + 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, 0x25, 0xec, 0xff, 0x47, + 0x72, 0x16, 0x8c, 0x05, + ], + ephemeral_key: [ + 0xc1, 0xce, 0x25, 0xfb, 0x89, 0xe5, 0xca, 0x89, 0x97, 0xf9, 0xb4, 0xbb, 0x0e, 0x1e, + 0xfb, 0xcc, 0x1a, 0x8c, 0xbf, 0x44, 0xec, 0xfd, 0x33, 0x2c, 0x6c, 0x5c, 0x17, 0x3b, + 0xb1, 0x1f, 0xb5, 0x87, + ], + shared_secret: [ + 0x2e, 0xe5, 0x69, 0xce, 0xb3, 0xfd, 0xb8, 0x67, 0xa5, 0xd8, 0x4c, 0x92, 0x68, 0x24, + 0xef, 0x54, 0x9f, 0x2d, 0xd2, 0x8f, 0x8b, 0x04, 0x8d, 0x67, 0xd0, 0x28, 0x81, 0x7d, + 0xbf, 0xf5, 0xd2, 0xb1, + ], + k_enc: [ + 0x41, 0x4d, 0x80, 0x67, 0xc9, 0xfe, 0xbd, 0x5e, 0xbc, 0xd9, 0xae, 0x8c, 0x05, 0x99, + 0x4e, 0x3b, 0x06, 0x85, 0xc8, 0x86, 0x6f, 0x88, 0x95, 0x94, 0xc3, 0x74, 0xb3, 0x75, + 0xac, 0x2c, 0x6d, 0x24, + ], + p_enc: [ + 0x03, 0x4e, 0x42, 0x6d, 0xf1, 0xad, 0x32, 0x48, 0x94, 0xbc, 0xa2, 0xc1, 0xf3, 0xdb, + 0x77, 0x79, 0xb5, 0x84, 0x64, 0x34, 0x49, 0x56, 0xbb, 0xb1, 0x95, 0xa4, 0xfa, 0x66, + 0xdc, 0x9c, 0xd5, 0x42, 0xc7, 0x6b, 0x91, 0x50, 0xc8, 0x4b, 0xf8, 0x90, 0x78, 0x99, + 0x42, 0xf5, 0x5c, 0x20, 0x0b, 0x77, 0x3e, 0xcd, 0xd7, 0x99, 0xa6, 0x33, 0x05, 0x44, + 0xe5, 0x46, 0x39, 0xb5, 0x41, 0x87, 0x01, 0xff, 0x4c, 0xc4, 0x5a, 0x31, 0xf6, 0x2e, + 0xdd, 0x84, 0x3d, 0xbb, 0xdc, 0x5a, 0xa7, 0x27, 0xab, 0x79, 0xb4, 0x42, 0x68, 0x3c, + 0xff, 0x2c, 0xff, 0x3e, 0xca, 0x24, 0xde, 0x3e, 0x09, 0x84, 0xe1, 0x0e, 0x68, 0xae, + 0x38, 0x75, 0x34, 0xb9, 0x6c, 0xde, 0x37, 0x92, 0xf1, 0x35, 0xbf, 0x5f, 0x68, 0x78, + 0x7d, 0x37, 0x0c, 0xa8, 0xc4, 0xc4, 0x07, 0x4d, 0xc5, 0xd6, 0x01, 0xae, 0x90, 0x49, + 0x54, 0x37, 0xc3, 0xc2, 0xd4, 0x8a, 0x3d, 0x96, 0x66, 0x83, 0xac, 0x05, 0x16, 0x0b, + 0x7a, 0x84, 0xea, 0xa7, 0xaa, 0xb7, 0x40, 0x09, 0xe5, 0x7a, 0x85, 0xf7, 0xbf, 0x68, + 0xa2, 0xe4, 0x82, 0x00, 0x0f, 0x82, 0x9c, 0x54, 0x50, 0x73, 0xa1, 0x5d, 0x5c, 0xd0, + 0xfc, 0xc5, 0x74, 0x39, 0xa4, 0x35, 0x0e, 0xaf, 0x09, 0x8d, 0xfb, 0x82, 0xa0, 0x85, + 0xea, 0x8a, 0x4a, 0xf6, 0xfa, 0x83, 0x81, 0xf0, 0x65, 0x88, 0x19, 0xea, 0xb4, 0x83, + 0xf6, 0x5b, 0x32, 0x5d, 0x5a, 0xed, 0xa1, 0x52, 0x32, 0xcf, 0xad, 0xec, 0x75, 0xab, + 0x18, 0x66, 0xe4, 0xc0, 0x15, 0x5a, 0x9c, 0x74, 0xa7, 0xa5, 0x7c, 0xcf, 0x34, 0xc4, + 0x83, 0xac, 0x7d, 0xa1, 0x58, 0x8a, 0x1b, 0x6b, 0x99, 0x41, 0xf1, 0x10, 0x40, 0xf9, + 0x4c, 0xf7, 0x8f, 0xad, 0x89, 0xbf, 0x11, 0xfe, 0xd6, 0x9a, 0xa0, 0xd8, 0x31, 0x05, + 0xad, 0xac, 0xdd, 0x4e, 0x5f, 0x04, 0xa6, 0x24, 0x24, 0x02, 0x3c, 0x9b, 0x9e, 0x33, + 0xc4, 0xfb, 0x7f, 0x12, 0xbd, 0xf2, 0x1f, 0x07, 0xf2, 0x65, 0xc5, 0x37, 0xd5, 0x1c, + 0x65, 0x51, 0xf4, 0x61, 0x7b, 0x91, 0x5d, 0x21, 0x99, 0x18, 0x39, 0xc3, 0xd0, 0xd3, + 0x63, 0x93, 0xd6, 0x46, 0xe0, 0xa8, 0xa4, 0x15, 0x09, 0x21, 0x7d, 0x0e, 0x7d, 0x2c, + 0xa1, 0xa0, 0xa0, 0xd6, 0x77, 0xa3, 0xea, 0xca, 0x23, 0xed, 0xeb, 0x07, 0xb7, 0x4e, + 0x65, 0x2a, 0x0b, 0xc5, 0x0c, 0x6c, 0x08, 0x3a, 0x55, 0xd6, 0xc7, 0x30, 0x6e, 0x74, + 0x08, 0x6f, 0x47, 0x68, 0x93, 0x3a, 0xa2, 0x48, 0x73, 0x68, 0x18, 0x67, 0xa7, 0x89, + 0x3d, 0x77, 0xcb, 0x7f, 0x29, 0xb8, 0xc8, 0x47, 0xc5, 0x83, 0xf2, 0xd0, 0x71, 0xa6, + 0x86, 0x61, 0x6e, 0x20, 0x67, 0x19, 0xf7, 0x61, 0xae, 0x39, 0xc1, 0x10, 0x44, 0x2e, + 0x06, 0x16, 0x3d, 0x2b, 0x84, 0x59, 0x03, 0x60, 0x69, 0x5d, 0x4e, 0x19, 0x84, 0x9e, + 0x63, 0x4f, 0x24, 0xd9, 0xad, 0x39, 0x6c, 0x19, 0xff, 0x83, 0xce, 0x74, 0xf4, 0x6e, + 0x64, 0x5f, 0x93, 0x2e, 0x14, 0x1a, 0x41, 0x19, 0x59, 0x36, 0xc8, 0x5d, 0x51, 0x44, + 0x14, 0xf1, 0x12, 0xe6, 0x0b, 0x1a, 0x25, 0x37, 0xc3, 0x8d, 0x6d, 0xc6, 0xc4, 0x63, + 0x83, 0x05, 0xc9, 0xbd, 0x6c, 0x62, 0xe3, 0x66, 0xbc, 0x63, 0x12, 0x3e, 0x3e, 0x6d, + 0xd3, 0x6e, 0xed, 0xd3, 0x13, 0x6f, 0xce, 0x8d, 0xee, 0xca, 0x2a, 0xa0, 0x9a, 0x32, + 0x98, 0xa3, 0x9d, 0x83, 0x85, 0x9e, 0xfc, 0x9b, 0x2b, 0x69, 0xcf, 0x9a, 0x7d, 0xee, + 0x08, 0xa9, 0x8e, 0x4b, 0xe5, 0x58, 0xac, 0x79, 0x12, 0xfd, 0xcb, 0x42, 0x20, 0x90, + 0x75, 0x42, 0x02, 0x60, 0xf7, 0xca, 0xd0, 0xf2, 0xc0, 0x1f, 0x2a, 0xfe, 0x33, 0x07, + 0x3f, 0x26, 0x24, 0x9d, 0x94, 0x4f, 0x7a, 0x50, 0xdd, 0x84, 0x83, 0x9b, 0xc3, 0xea, + 0x7f, 0xde, 0xe4, 0xed, 0x71, 0x44, 0x9c, 0xf0, 0x75, 0x33, 0xd2, 0x6e, 0x1e, 0x27, + 0xa3, 0xef, 0xb0, 0x32, 0xc3, 0xa3, 0xb3, 0x4b, 0xd3, 0x09, 0x26, 0x22, 0xd2, 0x06, + 0x2a, 0xe5, 0x36, 0xef, 0x51, 0x49, 0xc4, 0x9b, 0x5b, 0xc9, 0x47, 0x5e, 0xaf, 0xab, + 0x6e, 0x67, 0x57, 0x61, 0x00, 0x8b, 0x0d, 0xad, 0xde, 0xec, 0xaa, 0x60, 0x44, 0x70, + 0xbb, 0xe0, 0xfa, 0xda, 0x25, 0x5d, 0x29, 0x0e, 0x92, 0xb1, 0x90, 0xc2, 0xc2, 0xd8, + 0xc2, 0xde, 0xe5, 0x45, 0x5d, 0x1f, 0xa9, 0xa9, + ], + c_enc: [ + 0xbc, 0x8a, 0x16, 0xfd, 0x57, 0xbc, 0x03, 0x60, 0x59, 0xe5, 0x4d, 0xc2, 0xbc, 0xfa, + 0xad, 0x9c, 0xc1, 0xfa, 0xe8, 0xcb, 0x2b, 0xe2, 0xa0, 0xc8, 0x5e, 0x81, 0x6c, 0x67, + 0xfd, 0xcd, 0x0b, 0x93, 0xe6, 0xa1, 0xed, 0xc8, 0x3b, 0xfa, 0xc4, 0x1e, 0xb4, 0x19, + 0x1c, 0x56, 0x4b, 0xac, 0x58, 0x01, 0x62, 0x92, 0x2d, 0x88, 0x25, 0x30, 0x28, 0xeb, + 0x88, 0xed, 0x46, 0xbf, 0x24, 0x2d, 0x82, 0x28, 0x6c, 0xb0, 0xa5, 0x66, 0xce, 0x01, + 0x18, 0x09, 0x4c, 0x90, 0x8f, 0xc2, 0x68, 0xb3, 0x2b, 0xcb, 0xdc, 0x4c, 0x22, 0x82, + 0xc5, 0x24, 0x2a, 0x65, 0x15, 0x48, 0x8b, 0x83, 0x3d, 0x29, 0x8e, 0x49, 0xda, 0x33, + 0x3a, 0xdd, 0x96, 0xc9, 0x9b, 0x98, 0xac, 0x06, 0x7f, 0x21, 0x41, 0x28, 0x9a, 0xcd, + 0x89, 0x49, 0x64, 0xfc, 0xf8, 0x94, 0xc9, 0x26, 0xf1, 0x81, 0xb1, 0x19, 0x85, 0x68, + 0xb1, 0xdd, 0x6f, 0x5e, 0xd1, 0x22, 0xdc, 0x70, 0x44, 0xad, 0x96, 0x76, 0xa7, 0xc5, + 0xae, 0x8e, 0xa9, 0x0f, 0x64, 0xbc, 0x59, 0x09, 0x36, 0xe0, 0xdf, 0x53, 0x1c, 0x1b, + 0x94, 0xb7, 0x35, 0xcd, 0x7b, 0x18, 0x73, 0xc8, 0x51, 0x6f, 0xea, 0x83, 0x64, 0x91, + 0x40, 0xbc, 0xbb, 0x9b, 0x42, 0xea, 0x6c, 0xb7, 0xaf, 0x67, 0xdc, 0x2d, 0xdb, 0xb4, + 0x7a, 0xb2, 0x25, 0xe7, 0x98, 0x29, 0xcd, 0xaf, 0x77, 0x04, 0xfb, 0x56, 0x5b, 0x43, + 0x91, 0x76, 0xf3, 0x35, 0xe4, 0x2b, 0x64, 0xc1, 0x6d, 0xdf, 0xe0, 0x88, 0x45, 0x38, + 0xbf, 0x43, 0x33, 0xe3, 0x2c, 0xa1, 0xe6, 0x27, 0x41, 0xc3, 0xe7, 0x4c, 0x8f, 0xaa, + 0xde, 0x0d, 0x89, 0xfa, 0x10, 0x30, 0xcd, 0x8e, 0xfd, 0x20, 0x22, 0x3e, 0x41, 0xc3, + 0xfc, 0xca, 0xaa, 0xe7, 0x76, 0xe6, 0x8e, 0xe8, 0x40, 0x56, 0x6f, 0x4d, 0x13, 0xc1, + 0xc9, 0xd5, 0xcb, 0xbe, 0xcf, 0xa7, 0x49, 0x9d, 0x43, 0x12, 0x7c, 0xe8, 0xfd, 0x83, + 0xdb, 0x6e, 0x89, 0x67, 0x90, 0x32, 0x25, 0x24, 0x87, 0x21, 0x40, 0x0d, 0x5e, 0x3e, + 0xc0, 0xc1, 0x8e, 0x10, 0xf5, 0xe6, 0x6e, 0x10, 0x17, 0x0c, 0xb3, 0x74, 0x48, 0x22, + 0x4a, 0xde, 0x39, 0x9f, 0x1d, 0x74, 0xa2, 0x16, 0x7d, 0x9f, 0xdb, 0xfe, 0x36, 0xe1, + 0x28, 0xe4, 0x8c, 0x01, 0x62, 0x61, 0x16, 0xc1, 0xa2, 0xdf, 0x3c, 0xb0, 0x23, 0xd8, + 0x0a, 0xed, 0x9b, 0xfc, 0x02, 0x71, 0xb8, 0x1f, 0xf9, 0x79, 0x81, 0x01, 0x6f, 0xff, + 0x19, 0x61, 0x08, 0x88, 0x8b, 0xcb, 0xca, 0x84, 0x5b, 0x5d, 0x97, 0x1b, 0xd5, 0x4f, + 0x49, 0x7d, 0x3f, 0x3a, 0x09, 0x29, 0x9e, 0x56, 0x50, 0xd3, 0x26, 0xd8, 0x9b, 0x9a, + 0x5e, 0xff, 0x3e, 0xbd, 0x27, 0x39, 0x34, 0xc4, 0x9f, 0x81, 0x46, 0x7e, 0xb8, 0x4f, + 0x56, 0x98, 0x90, 0xcf, 0x89, 0x05, 0xb7, 0x4c, 0xd3, 0xed, 0xa6, 0x3c, 0x53, 0x88, + 0xd5, 0x51, 0x5e, 0x3f, 0xd8, 0x1c, 0x70, 0xc1, 0x5e, 0x2a, 0x98, 0x2d, 0x59, 0x0e, + 0x87, 0xb8, 0x64, 0x45, 0x4b, 0xcd, 0xf5, 0xf8, 0x4d, 0x9f, 0x11, 0xcb, 0x9c, 0xf2, + 0xb5, 0xde, 0x3c, 0x5e, 0x0e, 0x2a, 0x6c, 0x48, 0x16, 0x61, 0x64, 0x96, 0x6f, 0xb9, + 0x0d, 0xac, 0xf8, 0x67, 0x4f, 0x9f, 0x1a, 0x34, 0xd2, 0xcd, 0xc7, 0xc9, 0x48, 0xab, + 0x99, 0xc3, 0x58, 0xa1, 0x95, 0x47, 0x0a, 0xdd, 0x06, 0x5e, 0xaf, 0x79, 0x24, 0xfa, + 0xed, 0x63, 0x27, 0xa6, 0x10, 0xf5, 0x2e, 0xd5, 0xd3, 0xa8, 0x7e, 0x11, 0xb5, 0x97, + 0x4f, 0xa0, 0x60, 0x45, 0xa4, 0x08, 0x95, 0xcd, 0xad, 0x60, 0x1c, 0xae, 0x01, 0xed, + 0xda, 0x17, 0x52, 0x81, 0x62, 0xd7, 0x21, 0x24, 0xf2, 0x05, 0x6b, 0x9a, 0xb8, 0xc0, + 0xc0, 0xf5, 0xc6, 0xdd, 0xaa, 0x0f, 0x5e, 0x33, 0xfb, 0x04, 0x23, 0x0b, 0x61, 0x1b, + 0xff, 0xd8, 0xbd, 0xdc, 0x63, 0x4c, 0x79, 0x60, 0xa3, 0xd4, 0xe6, 0x8f, 0x21, 0xe7, + 0x83, 0x04, 0xe4, 0xc4, 0xd2, 0xdc, 0xd6, 0xa1, 0x9c, 0xfc, 0x04, 0x57, 0x97, 0x09, + 0xf0, 0x33, 0xf1, 0x95, 0x78, 0xae, 0x7f, 0x0b, 0xc6, 0x46, 0x32, 0xa6, 0xd7, 0xda, + 0x40, 0xdc, 0x0c, 0x38, 0x1d, 0xd4, 0x49, 0xe1, 0xa0, 0xb0, 0xe7, 0xf8, 0xc5, 0xfe, + 0x88, 0xaa, 0x93, 0x4e, 0x16, 0xc8, 0xf1, 0xdb, 0xef, 0x72, 0x88, 0x34, 0xcf, 0x25, + 0x30, 0xe3, 0x3f, 0xb9, 0x27, 0xe9, 0x96, 0xce, 0x48, 0x89, 0xf9, 0xf6, 0xf4, 0x42, + 0x1c, 0x60, 0x78, 0xb0, 0x8d, 0x72, 0x2d, 0xc4, 0x4a, 0xb7, + ], + ock: [ + 0x9c, 0xba, 0xd2, 0xf3, 0x8b, 0xf8, 0x8f, 0x39, 0x47, 0xce, 0xf6, 0x4d, 0xe7, 0xa6, + 0xf4, 0x3e, 0x4c, 0xbb, 0x41, 0xe6, 0xe0, 0x37, 0xf1, 0x42, 0x01, 0xae, 0xe8, 0xab, + 0xfd, 0xf8, 0xa2, 0x35, + ], + op: [ + 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, + 0xbc, 0xab, 0xf4, 0x0f, 0xf1, 0xe4, 0x2c, 0x48, 0x66, 0x77, 0x57, 0x4f, 0x9e, 0xf8, + 0x36, 0x34, 0xb0, 0x23, 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, + 0xa9, 0x19, 0xa2, 0x06, 0x31, 0xe2, 0x91, 0x14, 0xc8, 0x60, 0x07, 0xa2, 0xb1, 0x8b, + 0x25, 0xec, 0xff, 0x47, 0x72, 0x16, 0x8c, 0x05, + ], + c_out: [ + 0xf6, 0x25, 0xcd, 0x3d, 0x19, 0x97, 0xb0, 0xd3, 0xf2, 0x29, 0x5a, 0xac, 0xc0, 0x3a, + 0xe0, 0xc9, 0x47, 0x28, 0xb3, 0x3c, 0xc4, 0xf1, 0x6f, 0xd4, 0x28, 0xd6, 0x5f, 0x3c, + 0x78, 0x5e, 0x8c, 0x0b, 0xb4, 0x66, 0xc1, 0x33, 0xd4, 0x83, 0xdf, 0xc5, 0xb1, 0xb3, + 0x15, 0x1d, 0xa2, 0xd5, 0xf2, 0x4a, 0x2b, 0x32, 0x0d, 0x8e, 0x9c, 0xd3, 0x41, 0x5c, + 0x25, 0xb6, 0xf9, 0x76, 0x1f, 0x42, 0x70, 0x04, 0xce, 0xe5, 0x4f, 0x75, 0xf1, 0x25, + 0xbc, 0x50, 0x5e, 0xf6, 0x26, 0xef, 0xc9, 0xdd, 0x63, 0x66, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x47, 0x30, 0x68, 0xbf, 0x68, 0xe5, 0x0b, 0xe3, 0x85, 0x7d, 0xec, 0xb2, 0xef, 0xd5, + 0xde, 0x20, 0xea, 0xc8, 0x1b, 0x37, 0x5b, 0xd0, 0xbb, 0xe8, 0x36, 0x86, 0x6e, 0x99, + 0x36, 0x3b, 0x37, 0x50, 0x9d, 0x53, 0x8f, 0xcc, 0xa9, 0x33, 0x37, 0xad, 0xbc, 0x24, + 0x81, 0xe2, 0x70, 0x26, 0x18, 0x4c, 0x3f, 0x4f, 0x48, 0xcc, 0x5d, 0x5a, 0x0e, 0x4a, + 0x4c, 0xfa, 0x4d, 0x6a, 0x24, 0x7f, 0x2e, 0x39, + ], + ovk: [ + 0x25, 0xb4, 0xc2, 0x6e, 0xb0, 0x3f, 0x71, 0x66, 0x46, 0x61, 0x9a, 0xf0, 0x24, 0x56, + 0xae, 0x69, 0x59, 0x62, 0xfe, 0x5e, 0x93, 0x1a, 0x63, 0xb5, 0xc7, 0x90, 0x52, 0xec, + 0xd3, 0x33, 0xe1, 0x84, + ], + default_d: [ + 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, + ], + default_pk_d: [ + 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, + 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, + 0x34, 0xeb, 0x90, 0x2c, + ], + v: 15119422206032203650, + rseed: [ + 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, + 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, + 0x2d, 0x9b, 0x4c, 0x8f, + ], + asset: [ + 0x61, 0x16, 0xcf, 0xec, 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, + 0x6a, 0xe8, 0xf7, 0xcc, 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, + 0x38, 0xe1, 0x73, 0x29, + ], + memo: [ + 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, + 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, + 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, + 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, + 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, + 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, + 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, + 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, + 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, + 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, + 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, + 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, + 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, + 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, + 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, + 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, + 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, + 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, + 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, + 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, + 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, + 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, + 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, + 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, + 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, + 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, + 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, + 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, + 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, + 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, + 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, + 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, + 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, + 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, + 0x08, 0x74, 0x86, 0x9c, 0x02, 0xf3, 0xdc, 0xa1, 0x1c, 0x3b, 0x90, 0xcb, 0x21, 0x4e, + 0x68, 0xbc, 0x1c, 0xae, 0x03, 0x9d, 0x7a, 0x14, 0x6c, 0xdc, 0x1d, 0x60, 0x9d, 0x7a, + 0x6b, 0x3f, 0xd5, 0xd4, 0x61, 0xb0, 0x95, 0x1c, + ], + cv_net: [ + 0x45, 0x37, 0x85, 0x3e, 0x18, 0xac, 0x2c, 0xe9, 0x37, 0x79, 0x8c, 0x9b, 0xce, 0xa9, + 0x80, 0x2d, 0x65, 0x00, 0x74, 0xdb, 0xd7, 0xe0, 0x6a, 0x48, 0x98, 0x03, 0x15, 0x30, + 0x78, 0xe9, 0x97, 0x0b, + ], + rho: [ + 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, + 0x85, 0x72, 0xa3, 0x05, 0xfa, 0x3b, 0x70, 0x68, 0xa3, 0x78, 0x38, 0x27, 0xaf, 0xe2, + 0x14, 0x7a, 0x27, 0x10, + ], + cmx: [ + 0xf2, 0x04, 0x22, 0x51, 0xa0, 0x59, 0xa2, 0xf5, 0x8a, 0xb8, 0xe9, 0x0b, 0x52, 0x64, + 0xd0, 0xa4, 0x3f, 0x96, 0xd7, 0x7e, 0xdd, 0x54, 0xf8, 0x0f, 0xf4, 0x9d, 0x43, 0x86, + 0x81, 0x4d, 0x73, 0x2e, + ], + esk: [ + 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, 0x1d, 0xa4, 0xb1, 0x44, + 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, 0xaf, 0x2b, 0xd1, 0xa0, + 0x8c, 0x67, 0xd9, 0x3f, + ], + ephemeral_key: [ + 0x46, 0x73, 0x1f, 0xff, 0xc5, 0x9a, 0xf4, 0xc1, 0x28, 0x82, 0xbc, 0xca, 0xea, 0xa7, + 0xb8, 0xed, 0x39, 0x0b, 0x14, 0x66, 0x72, 0xe1, 0x36, 0x51, 0xc3, 0x2e, 0x57, 0x80, + 0x62, 0x68, 0x65, 0xa7, + ], + shared_secret: [ + 0x9d, 0x56, 0xbd, 0x96, 0x00, 0x39, 0x62, 0x5e, 0x11, 0x7d, 0x7b, 0xfe, 0xd4, 0x3a, + 0x57, 0x3b, 0x11, 0x51, 0x7f, 0xfa, 0x76, 0x14, 0xea, 0x2d, 0xa7, 0x7e, 0xdf, 0x62, + 0x7f, 0x6f, 0x13, 0xaa, + ], + k_enc: [ + 0x04, 0x2f, 0x92, 0x82, 0x13, 0x44, 0xde, 0x97, 0x7c, 0xee, 0x89, 0x9e, 0xd2, 0x1b, + 0xc8, 0x48, 0xf5, 0xc4, 0xfe, 0xdc, 0x39, 0xf2, 0xdf, 0xed, 0xad, 0x62, 0xcc, 0x7a, + 0x92, 0x7f, 0x74, 0xfd, + ], + p_enc: [ + 0x03, 0x61, 0x5f, 0x53, 0x89, 0x1a, 0x18, 0xe0, 0x52, 0x17, 0x2d, 0x81, 0x82, 0xcf, + 0xb3, 0xe7, 0x63, 0xfa, 0xd2, 0xd1, 0x45, 0x60, 0x3a, 0x53, 0x46, 0x2c, 0x60, 0xe1, + 0xf6, 0xcb, 0x0c, 0x9c, 0xa0, 0x39, 0x0c, 0x48, 0x82, 0x24, 0xc3, 0x13, 0x26, 0x9f, + 0xcd, 0x59, 0xfc, 0xb6, 0x11, 0xfb, 0x2d, 0x9b, 0x4c, 0x8f, 0x61, 0x16, 0xcf, 0xec, + 0x26, 0x47, 0xcc, 0xaa, 0xe1, 0xc7, 0x4b, 0x41, 0x6f, 0x3e, 0x6a, 0xe8, 0xf7, 0xcc, + 0x60, 0xea, 0xaf, 0x7b, 0x6a, 0x59, 0x0d, 0x51, 0x54, 0x41, 0x38, 0xe1, 0x73, 0x29, + 0xff, 0xa6, 0x01, 0xbb, 0x1c, 0xb8, 0xd0, 0x7d, 0x79, 0x7b, 0xf5, 0xde, 0x52, 0xbc, + 0xee, 0xb0, 0x23, 0x01, 0xc8, 0x96, 0x2a, 0xc1, 0xfc, 0x04, 0x91, 0xdc, 0x81, 0xaf, + 0xfd, 0x6c, 0x1e, 0xbf, 0x89, 0xa1, 0x3d, 0x6f, 0x29, 0x0e, 0xda, 0x5d, 0x5c, 0xef, + 0x38, 0x22, 0x15, 0xc5, 0xe9, 0x51, 0xd7, 0x13, 0x05, 0xef, 0x33, 0xd9, 0x73, 0x71, + 0x26, 0xd0, 0xe6, 0x62, 0x90, 0x5f, 0x12, 0x50, 0x92, 0x6f, 0x6a, 0x22, 0x99, 0x90, + 0xe3, 0x8f, 0x69, 0xad, 0x9a, 0x91, 0x92, 0xb3, 0x02, 0xf2, 0x6b, 0xdd, 0xa4, 0x65, + 0xd9, 0x0b, 0x94, 0xb1, 0x2c, 0x57, 0xfa, 0x3f, 0xd6, 0x93, 0x00, 0x83, 0xf1, 0x84, + 0x43, 0x8d, 0x8a, 0x88, 0x9d, 0x3f, 0x5e, 0xce, 0xa2, 0xc6, 0xd2, 0x3d, 0x67, 0x36, + 0xf2, 0xa0, 0xf1, 0x8e, 0x26, 0xf4, 0xfa, 0x45, 0xd1, 0xbe, 0x8f, 0x3d, 0xc4, 0xa7, + 0x07, 0x13, 0x7e, 0x95, 0xd2, 0xad, 0x59, 0x4f, 0x6c, 0x03, 0xd2, 0x49, 0x23, 0x06, + 0x7a, 0xe4, 0x7f, 0xd6, 0x42, 0x5e, 0xfb, 0x9c, 0x1d, 0x50, 0x4e, 0x6f, 0xd5, 0x57, + 0x53, 0x40, 0x94, 0x56, 0x01, 0xfe, 0x80, 0x6f, 0x57, 0x56, 0xac, 0xb5, 0x62, 0xf1, + 0x3c, 0x0c, 0xa1, 0xd8, 0x03, 0xa1, 0x95, 0xc2, 0xeb, 0xb2, 0xef, 0x02, 0xac, 0x33, + 0xe6, 0xa8, 0x8d, 0xea, 0x07, 0x5b, 0xa9, 0x96, 0xd3, 0xc3, 0x36, 0x64, 0x8e, 0x86, + 0x94, 0xd3, 0xa1, 0x9d, 0x3d, 0xca, 0x53, 0x1b, 0xeb, 0x50, 0xd4, 0x32, 0x7c, 0x5c, + 0x0c, 0x23, 0xcb, 0x7c, 0xfd, 0xb0, 0x8c, 0xa7, 0xcf, 0x2c, 0xac, 0x6b, 0xc1, 0x39, + 0xd0, 0x74, 0x14, 0x73, 0xd3, 0x76, 0x02, 0x9c, 0xb4, 0xab, 0x6b, 0xf0, 0x54, 0x55, + 0x7c, 0xe2, 0x94, 0xc7, 0x28, 0xa4, 0x68, 0x7d, 0x57, 0xec, 0x89, 0x09, 0xff, 0x51, + 0xa4, 0xd0, 0x2f, 0x9d, 0xcd, 0x11, 0x19, 0x3d, 0x7d, 0x1c, 0x9f, 0xda, 0xe6, 0xa1, + 0x73, 0x96, 0xa1, 0xbf, 0x57, 0xa9, 0x94, 0x93, 0x4f, 0x5e, 0x7a, 0x59, 0xf0, 0x45, + 0xde, 0xbe, 0xaf, 0xf6, 0x2e, 0xf3, 0x26, 0xb9, 0x47, 0xf2, 0xa8, 0xb4, 0x95, 0x55, + 0xe4, 0xd9, 0x9b, 0x3b, 0xf5, 0xc8, 0x1f, 0xf9, 0xfe, 0x31, 0x4e, 0x04, 0x7a, 0xf1, + 0x52, 0x50, 0x8f, 0x57, 0x01, 0x5c, 0xa4, 0x02, 0xc6, 0x7d, 0x92, 0x5c, 0x99, 0xac, + 0xea, 0x3e, 0xe8, 0xcc, 0x4b, 0x00, 0x8c, 0x5c, 0xb4, 0x39, 0x66, 0xe7, 0x14, 0xef, + 0x48, 0x0f, 0xd0, 0x5e, 0x07, 0xc7, 0xb2, 0xdd, 0xa9, 0xaa, 0x39, 0x66, 0x11, 0x3e, + 0xaa, 0x29, 0x3d, 0x3f, 0x62, 0x2b, 0x30, 0x9d, 0x64, 0x80, 0x3c, 0xe1, 0xe6, 0x37, + 0x8b, 0x6a, 0xac, 0x4f, 0xab, 0x52, 0x7c, 0x43, 0xcd, 0x45, 0xed, 0x0a, 0x3c, 0x1a, + 0x4b, 0x9f, 0xb1, 0x8d, 0xcc, 0xcf, 0xcd, 0xb6, 0xac, 0x0c, 0x24, 0x21, 0x63, 0x9c, + 0xda, 0x00, 0x75, 0xa2, 0x0d, 0xc5, 0x11, 0x1b, 0x8d, 0x3d, 0x31, 0x99, 0x49, 0x5b, + 0xd9, 0x13, 0x3d, 0xba, 0xb9, 0x45, 0x41, 0x41, 0x0e, 0x4f, 0xba, 0x92, 0xc7, 0xb6, + 0x06, 0xa5, 0xcb, 0x12, 0x2f, 0x14, 0x0c, 0xf1, 0xa3, 0x59, 0x6f, 0x27, 0x88, 0xf3, + 0xc8, 0xb9, 0x26, 0x60, 0xf1, 0x4c, 0xb6, 0x5a, 0xf5, 0xdd, 0x23, 0xdf, 0xdb, 0xac, + 0x13, 0x71, 0xec, 0xf4, 0xb3, 0x37, 0x12, 0xfe, 0xd2, 0x29, 0x2c, 0x44, 0xf7, 0x08, + 0x34, 0xcf, 0x96, 0xc0, 0x5d, 0x58, 0x82, 0x7e, 0x69, 0xbf, 0xc2, 0xe6, 0x96, 0xfa, + 0x08, 0x74, 0x86, 0x9c, 0x02, 0xf3, 0xdc, 0xa1, 0x1c, 0x3b, 0x90, 0xcb, 0x21, 0x4e, + 0x68, 0xbc, 0x1c, 0xae, 0x03, 0x9d, 0x7a, 0x14, 0x6c, 0xdc, 0x1d, 0x60, 0x9d, 0x7a, + 0x6b, 0x3f, 0xd5, 0xd4, 0x61, 0xb0, 0x95, 0x1c, + ], + c_enc: [ + 0x16, 0x76, 0x72, 0x3a, 0x18, 0xff, 0x58, 0x77, 0x70, 0x15, 0x8d, 0x6b, 0x85, 0x09, + 0x3c, 0x49, 0x20, 0x16, 0xf8, 0x7e, 0xc3, 0xfa, 0xe8, 0xb0, 0xb4, 0x7c, 0xd9, 0x29, + 0x8f, 0xa2, 0x07, 0xc4, 0xb6, 0x09, 0xc6, 0x92, 0xdd, 0xb9, 0x10, 0x19, 0x72, 0xc9, + 0x4c, 0x71, 0x87, 0x84, 0x85, 0x42, 0x1e, 0xfb, 0x70, 0x1c, 0xf5, 0x15, 0xa2, 0x3f, + 0xbf, 0x36, 0xfe, 0x93, 0x54, 0x0d, 0x82, 0xd6, 0x9a, 0x72, 0x62, 0x4e, 0x25, 0x4f, + 0xe3, 0xa0, 0x11, 0xc5, 0xdb, 0xdb, 0xd2, 0xbd, 0xff, 0xb8, 0x83, 0x8a, 0xf3, 0x7d, + 0x03, 0xce, 0x69, 0x12, 0x6b, 0x2f, 0x68, 0x21, 0x25, 0xb7, 0xa9, 0xb2, 0xa3, 0xee, + 0x11, 0x8a, 0xe5, 0xad, 0xb4, 0x60, 0xa4, 0x68, 0x7c, 0x24, 0x30, 0x18, 0x7b, 0xfd, + 0x0f, 0x6c, 0x2a, 0x3d, 0x5d, 0x74, 0x30, 0x1c, 0xbd, 0x8f, 0xd0, 0x26, 0xc8, 0x64, + 0x4f, 0xbf, 0xa2, 0x65, 0x69, 0x88, 0xe9, 0x58, 0x59, 0x0b, 0x81, 0x6a, 0x1e, 0x64, + 0x0e, 0x46, 0x71, 0x0e, 0x46, 0xfa, 0x15, 0x94, 0xff, 0x2a, 0x61, 0xd6, 0xf6, 0xe7, + 0xb4, 0xa9, 0xf6, 0xe0, 0xde, 0x68, 0x3d, 0x95, 0xe5, 0x9d, 0x43, 0x57, 0xf7, 0x9a, + 0xc4, 0x93, 0x86, 0x6d, 0xab, 0x06, 0x57, 0x76, 0xc0, 0xb1, 0x43, 0x6b, 0x8e, 0x04, + 0x47, 0x68, 0x43, 0xc2, 0x8b, 0x48, 0x45, 0xea, 0xff, 0x17, 0x83, 0xa8, 0x50, 0xc2, + 0x4a, 0x90, 0x65, 0xc3, 0x36, 0x51, 0xc4, 0xb3, 0xdd, 0x19, 0x92, 0xf4, 0xf2, 0x08, + 0xb8, 0x51, 0xbf, 0xff, 0xe9, 0xb7, 0xbb, 0x7a, 0xad, 0x76, 0x7c, 0x23, 0x60, 0xb0, + 0x5c, 0x11, 0x23, 0x09, 0x66, 0xda, 0x55, 0x7e, 0x31, 0x3a, 0xe6, 0x1c, 0x95, 0x42, + 0x97, 0x66, 0x10, 0x6b, 0x4b, 0x1b, 0x35, 0x47, 0x64, 0xe4, 0xe1, 0xe4, 0xdf, 0x90, + 0xc1, 0x2d, 0x24, 0x37, 0x9d, 0x67, 0xba, 0xc6, 0x66, 0x97, 0xaf, 0x23, 0x44, 0x97, + 0xf2, 0xd6, 0xf9, 0xa6, 0x12, 0x85, 0x0d, 0xd7, 0x1d, 0x1c, 0x98, 0xce, 0x65, 0xd8, + 0x50, 0x7f, 0xa3, 0x46, 0x35, 0x83, 0x12, 0x39, 0xe2, 0x10, 0xf7, 0xdb, 0xb3, 0x05, + 0x04, 0x2d, 0x47, 0x50, 0xd9, 0x5a, 0xdf, 0xff, 0xc9, 0x8d, 0xeb, 0x0f, 0x17, 0x13, + 0xbc, 0x01, 0xaf, 0x5d, 0xb5, 0x99, 0x29, 0x89, 0x76, 0xab, 0xba, 0xdb, 0x0f, 0x4d, + 0xed, 0x1a, 0x2f, 0xe4, 0xcf, 0x90, 0x60, 0x0e, 0x0d, 0x28, 0xd3, 0x07, 0xc6, 0x41, + 0xf7, 0x52, 0x3c, 0x16, 0x66, 0x40, 0x1d, 0x78, 0x6f, 0xd2, 0x4a, 0xe1, 0x68, 0x0f, + 0xe9, 0x26, 0x70, 0x4c, 0xb6, 0xe2, 0xaf, 0x80, 0x1a, 0x0d, 0x82, 0x75, 0x9d, 0xd8, + 0x7a, 0x8c, 0xd8, 0x7b, 0x85, 0xbb, 0x07, 0x51, 0xa7, 0x08, 0xc9, 0xf4, 0xa7, 0xd3, + 0x24, 0xe5, 0xc9, 0x3a, 0xd2, 0x2b, 0x86, 0x43, 0xdf, 0xfa, 0x5f, 0x50, 0x79, 0xfc, + 0x6f, 0x01, 0x6d, 0x94, 0x3c, 0x99, 0x09, 0x27, 0x5c, 0x96, 0xf5, 0xfe, 0x7b, 0x56, + 0x33, 0x3c, 0x24, 0x01, 0x99, 0x73, 0xd9, 0x4f, 0x06, 0xeb, 0xf6, 0xc0, 0xf6, 0xef, + 0xdd, 0x42, 0xea, 0xb0, 0x63, 0x49, 0xd5, 0xe8, 0xb9, 0x60, 0xba, 0x8c, 0x68, 0xee, + 0xfd, 0x44, 0x49, 0x99, 0xf6, 0xfa, 0x3d, 0x6a, 0x3a, 0xe3, 0x1a, 0xe8, 0x54, 0x6e, + 0xdc, 0x62, 0x78, 0x25, 0x63, 0x7e, 0x1e, 0x86, 0x39, 0x8d, 0x0e, 0xd3, 0xd8, 0x8b, + 0xfa, 0xea, 0x8b, 0x4b, 0x08, 0x50, 0xd8, 0xa8, 0x28, 0x6e, 0xa9, 0xf3, 0xd1, 0x3f, + 0xa8, 0xf4, 0x16, 0x53, 0x45, 0x1b, 0x97, 0xb3, 0x8b, 0x06, 0x3a, 0x5f, 0xc6, 0xdb, + 0xe4, 0xe9, 0x19, 0x94, 0x87, 0xc9, 0x73, 0xef, 0x8f, 0x2c, 0x26, 0x3f, 0x85, 0x05, + 0xf4, 0xc3, 0xbe, 0xc9, 0xd1, 0x79, 0xbb, 0xd6, 0x5d, 0x1e, 0xdc, 0x58, 0x95, 0xa1, + 0x6c, 0xc7, 0x98, 0x6b, 0xcf, 0xc4, 0xba, 0xe8, 0x7e, 0xc0, 0xb2, 0x9b, 0xf1, 0xb3, + 0x97, 0x61, 0x5c, 0x95, 0x13, 0xfa, 0x52, 0xeb, 0xe1, 0xe9, 0xfc, 0xfb, 0xf1, 0x92, + 0xed, 0x49, 0x26, 0x27, 0x27, 0xa0, 0x8a, 0xd3, 0xc2, 0x95, 0x5b, 0x3d, 0xf2, 0xee, + 0xad, 0x30, 0x24, 0x3e, 0x32, 0xb2, 0x54, 0x1e, 0x8f, 0x9f, 0xce, 0x6c, 0xa5, 0xe7, + 0x0f, 0xf3, 0xa5, 0xe9, 0x35, 0x2b, 0xb8, 0x93, 0xe3, 0xdc, 0xa2, 0x74, 0xa1, 0x11, + 0xbb, 0xd6, 0x9c, 0x2b, 0x4c, 0x2e, 0xc9, 0x49, 0x81, 0x3d, 0xb7, 0x8c, 0x5e, 0x16, + 0xbc, 0x7a, 0xf6, 0x72, 0xb2, 0x0d, 0x7a, 0x16, 0xec, 0x48, + ], + ock: [ + 0x97, 0x9b, 0x31, 0x5d, 0x3e, 0x1f, 0x5c, 0xa1, 0x8a, 0x92, 0x86, 0xd9, 0x2c, 0xc8, + 0x8e, 0x63, 0x62, 0x4b, 0x39, 0x9b, 0x29, 0x19, 0xbf, 0x4e, 0x67, 0xda, 0x7c, 0xd3, + 0x94, 0xf4, 0x5c, 0x49, + ], + op: [ + 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, + 0x4f, 0x3a, 0x65, 0x91, 0xa7, 0xc0, 0x1e, 0xe2, 0xcf, 0x35, 0x30, 0x2f, 0x38, 0xd3, + 0x34, 0xeb, 0x90, 0x2c, 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, + 0x1d, 0xa4, 0xb1, 0x44, 0x01, 0x72, 0x02, 0x9a, 0x2e, 0xbc, 0x0a, 0x2a, 0xbe, 0xb8, + 0xaf, 0x2b, 0xd1, 0xa0, 0x8c, 0x67, 0xd9, 0x3f, + ], + c_out: [ + 0x83, 0xf7, 0xa1, 0xda, 0x72, 0x4d, 0xd1, 0x54, 0xe7, 0xd9, 0x47, 0xc0, 0xfc, 0x83, + 0x42, 0x87, 0xf3, 0x3c, 0xd4, 0xb3, 0x4a, 0xfa, 0xc0, 0xda, 0x55, 0xe4, 0x37, 0xaf, + 0xae, 0x67, 0xa9, 0x9c, 0xbd, 0x89, 0x75, 0xc9, 0x54, 0xcf, 0x41, 0xaa, 0x1e, 0x9a, + 0x8f, 0x99, 0x98, 0x3d, 0x58, 0x6f, 0x5e, 0x35, 0x37, 0xda, 0xb7, 0x2a, 0xe1, 0x82, + 0x7a, 0xa5, 0xdf, 0xc9, 0xdd, 0xad, 0x06, 0x26, 0x78, 0x84, 0x6f, 0xf8, 0x09, 0x3d, + 0xfd, 0x15, 0xf6, 0x3d, 0x47, 0xe5, 0xa3, 0xbb, 0x74, 0x39, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xfc, 0x8c, 0x64, 0x1c, 0x0b, 0x28, 0xbe, 0xbf, 0x85, 0x24, 0x25, 0xae, 0x95, 0x5f, + 0xe6, 0x40, 0x1c, 0xfd, 0x9e, 0x60, 0x63, 0xf2, 0x50, 0x11, 0x3d, 0xa0, 0xb5, 0x8b, + 0x2a, 0x0f, 0x49, 0xb9, 0x12, 0x0b, 0x89, 0x9f, 0x08, 0x10, 0x6b, 0x30, 0x86, 0xb2, + 0xf4, 0x11, 0x63, 0x6f, 0x50, 0xab, 0x48, 0x7c, 0xfb, 0x28, 0x81, 0x89, 0x77, 0x8f, + 0xe4, 0xe5, 0xa1, 0x91, 0x8b, 0x98, 0xd5, 0x0a, + ], + ovk: [ + 0xbe, 0xd1, 0x7d, 0xf5, 0xf8, 0x88, 0xc8, 0xca, 0x14, 0x67, 0xae, 0x17, 0xdb, 0xbc, + 0xde, 0x31, 0xc1, 0x10, 0x5c, 0xb5, 0xbd, 0xa8, 0x8a, 0xc6, 0xc6, 0x27, 0x00, 0x2c, + 0xe2, 0x1c, 0x02, 0x14, + ], + default_d: [ + 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, + ], + default_pk_d: [ + 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, + 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, + 0x89, 0xcf, 0xf9, 0x1e, + ], + v: 7555450289479839818, + rseed: [ + 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, + 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, + 0x03, 0xaa, 0xe0, 0x4b, + ], + asset: [ + 0x29, 0x8a, 0xc0, 0xaf, 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, + 0x62, 0xcd, 0x1c, 0xa0, 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, + 0x82, 0x1a, 0x41, 0x84, + ], + memo: [ + 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, + 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, + 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, + 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, + 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, + 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, + 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, + 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, + 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, + 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, + 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, + 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, + 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, + 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, + 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, + 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, + 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, + 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, + 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, + 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, + 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, + 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, + 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, + 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, + 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, + 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, + 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, + 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, + 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, + 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, + 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, + 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, + 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, + 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, + 0x6b, 0x21, 0x43, 0x0f, 0xa5, 0x4d, 0xcf, 0xbf, 0x2b, 0x9c, 0x49, 0xd1, 0x42, 0x06, + 0x42, 0x09, 0xee, 0xee, 0xd4, 0xd4, 0x71, 0xff, 0xc0, 0x17, 0xd4, 0xe2, 0x0a, 0x79, + 0x6b, 0x09, 0x27, 0x80, 0x4c, 0x06, 0x1b, 0x9f, + ], + cv_net: [ + 0x71, 0x00, 0xa7, 0x52, 0x93, 0xf4, 0xae, 0xfd, 0x89, 0xa1, 0x66, 0xa5, 0xf8, 0x4d, + 0x34, 0xda, 0xf4, 0xe5, 0x98, 0x34, 0xcd, 0x65, 0xd7, 0x9f, 0xfc, 0x41, 0xdd, 0xf0, + 0x68, 0x2d, 0xc2, 0xab, + ], + rho: [ + 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, + 0x4d, 0x4b, 0x32, 0x36, 0xdb, 0x1f, 0x32, 0xac, 0xa7, 0x94, 0x5c, 0xf2, 0x6e, 0xc8, + 0xb9, 0xd0, 0xb7, 0x32, + ], + cmx: [ + 0xe1, 0xc7, 0x67, 0xf3, 0x30, 0x15, 0xb5, 0xe2, 0x4a, 0x9a, 0xa5, 0x8b, 0x64, 0x7b, + 0x6b, 0x61, 0x32, 0x3c, 0xd3, 0x47, 0xe7, 0x21, 0x4c, 0x29, 0x1d, 0x09, 0x95, 0xc0, + 0xf5, 0xa6, 0x93, 0x2f, + ], + esk: [ + 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, 0x58, 0x93, 0x20, 0x26, + 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, 0x44, 0x72, 0x83, 0xf9, + 0x4e, 0xd5, 0x95, 0x3d, + ], + ephemeral_key: [ + 0xce, 0x67, 0x94, 0x31, 0x5f, 0x46, 0x2d, 0xed, 0xf3, 0xc5, 0x77, 0x4a, 0xac, 0x7f, + 0x3c, 0x7b, 0x70, 0xba, 0x7d, 0x72, 0x43, 0xbb, 0x0c, 0xc3, 0xb0, 0x67, 0xdc, 0x28, + 0x38, 0xf1, 0x11, 0xa3, + ], + shared_secret: [ + 0xea, 0x22, 0x6b, 0x69, 0xec, 0x2d, 0x9f, 0xcf, 0x91, 0x9c, 0xe5, 0x70, 0x06, 0x09, + 0x89, 0x94, 0xf7, 0x14, 0xb3, 0x9c, 0x34, 0x61, 0x52, 0xbc, 0x11, 0x51, 0xa0, 0xc6, + 0x9e, 0xe0, 0x04, 0x06, + ], + k_enc: [ + 0xb4, 0x56, 0x1b, 0xdb, 0xe0, 0xea, 0x44, 0x20, 0x75, 0xe7, 0xe6, 0x6f, 0xb3, 0xc0, + 0xfa, 0xd3, 0xaf, 0xc2, 0x85, 0x6e, 0xf4, 0xf3, 0x61, 0xb4, 0xac, 0x33, 0xaa, 0xe0, + 0x15, 0x52, 0xfd, 0x49, + ], + p_enc: [ + 0x03, 0xd2, 0xf7, 0x5f, 0x7c, 0xe7, 0x1b, 0xa4, 0xa7, 0xab, 0x69, 0xb8, 0x4a, 0x70, + 0x91, 0xfe, 0x01, 0x5a, 0xda, 0x68, 0x13, 0xeb, 0x7c, 0xea, 0xa5, 0xff, 0x12, 0x90, + 0xb0, 0x3e, 0xc9, 0x1c, 0xe6, 0xdd, 0x28, 0x13, 0x0c, 0x3a, 0xb0, 0xb2, 0x3b, 0x60, + 0x2b, 0xd5, 0xbe, 0x5d, 0xc2, 0x60, 0x03, 0xaa, 0xe0, 0x4b, 0x29, 0x8a, 0xc0, 0xaf, + 0xdc, 0x52, 0x87, 0xd7, 0xad, 0x12, 0x4c, 0xd9, 0x40, 0x5a, 0x62, 0xcd, 0x1c, 0xa0, + 0x8b, 0x28, 0x2e, 0xfe, 0xf7, 0xf9, 0x28, 0xdf, 0x76, 0xe2, 0x82, 0x1a, 0x41, 0x84, + 0xff, 0x33, 0xd7, 0xbd, 0x25, 0x90, 0xe9, 0x0c, 0x8c, 0x38, 0x8e, 0xa7, 0x95, 0x51, + 0x22, 0xdb, 0xac, 0xa6, 0x7b, 0x30, 0x39, 0x5a, 0x92, 0x8b, 0x57, 0xb8, 0x57, 0x51, + 0x23, 0x20, 0x5a, 0xe1, 0x91, 0x52, 0xe4, 0x1e, 0x00, 0x29, 0x31, 0xb4, 0x57, 0x46, + 0x19, 0x8e, 0x5d, 0xd9, 0x57, 0x1a, 0x56, 0xa7, 0xe0, 0xd4, 0x23, 0xff, 0x27, 0x98, + 0x9d, 0x3e, 0xb4, 0x17, 0xec, 0xd3, 0xc3, 0x09, 0x3f, 0xb8, 0x2c, 0x56, 0x58, 0xe2, + 0x96, 0x24, 0xc5, 0x32, 0x19, 0xa6, 0x0c, 0xd0, 0xa8, 0xc4, 0xda, 0x36, 0x7e, 0x29, + 0xa7, 0x17, 0x79, 0xa7, 0x30, 0x32, 0x98, 0x5a, 0x3d, 0x1f, 0xd0, 0x3d, 0xd4, 0xd0, + 0x6e, 0x05, 0x56, 0x6f, 0x3b, 0x84, 0x36, 0x7c, 0xf0, 0xfa, 0xee, 0x9b, 0xc3, 0xbd, + 0x7a, 0x3a, 0x60, 0x6a, 0x9f, 0xdb, 0x84, 0x9c, 0x5d, 0x82, 0xd0, 0xa6, 0x19, 0x23, + 0xc2, 0xe5, 0xd8, 0xaa, 0x63, 0xa8, 0xa5, 0x0c, 0x38, 0xbd, 0x03, 0x87, 0x72, 0xc4, + 0x14, 0x3d, 0x8b, 0x7a, 0xcf, 0xd7, 0x4e, 0x72, 0xc0, 0x4d, 0x89, 0x24, 0x8d, 0xff, + 0x20, 0xfe, 0x8d, 0xc5, 0xec, 0x21, 0x49, 0x05, 0x4e, 0xa2, 0x41, 0x64, 0xe8, 0x5f, + 0x67, 0x44, 0xad, 0x0c, 0xac, 0xf1, 0xa8, 0xb7, 0x01, 0x26, 0xf4, 0x82, 0xc0, 0x92, + 0xed, 0x9f, 0x61, 0x27, 0xd2, 0x05, 0x0d, 0x12, 0xe8, 0x78, 0xa7, 0x96, 0x53, 0xa1, + 0xe8, 0x4d, 0xae, 0xc3, 0xeb, 0xe6, 0x2d, 0x5f, 0x6c, 0x4a, 0xbe, 0x5c, 0xe9, 0x0a, + 0x7f, 0xe2, 0xe5, 0x2a, 0x8d, 0x78, 0x46, 0xe8, 0xed, 0xf2, 0xf2, 0xbc, 0xe0, 0x5a, + 0x03, 0x7c, 0x82, 0x6f, 0x22, 0xca, 0xad, 0x12, 0x61, 0x46, 0x7d, 0xcf, 0xb7, 0xd6, + 0xb6, 0x13, 0x3d, 0xc2, 0x1e, 0x80, 0x96, 0xc7, 0xe9, 0xf8, 0xe9, 0xe1, 0x0c, 0x1e, + 0x3f, 0xac, 0x40, 0x58, 0xb6, 0x82, 0xc6, 0x8e, 0x54, 0xfa, 0xca, 0xe0, 0xf9, 0xc2, + 0xdd, 0x4d, 0x64, 0xd9, 0x04, 0x61, 0x52, 0xb4, 0x76, 0x23, 0x32, 0x93, 0x9f, 0x17, + 0xe6, 0xaa, 0xf7, 0xd8, 0xb9, 0xd3, 0x58, 0xe2, 0x21, 0x8d, 0x4e, 0x0d, 0x69, 0xa4, + 0xf1, 0x19, 0xe1, 0xc6, 0x4e, 0xec, 0x4c, 0x8b, 0x53, 0x28, 0x09, 0x70, 0x71, 0x31, + 0xf0, 0x1f, 0x55, 0xc7, 0xad, 0x04, 0xcf, 0xb6, 0x3f, 0x7c, 0x4a, 0x3d, 0x0a, 0x2b, + 0x0f, 0xfb, 0x0b, 0x05, 0xa6, 0xbe, 0x05, 0x5b, 0x8c, 0x94, 0xca, 0x80, 0xbb, 0x0a, + 0x1d, 0x13, 0xcd, 0x4c, 0xd6, 0x9a, 0xb9, 0x83, 0x04, 0xae, 0x25, 0x15, 0xd5, 0xf7, + 0x69, 0x9d, 0x4a, 0xbe, 0xe5, 0xc2, 0x0b, 0xe6, 0x09, 0xd8, 0x73, 0x51, 0x10, 0x12, + 0xf2, 0x34, 0xbd, 0x85, 0xa7, 0xef, 0xf5, 0xfb, 0x63, 0x4c, 0xff, 0x26, 0x58, 0xba, + 0x65, 0x16, 0x04, 0x85, 0x63, 0x09, 0x5e, 0xce, 0xfb, 0x30, 0x15, 0xee, 0x3f, 0x03, + 0xca, 0x52, 0xa1, 0x77, 0xf2, 0x61, 0xec, 0xdc, 0x26, 0xbc, 0x08, 0x9d, 0x34, 0xc6, + 0x40, 0x48, 0x46, 0xe9, 0xc6, 0x47, 0xfc, 0xfe, 0x98, 0xcc, 0x6a, 0xcd, 0xbb, 0x46, + 0x4f, 0x64, 0x27, 0x8a, 0xd8, 0xce, 0x9d, 0x1a, 0xe0, 0xd4, 0x15, 0xbc, 0x0c, 0x05, + 0x24, 0x5f, 0xdd, 0xaf, 0x4e, 0xbc, 0x8d, 0xc7, 0x03, 0xa8, 0x5c, 0xb2, 0x70, 0xf7, + 0x96, 0xad, 0x2d, 0x93, 0x7e, 0x2a, 0xc0, 0xd5, 0xe0, 0xa3, 0x48, 0x21, 0x75, 0x80, + 0x00, 0xaa, 0x59, 0xc9, 0xd4, 0x65, 0x24, 0x85, 0x29, 0x4e, 0xe0, 0xab, 0x29, 0x69, + 0x6b, 0x21, 0x43, 0x0f, 0xa5, 0x4d, 0xcf, 0xbf, 0x2b, 0x9c, 0x49, 0xd1, 0x42, 0x06, + 0x42, 0x09, 0xee, 0xee, 0xd4, 0xd4, 0x71, 0xff, 0xc0, 0x17, 0xd4, 0xe2, 0x0a, 0x79, + 0x6b, 0x09, 0x27, 0x80, 0x4c, 0x06, 0x1b, 0x9f, + ], + c_enc: [ + 0x59, 0x9a, 0x4d, 0x9f, 0x53, 0x3c, 0x46, 0xa9, 0x6f, 0x92, 0xaf, 0x8c, 0x08, 0xae, + 0x59, 0x71, 0x10, 0x23, 0x0e, 0xb8, 0x41, 0xc2, 0xf7, 0xc9, 0xd4, 0xf1, 0x45, 0x87, + 0x76, 0x36, 0xc8, 0x9d, 0xd8, 0xf3, 0x84, 0xa9, 0x40, 0xdc, 0x89, 0x72, 0x55, 0x53, + 0x57, 0xbc, 0x07, 0x48, 0x2a, 0x0a, 0x32, 0x3d, 0x87, 0xae, 0x10, 0xeb, 0x99, 0x82, + 0x5a, 0xe4, 0xe0, 0x06, 0x0e, 0x25, 0x6c, 0x3c, 0x3b, 0xeb, 0xa3, 0x2f, 0xa2, 0xb2, + 0xd2, 0x7f, 0x04, 0x6f, 0x7a, 0x93, 0x6d, 0xf8, 0xa9, 0x61, 0xc8, 0x18, 0x4e, 0xe3, + 0xc6, 0x8e, 0xbc, 0xe9, 0x80, 0x64, 0x45, 0xb4, 0x3e, 0x66, 0x67, 0x19, 0x95, 0xa2, + 0x43, 0x7a, 0x7f, 0x70, 0x91, 0x47, 0x14, 0x8a, 0x76, 0x03, 0x6d, 0x25, 0x5e, 0xba, + 0xc4, 0xd0, 0xd8, 0x34, 0x82, 0x93, 0x23, 0x9a, 0x78, 0x64, 0xe7, 0x9b, 0xef, 0xf7, + 0x6f, 0x61, 0x50, 0xe0, 0xc4, 0xf4, 0x7a, 0x85, 0x26, 0xe3, 0xed, 0x06, 0x75, 0xfa, + 0xc6, 0xac, 0xcc, 0x30, 0xa4, 0xd6, 0x73, 0xca, 0x80, 0x85, 0x95, 0x96, 0xfe, 0xc9, + 0xcd, 0x6a, 0x93, 0xfb, 0xa0, 0xe8, 0x9e, 0xf5, 0x3f, 0x3e, 0x26, 0x74, 0xd3, 0x2a, + 0x4b, 0x43, 0xf9, 0xa4, 0x38, 0x7d, 0xce, 0x33, 0xac, 0xa1, 0xe4, 0xff, 0xdc, 0x6d, + 0x2d, 0x31, 0x89, 0xc6, 0x23, 0xca, 0x56, 0x4d, 0x03, 0xac, 0x5b, 0x35, 0xb1, 0xa7, + 0x47, 0xff, 0x44, 0x6b, 0xc2, 0x5e, 0xd2, 0x2d, 0x09, 0x68, 0x2c, 0xef, 0x3a, 0x30, + 0xff, 0xa5, 0xc4, 0x0e, 0x27, 0x70, 0xf1, 0x84, 0x98, 0xb1, 0x2f, 0x86, 0x8b, 0xa9, + 0x2a, 0x13, 0xaa, 0x4f, 0xa2, 0x14, 0xb0, 0x62, 0xe3, 0x64, 0x9c, 0xf9, 0xc8, 0x5e, + 0x7a, 0x8a, 0x55, 0xf5, 0xf3, 0xdd, 0x68, 0x84, 0x2a, 0xea, 0x7c, 0x92, 0x79, 0x2a, + 0x52, 0x60, 0x0f, 0x86, 0x6c, 0x34, 0xa1, 0x0c, 0x51, 0x14, 0x13, 0x62, 0x02, 0x24, + 0xfb, 0x85, 0xaf, 0xc6, 0x06, 0xdd, 0x4f, 0x7b, 0x2f, 0x76, 0xbe, 0x76, 0x0c, 0xa1, + 0x94, 0xb6, 0xd4, 0x88, 0x2e, 0x5a, 0x4a, 0x76, 0x3d, 0x75, 0x0d, 0xb7, 0xe1, 0x68, + 0xa4, 0x18, 0x11, 0x92, 0x35, 0xda, 0xf9, 0xcb, 0x1b, 0xdb, 0x07, 0xff, 0x46, 0x83, + 0x3a, 0x87, 0xa3, 0x92, 0x6b, 0x14, 0xa5, 0x26, 0x4f, 0x10, 0x4f, 0x7f, 0x89, 0xf7, + 0x6f, 0x10, 0x10, 0x8f, 0x2b, 0x6e, 0xa5, 0x05, 0xd4, 0xf0, 0xd2, 0x6d, 0x58, 0x31, + 0x1c, 0xc7, 0x21, 0x9c, 0x6b, 0xc4, 0x38, 0xd0, 0xe1, 0xb3, 0x17, 0x60, 0x18, 0x73, + 0x9e, 0x6f, 0x75, 0xd0, 0x73, 0x59, 0xf5, 0xe8, 0x95, 0x7e, 0x12, 0xc3, 0x03, 0xaa, + 0x52, 0x9b, 0x11, 0xa1, 0x81, 0x66, 0x25, 0xa1, 0x20, 0xf3, 0x6d, 0xcd, 0xdd, 0xff, + 0x9c, 0x65, 0xbc, 0xac, 0x8f, 0x10, 0x67, 0xc7, 0xfe, 0x88, 0xf6, 0x44, 0x85, 0x94, + 0xcf, 0x1d, 0xff, 0x8e, 0x29, 0x00, 0xae, 0x84, 0xd2, 0xa7, 0xc8, 0x1b, 0x90, 0x6d, + 0xd0, 0xbc, 0x86, 0x96, 0xe3, 0x70, 0x98, 0x07, 0x4b, 0x75, 0xd8, 0x38, 0xd8, 0xab, + 0xdc, 0x90, 0x46, 0x08, 0x2b, 0xe4, 0xa6, 0x09, 0x95, 0xc4, 0xf4, 0xed, 0x80, 0xe2, + 0xd7, 0x87, 0x38, 0x25, 0x77, 0x3b, 0xa6, 0x3e, 0xe4, 0xcb, 0x97, 0x36, 0x9a, 0x50, + 0x70, 0xb5, 0x72, 0x5c, 0x5f, 0xeb, 0x32, 0x62, 0x45, 0x87, 0x80, 0x1e, 0x5a, 0xc0, + 0x30, 0xe6, 0x45, 0xbd, 0xf2, 0xe5, 0x86, 0xcf, 0x98, 0x66, 0xea, 0xfb, 0x76, 0xf5, + 0x59, 0x76, 0xa3, 0x3d, 0x62, 0xae, 0xdc, 0x76, 0x27, 0x78, 0x3b, 0x48, 0x48, 0x93, + 0x61, 0xf9, 0x9c, 0xae, 0xb1, 0xb1, 0x9c, 0x55, 0x22, 0x58, 0x9f, 0xd2, 0x1d, 0x51, + 0x45, 0x49, 0xd7, 0x4a, 0xb1, 0x92, 0x25, 0xed, 0x6e, 0x4c, 0x20, 0x3a, 0xdd, 0xfa, + 0x55, 0xfc, 0x9e, 0xc9, 0x89, 0xb6, 0x69, 0x02, 0x3c, 0xf3, 0x05, 0xb4, 0x2b, 0x33, + 0x0f, 0xc2, 0x30, 0x80, 0xab, 0xe4, 0x25, 0x01, 0xe5, 0x9c, 0x85, 0x1c, 0x54, 0xc7, + 0x49, 0x66, 0xf6, 0x0b, 0xe9, 0xdc, 0x56, 0x1a, 0x2d, 0x91, 0xf5, 0xd3, 0x2a, 0xdd, + 0x19, 0xb8, 0x9a, 0xca, 0xbe, 0x92, 0x1b, 0x99, 0x25, 0x3a, 0xfe, 0xfb, 0x2f, 0xf6, + 0x42, 0xd8, 0x6e, 0x65, 0x59, 0x51, 0x95, 0x8e, 0xfb, 0x82, 0xab, 0xe5, 0x84, 0x5d, + 0xad, 0xf0, 0x13, 0x27, 0x03, 0x7e, 0xda, 0x01, 0xf9, 0x97, 0xd4, 0x19, 0x4f, 0x97, + 0xb7, 0xd7, 0xef, 0xa4, 0xf4, 0xd0, 0x18, 0x2d, 0xa4, 0xc4, + ], + ock: [ + 0x55, 0x0e, 0xbf, 0x98, 0x83, 0x6c, 0xce, 0x43, 0x52, 0x25, 0xa1, 0x4b, 0xa6, 0x52, + 0xa7, 0xd5, 0x58, 0xcf, 0x5f, 0x3f, 0x7a, 0xfb, 0x00, 0xb0, 0x24, 0x70, 0xe8, 0xe4, + 0xd2, 0x6d, 0xb7, 0x9c, + ], + op: [ + 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, + 0x30, 0x79, 0xc0, 0x8d, 0x9c, 0x6d, 0x50, 0xf9, 0x35, 0x86, 0x7d, 0x33, 0x01, 0xf6, + 0x89, 0xcf, 0xf9, 0x1e, 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, + 0x58, 0x93, 0x20, 0x26, 0xf9, 0xdd, 0x2c, 0x35, 0xb9, 0x05, 0x7f, 0xad, 0x50, 0xd8, + 0x44, 0x72, 0x83, 0xf9, 0x4e, 0xd5, 0x95, 0x3d, + ], + c_out: [ + 0x9a, 0x01, 0xb7, 0x5e, 0x27, 0xea, 0x97, 0x51, 0x45, 0x5d, 0x54, 0xf2, 0xa5, 0x2b, + 0x88, 0x4b, 0x45, 0x6a, 0x6f, 0xc3, 0xda, 0xdb, 0xec, 0x79, 0xbf, 0x4d, 0x10, 0xbe, + 0x06, 0x7b, 0xef, 0x3e, 0xa2, 0xa5, 0xc0, 0x59, 0x81, 0xd4, 0x06, 0x05, 0x6a, 0x2f, + 0xf6, 0x4c, 0xb4, 0xc6, 0xfd, 0x46, 0x7d, 0xa8, 0x0b, 0xa1, 0x17, 0x48, 0xe9, 0xe2, + 0xae, 0x07, 0xb7, 0x62, 0xdf, 0x9d, 0x4a, 0x23, 0x58, 0x77, 0xf5, 0x8f, 0x43, 0x24, + 0xd8, 0x00, 0x3c, 0x32, 0x4f, 0xd9, 0xc6, 0x39, 0xbc, 0xa6, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x53, 0x3d, 0xc3, 0xd4, 0x93, 0xf2, 0xb8, 0x7a, 0x03, 0x3d, 0xf5, 0x07, 0x05, 0xf2, + 0x90, 0x54, 0x16, 0x38, 0xe9, 0x08, 0x7d, 0xcd, 0xbc, 0xfe, 0x52, 0x7e, 0x77, 0x5a, + 0xaf, 0x09, 0x30, 0x29, 0xac, 0xec, 0x74, 0xdd, 0xe6, 0x02, 0xfc, 0x7c, 0x73, 0xcb, + 0x38, 0x50, 0xbd, 0xfb, 0xf2, 0x61, 0x79, 0x4c, 0x9c, 0x29, 0x9d, 0x0b, 0x98, 0xee, + 0x0f, 0x20, 0x71, 0xd6, 0xd4, 0xe3, 0x7b, 0x05, + ], + ovk: [ + 0x32, 0x4d, 0xce, 0x2a, 0x1e, 0xa1, 0xe4, 0x30, 0x4f, 0x49, 0xe4, 0x3a, 0xe0, 0x65, + 0xe3, 0xfb, 0x19, 0x6f, 0x76, 0xd9, 0xb8, 0x79, 0xc7, 0x20, 0x08, 0x62, 0xea, 0xd1, + 0x8d, 0xea, 0x5f, 0xb6, + ], + default_d: [ + 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, + ], + default_pk_d: [ + 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, + 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, + 0xab, 0x00, 0xa0, 0x28, + ], + v: 12711846894898776584, + rseed: [ + 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, + 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, + 0xad, 0xe8, 0x24, 0xf3, + ], + asset: [ + 0xf9, 0x78, 0x1e, 0xbe, 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, + 0xf1, 0xb1, 0xaa, 0x9b, 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, + 0xe3, 0x81, 0x93, 0xbc, + ], + memo: [ + 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, + 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, + 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, + 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, + 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, + 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, + 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, + 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, + 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, + 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, + 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, + 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, + 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, + 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, + 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, + 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, + 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, + 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, + 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, + 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, + 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, + 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, + 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, + 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, + 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, + 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, + 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, + 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, + 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, + 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, + 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, + 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, + 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, + 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, + 0x66, 0x17, 0x00, 0x8c, 0x78, 0xf4, 0xfb, 0x11, 0x12, 0xf4, 0x02, 0x8a, 0x70, 0x4f, + 0xc5, 0xa9, 0x38, 0x2c, 0x6b, 0x03, 0xe7, 0xd8, 0x08, 0x5e, 0x90, 0x6c, 0xf8, 0x4c, + 0xa2, 0xc1, 0x20, 0x7c, 0x87, 0xa2, 0xbc, 0xe2, + ], + cv_net: [ + 0x5d, 0xd1, 0x3d, 0xcf, 0x9a, 0xf3, 0x52, 0xf5, 0xfe, 0x0b, 0x2b, 0xcb, 0xd0, 0xdb, + 0xd7, 0xda, 0xfb, 0xbe, 0x53, 0xb0, 0xa9, 0x6b, 0x08, 0x1c, 0x90, 0xba, 0xde, 0xd9, + 0xbe, 0x4b, 0x4f, 0x87, + ], + rho: [ + 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, + 0x4f, 0xfb, 0xc2, 0x36, 0x9c, 0xb1, 0x48, 0xeb, 0x76, 0xf1, 0xed, 0xf1, 0xb5, 0xc7, + 0x41, 0x84, 0x28, 0x2a, + ], + cmx: [ + 0xd7, 0x60, 0xac, 0xdb, 0xca, 0xda, 0xd1, 0x88, 0x08, 0x4f, 0xe4, 0x1a, 0x5c, 0x03, + 0xc2, 0xc8, 0xce, 0x34, 0xe1, 0x5f, 0x9d, 0xf4, 0x7b, 0x86, 0x9c, 0x44, 0xc7, 0x21, + 0x13, 0xa4, 0x0c, 0x3d, + ], + esk: [ + 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, 0xdf, 0x7c, 0xe2, 0xd2, + 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, 0x86, 0x48, 0x56, 0x2c, + 0xbd, 0x86, 0x3f, 0x09, + ], + ephemeral_key: [ + 0x5a, 0x48, 0x58, 0x15, 0xc4, 0xa7, 0x47, 0x06, 0xe9, 0xde, 0x87, 0xfa, 0x60, 0xa2, + 0x81, 0x6f, 0x89, 0x0b, 0xe3, 0xdb, 0x54, 0xeb, 0x3f, 0x4b, 0xaf, 0x37, 0xdb, 0xc9, + 0xbd, 0xe5, 0xfe, 0x9d, + ], + shared_secret: [ + 0x96, 0x8d, 0xf2, 0xe8, 0x5d, 0x7b, 0xd1, 0x08, 0xf5, 0x72, 0x12, 0x53, 0x93, 0x76, + 0xaf, 0x25, 0x83, 0x2e, 0xf4, 0xdb, 0xd6, 0x40, 0x2a, 0x41, 0x4d, 0x73, 0xc5, 0x6b, + 0xee, 0xe4, 0xf2, 0xa8, + ], + k_enc: [ + 0xf7, 0x73, 0x91, 0x24, 0x3f, 0xdb, 0x35, 0xb2, 0x26, 0x94, 0xdb, 0x91, 0xde, 0xbd, + 0x78, 0x55, 0x79, 0x3c, 0xa7, 0x1e, 0x82, 0xbd, 0xc2, 0xee, 0x74, 0xc9, 0xb7, 0xb6, + 0x97, 0xc0, 0x24, 0x71, + ], + p_enc: [ + 0x03, 0x20, 0x8c, 0x6d, 0x90, 0x6c, 0xfa, 0x93, 0xf1, 0x2d, 0x6a, 0x7e, 0x08, 0x0a, + 0x98, 0x91, 0x66, 0x8d, 0x69, 0xb0, 0x7b, 0xdc, 0x8b, 0xa3, 0xe4, 0xe3, 0xd1, 0xd9, + 0x33, 0xbf, 0xb5, 0x80, 0xf5, 0xb3, 0xe8, 0x7a, 0x2a, 0x06, 0x51, 0x70, 0x51, 0x41, + 0x0f, 0xe1, 0xb4, 0xff, 0x1e, 0xa0, 0xad, 0xe8, 0x24, 0xf3, 0xf9, 0x78, 0x1e, 0xbe, + 0x31, 0x7a, 0x07, 0x10, 0xae, 0x54, 0x61, 0xe3, 0x4f, 0xe6, 0xf1, 0xb1, 0xaa, 0x9b, + 0x4e, 0x67, 0xb1, 0x49, 0x10, 0x98, 0x48, 0x02, 0xc2, 0xa7, 0xe3, 0x81, 0x93, 0xbc, + 0xff, 0x38, 0x51, 0x54, 0x56, 0xa5, 0x7c, 0x7a, 0x91, 0x6a, 0x74, 0x38, 0x8e, 0xe8, + 0xf1, 0x28, 0x1f, 0x9a, 0xde, 0x0a, 0xe2, 0xa2, 0x61, 0x3a, 0x06, 0x12, 0xc4, 0x69, + 0xdf, 0x79, 0x2b, 0x8d, 0xf4, 0xca, 0xe4, 0xfc, 0x25, 0xc1, 0xca, 0xdb, 0xa9, 0x5a, + 0x80, 0x7c, 0xe6, 0x1e, 0x5a, 0x53, 0x03, 0xfa, 0xaf, 0x9e, 0x14, 0x65, 0x39, 0x96, + 0xb5, 0xa8, 0xad, 0xc3, 0x4f, 0xd4, 0x75, 0xef, 0x14, 0x99, 0x09, 0x4b, 0xab, 0xaf, + 0x1f, 0x3f, 0x07, 0xda, 0x9a, 0x39, 0x0b, 0x1d, 0x9f, 0xc9, 0xa0, 0x83, 0x27, 0x98, + 0x7a, 0xdf, 0xe9, 0x56, 0x48, 0x63, 0xfb, 0xdf, 0xa8, 0xf6, 0xb4, 0x6a, 0x88, 0x41, + 0x58, 0x30, 0x99, 0xaf, 0xb7, 0x87, 0x01, 0x18, 0xfa, 0xce, 0x76, 0x34, 0x7e, 0x40, + 0xb6, 0xfd, 0x8c, 0xd1, 0x55, 0x82, 0xae, 0x8e, 0x23, 0xbe, 0x9a, 0x02, 0x19, 0xbc, + 0x3e, 0x4e, 0x45, 0x46, 0xa3, 0x0d, 0x3b, 0xbb, 0xbd, 0x16, 0x86, 0x08, 0x68, 0x76, + 0xbe, 0x0e, 0x4c, 0x85, 0x9b, 0xe7, 0x1f, 0xb5, 0x8f, 0x4f, 0xab, 0x3d, 0x28, 0xc0, + 0xb4, 0xf7, 0xe7, 0x5a, 0xd1, 0xed, 0xb7, 0xf8, 0x89, 0x46, 0xfb, 0x40, 0xcf, 0xa5, + 0x78, 0x6a, 0x0f, 0xcb, 0xa1, 0x30, 0x3c, 0x83, 0x47, 0xec, 0xee, 0x93, 0xd4, 0x6d, + 0x14, 0x0b, 0xb5, 0xf6, 0x95, 0x31, 0xd6, 0x66, 0x54, 0x8b, 0x10, 0x9c, 0xe7, 0x64, + 0xbe, 0xad, 0x7c, 0x87, 0xbd, 0x4c, 0x87, 0x64, 0x94, 0xde, 0x82, 0xdb, 0x6e, 0x50, + 0x73, 0xa6, 0xc9, 0x4f, 0x7c, 0x09, 0x9a, 0x40, 0xd7, 0xa3, 0x1c, 0x4a, 0x04, 0xb6, + 0x9c, 0x9f, 0xcc, 0xf3, 0xc7, 0xdd, 0x56, 0xf5, 0x54, 0x47, 0x76, 0xc5, 0x3b, 0x4d, + 0xf7, 0x95, 0x39, 0x81, 0xd5, 0x5a, 0x96, 0xa6, 0xdc, 0xff, 0x99, 0x04, 0xa9, 0x08, + 0x42, 0xe5, 0xba, 0xfe, 0xc8, 0x84, 0x0c, 0x2d, 0x25, 0x5b, 0xf5, 0xad, 0x61, 0xc4, + 0x60, 0xf9, 0x8f, 0xeb, 0x82, 0xa1, 0x0f, 0xa1, 0xc0, 0x99, 0xf6, 0x27, 0x76, 0x79, + 0x82, 0x36, 0xc5, 0xca, 0x7f, 0x1e, 0x46, 0xeb, 0xdb, 0x2b, 0x14, 0x4d, 0x87, 0x13, + 0xe5, 0x6c, 0x77, 0x2f, 0x2c, 0x3b, 0x86, 0x0e, 0xa5, 0xb0, 0x3a, 0x88, 0x54, 0xbc, + 0x6e, 0x65, 0x90, 0xd6, 0x3c, 0xc0, 0xea, 0x54, 0xf1, 0x0b, 0x73, 0xba, 0x24, 0x1b, + 0xf7, 0x4b, 0x63, 0x55, 0x51, 0xa2, 0xaa, 0xca, 0x96, 0x87, 0xac, 0x52, 0x69, 0xfd, + 0x36, 0x8b, 0x26, 0xd7, 0x0a, 0x73, 0x7f, 0x26, 0x76, 0x85, 0x99, 0x8a, 0x3f, 0x7d, + 0x26, 0x37, 0x91, 0x49, 0x09, 0xc7, 0x46, 0x49, 0x5d, 0x24, 0xc4, 0x98, 0x63, 0x5e, + 0xf9, 0x7a, 0xc6, 0x6a, 0x40, 0x08, 0x94, 0xc0, 0x9f, 0x73, 0x48, 0x8e, 0xb7, 0xcf, + 0x33, 0xf6, 0xda, 0xd1, 0x66, 0x6a, 0x05, 0xf9, 0x1a, 0xd7, 0x75, 0x79, 0x65, 0xc2, + 0x99, 0x36, 0xe7, 0xfa, 0x48, 0xd7, 0x7e, 0x89, 0xee, 0x09, 0x62, 0xf5, 0x8c, 0x05, + 0x1d, 0x11, 0xd0, 0x55, 0xfc, 0xe2, 0x04, 0xa5, 0x62, 0xde, 0x68, 0x08, 0x8a, 0x1b, + 0x26, 0x48, 0xb8, 0x17, 0x4c, 0xbc, 0xfc, 0x8b, 0x5b, 0x5c, 0xd0, 0x77, 0x11, 0x5a, + 0xfd, 0xe1, 0x84, 0x05, 0x05, 0x4e, 0x5d, 0xa9, 0xa0, 0x43, 0x10, 0x34, 0x2c, 0x5d, + 0x3b, 0x52, 0x6e, 0x0b, 0x02, 0xc5, 0xca, 0x17, 0x22, 0xba, 0xde, 0xee, 0x23, 0xd1, + 0x45, 0xe8, 0xeb, 0x22, 0x13, 0xfc, 0x4a, 0xf1, 0xe4, 0x50, 0xe4, 0xd5, 0x21, 0x7c, + 0x66, 0x17, 0x00, 0x8c, 0x78, 0xf4, 0xfb, 0x11, 0x12, 0xf4, 0x02, 0x8a, 0x70, 0x4f, + 0xc5, 0xa9, 0x38, 0x2c, 0x6b, 0x03, 0xe7, 0xd8, 0x08, 0x5e, 0x90, 0x6c, 0xf8, 0x4c, + 0xa2, 0xc1, 0x20, 0x7c, 0x87, 0xa2, 0xbc, 0xe2, + ], + c_enc: [ + 0xf9, 0x09, 0x97, 0x73, 0x8b, 0x14, 0xd8, 0xa8, 0x4e, 0x32, 0x74, 0xbb, 0x70, 0x76, + 0x31, 0x15, 0xb7, 0x2e, 0x0a, 0x3d, 0xde, 0x8e, 0xa4, 0x70, 0x91, 0x1f, 0xb4, 0x58, + 0x70, 0xb0, 0x14, 0x8e, 0x7d, 0x37, 0x2b, 0xf2, 0x26, 0x8b, 0x3e, 0xe8, 0xda, 0xe5, + 0xfd, 0xe5, 0xea, 0x9b, 0x61, 0x59, 0x8e, 0xf1, 0x1b, 0x73, 0x14, 0x4f, 0x75, 0x53, + 0xb2, 0x13, 0xa0, 0x4c, 0x85, 0xf2, 0x5c, 0x54, 0x6c, 0x8a, 0x38, 0xa6, 0x0e, 0x50, + 0x86, 0x08, 0xb9, 0xca, 0x59, 0x3b, 0x94, 0xd8, 0x68, 0x8d, 0x6e, 0xff, 0xa5, 0x36, + 0x04, 0xd4, 0xdb, 0xc0, 0xf3, 0x45, 0x03, 0xaa, 0xe4, 0x6f, 0x3c, 0x8a, 0x8d, 0x2e, + 0x46, 0xa8, 0x1f, 0x09, 0x12, 0x6c, 0x45, 0x36, 0xfd, 0x02, 0x58, 0xf5, 0x97, 0x40, + 0xad, 0x0d, 0xb8, 0x02, 0xcc, 0x02, 0x42, 0x53, 0x4d, 0xdf, 0x52, 0xa6, 0xbf, 0x6a, + 0x03, 0x4d, 0xe6, 0x26, 0xf0, 0x18, 0x84, 0x4a, 0xdc, 0xb2, 0x6d, 0xcd, 0xc2, 0x85, + 0x16, 0x37, 0x16, 0xdd, 0x54, 0x65, 0x1c, 0x88, 0x73, 0x53, 0xf1, 0xff, 0xef, 0xa0, + 0x37, 0x71, 0x2a, 0xc0, 0xdf, 0x3a, 0x92, 0x98, 0x19, 0x06, 0x87, 0x54, 0x9d, 0x79, + 0xc6, 0xa3, 0x60, 0x0c, 0xc1, 0xc7, 0x29, 0xa3, 0x93, 0xd4, 0x4f, 0xec, 0xe5, 0x7f, + 0xd4, 0xcb, 0x0c, 0x0f, 0xb0, 0xc7, 0x86, 0x1b, 0x92, 0x5b, 0x94, 0xcd, 0x6a, 0x26, + 0x90, 0xf0, 0x02, 0xc4, 0x3a, 0x16, 0x6e, 0x56, 0x77, 0x72, 0x9f, 0x35, 0x52, 0xae, + 0xe0, 0xf2, 0xc1, 0x95, 0xaa, 0x91, 0xb2, 0xdd, 0xe3, 0x65, 0xdd, 0x14, 0xf2, 0xf0, + 0x7b, 0x3c, 0x38, 0x34, 0x7f, 0x6c, 0x0d, 0xab, 0x82, 0x84, 0x1e, 0xba, 0xde, 0x1e, + 0xf8, 0x13, 0xf2, 0xcd, 0x88, 0x5b, 0x57, 0x84, 0x37, 0x44, 0x45, 0x24, 0x93, 0x6a, + 0x65, 0x46, 0xc4, 0x55, 0xd6, 0xc9, 0x2e, 0x6d, 0x3d, 0xc5, 0x38, 0xb6, 0xcd, 0x9f, + 0x6d, 0x4c, 0xc0, 0xd7, 0x4d, 0x7b, 0xc2, 0x46, 0x7e, 0x21, 0x5b, 0xe8, 0xc3, 0xd4, + 0xff, 0x91, 0x8a, 0x2d, 0x98, 0x71, 0x00, 0xff, 0x34, 0x02, 0x4c, 0x88, 0x62, 0x79, + 0xd6, 0x4c, 0xaf, 0xdf, 0xd9, 0x0f, 0x1c, 0x04, 0xc4, 0x6b, 0xc9, 0xd5, 0xe9, 0xe2, + 0xaf, 0xd0, 0x3a, 0xb7, 0x55, 0xe4, 0x0f, 0x08, 0x7e, 0xb5, 0x1e, 0xe3, 0xd1, 0x02, + 0xb6, 0xb0, 0x69, 0xb6, 0x50, 0xf5, 0xd8, 0x55, 0x03, 0x35, 0x47, 0x1b, 0x24, 0x46, + 0x5d, 0x93, 0x4d, 0x63, 0x34, 0x39, 0xb1, 0x08, 0xd9, 0x04, 0x2b, 0x37, 0xf9, 0xf7, + 0x2e, 0x74, 0xfd, 0x6b, 0xa0, 0x01, 0x58, 0x5b, 0x08, 0x62, 0xdb, 0x99, 0x4a, 0x5e, + 0xc1, 0x2d, 0xc9, 0x1e, 0x01, 0x48, 0x6a, 0x8d, 0xc6, 0x8a, 0xb9, 0xa3, 0x41, 0x93, + 0x52, 0x61, 0x73, 0xec, 0xc0, 0xd1, 0x55, 0xb5, 0xcd, 0xd6, 0xbc, 0x07, 0xe6, 0x3e, + 0x41, 0xaf, 0x9e, 0x52, 0x4c, 0xd3, 0xe6, 0x55, 0x5d, 0x38, 0xb4, 0x6d, 0xb2, 0xd9, + 0x9e, 0x5b, 0xa4, 0xa4, 0x95, 0xff, 0x30, 0xfe, 0xf2, 0x54, 0xc9, 0xfe, 0x7b, 0x79, + 0x0c, 0xe5, 0x6a, 0x40, 0xf4, 0x00, 0x27, 0xbb, 0x62, 0x05, 0x86, 0x38, 0xc4, 0x94, + 0x17, 0x7b, 0x7f, 0x5c, 0x8f, 0x29, 0x44, 0x9e, 0x9e, 0xc3, 0xbd, 0xb3, 0xab, 0x04, + 0x16, 0x0d, 0x96, 0xd0, 0xd4, 0x04, 0x79, 0x5d, 0x54, 0x28, 0x40, 0x82, 0xb6, 0x35, + 0x7d, 0x58, 0x1d, 0xc2, 0x64, 0x81, 0x13, 0x67, 0xbb, 0xb1, 0x31, 0x9a, 0x31, 0xf7, + 0x66, 0x4a, 0x4e, 0xca, 0x93, 0x2a, 0xbb, 0xd7, 0x33, 0xa7, 0x1a, 0x31, 0xaf, 0x23, + 0x11, 0xc4, 0x9a, 0xc9, 0xaf, 0x22, 0xf8, 0x16, 0x7b, 0x25, 0x51, 0xac, 0xf5, 0x73, + 0xd9, 0x1b, 0x40, 0x98, 0xc4, 0xde, 0xa8, 0xa9, 0x79, 0x9d, 0x9d, 0x54, 0x52, 0x0c, + 0xc6, 0x3e, 0x55, 0x71, 0x8a, 0x24, 0x85, 0xbf, 0x6f, 0x63, 0x16, 0x30, 0x7c, 0xea, + 0x21, 0x5e, 0x22, 0x22, 0x8d, 0x45, 0x34, 0x9a, 0x03, 0x50, 0x31, 0xa4, 0xcb, 0x67, + 0x7b, 0x52, 0x3a, 0x3a, 0x51, 0x25, 0x2c, 0x6c, 0x61, 0xd0, 0xe2, 0x43, 0x2b, 0x94, + 0xac, 0x9c, 0x0d, 0xb5, 0x0d, 0xbc, 0xb9, 0xa2, 0xaf, 0x76, 0xb9, 0xf9, 0x11, 0x0a, + 0xd6, 0xcc, 0x2e, 0x7d, 0xe6, 0x49, 0x3a, 0x8e, 0x3c, 0xd1, 0xab, 0xf0, 0x6f, 0x4a, + 0x2d, 0x47, 0x5e, 0xc7, 0x60, 0xeb, 0x7c, 0x36, 0xbb, 0xb1, 0x27, 0x50, 0x61, 0x10, + 0x2d, 0xb3, 0x35, 0x6e, 0x11, 0x4d, 0xbc, 0xa3, 0xc5, 0xd8, + ], + ock: [ + 0x53, 0x29, 0x6e, 0xed, 0x43, 0xb4, 0xeb, 0x30, 0xa4, 0x3d, 0x88, 0x90, 0x2f, 0x74, + 0x04, 0x26, 0x62, 0x1d, 0x85, 0x21, 0x3a, 0x36, 0xc5, 0x20, 0xa1, 0x84, 0xa4, 0x3a, + 0xfb, 0xd4, 0x89, 0x6d, + ], + op: [ + 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, + 0xe1, 0xd4, 0x39, 0x55, 0xae, 0x66, 0xd8, 0x93, 0x92, 0xbf, 0x48, 0xaf, 0xb6, 0xc4, + 0xab, 0x00, 0xa0, 0x28, 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, + 0xdf, 0x7c, 0xe2, 0xd2, 0x33, 0x58, 0x4e, 0x66, 0x17, 0xd6, 0xf6, 0xa2, 0x1c, 0xdc, + 0x86, 0x48, 0x56, 0x2c, 0xbd, 0x86, 0x3f, 0x09, + ], + c_out: [ + 0x38, 0xee, 0x14, 0xef, 0xb0, 0x63, 0x94, 0x64, 0x44, 0x6f, 0x5f, 0xb8, 0x79, 0x5d, + 0x23, 0xf8, 0x8c, 0xf5, 0x65, 0x37, 0xe6, 0x4e, 0x1a, 0x46, 0x63, 0x17, 0xb3, 0x6f, + 0x22, 0x2e, 0x00, 0x5b, 0x92, 0x4c, 0xc9, 0x10, 0xd6, 0x29, 0x06, 0x6e, 0x05, 0x07, + 0xcb, 0x91, 0x2b, 0x0b, 0xc1, 0xd3, 0x16, 0xc2, 0x00, 0xb1, 0xa9, 0x56, 0x49, 0xc0, + 0xc5, 0x30, 0xb4, 0xf3, 0xd0, 0x43, 0x06, 0x8e, 0xf6, 0xf4, 0x2d, 0xcb, 0xef, 0xd0, + 0x2a, 0x34, 0x80, 0xe3, 0x2a, 0xa4, 0x5e, 0x33, 0xce, 0x25, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x77, 0x5c, 0x7f, 0x5c, 0xab, 0x43, 0x86, 0x88, 0x64, 0x3d, 0xdd, 0x15, 0x8d, 0xda, + 0xed, 0xf9, 0xa0, 0xea, 0xef, 0x61, 0x4b, 0x54, 0x90, 0x60, 0xf1, 0xe4, 0xd7, 0xcc, + 0x3e, 0x7e, 0x8b, 0x64, 0x49, 0x9a, 0x81, 0x8a, 0x6d, 0x0e, 0x33, 0x57, 0x68, 0x6e, + 0x65, 0xbc, 0x27, 0x4e, 0x3f, 0x7d, 0x45, 0x5b, 0x91, 0x1f, 0x13, 0x9f, 0x19, 0xf0, + 0x81, 0x61, 0x57, 0x51, 0x91, 0x3e, 0xb4, 0x12, + ], + ovk: [ + 0x45, 0xe1, 0x59, 0x6c, 0xbf, 0x46, 0x70, 0xb7, 0xe0, 0x5d, 0xfd, 0xaf, 0xbb, 0x0c, + 0xf3, 0xdd, 0xee, 0x28, 0xd7, 0x6a, 0x82, 0x42, 0x8e, 0x8a, 0xba, 0x43, 0x64, 0xe8, + 0x4b, 0xac, 0x37, 0x92, + ], + default_d: [ + 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, + ], + default_pk_d: [ + 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, + 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, + 0x96, 0xdc, 0xe6, 0xb7, + ], + v: 10238534295395242511, + rseed: [ + 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, + 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, + 0xa5, 0xfa, 0x38, 0x5d, + ], + asset: [ + 0x76, 0xba, 0x24, 0x3f, 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, + 0xc4, 0xbd, 0x4f, 0xc9, 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, + 0xf6, 0x99, 0x03, 0x18, + ], + memo: [ + 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, + 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, + 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, + 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, + 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, + 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, + 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, + 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, + 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, + 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, + 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, + 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, + 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, + 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, + 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, + 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, + 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, + 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, + 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, + 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, + 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, + 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, + 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, + 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, + 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, + 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, + 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, + 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, + 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, + 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, + 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, + 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, + 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, + 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, + 0xee, 0xfc, 0x52, 0x7b, 0xe3, 0xa8, 0x54, 0x3e, 0xb9, 0x0a, 0x5e, 0xc0, 0x2f, 0x35, + 0xa7, 0xc6, 0x4b, 0x7d, 0xd5, 0x9a, 0x72, 0xda, 0x00, 0x74, 0x63, 0x4e, 0x01, 0xd2, + 0xab, 0xf3, 0x63, 0x7a, 0xdd, 0x77, 0xc7, 0x35, + ], + cv_net: [ + 0x43, 0x94, 0x47, 0xab, 0x14, 0x5a, 0x6f, 0x0e, 0x5a, 0x3b, 0x43, 0x63, 0x04, 0x4c, + 0x73, 0x07, 0x93, 0xf4, 0x36, 0x33, 0x1f, 0xfe, 0x66, 0x30, 0xc7, 0xca, 0x2d, 0x9b, + 0x23, 0x2a, 0xe1, 0x98, + ], + rho: [ + 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, + 0x53, 0xb9, 0x3b, 0xcb, 0xb4, 0x37, 0x57, 0x1c, 0x62, 0xf3, 0x75, 0x60, 0x7e, 0x90, + 0x4e, 0xb3, 0xa2, 0x08, + ], + cmx: [ + 0x8f, 0x56, 0xd1, 0x3f, 0xd9, 0xc8, 0x3e, 0xb7, 0x1b, 0x95, 0x87, 0x7a, 0x4f, 0x29, + 0x39, 0x64, 0xbf, 0x3f, 0x73, 0x1d, 0x8d, 0xf2, 0x04, 0x32, 0x2c, 0xed, 0xcb, 0x38, + 0x68, 0x21, 0x90, 0x3c, + ], + esk: [ + 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, 0x44, 0xb0, 0xb0, 0x4f, + 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, 0xa9, 0xec, 0x88, 0x17, + 0x18, 0x65, 0x40, 0x33, + ], + ephemeral_key: [ + 0x51, 0x66, 0x26, 0x31, 0x6e, 0xea, 0x63, 0xa6, 0x45, 0xae, 0x56, 0x23, 0x81, 0x5a, + 0x31, 0x74, 0xb3, 0xed, 0x36, 0x64, 0xc3, 0x3e, 0x6a, 0x51, 0x81, 0xa9, 0xf5, 0xb5, + 0x42, 0x76, 0x7a, 0x2d, + ], + shared_secret: [ + 0xf6, 0x04, 0x23, 0x98, 0x7f, 0x0e, 0x67, 0x6d, 0x1a, 0x3b, 0xb6, 0xef, 0xe0, 0x39, + 0x42, 0x1d, 0xbb, 0xc8, 0x24, 0xb6, 0x90, 0xc1, 0x94, 0xa4, 0x90, 0xe4, 0x17, 0x1d, + 0xde, 0x21, 0x58, 0x19, + ], + k_enc: [ + 0x20, 0x98, 0x25, 0x7e, 0x2b, 0x9b, 0x7f, 0xc0, 0x62, 0x82, 0x38, 0x03, 0x38, 0x59, + 0x7d, 0xcb, 0x62, 0x7d, 0xdf, 0x47, 0x3e, 0x83, 0xa7, 0x2e, 0x61, 0xb0, 0xf2, 0x2c, + 0xcf, 0xaf, 0xbe, 0x4e, + ], + p_enc: [ + 0x03, 0x2d, 0x0e, 0x22, 0xbe, 0xb8, 0x62, 0xfe, 0x52, 0xc1, 0x4c, 0xf5, 0x0f, 0x12, + 0xb0, 0x11, 0xb2, 0x94, 0x16, 0x8e, 0xad, 0x8c, 0x7d, 0x94, 0x37, 0xe2, 0x0e, 0x2a, + 0x1f, 0x20, 0xe8, 0x18, 0xf9, 0x05, 0x7c, 0x5a, 0xba, 0xaa, 0x2e, 0x5c, 0x15, 0xb9, + 0x49, 0x45, 0xcd, 0x42, 0x4c, 0x28, 0xa5, 0xfa, 0x38, 0x5d, 0x76, 0xba, 0x24, 0x3f, + 0x28, 0x42, 0xb7, 0xb5, 0xfc, 0x74, 0x6a, 0xe5, 0x1b, 0x0b, 0xc4, 0xbd, 0x4f, 0xc9, + 0xfd, 0x83, 0x35, 0x65, 0xea, 0x85, 0x2b, 0x92, 0xb2, 0x24, 0xf6, 0x99, 0x03, 0x18, + 0xff, 0xad, 0xfe, 0x49, 0x07, 0xb2, 0x74, 0xd8, 0x42, 0x70, 0x7d, 0xb3, 0x69, 0x7a, + 0x5a, 0xe6, 0xc8, 0xf5, 0x42, 0xe5, 0xec, 0xc0, 0x7f, 0xe4, 0x73, 0x50, 0xd1, 0x01, + 0x46, 0x70, 0x21, 0x2e, 0xfe, 0x81, 0xfb, 0x7c, 0x73, 0xe8, 0x45, 0x0d, 0xf8, 0x14, + 0xef, 0x62, 0x32, 0xf7, 0x49, 0x0f, 0x63, 0xcc, 0xf0, 0x74, 0x80, 0xf8, 0x84, 0xa6, + 0x6e, 0xaf, 0xfc, 0x28, 0xfe, 0xa4, 0x48, 0xd7, 0xb4, 0x01, 0xcd, 0xae, 0x10, 0xe7, + 0xc0, 0xc7, 0xf9, 0xa7, 0xb1, 0x53, 0x31, 0x96, 0x9f, 0xc8, 0xcb, 0x36, 0x39, 0x67, + 0x73, 0xde, 0x19, 0x19, 0x31, 0xc7, 0x50, 0xf6, 0xce, 0x5c, 0xaa, 0xf2, 0x97, 0x68, + 0xeb, 0xb2, 0x7d, 0xac, 0xc7, 0x38, 0x05, 0x6a, 0x81, 0x25, 0xb4, 0x77, 0x2b, 0xf8, + 0x7a, 0xe1, 0x0a, 0x8a, 0x30, 0x9b, 0x9b, 0xd6, 0x55, 0x04, 0x3c, 0xfc, 0x31, 0x59, + 0x49, 0x43, 0x68, 0xc5, 0xab, 0x8c, 0xad, 0xb7, 0xf6, 0x71, 0xe9, 0x62, 0x6b, 0xd2, + 0x63, 0xe3, 0x11, 0x81, 0xa6, 0x04, 0xb5, 0x06, 0xa0, 0x3b, 0x43, 0x9a, 0x7f, 0xfe, + 0x43, 0x55, 0x89, 0x24, 0x77, 0xe2, 0xbd, 0xf3, 0x38, 0xc6, 0x2c, 0x39, 0x22, 0xf7, + 0xd3, 0xc9, 0xa5, 0x6c, 0x71, 0x03, 0xd9, 0x11, 0x94, 0x8a, 0x84, 0xb5, 0xae, 0x2d, + 0xbb, 0x16, 0xa3, 0x76, 0x1a, 0xdd, 0x05, 0x3a, 0x0f, 0x96, 0x7e, 0x6b, 0x5b, 0xc9, + 0x42, 0x11, 0xb6, 0x54, 0x71, 0x53, 0x26, 0x7c, 0x6e, 0xe1, 0xca, 0xd0, 0xd9, 0x74, + 0xa7, 0x10, 0x88, 0x58, 0x37, 0x35, 0xe4, 0xf6, 0x3d, 0x33, 0x15, 0x6d, 0xad, 0xd5, + 0x4c, 0x2f, 0xaf, 0x89, 0x11, 0x4a, 0x12, 0x7b, 0x97, 0xb9, 0x4c, 0xc2, 0xa2, 0x2e, + 0xf3, 0x03, 0xf4, 0x59, 0xd0, 0x4f, 0xc0, 0xb5, 0x3a, 0xce, 0x59, 0x18, 0xd4, 0x7f, + 0xf3, 0x3a, 0x55, 0x8b, 0xd7, 0x1a, 0x75, 0xf3, 0x55, 0xfb, 0xd0, 0x6b, 0xbc, 0xcf, + 0x4e, 0x02, 0xc3, 0xc0, 0xa4, 0xb6, 0x3d, 0x0c, 0xc9, 0x49, 0x80, 0x1d, 0x63, 0xa6, + 0x4c, 0xb2, 0xd3, 0x23, 0x73, 0xb2, 0xc7, 0xb2, 0x74, 0xab, 0x2d, 0xb4, 0x68, 0x21, + 0x42, 0xc8, 0xb2, 0x1d, 0x84, 0xc4, 0x81, 0xf5, 0xef, 0x21, 0xe4, 0xb5, 0xe3, 0x60, + 0x34, 0x51, 0xbf, 0x94, 0x77, 0x4d, 0x0e, 0xf4, 0x7f, 0x63, 0xfa, 0x6a, 0xbb, 0x78, + 0xd2, 0x1c, 0x19, 0x3c, 0xbe, 0x65, 0xb6, 0x95, 0xfe, 0x67, 0x42, 0x3c, 0x1e, 0x2d, + 0x31, 0x2e, 0x27, 0x76, 0xfa, 0x24, 0xec, 0xe8, 0x46, 0x83, 0xe7, 0x48, 0x76, 0xc5, + 0x5e, 0xa0, 0x36, 0x9e, 0x4e, 0xa0, 0xe8, 0x64, 0x94, 0xe0, 0x0d, 0xde, 0x23, 0x6a, + 0x16, 0x89, 0x73, 0x1f, 0x0a, 0x5d, 0x82, 0x03, 0xaf, 0xde, 0x5c, 0x42, 0x36, 0x40, + 0xb8, 0x1e, 0x4f, 0x63, 0x1c, 0x98, 0x1c, 0x11, 0xa2, 0xe1, 0xd1, 0x84, 0xc6, 0x7c, + 0x52, 0x8d, 0xf9, 0x2d, 0x53, 0xae, 0xc4, 0x4a, 0x40, 0xa4, 0xea, 0x2a, 0x13, 0x1b, + 0x47, 0x33, 0xcf, 0xe4, 0x5c, 0x6b, 0x00, 0x12, 0xc3, 0xe9, 0xe2, 0x09, 0x75, 0xba, + 0xae, 0xcb, 0x02, 0x32, 0xdf, 0x88, 0x0b, 0xd7, 0xd1, 0xde, 0x13, 0xe1, 0x34, 0x94, + 0x62, 0xec, 0x8d, 0x5d, 0xf3, 0xe7, 0x80, 0xff, 0xa7, 0x2e, 0xba, 0x8a, 0x8d, 0xf7, + 0xfc, 0xf3, 0x98, 0xec, 0x23, 0x05, 0x13, 0xca, 0x9d, 0x61, 0x23, 0xf8, 0xb9, 0xd8, + 0x17, 0x85, 0x60, 0xda, 0xf9, 0x75, 0x11, 0x19, 0x55, 0xa2, 0xbc, 0xa3, 0x42, 0x3e, + 0xee, 0xfc, 0x52, 0x7b, 0xe3, 0xa8, 0x54, 0x3e, 0xb9, 0x0a, 0x5e, 0xc0, 0x2f, 0x35, + 0xa7, 0xc6, 0x4b, 0x7d, 0xd5, 0x9a, 0x72, 0xda, 0x00, 0x74, 0x63, 0x4e, 0x01, 0xd2, + 0xab, 0xf3, 0x63, 0x7a, 0xdd, 0x77, 0xc7, 0x35, + ], + c_enc: [ + 0xa4, 0x01, 0xab, 0x60, 0x1f, 0x8d, 0x69, 0xd9, 0x38, 0x0c, 0x3d, 0xef, 0x1f, 0x1a, + 0x34, 0xbe, 0x6c, 0xfa, 0x4d, 0x83, 0x8b, 0xf8, 0x7f, 0x00, 0xe3, 0x6b, 0xe6, 0xbe, + 0x68, 0x60, 0xbe, 0xa8, 0x3d, 0xab, 0xdd, 0x00, 0xab, 0xe7, 0xe0, 0xd1, 0x21, 0x90, + 0xfb, 0x54, 0xb0, 0xf2, 0xad, 0xcf, 0xef, 0x9e, 0xf4, 0x2b, 0xa2, 0x31, 0x77, 0x6a, + 0xd3, 0xee, 0x09, 0x86, 0xdb, 0x3f, 0x4f, 0xc0, 0xa8, 0xa1, 0xc6, 0xa7, 0xfe, 0x54, + 0xa6, 0x6b, 0xd7, 0x68, 0xa9, 0xde, 0xd2, 0x5b, 0xb1, 0x89, 0xd5, 0x87, 0x1c, 0xaf, + 0x4d, 0xf8, 0x95, 0x6c, 0x2f, 0x30, 0x70, 0x15, 0x89, 0xa4, 0xdc, 0xdb, 0x68, 0x11, + 0x6d, 0x0f, 0x50, 0x9b, 0x34, 0x1e, 0x8f, 0x25, 0x8e, 0x17, 0x38, 0xb5, 0x51, 0x9c, + 0x99, 0xf1, 0xdb, 0xd0, 0x86, 0x31, 0x56, 0x2f, 0x90, 0xd1, 0x5e, 0x72, 0x8a, 0x85, + 0x25, 0xa1, 0x1b, 0xfe, 0x53, 0x95, 0x24, 0x5d, 0x71, 0x79, 0xcf, 0x8e, 0x97, 0xa8, + 0x3f, 0xaa, 0x4c, 0xf3, 0xb2, 0xa8, 0xb5, 0xef, 0x62, 0x13, 0xe3, 0x30, 0x89, 0xb4, + 0xeb, 0x03, 0xe7, 0xc2, 0xf0, 0x12, 0x11, 0xfc, 0x53, 0xbc, 0x01, 0x16, 0x40, 0x05, + 0x01, 0x5d, 0xbf, 0x33, 0xc6, 0x50, 0xa3, 0xf8, 0x33, 0xba, 0x67, 0x77, 0xcf, 0xf1, + 0xd7, 0x38, 0xe2, 0x1c, 0x58, 0xdc, 0x05, 0xc3, 0xb4, 0xec, 0xb9, 0x7a, 0x6c, 0xe0, + 0xb0, 0xc5, 0xee, 0x94, 0x4c, 0x24, 0xb3, 0x3b, 0xb0, 0xce, 0x32, 0xbe, 0x02, 0x3e, + 0x21, 0x3f, 0xf7, 0xc9, 0xd4, 0x12, 0x4f, 0xc9, 0xdc, 0x4a, 0xa7, 0xca, 0x47, 0x13, + 0x86, 0x48, 0xe2, 0xbb, 0x80, 0x7c, 0xea, 0x7a, 0x58, 0xe7, 0x67, 0xd3, 0x27, 0x07, + 0x4a, 0xe5, 0xe3, 0x9c, 0x3c, 0x17, 0xb7, 0x7c, 0x09, 0x0a, 0xf9, 0x42, 0x5b, 0xc6, + 0x40, 0xd2, 0x1d, 0xd6, 0x81, 0xa6, 0x37, 0x45, 0xe9, 0x02, 0x59, 0xe2, 0xd1, 0x09, + 0x0c, 0x88, 0x48, 0x8e, 0x21, 0x48, 0xb9, 0xee, 0x24, 0x31, 0xc5, 0xae, 0xf5, 0x10, + 0x95, 0xb3, 0x5a, 0x37, 0x7c, 0xfa, 0x76, 0x5d, 0x82, 0x24, 0x98, 0x83, 0x00, 0x04, + 0x71, 0x79, 0xa5, 0x09, 0x40, 0x28, 0xbe, 0x52, 0x7d, 0x5d, 0xe1, 0xc2, 0x69, 0xff, + 0x45, 0x2c, 0x0a, 0xaf, 0x5a, 0x47, 0x7e, 0x93, 0x90, 0xa0, 0xf0, 0xa8, 0x68, 0x11, + 0x3c, 0x7c, 0xd1, 0x9e, 0x2e, 0xac, 0x54, 0x0d, 0xc6, 0x59, 0xda, 0x29, 0x60, 0x06, + 0x77, 0x6e, 0xda, 0x0d, 0xf9, 0x81, 0xc4, 0x11, 0xc1, 0x50, 0x01, 0xa9, 0x8b, 0x6a, + 0xd6, 0x58, 0xd9, 0xa6, 0x4c, 0x12, 0x6a, 0xbe, 0xfc, 0x73, 0x9a, 0xa1, 0xf4, 0x44, + 0xbb, 0x83, 0xf3, 0xf1, 0x4d, 0x11, 0x3d, 0x02, 0x8f, 0xae, 0x10, 0xe4, 0xc5, 0xdb, + 0xe7, 0x78, 0x51, 0x96, 0x83, 0xcd, 0xf4, 0xc2, 0xf4, 0x6c, 0x4a, 0x52, 0xae, 0x12, + 0x09, 0xe1, 0x12, 0x7f, 0x9d, 0xc4, 0xed, 0x86, 0x7d, 0x8e, 0xda, 0x02, 0x4a, 0x68, + 0x9f, 0x6b, 0x15, 0xb8, 0x05, 0x38, 0x03, 0x02, 0x44, 0x02, 0xa1, 0xce, 0x6f, 0x1c, + 0x63, 0x6f, 0x2e, 0xfc, 0xf9, 0xd0, 0x60, 0x51, 0x5c, 0xd6, 0x14, 0x71, 0x8d, 0x51, + 0x52, 0x7d, 0x26, 0x7a, 0xd8, 0x95, 0xfa, 0xd8, 0xec, 0xfb, 0x23, 0x51, 0xf8, 0x92, + 0x45, 0x0d, 0xc8, 0x74, 0xe8, 0x74, 0x39, 0x2c, 0x91, 0xed, 0x3a, 0xf1, 0x18, 0x38, + 0xc4, 0xb5, 0x48, 0x2e, 0x8c, 0x92, 0xeb, 0xc7, 0xa0, 0x08, 0x8e, 0x49, 0xd2, 0xb0, + 0xb4, 0xa1, 0xbd, 0x33, 0x3b, 0x38, 0x7f, 0x49, 0xe3, 0x0f, 0xd2, 0x1a, 0x6e, 0xdc, + 0x89, 0x94, 0x83, 0x4f, 0x28, 0xe9, 0xf2, 0x52, 0x9a, 0x7e, 0x27, 0x24, 0x21, 0x6d, + 0x9e, 0x1a, 0xe5, 0xb4, 0x6e, 0xb1, 0x9a, 0x53, 0xea, 0x2b, 0x97, 0x99, 0x65, 0xf7, + 0x5b, 0x83, 0xf6, 0x86, 0xed, 0xc0, 0x1d, 0x25, 0x7a, 0x06, 0x58, 0xd7, 0x4e, 0x25, + 0xc0, 0xe1, 0xa8, 0xb0, 0x65, 0x60, 0x43, 0x1f, 0x85, 0x10, 0x5c, 0xf9, 0x8a, 0x1f, + 0xfe, 0x28, 0x40, 0x8a, 0x64, 0xf4, 0xc0, 0x27, 0x8d, 0x36, 0xed, 0xea, 0x76, 0x40, + 0xa2, 0x18, 0x26, 0xc3, 0xae, 0xba, 0xcb, 0x41, 0x4d, 0xa1, 0x8c, 0xc1, 0xd1, 0xe8, + 0x64, 0xc1, 0x6e, 0x97, 0x71, 0x0d, 0x56, 0xe0, 0xa1, 0x0e, 0x2c, 0xae, 0x86, 0xcb, + 0x27, 0x50, 0x14, 0x21, 0xdf, 0x52, 0xeb, 0x3c, 0x2f, 0x6e, 0x9d, 0x15, 0x59, 0xc1, + 0xb9, 0x5e, 0x7f, 0x63, 0xcb, 0x5c, 0xfa, 0xf5, 0xca, 0xc1, + ], + ock: [ + 0x2a, 0x2e, 0x0d, 0x99, 0x69, 0xf0, 0x2e, 0xbd, 0xb6, 0xd9, 0xc8, 0xe7, 0xe6, 0xfd, + 0xde, 0x20, 0x85, 0x12, 0x4b, 0x19, 0xad, 0x70, 0x90, 0xcc, 0x26, 0x15, 0x1d, 0x4d, + 0xa4, 0x2a, 0x00, 0x3e, + ], + op: [ + 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, + 0x9a, 0x02, 0x53, 0xe5, 0x24, 0xa0, 0x2c, 0x77, 0x95, 0xe9, 0x8f, 0x83, 0xec, 0x7d, + 0x96, 0xdc, 0xe6, 0xb7, 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, + 0x44, 0xb0, 0xb0, 0x4f, 0xe7, 0x93, 0x92, 0x5d, 0x49, 0xc4, 0xc0, 0x1f, 0x49, 0x2e, + 0xa9, 0xec, 0x88, 0x17, 0x18, 0x65, 0x40, 0x33, + ], + c_out: [ + 0x74, 0x6a, 0xae, 0x9d, 0xa6, 0x1c, 0x02, 0xae, 0xaa, 0x8b, 0xed, 0xbe, 0x2b, 0x6c, + 0x84, 0x1b, 0xc4, 0x36, 0x17, 0x3c, 0x7c, 0x91, 0x13, 0x66, 0x3a, 0x39, 0xc1, 0x74, + 0x69, 0x29, 0x0b, 0xd2, 0x19, 0xea, 0xdc, 0x4a, 0x97, 0x5a, 0xd0, 0x52, 0xd0, 0x5d, + 0xc0, 0xa3, 0x08, 0xf3, 0x63, 0xf9, 0x22, 0x68, 0x2d, 0x75, 0x21, 0x9d, 0xaa, 0x33, + 0x6f, 0x69, 0xb5, 0x9e, 0x86, 0x7c, 0x85, 0xd9, 0x37, 0x34, 0x4c, 0x19, 0xd3, 0x88, + 0x01, 0x63, 0x19, 0xb3, 0xf6, 0x0f, 0x76, 0xd0, 0x28, 0x93, + ], + }, + TestVector { + incoming_viewing_key: [ + 0x9c, 0xe9, 0x20, 0x37, 0x6a, 0x6a, 0x54, 0x1e, 0x6a, 0xad, 0x66, 0x0e, 0xfa, 0x09, + 0x8d, 0xc5, 0x4c, 0x18, 0xfc, 0xeb, 0x13, 0xd0, 0x99, 0x9f, 0xbc, 0xc7, 0xfd, 0x45, + 0xa5, 0x7c, 0xcc, 0x10, 0xb8, 0xaa, 0x86, 0xc4, 0x54, 0x0d, 0x0a, 0x9f, 0xc6, 0x6d, + 0xf8, 0x5d, 0xad, 0xd6, 0x21, 0x56, 0x36, 0x5e, 0x28, 0xa3, 0xe9, 0x80, 0xb9, 0x8d, + 0x13, 0x1b, 0x50, 0x3a, 0xa0, 0x6a, 0x6c, 0x19, + ], + ovk: [ + 0xf8, 0x1a, 0xd6, 0x17, 0xfa, 0x26, 0xf0, 0xdf, 0xb8, 0x36, 0x55, 0xb8, 0xa2, 0x9a, + 0x7f, 0x83, 0x42, 0x32, 0x42, 0x5e, 0x8c, 0x47, 0x45, 0x88, 0xf1, 0x8d, 0xd3, 0x26, + 0xaa, 0x39, 0x6c, 0x3e, + ], + default_d: [ + 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, + ], + default_pk_d: [ + 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, + 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, + 0x43, 0x4b, 0x1e, 0xb0, + ], + v: 2690686290017047047, + rseed: [ + 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, + 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, + 0xee, 0xba, 0xe6, 0xfa, + ], + asset: [ + 0x64, 0xd0, 0x87, 0x40, 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, + 0xc3, 0x93, 0x11, 0x78, 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, + 0xe5, 0xf5, 0xd4, 0xbc, + ], + memo: [ + 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, + 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, + 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, + 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, + 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, + 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, + 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, + 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, + 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, + 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, + 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, + 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, + 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, + 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, + 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, + 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, + 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, + 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, + 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, + 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, + 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, + 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, + 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, + 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, + 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, + 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, + 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, + 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, + 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, + 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, + 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, + 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, + 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, + 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, + 0xe8, 0xba, 0x4f, 0x52, 0x4d, 0xfa, 0xfe, 0x87, 0x52, 0x62, 0xdd, 0x7b, 0xe4, 0x1c, + 0xbb, 0xc6, 0x24, 0x20, 0xd4, 0xad, 0x6d, 0xf5, 0xc9, 0xb7, 0x13, 0x60, 0x4f, 0x65, + 0x60, 0x88, 0xa4, 0x48, 0x5e, 0x93, 0xbe, 0x19, + ], + cv_net: [ + 0xf4, 0x5c, 0xba, 0x14, 0x6a, 0xe7, 0x18, 0x85, 0xfd, 0x61, 0xb4, 0xa0, 0xf3, 0x6b, + 0x95, 0x26, 0xa6, 0xe9, 0x4a, 0x49, 0x70, 0x10, 0xe3, 0x2a, 0x8a, 0x76, 0xbc, 0xdf, + 0xa7, 0x20, 0xb8, 0xa6, + ], + rho: [ + 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, + 0xa5, 0xed, 0x09, 0xc6, 0xee, 0x3b, 0x7f, 0x39, 0x34, 0x14, 0xe1, 0x1c, 0xd4, 0x20, + 0x4c, 0x3f, 0x8d, 0x26, + ], + cmx: [ + 0x69, 0x4b, 0x6f, 0x3a, 0xb8, 0x37, 0xa9, 0x26, 0xd6, 0x77, 0x3e, 0xc4, 0xa6, 0x76, + 0x5d, 0xef, 0x82, 0x89, 0x33, 0x74, 0x2d, 0x93, 0x29, 0xfc, 0x88, 0x67, 0x1c, 0xcd, + 0x81, 0x21, 0xa4, 0x23, + ], + esk: [ + 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, 0xa5, 0xd8, 0x9a, 0xa8, + 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, 0x6a, 0x72, 0xcb, 0x74, + 0xfb, 0x18, 0xd1, 0x17, + ], + ephemeral_key: [ + 0x3c, 0x04, 0xbe, 0x6e, 0x42, 0xa6, 0xca, 0x7f, 0x5d, 0xda, 0x0d, 0x82, 0xdf, 0x30, + 0x7b, 0xd9, 0x6b, 0xb7, 0xb1, 0xae, 0x8d, 0x62, 0x31, 0x87, 0xe3, 0x9c, 0x00, 0xa4, + 0x8c, 0x25, 0xaa, 0x9d, + ], + shared_secret: [ + 0x3a, 0x60, 0x2b, 0xaf, 0xb8, 0xa2, 0x66, 0x5a, 0x74, 0xdf, 0x34, 0xab, 0x6e, 0x3c, + 0x48, 0x8b, 0x09, 0xe2, 0x28, 0x4e, 0xa1, 0x7d, 0x56, 0x02, 0x62, 0xe2, 0x1f, 0x7f, + 0x3c, 0xba, 0xa3, 0x95, + ], + k_enc: [ + 0x1b, 0x6d, 0xd1, 0x03, 0x49, 0x63, 0x67, 0xc9, 0x2b, 0x36, 0x8f, 0xc2, 0xf1, 0xc6, + 0x2e, 0x56, 0xc8, 0xc9, 0xfb, 0xe3, 0x4a, 0x35, 0x84, 0x1f, 0xe1, 0xa3, 0x70, 0x96, + 0x43, 0xe1, 0x35, 0xe1, + ], + p_enc: [ + 0x03, 0xfb, 0x8e, 0xa2, 0xcc, 0x0a, 0xd2, 0x30, 0x91, 0x32, 0xfd, 0x11, 0x07, 0xd2, + 0x7a, 0xc6, 0xec, 0x3c, 0x57, 0x25, 0x0b, 0x39, 0x05, 0xa4, 0xe3, 0xbd, 0x01, 0xc5, + 0x4d, 0xf8, 0x64, 0x34, 0x43, 0xbe, 0x0f, 0x88, 0x90, 0x32, 0xea, 0x32, 0x5b, 0xf0, + 0x71, 0x07, 0xfd, 0x41, 0xd6, 0x73, 0xee, 0xba, 0xe6, 0xfa, 0x64, 0xd0, 0x87, 0x40, + 0x89, 0x86, 0xe7, 0x3d, 0x6e, 0x28, 0x4f, 0xea, 0x9a, 0x23, 0xc3, 0x93, 0x11, 0x78, + 0x2f, 0x86, 0xca, 0xbf, 0xf9, 0x45, 0x5e, 0x4c, 0xf6, 0x99, 0xe5, 0xf5, 0xd4, 0xbc, + 0xff, 0x63, 0x7b, 0x70, 0xcc, 0x0e, 0xd3, 0xf0, 0x09, 0x58, 0xdf, 0xb8, 0xdc, 0xf0, + 0x0e, 0x85, 0xa1, 0xd0, 0xa6, 0xa8, 0x90, 0x81, 0x40, 0xc2, 0xf4, 0x34, 0xc2, 0xe2, + 0x60, 0xef, 0xb0, 0xbc, 0xa2, 0x00, 0x35, 0x04, 0xc9, 0x99, 0x93, 0xa9, 0xe1, 0xc0, + 0xff, 0x9c, 0xef, 0xe6, 0xa6, 0x65, 0xd7, 0x91, 0x42, 0x86, 0x90, 0xe4, 0x7e, 0xf8, + 0xc1, 0x31, 0xa8, 0xe9, 0xbf, 0xb4, 0xc3, 0x08, 0x02, 0x35, 0x03, 0x2d, 0x73, 0x1b, + 0x0d, 0x38, 0x41, 0x22, 0x5f, 0x1c, 0x11, 0xe2, 0xc2, 0x8e, 0xe8, 0x4d, 0x35, 0xf9, + 0x22, 0x61, 0x00, 0x56, 0x59, 0x72, 0xeb, 0x26, 0x9d, 0x27, 0x8e, 0xf6, 0x49, 0x79, + 0xbf, 0x65, 0x15, 0xed, 0x4a, 0x68, 0x40, 0xb0, 0x88, 0x3a, 0x9e, 0x6e, 0xf6, 0x4a, + 0x0e, 0xfc, 0xae, 0x1c, 0xf2, 0x1d, 0xfe, 0x74, 0x85, 0x4e, 0x84, 0xc2, 0x74, 0x9f, + 0xac, 0x03, 0x82, 0x52, 0x75, 0xc9, 0xb6, 0x30, 0x21, 0x84, 0xc7, 0x2d, 0xf4, 0xc4, + 0xbb, 0x28, 0x62, 0xe4, 0xe8, 0xa7, 0xd9, 0xa4, 0xa2, 0x82, 0x86, 0x6f, 0x9a, 0x7b, + 0x2c, 0xfc, 0x9a, 0x56, 0x31, 0x3d, 0xa0, 0xc4, 0x7a, 0x34, 0xb7, 0xb9, 0xcd, 0xa3, + 0xac, 0xe8, 0x18, 0x5f, 0x07, 0xdf, 0x36, 0xe4, 0x48, 0xa7, 0x6a, 0xa4, 0x77, 0xf2, + 0x24, 0xd8, 0x7a, 0x07, 0x4f, 0x43, 0xaf, 0x5d, 0x5f, 0x79, 0xb3, 0xab, 0x11, 0x28, + 0xf0, 0x81, 0x91, 0x44, 0x7f, 0xa6, 0x46, 0xbf, 0xdd, 0xe5, 0xb5, 0x1e, 0x23, 0x3c, + 0xa6, 0x15, 0x5d, 0x10, 0x15, 0x85, 0xbc, 0x2c, 0x40, 0x15, 0x8a, 0xc2, 0x10, 0x6e, + 0x66, 0xa2, 0x6e, 0x46, 0x42, 0x33, 0x70, 0x63, 0x68, 0x76, 0xb4, 0x34, 0xa7, 0x4f, + 0x8c, 0xe8, 0x06, 0x00, 0x50, 0xb0, 0x82, 0xa7, 0x9b, 0x61, 0xbb, 0x5d, 0x34, 0x4e, + 0xb5, 0xa1, 0x15, 0x83, 0x26, 0xce, 0xd9, 0xa9, 0xd9, 0xf5, 0x4f, 0xb2, 0xfe, 0x8f, + 0x9f, 0x05, 0xcd, 0x11, 0x1e, 0xe4, 0x6c, 0x47, 0x10, 0xf6, 0xf6, 0x3a, 0x62, 0x69, + 0x45, 0x57, 0xef, 0x1b, 0x12, 0xc8, 0x80, 0x06, 0xb6, 0x78, 0x72, 0x50, 0x5f, 0x4e, + 0x88, 0x3b, 0x58, 0x59, 0x07, 0x92, 0x9a, 0x2f, 0x3f, 0xdb, 0x0d, 0x8f, 0x79, 0x14, + 0xc4, 0x2d, 0xde, 0x2d, 0x20, 0x00, 0xf5, 0xae, 0x02, 0xd4, 0x18, 0x21, 0xc8, 0xe1, + 0xee, 0x01, 0x38, 0xeb, 0xcb, 0x72, 0x8d, 0x7c, 0x6c, 0x3c, 0x80, 0x02, 0x7e, 0x43, + 0x75, 0x94, 0xc6, 0x70, 0xfd, 0x6f, 0x39, 0x08, 0x22, 0x2e, 0xe7, 0xa1, 0xb9, 0x17, + 0xf8, 0x27, 0x1a, 0xbe, 0x66, 0x0e, 0x39, 0xe0, 0x51, 0xaa, 0xa6, 0xfc, 0xa1, 0x86, + 0x22, 0x76, 0xe2, 0xba, 0xa0, 0xfe, 0x0b, 0x16, 0x2a, 0xeb, 0xcf, 0xe3, 0xd9, 0x34, + 0x9c, 0x8d, 0x15, 0x4b, 0xb7, 0xee, 0x28, 0x21, 0x2c, 0x1b, 0xaa, 0x70, 0x5d, 0x82, + 0x07, 0x0d, 0x70, 0x32, 0xf2, 0x69, 0x5d, 0x17, 0x96, 0x80, 0x9f, 0xab, 0x41, 0x24, + 0x69, 0x26, 0xaf, 0x99, 0x2b, 0x6e, 0xee, 0x95, 0xa9, 0xa0, 0x6b, 0xc4, 0x56, 0x2c, + 0x5f, 0x2f, 0x1b, 0x19, 0x54, 0x95, 0x00, 0x37, 0x2e, 0x7a, 0xd5, 0x79, 0xa6, 0xd6, + 0xd7, 0x8b, 0x33, 0x15, 0x31, 0x30, 0xfb, 0x44, 0x8f, 0xb7, 0x9e, 0x8a, 0x66, 0x9d, + 0xb8, 0xa0, 0xf3, 0x5c, 0xdf, 0x9a, 0xe5, 0xd3, 0x2d, 0x73, 0x2f, 0xc7, 0x94, 0x18, + 0xe2, 0x3b, 0x45, 0x1d, 0xdc, 0x95, 0xa2, 0x2a, 0xba, 0xbb, 0x05, 0x6e, 0xc6, 0xb5, + 0xe8, 0xba, 0x4f, 0x52, 0x4d, 0xfa, 0xfe, 0x87, 0x52, 0x62, 0xdd, 0x7b, 0xe4, 0x1c, + 0xbb, 0xc6, 0x24, 0x20, 0xd4, 0xad, 0x6d, 0xf5, 0xc9, 0xb7, 0x13, 0x60, 0x4f, 0x65, + 0x60, 0x88, 0xa4, 0x48, 0x5e, 0x93, 0xbe, 0x19, + ], + c_enc: [ + 0xb4, 0x15, 0x88, 0x23, 0x1d, 0x6b, 0xa2, 0x9c, 0xc5, 0xb9, 0xaa, 0xf0, 0xc1, 0xf0, + 0xba, 0x44, 0x16, 0x6e, 0xdb, 0x8a, 0x27, 0x29, 0xca, 0xba, 0x53, 0x71, 0xe7, 0xac, + 0x36, 0x90, 0x0f, 0xaa, 0x64, 0xf5, 0x76, 0x0d, 0xce, 0x55, 0x20, 0xda, 0x82, 0x8d, + 0x5e, 0x25, 0xbd, 0x83, 0x51, 0x95, 0x11, 0x64, 0x12, 0x11, 0x80, 0x9d, 0xff, 0xd8, + 0xcf, 0xeb, 0xff, 0xf3, 0xcd, 0xdc, 0xd2, 0x75, 0x88, 0x1e, 0x39, 0xb6, 0x3d, 0xac, + 0x4d, 0x98, 0x6b, 0x10, 0xc0, 0xe4, 0xc5, 0x52, 0x63, 0xde, 0x3e, 0x02, 0x54, 0x94, + 0x81, 0x8a, 0x38, 0x08, 0xd9, 0xab, 0xc6, 0xec, 0x38, 0x8f, 0x95, 0x26, 0x73, 0x95, + 0x0a, 0xa2, 0xd0, 0xe4, 0xba, 0x00, 0x53, 0x75, 0xac, 0x60, 0x5d, 0xc8, 0x25, 0xde, + 0x4d, 0xd8, 0x93, 0x8b, 0x94, 0x7f, 0xf7, 0x19, 0x4c, 0xfe, 0x7c, 0x1d, 0x79, 0xa1, + 0x27, 0x15, 0x5d, 0x11, 0xcb, 0xe3, 0x43, 0xf3, 0x2f, 0xd1, 0x0c, 0x7d, 0xae, 0x39, + 0x1f, 0x00, 0xb4, 0x4f, 0xbe, 0x30, 0x1c, 0x63, 0xfd, 0x4b, 0xf1, 0xc0, 0xdf, 0xb6, + 0xc9, 0xec, 0xb4, 0xc3, 0xf3, 0xfe, 0xf5, 0x40, 0xb6, 0x7e, 0xb9, 0x23, 0x13, 0x71, + 0x9c, 0x5a, 0x30, 0x7a, 0xd3, 0x95, 0x6b, 0xb9, 0x4e, 0x29, 0x86, 0x85, 0x2a, 0x64, + 0x5a, 0x95, 0xd6, 0xdc, 0x75, 0xaa, 0x27, 0x4c, 0xcf, 0xd2, 0x71, 0xd0, 0xea, 0xe2, + 0x65, 0x81, 0xf5, 0xf5, 0x5d, 0x64, 0x74, 0xaa, 0xad, 0x37, 0x4c, 0x86, 0x45, 0x05, + 0xe6, 0x92, 0x37, 0xf6, 0x66, 0x99, 0xee, 0x39, 0xe9, 0xfc, 0xf5, 0xb1, 0xb7, 0x03, + 0x35, 0x1e, 0x71, 0xf6, 0x3b, 0x02, 0x33, 0x40, 0x82, 0xee, 0xbe, 0xd8, 0x68, 0xb5, + 0x61, 0x2a, 0x33, 0x95, 0x78, 0x5a, 0x33, 0x2a, 0x52, 0x43, 0xe4, 0x98, 0x6e, 0x1f, + 0xf5, 0xb4, 0x2d, 0x06, 0x69, 0xc1, 0x5c, 0x45, 0xff, 0x81, 0xe2, 0x2e, 0xea, 0xe4, + 0xde, 0x7d, 0x9a, 0x4f, 0x57, 0x24, 0xc8, 0x96, 0x03, 0x94, 0x92, 0x5b, 0xa1, 0xa1, + 0x90, 0x0f, 0xa2, 0xb5, 0x59, 0x3d, 0x55, 0x45, 0x5e, 0x0b, 0xe0, 0x31, 0x8c, 0x80, + 0x23, 0x81, 0xec, 0x9c, 0x0a, 0x83, 0xc2, 0xe5, 0xf9, 0x33, 0x9f, 0x02, 0x9c, 0x44, + 0x24, 0x72, 0x8f, 0x91, 0x9d, 0x18, 0x4f, 0x36, 0x16, 0x50, 0xba, 0x65, 0xd6, 0x98, + 0xa8, 0xd1, 0x67, 0xbe, 0xd9, 0xdd, 0x01, 0xfa, 0x70, 0x74, 0xe4, 0x6a, 0xf6, 0x57, + 0x16, 0xdd, 0xd9, 0x7e, 0x7b, 0xb6, 0x00, 0x13, 0x05, 0x96, 0x8c, 0xd5, 0xb4, 0x87, + 0x0d, 0xf2, 0x00, 0x42, 0xe7, 0x69, 0xe0, 0x2d, 0xf1, 0x8b, 0x9f, 0xde, 0x9f, 0xda, + 0xa7, 0x6b, 0x00, 0xca, 0x26, 0x45, 0x9d, 0x54, 0x37, 0x19, 0x19, 0x72, 0xd7, 0x08, + 0xde, 0xda, 0xbf, 0x1d, 0x61, 0x7f, 0x73, 0x3a, 0x60, 0xeb, 0xfe, 0xc6, 0xac, 0xf0, + 0x0b, 0xb1, 0xdf, 0xbf, 0x11, 0x2d, 0x3a, 0xaa, 0xc9, 0xfb, 0xd2, 0x30, 0xcc, 0xaa, + 0x9c, 0xf3, 0x58, 0x45, 0x93, 0x54, 0xac, 0x5b, 0x29, 0xbd, 0xb7, 0x3a, 0x45, 0x27, + 0x1b, 0x1f, 0x9e, 0xd0, 0x0e, 0x3e, 0x20, 0xb1, 0x2f, 0xed, 0x5c, 0xd5, 0x6a, 0xbb, + 0xb0, 0xb9, 0x4a, 0x9e, 0xee, 0x5f, 0xf8, 0xf9, 0x36, 0x1d, 0xfd, 0x6c, 0x94, 0x08, + 0x5d, 0x28, 0x98, 0xe5, 0x46, 0xeb, 0x92, 0xe6, 0xdb, 0xe9, 0xf0, 0x2e, 0xb5, 0xbf, + 0x7d, 0x12, 0x67, 0x5d, 0x3c, 0x6a, 0xc7, 0x18, 0x4b, 0x26, 0x01, 0xe4, 0xf4, 0x05, + 0x37, 0x3a, 0x4f, 0x1c, 0x5d, 0xf7, 0x6b, 0x3c, 0xb5, 0x29, 0x99, 0xd8, 0x0f, 0x59, + 0xb3, 0x94, 0xbc, 0xed, 0x9f, 0x66, 0xbc, 0xf7, 0xdc, 0x37, 0xc2, 0xb4, 0xc6, 0xf7, + 0x74, 0x5b, 0xc6, 0xf0, 0x37, 0x74, 0xfa, 0xc6, 0x24, 0x5d, 0x7c, 0x63, 0x6d, 0xfc, + 0x5f, 0x76, 0x58, 0xb2, 0xd2, 0xfd, 0x84, 0xac, 0xa9, 0xe0, 0xef, 0xcd, 0xe0, 0x09, + 0x3e, 0x62, 0x29, 0x38, 0xb7, 0x5d, 0xae, 0x66, 0xcf, 0x63, 0xf6, 0xd2, 0x35, 0x17, + 0x2e, 0x5a, 0x0b, 0xbe, 0xcd, 0x15, 0x56, 0x6c, 0x61, 0xfe, 0x5a, 0x58, 0x94, 0x7c, + 0x18, 0xb9, 0xb5, 0xa1, 0x27, 0x29, 0x4b, 0x67, 0x67, 0xd0, 0x2b, 0x0f, 0x66, 0x4c, + 0xef, 0x25, 0x8e, 0x26, 0x11, 0x1c, 0xf0, 0x9c, 0x9b, 0x61, 0xd4, 0x41, 0x52, 0x8d, + 0x8c, 0xa2, 0xd8, 0x00, 0x5c, 0xad, 0x2a, 0xe4, 0x16, 0xe3, 0x4b, 0xb2, 0x6b, 0x41, + 0xa1, 0x85, 0x5a, 0xf9, 0x90, 0xcd, 0xb6, 0x77, 0xaf, 0x0d, + ], + ock: [ + 0x67, 0x1c, 0xed, 0xd6, 0xf5, 0x73, 0xa4, 0x6f, 0xf1, 0xea, 0xd0, 0x48, 0x21, 0x98, + 0x56, 0x36, 0xe2, 0x3f, 0xb1, 0x5c, 0x6f, 0x48, 0x05, 0xfd, 0x57, 0x63, 0x12, 0xc2, + 0x07, 0x02, 0xa4, 0x24, + ], + op: [ + 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, + 0x5d, 0x71, 0xd0, 0xea, 0xba, 0x7c, 0xf3, 0xc2, 0xba, 0x94, 0x77, 0x12, 0x32, 0x75, + 0x43, 0x4b, 0x1e, 0xb0, 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, + 0xa5, 0xd8, 0x9a, 0xa8, 0xd6, 0xb3, 0xb0, 0x86, 0x92, 0x23, 0xed, 0x76, 0x3b, 0x67, + 0x6a, 0x72, 0xcb, 0x74, 0xfb, 0x18, 0xd1, 0x17, + ], + c_out: [ + 0x59, 0x97, 0x53, 0xe4, 0x0a, 0xda, 0xea, 0xff, 0x6f, 0xaa, 0xf5, 0xa6, 0xf3, 0x0e, + 0x39, 0x13, 0x8f, 0xde, 0x82, 0x0f, 0x7b, 0xec, 0x7c, 0x8d, 0x0f, 0xd8, 0x4b, 0x48, + 0x36, 0x94, 0xe5, 0x0c, 0x4b, 0xdd, 0xee, 0x2f, 0xb1, 0xa4, 0xf9, 0x95, 0xb1, 0xa3, + 0xba, 0x40, 0xf4, 0x66, 0xb4, 0x2e, 0x8b, 0x5d, 0x01, 0x38, 0xfd, 0x30, 0xbf, 0xf6, + 0xae, 0x8c, 0xb1, 0x55, 0xf4, 0x0c, 0xdc, 0x37, 0x39, 0xfa, 0xbf, 0x2f, 0x00, 0xda, + 0x3a, 0xc6, 0xa7, 0x36, 0x3b, 0xc2, 0xf4, 0xaa, 0x10, 0xfe, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xb4, 0x9e, 0x3c, 0x5b, 0xb9, 0x9e, 0x47, 0xc5, 0x3d, 0x6e, 0x5c, 0x34, 0x7c, 0x99, + 0x8f, 0x30, 0x2d, 0x3f, 0xf4, 0x75, 0x23, 0xe7, 0xc3, 0xd7, 0xb6, 0x4c, 0x82, 0x98, + 0xdc, 0x7b, 0x10, 0xe9, 0x54, 0xdf, 0x06, 0x00, 0x0b, 0xc0, 0xcc, 0x30, 0xec, 0xf6, + 0x75, 0x5d, 0x92, 0x7e, 0xee, 0xce, 0xe6, 0xec, 0x9e, 0x8e, 0x0c, 0xba, 0xa3, 0x1b, + 0x71, 0xe0, 0xa4, 0x33, 0x4a, 0xd6, 0x42, 0x1b, + ], + ovk: [ + 0x97, 0x9f, 0x06, 0x58, 0x66, 0x73, 0xbc, 0x6f, 0xf1, 0xc5, 0xd3, 0xb3, 0x20, 0xf3, + 0x49, 0xa5, 0xb3, 0xa8, 0xb3, 0x55, 0x59, 0x22, 0x96, 0xaa, 0xf6, 0x1c, 0x5b, 0x72, + 0x52, 0xf7, 0x3e, 0xc0, + ], + default_d: [ + 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, + ], + default_pk_d: [ + 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, + 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, + 0xf4, 0x1a, 0x1f, 0x88, + ], + v: 5531329397987978327, + rseed: [ + 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, + 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, + 0xd0, 0x11, 0x8b, 0xbd, + ], + asset: [ + 0xc3, 0xcc, 0x4f, 0x43, 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, + 0xe3, 0x7a, 0x83, 0xec, 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, + 0x29, 0x03, 0x35, 0xaa, + ], + memo: [ + 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, + 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, + 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, + 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, + 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, + 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, + 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, + 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, + 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, + 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, + 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, + 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, + 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, + 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, + 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, + 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, + 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, + 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, + 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, + 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, + 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, + 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, + 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, + 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, + 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, + 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, + 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, + 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, + 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, + 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, + 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, + 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, + 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, + 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, + 0x09, 0x5d, 0x98, 0x77, 0xa8, 0xf2, 0xdc, 0x53, 0xf4, 0x6f, 0x6c, 0x9b, 0x07, 0xad, + 0xdf, 0x14, 0x6f, 0x4f, 0xfa, 0x50, 0x1f, 0x9d, 0xd3, 0xcf, 0xf9, 0x24, 0xe3, 0x01, + 0x0f, 0xaf, 0x50, 0x4e, 0x2b, 0x8a, 0xca, 0x73, + ], + cv_net: [ + 0x1a, 0xa2, 0x3d, 0x96, 0x79, 0xbc, 0x66, 0x04, 0xb6, 0x25, 0x2c, 0x4f, 0x48, 0x1b, + 0x3a, 0x2a, 0xf5, 0x46, 0x32, 0xf8, 0x30, 0x08, 0x14, 0x68, 0x29, 0x65, 0x94, 0x5e, + 0x7e, 0x33, 0x2a, 0x0d, + ], + rho: [ + 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, + 0x67, 0x93, 0xc3, 0xfe, 0xfa, 0xda, 0xee, 0xa8, 0xe2, 0x3c, 0x44, 0xd5, 0xe0, 0x18, + 0x4b, 0xc8, 0x45, 0x10, + ], + cmx: [ + 0x76, 0xf1, 0xbd, 0x50, 0xf9, 0xb9, 0x06, 0xcb, 0x9f, 0xf2, 0xdd, 0x91, 0x8a, 0x36, + 0x7e, 0x5f, 0xb1, 0xa2, 0xef, 0x39, 0xf1, 0x4f, 0x6c, 0xe9, 0x4f, 0xf9, 0xf0, 0x91, + 0x55, 0xf8, 0xc2, 0x11, + ], + esk: [ + 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, 0xa1, 0xe6, 0xfb, 0x57, + 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, 0xb9, 0x5f, 0xc8, 0x7e, + 0xa7, 0x37, 0x3e, 0x2f, + ], + ephemeral_key: [ + 0xda, 0x72, 0x84, 0xa0, 0xe0, 0xde, 0x52, 0x09, 0x3c, 0xc2, 0xe1, 0x9c, 0x0a, 0xf1, + 0x93, 0xbd, 0xb4, 0x2c, 0x80, 0xc9, 0xc7, 0xf9, 0xf2, 0x36, 0x00, 0xe6, 0x08, 0x01, + 0x72, 0xc5, 0xf5, 0x39, + ], + shared_secret: [ + 0x9b, 0xcf, 0xb9, 0x6f, 0x4c, 0xf1, 0x83, 0xc1, 0x7f, 0xb1, 0x99, 0xda, 0x16, 0x5f, + 0xbf, 0x8a, 0x47, 0x47, 0x7e, 0x00, 0x36, 0x6d, 0x1c, 0xb7, 0x3b, 0x32, 0xec, 0x0e, + 0x3a, 0xc1, 0x98, 0x0f, + ], + k_enc: [ + 0x21, 0xe0, 0x97, 0x87, 0x0a, 0xee, 0xc0, 0x19, 0x76, 0x86, 0xee, 0x37, 0x22, 0x78, + 0xfe, 0x4a, 0xa2, 0x23, 0x8d, 0x87, 0x65, 0x32, 0x63, 0x84, 0x8a, 0x2f, 0xf5, 0x27, + 0x9f, 0x2b, 0x1d, 0x9b, + ], + p_enc: [ + 0x03, 0x8d, 0xb1, 0x31, 0xa6, 0x5b, 0xa6, 0xca, 0x91, 0xc9, 0xe9, 0x7b, 0x57, 0xac, + 0xbf, 0xfe, 0xc7, 0x3a, 0xc3, 0x4c, 0x1f, 0xbd, 0x83, 0xd5, 0x4a, 0xaf, 0x44, 0x1e, + 0x31, 0x9e, 0xa4, 0x7a, 0x86, 0x2a, 0xd0, 0x29, 0x3c, 0xed, 0xf5, 0xdd, 0x9e, 0xda, + 0xde, 0xee, 0x33, 0xcb, 0x52, 0x2c, 0xd0, 0x11, 0x8b, 0xbd, 0xc3, 0xcc, 0x4f, 0x43, + 0xfa, 0x01, 0x88, 0x52, 0x1b, 0xc6, 0x1b, 0x21, 0xdd, 0x04, 0xe3, 0x7a, 0x83, 0xec, + 0xe6, 0x8c, 0xa7, 0xa2, 0xfa, 0x6c, 0x8f, 0x9e, 0x34, 0xa6, 0x29, 0x03, 0x35, 0xaa, + 0xff, 0x81, 0x1a, 0xce, 0x9a, 0x23, 0xbd, 0xa3, 0x9a, 0xba, 0x72, 0xf1, 0x56, 0x6f, + 0xc1, 0x68, 0x84, 0x97, 0xd2, 0xa7, 0x92, 0x8c, 0x36, 0x70, 0x15, 0x25, 0x67, 0x8b, + 0xc9, 0x72, 0x14, 0xb3, 0x1b, 0x37, 0xba, 0xb4, 0x6b, 0x88, 0xf2, 0x7f, 0x04, 0x48, + 0xde, 0xcb, 0x31, 0x62, 0x2d, 0x0f, 0x0f, 0x87, 0xa8, 0x55, 0xba, 0x54, 0x00, 0x03, + 0x32, 0x03, 0x1f, 0x73, 0xab, 0xff, 0xd4, 0x65, 0x91, 0xda, 0x0b, 0x88, 0x72, 0x35, + 0x04, 0xed, 0xb2, 0x33, 0x72, 0x30, 0xda, 0xd2, 0xac, 0xc0, 0xd8, 0xbb, 0x68, 0xbc, + 0x83, 0x7a, 0x2f, 0xf9, 0x30, 0xbf, 0xf0, 0x6f, 0xde, 0x74, 0xeb, 0x90, 0xaa, 0xe4, + 0xf6, 0x0d, 0xbb, 0x6e, 0xb8, 0x27, 0xea, 0x99, 0x88, 0x4a, 0xcd, 0x62, 0x85, 0xa9, + 0x88, 0x92, 0x80, 0x2c, 0xf5, 0x9d, 0x5d, 0x60, 0xd0, 0x16, 0x63, 0x38, 0x7b, 0x3e, + 0xd2, 0x72, 0x3b, 0xd6, 0x48, 0x9e, 0x9c, 0x2c, 0x10, 0x6d, 0x4a, 0xa2, 0xde, 0x23, + 0xce, 0xd1, 0x6c, 0x72, 0x04, 0x29, 0xc7, 0x75, 0x3a, 0x77, 0x38, 0xec, 0x7d, 0x9d, + 0xb8, 0x62, 0x42, 0x29, 0xed, 0xd2, 0x17, 0xb8, 0x0d, 0x74, 0x87, 0x5a, 0x14, 0xca, + 0xe4, 0x86, 0x3f, 0x13, 0x9e, 0x9c, 0x0b, 0x13, 0x1b, 0x2a, 0x4c, 0x28, 0x07, 0x1a, + 0x38, 0xec, 0x61, 0xf6, 0x68, 0x01, 0xaa, 0x59, 0x56, 0xfc, 0xb2, 0xa4, 0x6b, 0x95, + 0x87, 0x66, 0x5b, 0x75, 0x71, 0xaa, 0x03, 0x48, 0x1f, 0xd8, 0xd9, 0xd5, 0x69, 0x8f, + 0x83, 0x6f, 0xc8, 0x63, 0x5e, 0x69, 0xe3, 0xbd, 0xe4, 0x2f, 0x4a, 0xc0, 0x71, 0x32, + 0x8b, 0x54, 0x09, 0xf6, 0xe4, 0x2d, 0x79, 0x0a, 0xed, 0xd7, 0x3b, 0xc1, 0xa2, 0x35, + 0x47, 0x23, 0xb3, 0xb8, 0x19, 0xd0, 0x63, 0x7a, 0x6f, 0xa4, 0x66, 0x39, 0x46, 0xa3, + 0x0a, 0xc5, 0xaf, 0xdd, 0x30, 0xce, 0x83, 0x0f, 0x67, 0x91, 0xb4, 0x57, 0x52, 0x70, + 0xa1, 0x72, 0x0f, 0x91, 0x86, 0x6e, 0x2b, 0x86, 0xf4, 0x78, 0x88, 0x94, 0xc8, 0xda, + 0x62, 0xd8, 0xb9, 0x1f, 0xaf, 0x52, 0x0e, 0x3b, 0xed, 0xbc, 0x12, 0x06, 0xa5, 0xa5, + 0xe6, 0xef, 0xd3, 0xdf, 0xde, 0x08, 0x43, 0xc3, 0xb0, 0x67, 0x57, 0x64, 0x3f, 0xc0, + 0x06, 0x00, 0x88, 0x38, 0xca, 0x47, 0x30, 0x87, 0xf8, 0x97, 0x79, 0x18, 0xcc, 0x1b, + 0x81, 0xc9, 0xe6, 0x8e, 0x3b, 0x88, 0x8f, 0xe6, 0xf7, 0xc6, 0x30, 0xf1, 0xbc, 0x7a, + 0xe1, 0x88, 0xf5, 0x12, 0x84, 0x20, 0x41, 0xca, 0xda, 0x1e, 0x05, 0xf8, 0x66, 0xd2, + 0x56, 0x2d, 0xbe, 0x09, 0xc4, 0xb4, 0x30, 0x68, 0xf7, 0x54, 0xda, 0xd3, 0x4d, 0xf0, + 0xfc, 0xfc, 0x18, 0x1f, 0x31, 0x80, 0x1a, 0x79, 0x92, 0xd2, 0xf1, 0x6b, 0xe0, 0x21, + 0x1b, 0x4a, 0x22, 0xf6, 0x2a, 0xab, 0x64, 0x70, 0x1b, 0xf4, 0xa4, 0xe6, 0xd6, 0x66, + 0xfc, 0x30, 0x4a, 0x5c, 0x79, 0xc6, 0x09, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x86, 0x48, + 0x93, 0xd3, 0x7d, 0x50, 0x07, 0xf0, 0xc3, 0x29, 0xa4, 0x75, 0x50, 0x52, 0x57, 0x75, + 0x70, 0xdd, 0x38, 0xfa, 0xc0, 0x43, 0xcd, 0x91, 0xc1, 0x2e, 0xe3, 0x4e, 0x9c, 0xfa, + 0xe3, 0x92, 0xa7, 0x8b, 0xda, 0xbd, 0x4e, 0xe3, 0x1d, 0xc0, 0xde, 0xb0, 0x2f, 0xe7, + 0xb1, 0xd8, 0xb0, 0x17, 0x8a, 0xc9, 0x51, 0x31, 0x05, 0xfc, 0xc7, 0xe3, 0x0b, 0xa8, + 0xe0, 0x16, 0xaa, 0x36, 0xa6, 0xb5, 0xdf, 0x5e, 0x5a, 0x19, 0x09, 0xf6, 0x3a, 0xba, + 0x09, 0x5d, 0x98, 0x77, 0xa8, 0xf2, 0xdc, 0x53, 0xf4, 0x6f, 0x6c, 0x9b, 0x07, 0xad, + 0xdf, 0x14, 0x6f, 0x4f, 0xfa, 0x50, 0x1f, 0x9d, 0xd3, 0xcf, 0xf9, 0x24, 0xe3, 0x01, + 0x0f, 0xaf, 0x50, 0x4e, 0x2b, 0x8a, 0xca, 0x73, + ], + c_enc: [ + 0x13, 0xd7, 0xdf, 0xcd, 0x1d, 0x75, 0x4d, 0xcd, 0x16, 0x52, 0x32, 0x83, 0x8f, 0x14, + 0xdd, 0x80, 0x5e, 0x12, 0xcc, 0x7e, 0x75, 0x15, 0x43, 0xd2, 0xa6, 0x8e, 0x23, 0x7a, + 0x92, 0x3b, 0xce, 0xeb, 0xa3, 0x5a, 0x62, 0x43, 0xc6, 0xa4, 0xc5, 0xf0, 0xd2, 0xa4, + 0xc3, 0x86, 0x07, 0xa6, 0xf1, 0x1b, 0x17, 0xfd, 0xd6, 0xc6, 0x92, 0x66, 0xf2, 0xc9, + 0x6a, 0xdc, 0x44, 0x6f, 0x2e, 0x2d, 0x07, 0x3e, 0xe9, 0xea, 0xe2, 0x9a, 0x37, 0xef, + 0x5d, 0x03, 0xf6, 0x78, 0xf5, 0x56, 0x29, 0x45, 0xb2, 0x08, 0x27, 0x76, 0xce, 0x9f, + 0x39, 0x08, 0x87, 0x3a, 0x99, 0xa6, 0xa2, 0x8b, 0xae, 0xdc, 0x7f, 0x54, 0x89, 0xce, + 0x4b, 0x30, 0xd8, 0x43, 0x66, 0xc5, 0x46, 0xb4, 0x36, 0x67, 0x91, 0x44, 0xf9, 0x27, + 0xf7, 0x1c, 0x65, 0x09, 0x69, 0xda, 0x22, 0x42, 0x28, 0x5a, 0x86, 0x27, 0x96, 0x54, + 0x89, 0xb7, 0x0b, 0x35, 0x6c, 0xf7, 0x4e, 0x07, 0x8a, 0xa2, 0x7d, 0xa8, 0xf9, 0x2f, + 0xb3, 0x09, 0x57, 0x12, 0x62, 0xf2, 0xd4, 0xc3, 0x36, 0xf7, 0x12, 0x15, 0x9b, 0x3e, + 0x9b, 0x43, 0x24, 0x38, 0x5b, 0xb3, 0x26, 0x2a, 0xc5, 0xf3, 0x13, 0x57, 0xaf, 0x9e, + 0x1a, 0xaa, 0x75, 0xd0, 0x1c, 0x06, 0x31, 0xbf, 0xdd, 0x34, 0xc5, 0x9b, 0x27, 0xd5, + 0x3b, 0xeb, 0xf1, 0xaa, 0x54, 0xe9, 0xc4, 0xaa, 0x98, 0x0f, 0x24, 0x7b, 0xf4, 0x22, + 0xa0, 0xe6, 0xdb, 0xf5, 0x54, 0x6e, 0xdc, 0x10, 0x0f, 0xce, 0x6c, 0xce, 0xc8, 0x32, + 0x7e, 0xb4, 0x8a, 0x9a, 0x39, 0xe4, 0xc2, 0xa9, 0x12, 0xb2, 0x98, 0x85, 0xe0, 0xc3, + 0xe7, 0x33, 0x55, 0x58, 0xbd, 0x85, 0x84, 0x38, 0xd0, 0x35, 0xd2, 0xf2, 0xbe, 0x1d, + 0x35, 0x66, 0xe4, 0x22, 0xfe, 0x37, 0xc0, 0xcb, 0x2e, 0x05, 0x8d, 0xad, 0x8c, 0xc6, + 0x45, 0x62, 0xa5, 0x50, 0x1b, 0x54, 0xa4, 0x4f, 0x9a, 0x77, 0x77, 0xc6, 0xd2, 0x77, + 0x04, 0xa4, 0xce, 0xad, 0x26, 0xa1, 0xc2, 0x56, 0x01, 0x8d, 0xc1, 0xbb, 0xfa, 0x58, + 0x84, 0xa0, 0x6c, 0xc7, 0x25, 0x23, 0xaf, 0xfb, 0x43, 0xf5, 0xc5, 0xbc, 0x2f, 0x1d, + 0x36, 0x04, 0x0f, 0x85, 0xf7, 0xe8, 0xc0, 0x62, 0xc1, 0xf2, 0x26, 0x50, 0x9d, 0x20, + 0xf9, 0xa4, 0x88, 0x5e, 0x15, 0x70, 0x4f, 0x73, 0x01, 0xdf, 0x60, 0x3d, 0xa1, 0xfc, + 0x5b, 0xca, 0x84, 0xf8, 0x55, 0xc1, 0x17, 0xcb, 0x30, 0x55, 0xc5, 0x70, 0x83, 0x45, + 0x7e, 0x1d, 0x14, 0x85, 0x7c, 0x2b, 0xf9, 0x41, 0xe8, 0x20, 0x73, 0x5c, 0x58, 0x8a, + 0xae, 0x6f, 0x66, 0x45, 0xdc, 0x3f, 0xbd, 0x30, 0x65, 0xab, 0xa1, 0x7f, 0xd2, 0x48, + 0x2a, 0x1b, 0x37, 0xb2, 0xf3, 0x88, 0x07, 0x5e, 0x46, 0xbb, 0x9d, 0x37, 0x27, 0xcc, + 0x73, 0xdb, 0xae, 0x0e, 0x96, 0xa8, 0x44, 0x5f, 0xda, 0x8f, 0x87, 0x64, 0xf9, 0x68, + 0x0b, 0xf6, 0xc5, 0x91, 0xa8, 0x48, 0x10, 0xfa, 0x0c, 0x1b, 0x5a, 0x2f, 0x2a, 0xa9, + 0xad, 0xbb, 0x88, 0x64, 0x22, 0x31, 0x72, 0x1e, 0xd6, 0xea, 0x12, 0x16, 0xab, 0x9b, + 0xfa, 0x0e, 0x12, 0x4c, 0xe4, 0x74, 0x94, 0x44, 0x53, 0x4d, 0x68, 0x70, 0x19, 0x74, + 0x60, 0xf7, 0x49, 0xef, 0xb0, 0x28, 0x8f, 0x96, 0x28, 0x3f, 0xc9, 0x37, 0xef, 0xbb, + 0x14, 0x59, 0xaa, 0x73, 0xc2, 0x7b, 0x6b, 0x2b, 0x5c, 0x57, 0x7d, 0x46, 0x60, 0xf9, + 0x8e, 0x81, 0x8c, 0xaa, 0xad, 0xbe, 0x45, 0x4e, 0xcd, 0x16, 0xc1, 0xd8, 0xa9, 0x9b, + 0x77, 0x97, 0x8e, 0x93, 0xd6, 0x9d, 0xcb, 0x8b, 0xf0, 0xe8, 0x4a, 0x0a, 0x91, 0x3f, + 0x55, 0xcc, 0x16, 0x50, 0xc2, 0xb9, 0x2d, 0x4c, 0x9d, 0xcd, 0xb1, 0x2e, 0xe2, 0x36, + 0x7e, 0xd9, 0x79, 0xb9, 0x53, 0x5f, 0xe1, 0x5c, 0x87, 0xd1, 0x7f, 0x37, 0xa3, 0x24, + 0x84, 0x7f, 0x16, 0x45, 0x39, 0x75, 0x7d, 0x83, 0x00, 0x87, 0xf6, 0x39, 0xeb, 0x6c, + 0x3e, 0xfb, 0x8d, 0xa4, 0xff, 0xa5, 0xd7, 0xca, 0x58, 0x34, 0x4d, 0x65, 0x81, 0x76, + 0x64, 0xa7, 0x4e, 0xaf, 0xa1, 0xa4, 0x7f, 0x69, 0xf1, 0xc8, 0x10, 0x6b, 0x6f, 0x5f, + 0x96, 0x4f, 0x4c, 0x73, 0xed, 0xed, 0xb1, 0xe1, 0x25, 0xde, 0xb2, 0x28, 0xc5, 0x62, + 0xfd, 0xc1, 0x87, 0x41, 0x41, 0xa9, 0x7c, 0x62, 0x58, 0x16, 0xc0, 0xcf, 0xeb, 0x83, + 0x84, 0x28, 0x7f, 0x6b, 0x2d, 0x5f, 0xa1, 0x81, 0x89, 0xe1, 0x4f, 0x91, 0xdf, 0x72, + 0x4e, 0x59, 0x80, 0x45, 0x8c, 0x51, 0xfb, 0x1c, 0xd8, 0x46, + ], + ock: [ + 0x57, 0x97, 0xef, 0x48, 0x70, 0xb0, 0x86, 0x50, 0xfa, 0x99, 0xad, 0xae, 0x58, 0x85, + 0x19, 0x9e, 0x3b, 0x04, 0x4b, 0x2a, 0x0a, 0x8c, 0xe1, 0x61, 0x43, 0x42, 0xb5, 0xdc, + 0xb2, 0x8e, 0x6e, 0x09, + ], + op: [ + 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, + 0xe9, 0xdc, 0xa5, 0x1a, 0x42, 0x58, 0xf3, 0xae, 0x72, 0x23, 0x87, 0xf6, 0xd0, 0xdf, + 0xf4, 0x1a, 0x1f, 0x88, 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, + 0xa1, 0xe6, 0xfb, 0x57, 0xe2, 0xb8, 0x01, 0xb4, 0x49, 0x6f, 0xbd, 0xd4, 0xc0, 0xa8, + 0xb9, 0x5f, 0xc8, 0x7e, 0xa7, 0x37, 0x3e, 0x2f, + ], + c_out: [ + 0xb8, 0xb4, 0x6c, 0x7e, 0xc4, 0xa8, 0x74, 0x2a, 0x22, 0xd3, 0xcd, 0x11, 0x74, 0x1c, + 0x23, 0x04, 0x22, 0x1c, 0xa5, 0x97, 0x29, 0x4e, 0x08, 0xa4, 0xc7, 0x1b, 0x17, 0xc7, + 0x26, 0x5d, 0x4d, 0xa7, 0x7c, 0xfe, 0x84, 0xb8, 0x7e, 0x76, 0xed, 0xaa, 0xec, 0xc2, + 0x24, 0xb8, 0x36, 0xde, 0x22, 0x4c, 0x73, 0x58, 0x13, 0x19, 0xa0, 0xba, 0x27, 0x88, + 0xdb, 0xf8, 0x3b, 0xcf, 0x47, 0xa4, 0x8e, 0xeb, 0x02, 0xb4, 0x3a, 0x18, 0x02, 0x7b, + 0x8f, 0x59, 0x11, 0x65, 0xc2, 0x86, 0xe8, 0xb6, 0x54, 0xec, + ], + }, + TestVector { + incoming_viewing_key: [ + 0xa6, 0x68, 0x13, 0x52, 0xa3, 0x52, 0x26, 0x91, 0x10, 0x0f, 0x53, 0xfc, 0x34, 0xab, + 0x73, 0x32, 0x8a, 0xf1, 0xb9, 0xf3, 0xa4, 0xa0, 0x6d, 0xbd, 0x3a, 0x14, 0x99, 0x67, + 0x09, 0xe6, 0xf2, 0x84, 0x31, 0xee, 0x72, 0xf2, 0x69, 0xae, 0xd7, 0x5d, 0x36, 0x34, + 0x89, 0x36, 0x90, 0x5e, 0xbb, 0x91, 0x80, 0x7d, 0x74, 0xd5, 0x0c, 0xb2, 0x7f, 0xcd, + 0x8b, 0x4f, 0xb6, 0xf4, 0x48, 0xc3, 0x62, 0x03, + ], + ovk: [ + 0x78, 0xf1, 0x45, 0xea, 0x29, 0xd2, 0x71, 0xb9, 0x40, 0xc6, 0x99, 0x41, 0xe4, 0xc3, + 0xfd, 0x2d, 0x71, 0xf3, 0xb1, 0x90, 0x69, 0x0e, 0xe1, 0x6f, 0x5d, 0x14, 0xac, 0x22, + 0x24, 0xe6, 0xfc, 0x89, + ], + default_d: [ + 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, + ], + default_pk_d: [ + 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, + 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, + 0x3a, 0x56, 0x6a, 0xaa, + ], + v: 15093716717054627455, + rseed: [ + 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, + 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, + 0x24, 0x57, 0x16, 0xa4, + ], + asset: [ + 0x96, 0x86, 0xaa, 0x36, 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, + 0xab, 0xcf, 0xac, 0x88, 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, + 0x07, 0x2d, 0x2d, 0x18, + ], + memo: [ + 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, + 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, + 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, + 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, + 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, + 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, + 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, + 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, + 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, + 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, + 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, + 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, + 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, + 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, + 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, + 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, + 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, + 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, + 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, + 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, + 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, + 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, + 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, + 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, + 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, + 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, + 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, + 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, + 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, + 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, + 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, + 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, + 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, + 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, + 0x70, 0xe0, 0x90, 0x3a, 0xf6, 0xe1, 0x70, 0x81, 0xd5, 0x81, 0x8e, 0x88, 0xb1, 0x4e, + 0x4f, 0x60, 0x1b, 0x8c, 0x06, 0x3e, 0x3f, 0x43, 0x87, 0xff, 0xa2, 0x32, 0x2a, 0x51, + 0x81, 0x90, 0x9f, 0x09, 0x80, 0xd6, 0x89, 0xde, + ], + cv_net: [ + 0x91, 0x6d, 0xc3, 0x82, 0x2a, 0x4e, 0x3b, 0xb4, 0x1f, 0xa8, 0x33, 0xc2, 0x73, 0xa9, + 0xd3, 0x7d, 0x17, 0x17, 0xa4, 0x8d, 0x8f, 0x00, 0x6c, 0x1f, 0xf5, 0x86, 0x21, 0x46, + 0x29, 0x55, 0x39, 0x1c, + ], + rho: [ + 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, + 0xd0, 0x28, 0x44, 0x22, 0x13, 0x50, 0x86, 0x4e, 0xed, 0x56, 0x3d, 0xab, 0x30, 0x22, + 0x7f, 0x28, 0x4b, 0x2e, + ], + cmx: [ + 0x89, 0xe6, 0xa2, 0xb9, 0x70, 0x84, 0xe3, 0xd3, 0x34, 0x4f, 0xee, 0xb4, 0x64, 0x65, + 0x05, 0x72, 0x51, 0xb1, 0x9d, 0xa0, 0xce, 0xdf, 0x79, 0x71, 0x94, 0xc5, 0x97, 0xf9, + 0xf7, 0x7e, 0xf2, 0x1f, + ], + esk: [ + 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, 0x02, 0xf5, 0x10, 0xe9, + 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, 0xc4, 0x69, 0x2d, 0x0c, + 0x1b, 0x30, 0x33, 0x01, + ], + ephemeral_key: [ + 0x27, 0xcb, 0x40, 0x68, 0x0f, 0xb1, 0xd9, 0x19, 0x64, 0x6e, 0x74, 0x20, 0xe6, 0xa8, + 0xb5, 0x20, 0xe1, 0x9a, 0x17, 0x3f, 0x1e, 0x79, 0x4d, 0x2b, 0x49, 0x2b, 0xfa, 0xbb, + 0x83, 0xce, 0x6c, 0xa0, + ], + shared_secret: [ + 0x1c, 0xd0, 0x66, 0x91, 0x6c, 0x19, 0xfa, 0x33, 0x69, 0xaa, 0x3c, 0x6a, 0x53, 0x76, + 0x97, 0xf4, 0xb4, 0x26, 0x44, 0xda, 0x20, 0xca, 0x46, 0x79, 0x93, 0x2b, 0x7c, 0x90, + 0x5f, 0x2d, 0x69, 0x00, + ], + k_enc: [ + 0xce, 0x9d, 0x22, 0x0d, 0x3a, 0xfe, 0xc6, 0x23, 0x21, 0xdd, 0xf1, 0x97, 0xa6, 0x36, + 0xdc, 0xb3, 0x45, 0x58, 0x83, 0xb7, 0x35, 0x82, 0x8c, 0x65, 0xe7, 0x16, 0x6c, 0x15, + 0xd8, 0xcc, 0xfc, 0xf9, + ], + p_enc: [ + 0x03, 0x11, 0x6e, 0x79, 0x94, 0x55, 0xae, 0xa1, 0x91, 0x8f, 0xbf, 0xd4, 0x7f, 0x8e, + 0x6a, 0x5c, 0x62, 0xa7, 0x77, 0xd1, 0x7e, 0x62, 0x25, 0x8d, 0x65, 0xa1, 0x92, 0x15, + 0x7c, 0xdf, 0x2e, 0xc3, 0x21, 0x40, 0x7f, 0x68, 0x2f, 0x5e, 0xec, 0x6a, 0x32, 0x97, + 0xab, 0x20, 0xb7, 0x06, 0x1c, 0x62, 0x24, 0x57, 0x16, 0xa4, 0x96, 0x86, 0xaa, 0x36, + 0x36, 0xbd, 0x37, 0x5b, 0xd3, 0x13, 0x6b, 0xee, 0x0b, 0xda, 0xab, 0xcf, 0xac, 0x88, + 0x1b, 0xc7, 0x01, 0x81, 0x27, 0x21, 0xe6, 0xfb, 0x75, 0xaa, 0x07, 0x2d, 0x2d, 0x18, + 0xff, 0x4f, 0x71, 0xfb, 0xfc, 0x34, 0xc7, 0x9b, 0x44, 0xe0, 0x9e, 0x42, 0x12, 0xac, + 0x26, 0x53, 0xf6, 0xc4, 0x03, 0x64, 0x3e, 0x1c, 0x5b, 0x9a, 0xd1, 0x34, 0xd8, 0x9c, + 0x68, 0x0b, 0x70, 0x72, 0x83, 0xaf, 0x54, 0x32, 0x6f, 0xc4, 0xf8, 0x4d, 0x6a, 0x58, + 0x29, 0xa0, 0xad, 0x48, 0x30, 0x80, 0x6c, 0x05, 0x75, 0x84, 0x92, 0xcd, 0x6a, 0xc4, + 0x6b, 0xa0, 0x1a, 0x2b, 0x37, 0x22, 0xb5, 0xe4, 0xcd, 0xaf, 0xbb, 0x3f, 0x36, 0x78, + 0x5f, 0x42, 0x4a, 0xf0, 0x44, 0xda, 0xc5, 0xdb, 0x5f, 0x7d, 0xf8, 0x39, 0xeb, 0x63, + 0xc0, 0xc1, 0x7d, 0x8b, 0x0c, 0x79, 0xdb, 0x86, 0x30, 0x94, 0x20, 0x15, 0xbe, 0x13, + 0xf7, 0x9a, 0xf6, 0xf4, 0x3e, 0x5a, 0xb0, 0x77, 0x81, 0x14, 0x79, 0x8f, 0x44, 0x22, + 0x58, 0xee, 0xdc, 0x43, 0x6f, 0xcc, 0x38, 0x6b, 0x36, 0xb5, 0x7e, 0x19, 0x17, 0xd7, + 0x20, 0x17, 0x73, 0x66, 0xf4, 0x24, 0xb0, 0xa5, 0x4b, 0x0b, 0x60, 0xf4, 0xfb, 0x13, + 0x58, 0xc2, 0x0a, 0xa4, 0x1d, 0xc5, 0x02, 0xe1, 0xdd, 0x8a, 0x16, 0x33, 0xf3, 0xd8, + 0xe3, 0x27, 0x6b, 0x59, 0xe7, 0xd2, 0xc4, 0xe6, 0x24, 0xa6, 0xf5, 0x36, 0x95, 0xbc, + 0xaf, 0x24, 0x7e, 0x36, 0x48, 0x3f, 0x13, 0xb2, 0x04, 0x42, 0x22, 0x37, 0xfc, 0x6a, + 0xb3, 0xeb, 0xa0, 0x2f, 0xc4, 0x14, 0x2b, 0x42, 0x97, 0xeb, 0xb5, 0x68, 0x3d, 0xb8, + 0xd2, 0x43, 0x19, 0x70, 0x6a, 0xd2, 0x6a, 0xaf, 0xd8, 0x1c, 0x53, 0xb7, 0x40, 0xf3, + 0x45, 0x43, 0xa6, 0xb3, 0xe9, 0xf5, 0xbb, 0x7d, 0x5c, 0x49, 0xe8, 0xc3, 0x7f, 0x61, + 0x49, 0x21, 0x25, 0x4f, 0x32, 0x12, 0x39, 0x4c, 0x79, 0x7d, 0x1c, 0xee, 0x78, 0x99, + 0xb7, 0xb4, 0xb6, 0x5b, 0x59, 0xb7, 0x34, 0x2f, 0x92, 0x53, 0x1c, 0x1d, 0x59, 0xe1, + 0x79, 0x70, 0xb7, 0x31, 0x74, 0x14, 0x43, 0x8c, 0xd8, 0x0b, 0xd0, 0xf9, 0xa6, 0x7c, + 0x9b, 0x9e, 0x55, 0x2f, 0x01, 0x3c, 0x11, 0x5a, 0x95, 0x4f, 0x35, 0xe0, 0x61, 0x6c, + 0x68, 0xd4, 0x31, 0x63, 0xd3, 0x34, 0xda, 0xc3, 0x82, 0x70, 0x33, 0xe5, 0xad, 0x84, + 0x88, 0xbf, 0xd9, 0xc4, 0xbb, 0xbe, 0x8f, 0x59, 0x35, 0xc6, 0xc5, 0xea, 0x04, 0xc3, + 0xad, 0x49, 0xc7, 0x47, 0xa9, 0xe7, 0x23, 0x1b, 0xcd, 0x7d, 0x16, 0x21, 0x5e, 0x6e, + 0x80, 0x73, 0x7d, 0x6b, 0x54, 0xfe, 0xc8, 0xb8, 0x84, 0x02, 0xf0, 0x47, 0x52, 0x45, + 0xe1, 0x74, 0xa7, 0x45, 0xb8, 0x31, 0xf8, 0xfe, 0x03, 0xa7, 0x6f, 0xb9, 0xce, 0xca, + 0x4d, 0x22, 0xb7, 0x83, 0xc3, 0x28, 0xc6, 0x91, 0x5c, 0x43, 0x40, 0x50, 0x64, 0xae, + 0x56, 0xbc, 0x89, 0xe6, 0x4d, 0x15, 0x78, 0xe4, 0xd3, 0xa3, 0x4b, 0xb9, 0x55, 0x91, + 0xea, 0xf1, 0xd3, 0xda, 0x02, 0xa4, 0x54, 0x9f, 0xa8, 0x0d, 0xb0, 0xff, 0x7c, 0xb0, + 0x39, 0x93, 0xb6, 0x8a, 0xe1, 0x5a, 0x30, 0xe8, 0x79, 0x49, 0xaa, 0x08, 0x0e, 0x94, + 0xab, 0xde, 0x68, 0x89, 0x8c, 0x33, 0x92, 0xa2, 0x17, 0xd6, 0x49, 0x61, 0x6b, 0xbe, + 0x73, 0x9b, 0x13, 0xd1, 0x4d, 0xf0, 0x3f, 0xf2, 0x76, 0x71, 0x48, 0x9b, 0xe0, 0xb4, + 0xbe, 0xba, 0xaf, 0xa7, 0xd1, 0xe6, 0x39, 0xd5, 0xb3, 0xe9, 0x94, 0xff, 0xb6, 0xb7, + 0xa2, 0x09, 0xf6, 0xad, 0xfe, 0x8d, 0x1e, 0x5c, 0xcf, 0x01, 0x0c, 0x19, 0x16, 0x8a, + 0xeb, 0x18, 0xaa, 0x9d, 0x68, 0x7e, 0x24, 0xad, 0xc0, 0xb1, 0x13, 0x5c, 0x70, 0xc9, + 0x70, 0xe0, 0x90, 0x3a, 0xf6, 0xe1, 0x70, 0x81, 0xd5, 0x81, 0x8e, 0x88, 0xb1, 0x4e, + 0x4f, 0x60, 0x1b, 0x8c, 0x06, 0x3e, 0x3f, 0x43, 0x87, 0xff, 0xa2, 0x32, 0x2a, 0x51, + 0x81, 0x90, 0x9f, 0x09, 0x80, 0xd6, 0x89, 0xde, + ], + c_enc: [ + 0xb1, 0x69, 0x64, 0x77, 0xe6, 0x58, 0xb6, 0xf8, 0xe2, 0x4e, 0x02, 0x55, 0x52, 0xb4, + 0x8d, 0xd4, 0x84, 0x58, 0xf2, 0xcd, 0x75, 0x70, 0xc0, 0xe8, 0xce, 0xc4, 0xed, 0x4c, + 0xf7, 0x9b, 0xd5, 0xb6, 0x9e, 0xa8, 0x54, 0x12, 0x3b, 0x4e, 0xaf, 0x97, 0x8b, 0x14, + 0x2e, 0xb3, 0xef, 0x53, 0xaa, 0xfc, 0x78, 0x90, 0xdd, 0xa2, 0x8a, 0xfa, 0x25, 0xf1, + 0x45, 0xc8, 0xb9, 0x7f, 0x7b, 0x94, 0x50, 0xc1, 0xd5, 0xe0, 0xc3, 0x7d, 0xaf, 0x5e, + 0xd4, 0xec, 0xd9, 0xb6, 0x3d, 0xbc, 0xd2, 0x15, 0x11, 0x23, 0x13, 0x9b, 0xbc, 0x2b, + 0x65, 0x1a, 0x8f, 0x69, 0xcf, 0xbf, 0xb7, 0xcb, 0x60, 0x44, 0x78, 0xf3, 0xf2, 0x64, + 0xd9, 0xdd, 0x75, 0xcf, 0x31, 0x9e, 0x3e, 0xcd, 0xf5, 0xb3, 0x34, 0x26, 0x54, 0x85, + 0x7c, 0x52, 0xa1, 0xfc, 0x61, 0x40, 0x55, 0xa2, 0x46, 0xf5, 0x26, 0x3e, 0x85, 0x36, + 0x83, 0xef, 0x54, 0x41, 0x3b, 0xac, 0x99, 0x1a, 0xe6, 0x35, 0x01, 0x50, 0xe1, 0x34, + 0x52, 0xa3, 0xa6, 0x20, 0xc5, 0x3f, 0x80, 0xda, 0xcc, 0x7a, 0xf0, 0x59, 0x26, 0xd9, + 0xc5, 0x9a, 0x94, 0xe4, 0x78, 0x9a, 0xcc, 0x68, 0xd8, 0x51, 0x05, 0x6b, 0x75, 0xa7, + 0x4e, 0x2e, 0x1b, 0x38, 0xbf, 0xcb, 0x6d, 0xba, 0xab, 0x37, 0xa3, 0x8a, 0xe0, 0x2c, + 0x9c, 0x35, 0x25, 0x9e, 0x52, 0x84, 0xe4, 0xfe, 0x83, 0xdd, 0xb2, 0x29, 0x24, 0xa1, + 0xc4, 0x0a, 0xa2, 0x5e, 0xd1, 0xf5, 0xc0, 0x6d, 0xa1, 0x58, 0x31, 0xf0, 0x41, 0x50, + 0xa3, 0x7c, 0x1b, 0xa3, 0xd1, 0x17, 0x04, 0x93, 0xca, 0x29, 0xf3, 0x43, 0x4a, 0xfa, + 0x06, 0x9b, 0x46, 0xaf, 0xdc, 0x87, 0x0a, 0x29, 0x6f, 0xdc, 0x0e, 0xb6, 0x1b, 0x55, + 0x70, 0x77, 0xa1, 0xda, 0x1f, 0xe8, 0x22, 0xb6, 0xce, 0x24, 0x7c, 0x8e, 0x19, 0x9f, + 0xc4, 0x85, 0x14, 0x6f, 0x38, 0x4a, 0xcf, 0x5c, 0x52, 0x69, 0x7e, 0xfa, 0xcc, 0x5b, + 0xfe, 0x42, 0x02, 0xe8, 0x5f, 0x06, 0x4b, 0xc8, 0xe1, 0x2e, 0xee, 0x39, 0x79, 0x6d, + 0xfd, 0x13, 0x99, 0xb1, 0xc1, 0xe8, 0xc7, 0x4b, 0x5e, 0xc3, 0xc3, 0x1d, 0x2c, 0xfa, + 0x44, 0x87, 0x02, 0x5c, 0xeb, 0x5d, 0xb3, 0x55, 0x9d, 0x4b, 0x7b, 0xac, 0x02, 0x73, + 0xf1, 0x33, 0x51, 0xd2, 0xd1, 0x3c, 0xec, 0x0a, 0x44, 0x8c, 0x00, 0x11, 0x09, 0x45, + 0x2c, 0x40, 0x92, 0xc8, 0x11, 0x91, 0xa0, 0xda, 0xa9, 0x79, 0xe2, 0x6a, 0x96, 0x24, + 0xe4, 0x0c, 0xa4, 0xac, 0xcb, 0x63, 0x46, 0xaa, 0xe1, 0x88, 0xca, 0x09, 0x39, 0xdd, + 0x9f, 0x6b, 0x6e, 0x45, 0xe4, 0x1b, 0xca, 0xeb, 0xdc, 0x1d, 0xa8, 0x01, 0xcc, 0xd4, + 0xdc, 0x93, 0x32, 0x26, 0x6f, 0xb3, 0xeb, 0x23, 0x7b, 0x07, 0x72, 0x45, 0xa7, 0x91, + 0xec, 0xb4, 0x0e, 0x5c, 0x40, 0x56, 0xad, 0xd6, 0xb1, 0xb5, 0xf7, 0xf8, 0xfa, 0x10, + 0x4f, 0xba, 0x61, 0x3e, 0xd9, 0x29, 0xe1, 0xfa, 0xd2, 0x26, 0x47, 0x50, 0x35, 0xb6, + 0x1a, 0x9f, 0x85, 0xaf, 0xba, 0xfb, 0x16, 0x6b, 0x24, 0xc2, 0x4d, 0x2c, 0x28, 0x93, + 0x7b, 0x17, 0x70, 0xba, 0x26, 0x9c, 0x15, 0xeb, 0x2d, 0x9b, 0xdc, 0x2b, 0x83, 0xea, + 0xd8, 0xa0, 0x1d, 0xdb, 0x11, 0x08, 0x3b, 0x13, 0xd6, 0x2d, 0x57, 0x2c, 0xf7, 0x8d, + 0x5c, 0xba, 0x6f, 0x36, 0x52, 0xca, 0xc4, 0xd2, 0x4c, 0x71, 0xc5, 0x47, 0x27, 0x26, + 0x24, 0xc0, 0x78, 0xe0, 0xb9, 0x69, 0x68, 0xfe, 0x09, 0xd8, 0x3e, 0xf7, 0x30, 0x20, + 0x62, 0xbb, 0x5d, 0x3a, 0x2c, 0xcf, 0x73, 0x4e, 0x0f, 0xd3, 0x51, 0x01, 0xfd, 0x58, + 0x64, 0x73, 0x3f, 0x44, 0xd0, 0x75, 0xc3, 0x8b, 0x73, 0xf6, 0xbf, 0xb8, 0xc3, 0x9c, + 0x7b, 0x6b, 0x3d, 0xbc, 0xd1, 0x9a, 0x05, 0x89, 0x91, 0x86, 0x37, 0xf7, 0x5b, 0xbe, + 0x40, 0x15, 0x7b, 0x80, 0xe5, 0x9e, 0x55, 0x58, 0x50, 0x28, 0xa5, 0xec, 0x20, 0x1e, + 0x00, 0x8f, 0xf6, 0xf5, 0x12, 0xe2, 0x53, 0xcc, 0x9a, 0xcf, 0x62, 0x7d, 0x94, 0x35, + 0xdb, 0x6b, 0x14, 0xb9, 0x82, 0x48, 0x79, 0xf4, 0xe4, 0x0a, 0x36, 0xd5, 0xec, 0x94, + 0x2b, 0xff, 0x04, 0xfd, 0x0b, 0xb8, 0x0c, 0x3e, 0xdd, 0xb7, 0xb2, 0x0a, 0x11, 0x6b, + 0xa7, 0x0d, 0x84, 0x84, 0x6e, 0xc6, 0xd2, 0x52, 0x0f, 0xe7, 0x68, 0x89, 0x9e, 0xd5, + 0x27, 0xd3, 0x1d, 0x32, 0x19, 0x68, 0xde, 0xc1, 0x32, 0x7b, 0x81, 0xcc, 0x61, 0x89, + 0x8f, 0x2c, 0xc4, 0x5a, 0xeb, 0x43, 0x52, 0x9e, 0x7d, 0x08, + ], + ock: [ + 0x95, 0x83, 0xf1, 0x0f, 0xed, 0x70, 0xa4, 0x1e, 0x45, 0x8c, 0x65, 0x5c, 0xc0, 0x14, + 0xe2, 0x35, 0x5a, 0x7f, 0x99, 0xae, 0xbc, 0xfe, 0xf7, 0x4a, 0x55, 0x9a, 0xcd, 0x24, + 0x25, 0xfa, 0x21, 0xcf, + ], + op: [ + 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, + 0xcf, 0xfb, 0xb2, 0x98, 0xf8, 0xd5, 0x34, 0xc8, 0xd9, 0xd3, 0x11, 0xe4, 0xc6, 0x10, + 0x3a, 0x56, 0x6a, 0xaa, 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, + 0x02, 0xf5, 0x10, 0xe9, 0xeb, 0x09, 0xed, 0x76, 0xda, 0xbc, 0xfe, 0x2a, 0x69, 0x1c, + 0xc4, 0x69, 0x2d, 0x0c, 0x1b, 0x30, 0x33, 0x01, + ], + c_out: [ + 0xb8, 0x3b, 0x74, 0x5c, 0x9c, 0x0b, 0x04, 0xdd, 0xc7, 0xf1, 0x38, 0x16, 0x94, 0x38, + 0x99, 0x55, 0x3a, 0x30, 0x6a, 0x4a, 0xd0, 0xf2, 0xf5, 0x70, 0x92, 0x2a, 0x89, 0x9b, + 0xab, 0xb9, 0xda, 0xca, 0xd2, 0xbb, 0xc9, 0x5c, 0xf6, 0x5b, 0x73, 0x08, 0x55, 0x0d, + 0xce, 0xdb, 0x64, 0x9e, 0xf1, 0x5e, 0x0b, 0x1a, 0x09, 0x1f, 0xad, 0x5a, 0x93, 0x92, + 0xd0, 0x71, 0xb7, 0x5a, 0xb5, 0x1a, 0x7e, 0x35, 0x06, 0xad, 0x58, 0xd1, 0x71, 0x95, + 0xc9, 0x9f, 0x29, 0x8a, 0xc3, 0x14, 0xec, 0x05, 0xa6, 0x6a, + ], + }, + ] +} diff --git a/src/value.rs b/src/value.rs index dd3a5546d..b514e7a28 100644 --- a/src/value.rs +++ b/src/value.rs @@ -53,13 +53,14 @@ use pasta_curves::{ use rand::RngCore; use subtle::CtOption; -use crate::builder::Error; -use crate::note::AssetId; use crate::{ constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_R_BYTES}, primitives::redpallas::{self, Binding}, }; +use crate::builder::Error; +use crate::note::AssetId; + /// Maximum note value. pub const MAX_NOTE_VALUE: u64 = u64::MAX; diff --git a/tests/builder.rs b/tests/builder.rs index 312541ecf..3e7c416c6 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -6,7 +6,7 @@ use orchard::{ circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::ExtractedNoteCommitment, - note_encryption::OrchardDomain, + note_encryption_v3::OrchardDomainV3, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, Anchor, Bundle, Note, @@ -89,7 +89,7 @@ fn bundle_chain() { .actions() .iter() .find_map(|action| { - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); try_note_decryption(&domain, &ivk, action) }) .unwrap(); diff --git a/tests/zsa.rs b/tests/zsa.rs index 9aad802d5..fa41d48e4 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -7,7 +7,7 @@ use orchard::bundle::Authorized; use orchard::issuance::{verify_issue_bundle, IssueBundle, Signed, Unauthorized}; use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use orchard::note::{AssetId, ExtractedNoteCommitment}; -use orchard::note_encryption::OrchardDomain; +use orchard::note_encryption_v3::OrchardDomainV3; use orchard::tree::{MerkleHashOrchard, MerklePath}; use orchard::{ builder::Builder, @@ -204,7 +204,7 @@ fn create_native_note(keys: &Keychain) -> Note { .actions() .iter() .find_map(|action| { - let domain = OrchardDomain::for_action(action); + let domain = OrchardDomainV3::for_action(action); try_note_decryption(&domain, &PreparedIncomingViewingKey::new(&ivk), action) }) .unwrap(); From 4e4767789e675c1317dfbdd6ec70de1758cef37b Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 9 Feb 2023 12:44:25 +0100 Subject: [PATCH 18/92] Minimal API changes for Issuance in Client (#43) Make IVK::from_bytes public --- src/keys.rs | 5 ++++- src/primitives/redpallas.rs | 2 +- tests/zsa.rs | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index 65d464147..dc1d7d77b 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -277,7 +277,10 @@ impl IssuanceValidatingKey { <[u8; 32]>::from(&self.0) } - pub(crate) fn from_bytes(bytes: &[u8]) -> Option { + /// Constructs an Orchard issuance validating key from uniformly-random bytes. + /// + /// Returns `None` if the bytes do not correspond to a valid key. + pub fn from_bytes(bytes: &[u8]) -> Option { <[u8; 32]>::try_from(bytes) .ok() .and_then(check_structural_validity) diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index d19a05048..92fe165e4 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -22,7 +22,7 @@ pub type Binding = reddsa::orchard::Binding; impl SigType for Binding {} /// A RedPallas signing key. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct SigningKey(reddsa::SigningKey); impl From> for [u8; 32] { diff --git a/tests/zsa.rs b/tests/zsa.rs index fa41d48e4..9ddaaf7bd 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -74,11 +74,11 @@ fn prepare_keys() -> Keychain { fn sign_issue_bundle( unauthorized: IssueBundle, mut rng: OsRng, - isk: IssuanceAuthorizingKey, + isk: &IssuanceAuthorizingKey, ) -> IssueBundle { let sighash = unauthorized.commitment().into(); let proven = unauthorized.prepare(sighash); - proven.sign(&mut rng, &isk).unwrap() + proven.sign(&mut rng, isk).unwrap() } fn build_and_sign_bundle( @@ -159,7 +159,7 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { ) .is_ok()); - let issue_bundle = sign_issue_bundle(unauthorized, rng, keys.isk().clone()); + let issue_bundle = sign_issue_bundle(unauthorized, rng, keys.isk()); // Take notes from first action let notes = issue_bundle.get_all_notes(); From cbf0a3a651e00fd560c67da66e56a7d4c7083cea Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 14 Feb 2023 18:04:59 +0100 Subject: [PATCH 19/92] Circuit: Split_flag handling (#42) When split_flag is set, the following values are modified * v_net is equal to -v_new instead of v_old - v_new * cv_net is evaluated with this new value of v_net The following constraints are modified * (v_old - v_new = magnitude * sign) becomes (v_old * (1-split_flag) - v_new = magnitude * sign) to take into account the new value of v_net * nf_old = nf_old_pub is only checked when split_flag=0 * the new constraint asset_old = asset_new is always checked regardless of the value of split_flag --- Cargo.toml | 3 +- src/builder.rs | 17 +- src/circuit.rs | 164 +++++++- src/circuit_description | 647 ++++++++++++++++++++++---------- src/circuit_proof_test_case.bin | Bin 5154 -> 5154 bytes 5 files changed, 609 insertions(+), 222 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5461be1e..20a2ac0b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,8 @@ proptest = "1.0.0" zcash_note_encryption = { version = "0.2", features = ["pre-zip-212"] } [target.'cfg(unix)'.dev-dependencies] -pprof = { version = "0.9", features = ["criterion", "flamegraph"] } # MSRV 1.56 +# TODO: upgrade the pprof version once its inferno dependency respects all clippy lints +pprof = { version = "0.6", features = ["criterion", "flamegraph"] } # MSRV 1.56 [lib] bench = false diff --git a/src/builder.rs b/src/builder.rs index d420d742e..0a7f441c7 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -399,20 +399,14 @@ impl Builder { .cloned() .unwrap(); - // TODO: uncomment once the circuit is ready. // use the first spend to create split spend(s) or create a dummy if empty. - // let dummy_spend = spends.first().map_or_else( - // || SpendInfo::dummy(asset, &mut rng), - // |s| s.create_split_spend(), - // ); - // spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); - - // Extend the spends and recipients with dummy values. - spends.extend( - iter::repeat_with(|| SpendInfo::dummy(asset, &mut rng)) - .take(num_actions - num_spends), + let dummy_spend = spends.first().map_or_else( + || SpendInfo::dummy(asset, &mut rng), + |s| s.create_split_spend(), ); + spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); + // Extend the recipients with dummy values. recipients.extend( iter::repeat_with(|| RecipientInfo::dummy(&mut rng, asset)) .take(num_actions - num_recipients), @@ -424,6 +418,7 @@ impl Builder { spends.shuffle(&mut rng); recipients.shuffle(&mut rng); + assert_eq!(spends.len(), recipients.len()); pre_actions.extend( spends .into_iter() diff --git a/src/circuit.rs b/src/circuit.rs index 7797f563e..e6c9f6e09 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -36,7 +36,7 @@ use crate::{ note::{ commitment::{NoteCommitTrapdoor, NoteCommitment}, nullifier::Nullifier, - ExtractedNoteCommitment, Note, + AssetId, ExtractedNoteCommitment, Note, }, primitives::redpallas::{SpendAuth, VerificationKey}, spec::NonIdentityPallasPoint, @@ -56,7 +56,7 @@ use halo2_gadgets::{ MerklePath, }, }, - utilities::lookup_range_check::LookupRangeCheckConfig, + utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig}, }; mod commit_ivk; @@ -109,6 +109,7 @@ pub struct Circuit { pub(crate) psi_old: Value, pub(crate) rcm_old: Value, pub(crate) cm_old: Value, + pub(crate) asset_old: Value, pub(crate) alpha: Value, pub(crate) ak: Value, pub(crate) nk: Value, @@ -118,7 +119,9 @@ pub struct Circuit { pub(crate) v_new: Value, pub(crate) psi_new: Value, pub(crate) rcm_new: Value, + pub(crate) asset_new: Value, pub(crate) rcv: Value, + pub(crate) split_flag: Value, } impl Circuit { @@ -172,6 +175,7 @@ impl Circuit { psi_old: Value::known(psi_old), rcm_old: Value::known(rcm_old), cm_old: Value::known(spend.note.commitment()), + asset_old: Value::known(spend.note.asset()), alpha: Value::known(alpha), ak: Value::known(spend.fvk.clone().into()), nk: Value::known(*spend.fvk.nk()), @@ -181,7 +185,9 @@ impl Circuit { v_new: Value::known(output_note.value()), psi_new: Value::known(psi_new), rcm_new: Value::known(rcm_new), + asset_new: Value::known(output_note.asset()), rcv: Value::known(rcv), + split_flag: Value::known(spend.split_flag), } } } @@ -209,10 +215,12 @@ impl plonk::Circuit for Circuit { meta.advice_column(), ]; - // Constrain v_old - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - // Either v_old = 0, or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Constrain split_flag to be boolean + // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + // Constrain v_old = 0 or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). + // Constrain split_flag = 1 or nf_old = nf_old_pub let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -227,17 +235,25 @@ impl plonk::Circuit for Circuit { let enable_spends = meta.query_advice(advices[6], Rotation::cur()); let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); + let split_flag = meta.query_advice(advices[8], Rotation::cur()); + + let nf_old = meta.query_advice(advices[9], Rotation::cur()); + let nf_old_pub = meta.query_advice(advices[0], Rotation::next()); + let one = Expression::Constant(pallas::Base::one()); Constraints::with_selector( q_orchard, [ + ("bool_check split_flag", bool_check(split_flag.clone())), ( - "v_old - v_new = magnitude * sign", - v_old.clone() - v_new.clone() - magnitude * sign, + "v_old * (1 - split_flag) - v_new = magnitude * sign", + v_old.clone() * (one.clone() - split_flag.clone()) + - v_new.clone() + - magnitude * sign, ), ( - "Either v_old = 0, or root = anchor", + "v_old = 0 or root = anchor", v_old.clone() * (root - anchor), ), ( @@ -246,7 +262,11 @@ impl plonk::Circuit for Circuit { ), ( "v_new = 0 or enable_outputs = 1", - v_new * (one - enable_outputs), + v_new * (one.clone() - enable_outputs), + ), + ( + "split_flag = 1 or nf_old = nf_old_pub", + (one - split_flag) * (nf_old - nf_old_pub), ), ], ) @@ -455,6 +475,23 @@ impl plonk::Circuit for Circuit { (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) }; + // Verify that asset_old and asset_new are equals + { + let asset_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset_old"), + self.asset_old + .map(|asset_old| asset_old.cv_base().to_affine()), + )?; + let asset_new = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "asset equality"), + self.asset_new + .map(|asset_new| asset_new.cv_base().to_affine()), + )?; + asset_old.constrain_equal(layouter.namespace(|| "asset equality"), &asset_new)?; + } + // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). let root = { let path = self @@ -474,7 +511,17 @@ impl plonk::Circuit for Circuit { let v_net_magnitude_sign = { // Witness the magnitude and sign of v_net = v_old - v_new let v_net_magnitude_sign = { - let v_net = self.v_old - self.v_new; + // v_net is equal to + // (-v_new) if split_flag = true + // v_old - v_new if split_flag = false + let v_net = self.split_flag.and_then(|split_flag| { + if split_flag { + Value::known(crate::value::NoteValue::zero()) - self.v_new + } else { + self.v_old - self.v_new + } + }); + let magnitude_sign = v_net.map(|v_net| { let (magnitude, sign) = v_net.magnitude_sign(); @@ -541,9 +588,6 @@ impl plonk::Circuit for Circuit { nk.clone(), )?; - // Constrain nf_old to equal public input - layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; - nf_old }; @@ -745,6 +789,27 @@ impl plonk::Circuit for Circuit { 0, )?; + region.assign_advice( + || "split_flag", + config.advices[8], + 0, + || { + self.split_flag + .map(|split_flag| pallas::Base::from(split_flag as u64)) + }, + )?; + + nf_old + .inner() + .copy_advice(|| "nf_old", &mut region, config.advices[9], 0)?; + region.assign_advice_from_instance( + || "nf_old pub", + config.primary, + NF_OLD, + config.advices[0], + 1, + )?; + config.q_orchard.enable(&mut region, 0) }, )?; @@ -968,6 +1033,7 @@ mod tests { use rand::{rngs::OsRng, RngCore}; use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; + use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; use crate::note::AssetId; use crate::{ keys::SpendValidatingKey, @@ -1008,6 +1074,7 @@ mod tests { psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), cm_old: Value::known(spent_note.commitment()), + asset_old: Value::known(spent_note.asset()), alpha: Value::known(alpha), ak: Value::known(ak), nk: Value::known(nk), @@ -1017,7 +1084,9 @@ mod tests { v_new: Value::known(output_note.value()), psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + asset_new: Value::known(output_note.asset()), rcv: Value::known(rcv), + split_flag: Value::known(false), }, Instance { anchor, @@ -1087,6 +1156,74 @@ mod tests { assert_eq!(proof.0.len(), expected_proof_size); } + #[test] + fn test_not_equal_asset_ids() { + use halo2_proofs::dev::{ + metadata::Column, metadata::Region, FailureLocation, VerifyFailure, + }; + use halo2_proofs::plonk::Any::Advice; + + let mut rng = OsRng; + + let (mut circuit, instance) = generate_circuit_instance(&mut rng); + + // We would like to test that if the asset of the spent note (called asset_old) and the + // asset of the output note (called asset_new) are not equal, the proof is not verified. + // To do that, we attribute a random value to asset_new. + let random_asset_id = { + let sk = SpendingKey::random(&mut rng); + let isk = IssuanceAuthorizingKey::from(&sk); + let ik = IssuanceValidatingKey::from(&isk); + let asset_descr = "zsa_asset"; + AssetId::derive(&ik, asset_descr) + }; + circuit.asset_new = Value::known(random_asset_id); + + assert_eq!( + MockProver::run( + K, + &circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect() + ) + .unwrap() + .verify(), + Err(vec![ + VerifyFailure::Permutation { + column: Column::from((Advice, 0)), + location: FailureLocation::InRegion { + region: Region::from((9, "witness non-identity point".to_string())), + offset: 0 + } + }, + VerifyFailure::Permutation { + column: Column::from((Advice, 0)), + location: FailureLocation::InRegion { + region: Region::from((10, "witness non-identity point".to_string())), + offset: 0 + } + }, + VerifyFailure::Permutation { + column: Column::from((Advice, 1)), + location: FailureLocation::InRegion { + region: Region::from((9, "witness non-identity point".to_string())), + offset: 0 + } + }, + VerifyFailure::Permutation { + column: Column::from((Advice, 1)), + location: FailureLocation::InRegion { + region: Region::from((10, "witness non-identity point".to_string())), + offset: 0 + } + } + ]) + ); + } + #[test] fn serialized_proof_test_case() { use std::io::{Read, Write}; @@ -1194,6 +1331,7 @@ mod tests { psi_old: Value::unknown(), rcm_old: Value::unknown(), cm_old: Value::unknown(), + asset_old: Value::unknown(), alpha: Value::unknown(), ak: Value::unknown(), nk: Value::unknown(), @@ -1203,7 +1341,9 @@ mod tests { v_new: Value::unknown(), psi_new: Value::unknown(), rcm_new: Value::unknown(), + asset_new: Value::unknown(), rcv: Value::unknown(), + split_flag: Value::unknown(), }; halo2_proofs::dev::CircuitLayout::default() .show_labels(false) diff --git a/src/circuit_description b/src/circuit_description index 8bb3759ed..66bdfeadc 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -12,6 +12,118 @@ PinnedVerificationKey { num_instance_columns: 1, num_selectors: 56, gates: [ + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), Product( Product( Product( @@ -102,13 +214,29 @@ PinnedVerificationKey { ), Sum( Sum( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Negated( Advice { query_index: 1, @@ -479,6 +607,129 @@ PinnedVerificationKey { ), ), ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 10, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), Product( Product( Product( @@ -687,7 +938,7 @@ PinnedVerificationKey { Product( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -696,7 +947,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000400, ), Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -1121,7 +1372,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -1283,7 +1534,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -1346,7 +1597,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -1757,7 +2008,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -1880,7 +2131,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -1901,7 +2152,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -2043,7 +2294,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -2164,7 +2415,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -2185,7 +2436,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -2277,7 +2528,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -2377,7 +2628,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -2477,7 +2728,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -2577,7 +2828,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -2716,7 +2967,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -2845,7 +3096,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -2954,14 +3205,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -2970,7 +3221,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -2981,14 +3232,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -2997,7 +3248,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -3007,7 +3258,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -3121,7 +3372,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -3337,7 +3588,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -3363,7 +3614,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -3581,7 +3832,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -3718,7 +3969,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -3886,7 +4137,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -3973,14 +4224,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -3989,7 +4240,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -4000,14 +4251,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -4016,7 +4267,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -4026,7 +4277,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -4142,7 +4393,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -4168,7 +4419,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -4386,7 +4637,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -4523,7 +4774,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -4691,7 +4942,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -4775,7 +5026,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -4876,7 +5127,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -4922,7 +5173,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -5020,7 +5271,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -5799,7 +6050,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -5845,7 +6096,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -6614,7 +6865,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -6626,7 +6877,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -6642,7 +6893,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -6654,7 +6905,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -6743,7 +6994,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -6755,7 +7006,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -6791,7 +7042,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -6803,7 +7054,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 11, + query_index: 12, column_index: 9, rotation: Rotation( -1, @@ -7406,7 +7657,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -7432,7 +7683,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -7515,7 +7766,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -7550,7 +7801,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -7581,7 +7832,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -7652,7 +7903,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -7687,7 +7938,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -7753,7 +8004,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7779,7 +8030,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7808,7 +8059,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7837,7 +8088,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7866,7 +8117,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7895,7 +8146,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7924,7 +8175,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -7953,7 +8204,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8016,7 +8267,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8053,7 +8304,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8075,7 +8326,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8113,7 +8364,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8135,7 +8386,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8157,7 +8408,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8196,7 +8447,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8218,7 +8469,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8240,7 +8491,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8262,7 +8513,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8302,7 +8553,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8324,7 +8575,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8346,7 +8597,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8368,7 +8619,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8390,7 +8641,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8431,7 +8682,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8453,7 +8704,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8475,7 +8726,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8497,7 +8748,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8519,7 +8770,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8541,7 +8792,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8583,7 +8834,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8605,7 +8856,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8627,7 +8878,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8649,7 +8900,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8671,7 +8922,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8693,7 +8944,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -8715,7 +8966,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -12867,7 +13118,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -12953,7 +13204,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -13069,14 +13320,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, ), }, Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -13085,7 +13336,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -13096,14 +13347,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, ), }, Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -13112,7 +13363,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -13163,7 +13414,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -13572,7 +13823,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -13584,7 +13835,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -13684,7 +13935,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -13715,7 +13966,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -13829,7 +14080,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -13956,7 +14207,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -13964,7 +14215,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -14175,7 +14426,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -14261,7 +14512,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -14384,7 +14635,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -14393,7 +14644,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -14420,7 +14671,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -15040,7 +15291,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -15052,7 +15303,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -15168,7 +15419,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -15694,7 +15945,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -15706,7 +15957,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -15937,7 +16188,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -15946,7 +16197,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -15954,7 +16205,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -16209,7 +16460,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -16220,7 +16471,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -16231,7 +16482,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 10, column_index: 0, rotation: Rotation( 1, @@ -16764,14 +17015,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 13, + query_index: 14, column_index: 3, rotation: Rotation( 1, @@ -16869,7 +17120,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -17105,7 +17356,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 14, + query_index: 15, column_index: 4, rotation: Rotation( 1, @@ -19148,7 +19399,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -19684,7 +19935,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -20367,7 +20618,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -21036,7 +21287,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -21278,7 +21529,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -21435,7 +21686,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -21574,7 +21825,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -21956,7 +22207,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -24104,7 +24355,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -24640,7 +24891,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -25323,7 +25574,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -25992,7 +26243,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -26234,7 +26485,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -26391,7 +26642,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -26530,7 +26781,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 15, + query_index: 16, column_index: 5, rotation: Rotation( 1, @@ -26912,7 +27163,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -27014,7 +27265,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 0, column_type: Advice, }, Rotation( @@ -27027,21 +27278,21 @@ PinnedVerificationKey { column_type: Advice, }, Rotation( - -1, + 1, ), ), ( Column { - index: 2, + index: 9, column_type: Advice, }, Rotation( - 1, + -1, ), ), ( Column { - index: 3, + index: 2, column_type: Advice, }, Rotation( @@ -27050,7 +27301,7 @@ PinnedVerificationKey { ), ( Column { - index: 4, + index: 3, column_type: Advice, }, Rotation( @@ -27059,7 +27310,7 @@ PinnedVerificationKey { ), ( Column { - index: 5, + index: 4, column_type: Advice, }, Rotation( @@ -27068,7 +27319,7 @@ PinnedVerificationKey { ), ( Column { - index: 0, + index: 5, column_type: Advice, }, Rotation( @@ -27517,7 +27768,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 10, + query_index: 11, column_index: 9, rotation: Rotation( 1, @@ -27620,7 +27871,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 12, + query_index: 13, column_index: 2, rotation: Rotation( 1, @@ -28091,47 +28342,47 @@ PinnedVerificationKey { (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), - (0x18cd12d5f4e12bd7247a8fd7cc93ded7a8a9b60935b319b2db578a8fceef9559, 0x16b15af4fcfb9ed75533e7a4c1966cae5621f10dc1dfbba39a491ec37c911b5e), - (0x37e70146801841d95832259e4d8f39aeee8a364ea5007f82aa84a0e387231315, 0x20ef65833381c985722a95e65125a1123cab3357741168a5ed7e92e972dbd30d), - (0x12e3af8e507a2ca30e544568cf319701ecbc29dc5919f0198d541938edecc8f3, 0x3fb1bb2804faaa4c215e93694d5d1e6f87874cb8c34cb9206ff958de14e44275), - (0x334d99f316343f01c8eb67e327c76f743f8de7f957c893c6f30ccd87e5d1af3a, 0x1da64caf127c8eb513653791147a85ed1edcca12935c95b7d615a9377c9406d8), - (0x1430dca15080286939046d3cb9fb7ace4ed1da2fbe7a362e8f3575489bc6e3e1, 0x1ef5f4aff2902f3bc8acb2cc884a2d44334f910a68b2701f1c37943652b46d8f), - (0x02ebdeac7e91b3d15e4b7c0533e42678672ec384d51e51e22342be7edeeb8074, 0x03638952e0489de03ff03236433f5d2617cb4ddd0a72637ed31095deca85a2a6), - (0x31179b7f5b01ad2a55cf9a66f57b696e9b9cb4919cca426d469b270827f3018b, 0x2b231a9a71b674cc546ba9b36916a13411648903cfdcb808926fc47ee745586c), - (0x0673497660cec8a8c391cfb16f5ffdcb710f9e9e194a1a85935cf4bc45b01359, 0x15ce8801c51811f0256a43f762e497fe38c88866c09bb256289d93e0393dc225), - (0x098d2a0cfedae91fe29e21a01b5e43045b9cc8d9a334f1aee3e075f36a16e323, 0x0be47cc41643c9e6d95012428d5b46ae5a44e765392e05152a0181e30689d8b6), + (0x0ba01714529dc85dd2460cdbf014b71e7638d18a35eacf06868020c27c28232d, 0x2dcbb2c3191f582b6882cc9c5e6cac1a0361d0534f8f4c814e33a272b8e8da8d), + (0x0f8fb02c096c0957230639133087e8ae516d04d1678ace6ab0495a8e8576c0db, 0x2842b28258744140b09e0d27559d84e1d8f1d55350b0af37237879d14f8eb2a1), + (0x36f2f0410d5ab00d5296bf101cbd91008551d4afe2b5ac45fc437aa157c731aa, 0x19e8c688f0c92a3db3e74b66075d2e0771d5c744e77090c487ffca245a7f7f96), + (0x09ce7fd65bf8af2b554230465003160d3d0b7bfc495f6d33f5f0704cb57d6320, 0x38d3478df8841a4f7a74a3c1fe7788e6e1cbb1076d5f7358be729fa2572c9530), + (0x2abaec8c54bde721f7f2aea685764c80b0b935447c00173ff34209ac8d96b633, 0x36957cf784345bfbdb97f0fad0b74d3e5d683fcc80ee407d6a6bedfe097c0011), + (0x3f1845e758196892c66d920980dc29cc2e1844fa03575668bf84349071094207, 0x1873355bc49aeed1faee56e6d21907a5277fcd0283a3f51fface877e1c59f046), + (0x04e5834f610cf806911a2e9c14519132a49ac55f40095c3156e3b20d09a2f250, 0x2ea666b99d148e1090b42fd2f67fd34c7e94ca505447c1431485eca09ed1fe0b), + (0x35de09079a5b05d25f756479ea044c654c97043bc4a79b34f860faa9b049337a, 0x06c4cc500093cfdc9bd284f3c44a2a8856cfc8ce70786dd65787397292e4fe53), + (0x235b63a940346f07c5a669831067ba59acb3b9936db7d66c4a4cf6746af5f97e, 0x0d838f859fb1386034263d43ace744961a310f548f7274586f133aa4ddc779a9), (0x02adb7cbc9ebbbd87d7d6a41fc40cb4cf57585c6243aa204f757c9026ef20fd3, 0x327fc06fee179c6a57ed95336f9fb7854420d80dd191251a40935664ff6c8067), (0x2d00d4ec8aa5e4b3d035131f559e4a97f896e8dbc39badb92b58a8d46b5e91df, 0x37046fb32ed8eb4ba0b4da8e1c9b56cd3832fa2ed4788f7faf4fee1f76a94c32), - (0x212f5afd70e787e2fd951e0ddc5430d1fa78f988c30740384d18cf9ff276b43b, 0x20c5a150e200caddf9a35a993668fc4742be5d924d1086f05c74ef6a78b5feb2), + (0x1e5ddb2d4ee82f8d1982eb0333d98528efeb71f4d413fea2f1eed9e2c4d19dc3, 0x3e092c6d429d9f7d5b5a729af533e7b9e943752835b540060a2e0e31aa25958e), (0x02c283cbde85f2ad26daddeabe01b1574ce7de68f0e329ec95a4154dd4713f29, 0x208cf96aa5255b543933ee3e9bdd054d4f15265a7c8921aaee89c192af2fd284), (0x1f777f0e4263ec4a19f30813739c640335ffa951cc3cc586b6c4095e737f95be, 0x061c07fb12cb19582eefd858a08e689acd970c8cb9ed8f7b928d88e691a2f586), (0x13d0bd76da4ace22c0e90b098d6073551322b8c734bf37eeca67fbf19687f550, 0x3d996cc9da5a31cefb453390b906eabbcc75797bc6a6b9c9e3af2fe7b6b8beed), - (0x04cad7405b492a30db0a710c842cecc97d02059acf4c02aa79626dce68ac4837, 0x3d6d7b6698b258e61ebe0b25d9cbcd4a016cb0a2ae8d92752532d98cfb27720d), - (0x1b6f5383c5a0ae5bf457e1c8e17a933e892464d33fef9e9262411e01c117d87e, 0x0c552b960e8ce365b5f2302bcc0b7ce5cdf964e6036602cfc859c8769184f619), - (0x3fa4b5cc33e30de3ac7342c84f47f4fffe7ae77dda1689c2f08050d0ab743cb1, 0x327663e39b128ec28c94486b1e5d4429000626f65230ed572c66f80406a42176), - (0x2184a7d65b5000cc5c5f178c2f4ab5b11a67fdc626771c29ade508020c8da032, 0x34c98ee1f6dfa6c1e8cd915d1efeb484206e13e5e32e13118925913568e620b7), + (0x088ced578c98f9634cd7aba72b2ff3c6a43109aca67cd1cdc0717a70da32aebf, 0x1a17c29333cc59a199472807282d2b8364baf57ac00e8c29f51dcde32f0b6549), + (0x0525a1d721b05a02ee6e9580254e13213ada10c168213fbfebc7c1c71de072d2, 0x2edc5a41f195c2cc25cefce1405af856721c23dadb1728b2ff3335f08118c4c6), + (0x02e4214937491f7c86b1e37516f7ad0d030beeeab0149ef9062a7ec77604890e, 0x3d1763bcb3f7b989fccb1376b291dfbaef0e139ce4e3f43854fe507bbaad59d5), + (0x3f9542a72fadf26c1931411e1d690e89fef20b05a20f9706f1231e23adb00082, 0x0676af65a2925d168339df2b8dcee0139cbbfaec9470ed902ad600362602737d), (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), (0x1e355d783cffccafc120f462461fb312773442762383ac444009653f3d8d4be6, 0x3c60e17b18492aa2c41798b409d2bcc1857ca57ee9d2fb0001584cedc8e141d6), - (0x0a6fe1cc1ce659681079768ca8ff94d82c7d51ef39cd99b738b144de3a3027f6, 0x30cfc2f4e0ec95f623199970d8b762647ad2d7c3591a20781ee8187702babe5f), - (0x00d87a2c430f1db50a63f18f8cf8807f4f70d3acb940d4130ba6811f8ba2d479, 0x13d5742320e1b2cecda6073b7f2bf5816b9067453deeaa829f356a65ef5621b2), - (0x3118979ade023f3977d034f86eed6506d7e0586ead81f80bc5ca01a7660ee0c9, 0x30f6731193d5c786cf61b05523c05e2664a066c2d39a685588f02883057320ad), - (0x0df51bd411d5f95da66fcc57f5e4d8dbcca3d82b08ceb61e9ff1befa074e08d3, 0x11c9092b6d02c46f173b0108854499ca4922afaf58e0734e77a6088715e84b64), - (0x24289014ede2672df8e8e32eb4e0d71709846041319fb85b1328cdb3b8764565, 0x0833de9c0b76ae816df0e41ae33daece27c63a41f2ba9abbbc7c08724211b50c), + (0x18909046614ff6e61f755dbbb92989aac36dfa3d92fb8b54a37600ccb8cfba82, 0x053ec2a2bdc4e2771bfd6bc883c02db47d38d199bdab01adea7b1a272f223b7c), + (0x23a3dcd68c8a837c9eb84436ab2a184973d6fd3a1ba05d92d6fd747d23c799b0, 0x3f3802f0cfeaaae7f5f766bd3231299654bfd0a5d27b7f1d2ea93bee3d95b4b8), + (0x2331a44c6cf195b1afed0198fbe5a39da809e9815252a0aaa71a45803c81fb3b, 0x3223527d36e068b4821c95d09de240340564a5884bd6363ffd0c2f1961871651), + (0x2aa6286d3aba61beb097804a736279e5d0df5be592d21bdf04b1c418a2a20c69, 0x2d48db2dceacb16afe698d7a8314a2870939101a5cac866a70a946f3c46c3e73), + (0x1a81a317cb5b7169c17c6568fb7641cbe98969f8bee26164544c8cf3b8b4ac3b, 0x003012d4d94fc0502d0c8fd0322de8d1317a30fd8282a07f3eed945c678faf3e), ], permutation: VerifyingKey { commitments: [ - (0x2ad778f0e75a3dcad7c0cc2215e554f3d6fe41eabd612c487ea2708d59fb2e7e, 0x0561e9268230b53ec9cac0fd7654b3edaa3851f624c62bdae39519ae17526c06), - (0x358a21858e7f0da213959badd192b12e7bd40f6b18f5617a7fbad1f142b53c41, 0x1cc665c7a95332ea3ecb79bc35c4d672837809470691ad6a96f2eca081ca9c98), - (0x28d6468db328f1d201b3b7ca36f3affddee9dd0043d8868e34f1839742ac3190, 0x2f38eba3a82748cc28e46c1e20b7d343fdac7ef726ed6de89f6484c6070204f1), - (0x21f27b52cd9a76e1dbbf572fbfc0262007015777b68bda954f3c9db60ebb27f9, 0x0dbbf8f04e8476544a853e54093689d59935de9194eef24a0ee04d6faef9423f), - (0x0253a69e81add6bc1c2fe14bd90dab3e3c2603747dd3760c9dd1e341d96a79ed, 0x15cbe812a45a46512cc8ed493250f75a9dcaaee4be0d3bdaee8b43d74c50481f), - (0x19eb8760e7d0e6ae6d28d65627d958661cdde4e58a0aeb55a6b7017bcf723002, 0x064575794bf9bfdbc50e94b8afbbd2851ae4e12ff2809777d28fe71c235727d9), - (0x0e5c408b5224841cb4f75aec5cdb7bc95c150bbe858dbde8dbac9f72e5392462, 0x01030c69ac5fc7dd63e4e0bb1718d26f51b79dccc81e0b172e98c26e59145414), - (0x12437cb05ecff24131b52b5a55f6f143d8437c28c9d7c31eb06cfa093972a64b, 0x06e1a5e39566b4ce097a6c7dace6dcb827e54dac7d64fa79d994fb1557717614), - (0x34636ff9de412da15f41a8a006abbe8f43a5cffc94e6c3deb02f98af4fb2b8c7, 0x0270f0c3fa8cc7338f20fbcd5ec4e62799e051e0c5938d9e8c41581de8da6165), - (0x218e047b1c0a3b92c59539b3f6d9c23d34ebeeb65ca0be98f5e0e9642bdf1085, 0x20c1117f40b375688a94ff5c5c0b70004e43c7c7cd492fe8055fea081ea5ca78), - (0x2478c8226d4ede1c203fa7455b5fe28f99d5a0cb8ccdb5be4b54d5edcce974c4, 0x1ce69b76f05daeae57cd3d452370439237da89f2ddc84f7b2e35703acbf99655), - (0x08383138ecc6f2fb5459043c7666ae3df7802f1f02392af44db6ba25cd7d2c56, 0x20957d7a3f00a8589f627c5f5e471f45a84fbcbdcde00dfc97b9a97f3f723202), + (0x39c3094020a1b893afa09240d88a468f5803f8c67efd9bb4b1c0bfb94dab6271, 0x0416775ce28cc7214bd6573f9c5e3f2972abb9f4468c1acf8dd5005dcfc3841f), + (0x1eee618d6829a4cbe8bcaad592b532e181af07bdc5074bcfed31b08ade1e27a8, 0x1bcec4c593b72804ac2e9eaa9706b38aae13ad1898cfc11c547741c73e63c3c6), + (0x37be1e93e1e474611af94327cb85b27f652a1b1bbfd952bf3ee45be138918fe0, 0x250bffe2eacca2244b2ae88dccc8c0678f8d3b0ba4d1e4f663dcd95eff0be5cf), + (0x2d95cfb99fce4d1ce1ab680674b4344cb0689c82bb667953a88d25f73a07a3a6, 0x30b015209e497612526ce2b940f38b73608a791bf1b9081ec6592aa4a3b3d6e2), + (0x20384319aa772450c3f144ad974a5ba707e863419e0d035d8c60debaaeff9283, 0x3909e58668259a03f10d849f032963686cf15e49ff5c993bbbf4b913c1e57d6b), + (0x1240cf41a87879f67dab54f4580882aea1d1b5154b821c0c40b15b9635d0487e, 0x1792251c1ac4a5e689b6d75696d7cfd3d157561e5dd5c48508add90da16d7a51), + (0x0546256e9b7ed28e1bd03fba20aab2f954f477856c7cd26e81c11e31065a0820, 0x1ff390755b1b4a2568762672a7a62e147f12a1cbe8a898dd4b078f5b7bf47253), + (0x322ad473ba02ff5d65ef29f0593b823a974cee815177a9f946bd1dd09f5d8fd3, 0x3dc0527f997c8c0948b32dbaf41e1d8c5cd057152fe54a6c8ea9f7d20285c111), + (0x2ab170c47a1311a82abf11d9f34b6fb47f4955740987f6a2afee3c9a7544dfb3, 0x0513f4a2c077a7c6ed881afe96c90e8e13d31c22b5f53a4203f75c7011bc72f5), + (0x085e66ccf3a3667cdbb2d5abaa37d339b594c079e3a06bf2cda8345a2fffcd88, 0x36da573fe8112eec770349dbcae747acb8a513b0504606285970d653bf25c2e2), + (0x2aa7abe46cd3f3786469fd351047535d2596525d93573a6af9044a223e1fc170, 0x246a8655cc204e81045bdc047627c364f7e501ac24a89372a1dbcb8a515d6016), + (0x1ad163c8b2e5840d94fe2925b62824788b50bd130c6deb3dc01f2f77d246c6eb, 0x2f3657736db088a93fba26e49be620728061d989717ba60899d22e22dfd7ec6f), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 9dcabe5b67196ea961707b01496939b1c75770c7..fe636afae568d1de011e6fded98e266980089870 100644 GIT binary patch literal 5154 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

5z4f$eYFG}{=|M7 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 Date: Thu, 2 Mar 2023 14:26:19 +0200 Subject: [PATCH 20/92] AssetBase spec update (#44) - Renamed AssetId to AssetBase - Changed the AssetBase implementation to support the zip update. - Updated visibility for various members of issuance.rs --- benches/circuit.rs | 4 +- benches/note_decryption.rs | 6 +- src/action.rs | 2 +- src/builder.rs | 28 +++---- src/bundle.rs | 16 ++-- src/circuit.rs | 16 ++-- src/constants/fixed_bases.rs | 6 +- src/issuance.rs | 101 ++++++++++++++---------- src/keys.rs | 6 +- src/note.rs | 22 +++--- src/note/{asset_id.rs => asset_base.rs} | 81 ++++++++++++------- src/note/commitment.rs | 4 +- src/note_encryption.rs | 8 +- src/note_encryption_v2v3.rs | 14 ++-- src/note_encryption_v3.rs | 10 +-- src/value.rs | 16 ++-- tests/builder.rs | 6 +- tests/zsa.rs | 14 ++-- 18 files changed, 202 insertions(+), 158 deletions(-) rename src/note/{asset_id.rs => asset_base.rs} (60%) diff --git a/benches/circuit.rs b/benches/circuit.rs index e9bab616c..03868a418 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -6,7 +6,7 @@ use criterion::{BenchmarkId, Criterion}; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; -use orchard::note::AssetId; +use orchard::note::AssetBase; use orchard::{ builder::Builder, bundle::Flags, @@ -37,7 +37,7 @@ fn criterion_benchmark(c: &mut Criterion) { None, recipient, NoteValue::from_raw(10), - AssetId::native(), + AssetBase::native(), None, ) .unwrap(); diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 244de4378..6bd6fa10f 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -4,7 +4,7 @@ use orchard::{ bundle::Flags, circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, - note::AssetId, + note::AssetBase, note_encryption_v3::{CompactAction, OrchardDomainV3}, value::NoteValue, Anchor, Bundle, @@ -57,7 +57,7 @@ fn bench_note_decryption(c: &mut Criterion) { None, recipient, NoteValue::from_raw(10), - AssetId::native(), + AssetBase::native(), None, ) .unwrap(); @@ -66,7 +66,7 @@ fn bench_note_decryption(c: &mut Criterion) { None, recipient, NoteValue::from_raw(10), - AssetId::native(), + AssetBase::native(), None, ) .unwrap(); diff --git a/src/action.rs b/src/action.rs index ed3fe1661..c9e989c27 100644 --- a/src/action.rs +++ b/src/action.rs @@ -126,7 +126,7 @@ pub(crate) mod testing { use proptest::prelude::*; - use crate::note::asset_id::testing::arb_asset_id; + use crate::note::asset_base::testing::arb_asset_id; use crate::{ note::{ commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, diff --git a/src/builder.rs b/src/builder.rs index 0a7f441c7..09091c2ea 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -9,7 +9,7 @@ use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; -use crate::note::AssetId; +use crate::note::AssetBase; use crate::{ action::Action, address::Address, @@ -99,7 +99,7 @@ impl SpendInfo { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(asset: AssetId, rng: &mut impl RngCore) -> Self { + fn dummy(asset: AssetBase, rng: &mut impl RngCore) -> Self { let (sk, fvk, note) = Note::dummy(rng, None, asset); let merkle_path = MerklePath::dummy(rng); @@ -127,7 +127,7 @@ struct RecipientInfo { ovk: Option, recipient: Address, value: NoteValue, - asset: AssetId, + asset: AssetBase, memo: Option<[u8; 512]>, } @@ -135,7 +135,7 @@ impl RecipientInfo { /// Defined in [Zcash Protocol Spec § 4.8.3: Dummy Notes (Orchard)][orcharddummynotes]. /// /// [orcharddummynotes]: https://zips.z.cash/protocol/nu5.pdf#orcharddummynotes - fn dummy(rng: &mut impl RngCore, asset: AssetId) -> Self { + fn dummy(rng: &mut impl RngCore, asset: AssetBase) -> Self { let fvk: FullViewingKey = (&SpendingKey::random(rng)).into(); let recipient = fvk.address_at(0u32, Scope::External); @@ -253,7 +253,7 @@ impl ActionInfo { pub struct Builder { spends: Vec, recipients: Vec, - burn: HashMap, + burn: HashMap, flags: Flags, anchor: Anchor, } @@ -323,7 +323,7 @@ impl Builder { ovk: Option, recipient: Address, value: NoteValue, - asset: AssetId, + asset: AssetBase, memo: Option<[u8; 512]>, ) -> Result<(), &'static str> { if !self.flags.outputs_enabled() { @@ -342,7 +342,7 @@ impl Builder { } /// Add an instruction to burn a given amount of a specific asset. - pub fn add_burn(&mut self, asset: AssetId, value: NoteValue) -> Result<(), &'static str> { + pub fn add_burn(&mut self, asset: AssetBase, value: NoteValue) -> Result<(), &'static str> { if asset.is_native().into() { return Err("Burning is only possible for non-native assets"); } @@ -481,7 +481,7 @@ fn partition_by_asset( spends: &[SpendInfo], recipients: &[RecipientInfo], rng: &mut impl RngCore, -) -> HashMap, Vec)> { +) -> HashMap, Vec)> { let mut hm = HashMap::new(); for s in spends { @@ -499,7 +499,7 @@ fn partition_by_asset( } if hm.is_empty() { - let dummy_spend = SpendInfo::dummy(AssetId::native(), rng); + let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng); hm.insert(dummy_spend.note.asset(), (vec![dummy_spend], vec![])); } @@ -770,7 +770,7 @@ pub mod testing { use proptest::collection::vec; use proptest::prelude::*; - use crate::note::AssetId; + use crate::note::AssetBase; use crate::{ address::testing::arb_address, bundle::{Authorized, Bundle, Flags}, @@ -798,7 +798,7 @@ pub mod testing { sk: SpendingKey, anchor: Anchor, notes: Vec<(Note, MerklePath)>, - recipient_amounts: Vec<(Address, NoteValue, AssetId)>, + recipient_amounts: Vec<(Address, NoteValue, AssetBase)>, } impl ArbitraryBundleInputs { @@ -852,7 +852,7 @@ pub mod testing { arb_address().prop_flat_map(move |a| { arb_positive_note_value(MAX_NOTE_VALUE / n_recipients as u64) .prop_map(move |v| { - (a,v, AssetId::native()) + (a,v, AssetBase::native()) }) }), n_recipients as usize, @@ -904,7 +904,7 @@ mod tests { use rand::rngs::OsRng; use super::Builder; - use crate::note::AssetId; + use crate::note::AssetBase; use crate::{ bundle::{Authorized, Bundle, Flags}, circuit::ProvingKey, @@ -933,7 +933,7 @@ mod tests { None, recipient, NoteValue::from_raw(5000), - AssetId::native(), + AssetBase::native(), None, ) .unwrap(); diff --git a/src/bundle.rs b/src/bundle.rs index 1d1363daf..d7a75875b 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -12,7 +12,7 @@ use memuse::DynamicUsage; use nonempty::NonEmpty; use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; -use crate::note::AssetId; +use crate::note::AssetBase; use crate::{ action::Action, address::Address, @@ -142,7 +142,7 @@ pub struct Bundle { value_balance: V, /// Assets intended for burning /// TODO We need to add a consensus check to make sure that it is impossible to burn ZEC. - burn: Vec<(AssetId, V)>, + burn: Vec<(AssetBase, V)>, /// The root of the Orchard commitment tree that this bundle commits to. anchor: Anchor, /// The authorization for this bundle. @@ -175,7 +175,7 @@ impl Bundle { actions: NonEmpty>, flags: Flags, value_balance: V, - burn: Vec<(AssetId, V)>, + burn: Vec<(AssetBase, V)>, anchor: Anchor, authorization: T, ) -> Self { @@ -232,7 +232,7 @@ impl Bundle { .burn .into_iter() .map(|(asset, value)| Ok((asset, f(value)?))) - .collect::, E>>()?, + .collect::, E>>()?, anchor: self.anchor, authorization: self.authorization, }) @@ -397,7 +397,7 @@ impl> Bundle { - ValueCommitment::derive( ValueSum::from_raw(self.value_balance.into()), ValueCommitTrapdoor::zero(), - AssetId::native(), + AssetBase::native(), ) - self .burn @@ -527,8 +527,8 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; pub use crate::action::testing::{arb_action, arb_unauthorized_action}; - use crate::note::asset_id::testing::arb_zsa_asset_id; - use crate::note::AssetId; + use crate::note::asset_base::testing::arb_zsa_asset_id; + use crate::note::AssetBase; use crate::value::testing::arb_value_sum; /// Marker for an unauthorized bundle with no proofs or signatures. @@ -595,7 +595,7 @@ pub mod testing { ( asset_id in arb_zsa_asset_id(), value in arb_value_sum() - ) -> (AssetId, ValueSum) { + ) -> (AssetBase, ValueSum) { (asset_id, value) } } diff --git a/src/circuit.rs b/src/circuit.rs index e6c9f6e09..7ac075eea 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -36,7 +36,7 @@ use crate::{ note::{ commitment::{NoteCommitTrapdoor, NoteCommitment}, nullifier::Nullifier, - AssetId, ExtractedNoteCommitment, Note, + AssetBase, ExtractedNoteCommitment, Note, }, primitives::redpallas::{SpendAuth, VerificationKey}, spec::NonIdentityPallasPoint, @@ -109,7 +109,7 @@ pub struct Circuit { pub(crate) psi_old: Value, pub(crate) rcm_old: Value, pub(crate) cm_old: Value, - pub(crate) asset_old: Value, + pub(crate) asset_old: Value, pub(crate) alpha: Value, pub(crate) ak: Value, pub(crate) nk: Value, @@ -119,7 +119,7 @@ pub struct Circuit { pub(crate) v_new: Value, pub(crate) psi_new: Value, pub(crate) rcm_new: Value, - pub(crate) asset_new: Value, + pub(crate) asset_new: Value, pub(crate) rcv: Value, pub(crate) split_flag: Value, } @@ -1034,7 +1034,7 @@ mod tests { use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; - use crate::note::AssetId; + use crate::note::AssetBase; use crate::{ keys::SpendValidatingKey, note::Note, @@ -1043,7 +1043,7 @@ mod tests { }; fn generate_circuit_instance(mut rng: R) -> (Circuit, Instance) { - let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetId::native()); + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); let sender_address = spent_note.recipient(); let nk = *fvk.nk(); @@ -1053,12 +1053,12 @@ mod tests { let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old), AssetId::native()); + let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old), AssetBase::native()); let cmx = output_note.commitment().into(); let value = spent_note.value() - output_note.value(); let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv, AssetId::native()); + let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); @@ -1175,7 +1175,7 @@ mod tests { let isk = IssuanceAuthorizingKey::from(&sk); let ik = IssuanceValidatingKey::from(&isk); let asset_descr = "zsa_asset"; - AssetId::derive(&ik, asset_descr) + AssetBase::derive(&ik, asset_descr) }; circuit.asset_new = Value::known(random_asset_id); diff --git a/src/constants/fixed_bases.rs b/src/constants/fixed_bases.rs index 4b5d1518e..12ab8a47e 100644 --- a/src/constants/fixed_bases.rs +++ b/src/constants/fixed_bases.rs @@ -21,11 +21,11 @@ pub const ORCHARD_PERSONALIZATION: &str = "z.cash:Orchard"; /// SWU hash-to-curve personalization for the value commitment generator pub const VALUE_COMMITMENT_PERSONALIZATION: &str = "z.cash:Orchard-cv"; -/// SWU hash-to-curve personalization for the note type generator -// pub const ASSET_ID_PERSONALIZATION: &str = "z.cash:Orchard-NoteType"; +/// SWU hash-to-curve personalization for the ZSA asset base generator +pub const ZSA_ASSET_BASE_PERSONALIZATION: &str = "z.cash:OrchardZSA"; /// SWU hash-to-curve value for the value commitment generator -pub const VALUE_COMMITMENT_V_BYTES: [u8; 1] = *b"v"; +pub const NATIVE_ASSET_BASE_V_BYTES: [u8; 1] = *b"v"; /// SWU hash-to-curve value for the value commitment generator pub const VALUE_COMMITMENT_R_BYTES: [u8; 1] = *b"r"; diff --git a/src/issuance.rs b/src/issuance.rs index 74247f928..f3da1523b 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -12,8 +12,10 @@ use crate::issuance::Error::{ IssueBundleInvalidSignature, WrongAssetDescSize, }; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; -use crate::note::asset_id::is_asset_desc_of_valid_size; -use crate::note::{AssetId, Nullifier}; +use crate::note::asset_base::is_asset_desc_of_valid_size; +use crate::note::{AssetBase, Nullifier}; +use crate::primitives::redpallas::Signature; + use crate::value::NoteValue; use crate::{ primitives::redpallas::{self, SpendAuth}, @@ -21,7 +23,7 @@ use crate::{ }; /// A bundle of actions to be applied to the ledger. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct IssueBundle { /// The issuer key for the note being created. ik: IssuanceValidatingKey, @@ -81,11 +83,11 @@ impl IssueAction { self.finalize } - /// Return the `AssetId` if the provided `ik` is used to derive the `asset_id` for **all** internal notes. + /// Return the `AssetBase` if the provided `ik` is used to derive the `asset_id` for **all** internal notes. fn are_note_asset_ids_derived_correctly( &self, ik: &IssuanceValidatingKey, - ) -> Result { + ) -> Result { match self .notes .iter() @@ -97,7 +99,7 @@ impl IssueAction { .ok_or(IssueActionIncorrectNoteType) }) { Ok(asset) => asset // check that the asset was properly derived. - .eq(&AssetId::derive(ik, &self.asset_desc)) + .eq(&AssetBase::derive(ik, &self.asset_desc)) .then(|| asset) .ok_or(IssueBundleIkMismatchNoteType), Err(e) => Err(e), @@ -106,20 +108,20 @@ impl IssueAction { } /// Defines the authorization type of an Issue bundle. -pub trait IssueAuth: fmt::Debug {} +pub trait IssueAuth: fmt::Debug + Clone {} /// Marker for an unauthorized bundle with no proofs or signatures. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Unauthorized; /// Marker for an unauthorized bundle with injected sighash. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Prepared { sighash: [u8; 32], } /// Marker for an authorized bundle. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Signed { signature: redpallas::Signature, } @@ -129,6 +131,11 @@ impl Signed { pub fn signature(&self) -> &redpallas::Signature { &self.signature } + + /// Constructs an `Signed` from its constituent parts. + pub fn from_parts(signature: Signature) -> Self { + Signed { signature } + } } impl IssueAuth for Unauthorized {} @@ -163,11 +170,11 @@ impl IssueBundle { } /// Find an action by `asset` for a given `IssueBundle`. - pub fn get_action_by_type(&self, asset: AssetId) -> Option<&IssueAction> { + pub fn get_action_by_type(&self, asset: AssetBase) -> Option<&IssueAction> { let action = self .actions .iter() - .find(|a| AssetId::derive(&self.ik, &a.asset_desc).eq(&asset)); + .find(|a| AssetBase::derive(&self.ik, &a.asset_desc).eq(&asset)); action } @@ -176,6 +183,19 @@ impl IssueBundle { pub fn commitment(&self) -> IssueBundleCommitment { IssueBundleCommitment(hash_issue_bundle_txid_data(self)) } + + /// Constructs an `IssueBundle` from its constituent parts. + pub fn from_parts( + ik: IssuanceValidatingKey, + actions: Vec, + authorization: T, + ) -> Self { + IssueBundle { + ik, + actions, + authorization, + } + } } impl IssueBundle { @@ -202,12 +222,12 @@ impl IssueBundle { value: NoteValue, finalize: bool, mut rng: impl RngCore, - ) -> Result { + ) -> Result { if !is_asset_desc_of_valid_size(&asset_desc) { return Err(WrongAssetDescSize); } - let asset = AssetId::derive(&self.ik, &asset_desc); + let asset = AssetBase::derive(&self.ik, &asset_desc); let note = Note::new( recipient, @@ -335,26 +355,26 @@ impl IssueBundle { /// Validation for Orchard IssueBundles /// /// A set of previously finalized asset types must be provided. -/// In case of success, `finalized` will contain a set of the provided **and** the newly finalized `AssetId`s +/// In case of success, `finalized` will contain a set of the provided **and** the newly finalized `AssetBase`s /// /// The following checks are performed: /// * For the `IssueBundle`: /// * the Signature on top of the provided `sighash` verifies correctly. /// * For each `IssueAction`: /// * Asset description size is collect. -/// * `AssetId` for the `IssueAction` has not been previously finalized. +/// * `AssetBase` for the `IssueAction` has not been previously finalized. /// * For each `Note` inside an `IssueAction`: -/// * All notes have the same, correct `AssetId`. +/// * All notes have the same, correct `AssetBase`. pub fn verify_issue_bundle( bundle: &IssueBundle, sighash: [u8; 32], - finalized: &mut HashSet, // The finalization set. + finalized: &mut HashSet, // The finalization set. ) -> Result<(), Error> { if let Err(e) = bundle.ik.verify(&sighash, &bundle.authorization.signature) { return Err(IssueBundleInvalidSignature(e)); }; - let s = &mut HashSet::::new(); + let s = &mut HashSet::::new(); let newly_finalized = bundle .actions() @@ -403,7 +423,7 @@ pub enum Error { /// Invalid signature. IssueBundleInvalidSignature(reddsa::Error), /// The provided `NoteType` has been previously finalized. - IssueActionPreviouslyFinalizedNoteType(AssetId), + IssueActionPreviouslyFinalizedNoteType(AssetBase), } impl std::error::Error for Error {} @@ -454,7 +474,7 @@ mod tests { use crate::keys::{ FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; - use crate::note::{AssetId, Nullifier}; + use crate::note::{AssetBase, Nullifier}; use crate::value::NoteValue; use crate::{Address, Note}; use nonempty::NonEmpty; @@ -561,7 +581,7 @@ mod tests { bundle .add_recipient( - String::from("Precious NFT"), + String::from("NFT"), recipient, NoteValue::from_raw(u64::MIN), false, @@ -570,13 +590,13 @@ mod tests { .expect("Should properly add recipient"); bundle - .finalize_action(String::from("Precious NFT")) + .finalize_action(String::from("NFT")) .expect("Should finalize properly"); assert_eq!( bundle .add_recipient( - String::from("Precious NFT"), + String::from("NFT"), recipient, NoteValue::unsplittable(), false, @@ -588,7 +608,7 @@ mod tests { assert_eq!( bundle - .finalize_action(String::from("Another precious NFT")) + .finalize_action(String::from("Another NFT")) .unwrap_err(), IssueActionNotFound ); @@ -607,7 +627,7 @@ mod tests { bundle .add_recipient( - String::from("Another precious NFT"), + String::from("Another NFT"), recipient, NoteValue::unsplittable(), true, @@ -618,7 +638,7 @@ mod tests { assert_eq!( bundle .add_recipient( - String::from("Another precious NFT"), + String::from("Another NFT"), recipient, NoteValue::unsplittable(), true, @@ -718,7 +738,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - AssetId::derive(bundle.ik(), "Poisoned pill"), + AssetBase::derive(bundle.ik(), "zsa_asset"), Nullifier::dummy(&mut rng), &mut rng, ); @@ -771,7 +791,7 @@ mod tests { bundle .add_recipient( - String::from("verify_with_finalize"), + String::from("Verify with finalize"), recipient, NoteValue::from_raw(7), true, @@ -785,9 +805,10 @@ mod tests { let res = verify_issue_bundle(&signed, sighash, prev_finalized); assert!(res.is_ok()); - assert!( - prev_finalized.contains(&AssetId::derive(&ik, &String::from("verify_with_finalize"))) - ); + assert!(prev_finalized.contains(&AssetBase::derive( + &ik, + &String::from("Verify with finalize") + ))); assert_eq!(prev_finalized.len(), 1); } @@ -810,7 +831,7 @@ mod tests { let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); let prev_finalized = &mut HashSet::new(); - let final_type = AssetId::derive(&ik, &String::from("already final")); + let final_type = AssetBase::derive(&ik, &String::from("already final")); prev_finalized.insert(final_type); @@ -867,7 +888,7 @@ mod tests { bundle .add_recipient( - String::from("Good description"), + String::from("Asset description"), recipient, NoteValue::from_raw(5), false, @@ -896,7 +917,7 @@ mod tests { bundle .add_recipient( - String::from("Good description"), + String::from("Asset description"), recipient, NoteValue::from_raw(5), false, @@ -910,7 +931,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - AssetId::derive(signed.ik(), "Poisoned pill"), + AssetBase::derive(signed.ik(), "zsa_asset"), Nullifier::dummy(&mut rng), &mut rng, ); @@ -931,7 +952,7 @@ mod tests { #[test] fn issue_bundle_verify_fail_incorrect_ik() { - let asset_description = "asset"; + let asset_description = "Asset"; let (mut rng, isk, ik, recipient, sighash) = setup_params(); @@ -957,7 +978,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(55), - AssetId::derive(&incorrect_ik, asset_description), + AssetBase::derive(&incorrect_ik, asset_description), Nullifier::dummy(&mut rng), &mut rng, ); @@ -985,7 +1006,7 @@ mod tests { bundle .add_recipient( - String::from("Good description"), + String::from("Asset description"), recipient, NoteValue::from_raw(5), false, @@ -1024,7 +1045,7 @@ mod tests { pub mod testing { use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized}; use crate::keys::testing::{arb_issuance_authorizing_key, arb_issuance_validating_key}; - use crate::note::asset_id::testing::zsa_asset_id; + use crate::note::asset_base::testing::zsa_asset_id; use crate::note::testing::arb_zsa_note; use proptest::collection::vec; use proptest::prelude::*; diff --git a/src/keys.rs b/src/keys.rs index dc1d7d77b..faca48d2b 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -271,7 +271,7 @@ impl Eq for IssuanceValidatingKey {} impl IssuanceValidatingKey { /// Converts this spend validating key to its serialized form, /// I2LEOSP_256(ik). - pub(crate) fn to_bytes(&self) -> [u8; 32] { + pub fn to_bytes(&self) -> [u8; 32] { // This is correct because the wrapped point must have ỹ = 0, and // so the point repr is the same as I2LEOSP of its x-coordinate. <[u8; 32]>::from(&self.0) @@ -1127,7 +1127,7 @@ mod tests { testing::{arb_diversifier_index, arb_diversifier_key, arb_esk, arb_spending_key}, *, }; - use crate::note::AssetId; + use crate::note::AssetBase; use crate::{ note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, value::NoteValue, @@ -1219,7 +1219,7 @@ mod tests { let note = Note::from_parts( addr, NoteValue::from_raw(tv.note_v), - AssetId::native(), + AssetBase::native(), rho, RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(), ) diff --git a/src/note.rs b/src/note.rs index 7eeffe096..81c3b166f 100644 --- a/src/note.rs +++ b/src/note.rs @@ -19,8 +19,8 @@ pub use self::commitment::{ExtractedNoteCommitment, NoteCommitment}; pub(crate) mod nullifier; pub use self::nullifier::Nullifier; -pub(crate) mod asset_id; -pub use self::asset_id::AssetId; +pub(crate) mod asset_base; +pub use self::asset_base::AssetBase; /// The ZIP 212 seed randomness for a note. #[derive(Copy, Clone, Debug)] @@ -94,7 +94,7 @@ pub struct Note { /// The value of this note. value: NoteValue, /// The asset id of this note. - asset: AssetId, + asset: AssetBase, /// A unique creation ID for this note. /// /// This is set to the nullifier of the note that was spent in the [`Action`] that @@ -134,7 +134,7 @@ impl Note { pub fn from_parts( recipient: Address, value: NoteValue, - asset: AssetId, + asset: AssetBase, rho: Nullifier, rseed: RandomSeed, ) -> CtOption { @@ -156,7 +156,7 @@ impl Note { pub(crate) fn new( recipient: Address, value: NoteValue, - asset: AssetId, + asset: AssetBase, rho: Nullifier, mut rng: impl RngCore, ) -> Self { @@ -182,7 +182,7 @@ impl Note { pub(crate) fn dummy( rng: &mut impl RngCore, rho: Option, - asset: AssetId, + asset: AssetBase, ) -> (SpendingKey, FullViewingKey, Self) { let sk = SpendingKey::random(rng); let fvk: FullViewingKey = (&sk).into(); @@ -210,7 +210,7 @@ impl Note { } /// Returns the note type of this note. - pub fn asset(&self) -> AssetId { + pub fn asset(&self) -> AssetBase { self.asset } @@ -301,8 +301,8 @@ impl fmt::Debug for TransmittedNoteCiphertext { pub mod testing { use proptest::prelude::*; - use crate::note::asset_id::testing::arb_asset_id; - use crate::note::AssetId; + use crate::note::asset_base::testing::arb_asset_id; + use crate::note::AssetBase; use crate::value::testing::arb_note_value; use crate::{ address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, @@ -346,7 +346,7 @@ pub mod testing { Note { recipient, value, - asset: AssetId::native(), + asset: AssetBase::native(), rho, rseed, } @@ -355,7 +355,7 @@ pub mod testing { prop_compose! { /// Generate an arbitrary zsa note - pub fn arb_zsa_note(asset: AssetId)( + pub fn arb_zsa_note(asset: AssetBase)( recipient in arb_address(), value in arb_note_value(), rho in arb_nullifier(), diff --git a/src/note/asset_id.rs b/src/note/asset_base.rs similarity index 60% rename from src/note/asset_id.rs rename to src/note/asset_base.rs index 93993c47b..9e98cbd89 100644 --- a/src/note/asset_id.rs +++ b/src/note/asset_base.rs @@ -1,3 +1,4 @@ +use blake2b_simd::{Hash as Blake2bHash, Params}; use group::GroupEncoding; use halo2_proofs::arithmetic::CurveExt; use pasta_curves::pallas; @@ -5,25 +6,38 @@ use std::hash::{Hash, Hasher}; use subtle::{Choice, ConstantTimeEq, CtOption}; -use crate::constants::fixed_bases::{VALUE_COMMITMENT_PERSONALIZATION, VALUE_COMMITMENT_V_BYTES}; +use crate::constants::fixed_bases::{ + NATIVE_ASSET_BASE_V_BYTES, VALUE_COMMITMENT_PERSONALIZATION, ZSA_ASSET_BASE_PERSONALIZATION, +}; use crate::keys::IssuanceValidatingKey; /// Note type identifier. #[derive(Clone, Copy, Debug, Eq)] -pub struct AssetId(pallas::Point); +pub struct AssetBase(pallas::Point); pub const MAX_ASSET_DESCRIPTION_SIZE: usize = 512; -// the hasher used to derive the assetID -fn asset_id_hasher(msg: Vec) -> pallas::Point { - // TODO(zsa) replace personalization - pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION)(&msg) +/// Personalization for the ZSA asset digest generator +pub const ZSA_ASSET_DIGEST_PERSONALIZATION: &[u8; 16] = b"ZSA-Asset-Digest"; + +/// AssetDigest for the ZSA asset +/// +/// Defined in [Transfer and Burn of Zcash Shielded Assets][AssetDigest]. +/// +/// [assetdigest]: https://qed-it.github.io/zips/zip-0226.html#asset-identifiers +pub fn asset_digest(asset_id: Vec) -> Blake2bHash { + Params::new() + .hash_length(64) + .personal(ZSA_ASSET_DIGEST_PERSONALIZATION) + .to_state() + .update(&asset_id) + .finalize() } -impl AssetId { +impl AssetBase { /// Deserialize the asset_id from a byte array. pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { - pallas::Point::from_bytes(bytes).map(AssetId) + pallas::Point::from_bytes(bytes).map(AssetBase) } /// Serialize the asset_id to its canonical byte representation. @@ -33,9 +47,9 @@ impl AssetId { /// Note type derivation$. /// - /// Defined in [Transfer and Burn of Zcash Shielded Assets][notetypes]. + /// Defined in [Transfer and Burn of Zcash Shielded Assets][AssetBase]. /// - /// [notetypes]: https://qed-it.github.io/zips/draft-ZIP-0226.html#asset-types + /// [notetypes]: https://qed-it.github.io/zips/zip-0226.html#asset-identifiers /// /// # Panics /// @@ -44,16 +58,23 @@ impl AssetId { pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &str) -> Self { assert!(is_asset_desc_of_valid_size(asset_desc)); - let mut s = vec![]; - s.extend(ik.to_bytes()); - s.extend(asset_desc.as_bytes()); + // EncodeAssetId(ik, asset_desc) = version_byte || ik || asset_desc + let version_byte = [0x00]; + let encode_asset_id = [&version_byte[..], &ik.to_bytes(), asset_desc.as_bytes()].concat(); - AssetId(asset_id_hasher(s)) + let asset_digest = asset_digest(encode_asset_id); + + // AssetBase = ZSAValueBase(AssetDigest) + AssetBase( + pallas::Point::hash_to_curve(ZSA_ASSET_BASE_PERSONALIZATION)(asset_digest.as_bytes()), + ) } /// Note type for the "native" currency (zec), maintains backward compatibility with Orchard untyped notes. pub fn native() -> Self { - AssetId(asset_id_hasher(VALUE_COMMITMENT_V_BYTES.to_vec())) + AssetBase(pallas::Point::hash_to_curve( + VALUE_COMMITMENT_PERSONALIZATION, + )(&NATIVE_ASSET_BASE_V_BYTES[..])) } /// The base point used in value commitments. @@ -67,7 +88,7 @@ impl AssetId { } } -impl Hash for AssetId { +impl Hash for AssetBase { fn hash(&self, h: &mut H) { h.write(&self.to_bytes()); h.finish(); @@ -79,7 +100,7 @@ pub fn is_asset_desc_of_valid_size(asset_desc: &str) -> bool { !asset_desc.is_empty() && asset_desc.bytes().len() <= MAX_ASSET_DESCRIPTION_SIZE } -impl PartialEq for AssetId { +impl PartialEq for AssetBase { fn eq(&self, other: &Self) -> bool { bool::from(self.0.ct_eq(&other.0)) } @@ -89,7 +110,7 @@ impl PartialEq for AssetId { #[cfg(any(test, feature = "test-dependencies"))] #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { - use super::AssetId; + use super::AssetBase; use proptest::prelude::*; @@ -101,21 +122,21 @@ pub mod testing { is_native in prop::bool::ANY, sk in arb_spending_key(), str in "[A-Za-z]{255}", - ) -> AssetId { + ) -> AssetBase { if is_native { - AssetId::native() + AssetBase::native() } else { let isk = IssuanceAuthorizingKey::from(&sk); - AssetId::derive(&IssuanceValidatingKey::from(&isk), &str) + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) } } } prop_compose! { /// Generate the native note type - pub fn native_asset_id()(_i in 0..10) -> AssetId { + pub fn native_asset_id()(_i in 0..10) -> AssetBase { // TODO: remove _i - AssetId::native() + AssetBase::native() } } @@ -124,9 +145,9 @@ pub mod testing { pub fn arb_zsa_asset_id()( sk in arb_spending_key(), str in "[A-Za-z]{255}" - ) -> AssetId { + ) -> AssetBase { let isk = IssuanceAuthorizingKey::from(&sk); - AssetId::derive(&IssuanceValidatingKey::from(&isk), &str) + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) } } @@ -134,25 +155,27 @@ pub mod testing { /// Generate an asset ID using a specific description pub fn zsa_asset_id(asset_desc: String)( sk in arb_spending_key(), - ) -> AssetId { + ) -> AssetBase { assert!(super::is_asset_desc_of_valid_size(&asset_desc)); let isk = IssuanceAuthorizingKey::from(&sk); - AssetId::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) } } + // the following test should fail until updated to use the new asset ID derivation #[test] + #[should_panic] fn test_vectors() { let test_vectors = crate::test_vectors::asset_id::test_vectors(); for tv in test_vectors { let description = std::str::from_utf8(&tv.description).unwrap(); - let calculated_asset_id = AssetId::derive( + let calculated_asset_id = AssetBase::derive( &IssuanceValidatingKey::from_bytes(&tv.key).unwrap(), description, ); - let test_vector_asset_id = AssetId::from_bytes(&tv.asset_id).unwrap(); + let test_vector_asset_id = AssetBase::from_bytes(&tv.asset_id).unwrap(); assert_eq!(calculated_asset_id, test_vector_asset_id); } diff --git a/src/note/commitment.rs b/src/note/commitment.rs index f4bc7247b..f95d8be82 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -11,7 +11,7 @@ use crate::{ fixed_bases::{NOTE_COMMITMENT_PERSONALIZATION, NOTE_ZSA_COMMITMENT_PERSONALIZATION}, L_ORCHARD_BASE, }, - note::asset_id::AssetId, + note::asset_base::AssetBase, spec::extract_p, value::NoteValue, }; @@ -45,7 +45,7 @@ impl NoteCommitment { g_d: [u8; 32], pk_d: [u8; 32], v: NoteValue, - asset: AssetId, + asset: AssetBase, rho: pallas::Base, psi: pallas::Base, rcm: NoteCommitTrapdoor, diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 4beb99528..1e00c0351 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -8,7 +8,7 @@ use zcash_note_encryption::{ AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; -use crate::note::AssetId; +use crate::note::AssetBase; use crate::{ action::Action, keys::{ @@ -163,7 +163,7 @@ where let note = Option::from(Note::from_parts( recipient, value, - AssetId::native(), //V2 notes are always native. + AssetBase::native(), //V2 notes are always native. domain.rho, rseed, ))?; @@ -474,7 +474,7 @@ mod tests { }; use super::{prf_ock_orchard, CompactAction, OrchardDomainV2, OrchardNoteEncryption}; - use crate::note::AssetId; + use crate::note::AssetBase; use crate::{ action::Action, keys::{ @@ -566,7 +566,7 @@ mod tests { assert_eq!(ock.as_ref(), tv.ock); let recipient = Address::from_parts(d, pk_d); - let note = Note::from_parts(recipient, value, AssetId::native(), rho, rseed).unwrap(); + let note = Note::from_parts(recipient, value, AssetBase::native(), rho, rseed).unwrap(); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); let action = Action::from_parts( diff --git a/src/note_encryption_v2v3.rs b/src/note_encryption_v2v3.rs index bef34e06e..5d3eedf25 100644 --- a/src/note_encryption_v2v3.rs +++ b/src/note_encryption_v2v3.rs @@ -8,7 +8,7 @@ use zcash_note_encryption::{ AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; -use crate::note::AssetId; +use crate::note::AssetBase; use crate::{ action::Action, keys::{ @@ -109,14 +109,14 @@ where Some((note, recipient)) } -fn parse_version_and_asset_type(plaintext: &CompactNotePlaintextBytes) -> Option { +fn parse_version_and_asset_type(plaintext: &CompactNotePlaintextBytes) -> Option { match plaintext { - CompactNotePlaintextBytes::V2(x) if x[0] == 0x02 => Some(AssetId::native()), + CompactNotePlaintextBytes::V2(x) if x[0] == 0x02 => Some(AssetBase::native()), CompactNotePlaintextBytes::V3(x) if x[0] == 0x03 => { let bytes = x[COMPACT_NOTE_SIZE_V2..COMPACT_NOTE_SIZE_V3] .try_into() .unwrap(); - AssetId::from_bytes(bytes).into() + AssetBase::from_bytes(bytes).into() } _ => None, } @@ -554,7 +554,7 @@ mod tests { }; use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; - use crate::note::AssetId; + use crate::note::AssetBase; use crate::note_encryption::NoteCiphertextBytes; use crate::{ action::Action, @@ -646,8 +646,8 @@ mod tests { let recipient = Address::from_parts(d, pk_d); let asset = match tv.asset { - None => AssetId::native(), - Some(type_bytes) => AssetId::from_bytes(&type_bytes).unwrap(), + None => AssetBase::native(), + Some(type_bytes) => AssetBase::from_bytes(&type_bytes).unwrap(), }; let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); diff --git a/src/note_encryption_v3.rs b/src/note_encryption_v3.rs index c8a772ffe..4333f6dba 100644 --- a/src/note_encryption_v3.rs +++ b/src/note_encryption_v3.rs @@ -8,7 +8,7 @@ use zcash_note_encryption::{ AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; -use crate::note::AssetId; +use crate::note::AssetBase; use crate::{ action::Action, keys::{ @@ -161,12 +161,12 @@ where let recipient = Address::from_parts(diversifier, pk_d); let asset = match note_version(plaintext.0.as_ref())? { - 0x02 => AssetId::native(), + 0x02 => AssetBase::native(), 0x03 => { let bytes = plaintext.0[COMPACT_NOTE_SIZE_V2..COMPACT_NOTE_SIZE_V3] .try_into() .unwrap(); - AssetId::from_bytes(bytes).unwrap() + AssetBase::from_bytes(bytes).unwrap() } _ => panic!("invalid note version"), }; @@ -483,7 +483,7 @@ mod tests { OutgoingViewingKey, PreparedIncomingViewingKey, }, note::{ - testing::arb_note, AssetId, ExtractedNoteCommitment, Nullifier, RandomSeed, + testing::arb_note, AssetBase, ExtractedNoteCommitment, Nullifier, RandomSeed, TransmittedNoteCiphertext, }, primitives::redpallas, @@ -565,7 +565,7 @@ mod tests { let recipient = Address::from_parts(d, pk_d); - let asset = AssetId::from_bytes(&tv.asset).unwrap(); + let asset = AssetBase::from_bytes(&tv.asset).unwrap(); let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); diff --git a/src/value.rs b/src/value.rs index b514e7a28..fea4c6f94 100644 --- a/src/value.rs +++ b/src/value.rs @@ -59,7 +59,7 @@ use crate::{ }; use crate::builder::Error; -use crate::note::AssetId; +use crate::note::AssetBase; /// Maximum note value. pub const MAX_NOTE_VALUE: u64 = u64::MAX; @@ -345,7 +345,7 @@ impl ValueCommitment { /// /// [concretehomomorphiccommit]: https://zips.z.cash/protocol/nu5.pdf#concretehomomorphiccommit #[allow(non_snake_case)] - pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, asset: AssetId) -> Self { + pub fn derive(value: ValueSum, rcv: ValueCommitTrapdoor, asset: AssetBase) -> Self { let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); let R = hasher(&VALUE_COMMITMENT_R_BYTES); let abs_value = u64::try_from(value.0.abs()).expect("value must be in valid range"); @@ -461,9 +461,9 @@ pub mod testing { #[cfg(test)] mod tests { - use crate::note::asset_id::testing::{arb_asset_id, native_asset_id}; + use crate::note::asset_base::testing::{arb_asset_id, native_asset_id}; - use crate::note::AssetId; + use crate::note::AssetBase; use proptest::prelude::*; use super::{ @@ -473,10 +473,10 @@ mod tests { use crate::primitives::redpallas; fn check_binding_signature( - native_values: &[(ValueSum, ValueCommitTrapdoor, AssetId)], - arb_values: &[(ValueSum, ValueCommitTrapdoor, AssetId)], + native_values: &[(ValueSum, ValueCommitTrapdoor, AssetBase)], + arb_values: &[(ValueSum, ValueCommitTrapdoor, AssetBase)], neg_trapdoors: &[ValueCommitTrapdoor], - arb_values_to_burn: &[(ValueSum, ValueCommitTrapdoor, AssetId)], + arb_values_to_burn: &[(ValueSum, ValueCommitTrapdoor, AssetBase)], ) { // for each arb value, create a negative value with a different trapdoor let neg_arb_values: Vec<_> = arb_values @@ -513,7 +513,7 @@ mod tests { - ValueCommitment::derive( native_value_balance, ValueCommitTrapdoor::zero(), - AssetId::native(), + AssetBase::native(), ) - arb_values_to_burn .iter() diff --git a/tests/builder.rs b/tests/builder.rs index 3e7c416c6..0e9565eb7 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -1,5 +1,5 @@ use incrementalmerkletree::{bridgetree::BridgeTree, Hashable, Tree}; -use orchard::note::AssetId; +use orchard::note::AssetBase; use orchard::{ builder::Builder, bundle::{Authorized, Flags}, @@ -68,7 +68,7 @@ fn bundle_chain() { None, recipient, NoteValue::from_raw(5000), - AssetId::native(), + AssetBase::native(), None ), Ok(()) @@ -103,7 +103,7 @@ fn bundle_chain() { None, recipient, NoteValue::from_raw(5000), - AssetId::native(), + AssetBase::native(), None ), Ok(()) diff --git a/tests/zsa.rs b/tests/zsa.rs index 9ddaaf7bd..5b1ea4437 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -6,7 +6,7 @@ use incrementalmerkletree::{Hashable, Tree}; use orchard::bundle::Authorized; use orchard::issuance::{verify_issue_bundle, IssueBundle, Signed, Unauthorized}; use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; -use orchard::note::{AssetId, ExtractedNoteCommitment}; +use orchard::note::{AssetBase, ExtractedNoteCommitment}; use orchard::note_encryption_v3::OrchardDomainV3; use orchard::tree::{MerkleHashOrchard, MerklePath}; use orchard::{ @@ -189,7 +189,7 @@ fn create_native_note(keys: &Keychain) -> Note { None, keys.recipient, NoteValue::from_raw(100), - AssetId::native(), + AssetBase::native(), None ), Ok(()) @@ -225,13 +225,13 @@ impl TestSpendInfo { struct TestOutputInfo { value: NoteValue, - asset: AssetId, + asset: AssetBase, } fn build_and_verify_bundle( spends: Vec<&TestSpendInfo>, outputs: Vec, - assets_to_burn: Vec<(AssetId, NoteValue)>, + assets_to_burn: Vec<(AssetBase, NoteValue)>, anchor: Anchor, expected_num_actions: usize, keys: &Keychain, @@ -376,7 +376,7 @@ fn zsa_issue_and_transfer() { }, TestOutputInfo { value: NoteValue::from_raw(100), - asset: AssetId::native(), + asset: AssetBase::native(), }, ], vec![], @@ -396,7 +396,7 @@ fn zsa_issue_and_transfer() { }, TestOutputInfo { value: native_spend.note.value(), - asset: AssetId::native(), + asset: AssetBase::native(), }, ], vec![], @@ -493,7 +493,7 @@ fn zsa_issue_and_transfer() { let result = build_and_verify_bundle( vec![&native_spend], vec![], - vec![(AssetId::native(), native_spend.note.value())], + vec![(AssetBase::native(), native_spend.note.value())], native_anchor, 2, &keys, From 527e29a062d951ff3152a4ef992b22dc4700473f Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 20 Mar 2023 14:12:10 +0100 Subject: [PATCH 21/92] Upgrade pprof version with a limited inferno version (#48) --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 20a2ac0b7..5a09720a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,8 +58,8 @@ proptest = "1.0.0" zcash_note_encryption = { version = "0.2", features = ["pre-zip-212"] } [target.'cfg(unix)'.dev-dependencies] -# TODO: upgrade the pprof version once its inferno dependency respects all clippy lints -pprof = { version = "0.6", features = ["criterion", "flamegraph"] } # MSRV 1.56 +inferno = ">= 0.11, < 0.11.15" +pprof = { version = "0.9", features = ["criterion", "flamegraph"] } # MSRV 1.56 [lib] bench = false From f0b794896d1ef0359e53234905a3fd6ad643aec8 Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Wed, 19 Apr 2023 01:00:37 +0530 Subject: [PATCH 22/92] Making changes to the asset base derivation from the asset identifier (#49) This PR updates the test-vectors from the updates to the zcash-test-vectors repository (see here). The keys test is also updated to now use the asset base from the test vectors instead of just using the native asset. --- src/keys.rs | 2 +- src/note/asset_base.rs | 8 +- src/test_vectors/asset_id.rs | 1642 +++++++++++++++++----------------- src/test_vectors/keys.rs | 441 +++++---- 4 files changed, 1071 insertions(+), 1022 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index faca48d2b..6842d182d 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1219,7 +1219,7 @@ mod tests { let note = Note::from_parts( addr, NoteValue::from_raw(tv.note_v), - AssetBase::native(), + AssetBase::from_bytes(&tv.asset).unwrap(), rho, RandomSeed::from_bytes(tv.note_rseed, &rho).unwrap(), ) diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 9e98cbd89..1079e4a6c 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -162,22 +162,20 @@ pub mod testing { } } - // the following test should fail until updated to use the new asset ID derivation #[test] - #[should_panic] fn test_vectors() { let test_vectors = crate::test_vectors::asset_id::test_vectors(); for tv in test_vectors { let description = std::str::from_utf8(&tv.description).unwrap(); - let calculated_asset_id = AssetBase::derive( + let calculated_asset_base = AssetBase::derive( &IssuanceValidatingKey::from_bytes(&tv.key).unwrap(), description, ); - let test_vector_asset_id = AssetBase::from_bytes(&tv.asset_id).unwrap(); + let test_vector_asset_base = AssetBase::from_bytes(&tv.asset_base).unwrap(); - assert_eq!(calculated_asset_id, test_vector_asset_id); + assert_eq!(calculated_asset_base, test_vector_asset_base); } } } diff --git a/src/test_vectors/asset_id.rs b/src/test_vectors/asset_id.rs index c50c0f8f5..2f4f08385 100644 --- a/src/test_vectors/asset_id.rs +++ b/src/test_vectors/asset_id.rs @@ -3,7 +3,7 @@ pub(crate) struct TestVector { pub(crate) key: [u8; 32], pub(crate) description: [u8; 512], - pub(crate) asset_id: [u8; 32], + pub(crate) asset_base: [u8; 32], } pub(crate) fn test_vectors() -> Vec { @@ -15,48 +15,48 @@ pub(crate) fn test_vectors() -> Vec { 0x75, 0x51, 0x47, 0x24, ], description: [ - 0xc5, 0xb3, 0xc8, 0xbe, 0xc8, 0x8a, 0xc8, 0x98, 0xcd, 0xbb, 0xc2, 0xb7, 0xc2, 0xa3, - 0xc9, 0x8f, 0xc5, 0x94, 0xc2, 0xb5, 0xc8, 0x9d, 0x21, 0xc7, 0xbc, 0xc3, 0xb6, 0xc5, - 0xa5, 0xc7, 0xae, 0xc4, 0x9c, 0xc6, 0xa4, 0xc3, 0x81, 0xe2, 0xb1, 0xa5, 0xc6, 0xb6, - 0xc8, 0xb6, 0xc8, 0x88, 0xc3, 0x8c, 0xc6, 0x8e, 0x5d, 0x32, 0xc4, 0x9a, 0xc9, 0x84, - 0xc6, 0xbf, 0xc7, 0x9b, 0xc8, 0x99, 0xc7, 0x9d, 0xc8, 0xbc, 0xcd, 0xb2, 0xc4, 0x9e, - 0xc5, 0xa1, 0xc7, 0xa9, 0xc6, 0xbb, 0xc3, 0x80, 0xc8, 0xba, 0xc3, 0xa1, 0xc4, 0x84, - 0x5f, 0xc7, 0xaa, 0xc5, 0xad, 0xc3, 0x80, 0xc6, 0xaf, 0xc3, 0x85, 0xc6, 0xb1, 0xc7, - 0xbf, 0xc7, 0x93, 0xcd, 0xbc, 0xc3, 0xad, 0xc4, 0x94, 0xc5, 0xad, 0xc3, 0xb6, 0xc3, - 0xa4, 0xc7, 0x9e, 0xc7, 0x81, 0x50, 0xc3, 0xb5, 0xc7, 0x86, 0xcd, 0xbd, 0xe1, 0x9b, - 0x90, 0x23, 0xc6, 0x91, 0xc7, 0x85, 0xc6, 0x8a, 0xc6, 0x9a, 0xc7, 0x88, 0x4e, 0xe1, - 0x9b, 0x9f, 0xe1, 0x9b, 0x93, 0xe1, 0x9a, 0xaf, 0xc6, 0xa1, 0xc8, 0xb1, 0xc7, 0x8d, - 0xc5, 0x93, 0xc8, 0xa0, 0xc7, 0x86, 0x4e, 0xc6, 0xb4, 0xc3, 0x80, 0xce, 0x88, 0x77, - 0xe1, 0x9b, 0xa4, 0xc2, 0xaf, 0xc5, 0x91, 0xc7, 0xa9, 0xc8, 0x83, 0x4d, 0xc8, 0x8b, - 0x6b, 0xc7, 0x9b, 0xc7, 0x82, 0x57, 0xe2, 0xb1, 0xb3, 0xc5, 0x98, 0xc3, 0xb2, 0x61, - 0xc5, 0x9b, 0xc3, 0xbe, 0x3f, 0xc5, 0xb5, 0xc3, 0x88, 0x31, 0xc7, 0xb7, 0xc3, 0xa0, - 0xc5, 0xa2, 0x77, 0xc3, 0x94, 0xc7, 0xa7, 0xc3, 0xa4, 0x6c, 0xe1, 0x9b, 0x97, 0xe1, - 0x9b, 0x81, 0xc2, 0xa5, 0xc8, 0x99, 0xc3, 0xa6, 0xc4, 0x9f, 0xc5, 0x89, 0xc8, 0xa2, - 0xc4, 0xb3, 0xc5, 0x9a, 0xc6, 0x90, 0x48, 0xc3, 0x80, 0xc6, 0xb6, 0xc5, 0x92, 0xe1, - 0x9b, 0xa8, 0xc2, 0xa3, 0xc7, 0xba, 0xc2, 0xa2, 0xc8, 0x87, 0xc3, 0xb1, 0xc7, 0xbb, - 0x6d, 0xc8, 0xa2, 0xc7, 0xa2, 0xc6, 0xaf, 0xe1, 0x9b, 0xa3, 0xc3, 0x86, 0xe1, 0x9b, - 0xa1, 0x60, 0x37, 0xc7, 0x91, 0x56, 0xc5, 0x95, 0xc4, 0xbc, 0xc5, 0xbe, 0xc4, 0x97, - 0x5a, 0x31, 0xc5, 0x89, 0xc9, 0x83, 0xc8, 0xb4, 0xc6, 0xa4, 0xc7, 0xb5, 0xe1, 0x9b, - 0x9e, 0xc3, 0xab, 0xcd, 0xb0, 0x56, 0xc7, 0x86, 0xc6, 0x99, 0xe1, 0x9b, 0x96, 0xc7, - 0x90, 0xe1, 0x9b, 0x95, 0xc4, 0xaf, 0xc8, 0xac, 0xe2, 0xb1, 0xa7, 0xc3, 0x91, 0xc9, - 0x8b, 0xc6, 0xad, 0xc5, 0x87, 0x5f, 0xe2, 0xb1, 0xb4, 0xc2, 0xb4, 0xc9, 0x8b, 0xc8, - 0x9b, 0xc7, 0x80, 0xc6, 0xbb, 0xc2, 0xbd, 0xc8, 0xbb, 0xc4, 0xa2, 0x48, 0xc7, 0xa1, - 0xc2, 0xa4, 0xc4, 0x86, 0xe2, 0xb1, 0xa8, 0xc6, 0x87, 0xc7, 0xb9, 0xe1, 0x9a, 0xa0, - 0xc6, 0xb0, 0xc6, 0xad, 0xc9, 0x83, 0xc7, 0x99, 0xc4, 0x9e, 0xe1, 0x9a, 0xbf, 0xc7, - 0xa6, 0x67, 0xc8, 0x95, 0xc3, 0x83, 0xe1, 0x9a, 0xa2, 0xce, 0x8a, 0x57, 0xc3, 0xa3, - 0xc7, 0x81, 0xc6, 0xab, 0xc6, 0xbe, 0x7b, 0xc3, 0x9e, 0xc7, 0x88, 0xe1, 0x9a, 0xae, - 0xc3, 0x94, 0xc6, 0x8e, 0xce, 0x88, 0xe1, 0x9b, 0x96, 0xc3, 0x85, 0xc4, 0xa9, 0xe2, - 0xb1, 0xb4, 0xc7, 0xab, 0xe1, 0x9b, 0x8e, 0xc4, 0xa9, 0xe2, 0xb1, 0xa1, 0xe2, 0xb1, - 0xa0, 0xc7, 0x96, 0xc3, 0xbe, 0xe1, 0x9a, 0xa2, 0xc4, 0xba, 0xe1, 0x9b, 0x95, 0xe2, - 0xb1, 0xaa, 0xc5, 0x88, 0xc6, 0xa2, 0xe1, 0x9b, 0x99, 0xc2, 0xaa, 0xe1, 0x9a, 0xa7, - 0xc6, 0x98, 0x72, 0xe1, 0x9b, 0x88, 0xc6, 0xa0, 0xc5, 0x8f, 0xc2, 0xa6, 0xc2, 0xb8, - 0xc5, 0x8f, 0xc6, 0x9f, 0xc7, 0xb0, 0xc4, 0xb8, 0xc9, 0x8f, 0xc7, 0xac, 0x6e, 0x44, - 0xe1, 0x9a, 0xba, 0xc3, 0xb3, 0xc3, 0x99, 0x5a, + 0xe1, 0x9b, 0x91, 0xc8, 0xa3, 0xe1, 0x9b, 0x8b, 0xc7, 0xac, 0xc8, 0xa0, 0xe1, 0x9b, + 0x89, 0xc3, 0x9b, 0xe1, 0x9b, 0xaa, 0xc6, 0xa7, 0xc9, 0x8e, 0xc2, 0xa2, 0xc2, 0xb2, + 0xe1, 0x9a, 0xbb, 0xc5, 0x9f, 0xc6, 0xaa, 0xc6, 0xbf, 0x69, 0xe1, 0x9b, 0xa9, 0xe1, + 0x9a, 0xae, 0xc4, 0xab, 0xe1, 0x9b, 0xa1, 0xc9, 0x8b, 0x23, 0xe1, 0x9b, 0x8a, 0xc7, + 0xa0, 0xe1, 0x9b, 0x88, 0xc4, 0xa6, 0xe1, 0x9b, 0xad, 0xc4, 0x9a, 0xe2, 0xb1, 0xb5, + 0xc7, 0xa7, 0x51, 0x78, 0x3f, 0xc3, 0xb0, 0xc8, 0x8a, 0x45, 0xc4, 0xa5, 0xc7, 0xb4, + 0xe1, 0x9a, 0xba, 0xe2, 0xb1, 0xbe, 0x38, 0xc2, 0xaa, 0xc8, 0xbb, 0xc8, 0xb2, 0xc6, + 0x86, 0xc6, 0xaa, 0xe1, 0x9b, 0xa2, 0xc8, 0xa7, 0xc5, 0x94, 0xc4, 0xad, 0x78, 0xc5, + 0x96, 0xe1, 0x9b, 0x81, 0xc9, 0x80, 0xc3, 0x93, 0xc6, 0xbe, 0xe1, 0x9a, 0xb0, 0x6d, + 0xc5, 0x90, 0xc4, 0x8a, 0x75, 0xc7, 0xa8, 0xc4, 0xac, 0xc4, 0x92, 0xc7, 0xa4, 0xc5, + 0x99, 0x25, 0xc6, 0xa1, 0xc5, 0x87, 0xc7, 0xa3, 0xce, 0x88, 0xc7, 0x8e, 0xc5, 0x85, + 0xe1, 0x9a, 0xb5, 0xe2, 0xb1, 0xad, 0xc4, 0x82, 0xc2, 0xb7, 0xc6, 0xac, 0xe1, 0x9b, + 0x82, 0x57, 0x30, 0xc3, 0xb0, 0xc7, 0xab, 0x69, 0xe1, 0x9b, 0x82, 0xc8, 0xb6, 0xc3, + 0xae, 0xe2, 0xb1, 0xab, 0x4f, 0xe1, 0x9a, 0xb5, 0xcd, 0xb5, 0xce, 0x88, 0xc4, 0x9f, + 0xc3, 0xb7, 0xc5, 0xb9, 0xc8, 0x88, 0x2f, 0xcd, 0xb7, 0xc8, 0x8f, 0xc8, 0xa4, 0xc5, + 0x95, 0xc3, 0xbc, 0x37, 0xe2, 0xb1, 0xb3, 0xc7, 0xa1, 0xc7, 0x89, 0xc4, 0x8d, 0xc5, + 0x87, 0x5f, 0xe1, 0x9a, 0xa2, 0xe1, 0x9b, 0x80, 0x76, 0xc7, 0xa6, 0xe2, 0xb1, 0xa2, + 0xe2, 0xb1, 0xb3, 0xc9, 0x83, 0xc3, 0xbd, 0x55, 0xe1, 0x9b, 0x84, 0xc7, 0xb6, 0xc9, + 0x8f, 0xc4, 0xa2, 0xc3, 0xbd, 0xe1, 0x9b, 0xa2, 0xc5, 0xb3, 0xc3, 0x90, 0x3d, 0xc6, + 0x8f, 0xc8, 0xbe, 0xc7, 0x99, 0xc5, 0xb4, 0xe2, 0xb1, 0xbd, 0xe2, 0xb1, 0xb4, 0xc8, + 0x9b, 0xc3, 0x81, 0xc6, 0xb0, 0x7d, 0xe2, 0xb1, 0xae, 0xc6, 0x85, 0xc5, 0x98, 0xc5, + 0x96, 0xc7, 0xb7, 0xc5, 0xa0, 0xcd, 0xbc, 0xc5, 0xa6, 0xe1, 0x9a, 0xb4, 0xc2, 0xa5, + 0xe1, 0x9b, 0xae, 0xc7, 0xbd, 0xc6, 0x9f, 0xc7, 0x81, 0xc6, 0x8e, 0x53, 0xc5, 0xb7, + 0xc2, 0xb0, 0xc7, 0xb6, 0xe1, 0x9b, 0xa6, 0xc7, 0x94, 0xe1, 0x9a, 0xa8, 0xc5, 0xa5, + 0xc8, 0xa6, 0x56, 0xc7, 0xae, 0xc6, 0x88, 0xe1, 0x9b, 0x8b, 0xc2, 0xb5, 0xe1, 0x9a, + 0xb5, 0xe1, 0x9a, 0xba, 0xe1, 0x9a, 0xa8, 0x32, 0xc2, 0xaf, 0xc6, 0xae, 0xce, 0x8a, + 0xc7, 0x92, 0xc2, 0xbf, 0xe1, 0x9b, 0x91, 0xc7, 0xb9, 0xc5, 0xa5, 0xc8, 0x95, 0xe2, + 0xb1, 0xb2, 0xc2, 0xa4, 0xc4, 0x9e, 0xc6, 0xa5, 0xc7, 0xb3, 0xc2, 0xa3, 0xe2, 0xb1, + 0xac, 0xe1, 0x9a, 0xa0, 0xc7, 0xa3, 0xcd, 0xb5, 0xc3, 0x9a, 0xc7, 0xaf, 0xc5, 0x87, + 0xe1, 0x9b, 0xa8, 0xc5, 0xaf, 0xc2, 0xbb, 0xc3, 0xae, 0xc6, 0xb9, 0xc6, 0x99, 0xc4, + 0xa7, 0xc3, 0x89, 0xe1, 0x9a, 0xbc, 0xc8, 0x95, 0xc5, 0x9e, 0xe1, 0x9a, 0xa6, 0xc4, + 0xab, 0xc8, 0x9b, 0xc5, 0xaf, 0xc3, 0x99, 0xc6, 0xaf, 0xe1, 0x9b, 0x90, 0xc8, 0xa7, + 0xc3, 0x97, 0x51, 0xc8, 0xab, 0xe2, 0xb1, 0xa2, 0x7d, 0x2c, 0x72, 0x36, 0x2b, 0xc3, + 0xb0, 0xc8, 0x8d, 0x46, 0xc5, 0x9d, 0xc4, 0xba, 0xc4, 0xa9, 0xc2, 0xa2, 0xc6, 0x9b, + 0xc3, 0xaf, 0x2f, 0xc8, 0x99, 0xe1, 0x9a, 0xb4, 0xc3, 0xba, 0xe1, 0x9b, 0x9b, 0xc2, + 0xa7, 0xc8, 0xb1, 0xe1, 0x9b, 0xae, 0xc7, 0xad, 0xe1, 0x9a, 0xaf, 0xc4, 0xbd, 0xc3, + 0x82, 0xc4, 0xaf, 0xc4, 0xb1, 0xe1, 0x9a, 0xaa, ], - asset_id: [ - 0x29, 0xb8, 0x07, 0x86, 0xde, 0xf6, 0x7e, 0xee, 0xe1, 0xfa, 0x1e, 0xb2, 0x4f, 0xd9, - 0xad, 0xf0, 0xab, 0xba, 0xe1, 0x70, 0x57, 0xeb, 0x4a, 0x04, 0x11, 0x13, 0xa4, 0x4e, - 0x9a, 0x1c, 0x92, 0x33, + asset_base: [ + 0x64, 0x0c, 0x81, 0x73, 0x79, 0x71, 0x4a, 0xe4, 0x8a, 0xf0, 0xbb, 0x83, 0x32, 0xf2, + 0x0d, 0x57, 0x7c, 0xb2, 0x42, 0x7e, 0x8f, 0x04, 0x49, 0x18, 0xee, 0xe5, 0x76, 0x45, + 0x05, 0x09, 0x6c, 0x97, ], }, TestVector { @@ -66,48 +66,48 @@ pub(crate) fn test_vectors() -> Vec { 0xd4, 0xff, 0xf7, 0x12, ], description: [ - 0x76, 0xc4, 0xb6, 0xc5, 0xb8, 0xe1, 0x9b, 0xa4, 0xc4, 0x9f, 0xc7, 0xb9, 0xc2, 0xb8, - 0xc7, 0x95, 0xc6, 0xbf, 0xc9, 0x87, 0xc5, 0xb3, 0xe1, 0x9b, 0xa1, 0xc5, 0xa9, 0xc3, - 0xa2, 0xc7, 0xb7, 0x77, 0xc6, 0xbf, 0xc6, 0xb5, 0xe1, 0x9a, 0xb6, 0xc3, 0xa2, 0xc5, - 0xbf, 0xe1, 0x9b, 0x82, 0xc4, 0x9c, 0xc6, 0xab, 0xc4, 0xbc, 0xc5, 0xb8, 0xe1, 0x9a, - 0xb6, 0xc7, 0xb7, 0xc2, 0xbe, 0xc7, 0x8e, 0xcd, 0xbd, 0xe1, 0x9a, 0xb4, 0xc8, 0x98, - 0xc8, 0x93, 0xc5, 0xb9, 0xc7, 0xb8, 0xc4, 0x8d, 0xe1, 0x9b, 0x86, 0xc7, 0x85, 0xc7, - 0x8e, 0xc4, 0x9f, 0xc5, 0xa3, 0x47, 0x7a, 0xc6, 0xa3, 0x5e, 0xe1, 0x9a, 0xa7, 0x66, - 0xc8, 0x9a, 0x45, 0xc4, 0x94, 0xc9, 0x8e, 0xc7, 0x9b, 0xc8, 0xbf, 0xe1, 0x9a, 0xa4, - 0x2b, 0xc6, 0xad, 0xc3, 0x9c, 0xc5, 0xbf, 0xc3, 0x91, 0xe1, 0x9b, 0xaf, 0xc5, 0x94, - 0xe1, 0x9b, 0x8d, 0xc2, 0xbb, 0xc4, 0xab, 0xc3, 0x88, 0xc4, 0xac, 0xe1, 0x9b, 0x96, - 0xcd, 0xb7, 0xc3, 0x97, 0x2b, 0x3c, 0xe1, 0x9b, 0x99, 0xc7, 0x91, 0xe1, 0x9a, 0xa4, - 0xc4, 0x8e, 0xc7, 0xa7, 0xe2, 0xb1, 0xac, 0xc2, 0xbc, 0xc4, 0x82, 0xc3, 0x81, 0xc6, - 0xb8, 0xe1, 0x9b, 0xa8, 0xe1, 0x9b, 0x95, 0xc4, 0xa4, 0xe1, 0x9b, 0xaa, 0xe1, 0x9a, - 0xa0, 0xc5, 0xbe, 0xe1, 0x9b, 0x8a, 0x34, 0xc7, 0x82, 0x7d, 0xe1, 0x9a, 0xbe, 0xc4, - 0x83, 0xe1, 0x9a, 0xa5, 0xc5, 0x8d, 0x51, 0xc8, 0xa9, 0xc9, 0x81, 0xc7, 0xa9, 0xc4, - 0x8f, 0xe2, 0xb1, 0xa2, 0x58, 0xc3, 0x9d, 0xc6, 0x94, 0xce, 0x85, 0xc7, 0xbe, 0xc4, - 0x89, 0x3c, 0xc2, 0xa3, 0xc7, 0xaf, 0xc3, 0x9b, 0xc7, 0xae, 0xc8, 0x89, 0xc9, 0x88, - 0xc5, 0xa8, 0xe2, 0xb1, 0xa9, 0xc5, 0xa3, 0x67, 0xc6, 0xa8, 0xe1, 0x9a, 0xb3, 0xc7, - 0x95, 0xc5, 0xa9, 0xc5, 0xa0, 0xc5, 0x84, 0xe1, 0x9a, 0xbf, 0xc7, 0xb4, 0xc9, 0x8a, - 0xc4, 0xbc, 0xc5, 0xbb, 0xc7, 0x99, 0xc3, 0x8e, 0xe1, 0x9a, 0xb0, 0xc5, 0x87, 0xe2, - 0xb1, 0xb0, 0xe1, 0x9a, 0xab, 0xc4, 0x8f, 0xc5, 0xb8, 0xc5, 0x90, 0xc5, 0xbc, 0xc3, - 0x80, 0xc3, 0xbc, 0xc4, 0x8a, 0xc5, 0xbb, 0x64, 0x3e, 0xc2, 0xa7, 0xc6, 0xb3, 0xe2, - 0xb1, 0xb6, 0xc8, 0xa4, 0x72, 0x71, 0xe1, 0x9b, 0x92, 0x3c, 0xc4, 0x99, 0xe2, 0xb1, - 0xb5, 0xc7, 0x81, 0xc4, 0xbd, 0xc8, 0xa6, 0xc4, 0xa8, 0xe1, 0x9a, 0xa1, 0xc3, 0x85, - 0xc6, 0x8f, 0xc2, 0xb9, 0xc7, 0x9b, 0xc7, 0xa7, 0xe1, 0x9a, 0xb3, 0xc8, 0x99, 0xc7, - 0xb4, 0xe1, 0x9b, 0xa6, 0xc3, 0x94, 0xe1, 0x9b, 0x91, 0xc6, 0xb7, 0x31, 0xc7, 0xb2, - 0xc3, 0x9e, 0xc7, 0xad, 0xc3, 0xa4, 0xc4, 0x97, 0xcd, 0xb5, 0xe1, 0x9a, 0xac, 0x63, - 0xc7, 0x96, 0xe2, 0xb1, 0xa3, 0xc8, 0x86, 0xc4, 0x97, 0x37, 0xc5, 0xa9, 0xc2, 0xa5, - 0xc4, 0xbf, 0xc7, 0x85, 0xc2, 0xa4, 0xe1, 0x9a, 0xa6, 0xc5, 0xba, 0xc6, 0xb3, 0xc5, - 0xb5, 0x36, 0x4e, 0x6e, 0xc5, 0x90, 0xc3, 0x80, 0xc7, 0xbd, 0xc6, 0x88, 0xc3, 0xb4, - 0xe2, 0xb1, 0xa6, 0xc8, 0xa4, 0xc8, 0xb0, 0xe1, 0x9a, 0xa0, 0xc3, 0x84, 0xc8, 0x8b, - 0xcd, 0xbe, 0xc5, 0x80, 0xc8, 0x9e, 0xc3, 0x99, 0xc4, 0x8a, 0xc3, 0x83, 0x3e, 0x28, - 0x4a, 0xe1, 0x9b, 0x85, 0xce, 0x87, 0xc5, 0x82, 0xc8, 0xbb, 0xc8, 0x8d, 0xc4, 0x88, - 0xc6, 0x9e, 0xc6, 0x98, 0xc5, 0xbf, 0x45, 0xc7, 0xb2, 0xe1, 0x9a, 0xbb, 0xe1, 0x9b, - 0x9a, 0xc4, 0xb5, 0xc2, 0xae, 0xc9, 0x80, 0xc6, 0x88, 0xc3, 0x8c, 0xc8, 0xa5, 0xc2, - 0xb8, 0x35, 0xc7, 0xba, 0xc6, 0xac, 0x58, 0xc4, 0x97, 0x7e, 0xc7, 0x98, 0xc3, 0xbd, - 0xc2, 0xb9, 0xc8, 0x99, 0xe1, 0x9b, 0x8c, 0x5a, + 0xc6, 0x89, 0xc8, 0x9f, 0xc4, 0xa2, 0xe1, 0x9a, 0xb6, 0xc7, 0xa7, 0xe2, 0xb1, 0xa8, + 0xc2, 0xbc, 0xe2, 0xb1, 0xa2, 0xc3, 0x8d, 0x73, 0xc3, 0xa1, 0xc7, 0xbf, 0xc7, 0xa5, + 0xc7, 0xb3, 0xc6, 0x83, 0x7d, 0xc5, 0x85, 0x3c, 0xc8, 0x9d, 0x6a, 0x51, 0xc8, 0xac, + 0xe1, 0x9a, 0xb6, 0xce, 0x85, 0xc5, 0xbf, 0xc7, 0xb5, 0xe1, 0x9a, 0xb3, 0xc4, 0xa4, + 0xc2, 0xb9, 0x50, 0xe2, 0xb1, 0xa7, 0xc2, 0xb7, 0xc7, 0x91, 0xe1, 0x9b, 0xb0, 0xc4, + 0x8b, 0xe2, 0xb1, 0xae, 0xc3, 0x8a, 0xc4, 0x93, 0xc5, 0xac, 0xc2, 0xa2, 0xe2, 0xb1, + 0xad, 0xc3, 0x8e, 0xe1, 0x9b, 0x84, 0xc9, 0x88, 0xc5, 0xb1, 0xc4, 0xbb, 0xc4, 0x80, + 0xcd, 0xb5, 0xc5, 0xba, 0x45, 0xe1, 0x9a, 0xbe, 0xe2, 0xb1, 0xbd, 0xc9, 0x82, 0xc4, + 0xa2, 0x62, 0xc7, 0x91, 0x2e, 0xc7, 0x82, 0xc8, 0x92, 0xc8, 0x9e, 0xc7, 0x8f, 0xe1, + 0x9b, 0x9a, 0xc8, 0xa9, 0xc4, 0x9b, 0xc3, 0x9a, 0xc4, 0x9a, 0xc3, 0x8d, 0xc8, 0x88, + 0xc4, 0x8d, 0xc2, 0xa9, 0xcd, 0xbc, 0x5e, 0xc8, 0xb7, 0xcd, 0xbe, 0xc2, 0xb0, 0xe2, + 0xb1, 0xb0, 0xc3, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x84, 0xc7, 0x82, 0xc7, 0xb9, 0xc8, + 0xb6, 0xc9, 0x87, 0xc5, 0xbb, 0xc2, 0xb1, 0xc4, 0xaf, 0x73, 0xcd, 0xb4, 0x54, 0xc5, + 0xb6, 0xc7, 0x97, 0xc3, 0x87, 0xce, 0x87, 0xc6, 0xb3, 0x69, 0xc4, 0x84, 0xe1, 0x9b, + 0x9a, 0xc5, 0x91, 0xc7, 0x89, 0xc2, 0xa2, 0x2e, 0xc6, 0x85, 0xc5, 0x94, 0xc4, 0xbf, + 0xc3, 0xa8, 0xc6, 0xbc, 0xc7, 0x9c, 0xe2, 0xb1, 0xa5, 0x6e, 0xc6, 0xb4, 0xc8, 0xa1, + 0xc6, 0x91, 0xc6, 0x91, 0xc6, 0xa9, 0xe1, 0x9b, 0x88, 0xc7, 0x90, 0xc4, 0xb3, 0xe1, + 0x9a, 0xb9, 0xc4, 0x87, 0xc5, 0xbc, 0xe2, 0xb1, 0xae, 0xc3, 0x83, 0xe1, 0x9b, 0x9e, + 0xc5, 0x89, 0xc8, 0x9d, 0x66, 0xe2, 0xb1, 0xae, 0xc5, 0x98, 0xc4, 0xb5, 0xc8, 0x9f, + 0xc8, 0xaa, 0xc9, 0x86, 0xe1, 0x9a, 0xa3, 0xc5, 0x94, 0xc7, 0x8d, 0xc6, 0x90, 0xc7, + 0xb2, 0xc7, 0x9b, 0xc7, 0xb2, 0xc4, 0xa4, 0xc7, 0x88, 0xc8, 0xa5, 0xc6, 0x9a, 0xc4, + 0x8b, 0x39, 0xc7, 0xb8, 0x3c, 0xc8, 0xa8, 0xc6, 0x89, 0xc7, 0xb2, 0xc7, 0x98, 0xc3, + 0xb0, 0xc3, 0xb2, 0xc6, 0xa0, 0xc5, 0xa5, 0xc8, 0x90, 0x47, 0xc5, 0x9f, 0xc8, 0x8f, + 0xc7, 0x98, 0xc3, 0xb6, 0xe1, 0x9a, 0xa5, 0x2f, 0xc9, 0x89, 0xc8, 0xb0, 0xc7, 0x9f, + 0xc4, 0x80, 0xe2, 0xb1, 0xa2, 0x74, 0xe1, 0x9b, 0x82, 0xc3, 0x90, 0xc7, 0xb6, 0xc8, + 0xa4, 0xe2, 0xb1, 0xa7, 0xc6, 0xb4, 0xc7, 0xbe, 0x71, 0xc5, 0x8d, 0xe2, 0xb1, 0xbd, + 0xc6, 0x97, 0xc6, 0x95, 0x72, 0xc4, 0xa9, 0xe1, 0x9b, 0xaf, 0xc5, 0xa8, 0xc6, 0x89, + 0xc6, 0xad, 0xe2, 0xb1, 0xae, 0xc7, 0xb1, 0x6c, 0xc5, 0xab, 0xe2, 0xb1, 0xbe, 0xe1, + 0x9b, 0x8e, 0xc3, 0x96, 0xe1, 0x9b, 0xa7, 0x65, 0xc6, 0xab, 0xe1, 0x9b, 0x97, 0xc6, + 0x90, 0xe1, 0x9b, 0xa9, 0xe1, 0x9a, 0xa4, 0xc7, 0x8a, 0x5b, 0xe2, 0xb1, 0xa6, 0xc5, + 0xbf, 0xc9, 0x86, 0xc8, 0x8b, 0xc6, 0xbd, 0xc5, 0xab, 0xc3, 0x90, 0xc2, 0xbb, 0xc8, + 0xb4, 0xc5, 0x84, 0xc3, 0xa0, 0xc6, 0x91, 0xc9, 0x8e, 0xc4, 0x87, 0xe2, 0xb1, 0xa5, + 0x71, 0xe1, 0x9a, 0xbb, 0xc7, 0x90, 0xc8, 0x85, 0xc6, 0x84, 0xce, 0x8a, 0xe2, 0xb1, + 0xbf, 0xc3, 0x9d, 0xc4, 0xbe, 0xc5, 0xac, 0x53, 0xc4, 0x8b, 0xc7, 0x97, 0xc6, 0x8d, + 0xe2, 0xb1, 0xb0, 0xc6, 0x87, 0xe1, 0x9b, 0x9a, 0xc7, 0x8c, 0xe1, 0x9b, 0x90, 0xc3, + 0xa4, 0xc4, 0xa7, 0xc7, 0xb9, 0x7a, 0xe1, 0x9b, 0x98, 0x2a, 0x46, 0x65, 0xc8, 0x88, + 0x78, 0xc7, 0x83, 0xe1, 0x9b, 0xa7, 0xc3, 0xbf, ], - asset_id: [ - 0x35, 0x52, 0x83, 0x87, 0xd4, 0x4d, 0x74, 0x21, 0xa9, 0x78, 0xad, 0x56, 0xe5, 0x33, - 0xf3, 0x6e, 0x85, 0xec, 0xac, 0x44, 0x9f, 0x3b, 0x3f, 0x68, 0xe7, 0xff, 0x39, 0x7f, - 0xae, 0x24, 0x5a, 0x99, + asset_base: [ + 0xd6, 0x9d, 0x7b, 0xa8, 0xcd, 0x66, 0x3c, 0xf9, 0x52, 0x8f, 0x01, 0x0a, 0x2d, 0xee, + 0x7b, 0x42, 0x9f, 0xe5, 0x62, 0x65, 0x50, 0x09, 0x30, 0x52, 0x90, 0x5a, 0xa9, 0x09, + 0x88, 0x38, 0x8d, 0x06, ], }, TestVector { @@ -117,48 +117,48 @@ pub(crate) fn test_vectors() -> Vec { 0x45, 0x02, 0x53, 0x01, ], description: [ - 0xc7, 0x8e, 0x4f, 0xc2, 0xbb, 0x39, 0xc3, 0xa4, 0xc4, 0x94, 0xc5, 0xbb, 0xc5, 0xa6, - 0xc2, 0xab, 0xc2, 0xba, 0xc7, 0x9e, 0xc5, 0x88, 0xc8, 0x9c, 0x57, 0xc3, 0xbc, 0xe2, - 0xb1, 0xb7, 0xe1, 0x9a, 0xa9, 0x3a, 0xc3, 0x84, 0xc5, 0x9b, 0xc8, 0xb5, 0xc5, 0x80, - 0xc9, 0x81, 0xc7, 0xa7, 0xc5, 0x92, 0xc6, 0x9b, 0xc7, 0x86, 0xc8, 0xba, 0xc6, 0x88, - 0xc9, 0x85, 0xc3, 0xab, 0xc8, 0x94, 0xc8, 0x92, 0xc7, 0xa2, 0xc7, 0x82, 0xc4, 0x91, - 0x74, 0x62, 0xc5, 0x9b, 0x42, 0xc8, 0xbe, 0xc3, 0xa7, 0xc4, 0xb8, 0xc2, 0xaf, 0xc6, - 0x8d, 0x39, 0xc7, 0xb3, 0xc8, 0x97, 0xc8, 0x91, 0xc2, 0xbb, 0xc4, 0x87, 0xe1, 0x9b, - 0x8a, 0xc2, 0xa7, 0xc7, 0xb4, 0xc4, 0xbb, 0xc2, 0xb2, 0xc8, 0x9a, 0xe1, 0x9a, 0xa3, - 0xc3, 0x92, 0x36, 0xe1, 0x9b, 0x9d, 0xc7, 0x8f, 0xc8, 0x90, 0xc8, 0xb3, 0x36, 0x49, - 0xc4, 0x92, 0xe1, 0x9b, 0x84, 0xc6, 0x94, 0xc8, 0xba, 0xc9, 0x8c, 0xc7, 0x85, 0xc6, - 0x94, 0xc6, 0x87, 0xc6, 0xb6, 0xc4, 0xba, 0xc5, 0xb4, 0x51, 0xe1, 0x9a, 0xb7, 0xc3, - 0xbb, 0xcd, 0xbb, 0xc7, 0x89, 0xc3, 0xba, 0xc6, 0x93, 0xc2, 0xa7, 0xc3, 0xa1, 0xc3, - 0x8f, 0x7b, 0xc7, 0xa9, 0xc6, 0x92, 0x4b, 0xe1, 0x9b, 0xb0, 0xc8, 0xb3, 0xc5, 0x9a, - 0xe1, 0x9a, 0xb8, 0x71, 0xc9, 0x88, 0x4c, 0x25, 0xc7, 0x9b, 0xe1, 0x9b, 0x9a, 0xc2, - 0xb7, 0xc4, 0xb1, 0xe1, 0x9b, 0x97, 0x64, 0xe1, 0x9b, 0xa3, 0xc5, 0xb4, 0xe2, 0xb1, - 0xb1, 0xc9, 0x8d, 0x60, 0xe1, 0x9b, 0xa7, 0xe1, 0x9b, 0xa3, 0xc5, 0x84, 0xc4, 0x94, - 0xc7, 0xb8, 0xc8, 0x9c, 0x7c, 0xc3, 0xaa, 0x36, 0xc2, 0xa4, 0xc3, 0xa8, 0xe1, 0x9b, - 0x9f, 0xc3, 0x95, 0xc8, 0xa1, 0xc3, 0xac, 0xc4, 0x99, 0xc7, 0xa4, 0xc8, 0x93, 0xc8, - 0xb0, 0xc8, 0xa2, 0xc6, 0xb4, 0xc6, 0xa4, 0xe1, 0x9a, 0xaa, 0xc9, 0x85, 0xc2, 0xa5, - 0xcd, 0xbd, 0xc4, 0x97, 0xc4, 0xb2, 0xc4, 0xa7, 0xc4, 0x91, 0xc7, 0xbe, 0xe2, 0xb1, - 0xb4, 0xc9, 0x87, 0xc5, 0xab, 0xc7, 0x84, 0xc5, 0x9c, 0xe2, 0xb1, 0xaf, 0x55, 0xe2, - 0xb1, 0xaf, 0x23, 0xc4, 0x8e, 0xc5, 0xba, 0xc5, 0xaf, 0xc8, 0xaf, 0xe2, 0xb1, 0xa0, - 0x56, 0xc7, 0xb2, 0xc6, 0xb7, 0xc6, 0x90, 0xc6, 0x8d, 0x5e, 0xc6, 0xb5, 0xe1, 0x9a, - 0xb7, 0xc3, 0x89, 0xc8, 0x91, 0xc6, 0x9a, 0x74, 0x4f, 0xc4, 0xb1, 0xc7, 0xae, 0xc4, - 0xaa, 0xc3, 0xae, 0xc6, 0x9f, 0xc3, 0x99, 0xc8, 0x87, 0xe1, 0x9b, 0x9d, 0xe1, 0x9a, - 0xa4, 0xe1, 0x9b, 0xad, 0xc8, 0x93, 0xc6, 0x94, 0xc8, 0x82, 0xc7, 0xa8, 0xc6, 0xba, - 0xc6, 0x90, 0xc3, 0x88, 0xc6, 0xbb, 0xc9, 0x88, 0xc2, 0xa5, 0xc6, 0xad, 0xe1, 0x9a, - 0xb0, 0xc4, 0xbb, 0x47, 0x2e, 0xc6, 0x92, 0xc6, 0x8b, 0xe1, 0x9a, 0xaa, 0xc7, 0x80, - 0xe1, 0x9a, 0xa0, 0xc6, 0xab, 0xc3, 0xaf, 0xc8, 0xb9, 0xe1, 0x9b, 0x8f, 0xe1, 0x9a, - 0xb9, 0xc3, 0xa9, 0xc5, 0x8e, 0x68, 0xc8, 0xaa, 0xc4, 0xb6, 0xe2, 0xb1, 0xbd, 0xe1, - 0x9b, 0xad, 0xc7, 0xa6, 0xc5, 0x96, 0xc6, 0x82, 0xc7, 0x84, 0x3f, 0xc3, 0x97, 0xc4, - 0xbe, 0xc8, 0x91, 0xc6, 0xaa, 0x41, 0xc4, 0xa9, 0xc6, 0x80, 0xc2, 0xb7, 0xe2, 0xb1, - 0xb1, 0xc2, 0xa3, 0xc6, 0xa8, 0xe1, 0x9a, 0xa7, 0xc2, 0xaf, 0xc8, 0x83, 0xe1, 0x9b, - 0xac, 0x37, 0xc4, 0x8f, 0xc5, 0xb9, 0xe2, 0xb1, 0xb8, 0xc3, 0x8f, 0xc6, 0xb1, 0xc4, - 0xaa, 0xc5, 0x97, 0xe2, 0xb1, 0xab, 0xe1, 0x9b, 0x80, 0x58, 0xe1, 0x9b, 0x8b, 0xc8, - 0xb8, 0x2c, 0x21, 0x36, 0xc5, 0xb3, 0xc6, 0xaa, 0xc7, 0x8a, 0xc4, 0xa3, 0xc4, 0xb6, - 0xc5, 0xa4, 0xc5, 0x92, 0xe1, 0x9a, 0xbf, 0x5a, + 0xe1, 0x9a, 0xa0, 0xc7, 0xbb, 0xe1, 0x9b, 0xa1, 0xce, 0x8a, 0xc8, 0xb3, 0x31, 0xc8, + 0xba, 0xc8, 0x95, 0xc7, 0xae, 0xcd, 0xb5, 0xc4, 0xac, 0xc3, 0x87, 0x6b, 0xc3, 0xbd, + 0xc3, 0x9a, 0xc8, 0x83, 0xc7, 0x92, 0x48, 0xe1, 0x9b, 0x90, 0xe2, 0xb1, 0xb2, 0xc6, + 0x89, 0xe1, 0x9a, 0xa7, 0xc6, 0x81, 0xc2, 0xa9, 0xe1, 0x9b, 0x9c, 0xe1, 0x9b, 0xac, + 0xc3, 0xa8, 0xc5, 0xae, 0xc8, 0x8f, 0xc4, 0x96, 0xc3, 0x8e, 0xcd, 0xbb, 0xe1, 0x9b, + 0xaf, 0xc3, 0xa2, 0xc4, 0x92, 0xc5, 0xb2, 0xc6, 0x9f, 0xc3, 0xbb, 0xc5, 0xb5, 0xe2, + 0xb1, 0xb4, 0xc4, 0x95, 0xc7, 0x9f, 0xe1, 0x9a, 0xaf, 0xc9, 0x82, 0xc7, 0x8d, 0xc5, + 0x8c, 0xc3, 0x90, 0xe1, 0x9b, 0xa5, 0xe1, 0x9b, 0x94, 0xc9, 0x89, 0xe2, 0xb1, 0xa9, + 0xc4, 0x90, 0xc7, 0xa2, 0xc4, 0x8c, 0xc7, 0xbf, 0xc3, 0x80, 0xc6, 0x83, 0xc6, 0x95, + 0x24, 0x23, 0xe1, 0x9b, 0x90, 0xe1, 0x9a, 0xa3, 0xc3, 0x96, 0xc9, 0x8a, 0xc5, 0xb6, + 0x48, 0xc7, 0x9b, 0xc2, 0xaf, 0xc8, 0x86, 0xc5, 0xb9, 0xc8, 0x9b, 0x52, 0xc5, 0xa4, + 0x56, 0xe1, 0x9b, 0x9d, 0xe1, 0x9b, 0x95, 0xe1, 0x9a, 0xba, 0xc4, 0xa7, 0xc5, 0xaa, + 0xe2, 0xb1, 0xa6, 0xc8, 0xb5, 0x62, 0x4c, 0xe1, 0x9b, 0xaf, 0xc7, 0xab, 0xc5, 0x86, + 0xc5, 0x9d, 0x39, 0xc6, 0x9d, 0x3d, 0xc6, 0x82, 0xc8, 0x91, 0xe2, 0xb1, 0xaa, 0xc6, + 0xb8, 0xc5, 0x96, 0xc3, 0x90, 0xc3, 0xa5, 0x31, 0xc8, 0x94, 0x7d, 0xc7, 0xae, 0x56, + 0xc8, 0xaa, 0x66, 0xc7, 0x8d, 0x79, 0xc4, 0x9b, 0xc7, 0xb9, 0xc2, 0xbb, 0xc4, 0x84, + 0xce, 0x85, 0xc3, 0x9c, 0xc9, 0x83, 0xc8, 0xbc, 0xc8, 0x83, 0xc7, 0x96, 0xc6, 0xbf, + 0x28, 0xe1, 0x9a, 0xa1, 0xc6, 0xb3, 0xe2, 0xb1, 0xb5, 0xc4, 0x92, 0xc4, 0x92, 0xc2, + 0xa9, 0xc2, 0xb2, 0xc3, 0xad, 0xe2, 0xb1, 0xbe, 0xc6, 0xb3, 0xc8, 0x89, 0xc9, 0x8b, + 0xc4, 0x94, 0xc6, 0xa5, 0x2a, 0xc6, 0x8b, 0xe1, 0x9b, 0xa3, 0xe1, 0x9a, 0xa4, 0xc7, + 0x85, 0xc7, 0x8f, 0xc6, 0x90, 0xc7, 0xa3, 0xc7, 0xbe, 0xc3, 0x9e, 0xc2, 0xbd, 0x25, + 0xc8, 0xaf, 0xc6, 0x92, 0xe1, 0x9b, 0xab, 0xc8, 0xb9, 0x59, 0xc5, 0x93, 0xc7, 0xbf, + 0xc3, 0x96, 0xc6, 0xbf, 0xc3, 0xb0, 0xc6, 0x9e, 0xc9, 0x83, 0x35, 0xe2, 0xb1, 0xa1, + 0xc5, 0xaf, 0xc8, 0x9b, 0xc4, 0x9f, 0xc2, 0xa2, 0xcd, 0xb7, 0xc5, 0x83, 0xc6, 0x9b, + 0xc8, 0x92, 0xcd, 0xb7, 0xc8, 0xba, 0xc2, 0xa8, 0x44, 0xc4, 0xa6, 0xe1, 0x9a, 0xb8, + 0xc7, 0xa1, 0xc8, 0xa4, 0xc4, 0xbe, 0x6b, 0xc6, 0xa1, 0xc7, 0xa5, 0x4f, 0xc2, 0xa1, + 0xc8, 0x9b, 0xc4, 0xb8, 0x6e, 0xc3, 0x8f, 0xc6, 0xb5, 0xc4, 0x9c, 0xe1, 0x9b, 0x87, + 0xc5, 0x8a, 0xe2, 0xb1, 0xa7, 0xc3, 0x8d, 0xc4, 0x9b, 0xc7, 0xb0, 0x7a, 0xc7, 0x88, + 0xc5, 0xa7, 0x2e, 0xc2, 0xbb, 0xc3, 0x95, 0x6c, 0xe2, 0xb1, 0xa6, 0xe1, 0x9a, 0xad, + 0xc7, 0x85, 0xc9, 0x80, 0xc8, 0xa2, 0xc8, 0xaa, 0xe1, 0x9b, 0x9e, 0xc7, 0x9e, 0xc3, + 0x8b, 0xc6, 0xb4, 0xc8, 0x8c, 0xc9, 0x85, 0xc5, 0xab, 0xc5, 0x8a, 0x26, 0xc5, 0xa5, + 0xc3, 0x98, 0x30, 0xe1, 0x9b, 0x8b, 0xc5, 0xb3, 0xe2, 0xb1, 0xa9, 0x51, 0x33, 0xc6, + 0x85, 0x75, 0xc9, 0x82, 0xe1, 0x9a, 0xaa, 0xc6, 0x89, 0xe1, 0x9a, 0xb7, 0xc7, 0x81, + 0xc4, 0xa4, 0xc8, 0x86, 0xc3, 0xaf, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xab, 0xc7, 0x96, + 0x68, 0xc4, 0x93, 0x3f, 0xc3, 0x99, 0xc2, 0xb7, 0xc8, 0x8b, 0xc7, 0xb3, 0xc5, 0xa5, + 0xe1, 0x9b, 0xa9, 0xc5, 0x84, 0xc4, 0xa7, 0xc5, 0x99, 0xc4, 0xae, 0xc9, 0x87, 0xe1, + 0x9a, 0xba, 0xc4, 0x8a, 0xc4, 0xb2, 0x6d, 0x5a, ], - asset_id: [ - 0xf5, 0x4b, 0x0c, 0x9b, 0xad, 0x5a, 0x85, 0x26, 0x2b, 0x8a, 0x3b, 0xa4, 0x13, 0x6a, - 0x5b, 0x4c, 0xf3, 0x23, 0x85, 0xca, 0x49, 0x2f, 0x09, 0x4a, 0x42, 0xb2, 0xf6, 0xad, - 0x65, 0xc1, 0x07, 0x33, + asset_base: [ + 0x8e, 0x9c, 0x21, 0x17, 0xed, 0x4f, 0x4e, 0xe8, 0x9a, 0xb8, 0xb3, 0x53, 0xf5, 0xfd, + 0xd0, 0xcb, 0xde, 0xb7, 0xf2, 0xc9, 0x55, 0xfa, 0xdc, 0x7b, 0x1a, 0xda, 0x09, 0x97, + 0x56, 0x11, 0x72, 0x85, ], }, TestVector { @@ -168,48 +168,48 @@ pub(crate) fn test_vectors() -> Vec { 0x28, 0x88, 0xc6, 0x0e, ], description: [ - 0xce, 0x88, 0xcd, 0xb5, 0xc6, 0x9f, 0xc6, 0xa5, 0xc8, 0x9e, 0xc7, 0xb2, 0xc7, 0xbc, - 0x7d, 0xc3, 0xb9, 0xc5, 0x84, 0xc5, 0x8b, 0xc4, 0x9a, 0xc3, 0xb4, 0xc7, 0x9a, 0xe2, - 0xb1, 0xa1, 0xc7, 0xb4, 0xc3, 0x8d, 0xe1, 0x9a, 0xab, 0xc7, 0x92, 0xe1, 0x9b, 0xaa, - 0xc5, 0x88, 0x26, 0xc5, 0xba, 0xc4, 0xad, 0xc5, 0xb5, 0xc3, 0xa3, 0xc5, 0xa8, 0x30, - 0xc5, 0xaf, 0xc8, 0x96, 0xe1, 0x9b, 0xa6, 0xe1, 0x9b, 0xa9, 0xc2, 0xb2, 0xc7, 0xaa, - 0xc4, 0x93, 0xc8, 0x8f, 0xc5, 0xac, 0xe1, 0x9a, 0xa7, 0xc4, 0x89, 0xc8, 0xbc, 0xc3, - 0xb9, 0xc6, 0xb6, 0xe1, 0x9b, 0x99, 0xc7, 0xae, 0xc4, 0xa6, 0xc7, 0xb9, 0x7c, 0xce, - 0x88, 0xc3, 0xbe, 0xc5, 0x9c, 0xc8, 0x82, 0xc6, 0x88, 0xc7, 0x9a, 0xc6, 0xbb, 0xcd, - 0xb6, 0xc7, 0x8a, 0xc5, 0x88, 0xe1, 0x9a, 0xa2, 0x52, 0xc4, 0xae, 0xc2, 0xa9, 0xc5, - 0x9b, 0xc4, 0x83, 0x74, 0xc8, 0x9e, 0xc3, 0xb4, 0xc3, 0x82, 0x30, 0xc3, 0xbd, 0xc3, - 0x87, 0xc8, 0xba, 0xc5, 0xb1, 0xc8, 0x85, 0x6b, 0xc4, 0xb7, 0xc5, 0x9d, 0x57, 0xc7, - 0x90, 0xc6, 0xb9, 0x45, 0xc4, 0x9f, 0xc7, 0x8d, 0xc5, 0xa8, 0xc5, 0x8f, 0xc3, 0xaf, - 0xc3, 0xb3, 0xc3, 0xb3, 0xc3, 0xb1, 0xc2, 0xac, 0xc5, 0xb7, 0xe2, 0xb1, 0xa2, 0xc8, - 0xbb, 0xc7, 0xa7, 0xe1, 0x9a, 0xb9, 0xc5, 0xb2, 0xc5, 0xbd, 0xc6, 0xaf, 0xc3, 0xac, - 0xe1, 0x9b, 0xb0, 0xc7, 0x9d, 0xc4, 0x8a, 0xc6, 0xa9, 0xc5, 0xaa, 0xc3, 0x8e, 0xc2, - 0xa7, 0xc7, 0xaa, 0xc4, 0x90, 0x66, 0xe2, 0xb1, 0xb7, 0xe1, 0x9a, 0xbc, 0xc6, 0xbc, - 0xc5, 0x91, 0xc8, 0xbb, 0x44, 0xce, 0x8c, 0xc8, 0x84, 0xc8, 0x92, 0xe1, 0x9a, 0xbb, - 0xe1, 0x9a, 0xa2, 0xc6, 0x88, 0xc7, 0xb7, 0xc6, 0xa1, 0xe1, 0x9b, 0x90, 0xc4, 0xa2, - 0xc4, 0x92, 0x36, 0xc6, 0xb8, 0xc4, 0xaa, 0xc2, 0xb3, 0xe1, 0x9b, 0x81, 0xc9, 0x87, - 0xc7, 0xbc, 0x3b, 0xc8, 0xbc, 0xc8, 0x8e, 0xc3, 0xaa, 0xc9, 0x8a, 0xc6, 0x94, 0xe2, - 0xb1, 0xb4, 0xc5, 0x9a, 0xe1, 0x9b, 0x92, 0xc8, 0xa2, 0xc4, 0xb6, 0xc4, 0x91, 0xcd, - 0xbe, 0xc8, 0xac, 0xc4, 0xb5, 0xcd, 0xbc, 0x3d, 0xe1, 0x9b, 0xa7, 0xc2, 0xab, 0xc2, - 0xa8, 0xc6, 0xb0, 0xc4, 0x84, 0xc3, 0xb5, 0xe1, 0x9a, 0xb8, 0xc6, 0x96, 0xc3, 0x99, - 0x65, 0x56, 0xc3, 0xb9, 0xc8, 0xb0, 0xc4, 0xb2, 0xcd, 0xb6, 0x71, 0xc3, 0xb8, 0xc7, - 0xb6, 0xc8, 0x8b, 0xc3, 0xa3, 0xe1, 0x9b, 0x8f, 0x6c, 0xc4, 0xad, 0xc3, 0xa2, 0xc2, - 0xb2, 0xe1, 0x9a, 0xb6, 0xe1, 0x9b, 0x98, 0xe1, 0x9b, 0xae, 0xc8, 0xa2, 0xc2, 0xb6, - 0xc8, 0xb3, 0xc6, 0xbe, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0x90, 0xe1, 0x9b, 0x89, 0xc3, - 0xbc, 0xe2, 0xb1, 0xa2, 0xc5, 0xb3, 0xc3, 0x84, 0xc7, 0x95, 0xc5, 0x9d, 0xc4, 0xba, - 0xe2, 0xb1, 0xb6, 0xc2, 0xa8, 0x78, 0xc8, 0xad, 0xc3, 0xae, 0xc6, 0x88, 0xc3, 0x9e, - 0xc3, 0xa9, 0xc3, 0x9d, 0xe2, 0xb1, 0xaf, 0xc5, 0x8c, 0xe2, 0xb1, 0xa1, 0xc5, 0xbc, - 0xe1, 0x9a, 0xab, 0xc8, 0xbf, 0xc7, 0x8b, 0xc6, 0xb2, 0x21, 0xc3, 0x93, 0xc5, 0xa5, - 0x6d, 0xcd, 0xb2, 0xe1, 0x9b, 0x88, 0x5e, 0xe1, 0x9a, 0xb6, 0xc5, 0xb1, 0xc7, 0x87, - 0xc8, 0x9a, 0xc7, 0xa6, 0xc2, 0xaf, 0xe1, 0x9b, 0xa6, 0xc4, 0x86, 0xc2, 0xb1, 0x29, - 0xe1, 0x9a, 0xb9, 0xc7, 0x90, 0xc9, 0x8a, 0xc4, 0xab, 0xe1, 0x9b, 0x8e, 0xc7, 0x90, - 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0xa5, 0xc6, 0xb8, 0xc4, 0xa6, 0xe1, 0x9b, 0x8a, 0xc5, - 0xb2, 0xc6, 0xa8, 0xc6, 0x8e, 0xc2, 0xbe, 0xc8, 0xbd, 0xc8, 0xa5, 0xc5, 0xa5, 0xc6, - 0x90, 0x3f, 0xc7, 0xa8, 0xc4, 0xaf, 0xc2, 0xaa, + 0xc6, 0xb9, 0xe2, 0xb1, 0xae, 0xe2, 0xb1, 0xbc, 0xc7, 0x97, 0xe1, 0x9b, 0x9f, 0xc6, + 0x98, 0xc8, 0x82, 0xc3, 0xa2, 0xc4, 0xba, 0xc7, 0xbc, 0xc4, 0xbc, 0xc4, 0xa6, 0xc6, + 0xad, 0xc8, 0xb7, 0x70, 0xc3, 0x94, 0xe1, 0x9b, 0x81, 0xc5, 0x86, 0xe2, 0xb1, 0xa9, + 0xc8, 0x99, 0xce, 0x8c, 0xc3, 0x99, 0xc7, 0x91, 0xc3, 0xbd, 0x30, 0xc7, 0xb9, 0xc4, + 0xb0, 0xc8, 0xae, 0xe1, 0x9b, 0xa5, 0xc6, 0xbe, 0xc5, 0xad, 0xc5, 0xb6, 0xc2, 0xaf, + 0xc4, 0xbf, 0xce, 0x8c, 0xc8, 0xb8, 0x4a, 0xe2, 0xb1, 0xaa, 0xc3, 0xb1, 0xc5, 0x9a, + 0xe1, 0x9a, 0xb8, 0xc5, 0x9a, 0x33, 0xc4, 0x91, 0xc3, 0x9f, 0xc4, 0x86, 0x39, 0xc8, + 0x89, 0xc7, 0xa9, 0xc3, 0x9b, 0xc7, 0x92, 0xce, 0x89, 0x63, 0xc6, 0x93, 0xc6, 0x90, + 0xc2, 0xb6, 0xc5, 0x8f, 0xc8, 0x91, 0xc2, 0xab, 0xe1, 0x9a, 0xbc, 0xe2, 0xb1, 0xa4, + 0xc3, 0xb1, 0xc5, 0xaf, 0xe1, 0x9b, 0x84, 0xc5, 0xb5, 0xc5, 0x80, 0xe2, 0xb1, 0xa0, + 0x68, 0xc5, 0xa2, 0x26, 0xe1, 0x9a, 0xa1, 0xc4, 0x87, 0xc4, 0x9d, 0xc4, 0x9f, 0xc5, + 0x8b, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0x8d, 0xe1, 0x9a, 0xbd, 0xce, 0x88, 0xc9, 0x81, + 0xc7, 0x92, 0xe1, 0x9b, 0x9b, 0xc3, 0xb8, 0xc2, 0xab, 0x39, 0xe1, 0x9b, 0x9f, 0xc5, + 0xb4, 0xc5, 0xb3, 0xce, 0x86, 0xc8, 0x8d, 0xe1, 0x9b, 0x9b, 0xc5, 0xba, 0x38, 0xc6, + 0x84, 0xc8, 0xbf, 0xc6, 0xa2, 0xc8, 0x96, 0xc7, 0x8b, 0xc7, 0xbe, 0xc4, 0x97, 0xc8, + 0xb9, 0xc6, 0xb3, 0xc3, 0xbb, 0xc4, 0x8f, 0xc9, 0x86, 0xc5, 0x85, 0xc7, 0x9b, 0x7c, + 0xe2, 0xb1, 0xa0, 0xc7, 0xb2, 0xc8, 0x9c, 0xc5, 0xa8, 0xc2, 0xa8, 0xe1, 0x9a, 0xb6, + 0xc4, 0xaf, 0xc3, 0x8e, 0xc8, 0xbf, 0xc4, 0xa9, 0xc3, 0x95, 0xe1, 0x9b, 0x80, 0xc4, + 0xb7, 0xc8, 0x88, 0xc8, 0x80, 0xc5, 0xaf, 0xe1, 0x9a, 0xa4, 0xc7, 0x96, 0xc3, 0xb0, + 0xc4, 0xa2, 0x7c, 0xcd, 0xb6, 0xc7, 0x95, 0x4e, 0xc9, 0x86, 0xc2, 0xb0, 0xc3, 0xbb, + 0xc7, 0x8b, 0xc4, 0xb3, 0xe2, 0xb1, 0xaa, 0xe1, 0x9b, 0x8f, 0xc7, 0x84, 0xe1, 0x9a, + 0xaf, 0xc4, 0x92, 0xc7, 0x97, 0x34, 0xc2, 0xbe, 0xe1, 0x9b, 0x96, 0xc4, 0x9d, 0xc6, + 0xab, 0xe1, 0x9b, 0xa8, 0x4b, 0xc3, 0x86, 0xc7, 0x97, 0xc4, 0xa7, 0xc3, 0xbb, 0xc8, + 0x90, 0x48, 0xe1, 0x9b, 0x9a, 0xc6, 0x9d, 0xe1, 0x9b, 0x9b, 0xc4, 0xbb, 0xc3, 0x8f, + 0xc7, 0xb8, 0xc8, 0x9d, 0xc6, 0xac, 0xc6, 0xa5, 0xc6, 0x9e, 0xc7, 0x83, 0xc3, 0x97, + 0xc8, 0xae, 0xc3, 0xaf, 0xc3, 0xb4, 0xc5, 0xab, 0xc4, 0x81, 0xe1, 0x9b, 0xa0, 0xc3, + 0x85, 0xc4, 0x84, 0x7c, 0x21, 0xc2, 0xb4, 0xc9, 0x8b, 0xc9, 0x8b, 0xc8, 0x9c, 0xc7, + 0x8f, 0xe2, 0xb1, 0xab, 0xe1, 0x9a, 0xbc, 0xc7, 0x8b, 0xc6, 0xa0, 0xc6, 0xb2, 0xc9, + 0x82, 0xc5, 0x8c, 0xe2, 0xb1, 0xb7, 0xc7, 0x8d, 0xc5, 0xa9, 0xc4, 0xbd, 0xc6, 0x8f, + 0xc4, 0x83, 0xc6, 0x80, 0xe1, 0x9b, 0xa7, 0xc8, 0x94, 0xc5, 0x8e, 0xc6, 0x9e, 0x4a, + 0x62, 0x70, 0xe1, 0x9a, 0xa5, 0xe2, 0xb1, 0xba, 0xc3, 0x8f, 0xc3, 0x85, 0xc4, 0x82, + 0xc7, 0xbc, 0xce, 0x85, 0x77, 0xc2, 0xb2, 0xc8, 0x89, 0xe1, 0x9a, 0xa2, 0xc5, 0xac, + 0xc5, 0x9e, 0xcd, 0xb5, 0xc6, 0x83, 0xc6, 0x93, 0xc8, 0x9d, 0xe1, 0x9a, 0xa2, 0xe1, + 0x9b, 0xa8, 0xc2, 0xa2, 0xe1, 0x9a, 0xa5, 0xcd, 0xb3, 0xc4, 0xb8, 0x3c, 0xc6, 0xb5, + 0xc3, 0x8c, 0xc3, 0x90, 0xc3, 0xa4, 0xc7, 0x83, 0xc4, 0xb4, 0xc7, 0x93, 0xc5, 0xa3, + 0xc6, 0xa6, 0x25, 0xc5, 0xbf, 0x7d, 0xc6, 0xa3, 0x46, 0xc3, 0xa6, 0xc6, 0x9b, 0xc7, + 0xbc, 0xc6, 0x81, 0xc2, 0xba, 0xc7, 0xa7, 0x60, ], - asset_id: [ - 0xe2, 0xc6, 0x6a, 0x5e, 0x81, 0xaf, 0x85, 0x65, 0x05, 0x7c, 0x42, 0xab, 0x5a, 0x5b, - 0x5b, 0xb8, 0xc3, 0xca, 0x18, 0x13, 0xbe, 0x45, 0x76, 0xd8, 0xea, 0xe8, 0xb2, 0x50, - 0xfd, 0xe9, 0xfd, 0x95, + asset_base: [ + 0xd4, 0x7d, 0x06, 0xf8, 0x2f, 0x2d, 0x15, 0x8a, 0xee, 0xf7, 0x02, 0x8a, 0x1d, 0xb5, + 0xf3, 0xa1, 0xd1, 0x25, 0x0e, 0x2c, 0xfa, 0x28, 0x94, 0x44, 0x1d, 0x86, 0xee, 0xc4, + 0x7a, 0xbf, 0xbd, 0xb5, ], }, TestVector { @@ -219,48 +219,48 @@ pub(crate) fn test_vectors() -> Vec { 0x1f, 0xbd, 0x81, 0x30, ], description: [ - 0xe1, 0x9a, 0xa5, 0xe1, 0x9a, 0xb5, 0xc7, 0xb1, 0x2b, 0x72, 0xc6, 0x83, 0xc3, 0x82, - 0xe1, 0x9b, 0x8e, 0x34, 0xe1, 0x9b, 0x98, 0x3c, 0xc2, 0xa5, 0xc8, 0xbe, 0x2c, 0xc3, - 0x82, 0xc3, 0xa4, 0xe2, 0xb1, 0xa3, 0xc5, 0xab, 0xc3, 0xb4, 0xc7, 0xb8, 0xc2, 0xa2, - 0xc6, 0x86, 0xc6, 0xad, 0xc3, 0x9a, 0xc5, 0x93, 0xc7, 0xa3, 0xc2, 0xb7, 0xc6, 0x9a, - 0x5f, 0x55, 0xc9, 0x8c, 0xc9, 0x89, 0x58, 0xc6, 0x95, 0xe1, 0x9a, 0xba, 0xc7, 0x80, - 0xc2, 0xb4, 0xe1, 0x9b, 0x9b, 0xc4, 0x90, 0xe1, 0x9b, 0x8b, 0xe1, 0x9a, 0xae, 0xc8, - 0x92, 0xe1, 0x9b, 0xa8, 0xe2, 0xb1, 0xb2, 0xcd, 0xbd, 0xc3, 0x98, 0xe1, 0x9a, 0xba, - 0xe1, 0x9a, 0xb0, 0x48, 0xc6, 0xa4, 0x2f, 0xc5, 0x9d, 0xe1, 0x9b, 0x86, 0xe1, 0x9a, - 0xb5, 0x7c, 0xc5, 0xa5, 0xe1, 0x9a, 0xba, 0xc4, 0x86, 0xc8, 0xa6, 0xc6, 0xa6, 0xc6, - 0x84, 0xc3, 0xbb, 0xc5, 0xbe, 0x6e, 0xe1, 0x9b, 0xa6, 0xc5, 0x95, 0xe1, 0x9b, 0xaa, - 0xc7, 0xb7, 0xe2, 0xb1, 0xbd, 0xce, 0x8c, 0xc3, 0xa6, 0xc6, 0x9e, 0xc4, 0xb5, 0xe1, - 0x9a, 0xa4, 0xc3, 0xa8, 0xc7, 0x9c, 0xc4, 0x82, 0xc2, 0xa6, 0x31, 0xc3, 0xa6, 0xe2, - 0xb1, 0xae, 0xc7, 0xbb, 0x26, 0xc7, 0xa0, 0xc5, 0x9d, 0xc5, 0xb9, 0xe1, 0x9a, 0xb4, - 0xe1, 0x9b, 0xad, 0xc7, 0x88, 0x30, 0x42, 0xc6, 0x9f, 0xc3, 0x9b, 0x25, 0xc4, 0x9c, - 0xce, 0x87, 0xc5, 0x9c, 0xc5, 0x8c, 0xe1, 0x9b, 0x81, 0xce, 0x89, 0xc4, 0x9a, 0xc5, - 0xa7, 0xe1, 0x9a, 0xa9, 0xc3, 0x93, 0xc7, 0x9b, 0xc3, 0x8d, 0xc3, 0xbe, 0xc3, 0x93, - 0xc8, 0xbc, 0xc8, 0xb3, 0xc5, 0xaf, 0xc7, 0xb3, 0xe1, 0x9a, 0xa7, 0xc4, 0x80, 0xc4, - 0x80, 0xcd, 0xb2, 0xc7, 0x82, 0xc4, 0x83, 0xc7, 0x88, 0xc6, 0x84, 0xe1, 0x9b, 0x90, - 0xc3, 0xa4, 0xc3, 0xbc, 0xc5, 0xad, 0xc6, 0x8b, 0xc2, 0xac, 0xc4, 0xa1, 0xc3, 0xae, - 0xce, 0x86, 0xe1, 0x9b, 0x94, 0xc5, 0x9e, 0xc6, 0x92, 0xe1, 0x9b, 0xac, 0xc3, 0x8d, - 0xc5, 0xb9, 0xc3, 0x82, 0xc8, 0x81, 0xe2, 0xb1, 0xbb, 0xc8, 0xa0, 0xc2, 0xbd, 0xc5, - 0xa2, 0xc6, 0x86, 0xc3, 0xb7, 0xe1, 0x9a, 0xad, 0xc5, 0xbc, 0x2c, 0x51, 0xe1, 0x9a, - 0xab, 0xe1, 0x9b, 0x99, 0x77, 0xc3, 0x9c, 0xc6, 0x9c, 0x31, 0x60, 0xc5, 0x8e, 0xc3, - 0xb5, 0xc3, 0x85, 0xe1, 0x9b, 0xad, 0xc9, 0x8f, 0xc4, 0x8b, 0xc5, 0x93, 0xc2, 0xa2, - 0xc6, 0x8a, 0xe1, 0x9a, 0xa3, 0x4a, 0xc3, 0x9e, 0x30, 0xc8, 0xae, 0xc7, 0xbc, 0xcd, - 0xb3, 0xc7, 0x94, 0xe1, 0x9b, 0x93, 0xc3, 0x93, 0xc3, 0xaa, 0xc4, 0xad, 0xc8, 0x91, - 0xc5, 0xac, 0xe1, 0x9b, 0xa6, 0x26, 0x74, 0xc6, 0xbd, 0xe1, 0x9b, 0xa3, 0xc9, 0x8e, - 0xc8, 0x94, 0xc5, 0xad, 0xc6, 0xac, 0xc6, 0xb7, 0xc7, 0xa5, 0xc3, 0xa5, 0xc8, 0xb4, - 0xc6, 0x95, 0xc8, 0x93, 0xc8, 0xbc, 0xc8, 0xb9, 0xe1, 0x9b, 0x86, 0xc3, 0xb2, 0xc2, - 0xb5, 0xc5, 0x92, 0xe1, 0x9b, 0xa2, 0xe2, 0xb1, 0xb2, 0xc8, 0x80, 0xc4, 0x90, 0xe1, - 0x9a, 0xb9, 0xe2, 0xb1, 0xa7, 0xc5, 0xab, 0xc5, 0xa6, 0xc6, 0xaa, 0xc5, 0x98, 0xc4, - 0xb0, 0xc7, 0xb0, 0xe1, 0x9a, 0xbe, 0xe1, 0x9a, 0xaa, 0xc5, 0xb7, 0xc4, 0x96, 0xc7, - 0xa1, 0xc6, 0xbc, 0xe1, 0x9a, 0xb5, 0xc3, 0x87, 0xc8, 0xa5, 0x73, 0xc3, 0x84, 0xc4, - 0xa6, 0xc6, 0x9d, 0xc5, 0xa9, 0xc5, 0xaa, 0xc7, 0xa6, 0xc6, 0x9e, 0xc8, 0xbc, 0xe1, - 0x9a, 0xbf, 0xc6, 0xa3, 0xc3, 0x99, 0xc5, 0x97, 0xe2, 0xb1, 0xa0, 0xc4, 0x9e, 0x74, - 0xc4, 0x90, 0xc6, 0xa0, 0xe1, 0x9b, 0xaa, 0xc7, 0xaf, 0xc5, 0x8c, 0xc4, 0x91, 0xc7, - 0x93, 0xe1, 0x9b, 0xa3, 0xc5, 0xbd, 0xc8, 0xa3, + 0xc5, 0x99, 0xc2, 0xa5, 0xc6, 0xb8, 0x6d, 0xc5, 0xa7, 0xc7, 0xbd, 0xc4, 0xa0, 0xe1, + 0x9b, 0xa7, 0xc8, 0xba, 0xc9, 0x81, 0x7d, 0x36, 0xc5, 0x80, 0x52, 0xcd, 0xb5, 0xc5, + 0xba, 0xc2, 0xbb, 0x6d, 0xe2, 0xb1, 0xb1, 0xc5, 0xa8, 0xc5, 0x8c, 0x38, 0x47, 0xc9, + 0x87, 0x7c, 0x43, 0xc3, 0x96, 0xc6, 0x87, 0xc7, 0xbf, 0xc4, 0x9b, 0xe1, 0x9b, 0x98, + 0xc7, 0x94, 0xe1, 0x9b, 0x9b, 0xe1, 0x9b, 0x9d, 0xe1, 0x9a, 0xbf, 0x35, 0xc7, 0xba, + 0xc8, 0x82, 0xc4, 0x80, 0xc6, 0xbf, 0xc7, 0xba, 0xc4, 0xbd, 0xc4, 0x81, 0xe2, 0xb1, + 0xbc, 0xe1, 0x9a, 0xad, 0xe1, 0x9a, 0xab, 0xc5, 0xab, 0xc5, 0xba, 0xc6, 0xa8, 0x3b, + 0xc6, 0x98, 0xc7, 0x8c, 0xc8, 0x9e, 0xc2, 0xbe, 0xc6, 0x8b, 0xc7, 0x9c, 0xc8, 0xb4, + 0x3f, 0xc5, 0xb8, 0xc4, 0xb7, 0xc8, 0xb2, 0xc6, 0x86, 0xc3, 0xa1, 0xc7, 0x9b, 0x5c, + 0xe1, 0x9a, 0xa6, 0xe1, 0x9b, 0xac, 0xc7, 0x8c, 0xc6, 0xa7, 0x53, 0xc6, 0xa5, 0xc7, + 0x90, 0xe1, 0x9b, 0x85, 0xc8, 0x94, 0xcd, 0xb1, 0xc6, 0x99, 0xc4, 0xa8, 0xc7, 0xb3, + 0xe1, 0x9a, 0xb1, 0x7b, 0xc2, 0xb1, 0xe1, 0x9b, 0x94, 0x36, 0xc9, 0x8d, 0xc2, 0xa2, + 0x73, 0xc5, 0x80, 0xc5, 0x8d, 0xc8, 0x84, 0xc7, 0xa6, 0xc9, 0x85, 0xc4, 0xbd, 0xc7, + 0xb8, 0xc8, 0xb0, 0xc4, 0x83, 0xc3, 0xb8, 0xcd, 0xb1, 0x77, 0xc3, 0xa6, 0xc6, 0x80, + 0xc4, 0x83, 0xc8, 0x8e, 0xc9, 0x87, 0xc7, 0xb4, 0xc5, 0xb8, 0xc5, 0x99, 0xe2, 0xb1, + 0xaa, 0xc6, 0xb6, 0xc4, 0xa3, 0xc6, 0xb4, 0xc6, 0x8d, 0xe2, 0xb1, 0xa3, 0xe1, 0x9a, + 0xaa, 0xe1, 0x9a, 0xb8, 0xc3, 0x92, 0x63, 0xcd, 0xb4, 0xc7, 0x91, 0xc8, 0x83, 0xc3, + 0xaf, 0xcd, 0xb2, 0xc7, 0x9b, 0x5a, 0xe1, 0x9b, 0x82, 0xc6, 0x87, 0xc8, 0x91, 0xc5, + 0x83, 0xc5, 0xa8, 0xc4, 0x85, 0xe1, 0x9b, 0xab, 0xe1, 0x9b, 0x9f, 0x39, 0xc6, 0xbc, + 0x64, 0xc5, 0x98, 0xe1, 0x9b, 0x9f, 0xc8, 0xab, 0xe1, 0x9a, 0xb4, 0xc4, 0x83, 0xe2, + 0xb1, 0xb2, 0xe2, 0xb1, 0xa8, 0x5e, 0xc8, 0x93, 0xc4, 0xb3, 0xe1, 0x9b, 0xa6, 0xc5, + 0x93, 0xe1, 0x9b, 0x86, 0xc3, 0x98, 0xc2, 0xbd, 0xc7, 0x9a, 0xe1, 0x9a, 0xb2, 0xc7, + 0x8a, 0x73, 0xc7, 0x96, 0xe2, 0xb1, 0xb0, 0xcd, 0xbc, 0xc7, 0xb8, 0xc7, 0x95, 0xc4, + 0xa7, 0xe2, 0xb1, 0xb4, 0xc5, 0xa6, 0xc4, 0xa6, 0xe1, 0x9a, 0xa1, 0xc4, 0xbd, 0xc2, + 0xa2, 0xc5, 0x96, 0xe1, 0x9b, 0x89, 0xe1, 0x9b, 0x8e, 0xe2, 0xb1, 0xab, 0xc8, 0x8e, + 0x24, 0xcd, 0xb7, 0xc5, 0xab, 0xc8, 0x97, 0xce, 0x86, 0xc3, 0xac, 0x63, 0xc7, 0x97, + 0xc5, 0x81, 0xc6, 0x8b, 0xc4, 0xb7, 0xe2, 0xb1, 0xad, 0xc4, 0x8e, 0xc8, 0x98, 0xcd, + 0xbc, 0xe1, 0x9a, 0xbb, 0xc5, 0xb8, 0xc4, 0x9d, 0x28, 0xc6, 0x87, 0xe1, 0x9b, 0x9d, + 0xe1, 0x9b, 0x93, 0xc3, 0xbb, 0xc7, 0x8f, 0x74, 0xc8, 0x9e, 0xce, 0x88, 0xc7, 0x9c, + 0xc8, 0x9d, 0xc9, 0x80, 0xc4, 0xbf, 0xc7, 0xad, 0xc3, 0x97, 0xe2, 0xb1, 0xad, 0x2e, + 0xc6, 0xb7, 0x40, 0xc3, 0xb7, 0xc3, 0xaf, 0xe1, 0x9a, 0xbe, 0xc7, 0x88, 0xc4, 0x8a, + 0xc3, 0x81, 0xc5, 0x97, 0xc8, 0x93, 0xc8, 0xb8, 0xe1, 0x9a, 0xa8, 0xc3, 0x9e, 0xc8, + 0xb1, 0xc8, 0xaa, 0x5c, 0xc6, 0xa4, 0xe1, 0x9b, 0x9d, 0xc2, 0xb6, 0xc8, 0x85, 0xc7, + 0x98, 0xc4, 0xb8, 0xc4, 0xa1, 0xc9, 0x81, 0xc5, 0x94, 0xc4, 0xa4, 0xc2, 0xa8, 0xc7, + 0xa7, 0xc5, 0xba, 0x5a, 0xcd, 0xb3, 0xe1, 0x9b, 0xa0, 0xc4, 0x83, 0xc6, 0x83, 0xc9, + 0x85, 0x45, 0xc3, 0xb5, 0xc7, 0x9f, 0xc5, 0x93, 0xc3, 0x90, 0xc7, 0x95, 0xc8, 0xb1, + 0xc7, 0x87, 0xc3, 0xb2, 0xc7, 0xb9, 0xc3, 0xa8, ], - asset_id: [ - 0x9e, 0xa8, 0x07, 0x5c, 0x02, 0xdf, 0xe4, 0x64, 0x18, 0x07, 0xe0, 0x7d, 0x2d, 0x8a, - 0x84, 0x6c, 0x1f, 0xfb, 0xaf, 0x66, 0x86, 0x85, 0x74, 0x5c, 0x04, 0x5a, 0xf9, 0xe3, - 0x6c, 0xbe, 0x91, 0xb9, + asset_base: [ + 0xa9, 0xa8, 0xef, 0x9a, 0x58, 0xbd, 0xab, 0xa1, 0x51, 0xcf, 0xc2, 0x58, 0x66, 0xca, + 0x40, 0x54, 0xd7, 0xac, 0xae, 0xbd, 0xde, 0x1a, 0xf7, 0xe9, 0xe4, 0x89, 0x6b, 0x43, + 0xc7, 0x18, 0xef, 0x9d, ], }, TestVector { @@ -270,48 +270,48 @@ pub(crate) fn test_vectors() -> Vec { 0x6a, 0xbc, 0x03, 0x33, ], description: [ - 0xc3, 0x92, 0xcd, 0xb4, 0xc2, 0xaa, 0xc2, 0xb7, 0x78, 0xc5, 0x8d, 0xc5, 0x8f, 0xc5, - 0x84, 0xe1, 0x9b, 0x9c, 0xc4, 0x8f, 0xc3, 0x9a, 0xc6, 0x8f, 0x42, 0xc4, 0x94, 0x50, - 0x3a, 0xc5, 0x9f, 0x60, 0xc8, 0xa5, 0x21, 0xc3, 0xa2, 0x3a, 0xe1, 0x9a, 0xb1, 0xc5, - 0x88, 0xc5, 0x81, 0xc6, 0x9d, 0xc7, 0x95, 0xc4, 0xa1, 0x55, 0x3f, 0x48, 0xc9, 0x8a, - 0xc4, 0x8d, 0xc3, 0xbf, 0xe1, 0x9b, 0x8e, 0xc6, 0x8e, 0xc4, 0xbb, 0xe1, 0x9b, 0x9f, - 0xe1, 0x9a, 0xb9, 0xc4, 0xb1, 0xe1, 0x9a, 0xb3, 0xe1, 0x9b, 0x9b, 0xc6, 0x84, 0xe1, - 0x9a, 0xac, 0x2b, 0x51, 0xc5, 0x99, 0xe1, 0x9a, 0xb3, 0xc3, 0xb8, 0xc6, 0x99, 0xc8, - 0x9b, 0xe1, 0x9a, 0xbc, 0xc8, 0xa4, 0xe1, 0x9b, 0x84, 0x6e, 0xc4, 0x83, 0x5e, 0xe1, - 0x9a, 0xa8, 0xc6, 0xad, 0xc5, 0x82, 0xc8, 0xa4, 0xc4, 0x8a, 0xe2, 0xb1, 0xab, 0xc6, - 0x89, 0xe1, 0x9b, 0x8c, 0xc8, 0x8d, 0xe1, 0x9a, 0xb2, 0xe2, 0xb1, 0xb1, 0xc5, 0x87, - 0xe2, 0xb1, 0xad, 0xc4, 0xab, 0x50, 0xc2, 0xb9, 0xc7, 0xae, 0xc5, 0x99, 0xc3, 0x8a, - 0xc3, 0xbc, 0xc4, 0xa9, 0xe1, 0x9b, 0xa6, 0xc8, 0x92, 0xc4, 0xa7, 0xc2, 0xbd, 0xc2, - 0xbb, 0xc8, 0xb2, 0xcd, 0xbd, 0xe1, 0x9b, 0xa0, 0xc2, 0xbe, 0x63, 0xc5, 0xae, 0x69, - 0xc4, 0x90, 0x2e, 0xc4, 0xb0, 0x53, 0xc3, 0x83, 0xc5, 0xa7, 0xc3, 0xb1, 0xc2, 0xb1, - 0xc6, 0x8a, 0xc8, 0x85, 0xc6, 0xb0, 0x46, 0xc2, 0xb6, 0xc9, 0x88, 0xc4, 0xa5, 0xc7, - 0xb9, 0xc5, 0xb5, 0xc8, 0x80, 0xc4, 0xa8, 0xc8, 0x87, 0xc5, 0x8d, 0xc4, 0x97, 0xc8, - 0x86, 0xc2, 0xa8, 0xc4, 0xa9, 0xc6, 0x99, 0xc3, 0x98, 0xc4, 0x97, 0xc8, 0xb1, 0xce, - 0x84, 0xe1, 0x9a, 0xb0, 0xc6, 0x86, 0xc4, 0x97, 0xc6, 0xab, 0xe2, 0xb1, 0xac, 0xc8, - 0xa5, 0xc8, 0xa9, 0xc5, 0x80, 0x65, 0x51, 0xc8, 0x87, 0xe1, 0x9b, 0x95, 0xc4, 0x88, - 0xe1, 0x9b, 0xb0, 0xc6, 0x9d, 0xc5, 0xa8, 0xc8, 0x8b, 0xc7, 0xb4, 0xc4, 0xb9, 0xc7, - 0xb2, 0xc4, 0xb4, 0xe1, 0x9b, 0x9c, 0xc2, 0xbb, 0xe2, 0xb1, 0xa9, 0xc4, 0xa7, 0xc7, - 0x86, 0xc8, 0xac, 0xe2, 0xb1, 0xb1, 0xe1, 0x9b, 0x81, 0x71, 0xc4, 0x8d, 0xc7, 0x97, - 0x33, 0xc3, 0x83, 0xc9, 0x8a, 0xc6, 0xb3, 0xc4, 0xb0, 0xc3, 0xb1, 0xe2, 0xb1, 0xac, - 0xe1, 0x9b, 0x91, 0xc6, 0x96, 0xc2, 0xb5, 0xc7, 0xac, 0x29, 0x6d, 0x36, 0xc6, 0x91, - 0xc4, 0xa8, 0xc4, 0xb1, 0xc7, 0x8d, 0xce, 0x8c, 0xc3, 0x88, 0x6b, 0xc7, 0xbd, 0xc7, - 0x98, 0xc8, 0x95, 0xc7, 0xa2, 0xe2, 0xb1, 0xa0, 0xc7, 0xa0, 0x46, 0x31, 0x2e, 0xc6, - 0x81, 0xc8, 0x96, 0xc8, 0x8f, 0xe1, 0x9b, 0x98, 0xc4, 0xb3, 0xc8, 0xb8, 0xe1, 0x9a, - 0xb2, 0xc8, 0x9e, 0xc5, 0x83, 0xc7, 0x87, 0xc6, 0xa1, 0xc2, 0xae, 0x43, 0xc8, 0xb3, - 0xc4, 0x89, 0xc3, 0x9e, 0xe1, 0x9b, 0x96, 0xc5, 0x84, 0x33, 0xc9, 0x87, 0x69, 0xce, - 0x88, 0xc8, 0xac, 0xc5, 0x87, 0xc5, 0x87, 0xe1, 0x9b, 0x8b, 0xc4, 0x89, 0xc5, 0xb0, - 0xc4, 0x9f, 0xe1, 0x9b, 0x97, 0xc7, 0xa8, 0xc8, 0xb3, 0xc7, 0x83, 0xc4, 0x91, 0xe1, - 0x9a, 0xba, 0xc7, 0x82, 0xc7, 0xb0, 0xc4, 0xbd, 0xc5, 0xab, 0xe1, 0x9b, 0xac, 0xe2, - 0xb1, 0xbe, 0xc4, 0x89, 0xc3, 0x8b, 0xe2, 0xb1, 0xae, 0xcd, 0xbe, 0xc4, 0x9b, 0xc4, - 0xab, 0xc6, 0xbc, 0xe1, 0x9b, 0xac, 0xc4, 0x84, 0xc5, 0x9f, 0xc7, 0xac, 0xc3, 0xba, - 0xc6, 0x83, 0xc3, 0x9b, 0xc6, 0xa6, 0xc6, 0xac, 0xc7, 0xb5, 0xc6, 0x8a, 0xc4, 0xbf, - 0xe2, 0xb1, 0xaa, 0xc3, 0x96, 0x42, 0xc4, 0x95, 0xc3, 0xa2, 0xc6, 0xa5, 0x5b, 0x2e, - 0xc3, 0xaf, 0xc3, 0x93, 0xc4, 0x9d, 0xc8, 0xa4, + 0x62, 0xc8, 0xbb, 0xc6, 0xb1, 0xc5, 0xa9, 0xc9, 0x8c, 0xc9, 0x8e, 0xc6, 0xb6, 0xc3, + 0x85, 0xc4, 0xb0, 0x70, 0xc2, 0xb9, 0x49, 0xc8, 0x9b, 0xe1, 0x9b, 0x91, 0x69, 0xc8, + 0xaf, 0xc6, 0x94, 0xc5, 0xa2, 0x24, 0xe1, 0x9a, 0xb3, 0xcd, 0xb3, 0xe1, 0x9a, 0xa1, + 0x62, 0x67, 0xc3, 0x9a, 0xc7, 0x84, 0xe1, 0x9b, 0xa2, 0xc9, 0x86, 0xc6, 0xab, 0xc5, + 0xad, 0xc8, 0xad, 0xc6, 0xbe, 0xc3, 0x84, 0xc4, 0xad, 0xc3, 0xbf, 0xe2, 0xb1, 0xb9, + 0xc8, 0x8c, 0xc5, 0xb7, 0xe1, 0x9b, 0xad, 0xc6, 0x87, 0xc3, 0xa8, 0xce, 0x88, 0xc2, + 0xa5, 0xc3, 0xa7, 0xc5, 0xb6, 0xc4, 0x82, 0xe1, 0x9a, 0xbf, 0xc5, 0xad, 0xc8, 0xb9, + 0xc8, 0xab, 0xc3, 0xb8, 0xc5, 0x85, 0xc3, 0xb4, 0xc3, 0xa4, 0xc4, 0xb0, 0xc9, 0x8b, + 0xc6, 0x9c, 0xc8, 0x94, 0xe1, 0x9b, 0xab, 0xc8, 0xaa, 0xe1, 0x9a, 0xab, 0xc4, 0xa2, + 0xc3, 0xbc, 0x68, 0xc5, 0x84, 0xc9, 0x8c, 0xc8, 0xa8, 0x39, 0xc7, 0xab, 0xe1, 0x9b, + 0x8d, 0x47, 0xe1, 0x9a, 0xa1, 0x26, 0xc4, 0x82, 0xe1, 0x9a, 0xb0, 0xc8, 0xb4, 0x50, + 0xc8, 0xab, 0xc7, 0x81, 0xe1, 0x9a, 0xb3, 0xc5, 0x81, 0xe1, 0x9b, 0x94, 0x3e, 0xc3, + 0xa1, 0x4e, 0xc4, 0xb7, 0xc5, 0xbf, 0xc4, 0xa2, 0x26, 0xc2, 0xb1, 0xc6, 0xb3, 0xc5, + 0xa6, 0xc4, 0xb2, 0xc5, 0x90, 0xc8, 0x92, 0xc5, 0xbe, 0xc5, 0xbb, 0xc8, 0xac, 0x3c, + 0xc4, 0x91, 0xc4, 0xac, 0xc6, 0x87, 0xc4, 0x94, 0xe1, 0x9a, 0xa7, 0xc9, 0x85, 0xe2, + 0xb1, 0xa3, 0xe1, 0x9b, 0xb0, 0xc6, 0xaf, 0x79, 0xe1, 0x9a, 0xad, 0xc9, 0x8e, 0xe1, + 0x9a, 0xa2, 0x23, 0xe2, 0xb1, 0xb7, 0xc4, 0xba, 0x45, 0xe1, 0x9a, 0xbe, 0xc7, 0xb7, + 0xc3, 0xa6, 0x5a, 0xce, 0x88, 0xc5, 0xa9, 0x46, 0x6a, 0xc3, 0xb5, 0xe1, 0x9b, 0xab, + 0xc2, 0xbe, 0xe2, 0xb1, 0xbf, 0xc6, 0x82, 0x66, 0x42, 0xc5, 0xb4, 0xc8, 0x85, 0xc4, + 0x97, 0xc2, 0xab, 0xc2, 0xa9, 0xc7, 0x8f, 0xc7, 0xb9, 0xe1, 0x9b, 0x8f, 0xc8, 0xb1, + 0xc7, 0xaf, 0xc9, 0x82, 0xc7, 0x8a, 0x38, 0xc2, 0xa3, 0xc4, 0xaf, 0xc4, 0xac, 0xc3, + 0x9b, 0xc7, 0xb9, 0x6d, 0xc7, 0xbf, 0xe1, 0x9a, 0xa1, 0xe1, 0x9b, 0xa4, 0xc6, 0xbe, + 0xc6, 0xa7, 0xc3, 0x8f, 0xe1, 0x9b, 0xa9, 0xc6, 0xb1, 0xce, 0x89, 0xc2, 0xb3, 0xc5, + 0x8f, 0xc6, 0x95, 0x52, 0xc8, 0x83, 0xc2, 0xb1, 0xc6, 0xb3, 0xc3, 0x87, 0xe1, 0x9b, + 0x84, 0xc6, 0xae, 0x32, 0xe1, 0x9b, 0x99, 0xcd, 0xb6, 0xc5, 0xbb, 0xc6, 0xa7, 0xc5, + 0xbd, 0xc6, 0x9f, 0xc8, 0x87, 0xc2, 0xbb, 0xc2, 0xbe, 0x5c, 0xc5, 0xb8, 0xc8, 0x8c, + 0xc8, 0x9c, 0xc2, 0xab, 0xe2, 0xb1, 0xac, 0x3e, 0xc6, 0xbc, 0x6b, 0xc2, 0xb2, 0xc7, + 0x95, 0xc6, 0xa0, 0xc3, 0xa6, 0xe2, 0xb1, 0xaf, 0xe1, 0x9b, 0xa8, 0xc6, 0xb1, 0xc5, + 0x81, 0xc5, 0x96, 0xc3, 0x99, 0xc8, 0x9b, 0x2c, 0xc4, 0x93, 0xe2, 0xb1, 0xbb, 0xc2, + 0xab, 0xc8, 0x92, 0xc2, 0xb9, 0xc4, 0xb5, 0xc7, 0x94, 0xc3, 0x94, 0xe1, 0x9a, 0xb0, + 0xc4, 0xae, 0xe1, 0x9b, 0x84, 0x30, 0xc7, 0x91, 0xc2, 0xa4, 0xc5, 0x9a, 0xc5, 0x92, + 0xc9, 0x8f, 0xe1, 0x9a, 0xb6, 0xe1, 0x9a, 0xaa, 0xc8, 0xb2, 0xc6, 0x9e, 0x30, 0xc4, + 0xae, 0x6f, 0x73, 0xc2, 0xa3, 0xc7, 0x8c, 0xe2, 0xb1, 0xb8, 0x57, 0xc9, 0x89, 0xe1, + 0x9b, 0x8c, 0x60, 0xc4, 0x88, 0xce, 0x87, 0x4c, 0xc4, 0xaa, 0xc4, 0xab, 0xc2, 0xae, + 0xc7, 0x8a, 0xc7, 0xad, 0xc4, 0x87, 0xc5, 0xb3, 0x5b, 0x68, 0xc4, 0x9a, 0xc4, 0x9c, + 0x3a, 0xc4, 0x8b, 0xe1, 0x9a, 0xb2, 0x2e, 0xc5, 0x9a, 0xc2, 0xb9, 0xe1, 0x9a, 0xa3, + 0xe1, 0x9b, 0x8b, 0xc8, 0xa9, 0xc6, 0x9d, 0x34, ], - asset_id: [ - 0x02, 0xce, 0x39, 0x82, 0x1e, 0x86, 0x41, 0xcd, 0x79, 0x5c, 0x1e, 0x41, 0xf7, 0x48, - 0x3c, 0x59, 0x88, 0x81, 0xb5, 0x0f, 0x88, 0xe7, 0x36, 0xcb, 0x4f, 0xb0, 0x00, 0xbc, - 0xf0, 0x28, 0x62, 0x2b, + asset_base: [ + 0x3e, 0x9f, 0x51, 0x16, 0x2c, 0xbf, 0x73, 0x86, 0x1a, 0xe5, 0xd7, 0xc5, 0x82, 0x4e, + 0x0e, 0x54, 0xac, 0x96, 0xe9, 0xd7, 0xa2, 0xcf, 0x5a, 0x76, 0x0b, 0xf2, 0x61, 0x21, + 0x93, 0xe5, 0x7a, 0x15, ], }, TestVector { @@ -321,48 +321,48 @@ pub(crate) fn test_vectors() -> Vec { 0x67, 0xb7, 0xc7, 0x18, ], description: [ - 0xc7, 0x84, 0xc3, 0xb8, 0xc7, 0xba, 0xc6, 0xbc, 0xc6, 0xa3, 0x28, 0xc5, 0xb4, 0xc7, - 0x8c, 0xc2, 0xba, 0xe1, 0x9b, 0xac, 0x3d, 0xc5, 0xb3, 0xc5, 0xbf, 0xc4, 0xb5, 0xce, - 0x8a, 0xc5, 0xab, 0xc7, 0xbe, 0xc7, 0xa0, 0xc4, 0x95, 0xe1, 0x9b, 0xa8, 0xc3, 0xab, - 0xc7, 0x99, 0xe1, 0x9a, 0xae, 0xcd, 0xb6, 0xe2, 0xb1, 0xb1, 0xc5, 0x8a, 0xe1, 0x9b, - 0xab, 0xc5, 0xaa, 0xc7, 0xb8, 0xc6, 0xb2, 0x48, 0xe1, 0x9b, 0x94, 0xc8, 0xb4, 0xc7, - 0x9e, 0xc8, 0x9b, 0x4f, 0xc7, 0xab, 0xc5, 0xa8, 0xc7, 0x9c, 0xc8, 0x9f, 0xc4, 0x8a, - 0xc8, 0x98, 0xe1, 0x9a, 0xa6, 0xc4, 0xb7, 0xc3, 0xb8, 0xe1, 0x9b, 0x97, 0xc7, 0xb6, - 0x57, 0xc4, 0xa0, 0xe1, 0x9b, 0x9f, 0xc5, 0x9a, 0xc2, 0xa7, 0x2c, 0xe1, 0x9a, 0xa4, - 0xc6, 0x84, 0xcd, 0xba, 0xc7, 0x90, 0xc4, 0xae, 0xc4, 0xaf, 0xc2, 0xb1, 0xce, 0x84, - 0xe1, 0x9a, 0xa0, 0xe1, 0x9b, 0xa9, 0xc4, 0xa0, 0xce, 0x86, 0xc3, 0x83, 0xc7, 0xab, - 0xcd, 0xb4, 0xc5, 0x83, 0xc8, 0xbd, 0xc8, 0x98, 0xce, 0x89, 0x73, 0xe1, 0x9a, 0xa6, - 0xc5, 0xa1, 0xc2, 0xa7, 0xc3, 0x81, 0xc9, 0x83, 0xc5, 0xbc, 0xc5, 0x9b, 0xc4, 0xbe, - 0x5f, 0xc6, 0xb8, 0xe1, 0x9b, 0x86, 0x74, 0xc3, 0xb4, 0x40, 0xc8, 0xbc, 0xc8, 0x93, - 0xc8, 0x9c, 0xc2, 0xa4, 0xe1, 0x9a, 0xb4, 0xc3, 0x98, 0xc5, 0x96, 0xe1, 0x9b, 0xa0, - 0x7c, 0xe2, 0xb1, 0xa0, 0xc4, 0xb2, 0xc2, 0xb7, 0xce, 0x85, 0xc3, 0x8c, 0xc2, 0xa2, - 0xc8, 0x9a, 0x4f, 0xc7, 0xae, 0xc4, 0xb5, 0xc7, 0x95, 0xc3, 0x8e, 0xc8, 0xa3, 0xe1, - 0x9a, 0xa3, 0xc3, 0xa7, 0xc7, 0xb7, 0xc6, 0xaa, 0xc6, 0xb6, 0xc8, 0xbb, 0xc2, 0xa9, - 0xe1, 0x9b, 0x8b, 0xc7, 0x9a, 0xc9, 0x84, 0xc3, 0xa2, 0x71, 0xc5, 0x83, 0xc3, 0x83, - 0xc8, 0x86, 0xcd, 0xb2, 0xc4, 0xa7, 0xe1, 0x9b, 0x80, 0x58, 0xc5, 0x96, 0xe2, 0xb1, - 0xb2, 0xe2, 0xb1, 0xbd, 0xc7, 0xbc, 0x4b, 0xcd, 0xbc, 0xc8, 0x88, 0xc4, 0x81, 0xc7, - 0xb8, 0xc4, 0x8f, 0xc8, 0x8d, 0x26, 0xc7, 0x92, 0xc3, 0xa0, 0xc5, 0x8c, 0xc5, 0xbd, - 0xc6, 0xb3, 0xc2, 0xa4, 0x67, 0xc8, 0x93, 0xc8, 0xac, 0xc9, 0x89, 0xc4, 0xbd, 0xc8, - 0x82, 0xe2, 0xb1, 0xa9, 0xe1, 0x9b, 0xa2, 0x79, 0x54, 0xe1, 0x9b, 0x94, 0xc7, 0x96, - 0xc8, 0xae, 0xc7, 0xba, 0xc8, 0xa3, 0xc6, 0xa3, 0xcd, 0xba, 0xc8, 0xa7, 0xc4, 0xa8, - 0x3b, 0xc7, 0xb9, 0xc6, 0x83, 0xc8, 0x98, 0xc2, 0xb0, 0xe1, 0x9a, 0xae, 0xc8, 0x8c, - 0xc3, 0xa3, 0xe1, 0x9a, 0xbd, 0x45, 0xc8, 0xb6, 0xc9, 0x80, 0x28, 0xe1, 0x9b, 0x81, - 0x2b, 0x6d, 0xc8, 0xb9, 0xc7, 0x80, 0xe2, 0xb1, 0xad, 0xc8, 0x8d, 0x6c, 0x7b, 0xc6, - 0x91, 0xc3, 0x93, 0xc8, 0xa9, 0xc7, 0xaf, 0xc5, 0x95, 0xe1, 0x9b, 0xa0, 0xc6, 0xbe, - 0x21, 0xc4, 0xac, 0xc4, 0xa8, 0xe1, 0x9a, 0xbe, 0xc9, 0x8e, 0xc3, 0x88, 0xc4, 0x9e, - 0xc4, 0xbe, 0xe1, 0x9b, 0x90, 0xc3, 0x99, 0xc7, 0x93, 0xc6, 0xa8, 0xe1, 0x9b, 0xa9, - 0xe1, 0x9b, 0xa5, 0xc7, 0xa4, 0xc6, 0x81, 0xe1, 0x9b, 0x9a, 0xc3, 0xa0, 0xc5, 0xab, - 0xc4, 0x86, 0xc8, 0xa4, 0x53, 0xce, 0x8c, 0xc9, 0x81, 0xc3, 0xb7, 0xc7, 0xaa, 0xc8, - 0x8a, 0xc3, 0xa9, 0x41, 0xe1, 0x9b, 0xaa, 0xcd, 0xb7, 0xc3, 0xac, 0xc3, 0xbf, 0xc8, - 0x8d, 0xc7, 0xa7, 0xc7, 0xa3, 0xe1, 0x9b, 0xa9, 0x5a, 0xc4, 0xb1, 0x68, 0xe2, 0xb1, - 0xbf, 0x2a, 0x5b, 0xc8, 0xb6, 0xc5, 0xa0, 0x39, 0xc4, 0x8b, 0xc8, 0xae, 0x6c, 0xe2, - 0xb1, 0xb5, 0xe1, 0x9b, 0x9b, 0xc5, 0x8c, 0xc5, 0x91, 0x68, 0xc6, 0xaf, 0xc9, 0x84, - 0x44, 0xc7, 0x93, 0xc2, 0xb5, 0xc8, 0x90, 0x67, + 0xc5, 0x94, 0xc5, 0xb4, 0xc2, 0xbd, 0xc6, 0xa4, 0xc6, 0x8e, 0xe1, 0x9b, 0x80, 0xc5, + 0x9c, 0xc4, 0xb5, 0xc3, 0x9f, 0xc7, 0x9b, 0xc6, 0xb2, 0xc2, 0xa8, 0xc8, 0xa2, 0xc3, + 0xad, 0x52, 0xc5, 0xa9, 0xc4, 0x87, 0xc3, 0xbf, 0x2e, 0xc4, 0x8c, 0xc5, 0x8c, 0xc4, + 0x88, 0xc2, 0xbf, 0xc7, 0xb0, 0xc9, 0x85, 0xc4, 0xa6, 0xc7, 0x99, 0xe1, 0x9b, 0x81, + 0x42, 0xc3, 0x8f, 0xc7, 0x8c, 0xe1, 0x9a, 0xa8, 0x2b, 0xc3, 0x9d, 0xc9, 0x87, 0xc4, + 0x89, 0xc6, 0x87, 0xc8, 0x8c, 0xc4, 0xbe, 0x51, 0xc5, 0xac, 0xc9, 0x81, 0xc3, 0xb7, + 0xc5, 0xb2, 0xe1, 0x9b, 0x87, 0xc6, 0xad, 0xc8, 0xa6, 0xc6, 0xad, 0xc6, 0x93, 0xc9, + 0x84, 0xc8, 0x85, 0x6f, 0x41, 0xc7, 0xb5, 0xe1, 0x9b, 0xa8, 0xc5, 0x89, 0xe2, 0xb1, + 0xa7, 0xc3, 0x9f, 0x64, 0xc7, 0x9e, 0x62, 0xc3, 0x95, 0xc7, 0xa1, 0xc6, 0x80, 0xc4, + 0xbb, 0xc2, 0xb1, 0x53, 0xc7, 0xb4, 0x63, 0xe1, 0x9b, 0x95, 0x21, 0xc5, 0xa2, 0xc4, + 0xa3, 0xc3, 0x9a, 0xc6, 0xbe, 0xc4, 0x93, 0xc5, 0xa5, 0xe1, 0x9b, 0x88, 0xc3, 0x85, + 0xc7, 0x9e, 0xc3, 0xbf, 0x48, 0xc5, 0x8a, 0xc3, 0xaf, 0x51, 0xc5, 0x9b, 0xe1, 0x9b, + 0xa3, 0xc4, 0xbf, 0xc5, 0x96, 0xe1, 0x9b, 0x97, 0xc7, 0x8c, 0xc7, 0xb0, 0x7b, 0xc6, + 0x94, 0x23, 0xe1, 0x9b, 0x86, 0xce, 0x86, 0xc4, 0x85, 0xc5, 0x94, 0xc5, 0x9f, 0xc7, + 0x84, 0xc3, 0xb1, 0xc6, 0x8a, 0xc8, 0x97, 0xc3, 0x81, 0xe2, 0xb1, 0xaf, 0xc7, 0xbf, + 0xc2, 0xa6, 0xc6, 0xbf, 0xc4, 0xbe, 0xcd, 0xb6, 0xc3, 0xb6, 0xc9, 0x8c, 0xc7, 0x86, + 0xc5, 0x9a, 0xc3, 0x9d, 0xc3, 0x91, 0xc8, 0xb9, 0xc4, 0x9c, 0xc4, 0x89, 0xc3, 0x99, + 0x70, 0xe1, 0x9b, 0x83, 0xc8, 0x97, 0xc8, 0xaf, 0xc3, 0xa3, 0xe2, 0xb1, 0xbd, 0xe2, + 0xb1, 0xb8, 0xc7, 0x8c, 0xc7, 0xa5, 0x5c, 0xc6, 0xb2, 0xc2, 0xa9, 0xc7, 0xb9, 0xe1, + 0x9b, 0x88, 0xc5, 0xbc, 0xc5, 0x83, 0xc7, 0x90, 0xc6, 0x91, 0xc7, 0xa3, 0x30, 0xe1, + 0x9a, 0xb9, 0xe2, 0xb1, 0xbe, 0xe1, 0x9b, 0xa0, 0x4c, 0xe1, 0x9b, 0x93, 0xc5, 0x93, + 0xc8, 0xb8, 0xc6, 0x98, 0xc3, 0xb2, 0xc6, 0xbf, 0xe1, 0x9b, 0xa6, 0xc5, 0x84, 0xe1, + 0x9b, 0x91, 0xc6, 0xb2, 0xc5, 0x94, 0xc4, 0x93, 0xe1, 0x9b, 0x98, 0xcd, 0xb6, 0xc6, + 0xae, 0x60, 0xc5, 0xa4, 0xc6, 0x81, 0x46, 0xc6, 0x86, 0xc4, 0xa1, 0x33, 0xc6, 0xb2, + 0x71, 0xc6, 0xae, 0xe2, 0xb1, 0xb9, 0x3d, 0x35, 0xe1, 0x9b, 0x9e, 0x62, 0xc8, 0x93, + 0x61, 0xc4, 0x90, 0xe1, 0x9b, 0x8c, 0xe1, 0x9b, 0x9d, 0x35, 0xe1, 0x9b, 0xae, 0xc9, + 0x83, 0xc7, 0x8d, 0xe1, 0x9a, 0xa6, 0xe1, 0x9a, 0xb9, 0xc3, 0x86, 0xc8, 0x9e, 0xc8, + 0xa8, 0xc9, 0x8f, 0xcd, 0xbe, 0xc8, 0xbe, 0xc5, 0x94, 0x63, 0x67, 0xc2, 0xa7, 0xc8, + 0xbf, 0xe2, 0xb1, 0xb2, 0xc3, 0x80, 0x32, 0xc6, 0xac, 0xe1, 0x9a, 0xbc, 0xc3, 0xa6, + 0xc3, 0x96, 0xe1, 0x9b, 0xa5, 0xe1, 0x9a, 0xb2, 0x4c, 0xe1, 0x9b, 0xac, 0xc8, 0xac, + 0xc3, 0xb7, 0xc3, 0x8d, 0x79, 0xc3, 0x9b, 0xc9, 0x8c, 0xcd, 0xbc, 0xc5, 0x9c, 0xe1, + 0x9b, 0xb0, 0xe1, 0x9b, 0x9a, 0x7c, 0xc7, 0xb6, 0xc6, 0xbc, 0xc4, 0x88, 0xe1, 0x9a, + 0xb0, 0xc7, 0x83, 0xc4, 0x9c, 0xe1, 0x9b, 0x82, 0xc5, 0xad, 0xc8, 0xac, 0xe1, 0x9b, + 0xa7, 0x7c, 0xc8, 0x8e, 0xc2, 0xbc, 0xc6, 0x91, 0xc7, 0xbb, 0xc6, 0x83, 0xc5, 0x92, + 0xc5, 0x8e, 0x73, 0xcd, 0xb3, 0xe1, 0x9a, 0xbc, 0x40, 0x61, 0xc6, 0x98, 0xe2, 0xb1, + 0xa9, 0xce, 0x8a, 0xc7, 0xb2, 0x60, 0xc4, 0xb7, 0xc8, 0x83, 0xc6, 0xaa, 0xc7, 0xb5, + 0xc6, 0xbf, 0x41, 0xc7, 0xaf, 0xc6, 0x89, 0x5a, ], - asset_id: [ - 0x7a, 0x8e, 0xea, 0x55, 0xfb, 0xde, 0x77, 0x4d, 0x8a, 0x7a, 0x5c, 0x01, 0xfa, 0x8e, - 0xbc, 0x8c, 0x57, 0x5f, 0xf9, 0x33, 0xd9, 0xd1, 0x51, 0x9b, 0x62, 0xf3, 0x18, 0xf4, - 0x8c, 0xa2, 0xab, 0x94, + asset_base: [ + 0xf1, 0x2e, 0x1e, 0x6c, 0xdd, 0x2a, 0xdb, 0x59, 0x2a, 0x2b, 0xe1, 0x2c, 0x09, 0x18, + 0x31, 0x10, 0xc7, 0x39, 0x0b, 0x80, 0xf3, 0x7b, 0xba, 0x6c, 0x6f, 0x6f, 0xe2, 0x06, + 0xf6, 0xf6, 0x67, 0xac, ], }, TestVector { @@ -372,48 +372,48 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x22, 0xdf, 0x08, ], description: [ - 0xc6, 0x81, 0xc4, 0x90, 0xe1, 0x9a, 0xa0, 0xe1, 0x9b, 0x8c, 0x40, 0xc8, 0x8d, 0xc7, - 0xaf, 0xcd, 0xb2, 0xc5, 0xae, 0xc7, 0xb1, 0xce, 0x84, 0xc2, 0xb6, 0xc7, 0x99, 0xe1, - 0x9a, 0xb4, 0xe1, 0x9b, 0xaf, 0xc6, 0x93, 0xc9, 0x83, 0x37, 0xe2, 0xb1, 0xb1, 0xc4, - 0x98, 0xe1, 0x9b, 0xa7, 0xc8, 0x8f, 0xc3, 0x83, 0xc3, 0x82, 0xc4, 0x98, 0xc7, 0x9c, - 0xc2, 0xae, 0xc8, 0x9a, 0xcd, 0xb5, 0xc3, 0xac, 0xc6, 0x9c, 0xc8, 0xab, 0xc6, 0xbd, - 0x71, 0xc4, 0xaf, 0xe1, 0x9a, 0xa0, 0xe1, 0x9a, 0xb1, 0x23, 0xc5, 0xa8, 0xc4, 0xb9, - 0x45, 0xe1, 0x9b, 0xa8, 0xc6, 0xb0, 0xc4, 0xa0, 0xc8, 0xa7, 0xe1, 0x9b, 0x9b, 0xc6, - 0xa7, 0x79, 0xc7, 0xa8, 0xc7, 0xa1, 0xc7, 0xbd, 0xc3, 0xa1, 0xe2, 0xb1, 0xa2, 0xc3, - 0x82, 0xc6, 0xa7, 0xc4, 0x9d, 0xc7, 0xbb, 0x64, 0xc2, 0xb0, 0xc4, 0x91, 0xe1, 0x9a, - 0xbe, 0xc7, 0xaf, 0xe2, 0xb1, 0xaa, 0xc8, 0xa3, 0xe2, 0xb1, 0xbe, 0x3f, 0xc8, 0xa7, - 0xe1, 0x9b, 0x9c, 0xe1, 0x9b, 0x88, 0xc8, 0xa0, 0xc8, 0x96, 0x28, 0xc6, 0xb7, 0xc7, - 0xa2, 0xc6, 0x99, 0x66, 0xc8, 0x8c, 0xc3, 0x93, 0xc5, 0x8b, 0xc8, 0xa2, 0xc5, 0x91, - 0xe2, 0xb1, 0xa6, 0xc3, 0xbd, 0xc3, 0xa4, 0xc6, 0x86, 0xe1, 0x9b, 0xa4, 0xc3, 0xbe, - 0xc4, 0xbf, 0xc9, 0x88, 0xc6, 0x97, 0xcd, 0xb5, 0xc4, 0xb1, 0xc7, 0x92, 0xc3, 0x86, - 0xc5, 0x80, 0xc5, 0x9c, 0xc5, 0x92, 0xc3, 0x80, 0xe1, 0x9a, 0xbd, 0xc6, 0x84, 0x46, - 0xc6, 0xb6, 0xc6, 0x87, 0xc4, 0x95, 0xc3, 0xbe, 0xc3, 0xbc, 0xc2, 0xaf, 0xc2, 0xa9, - 0xe1, 0x9a, 0xa1, 0xc3, 0xa4, 0xe1, 0x9b, 0xaf, 0xc5, 0x8f, 0xe1, 0x9b, 0x98, 0xc5, - 0x91, 0x55, 0xc3, 0x99, 0xc8, 0xbf, 0xc7, 0xb4, 0x63, 0xc5, 0xa0, 0xc8, 0xa1, 0xe2, - 0xb1, 0xb7, 0xc3, 0xaf, 0xc5, 0x8c, 0xc8, 0xab, 0xc8, 0x8b, 0x3c, 0xc3, 0x8d, 0xc6, - 0x80, 0xc8, 0xa1, 0xc7, 0xb9, 0xc3, 0xbf, 0xc2, 0xa4, 0x4f, 0xc8, 0x82, 0xe2, 0xb1, - 0xa8, 0xc2, 0xbd, 0x78, 0xe1, 0x9b, 0xac, 0xc5, 0x90, 0xc3, 0x94, 0xc3, 0xb8, 0xc7, - 0xb7, 0xc3, 0x84, 0xe2, 0xb1, 0xaf, 0xc6, 0x88, 0xc7, 0x83, 0xc9, 0x8d, 0xc5, 0x9f, - 0x78, 0xc3, 0xbb, 0xe2, 0xb1, 0xa7, 0xe2, 0xb1, 0xbc, 0xc5, 0x8d, 0xc6, 0xbd, 0xe2, - 0xb1, 0xa5, 0xc4, 0x94, 0xc7, 0x91, 0xc8, 0x97, 0x63, 0xc3, 0x99, 0xc2, 0xb6, 0xc7, - 0x99, 0xe1, 0x9a, 0xa2, 0xc7, 0xa0, 0xc8, 0xa6, 0xcd, 0xbc, 0xc6, 0x86, 0xe2, 0xb1, - 0xb5, 0x42, 0xc2, 0xa1, 0xc8, 0x97, 0xc8, 0xa6, 0xc5, 0x98, 0xc4, 0xba, 0xc4, 0x88, - 0xc3, 0x80, 0x59, 0xc8, 0xa0, 0xc6, 0xa7, 0xc4, 0xb5, 0xc8, 0x8e, 0xc3, 0xa1, 0x7c, - 0xc6, 0xae, 0xc2, 0xaa, 0x7c, 0xc8, 0xaa, 0xc2, 0xb8, 0xc4, 0xa9, 0xc7, 0xa8, 0xc3, - 0x98, 0xc9, 0x82, 0xc8, 0x87, 0xc3, 0x98, 0xc5, 0x9d, 0xc9, 0x8b, 0xc4, 0x87, 0xce, - 0x86, 0xc8, 0x96, 0xc2, 0xa5, 0x66, 0xe2, 0xb1, 0xbb, 0xc4, 0x9f, 0xc7, 0xaa, 0xc8, - 0x93, 0xc4, 0xbe, 0xe2, 0xb1, 0xac, 0x5c, 0xc3, 0x8f, 0x44, 0xcd, 0xb4, 0x53, 0x31, - 0xc8, 0xaf, 0xc2, 0xbd, 0xc4, 0x85, 0xc4, 0xa1, 0xc5, 0xaf, 0xc8, 0xa2, 0xc8, 0x95, - 0xc6, 0x95, 0xe1, 0x9b, 0xac, 0xc4, 0x95, 0x2b, 0x4e, 0x78, 0xc5, 0xbf, 0xc7, 0x89, - 0xc7, 0x9c, 0xc3, 0x9b, 0x72, 0xcd, 0xbc, 0xc8, 0x93, 0xc6, 0x93, 0xc3, 0xa5, 0x66, - 0xe1, 0x9a, 0xbf, 0xc3, 0xa6, 0xc5, 0x84, 0xc4, 0xbd, 0xe2, 0xb1, 0xaf, 0xc4, 0x92, - 0x4e, 0xc5, 0x8c, 0xe1, 0x9b, 0xae, 0xc3, 0xac, 0xce, 0x88, 0xc7, 0xb5, 0xc3, 0xa8, - 0xe1, 0x9a, 0xab, 0xc7, 0x95, 0xe2, 0xb1, 0xbd, + 0xc4, 0x81, 0xc7, 0x88, 0xc8, 0xa0, 0xc8, 0xa8, 0xc7, 0xa1, 0xc7, 0x86, 0x29, 0xc6, + 0x99, 0xe2, 0xb1, 0xbe, 0xc4, 0xb0, 0xe1, 0x9a, 0xaf, 0xc5, 0xa7, 0xc8, 0xbd, 0xe1, + 0x9b, 0x93, 0xe2, 0xb1, 0xa7, 0xe1, 0x9a, 0xb6, 0xc6, 0xb3, 0xe1, 0x9b, 0x89, 0xce, + 0x86, 0xc5, 0xa4, 0xc2, 0xa8, 0xc8, 0xa1, 0xe2, 0xb1, 0xa7, 0xc4, 0x98, 0xe1, 0x9b, + 0xa0, 0xc2, 0xb3, 0xe1, 0x9b, 0xa3, 0xe1, 0x9b, 0x9e, 0x3c, 0xe2, 0xb1, 0xa8, 0xc8, + 0xba, 0xc2, 0xb9, 0xc5, 0x9d, 0xc5, 0xa0, 0xe1, 0x9a, 0xb8, 0xc8, 0x85, 0xc6, 0x88, + 0xe2, 0xb1, 0xbd, 0xe1, 0x9b, 0x8b, 0xc6, 0xbb, 0xc2, 0xa5, 0xc5, 0x8e, 0xcd, 0xb7, + 0x74, 0xc4, 0xba, 0xc4, 0x9a, 0xc6, 0xb9, 0xc5, 0xbc, 0xc5, 0x86, 0xc8, 0x9d, 0xe2, + 0xb1, 0xb9, 0xe2, 0xb1, 0xa2, 0xe2, 0xb1, 0xa6, 0xc3, 0xba, 0xc4, 0xb8, 0xcd, 0xb4, + 0xc8, 0xa8, 0x3f, 0xc4, 0xa1, 0xc7, 0x9c, 0x41, 0xc7, 0x81, 0xc8, 0xb8, 0xc6, 0xb8, + 0xc7, 0xaa, 0xcd, 0xb1, 0xc4, 0xb1, 0xce, 0x8c, 0xe1, 0x9b, 0x86, 0x2d, 0xc8, 0x88, + 0xc5, 0xaa, 0xc8, 0xab, 0xc3, 0xb6, 0xc9, 0x8a, 0x75, 0xc8, 0xa1, 0xc4, 0xa7, 0xc4, + 0x85, 0x48, 0xc6, 0x88, 0x3c, 0xe2, 0xb1, 0xb6, 0xc4, 0x8b, 0xe1, 0x9b, 0xa3, 0xc6, + 0x9b, 0xc8, 0x9d, 0xe1, 0x9b, 0xac, 0xe2, 0xb1, 0xaf, 0x2d, 0xc8, 0x93, 0xc4, 0x88, + 0xc3, 0x83, 0xc7, 0x95, 0xe1, 0x9a, 0xb5, 0xc4, 0xa2, 0x68, 0xc3, 0xbf, 0xc4, 0x96, + 0xc8, 0x9d, 0x43, 0xcd, 0xb4, 0x3d, 0xc6, 0xb1, 0xc4, 0x9c, 0xe1, 0x9b, 0xad, 0xc6, + 0xa3, 0xc3, 0xbe, 0xc4, 0xbf, 0xc7, 0xb8, 0xc2, 0xaa, 0xc8, 0xac, 0xc4, 0x91, 0x6f, + 0xc7, 0xbf, 0xc5, 0x84, 0xc8, 0x94, 0xc7, 0x8b, 0x69, 0xc7, 0xb5, 0x3f, 0xc4, 0xb9, + 0xc3, 0xa7, 0xc2, 0xa7, 0xcd, 0xb3, 0xc3, 0xa2, 0xc2, 0xb9, 0xc5, 0xbb, 0xc4, 0x8b, + 0xce, 0x88, 0x74, 0xc4, 0x94, 0xc2, 0xa2, 0xc6, 0x81, 0xc8, 0xb9, 0xc3, 0xb8, 0xc4, + 0xae, 0xc7, 0xb1, 0xc6, 0xb1, 0xc8, 0xa5, 0xc6, 0x9b, 0xc2, 0xaa, 0xe1, 0x9b, 0xa6, + 0xe2, 0xb1, 0xb4, 0xc3, 0xb5, 0xc3, 0xaf, 0xc4, 0xb7, 0xc2, 0xa3, 0xc8, 0xb7, 0x55, + 0xc4, 0xb0, 0xe1, 0x9a, 0xad, 0xc5, 0x8f, 0xc8, 0x9e, 0xc6, 0xa0, 0xc8, 0x9c, 0xc7, + 0xad, 0xe1, 0x9b, 0x8b, 0xc7, 0xbb, 0x62, 0xe2, 0xb1, 0xba, 0xc6, 0xb1, 0xc6, 0x94, + 0xc8, 0x84, 0xe1, 0x9b, 0x9b, 0xc7, 0xa8, 0xc3, 0x8d, 0xc7, 0x8c, 0xce, 0x87, 0xc7, + 0xa1, 0xc4, 0x89, 0xc7, 0xb8, 0x4e, 0xc2, 0xb0, 0xc6, 0x8a, 0xe2, 0xb1, 0xb0, 0xc9, + 0x8e, 0x2e, 0xe2, 0xb1, 0xb3, 0xc8, 0x9d, 0xc5, 0x90, 0xe1, 0x9b, 0xa8, 0xc5, 0xac, + 0xc3, 0x98, 0x72, 0xc4, 0xb1, 0xc4, 0x9f, 0x69, 0xe1, 0x9b, 0x8f, 0x7e, 0xc3, 0xaf, + 0xc7, 0x97, 0xc8, 0x96, 0xc3, 0x8a, 0xe1, 0x9b, 0xa2, 0xc6, 0xb8, 0xc7, 0x80, 0xc8, + 0xbc, 0x7d, 0xce, 0x87, 0x47, 0xc4, 0xad, 0xc4, 0xb8, 0xc8, 0xa4, 0xe1, 0x9b, 0xad, + 0xc7, 0x8a, 0xc3, 0x9c, 0xc2, 0xba, 0xe1, 0x9b, 0x9f, 0xe1, 0x9b, 0x86, 0xc2, 0xaa, + 0xc4, 0xaf, 0xc8, 0x84, 0x28, 0x6c, 0xc2, 0xb9, 0xe1, 0x9b, 0xa6, 0xe1, 0x9b, 0xac, + 0xc3, 0xa5, 0x53, 0xc2, 0xa6, 0xc2, 0xa2, 0xe1, 0x9b, 0xa3, 0x57, 0xc9, 0x84, 0xc4, + 0xa5, 0xc5, 0x8a, 0x7d, 0xc2, 0xb1, 0x66, 0xc8, 0x86, 0xc8, 0xb3, 0xc8, 0x8d, 0xe1, + 0x9b, 0xae, 0xe2, 0xb1, 0xad, 0xc5, 0xb1, 0x55, 0xc8, 0x89, 0xc8, 0x8f, 0xc6, 0xa7, + 0xc4, 0xbd, 0xe2, 0xb1, 0xb4, 0xc4, 0xb6, 0x34, 0xc7, 0xb8, 0xc3, 0x86, 0xc7, 0xad, + 0xc4, 0x88, 0xc8, 0xa9, 0xc8, 0x8f, 0xc8, 0x80, ], - asset_id: [ - 0xbe, 0x14, 0xb4, 0xa7, 0x43, 0x0a, 0x90, 0xa9, 0x50, 0xd5, 0x8d, 0xd7, 0xbb, 0x10, - 0x72, 0x0e, 0xb9, 0x50, 0xb2, 0x4e, 0x6f, 0x27, 0xce, 0x85, 0x4a, 0x80, 0xf6, 0x4a, - 0x19, 0x24, 0xcd, 0x28, + asset_base: [ + 0xd6, 0x96, 0x5d, 0xaf, 0xad, 0x0f, 0xc5, 0xb1, 0x1a, 0x16, 0xc3, 0xc4, 0x0b, 0x27, + 0xc2, 0x10, 0x4c, 0xf9, 0x99, 0x7a, 0x43, 0x56, 0xa3, 0x82, 0xbb, 0xd7, 0xd4, 0xd2, + 0xcc, 0x84, 0x84, 0x9c, ], }, TestVector { @@ -423,48 +423,48 @@ pub(crate) fn test_vectors() -> Vec { 0x96, 0x26, 0xc5, 0x03, ], description: [ - 0xc2, 0xaa, 0xc2, 0xb5, 0xc2, 0xa5, 0xc7, 0xbc, 0xc3, 0x9a, 0xc9, 0x83, 0xc3, 0x8f, - 0x25, 0xc5, 0x83, 0xc3, 0x86, 0xc4, 0xa4, 0xc3, 0xac, 0xc7, 0xbf, 0xc3, 0x93, 0xc6, - 0x95, 0x42, 0x3b, 0xe1, 0x9b, 0x96, 0xc7, 0x85, 0xc3, 0x84, 0x23, 0xc3, 0xb9, 0x53, - 0xc6, 0xb0, 0xc2, 0xac, 0xc4, 0x94, 0xe1, 0x9a, 0xba, 0xc9, 0x8c, 0xc8, 0x8e, 0xce, - 0x87, 0xc7, 0x8f, 0xc8, 0xbb, 0x79, 0xc3, 0xb4, 0x36, 0xc5, 0x9c, 0xc4, 0x9b, 0xe1, - 0x9a, 0xb4, 0x51, 0xc5, 0xb3, 0x2b, 0xc7, 0x93, 0xe1, 0x9b, 0xa7, 0xc5, 0x93, 0xe1, - 0x9b, 0x9b, 0xc6, 0x81, 0xc4, 0xa8, 0xc8, 0x9a, 0xe1, 0x9b, 0x90, 0xc8, 0x9b, 0xc3, - 0xa5, 0xc4, 0xbd, 0xc7, 0x8b, 0xe1, 0x9b, 0xad, 0xc5, 0xa0, 0xe1, 0x9a, 0xb5, 0x5e, - 0x69, 0x78, 0xc5, 0xbc, 0xc7, 0x8e, 0xc4, 0x8b, 0xc4, 0xa9, 0xc6, 0x91, 0xc5, 0xa8, - 0xc5, 0xbe, 0xc4, 0xb0, 0xc5, 0x96, 0xe1, 0x9a, 0xac, 0xe2, 0xb1, 0xbf, 0xc8, 0xae, - 0xc3, 0x97, 0xc6, 0x8a, 0xc4, 0x9b, 0xc8, 0x9b, 0xc7, 0x89, 0xe1, 0x9a, 0xbd, 0xe1, - 0x9b, 0x89, 0xc9, 0x86, 0xc7, 0x91, 0xe1, 0x9b, 0x96, 0xe1, 0x9a, 0xa4, 0xc8, 0xad, - 0xcd, 0xb0, 0xce, 0x87, 0xc5, 0xb7, 0x5d, 0xe1, 0x9b, 0x9b, 0xc9, 0x80, 0xc3, 0x9b, - 0xc3, 0x85, 0xc3, 0x9a, 0xc6, 0xb7, 0xe1, 0x9b, 0x89, 0xc2, 0xb6, 0xe1, 0x9a, 0xac, - 0xe1, 0x9b, 0x8f, 0xc2, 0xb3, 0xcd, 0xbd, 0xc3, 0x85, 0xc6, 0x90, 0x32, 0xc7, 0xab, - 0xe2, 0xb1, 0xac, 0xc8, 0x8a, 0xc4, 0x86, 0xc5, 0x98, 0xc5, 0x90, 0xc8, 0x9c, 0xc3, - 0x8e, 0xc8, 0x96, 0xc5, 0xa8, 0xc3, 0xa4, 0x7c, 0xc6, 0xb9, 0xc5, 0xa8, 0xc3, 0xa5, - 0x36, 0xc2, 0xa3, 0x7a, 0xc5, 0xb1, 0xc7, 0xb0, 0xc5, 0xb6, 0x61, 0xc5, 0x80, 0xc9, - 0x84, 0xc6, 0xb0, 0xc5, 0x8f, 0xe1, 0x9b, 0x9a, 0xc6, 0xb0, 0xcd, 0xb7, 0xe1, 0x9b, - 0x8a, 0xc6, 0xba, 0xe1, 0x9b, 0x9e, 0x3e, 0x57, 0xc8, 0x9c, 0xc6, 0x9b, 0x5e, 0xc8, - 0xa7, 0xc8, 0x98, 0xc5, 0xbc, 0xc3, 0x9d, 0xc3, 0xa4, 0xe1, 0x9a, 0xbd, 0xe1, 0x9b, - 0x81, 0xc6, 0xbf, 0x6c, 0xc4, 0xbd, 0xc4, 0xbe, 0xe1, 0x9b, 0x8a, 0x75, 0x6c, 0xc5, - 0x97, 0xc8, 0xbc, 0xc5, 0x9e, 0xc5, 0x94, 0xe1, 0x9a, 0xa5, 0xc9, 0x81, 0xc6, 0x88, - 0xe1, 0x9b, 0x85, 0xe2, 0xb1, 0xbe, 0x49, 0xc5, 0xa6, 0xc4, 0xb7, 0xc9, 0x88, 0xe1, - 0x9a, 0xa6, 0xc5, 0x91, 0xc5, 0xa5, 0xce, 0x8c, 0x56, 0xc3, 0x99, 0xc4, 0x9e, 0xc2, - 0xb4, 0xc3, 0x8b, 0x53, 0x2c, 0xc7, 0xb8, 0x3a, 0xc7, 0x81, 0xc6, 0xb3, 0xe1, 0x9b, - 0xaf, 0xc3, 0xaa, 0xc7, 0xa7, 0xc3, 0xbe, 0xe2, 0xb1, 0xb7, 0xe1, 0x9a, 0xb4, 0x5c, - 0x7c, 0xc2, 0xbf, 0xe1, 0x9a, 0xb3, 0xc8, 0xb6, 0xc6, 0x8e, 0xe1, 0x9b, 0xae, 0xc5, - 0xaf, 0xe1, 0x9b, 0x90, 0xc6, 0xab, 0xc5, 0xb2, 0xe1, 0x9b, 0x81, 0x49, 0xe1, 0x9b, - 0xa4, 0xc3, 0x80, 0x75, 0xc4, 0x9c, 0xc8, 0x96, 0xe1, 0x9a, 0xae, 0x5d, 0xc4, 0xba, - 0xe1, 0x9b, 0x86, 0x2b, 0xe2, 0xb1, 0xb0, 0xc4, 0x9d, 0xe2, 0xb1, 0xb9, 0xc6, 0xb5, - 0xc3, 0xb2, 0xc6, 0x87, 0xc5, 0x9c, 0xc5, 0x94, 0xc6, 0x92, 0xc3, 0x86, 0xc5, 0x82, - 0xc6, 0xb7, 0x47, 0xc6, 0x8b, 0xcd, 0xbd, 0xcd, 0xbd, 0xc7, 0xad, 0xc7, 0x97, 0xc2, - 0xa1, 0xc8, 0xa8, 0xe1, 0x9a, 0xbd, 0xc7, 0xad, 0xc4, 0xac, 0xc8, 0x99, 0x6c, 0x36, - 0x5f, 0xc5, 0x89, 0xc4, 0x87, 0xc4, 0x80, 0xc2, 0xbe, 0xe2, 0xb1, 0xbd, 0xc4, 0x8f, - 0xc4, 0xb1, 0xc3, 0x83, 0xc5, 0xbd, 0xc6, 0xa5, 0xc5, 0xb9, 0xc5, 0xa5, 0xc6, 0xba, - 0x6e, 0xc8, 0xaa, 0x6d, 0xc4, 0x80, 0x7c, 0x5a, + 0x2b, 0xc2, 0xbe, 0xe1, 0x9b, 0x94, 0xe2, 0xb1, 0xad, 0xc2, 0xa8, 0xc4, 0x9a, 0xc3, + 0x8c, 0xe2, 0xb1, 0xaa, 0xc7, 0x83, 0x6a, 0xc8, 0xbf, 0xc6, 0xbd, 0xc4, 0xa6, 0xc2, + 0xa2, 0xc5, 0x8e, 0xc8, 0x9e, 0xce, 0x89, 0xc5, 0xa1, 0xc6, 0xb8, 0xc8, 0x89, 0xe1, + 0x9a, 0xaf, 0xc8, 0xa1, 0xc9, 0x8e, 0xc3, 0xbf, 0xc7, 0xbc, 0x64, 0x72, 0xc4, 0xbb, + 0xc6, 0x9a, 0xc6, 0x97, 0x2a, 0xc3, 0xb4, 0x4f, 0x4b, 0xc4, 0xa2, 0xc3, 0x93, 0xe2, + 0xb1, 0xba, 0xe2, 0xb1, 0xb5, 0x37, 0xe1, 0x9b, 0x9a, 0xc2, 0xbb, 0xc5, 0x94, 0xc7, + 0xb8, 0xc5, 0x93, 0xc6, 0xa2, 0xc8, 0xa9, 0xc6, 0xa2, 0x5f, 0xc5, 0xb7, 0xc3, 0xae, + 0xc3, 0x98, 0xc6, 0x89, 0xc8, 0xa1, 0xc8, 0x87, 0xc4, 0x9c, 0xe2, 0xb1, 0xb5, 0xc7, + 0xb3, 0xc3, 0x9e, 0xc7, 0x8c, 0xc8, 0xa4, 0xe1, 0x9a, 0xa4, 0xe1, 0x9b, 0x9f, 0xe1, + 0x9b, 0x9a, 0xc8, 0x9c, 0xc7, 0xa4, 0xc3, 0xac, 0x47, 0x56, 0xe1, 0x9a, 0xae, 0x7e, + 0xc7, 0x8b, 0xc8, 0x9e, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, 0x84, 0x73, 0xc7, 0x93, 0xc5, + 0xba, 0x6f, 0xe2, 0xb1, 0xb0, 0xc4, 0xa0, 0xe1, 0x9b, 0x89, 0xe1, 0x9a, 0xb6, 0xc3, + 0x82, 0xe1, 0x9a, 0xbd, 0xc9, 0x8b, 0xc7, 0xb8, 0xe2, 0xb1, 0xaf, 0xc5, 0xba, 0x21, + 0xc3, 0x9c, 0x3c, 0xe1, 0x9b, 0x96, 0xc8, 0xac, 0x6e, 0xc5, 0x8d, 0xe1, 0x9b, 0x80, + 0xc3, 0xab, 0xc5, 0x85, 0xc4, 0xab, 0x6b, 0xc5, 0x90, 0xc8, 0x99, 0xe1, 0x9b, 0x99, + 0xc8, 0x84, 0xc3, 0xbb, 0xc8, 0x82, 0xc8, 0xa1, 0xc3, 0x92, 0xc7, 0x9d, 0xc4, 0xaf, + 0xc6, 0xaa, 0x61, 0xc5, 0x82, 0xc7, 0xb9, 0xc7, 0xa1, 0xce, 0x89, 0xc8, 0xb2, 0xe1, + 0x9b, 0xa8, 0xc7, 0x8d, 0xcd, 0xbe, 0x67, 0xc9, 0x87, 0xc4, 0xba, 0x43, 0xc7, 0xa2, + 0xc6, 0xb1, 0xe1, 0x9a, 0xad, 0xc5, 0x83, 0xc3, 0xb0, 0xc5, 0xb2, 0xc6, 0x9a, 0x3e, + 0xc4, 0xb8, 0xc2, 0xb9, 0xc8, 0xa1, 0xc6, 0x93, 0xc7, 0xa5, 0x6a, 0xc5, 0xa9, 0xc4, + 0xa7, 0xc8, 0xb6, 0xc3, 0xa6, 0xc4, 0xb2, 0xc8, 0x8d, 0xcd, 0xb1, 0x41, 0xc6, 0x85, + 0xc7, 0x84, 0xc4, 0x83, 0xe1, 0x9b, 0xa9, 0xc2, 0xb5, 0x52, 0xc5, 0x80, 0xe1, 0x9b, + 0x83, 0xc6, 0xbb, 0xc5, 0x8e, 0xe1, 0x9a, 0xa4, 0xc2, 0xa6, 0xe1, 0x9b, 0xa3, 0xe1, + 0x9a, 0xbd, 0xe1, 0x9b, 0xaf, 0xc4, 0xba, 0xe2, 0xb1, 0xa6, 0xc3, 0x89, 0x5a, 0xc4, + 0xa9, 0xe1, 0x9a, 0xba, 0x5d, 0xc6, 0x9f, 0xc4, 0xa8, 0xc4, 0xa3, 0xc5, 0x9f, 0xc6, + 0x8e, 0xe2, 0xb1, 0xb8, 0xc8, 0x9b, 0xe2, 0xb1, 0xa5, 0xc6, 0x9d, 0xe1, 0x9a, 0xaa, + 0xe1, 0x9b, 0x98, 0xc2, 0xa1, 0xc2, 0xb4, 0xc6, 0x87, 0xc7, 0x93, 0xc6, 0x88, 0xe1, + 0x9a, 0xb3, 0xc4, 0x98, 0xc2, 0xb1, 0xc8, 0x91, 0xc3, 0xb5, 0x62, 0xc7, 0xb8, 0xe1, + 0x9b, 0x94, 0xc3, 0x87, 0xc4, 0xa7, 0xc8, 0x8a, 0xc5, 0x95, 0xe1, 0x9b, 0xb0, 0xc4, + 0x98, 0xe2, 0xb1, 0xb3, 0xc5, 0xac, 0xcd, 0xb3, 0xc6, 0xbb, 0xc7, 0xbf, 0xc4, 0xbe, + 0xc3, 0x98, 0xcd, 0xba, 0x5d, 0xc3, 0x9e, 0x5a, 0xc4, 0x8c, 0x3e, 0x3f, 0x76, 0xc7, + 0x8a, 0xe1, 0x9a, 0xbf, 0xc6, 0xa6, 0xe1, 0x9b, 0x95, 0x77, 0xc7, 0xb2, 0xe1, 0x9b, + 0x91, 0xc8, 0x84, 0xe2, 0xb1, 0xa3, 0xc7, 0x82, 0xc4, 0x87, 0x70, 0xe1, 0x9a, 0xb1, + 0xc6, 0x91, 0xe1, 0x9a, 0xba, 0xc5, 0xa4, 0xc8, 0x8c, 0x59, 0xc4, 0xaa, 0xc6, 0x9a, + 0xc7, 0xb0, 0xc3, 0x87, 0xc7, 0xb6, 0xc6, 0x80, 0x3c, 0xcd, 0xb4, 0xc4, 0x8d, 0x71, + 0xe1, 0x9b, 0x9b, 0xe2, 0xb1, 0xb6, 0xc6, 0xb9, 0xe1, 0x9b, 0x85, 0xe2, 0xb1, 0xba, + 0xc7, 0xb2, 0xc8, 0xa4, 0xe1, 0x9a, 0xa2, 0x5a, ], - asset_id: [ - 0xac, 0xa7, 0x66, 0x43, 0xac, 0xdd, 0x83, 0xe3, 0x8e, 0xe5, 0xcf, 0xe0, 0xe7, 0xd2, - 0x99, 0xd6, 0x35, 0x69, 0x0a, 0x82, 0xba, 0x96, 0x51, 0x47, 0xe2, 0xa4, 0x48, 0x24, - 0x9b, 0xee, 0xb2, 0x88, + asset_base: [ + 0x98, 0x06, 0x94, 0xc0, 0xcc, 0x2c, 0x02, 0x1c, 0xa3, 0x57, 0xa6, 0x06, 0x25, 0x2e, + 0x7e, 0x66, 0x90, 0xed, 0xa5, 0xea, 0x56, 0xc4, 0xfb, 0x57, 0x32, 0xdd, 0x0b, 0x8b, + 0xbf, 0xf0, 0x3b, 0x9d, ], }, TestVector { @@ -474,48 +474,48 @@ pub(crate) fn test_vectors() -> Vec { 0x60, 0x3e, 0xf8, 0x1f, ], description: [ - 0xc7, 0xad, 0x3b, 0xc8, 0x91, 0xc6, 0x96, 0xe1, 0x9a, 0xbd, 0xe1, 0x9a, 0xa6, 0xce, - 0x87, 0xc3, 0x83, 0xc3, 0x84, 0xe1, 0x9b, 0x84, 0xc9, 0x8a, 0xc4, 0x97, 0xc9, 0x87, - 0xe2, 0xb1, 0xba, 0xc6, 0x93, 0xc6, 0x98, 0xe2, 0xb1, 0xb7, 0xc6, 0x8e, 0xc8, 0x8f, - 0xc9, 0x84, 0xc2, 0xbe, 0x55, 0xc8, 0xb0, 0xc7, 0x82, 0xc2, 0xb2, 0xc6, 0x88, 0xcd, - 0xb3, 0xc6, 0xb2, 0x2e, 0x2e, 0xc3, 0x87, 0xc9, 0x80, 0xc7, 0x9c, 0xc8, 0x9f, 0xc5, - 0xb0, 0xc8, 0x9e, 0xc4, 0xbb, 0xc7, 0x81, 0x74, 0x6c, 0xc6, 0x8c, 0xc6, 0x8f, 0xe1, - 0x9a, 0xb4, 0xc8, 0x94, 0xc2, 0xac, 0xc4, 0x8f, 0xc5, 0xb6, 0xc8, 0xb5, 0xc3, 0xb7, - 0xcd, 0xb6, 0xc2, 0xb1, 0xc5, 0xb1, 0xc4, 0xa5, 0x40, 0x68, 0x58, 0x2b, 0xc5, 0xb7, - 0xc4, 0x91, 0xc6, 0xa1, 0xc7, 0xa7, 0x79, 0xe1, 0x9b, 0xa6, 0xe2, 0xb1, 0xac, 0xc6, - 0x99, 0x51, 0xc7, 0xaf, 0xcd, 0xb4, 0xe1, 0x9b, 0x8e, 0xe1, 0x9b, 0xad, 0xc8, 0x96, - 0xe1, 0x9b, 0xad, 0xc3, 0xa1, 0xc6, 0x95, 0xc5, 0x98, 0xc6, 0x95, 0xc2, 0xaf, 0xe2, - 0xb1, 0xac, 0xc4, 0xbe, 0xc5, 0xac, 0xc8, 0x85, 0xc5, 0xa9, 0xc4, 0x93, 0xc5, 0x9a, - 0x6c, 0xc3, 0xae, 0xe1, 0x9a, 0xba, 0xc6, 0x85, 0xc6, 0x92, 0xc5, 0xa7, 0xc4, 0xa5, - 0xc5, 0x80, 0xc6, 0xaa, 0xe2, 0xb1, 0xa5, 0xc4, 0xaa, 0xc8, 0x83, 0xc5, 0xad, 0xc9, - 0x88, 0x7c, 0xc7, 0xa6, 0xe1, 0x9a, 0xb9, 0xc3, 0xa4, 0xc9, 0x84, 0xc5, 0xa3, 0xc3, - 0xb6, 0xc5, 0x8c, 0xc8, 0xab, 0xc8, 0xa7, 0xc8, 0xb7, 0xc5, 0x9c, 0xc6, 0xb5, 0xc8, - 0x8d, 0xc2, 0xb7, 0xc5, 0x93, 0xc5, 0xb7, 0xc7, 0xac, 0xcd, 0xbe, 0xc3, 0xa2, 0xc5, - 0xa5, 0xc4, 0x8c, 0xe2, 0xb1, 0xbf, 0x66, 0xc5, 0xbf, 0xc6, 0x83, 0xc6, 0x99, 0xc2, - 0xa2, 0xe1, 0x9b, 0xad, 0x7c, 0xc4, 0x9e, 0xc6, 0xa2, 0xc3, 0xb8, 0xc6, 0xb6, 0xc6, - 0xaf, 0x72, 0xc6, 0xb1, 0xc6, 0x98, 0xc6, 0xb8, 0x49, 0xe1, 0x9a, 0xa6, 0x59, 0xe1, - 0x9b, 0xa1, 0xc8, 0xb6, 0xc4, 0xa6, 0xc6, 0xbe, 0xc8, 0xa1, 0xe2, 0xb1, 0xa5, 0xe1, - 0x9b, 0xa3, 0xc5, 0x8d, 0xc2, 0xb5, 0xc6, 0xa8, 0xc7, 0xbd, 0xc8, 0x8a, 0xe1, 0x9b, - 0xb0, 0xc5, 0xaf, 0x56, 0xc8, 0x8b, 0x34, 0xc4, 0x94, 0xc4, 0xbc, 0x67, 0xc6, 0xb5, - 0xc2, 0xb0, 0x63, 0xe1, 0x9b, 0x99, 0xc4, 0xa8, 0xc6, 0x9c, 0xe1, 0x9a, 0xbc, 0xe1, - 0x9b, 0x8a, 0xc6, 0x99, 0x4b, 0xc6, 0xb2, 0xe1, 0x9b, 0xa2, 0xc8, 0x9f, 0xc5, 0x88, - 0xc5, 0xb6, 0xc3, 0xb8, 0x6d, 0xe2, 0xb1, 0xa2, 0xc7, 0xb4, 0xcd, 0xb3, 0xc2, 0xa3, - 0xc7, 0xa1, 0xc4, 0x83, 0xc7, 0xb1, 0xc8, 0x98, 0xc8, 0x84, 0x6b, 0xc7, 0x84, 0xc6, - 0xb6, 0xe1, 0x9a, 0xb8, 0xc5, 0x93, 0xc8, 0x90, 0x79, 0xc8, 0xa3, 0xe1, 0x9a, 0xb0, - 0xe1, 0x9b, 0xad, 0xc8, 0xb0, 0xc4, 0x9e, 0xe1, 0x9b, 0x9a, 0xc7, 0x97, 0x32, 0xc6, - 0xb2, 0xc9, 0x83, 0xe1, 0x9b, 0x96, 0xc9, 0x8f, 0xc3, 0x8c, 0xe2, 0xb1, 0xad, 0xc4, - 0xbd, 0xc3, 0xbe, 0xe1, 0x9b, 0x8b, 0xc8, 0x9d, 0xc6, 0x95, 0xc8, 0x8f, 0xc8, 0x9e, - 0xc8, 0x83, 0x74, 0xc7, 0xbe, 0xe1, 0x9b, 0x8a, 0x3c, 0xc5, 0x93, 0x63, 0xc7, 0x98, - 0x31, 0xc4, 0x82, 0x56, 0xe2, 0xb1, 0xa3, 0x53, 0xe1, 0x9b, 0xa4, 0xc7, 0x94, 0xc7, - 0x9e, 0x2e, 0xcd, 0xbe, 0xc7, 0x9c, 0xc4, 0x90, 0xe2, 0xb1, 0xbe, 0xe2, 0xb1, 0xba, - 0xc7, 0x82, 0xc5, 0xb2, 0xe1, 0x9a, 0xa4, 0xc6, 0xb2, 0xcd, 0xb2, 0xc3, 0xa5, 0xe1, - 0x9b, 0xab, 0xc3, 0xa9, 0xc7, 0xa3, 0xc3, 0x8a, 0xc2, 0xa3, 0xc9, 0x82, 0x7b, 0xc6, - 0xb3, 0x4b, 0xc4, 0xb6, 0xc4, 0x85, 0xc7, 0x8c, + 0xc2, 0xb3, 0xe2, 0xb1, 0xb3, 0xc4, 0xab, 0xe1, 0x9b, 0x81, 0xe1, 0x9a, 0xbc, 0xc7, + 0x82, 0xc3, 0xa6, 0xc7, 0x94, 0xc4, 0x8a, 0xc7, 0x8f, 0xc6, 0xaf, 0xc7, 0xaf, 0xc3, + 0xbe, 0xe1, 0x9a, 0xa7, 0xc6, 0x88, 0xc6, 0xb2, 0xc6, 0xab, 0xc4, 0x98, 0xc6, 0xb4, + 0xc7, 0x9b, 0xc7, 0xbb, 0xe1, 0x9b, 0xa1, 0xc5, 0xba, 0xc4, 0xb3, 0xc8, 0xb5, 0xe1, + 0x9b, 0x97, 0xc5, 0xb7, 0xc8, 0x89, 0x35, 0x66, 0xcd, 0xba, 0xc6, 0xb2, 0xc6, 0xac, + 0x29, 0xe2, 0xb1, 0xa9, 0xc8, 0xb4, 0xc3, 0xa5, 0x7d, 0xc8, 0xa0, 0xc3, 0x9a, 0xc8, + 0xaf, 0xc8, 0x82, 0xc3, 0xa4, 0xc4, 0xb5, 0x37, 0xe1, 0x9b, 0xa0, 0xc4, 0x8e, 0x32, + 0xc5, 0xb2, 0xc4, 0x90, 0xc5, 0xbb, 0xe1, 0x9b, 0x8d, 0xc7, 0x8a, 0xe1, 0x9a, 0xb2, + 0xc6, 0xbb, 0xc7, 0xa5, 0xc2, 0xbe, 0xe1, 0x9b, 0x96, 0xc3, 0x91, 0xc6, 0x86, 0xe1, + 0x9b, 0xa7, 0xc5, 0x93, 0xc3, 0xb5, 0x59, 0xc6, 0x9a, 0xc7, 0x9c, 0xe1, 0x9a, 0xb8, + 0xc6, 0x83, 0xe2, 0xb1, 0xb9, 0x59, 0xc9, 0x8b, 0xc4, 0x90, 0xc6, 0x92, 0xc2, 0xbf, + 0xc7, 0xbf, 0xc6, 0x97, 0x61, 0x37, 0xc8, 0xbc, 0xc2, 0xbd, 0xc5, 0xb7, 0xc5, 0xa3, + 0xc4, 0xa4, 0xc7, 0x96, 0xc6, 0x84, 0xc6, 0xb6, 0xc4, 0x83, 0x42, 0xc8, 0xba, 0xc7, + 0x94, 0xe1, 0x9b, 0xa2, 0xc3, 0xbf, 0xc6, 0xb5, 0xc6, 0x94, 0x7c, 0xc2, 0xbc, 0x5e, + 0xc3, 0xa6, 0xe1, 0x9a, 0xb6, 0xc9, 0x8b, 0xc4, 0x83, 0xc8, 0x9b, 0xc8, 0x9d, 0xc3, + 0xb3, 0xc8, 0xb6, 0xe1, 0x9b, 0xa8, 0xc2, 0xbd, 0xe1, 0x9b, 0xa3, 0xc8, 0x8f, 0x26, + 0xe1, 0x9b, 0x8d, 0xc8, 0x88, 0xc6, 0xbd, 0x6a, 0xc3, 0x8b, 0xc5, 0x91, 0xc4, 0xb1, + 0xce, 0x89, 0x4b, 0xc5, 0xb1, 0xe1, 0x9b, 0x8c, 0xc3, 0x9f, 0xc4, 0xb8, 0xc3, 0x98, + 0xe1, 0x9b, 0x91, 0xc7, 0xa9, 0xc8, 0x9c, 0xc5, 0x93, 0xc6, 0xb0, 0xe1, 0x9b, 0x89, + 0x6c, 0xe1, 0x9b, 0xa4, 0x4a, 0xc6, 0xad, 0xc7, 0x92, 0xc3, 0x88, 0x71, 0xc6, 0xa0, + 0xc6, 0x9f, 0xe1, 0x9b, 0x94, 0xc4, 0xbe, 0xc5, 0x84, 0xc4, 0x9e, 0xc2, 0xb6, 0xcd, + 0xb7, 0xc4, 0xa6, 0xc7, 0xbb, 0xc3, 0x97, 0xc7, 0x87, 0xc4, 0x94, 0x75, 0x43, 0xc6, + 0xbd, 0xc3, 0xb1, 0xc8, 0x92, 0xc3, 0x93, 0xc7, 0x8d, 0x65, 0xc8, 0x8a, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb5, 0xe2, 0xb1, 0xb0, 0xc7, 0x8d, 0x2f, 0x3f, 0xc3, 0xa9, 0xc8, 0xa1, + 0xc5, 0xa0, 0xc4, 0xa1, 0xc7, 0x87, 0xc2, 0xa6, 0x52, 0xc5, 0x89, 0xe1, 0x9b, 0xaf, + 0xc8, 0x84, 0xc5, 0xa3, 0xc7, 0x95, 0xc8, 0xa5, 0xc5, 0xb5, 0xc4, 0xa1, 0x79, 0xe1, + 0x9a, 0xba, 0xc8, 0x97, 0xc3, 0x94, 0xc5, 0x80, 0xe1, 0x9b, 0x88, 0x4b, 0x68, 0xc7, + 0x89, 0xc5, 0x98, 0x4e, 0xc4, 0xb9, 0xe1, 0x9b, 0xab, 0xc4, 0x95, 0xc6, 0xa0, 0xe1, + 0x9b, 0xa5, 0x24, 0xc6, 0x85, 0xc3, 0x93, 0xc6, 0x98, 0x6c, 0xc8, 0x94, 0xc5, 0xaa, + 0xc4, 0x94, 0xc3, 0xaf, 0xc4, 0xb6, 0x46, 0xc5, 0x90, 0xc4, 0x91, 0xc6, 0x97, 0xce, + 0x8a, 0xc7, 0xb9, 0xc6, 0xa7, 0xc3, 0x81, 0xc6, 0xa1, 0xc7, 0x82, 0xcd, 0xbc, 0xc6, + 0x82, 0xc2, 0xb9, 0xc5, 0xa7, 0xc5, 0xa3, 0xc9, 0x84, 0xc4, 0x8e, 0xc8, 0x9b, 0xe2, + 0xb1, 0xae, 0xe1, 0x9a, 0xbe, 0xc7, 0xb8, 0xe2, 0xb1, 0xb4, 0xe2, 0xb1, 0xba, 0xc4, + 0xb6, 0xc7, 0x8d, 0xe2, 0xb1, 0xb1, 0xc7, 0xbf, 0x50, 0xc5, 0x9f, 0xc6, 0x9d, 0xc5, + 0xa4, 0xc6, 0xb2, 0xc7, 0x83, 0x76, 0x68, 0xc8, 0x90, 0xc3, 0xaa, 0xc8, 0x8b, 0xc8, + 0x86, 0xc5, 0xba, 0x76, 0xcd, 0xb1, 0xc6, 0xa7, 0xc6, 0xa7, 0xc6, 0x84, 0xe1, 0x9b, + 0xa7, 0xc9, 0x8c, 0xc9, 0x89, 0x53, 0xc4, 0xb5, ], - asset_id: [ - 0x03, 0x74, 0x69, 0x16, 0xa8, 0xa6, 0xb8, 0xff, 0xa0, 0x4d, 0x71, 0x95, 0xbc, 0x06, - 0x74, 0x96, 0xa6, 0xce, 0xce, 0x35, 0x6a, 0x2a, 0x14, 0x6d, 0x69, 0x52, 0x9a, 0xea, - 0xac, 0x10, 0x1a, 0xb8, + asset_base: [ + 0xc1, 0x69, 0x63, 0x4b, 0xf8, 0x47, 0x9d, 0x3d, 0x09, 0x47, 0x76, 0x4f, 0xbd, 0x30, + 0x3c, 0x31, 0xdc, 0x10, 0xb0, 0xa2, 0x81, 0x39, 0x1f, 0x5a, 0xde, 0xac, 0xf8, 0x2a, + 0xae, 0xce, 0xf3, 0xbe, ], }, TestVector { @@ -525,48 +525,48 @@ pub(crate) fn test_vectors() -> Vec { 0xaf, 0x40, 0x8d, 0x12, ], description: [ - 0xe1, 0x9b, 0xad, 0xe1, 0x9a, 0xaf, 0x39, 0xc7, 0x92, 0xc4, 0x87, 0xc8, 0x8b, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9a, 0xbb, 0xe1, 0x9b, 0x97, 0xc6, 0x89, 0xc4, 0xb1, 0xc8, 0xa1, - 0xc7, 0xad, 0xc7, 0x8a, 0xe1, 0x9a, 0xb4, 0xe1, 0x9a, 0xa4, 0xc5, 0x99, 0xe1, 0x9b, - 0xa5, 0xcd, 0xb7, 0xc6, 0xa5, 0xc3, 0xb6, 0xe1, 0x9b, 0x9a, 0xe1, 0x9b, 0xab, 0xc5, - 0x9a, 0x4d, 0xe1, 0x9b, 0x81, 0xe1, 0x9b, 0x8a, 0xc2, 0xbe, 0xc5, 0x88, 0xc6, 0xbd, - 0xe2, 0xb1, 0xb8, 0xe2, 0xb1, 0xbb, 0xc5, 0x8d, 0xc2, 0xbc, 0xc6, 0x81, 0xc5, 0x9c, - 0xe2, 0xb1, 0xb5, 0xc8, 0x95, 0x6d, 0xc3, 0x9b, 0xc2, 0xb3, 0x36, 0xc4, 0x88, 0xc6, - 0xbf, 0xc7, 0xb6, 0xe1, 0x9b, 0xad, 0xc7, 0x8e, 0xe1, 0x9b, 0xa9, 0x69, 0xc3, 0xa5, - 0xe2, 0xb1, 0xb3, 0xc7, 0xbb, 0xc6, 0x9f, 0xc3, 0xa7, 0xc3, 0xbe, 0xce, 0x86, 0xc6, - 0xbd, 0xc6, 0x95, 0xc7, 0xa2, 0xc7, 0xbf, 0xc7, 0xad, 0xc4, 0x93, 0xc6, 0xb6, 0xc3, - 0x8b, 0xe2, 0xb1, 0xbb, 0xc3, 0x96, 0xc8, 0xaa, 0xc7, 0xa9, 0xc8, 0x8e, 0xc2, 0xb9, - 0xc8, 0x99, 0xc3, 0x93, 0xe1, 0x9b, 0x9c, 0xc2, 0xac, 0xc7, 0xbc, 0xc3, 0xb6, 0xc2, - 0xa7, 0xc3, 0xa9, 0xcd, 0xbc, 0xe2, 0xb1, 0xbf, 0xe1, 0x9a, 0xb1, 0xc2, 0xb8, 0xc3, - 0xb9, 0xe1, 0x9b, 0x9e, 0xc7, 0x88, 0xc5, 0x9e, 0xc6, 0xb9, 0xc4, 0x9e, 0xc6, 0x8e, - 0x3e, 0xc8, 0x93, 0x74, 0x37, 0xe2, 0xb1, 0xb2, 0x58, 0xcd, 0xbe, 0xc6, 0x9a, 0x5c, - 0xc8, 0x94, 0xe1, 0x9a, 0xb6, 0xc8, 0x90, 0xc5, 0x95, 0xe2, 0xb1, 0xa6, 0x23, 0xc5, - 0xa2, 0xc3, 0x9c, 0xe2, 0xb1, 0xb4, 0xc4, 0x94, 0xc3, 0x97, 0xc6, 0x9f, 0xc3, 0x92, - 0xcd, 0xbd, 0xc4, 0xbe, 0xc5, 0xba, 0xc6, 0xb0, 0x77, 0xc7, 0xba, 0xc5, 0xb0, 0xc3, - 0x9b, 0xc5, 0xbf, 0xc7, 0xa3, 0xc3, 0xad, 0xc6, 0xbf, 0xc3, 0xbe, 0xc5, 0xab, 0xc7, - 0xb9, 0xe1, 0x9b, 0xa9, 0xc5, 0xb3, 0xe1, 0x9a, 0xac, 0xe1, 0x9a, 0xa4, 0xc5, 0x9e, - 0xc2, 0xa7, 0xcd, 0xbe, 0x4e, 0xe2, 0xb1, 0xb5, 0xc4, 0xb8, 0xe1, 0x9a, 0xbd, 0xe1, - 0x9b, 0x83, 0xe2, 0xb1, 0xa2, 0xc6, 0xa4, 0xc6, 0xa6, 0xc7, 0xbc, 0xe1, 0x9b, 0x82, - 0x44, 0xe1, 0x9a, 0xa4, 0xc3, 0xb3, 0xc5, 0xb1, 0xc3, 0xa5, 0xc7, 0xaa, 0x5b, 0xc6, - 0x9c, 0xc7, 0x92, 0x2f, 0xc6, 0x86, 0xe1, 0x9b, 0xa5, 0xe1, 0x9a, 0xb5, 0x44, 0xc7, - 0xb1, 0xc4, 0xac, 0xc8, 0xae, 0xe1, 0x9a, 0xa1, 0xc8, 0xaa, 0xc5, 0x9a, 0xc3, 0xac, - 0xc8, 0xac, 0xe1, 0x9b, 0xa3, 0xc5, 0xab, 0xc7, 0x98, 0xe1, 0x9b, 0x93, 0x6e, 0xc7, - 0x8a, 0xc4, 0x9f, 0xe1, 0x9b, 0x9b, 0xc7, 0x86, 0xe2, 0xb1, 0xb8, 0xc6, 0xaa, 0xc8, - 0xa1, 0xc2, 0xbf, 0xc3, 0x97, 0xcd, 0xbd, 0xc8, 0x99, 0xc4, 0x98, 0xc3, 0x88, 0x3f, - 0x4a, 0xc7, 0x99, 0xc4, 0x8a, 0xc7, 0x9a, 0xc5, 0xa9, 0xc7, 0xb5, 0xc7, 0x9b, 0xc5, - 0xb1, 0xc5, 0xbf, 0xc7, 0x81, 0xc8, 0xb2, 0xc9, 0x89, 0xc5, 0xa4, 0xc8, 0x82, 0xc6, - 0x91, 0xe1, 0x9a, 0xa8, 0xc7, 0xac, 0x6c, 0x64, 0xc4, 0x86, 0xc8, 0x8b, 0xc5, 0x99, - 0xc6, 0x9a, 0xc3, 0x83, 0xc6, 0x8e, 0xc3, 0x9a, 0xc7, 0xa9, 0xc3, 0xb3, 0xe1, 0x9b, - 0x8a, 0xc7, 0x94, 0xc7, 0xbb, 0xe1, 0x9a, 0xbb, 0xc6, 0xb4, 0xc6, 0xaf, 0xe1, 0x9b, - 0xa8, 0xc2, 0xa1, 0x24, 0xe1, 0x9b, 0xab, 0xc8, 0xbb, 0xc3, 0xba, 0xe1, 0x9a, 0xb9, - 0xc8, 0x92, 0xc8, 0xb2, 0xc5, 0xa6, 0xc5, 0xb3, 0xc4, 0x8d, 0xc5, 0xad, 0xc5, 0xa0, - 0xc3, 0x9c, 0xe1, 0x9b, 0xae, 0xc7, 0xb2, 0xc4, 0x9b, 0xc6, 0xbb, 0xc5, 0xb0, 0xc7, - 0xbb, 0xc7, 0xba, 0xc5, 0xb7, 0xc8, 0xa4, 0x5a, + 0xc8, 0xa5, 0xc4, 0xb5, 0xc8, 0xb7, 0xc6, 0xa8, 0x2e, 0xc7, 0xa8, 0xc7, 0xb0, 0x52, + 0xc7, 0xac, 0xc8, 0xbf, 0x79, 0xe1, 0x9a, 0xba, 0xe1, 0x9b, 0x83, 0xc3, 0xa9, 0xc4, + 0x90, 0xc7, 0x90, 0xc3, 0x80, 0xe1, 0x9b, 0x93, 0xe1, 0x9a, 0xad, 0x58, 0xc7, 0x9b, + 0xc5, 0x85, 0x69, 0xc5, 0x90, 0xc2, 0xb8, 0xc5, 0x92, 0xc4, 0xaa, 0xc2, 0xa5, 0xc4, + 0xaa, 0xc3, 0xa9, 0xc6, 0xaa, 0xc8, 0xa1, 0xc5, 0x8b, 0xc2, 0xbf, 0xe1, 0x9b, 0xa3, + 0xcd, 0xb4, 0xc5, 0xb9, 0xc7, 0x95, 0x32, 0xc7, 0xba, 0xc5, 0x8f, 0xc2, 0xbb, 0xc3, + 0xb4, 0xe2, 0xb1, 0xb0, 0xc8, 0xb6, 0xe1, 0x9a, 0xbd, 0xc4, 0xa7, 0xc5, 0xad, 0xc4, + 0x9e, 0xe1, 0x9a, 0xb5, 0xc6, 0xae, 0xc3, 0xb9, 0xc3, 0x89, 0xc7, 0xba, 0xc3, 0x90, + 0xc7, 0xb4, 0xc3, 0xbe, 0xe2, 0xb1, 0xb7, 0xc6, 0x90, 0xc5, 0x83, 0xc8, 0xba, 0xc5, + 0x89, 0xc5, 0xa9, 0xc9, 0x86, 0x4d, 0x53, 0xcd, 0xb5, 0xc2, 0xb0, 0xc2, 0xb5, 0xc6, + 0x9b, 0x7a, 0xc4, 0x8f, 0xc3, 0x96, 0x45, 0xc3, 0xab, 0xc5, 0x8d, 0x4c, 0xc4, 0x81, + 0xe1, 0x9b, 0xad, 0xc8, 0x93, 0xe2, 0xb1, 0xbb, 0x5a, 0xc5, 0xaf, 0xc7, 0xa3, 0x71, + 0xc6, 0xa1, 0xe1, 0x9b, 0xaf, 0xc5, 0x84, 0xc6, 0x86, 0xc7, 0xa0, 0xc2, 0xae, 0xc4, + 0xac, 0xcd, 0xbb, 0xc4, 0x8e, 0xc6, 0x9c, 0xc8, 0x85, 0xc2, 0xa4, 0xc5, 0x85, 0xc8, + 0x9b, 0xc6, 0x87, 0xe1, 0x9b, 0xad, 0xc3, 0x80, 0xc4, 0xb5, 0xe2, 0xb1, 0xbb, 0xc5, + 0x9b, 0xc7, 0xb6, 0xc2, 0xb5, 0xc7, 0x8c, 0xc5, 0x86, 0xc6, 0xa8, 0xc5, 0xb7, 0xe1, + 0x9b, 0xa2, 0xc7, 0x90, 0xc2, 0xb0, 0x2e, 0xc5, 0x95, 0xe1, 0x9b, 0x82, 0xc5, 0x89, + 0xc4, 0xa3, 0xe1, 0x9b, 0x87, 0x3c, 0xc9, 0x84, 0x46, 0x2c, 0xe2, 0xb1, 0xbb, 0xe1, + 0x9b, 0x8c, 0xc3, 0xb2, 0xc6, 0xa1, 0xc6, 0x85, 0x31, 0x45, 0xe2, 0xb1, 0xa9, 0xc5, + 0x8c, 0xc6, 0x88, 0xce, 0x84, 0xc5, 0x93, 0xc5, 0xa9, 0xe1, 0x9a, 0xa7, 0xcd, 0xb6, + 0xe1, 0x9b, 0xae, 0xc8, 0xa3, 0x5f, 0xe1, 0x9b, 0x94, 0xe1, 0x9b, 0xac, 0xc5, 0xbb, + 0xc7, 0xa2, 0xc6, 0x99, 0xc7, 0xbb, 0xc5, 0xbf, 0xc4, 0x95, 0xc7, 0x94, 0xe1, 0x9a, + 0xb8, 0xe2, 0xb1, 0xaf, 0xc9, 0x8a, 0xc7, 0x9d, 0xc8, 0x88, 0x7e, 0xc9, 0x88, 0x3e, + 0x21, 0x3e, 0xc5, 0xba, 0xc4, 0x9a, 0x30, 0xc9, 0x87, 0xc5, 0x9c, 0x44, 0xc4, 0xa6, + 0xc3, 0xad, 0xc5, 0x90, 0xc4, 0xa7, 0xc7, 0x9b, 0x3c, 0x58, 0xc4, 0x89, 0xc5, 0x9e, + 0xc5, 0x93, 0xe1, 0x9a, 0xbf, 0xc8, 0xb3, 0xe1, 0x9a, 0xb3, 0xc2, 0xa2, 0xc8, 0xbc, + 0xc6, 0xa6, 0x24, 0xe1, 0x9a, 0xba, 0xc6, 0xae, 0xe1, 0x9a, 0xa0, 0x57, 0xc6, 0x9a, + 0xc2, 0xbc, 0xc8, 0xbc, 0xc2, 0xb0, 0xc3, 0xa5, 0xc5, 0x81, 0xc3, 0xba, 0xe2, 0xb1, + 0xa5, 0xc7, 0xbf, 0xc4, 0xae, 0xc8, 0xae, 0xc2, 0xa6, 0xc6, 0xad, 0xc7, 0x82, 0xc3, + 0xba, 0xc5, 0x9d, 0xc3, 0x96, 0xc7, 0x93, 0xc7, 0xb9, 0xc4, 0xa7, 0xc7, 0xba, 0xc2, + 0xb1, 0xcd, 0xb7, 0xc4, 0xa8, 0xe2, 0xb1, 0xac, 0xe1, 0x9b, 0x89, 0xe2, 0xb1, 0xbc, + 0xc6, 0xb3, 0xc8, 0x9b, 0xc8, 0xbb, 0xe1, 0x9a, 0xa1, 0xc2, 0xa1, 0xc7, 0x81, 0xc8, + 0x98, 0xc4, 0x9b, 0xe1, 0x9a, 0xb8, 0xc6, 0x9f, 0xc2, 0xa7, 0xc5, 0x85, 0xc3, 0xb8, + 0xc7, 0x97, 0xc9, 0x83, 0xc9, 0x89, 0xc7, 0x90, 0xc8, 0xbf, 0xc8, 0xaa, 0xc8, 0x8a, + 0xc6, 0x9a, 0xc5, 0x81, 0xc7, 0x9e, 0x4b, 0xc3, 0x90, 0xc6, 0xa8, 0xe1, 0x9b, 0x9c, + 0xc8, 0x94, 0xc7, 0x9c, 0xc5, 0x90, 0xc4, 0x9b, 0xe1, 0x9b, 0x9d, 0xe1, 0x9b, 0xb0, + 0xe1, 0x9a, 0xa2, 0xc6, 0xb8, 0x61, 0x5a, 0x5a, ], - asset_id: [ - 0x0f, 0x1a, 0x21, 0x20, 0x6c, 0x80, 0xdb, 0x63, 0x73, 0xde, 0x95, 0x66, 0xe9, 0x06, - 0xf1, 0x87, 0xe5, 0xea, 0x72, 0x84, 0x10, 0x86, 0x13, 0x86, 0x31, 0x77, 0x51, 0x0c, - 0xee, 0x14, 0xd7, 0xb1, + asset_base: [ + 0xed, 0x3b, 0xad, 0xc9, 0x6d, 0xc0, 0x5f, 0x5f, 0x70, 0x48, 0xcc, 0x86, 0xd9, 0xea, + 0xe7, 0x59, 0x9b, 0x57, 0xd8, 0x61, 0xbe, 0x33, 0x15, 0x4e, 0x3b, 0x88, 0xc3, 0xc6, + 0x86, 0xb2, 0x82, 0xbb, ], }, TestVector { @@ -576,48 +576,48 @@ pub(crate) fn test_vectors() -> Vec { 0xc1, 0xca, 0xcd, 0x02, ], description: [ - 0xc3, 0xa0, 0x26, 0xc8, 0xb0, 0xc3, 0x82, 0xc3, 0xb6, 0xc4, 0xa3, 0xc6, 0x85, 0xc3, - 0x8f, 0xc9, 0x8a, 0xc4, 0x99, 0xc8, 0xb8, 0xc6, 0xaa, 0xc4, 0xa4, 0xe1, 0x9b, 0x99, - 0xc6, 0x98, 0xe1, 0x9b, 0x99, 0xc6, 0x8a, 0x3c, 0xe1, 0x9b, 0x89, 0xc6, 0xa8, 0xc6, - 0xb4, 0x33, 0xe1, 0x9b, 0xa1, 0xc6, 0xb7, 0xcd, 0xb2, 0xc6, 0xbc, 0xc7, 0x86, 0xc6, - 0x9d, 0xc5, 0xac, 0xc2, 0xb7, 0xc6, 0x8a, 0xc7, 0xa5, 0xc3, 0x95, 0x35, 0xc3, 0x86, - 0x44, 0xc3, 0x89, 0xc5, 0xa1, 0xe1, 0x9b, 0xaf, 0xc6, 0xae, 0x41, 0xc4, 0x99, 0xc3, - 0xa8, 0x45, 0xe2, 0xb1, 0xb5, 0xc3, 0x83, 0x5f, 0x37, 0xc7, 0xbf, 0xe1, 0x9a, 0xa8, - 0xc7, 0x8f, 0xc5, 0x92, 0x7e, 0xc3, 0xad, 0xe2, 0xb1, 0xb9, 0xe1, 0x9a, 0xa9, 0xc6, - 0xa3, 0xc7, 0xbf, 0xcd, 0xb1, 0xc7, 0xb6, 0xe1, 0x9b, 0xa4, 0xe1, 0x9a, 0xb1, 0xe1, - 0x9a, 0xb8, 0x41, 0xc7, 0x90, 0xc5, 0x8e, 0xe1, 0x9b, 0xad, 0xc3, 0xb8, 0xc6, 0xae, - 0xc5, 0x9d, 0xc3, 0xb3, 0xc3, 0xbb, 0xc5, 0x97, 0xc7, 0x8f, 0xc8, 0xa4, 0xe1, 0x9b, - 0xb0, 0x63, 0x39, 0xe2, 0xb1, 0xa0, 0xc3, 0xbc, 0xc3, 0x97, 0xc8, 0x88, 0x5a, 0x30, - 0xc6, 0xb0, 0xe1, 0x9b, 0xa6, 0xc6, 0xbb, 0xc6, 0x86, 0xc6, 0xb8, 0xc6, 0x88, 0xe1, - 0x9a, 0xbc, 0xc5, 0xbb, 0xc5, 0xaa, 0xcd, 0xb6, 0xc6, 0xa0, 0xe2, 0xb1, 0xb7, 0xc3, - 0x8b, 0xc7, 0xa5, 0xc7, 0x9c, 0xe1, 0x9b, 0xa8, 0xe1, 0x9b, 0x82, 0xc6, 0xb4, 0xc8, - 0xa1, 0xc3, 0xb2, 0x77, 0xc3, 0xaf, 0xc2, 0xb9, 0xc6, 0x8d, 0xe2, 0xb1, 0xbf, 0xc4, - 0xb8, 0x33, 0xc3, 0xa4, 0xc8, 0xa5, 0xc7, 0xb5, 0xc7, 0x94, 0xc2, 0xaa, 0xc2, 0xbd, - 0x40, 0xe1, 0x9a, 0xba, 0xc8, 0x80, 0xc6, 0x9c, 0xc4, 0x96, 0x32, 0xe1, 0x9a, 0xb8, - 0xc3, 0xa2, 0xc7, 0xb1, 0xc4, 0x94, 0xc7, 0x88, 0xcd, 0xb4, 0xc4, 0x8d, 0x49, 0xc4, - 0xbd, 0xe1, 0x9a, 0xb4, 0xc7, 0x88, 0xe1, 0x9b, 0xac, 0xc4, 0x9a, 0xcd, 0xbe, 0xc5, - 0x96, 0xc8, 0x92, 0xe1, 0x9b, 0xaf, 0xc9, 0x89, 0xc5, 0xb5, 0x2f, 0x41, 0xcd, 0xbe, - 0xc4, 0x9d, 0xc3, 0x86, 0xc2, 0xbb, 0x25, 0xc3, 0xaa, 0xc3, 0x86, 0xc4, 0x97, 0xc8, - 0x9f, 0xcd, 0xb5, 0xc6, 0xb9, 0xc4, 0x83, 0x35, 0xe1, 0x9b, 0x9b, 0xc4, 0xa0, 0xc4, - 0x89, 0xc8, 0xa8, 0xc4, 0x84, 0xc4, 0xba, 0xc3, 0x80, 0xc4, 0xb4, 0x53, 0xc7, 0x81, - 0xc9, 0x85, 0xc6, 0xbc, 0xcd, 0xbb, 0xc6, 0xa8, 0xc5, 0x92, 0xce, 0x87, 0xe1, 0x9b, - 0x88, 0x34, 0xc8, 0xbc, 0xc6, 0xae, 0xc3, 0xbe, 0xc4, 0x9d, 0xc8, 0x81, 0xc4, 0xa4, - 0x60, 0xc7, 0x93, 0xce, 0x86, 0xc7, 0x94, 0xc7, 0x84, 0x78, 0xc8, 0x82, 0xcd, 0xb0, - 0xc6, 0xa4, 0xc6, 0x8a, 0x65, 0xc7, 0xba, 0xc6, 0xb7, 0xc4, 0xae, 0xc9, 0x82, 0xc5, - 0xaf, 0xc4, 0x84, 0xc8, 0x96, 0xc7, 0xb6, 0xc2, 0xb1, 0xc5, 0xaf, 0xc3, 0xac, 0xe1, - 0x9b, 0xa9, 0xc4, 0x87, 0x43, 0xc8, 0x84, 0xc9, 0x82, 0xc7, 0xb3, 0x6a, 0xc5, 0x89, - 0xc3, 0xb4, 0xc8, 0xa0, 0xe1, 0x9b, 0x8d, 0xc7, 0xbd, 0xc2, 0xb3, 0xc3, 0x80, 0xc6, - 0xa6, 0xc4, 0x84, 0x69, 0xc7, 0xa7, 0xc5, 0xb5, 0xc7, 0x95, 0x21, 0xc4, 0xad, 0xe1, - 0x9b, 0xaf, 0xe1, 0x9a, 0xa8, 0xc5, 0x85, 0xc7, 0xa8, 0xc9, 0x8c, 0xc5, 0x96, 0xe2, - 0xb1, 0xa1, 0x33, 0xe1, 0x9b, 0xa2, 0xc3, 0xbc, 0x2e, 0x63, 0x2b, 0xc3, 0x9f, 0x7c, - 0xc6, 0xa4, 0xc6, 0xbf, 0xc8, 0x8d, 0xc5, 0xa8, 0xc5, 0xb5, 0xc5, 0x96, 0xe1, 0x9b, - 0x98, 0xc8, 0xb3, 0xc6, 0x90, 0xc3, 0xa6, 0x3d, 0xc9, 0x8e, 0xc8, 0xb4, 0xc7, 0xbf, - 0xc2, 0xa6, 0xe1, 0x9a, 0xad, 0x41, 0x5e, 0x40, + 0x79, 0x60, 0xc6, 0xb7, 0xc3, 0x8a, 0xc7, 0xb3, 0xe2, 0xb1, 0xbd, 0xc6, 0x85, 0xc6, + 0xb3, 0xc7, 0x9d, 0xe1, 0x9a, 0xa6, 0xc7, 0xba, 0xc4, 0xb8, 0xe1, 0x9b, 0xa1, 0xc3, + 0xbe, 0xe2, 0xb1, 0xb4, 0x7c, 0xe2, 0xb1, 0xae, 0xc8, 0x90, 0xc5, 0xab, 0xc5, 0xbc, + 0x4f, 0xc5, 0xb8, 0x6c, 0x5f, 0xe1, 0x9a, 0xbf, 0xc5, 0x8a, 0xe1, 0x9b, 0xa7, 0xc8, + 0xbc, 0xc8, 0x9b, 0xc3, 0xa7, 0xc5, 0xa6, 0xc4, 0xac, 0xe2, 0xb1, 0xab, 0x38, 0xc7, + 0x99, 0x54, 0xe2, 0xb1, 0xb6, 0x50, 0xc5, 0x8c, 0xe2, 0xb1, 0xb0, 0xc5, 0xb7, 0xc5, + 0x86, 0xc5, 0xa8, 0x3e, 0xc8, 0x88, 0xc4, 0xb5, 0xc5, 0x9c, 0xc7, 0x9b, 0xe1, 0x9b, + 0x8a, 0xc3, 0x97, 0xc8, 0xba, 0xe1, 0x9a, 0xa8, 0xc6, 0xb8, 0xc2, 0xa3, 0xe1, 0x9b, + 0x82, 0xe1, 0x9b, 0xa5, 0xc2, 0xae, 0xc8, 0x94, 0xe1, 0x9b, 0xa8, 0xc6, 0xb4, 0xc8, + 0xb9, 0xc3, 0xaf, 0xc6, 0xab, 0xc3, 0x91, 0xe2, 0xb1, 0xb3, 0xc4, 0xb6, 0xc5, 0xbf, + 0xc4, 0x8d, 0x43, 0xc6, 0xa0, 0xc4, 0xb3, 0xc6, 0x98, 0xc5, 0xbc, 0xc6, 0x9a, 0xc6, + 0xb3, 0xc3, 0x91, 0xc3, 0xa2, 0xc8, 0xa7, 0xc8, 0x9c, 0xc7, 0xb4, 0x43, 0xc7, 0x82, + 0xc2, 0xbe, 0xc7, 0xbf, 0xe1, 0x9a, 0xa9, 0xc3, 0xb2, 0xc4, 0xb2, 0xc8, 0xb0, 0xc7, + 0x80, 0xc6, 0xac, 0xc3, 0xb7, 0xc5, 0x91, 0xe1, 0x9b, 0x8f, 0xc8, 0xbb, 0xc3, 0x9f, + 0xc6, 0xa5, 0x7b, 0xc3, 0xb9, 0xcd, 0xb0, 0xe1, 0x9b, 0xa2, 0xc8, 0x8f, 0xc5, 0xa9, + 0xcd, 0xbd, 0xc8, 0x90, 0xcd, 0xb3, 0xe1, 0x9b, 0xa9, 0xc8, 0x82, 0xc3, 0xb6, 0xe1, + 0x9b, 0xa9, 0xc2, 0xb4, 0xc4, 0x9f, 0xc9, 0x8e, 0xc6, 0x8a, 0x37, 0xc7, 0x93, 0xc6, + 0x96, 0xc3, 0xa8, 0xc2, 0xae, 0xce, 0x84, 0xe2, 0xb1, 0xb2, 0xc2, 0xb6, 0xc5, 0x95, + 0xe2, 0xb1, 0xba, 0xc4, 0xa2, 0xc6, 0xbb, 0xc8, 0x93, 0xc3, 0x9f, 0xc5, 0xb0, 0xc5, + 0xb8, 0xe1, 0x9b, 0x8f, 0xc7, 0xb4, 0xc7, 0xaa, 0xc2, 0xb0, 0xe1, 0x9a, 0xb3, 0x5f, + 0xc6, 0xb1, 0xc8, 0x93, 0xc4, 0xb8, 0xe1, 0x9a, 0xa0, 0xc7, 0x9f, 0xc2, 0xb6, 0xe1, + 0x9b, 0xa2, 0xc8, 0x86, 0xe1, 0x9a, 0xa6, 0xc5, 0x8d, 0xc8, 0x89, 0xe1, 0x9a, 0xa4, + 0x44, 0xc5, 0xb3, 0xc8, 0x89, 0x5d, 0xc4, 0xa8, 0xc2, 0xa1, 0xcd, 0xbc, 0xc3, 0x88, + 0xc6, 0xb2, 0xe1, 0x9b, 0xa9, 0x26, 0xc8, 0xbb, 0xc3, 0xb9, 0xe1, 0x9b, 0x99, 0xc5, + 0xb2, 0x40, 0xc3, 0x8d, 0xc9, 0x8c, 0x5e, 0xe2, 0xb1, 0xa9, 0xc7, 0x9a, 0xe1, 0x9b, + 0xa1, 0xc4, 0x9a, 0xe1, 0x9b, 0x85, 0xc9, 0x80, 0xe1, 0x9a, 0xbf, 0xc3, 0x81, 0xe1, + 0x9b, 0x8e, 0xc8, 0x92, 0xe1, 0x9a, 0xaa, 0xc6, 0xac, 0xc9, 0x8f, 0xc7, 0x88, 0x3e, + 0xc3, 0xa8, 0xc3, 0xba, 0xc8, 0x96, 0xc6, 0xa2, 0xc7, 0x9e, 0xc8, 0x81, 0xc6, 0xac, + 0xc6, 0x85, 0xc8, 0xb6, 0xc8, 0x91, 0xc7, 0x99, 0xc6, 0x89, 0xc4, 0xae, 0xe1, 0x9b, + 0x8c, 0xe1, 0x9b, 0xad, 0xe1, 0x9b, 0xae, 0xc2, 0xb3, 0xc5, 0xa3, 0xc2, 0xa8, 0xc5, + 0xbc, 0xc3, 0xa7, 0xc8, 0xb6, 0xc6, 0xb1, 0xc8, 0x9e, 0xc6, 0x87, 0xc6, 0x80, 0x61, + 0xc6, 0xb3, 0x5c, 0xe1, 0x9a, 0xb0, 0xe1, 0x9b, 0x97, 0xe2, 0xb1, 0xaa, 0x25, 0xcd, + 0xb4, 0xc7, 0x89, 0x28, 0xc6, 0x8d, 0x6e, 0x40, 0xc7, 0xb6, 0xc7, 0x9e, 0xc6, 0x93, + 0x2d, 0xc7, 0xaf, 0xc6, 0x86, 0xc6, 0xbf, 0xc6, 0x9a, 0xc7, 0x82, 0xc6, 0x8c, 0xc7, + 0xaa, 0xe2, 0xb1, 0xa4, 0xc7, 0xa9, 0x32, 0x75, 0xc8, 0x98, 0xc8, 0xb7, 0xe2, 0xb1, + 0xb5, 0xc5, 0x89, 0xc2, 0xb4, 0xc8, 0xb8, 0xc6, 0xad, 0xc4, 0x9a, 0xe2, 0xb1, 0xb3, + 0xc3, 0x84, 0xc2, 0xb0, 0xc8, 0xa4, 0xc6, 0xb3, ], - asset_id: [ - 0x8e, 0x95, 0x38, 0x48, 0xf3, 0xbd, 0xa6, 0xcd, 0xc0, 0x11, 0xdf, 0xd6, 0xe0, 0x1e, - 0x9f, 0x45, 0x71, 0xf9, 0x2c, 0xa1, 0x29, 0x4f, 0xd2, 0x69, 0xff, 0x98, 0x2b, 0xd2, - 0x1a, 0xac, 0xa0, 0xbc, + asset_base: [ + 0xb2, 0xd8, 0x44, 0xfe, 0xe4, 0x40, 0xbd, 0x64, 0x96, 0xd3, 0x1d, 0x5e, 0xdb, 0xee, + 0x95, 0x62, 0x3d, 0x19, 0x0e, 0xb3, 0x48, 0x4c, 0x48, 0x71, 0x0c, 0x76, 0x2f, 0x21, + 0x5b, 0x68, 0x4d, 0xbf, ], }, TestVector { @@ -627,48 +627,48 @@ pub(crate) fn test_vectors() -> Vec { 0x5b, 0xc5, 0xa8, 0x27, ], description: [ - 0xe1, 0x9b, 0x96, 0xe1, 0x9a, 0xb1, 0xc7, 0xb2, 0xc4, 0xb1, 0xc9, 0x81, 0xc2, 0xbe, - 0xc6, 0x84, 0xc4, 0x91, 0xc7, 0xb1, 0xc5, 0x83, 0xc2, 0xa3, 0xce, 0x8c, 0xce, 0x8c, - 0xc8, 0x8d, 0xc5, 0xaa, 0xc7, 0xa1, 0xe1, 0x9b, 0x9f, 0xc8, 0x8a, 0xc6, 0xbc, 0xc8, - 0xa3, 0xc8, 0xa8, 0xe1, 0x9b, 0x9b, 0xc8, 0xba, 0xc3, 0x88, 0xc7, 0x9f, 0x34, 0xc6, - 0xb9, 0xc2, 0xb9, 0xe1, 0x9a, 0xac, 0xc9, 0x88, 0xc5, 0x84, 0xc6, 0xa1, 0xe2, 0xb1, - 0xb6, 0xc2, 0xa8, 0xc6, 0xb4, 0xc7, 0xb3, 0x5a, 0x3d, 0xc7, 0xa1, 0xc8, 0x80, 0xc3, - 0x92, 0xc7, 0xa2, 0xc7, 0x93, 0xc7, 0xbb, 0xc8, 0xae, 0xc4, 0xb2, 0xc9, 0x83, 0xc6, - 0x88, 0xe2, 0xb1, 0xa2, 0xc8, 0x95, 0xc2, 0xb4, 0xc4, 0x86, 0xc5, 0xa5, 0x47, 0x70, - 0xe2, 0xb1, 0xb1, 0x62, 0xc3, 0x96, 0x5a, 0xe1, 0x9b, 0x97, 0xc5, 0x99, 0xc6, 0xb7, - 0xc3, 0xaa, 0xc5, 0x9d, 0xc7, 0x85, 0xc2, 0xa1, 0xc4, 0x93, 0xe1, 0x9a, 0xb8, 0xc3, - 0x8b, 0xe1, 0x9a, 0xad, 0xc7, 0xb3, 0xc7, 0x9a, 0xc7, 0xac, 0xe2, 0xb1, 0xaa, 0xc7, - 0xac, 0xc6, 0x91, 0xc2, 0xa9, 0xc5, 0xba, 0xc5, 0xa7, 0xc7, 0x9f, 0xc3, 0xad, 0xc8, - 0x81, 0xc8, 0x88, 0xc4, 0x86, 0xc9, 0x8d, 0xe1, 0x9b, 0xaf, 0xe1, 0x9b, 0xa1, 0xe2, - 0xb1, 0xb6, 0xc8, 0x8a, 0xc8, 0xa4, 0xc2, 0xaa, 0xe1, 0x9b, 0x9e, 0xc5, 0xa2, 0xc7, - 0x98, 0xc6, 0x93, 0xc4, 0xa8, 0xe1, 0x9b, 0x80, 0x2c, 0xc3, 0x8e, 0x25, 0x51, 0xe2, - 0xb1, 0xa7, 0xc8, 0xb3, 0xc3, 0xa4, 0xcd, 0xb6, 0xe2, 0xb1, 0xae, 0xc5, 0xb0, 0xe2, - 0xb1, 0xaa, 0xc7, 0xae, 0xc7, 0x8f, 0xc7, 0x9b, 0xc8, 0xa5, 0xc6, 0x9f, 0xc8, 0x8e, - 0x2e, 0x5a, 0xe1, 0x9a, 0xb9, 0xc2, 0xba, 0xc7, 0x8f, 0xc6, 0x90, 0xe1, 0x9a, 0xa9, - 0xc4, 0x85, 0xe1, 0x9b, 0x9f, 0x45, 0x3c, 0xc4, 0xbf, 0xc2, 0xa6, 0xc7, 0x9d, 0xe2, - 0xb1, 0xa8, 0xc7, 0x97, 0xc2, 0xbd, 0xc6, 0x8d, 0xcd, 0xb0, 0xc9, 0x83, 0x4a, 0xc8, - 0x80, 0xce, 0x89, 0xc9, 0x8f, 0xc3, 0xbb, 0xc4, 0xa7, 0xc7, 0x8c, 0x39, 0x7e, 0xc7, - 0x8f, 0xc5, 0xaa, 0x5a, 0xc3, 0x88, 0xc8, 0x93, 0xe1, 0x9b, 0xa6, 0xc5, 0x9e, 0xc8, - 0xaa, 0xc5, 0x90, 0x2e, 0xc8, 0xac, 0xe2, 0xb1, 0xb8, 0x7d, 0xc5, 0x9d, 0xc6, 0xaf, - 0xc8, 0x9d, 0xcd, 0xbe, 0xe2, 0xb1, 0xac, 0xc2, 0xbd, 0xc6, 0x9a, 0xc8, 0xb0, 0xe2, - 0xb1, 0xbc, 0xe1, 0x9b, 0x83, 0x29, 0x44, 0xe1, 0x9b, 0x9d, 0xc4, 0x87, 0xc6, 0x99, - 0xc7, 0xb6, 0xe1, 0x9b, 0x90, 0xcd, 0xb5, 0x3b, 0xc8, 0x92, 0xc6, 0x80, 0xc8, 0xa7, - 0xc9, 0x8e, 0xc2, 0xa8, 0xc7, 0x8b, 0xc2, 0xb1, 0xc5, 0xb4, 0xe2, 0xb1, 0xbf, 0xe1, - 0x9b, 0x86, 0xe1, 0x9a, 0xb8, 0x46, 0xe1, 0x9b, 0x81, 0x55, 0xc7, 0xa2, 0x26, 0xc5, - 0x99, 0x37, 0xe1, 0x9a, 0xa5, 0xc3, 0x93, 0xc7, 0x94, 0x6f, 0xe2, 0xb1, 0xba, 0xc7, - 0x86, 0xc2, 0xa9, 0xc5, 0x87, 0xc6, 0x9e, 0xc3, 0xae, 0xc8, 0xa7, 0xc3, 0x8c, 0x30, - 0xc7, 0x82, 0xc7, 0xaf, 0xc5, 0xa6, 0x77, 0xe1, 0x9b, 0x80, 0x5c, 0xcd, 0xbd, 0xc2, - 0xb5, 0xc7, 0x8f, 0x3c, 0xc3, 0x97, 0xc2, 0xb3, 0x58, 0xc6, 0x84, 0xc7, 0x86, 0xc6, - 0xaa, 0x61, 0xc5, 0x8c, 0xc5, 0xa1, 0xe2, 0xb1, 0xbf, 0xe1, 0x9b, 0xb0, 0xc3, 0x96, - 0xc8, 0x9e, 0xc8, 0xbb, 0xe1, 0x9a, 0xa0, 0xc6, 0x9d, 0xc4, 0xb3, 0xc8, 0x91, 0xc8, - 0xb2, 0xc8, 0xa5, 0xc8, 0x81, 0xc5, 0x80, 0xc8, 0x93, 0x62, 0x30, 0xe1, 0x9b, 0xa6, - 0xc5, 0x93, 0xc6, 0x81, 0xe1, 0x9a, 0xb3, 0x72, 0xc8, 0xa8, 0xc5, 0x90, 0xc8, 0x85, - 0xc3, 0x81, 0xc4, 0x97, 0xe1, 0x9b, 0x92, 0x5a, + 0xc7, 0x96, 0xc8, 0xad, 0xc4, 0xbd, 0xe1, 0x9b, 0x9b, 0xe1, 0x9b, 0x96, 0xe2, 0xb1, + 0xb2, 0xc3, 0x8f, 0xe1, 0x9b, 0x91, 0xc5, 0x85, 0xe1, 0x9a, 0xa2, 0xc4, 0xba, 0xc3, + 0xa8, 0xc3, 0xaa, 0xc3, 0xa9, 0xc8, 0x93, 0xc8, 0x9b, 0xc8, 0x80, 0xc4, 0xa5, 0xc5, + 0xa9, 0xc4, 0x90, 0x6f, 0xc2, 0xaf, 0xc3, 0x95, 0xc6, 0xa6, 0xc8, 0x86, 0xe1, 0x9a, + 0xbd, 0xc8, 0x87, 0xc7, 0x97, 0xc6, 0xaa, 0x79, 0x52, 0xc7, 0x89, 0xc2, 0xa1, 0xc4, + 0xa7, 0xc9, 0x8d, 0x53, 0xc8, 0x89, 0xc7, 0xa4, 0xe1, 0x9b, 0x84, 0xc5, 0xac, 0x79, + 0xc8, 0xbc, 0xc4, 0xb0, 0xc6, 0xa9, 0xe1, 0x9a, 0xa4, 0xe2, 0xb1, 0xb6, 0xc7, 0x86, + 0xc4, 0x9b, 0x72, 0xc7, 0x88, 0xc2, 0xbc, 0xe1, 0x9a, 0xa4, 0xcd, 0xb0, 0xc6, 0xb7, + 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xb8, 0xc5, 0x89, 0xc9, 0x84, 0x35, 0xc3, 0xa3, 0xe1, + 0x9b, 0x90, 0xc7, 0x9c, 0x31, 0xc5, 0x9a, 0xc5, 0xa9, 0xc8, 0x88, 0xce, 0x8c, 0xc4, + 0x88, 0xc4, 0x95, 0xc8, 0xaa, 0x69, 0x46, 0xc8, 0x8d, 0xc5, 0xb9, 0xcd, 0xb0, 0xe1, + 0x9a, 0xb7, 0xc8, 0x83, 0xc4, 0x99, 0xe1, 0x9b, 0x81, 0xc4, 0x90, 0xc2, 0xb3, 0xc3, + 0x9b, 0x37, 0xc7, 0x95, 0xc3, 0x86, 0xe1, 0x9a, 0xbc, 0xc3, 0xba, 0xe2, 0xb1, 0xa5, + 0xc8, 0xac, 0x51, 0xc6, 0xa4, 0xc4, 0xb4, 0x21, 0xc5, 0x94, 0xc5, 0x92, 0xc4, 0xa3, + 0xc6, 0x8c, 0xc8, 0x84, 0xc8, 0xa9, 0xc3, 0x81, 0xc5, 0xb2, 0x53, 0xc7, 0x8a, 0xe1, + 0x9a, 0xba, 0xc4, 0xb7, 0xc8, 0x9e, 0xc3, 0xb6, 0xc7, 0xb1, 0xe2, 0xb1, 0xad, 0xc7, + 0x80, 0xc7, 0xb7, 0x51, 0xce, 0x85, 0xc4, 0xab, 0xc7, 0xaa, 0xc3, 0xad, 0xc5, 0x97, + 0xc8, 0xbe, 0x2e, 0x36, 0x71, 0xe1, 0x9b, 0x8a, 0xc5, 0xb1, 0xc4, 0x9b, 0xe1, 0x9b, + 0x8a, 0xc5, 0xb7, 0xc5, 0xb9, 0xc3, 0xbe, 0xc7, 0x80, 0xc3, 0xad, 0xc8, 0x80, 0xe1, + 0x9b, 0x9d, 0xc5, 0xb2, 0xc6, 0xaa, 0xc8, 0xa6, 0xc5, 0x93, 0xc6, 0xb2, 0xe1, 0x9a, + 0xb0, 0xc5, 0x86, 0xc5, 0xa2, 0xe1, 0x9a, 0xaf, 0x77, 0xc4, 0xb1, 0xe1, 0x9a, 0xa0, + 0xc4, 0x91, 0xc8, 0xb9, 0x21, 0xc3, 0x9a, 0xc6, 0x88, 0xc3, 0x80, 0xc4, 0x80, 0xc4, + 0x83, 0xc7, 0x81, 0x24, 0xc3, 0xa5, 0xc6, 0xbf, 0xc7, 0xb1, 0xe1, 0x9b, 0x98, 0xc8, + 0xaf, 0xc5, 0x9a, 0xc7, 0xa1, 0xc4, 0x89, 0x4f, 0xc2, 0xaf, 0xc9, 0x8c, 0x2f, 0xc4, + 0x94, 0x74, 0xc5, 0xb8, 0x26, 0xe1, 0x9b, 0x85, 0xc6, 0x97, 0xc2, 0xa3, 0xc5, 0xb4, + 0xc7, 0xbe, 0xc6, 0xa3, 0xc4, 0x9b, 0xe1, 0x9b, 0xa2, 0xc8, 0xb9, 0x7d, 0xc8, 0xa2, + 0xc7, 0x8a, 0xe2, 0xb1, 0xaa, 0xc3, 0x92, 0x5b, 0xc3, 0xaa, 0xc8, 0xa4, 0xc7, 0xad, + 0xc4, 0x91, 0xc8, 0xad, 0xc8, 0x8a, 0xc4, 0x89, 0x3e, 0xc5, 0xba, 0x58, 0xc4, 0xb7, + 0xc5, 0x82, 0xe1, 0x9b, 0x82, 0x51, 0xc5, 0xa5, 0xc3, 0x96, 0xc2, 0xb1, 0xc2, 0xa4, + 0xc8, 0x8f, 0xc3, 0xac, 0xc6, 0x91, 0xe1, 0x9b, 0xa3, 0xc8, 0xba, 0xc4, 0x82, 0x21, + 0xc6, 0xb3, 0xc7, 0xb1, 0xc3, 0x92, 0x2f, 0xc4, 0x9a, 0xc7, 0x86, 0xc4, 0x82, 0x7c, + 0x2e, 0xc8, 0xb6, 0xe1, 0x9b, 0x8a, 0x2f, 0x34, 0xc4, 0xaf, 0xc7, 0xb8, 0xc9, 0x8b, + 0xc6, 0xb6, 0xe1, 0x9b, 0x91, 0xc7, 0xb2, 0xc5, 0x87, 0xce, 0x85, 0xc4, 0x8b, 0xc7, + 0x88, 0xc5, 0xb7, 0xc8, 0x9c, 0xc6, 0xbb, 0xc4, 0x9e, 0xc4, 0xb2, 0xc4, 0xa8, 0xe1, + 0x9b, 0x83, 0xc7, 0x91, 0xc8, 0x82, 0xc8, 0xb6, 0xc5, 0x8e, 0xe1, 0x9b, 0xaf, 0xc7, + 0x89, 0xc4, 0x98, 0xc7, 0x90, 0xc2, 0xb8, 0xc8, 0xa2, 0xc8, 0xbf, 0xc5, 0xb8, 0x6e, + 0xc2, 0xbc, 0xc3, 0xb0, 0xc3, 0xa0, 0xc6, 0xb6, ], - asset_id: [ - 0x08, 0xfe, 0xbb, 0x02, 0x39, 0x9f, 0x3d, 0x81, 0x83, 0x8b, 0x51, 0xbf, 0x9a, 0xb5, - 0x35, 0xe9, 0x5b, 0xba, 0x0f, 0x19, 0x9a, 0xda, 0x1c, 0x26, 0x65, 0xd4, 0x39, 0x4e, - 0xa0, 0xb2, 0xa7, 0x02, + asset_base: [ + 0xee, 0xb5, 0xc9, 0x51, 0xcd, 0x1c, 0x9b, 0x20, 0x4f, 0x65, 0xe6, 0xf2, 0xb9, 0xeb, + 0xa1, 0xd2, 0x16, 0x1e, 0x21, 0x2b, 0x6f, 0x8e, 0x1c, 0x37, 0x96, 0x22, 0xbb, 0x7c, + 0x44, 0xb8, 0x8e, 0xa7, ], }, TestVector { @@ -678,48 +678,48 @@ pub(crate) fn test_vectors() -> Vec { 0x8c, 0x10, 0x44, 0x20, ], description: [ - 0xc3, 0x92, 0xe1, 0x9b, 0x95, 0xe1, 0x9a, 0xbf, 0xc4, 0xbc, 0x42, 0xc3, 0x88, 0xc7, - 0xb1, 0x42, 0xc8, 0xb4, 0xc4, 0x8b, 0xc4, 0xa9, 0xc4, 0xbe, 0xc2, 0xa4, 0xc2, 0xa3, - 0xc8, 0xaf, 0xc4, 0x87, 0xc4, 0xaa, 0xc3, 0x94, 0xcd, 0xb0, 0xc8, 0x87, 0xc5, 0xaa, - 0x3d, 0xc2, 0xbb, 0xc7, 0x9c, 0xc3, 0xb1, 0xc2, 0xb9, 0xc8, 0x94, 0xc4, 0x93, 0x5e, - 0xe1, 0x9b, 0xa1, 0xc8, 0x91, 0xc7, 0xb7, 0x41, 0x46, 0x44, 0xc4, 0xac, 0xc6, 0x83, - 0xc5, 0xbe, 0xc3, 0xa7, 0xc8, 0x9a, 0xe1, 0x9b, 0x86, 0xc3, 0xa5, 0xc3, 0x9f, 0xc6, - 0xb5, 0xe1, 0x9b, 0xa8, 0xe2, 0xb1, 0xbc, 0xc6, 0xaa, 0xe1, 0x9a, 0xa1, 0xc3, 0x81, - 0xce, 0x87, 0xc3, 0x8c, 0xc6, 0xa0, 0xe1, 0x9a, 0xa7, 0x38, 0xc4, 0x98, 0xc4, 0x99, - 0xc2, 0xbd, 0xc3, 0xa4, 0xc3, 0xab, 0xc4, 0xa7, 0xe1, 0x9a, 0xa3, 0xcd, 0xb4, 0x7b, - 0xe1, 0x9a, 0xb7, 0xc4, 0xbb, 0xe2, 0xb1, 0xb3, 0xe2, 0xb1, 0xa7, 0xc6, 0x97, 0xc3, - 0x9f, 0xc3, 0x91, 0xce, 0x8c, 0xc3, 0x84, 0xc7, 0xac, 0xcd, 0xb1, 0xe2, 0xb1, 0xb9, - 0xe2, 0xb1, 0xac, 0xc9, 0x87, 0xc3, 0x9a, 0xc7, 0xb9, 0xc5, 0x96, 0xc7, 0x8e, 0xc4, - 0x8e, 0xc7, 0xbb, 0xc4, 0x9b, 0xe1, 0x9b, 0x9c, 0xc4, 0xad, 0xc7, 0x81, 0xc4, 0xa4, - 0x39, 0xc6, 0x81, 0xc6, 0x89, 0xc7, 0xa9, 0xc2, 0xa3, 0xe2, 0xb1, 0xac, 0xc9, 0x80, - 0x51, 0xcd, 0xbd, 0xc6, 0xb8, 0xc9, 0x81, 0xc5, 0x93, 0xc8, 0xa0, 0x5d, 0xc4, 0x9c, - 0xc6, 0x90, 0x35, 0xc4, 0xb7, 0xc8, 0x9a, 0xc5, 0x90, 0xc8, 0x94, 0xc8, 0x95, 0xc8, - 0x92, 0xc9, 0x8c, 0xc4, 0xb5, 0x49, 0xc6, 0xbe, 0xc9, 0x84, 0xc2, 0xbf, 0xc6, 0xbb, - 0xc2, 0xab, 0xe1, 0x9b, 0xac, 0xc6, 0x87, 0x6a, 0xc6, 0xbc, 0xc4, 0xae, 0xe1, 0x9b, - 0x81, 0xc4, 0xb3, 0xe2, 0xb1, 0xb4, 0xc3, 0x96, 0x2f, 0xc4, 0x94, 0xc7, 0x8c, 0xc3, - 0xb2, 0xc2, 0xab, 0xc5, 0x80, 0xc5, 0xac, 0xe2, 0xb1, 0xad, 0xc4, 0x9c, 0xc4, 0xae, - 0xc7, 0xb7, 0x7d, 0xe1, 0x9b, 0x9d, 0xe1, 0x9a, 0xbd, 0xc4, 0xb3, 0xcd, 0xb3, 0xc2, - 0xa6, 0xe1, 0x9a, 0xbc, 0x33, 0xe2, 0xb1, 0xb8, 0xc7, 0xa8, 0xe1, 0x9a, 0xa1, 0xe1, - 0x9b, 0xad, 0xc5, 0xac, 0xce, 0x8a, 0xc4, 0x94, 0xc3, 0x80, 0xc7, 0xb4, 0xc7, 0xa9, - 0xc9, 0x84, 0xc2, 0xb1, 0xc5, 0x9c, 0xc7, 0x88, 0xe2, 0xb1, 0xb6, 0xcd, 0xb0, 0xc5, - 0x93, 0xc2, 0xb7, 0xe1, 0x9b, 0x8e, 0xe1, 0x9a, 0xa4, 0xc4, 0x87, 0xc4, 0x8c, 0xc6, - 0x92, 0xc3, 0xa9, 0xc5, 0xa7, 0xc7, 0x96, 0xc3, 0xbd, 0xc4, 0x83, 0xc3, 0xb4, 0x44, - 0xc3, 0x96, 0xc2, 0xb3, 0x7b, 0xe1, 0x9b, 0x8d, 0xc6, 0x86, 0xc6, 0x89, 0x61, 0xc7, - 0x90, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x94, 0xc6, 0xb5, 0xc7, 0xae, 0xe1, 0x9b, 0x8f, - 0xc7, 0xa6, 0xc8, 0xac, 0xc5, 0x92, 0xc5, 0xb3, 0xc5, 0xb3, 0xc8, 0x92, 0xc3, 0x8e, - 0xc4, 0x93, 0xc3, 0xb0, 0xc4, 0x9b, 0xc4, 0x8c, 0xc3, 0x83, 0xce, 0x89, 0xc6, 0x9b, - 0x79, 0xc2, 0xa5, 0xc7, 0xa9, 0xc4, 0xa3, 0xc2, 0xa2, 0xc3, 0x90, 0xc6, 0x9e, 0xc6, - 0x9d, 0xe1, 0x9a, 0xbb, 0xc4, 0x8c, 0xc5, 0xa8, 0xc8, 0xb2, 0xc3, 0xac, 0x5e, 0xc8, - 0xb2, 0x38, 0xc7, 0xa0, 0xc4, 0x9e, 0xc5, 0x8f, 0xc6, 0xa9, 0xe1, 0x9a, 0xb1, 0xe1, - 0x9b, 0x84, 0xcd, 0xbe, 0x61, 0xc7, 0x87, 0xce, 0x85, 0xc4, 0x89, 0xc8, 0x96, 0xc8, - 0xa3, 0xc8, 0x96, 0xc3, 0xab, 0xc6, 0xae, 0xce, 0x88, 0xe1, 0x9a, 0xbf, 0xc5, 0x91, - 0xe1, 0x9b, 0xab, 0xc7, 0x96, 0x33, 0xc3, 0xab, 0xe2, 0xb1, 0xb9, 0xe2, 0xb1, 0xac, - 0xe2, 0xb1, 0xbb, 0xe2, 0xb1, 0xae, 0xc2, 0xbf, + 0xc3, 0x82, 0xc9, 0x85, 0xc3, 0xa9, 0xc7, 0xac, 0xc3, 0x93, 0xe1, 0x9b, 0xa7, 0xe1, + 0x9b, 0x81, 0xc8, 0xb5, 0x26, 0xe2, 0xb1, 0xbf, 0xc3, 0x96, 0xc4, 0xa2, 0xc5, 0x8c, + 0x4c, 0xc7, 0xbe, 0xce, 0x89, 0xc8, 0xa0, 0xc5, 0xb7, 0xc5, 0x92, 0xc7, 0xa6, 0xc4, + 0x8f, 0xc8, 0x84, 0x2f, 0xe2, 0xb1, 0xad, 0xc3, 0xab, 0xc6, 0xbc, 0xe1, 0x9a, 0xa8, + 0xc2, 0xb9, 0x72, 0x6b, 0xc3, 0xa9, 0xc3, 0xa3, 0xc9, 0x87, 0xc4, 0xb8, 0xc6, 0xbc, + 0xc8, 0xb8, 0xc6, 0x80, 0xe1, 0x9a, 0xbc, 0xc6, 0xb7, 0xc3, 0x9c, 0x3e, 0xc8, 0x8f, + 0xe1, 0x9b, 0x92, 0xc7, 0x88, 0x33, 0xc6, 0xab, 0xc8, 0x80, 0xc8, 0x9e, 0xe2, 0xb1, + 0xa2, 0x29, 0xc3, 0x9d, 0xc6, 0x82, 0xc3, 0xad, 0xc8, 0xa1, 0xe1, 0x9b, 0x99, 0xc4, + 0xad, 0xc9, 0x8c, 0xc7, 0xa8, 0xc8, 0x89, 0xc4, 0x90, 0xe1, 0x9b, 0xa0, 0xc4, 0xae, + 0xc6, 0xb5, 0xc7, 0x92, 0xc6, 0xbc, 0xc8, 0xa1, 0xc3, 0xac, 0xc3, 0x83, 0xe1, 0x9b, + 0x83, 0xc3, 0xb9, 0xc3, 0x9d, 0xc5, 0xa8, 0xe2, 0xb1, 0xbb, 0xc8, 0x9f, 0xc4, 0xb0, + 0xe2, 0xb1, 0xa3, 0xc7, 0xa8, 0xc4, 0x82, 0xc7, 0x87, 0xe1, 0x9b, 0x9e, 0xc8, 0x81, + 0xc3, 0xb7, 0xc5, 0x95, 0x34, 0xc6, 0xb8, 0xc5, 0xbd, 0xc4, 0x82, 0xc6, 0x92, 0xc4, + 0x9f, 0xc5, 0x9d, 0xc8, 0x9a, 0xc4, 0x89, 0xc3, 0x81, 0xc5, 0x8d, 0xe1, 0x9b, 0x85, + 0xc8, 0x84, 0xcd, 0xbe, 0xc6, 0xb5, 0xc7, 0xb5, 0xc4, 0xbe, 0x4d, 0xc6, 0x8c, 0xc6, + 0x83, 0xc6, 0x99, 0xc7, 0xa3, 0xc4, 0xae, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x86, 0xe1, + 0x9a, 0xa1, 0xc6, 0x84, 0xc3, 0xb0, 0xc9, 0x8b, 0xcd, 0xb0, 0xc7, 0x8c, 0xc6, 0xb4, + 0xc5, 0x82, 0xe2, 0xb1, 0xba, 0xc2, 0xbb, 0xc4, 0xbd, 0xc2, 0xaf, 0xc6, 0xba, 0x7b, + 0xc4, 0x89, 0x25, 0xe1, 0x9b, 0xae, 0xc7, 0x9d, 0xe1, 0x9b, 0x8b, 0xe2, 0xb1, 0xb8, + 0xe2, 0xb1, 0xa5, 0xc3, 0xb4, 0xc8, 0xb2, 0xc5, 0x9f, 0xc8, 0x9c, 0xc3, 0xa7, 0x38, + 0xc7, 0x8e, 0xc7, 0x92, 0xc6, 0xa8, 0xc6, 0x88, 0xe2, 0xb1, 0xa2, 0xc5, 0xb1, 0x39, + 0x6b, 0x4c, 0xe1, 0x9b, 0x86, 0xe1, 0x9a, 0xa8, 0xc2, 0xa6, 0xc5, 0xbf, 0xc5, 0xb5, + 0xc4, 0xaa, 0xe2, 0xb1, 0xa2, 0x3b, 0xc8, 0x98, 0xc9, 0x8f, 0xc4, 0x83, 0xc8, 0x91, + 0xc7, 0x8e, 0xe2, 0xb1, 0xab, 0xc8, 0x94, 0xc6, 0xb3, 0xc3, 0x93, 0xc3, 0x92, 0x3d, + 0xc4, 0x86, 0xc6, 0x88, 0xc4, 0xa3, 0xc5, 0x98, 0xc8, 0xb9, 0xc8, 0xb5, 0x26, 0xc4, + 0xb9, 0xc3, 0x90, 0xc5, 0xa7, 0xc6, 0xa6, 0xe2, 0xb1, 0xba, 0xc2, 0xb8, 0xc5, 0x93, + 0xce, 0x89, 0xc3, 0xa0, 0xc3, 0x8e, 0xe1, 0x9b, 0x81, 0xc2, 0xbb, 0xc7, 0xba, 0xc4, + 0x83, 0xc9, 0x83, 0xc5, 0xa8, 0xc4, 0x84, 0xc3, 0xb5, 0xc3, 0xad, 0x5d, 0xc4, 0x9b, + 0xc7, 0xbb, 0xe2, 0xb1, 0xb4, 0xc4, 0xb5, 0xc4, 0x8c, 0xc3, 0x8a, 0xc6, 0xb2, 0xe2, + 0xb1, 0xa5, 0xc6, 0xb1, 0xc4, 0xa7, 0xc3, 0xb3, 0xe1, 0x9b, 0xa6, 0xc7, 0x9d, 0xc4, + 0xb3, 0xc3, 0xbd, 0x3b, 0xe1, 0x9b, 0xa5, 0x3e, 0xc3, 0xbe, 0xc7, 0x87, 0xc3, 0xa4, + 0xc6, 0xbb, 0xe1, 0x9b, 0xad, 0xe2, 0xb1, 0xa4, 0xce, 0x89, 0xc8, 0xa2, 0xc8, 0x84, + 0x7a, 0xc8, 0x84, 0xc4, 0xb5, 0xc4, 0xbb, 0xc5, 0xa2, 0xc7, 0xaf, 0x49, 0xe1, 0x9b, + 0xb0, 0xc8, 0xab, 0xc6, 0xa7, 0xc7, 0xa4, 0xe2, 0xb1, 0xbd, 0xc4, 0x8f, 0xc6, 0x96, + 0xe1, 0x9b, 0x86, 0xc6, 0x9f, 0xc3, 0x83, 0xc4, 0x8b, 0x2b, 0xe1, 0x9a, 0xa9, 0x38, + 0xe2, 0xb1, 0xbc, 0xc3, 0x8c, 0xc8, 0x94, 0xcd, 0xb0, 0xc3, 0xb5, 0xc7, 0x82, 0x36, + 0x23, 0x41, 0xe2, 0xb1, 0xa8, 0x67, 0x5a, 0x5a, ], - asset_id: [ - 0xda, 0x5b, 0xdf, 0x78, 0xe8, 0x94, 0xa9, 0x67, 0xb8, 0x2b, 0xfe, 0xc3, 0x50, 0x04, - 0x41, 0x5e, 0xe1, 0xc8, 0xc3, 0xf2, 0x66, 0x22, 0xa2, 0xc2, 0x0c, 0xf5, 0x13, 0x9b, - 0x79, 0xf1, 0x08, 0xba, + asset_base: [ + 0x65, 0x3e, 0x99, 0x25, 0x68, 0x30, 0x69, 0xc9, 0x88, 0x32, 0xaf, 0x7d, 0x3a, 0xa9, + 0xd3, 0x14, 0x41, 0xcc, 0x0f, 0x76, 0x34, 0x07, 0x91, 0x49, 0xf3, 0xef, 0xcb, 0x64, + 0xc7, 0x36, 0x97, 0x3d, ], }, TestVector { @@ -729,48 +729,48 @@ pub(crate) fn test_vectors() -> Vec { 0x19, 0x68, 0x73, 0x26, ], description: [ - 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xb3, 0xc4, 0x8f, 0xe1, 0x9b, 0x97, 0x23, 0xe1, 0x9b, - 0xaf, 0x70, 0xc6, 0x9f, 0xc8, 0x82, 0xc4, 0x9c, 0xc7, 0x96, 0xc5, 0x81, 0xc3, 0x90, - 0xc5, 0xaf, 0xc6, 0x81, 0x33, 0xc8, 0xb2, 0x46, 0xc8, 0xba, 0x65, 0xcd, 0xb6, 0xe2, - 0xb1, 0xb7, 0xc8, 0xae, 0x5a, 0xc3, 0x87, 0xc6, 0xb3, 0xc6, 0x9f, 0x3d, 0xc3, 0x8a, - 0xc2, 0xb2, 0xc6, 0xab, 0xe1, 0x9b, 0x90, 0xc8, 0xbb, 0xe2, 0xb1, 0xab, 0xc3, 0x9f, - 0xc7, 0xb9, 0x67, 0xe2, 0xb1, 0xba, 0xe1, 0x9b, 0x88, 0xc4, 0x91, 0xc5, 0x9a, 0xe1, - 0x9b, 0x86, 0xe2, 0xb1, 0xbf, 0xc5, 0x9c, 0xc5, 0xad, 0x7d, 0xe2, 0xb1, 0xb1, 0xc4, - 0x9e, 0xc6, 0x90, 0xc5, 0x8b, 0xc4, 0xa3, 0xc5, 0x8c, 0xc3, 0xaf, 0xc4, 0x90, 0xc4, - 0xb2, 0x76, 0xc8, 0xbe, 0x33, 0xc9, 0x85, 0xc5, 0x80, 0xc7, 0x98, 0x6b, 0xe1, 0x9a, - 0xa8, 0x5e, 0xc4, 0xa3, 0xe1, 0x9b, 0x9c, 0xc7, 0x87, 0xc4, 0xbd, 0xce, 0x89, 0xc8, - 0xb4, 0x50, 0x3d, 0xc7, 0xa7, 0xc6, 0x97, 0xe1, 0x9b, 0xac, 0xc3, 0xb4, 0xe2, 0xb1, - 0xbc, 0xc6, 0x9f, 0xc4, 0xb5, 0xc5, 0xb7, 0xe1, 0x9a, 0xac, 0xc7, 0xa1, 0xe1, 0x9a, - 0xbe, 0xe2, 0xb1, 0xbb, 0xc6, 0x94, 0xc7, 0x90, 0xe1, 0x9b, 0x82, 0xe1, 0x9b, 0x80, - 0xc6, 0x98, 0xc4, 0x9f, 0xc7, 0xac, 0xc6, 0xab, 0xc5, 0xb2, 0x48, 0x6e, 0xc2, 0xa5, - 0xc4, 0x8c, 0xc9, 0x83, 0xc9, 0x86, 0x73, 0x29, 0x6b, 0xc3, 0xbd, 0xc2, 0xbf, 0xc4, - 0x9b, 0xe1, 0x9a, 0xbf, 0xc7, 0xbe, 0xe1, 0x9b, 0x83, 0xe2, 0xb1, 0xab, 0xc7, 0x8d, - 0xe2, 0xb1, 0xa2, 0x57, 0xc5, 0x84, 0xc6, 0xbc, 0xe1, 0x9b, 0xaf, 0xc5, 0xa3, 0xc8, - 0x8f, 0x25, 0xe2, 0xb1, 0xa3, 0x6d, 0x35, 0xc8, 0xae, 0x34, 0xe2, 0xb1, 0xb9, 0xe2, - 0xb1, 0xad, 0xc3, 0xb6, 0x71, 0xce, 0x84, 0xc8, 0x92, 0xc5, 0xa7, 0xc6, 0xb9, 0xce, - 0x87, 0xc4, 0xb8, 0xe1, 0x9b, 0xa8, 0xe1, 0x9b, 0x89, 0x76, 0xc4, 0xaf, 0xc4, 0x85, - 0xc2, 0xac, 0xc4, 0xbd, 0x7c, 0xc4, 0xba, 0xc4, 0x80, 0xc4, 0xa0, 0xc9, 0x82, 0xc3, - 0xb3, 0xe1, 0x9b, 0x9e, 0xc2, 0xaf, 0xc3, 0x86, 0x7e, 0xc6, 0xa0, 0xc4, 0x8d, 0xc6, - 0x8a, 0xc2, 0xba, 0xc4, 0xbd, 0xe1, 0x9b, 0x84, 0x75, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, - 0xbe, 0xc7, 0xa1, 0xc7, 0x90, 0xcd, 0xbb, 0x29, 0xc5, 0xa4, 0xc4, 0xb8, 0xc4, 0xbd, - 0xc9, 0x87, 0xc4, 0x9a, 0xc6, 0xa2, 0xe2, 0xb1, 0xa3, 0xc5, 0xae, 0xc2, 0xb4, 0xc5, - 0x89, 0xc7, 0x93, 0xc2, 0xa9, 0xc4, 0x9c, 0xe1, 0x9a, 0xa9, 0xc9, 0x81, 0xc6, 0x88, - 0xc3, 0x95, 0xc6, 0xb5, 0x56, 0x6b, 0x69, 0xc4, 0x86, 0xc4, 0xa5, 0xc4, 0xb3, 0xc3, - 0x85, 0xe2, 0xb1, 0xb0, 0xc4, 0x8e, 0x38, 0x5e, 0x3c, 0xc7, 0xb1, 0xc8, 0xa1, 0xc5, - 0x84, 0xc6, 0x85, 0xc8, 0xb9, 0xc6, 0x96, 0xc8, 0x94, 0xc3, 0x98, 0xc5, 0xb6, 0xc8, - 0x9a, 0xc8, 0x97, 0xc3, 0xa4, 0xc3, 0x81, 0xc3, 0xa9, 0x5c, 0xc7, 0xb7, 0xe1, 0x9b, - 0xac, 0xc8, 0x90, 0x2c, 0xe1, 0x9b, 0xa2, 0xc6, 0xb8, 0xc7, 0x93, 0xc4, 0x9e, 0xc4, - 0xbd, 0xc4, 0x90, 0xe1, 0x9a, 0xb7, 0xc9, 0x85, 0xc7, 0x9f, 0xc4, 0xbf, 0xc5, 0xba, - 0xc2, 0xa9, 0xe1, 0x9b, 0x9f, 0x76, 0xc3, 0xa3, 0xc8, 0xa6, 0xc5, 0x8c, 0xc6, 0xa0, - 0xc9, 0x8d, 0xc3, 0xa0, 0xc8, 0xa7, 0x2c, 0xc6, 0x80, 0xc8, 0xbf, 0x75, 0x2b, 0xc7, - 0xbe, 0xc5, 0xb5, 0xe1, 0x9b, 0x87, 0xc3, 0xbe, 0xcd, 0xba, 0xe1, 0x9b, 0x8f, 0xc6, - 0x82, 0xc7, 0xa7, 0xe1, 0x9b, 0x87, 0x62, 0xc3, 0x95, 0xc4, 0xbf, 0xe1, 0x9b, 0xaf, - 0xc4, 0xb3, 0xc7, 0xaf, 0xc3, 0x95, 0xc7, 0x9f, + 0xc8, 0x9b, 0x56, 0xe1, 0x9b, 0x9d, 0xc6, 0xaf, 0xe2, 0xb1, 0xbd, 0xc3, 0x80, 0xc5, + 0x8f, 0xe1, 0x9b, 0xaa, 0xc7, 0xbd, 0x45, 0x30, 0xe1, 0x9a, 0xbd, 0x62, 0xc5, 0x8a, + 0xc5, 0xba, 0xc7, 0x83, 0xc4, 0xa7, 0xe1, 0x9a, 0xa5, 0xc6, 0xab, 0xc6, 0x94, 0xe2, + 0xb1, 0xa0, 0xc3, 0x81, 0x6f, 0xc3, 0x84, 0x31, 0xc5, 0xbe, 0xc3, 0x87, 0xc7, 0xa8, + 0xe1, 0x9a, 0xa0, 0xc2, 0xa7, 0xc5, 0xb1, 0xc8, 0x85, 0xc8, 0xa1, 0x48, 0x2c, 0x41, + 0x53, 0xe2, 0xb1, 0xb4, 0xc7, 0xad, 0xc7, 0xb9, 0xc8, 0x9e, 0xc6, 0xa5, 0x4d, 0xe2, + 0xb1, 0xa4, 0xc3, 0x96, 0xc8, 0xbf, 0xc4, 0x95, 0xc6, 0x94, 0xc4, 0xa5, 0x64, 0xc4, + 0xbe, 0x69, 0xc8, 0xb9, 0x7d, 0xe1, 0x9b, 0x86, 0xe1, 0x9b, 0x9b, 0xce, 0x86, 0xe1, + 0x9a, 0xa9, 0xc4, 0x9f, 0x30, 0xc8, 0x8b, 0xe1, 0x9b, 0xa7, 0xc6, 0xbf, 0xc7, 0xbb, + 0xc7, 0x9a, 0xc8, 0x94, 0xc8, 0x9d, 0xc8, 0x8c, 0xc3, 0xb2, 0xc7, 0x95, 0x34, 0x71, + 0x38, 0xc6, 0xb5, 0xc4, 0xa6, 0xc8, 0x96, 0xce, 0x89, 0xc4, 0x93, 0x26, 0xc8, 0xa4, + 0xc6, 0xa7, 0xe1, 0x9b, 0xa7, 0x3b, 0xc4, 0x80, 0xc5, 0xb8, 0xc7, 0x86, 0xc8, 0xa0, + 0xc4, 0xbb, 0xc4, 0xa1, 0xc8, 0x88, 0x70, 0x5d, 0xe2, 0xb1, 0xa5, 0xc9, 0x89, 0xc7, + 0xbc, 0xc6, 0xb3, 0xc9, 0x8a, 0xc3, 0xbe, 0xe2, 0xb1, 0xa9, 0xc2, 0xbd, 0xc5, 0x88, + 0xc5, 0x88, 0xc4, 0xbc, 0xc6, 0x88, 0x5c, 0xc8, 0x86, 0xc3, 0xa8, 0x23, 0x58, 0xe1, + 0x9a, 0xa2, 0xc4, 0xb2, 0xc7, 0xbc, 0x5e, 0xe2, 0xb1, 0xb2, 0x45, 0xc7, 0xb7, 0xc9, + 0x81, 0xc2, 0xba, 0xe1, 0x9b, 0x91, 0xc3, 0x87, 0xc9, 0x8c, 0xce, 0x84, 0xe1, 0x9a, + 0xa8, 0xc8, 0x8c, 0xc7, 0x8b, 0xce, 0x86, 0xe2, 0xb1, 0xaf, 0x32, 0xc8, 0x88, 0xc4, + 0x9c, 0xe1, 0x9a, 0xac, 0xe1, 0x9b, 0x9e, 0xc6, 0xb1, 0xc7, 0x90, 0xe2, 0xb1, 0xa6, + 0xc8, 0x91, 0xc5, 0x9a, 0xc6, 0x8e, 0xc6, 0x84, 0xe1, 0x9a, 0xbd, 0xc4, 0xa6, 0xc5, + 0x84, 0xc3, 0x91, 0xc6, 0xbf, 0xc4, 0xb9, 0xce, 0x85, 0xc2, 0xa1, 0xc7, 0x93, 0xc9, + 0x8e, 0xc5, 0xb4, 0xc8, 0x91, 0xc5, 0xa1, 0xe1, 0x9b, 0x95, 0xc8, 0xa9, 0xe1, 0x9b, + 0x92, 0x5f, 0xc6, 0xba, 0x56, 0xc4, 0x95, 0x32, 0xe2, 0xb1, 0xa5, 0x53, 0xc3, 0xba, + 0x23, 0xc7, 0x99, 0xc7, 0xa8, 0xc3, 0x81, 0xc6, 0xa1, 0x34, 0xc5, 0xb1, 0xc3, 0x85, + 0xe1, 0x9b, 0xac, 0xc7, 0xad, 0xc4, 0x90, 0xc5, 0x9f, 0xc5, 0xaf, 0xc8, 0x9e, 0xc7, + 0xb5, 0xc5, 0x82, 0xc9, 0x81, 0xc5, 0x8d, 0xc5, 0x92, 0xc6, 0x9d, 0xc5, 0xba, 0xe1, + 0x9a, 0xa7, 0xc4, 0x81, 0xe2, 0xb1, 0xa1, 0xc6, 0xa5, 0xe2, 0xb1, 0xb9, 0xc4, 0x9f, + 0xce, 0x88, 0xc6, 0x97, 0xc6, 0xaf, 0xe1, 0x9b, 0xac, 0xc5, 0xa1, 0xe2, 0xb1, 0xb3, + 0xc9, 0x83, 0xc5, 0x86, 0xc6, 0xaa, 0xe2, 0xb1, 0xb0, 0xc7, 0x8b, 0xc5, 0xae, 0xc2, + 0xb5, 0x42, 0xc6, 0xab, 0x58, 0xc8, 0x93, 0xc6, 0x82, 0xe2, 0xb1, 0xb6, 0xc7, 0x92, + 0xe1, 0x9b, 0x95, 0xc4, 0x81, 0xc3, 0x9f, 0xc2, 0xb7, 0xc5, 0x8f, 0xc8, 0xb7, 0xc3, + 0xac, 0xc4, 0xbf, 0x48, 0xc5, 0xba, 0xe1, 0x9a, 0xb9, 0xc4, 0x8c, 0xe1, 0x9b, 0x87, + 0xc6, 0x93, 0xc4, 0x8a, 0xc7, 0x99, 0xc6, 0x98, 0xc6, 0xb7, 0xc5, 0xb9, 0xc4, 0x8b, + 0xc3, 0xbb, 0xc8, 0x8b, 0xc3, 0xbb, 0xc5, 0x93, 0xe1, 0x9b, 0xad, 0xe1, 0x9a, 0xb1, + 0xc3, 0x82, 0xc6, 0x99, 0xc5, 0x93, 0xc6, 0x8e, 0xcd, 0xb4, 0xe2, 0xb1, 0xa8, 0xc6, + 0x97, 0xc6, 0x99, 0xc5, 0x80, 0xc4, 0x9c, 0x78, 0xcd, 0xb2, 0xc4, 0xb3, 0xc5, 0x80, + 0xe1, 0x9b, 0x99, 0xc7, 0xa8, 0xc5, 0x8e, 0x5a, ], - asset_id: [ - 0x4f, 0x20, 0x3c, 0x3a, 0x6f, 0x5b, 0x58, 0xbb, 0x4b, 0x01, 0x14, 0xf0, 0x2c, 0x1f, - 0x4e, 0xbb, 0x78, 0x4a, 0xa3, 0xa3, 0x7e, 0x5d, 0xae, 0x4a, 0x27, 0xf0, 0xea, 0xcc, - 0xf6, 0x8b, 0xab, 0x29, + asset_base: [ + 0x76, 0xb6, 0xcc, 0x39, 0x90, 0xd8, 0xf1, 0x14, 0x96, 0x01, 0xe6, 0x8f, 0x2e, 0xca, + 0xcd, 0x97, 0x0f, 0xa0, 0xb7, 0xc0, 0xbe, 0xab, 0x7c, 0x88, 0x28, 0x21, 0x4a, 0x37, + 0xce, 0x87, 0x10, 0xa3, ], }, TestVector { @@ -780,48 +780,48 @@ pub(crate) fn test_vectors() -> Vec { 0xbf, 0xcd, 0x06, 0x38, ], description: [ - 0xc8, 0xb4, 0x34, 0xc3, 0x8c, 0xc7, 0x89, 0xc7, 0x86, 0x5e, 0xc5, 0xbb, 0xc7, 0xba, - 0xe1, 0x9b, 0x96, 0x5d, 0xc5, 0x88, 0x52, 0xcd, 0xb1, 0xe1, 0x9b, 0xad, 0xce, 0x88, - 0xc7, 0x80, 0xc5, 0x91, 0xc6, 0xba, 0xc6, 0x8f, 0xc6, 0x81, 0xc7, 0xa8, 0xc6, 0xb1, - 0x6b, 0xc6, 0x8c, 0xc5, 0x8f, 0xe2, 0xb1, 0xb3, 0xc5, 0x95, 0xc5, 0xa3, 0xc7, 0xaa, - 0xc5, 0xb5, 0xc7, 0xbe, 0xc6, 0xb2, 0xc6, 0x8d, 0x61, 0x23, 0xe2, 0xb1, 0xb3, 0xc4, - 0xbb, 0xc5, 0x96, 0xc6, 0x91, 0xc7, 0x99, 0x60, 0x2c, 0xe1, 0x9b, 0x82, 0xce, 0x86, - 0xc8, 0x92, 0xc4, 0xa1, 0xc4, 0xa2, 0xc7, 0xb4, 0x56, 0x23, 0xe1, 0x9b, 0xae, 0xc7, - 0x8d, 0xc3, 0xa0, 0xc6, 0xa4, 0xc4, 0x9b, 0xc9, 0x81, 0xc8, 0xb6, 0xe1, 0x9b, 0xa0, - 0xe2, 0xb1, 0xbc, 0xe1, 0x9b, 0x82, 0xc8, 0x98, 0xc3, 0xb7, 0xe1, 0x9b, 0x8b, 0xe1, - 0x9b, 0x80, 0xe1, 0x9a, 0xa5, 0x2a, 0xc3, 0x90, 0x5c, 0xc4, 0xb8, 0xc8, 0x9e, 0xc5, - 0x80, 0xc8, 0x9b, 0xe2, 0xb1, 0xaf, 0xc7, 0x9f, 0xc7, 0x97, 0xc3, 0x9d, 0xe1, 0x9b, - 0x9e, 0xc4, 0xaf, 0xc4, 0xb8, 0xc2, 0xb9, 0x3c, 0xc4, 0x9a, 0xc8, 0x80, 0xc6, 0x9d, - 0x2f, 0x47, 0xc6, 0xb0, 0xc6, 0xb4, 0xc7, 0xb9, 0xe2, 0xb1, 0xb6, 0xc8, 0xa5, 0xc7, - 0x91, 0xe1, 0x9b, 0x9d, 0xc6, 0x95, 0x74, 0xe1, 0x9b, 0x9b, 0xc4, 0xac, 0xc6, 0xa3, - 0xe1, 0x9b, 0xa8, 0xc4, 0x8d, 0xc6, 0x97, 0xc5, 0xb6, 0xc6, 0xb8, 0xe2, 0xb1, 0xa8, - 0xc2, 0xbb, 0xe1, 0x9b, 0x95, 0xc7, 0x91, 0xe1, 0x9a, 0xba, 0xc8, 0xbe, 0xc3, 0xa1, - 0xc2, 0xbf, 0xc6, 0x9d, 0xcd, 0xb2, 0x51, 0xc6, 0x8d, 0xe1, 0x9a, 0xb9, 0xc8, 0x8d, - 0xc5, 0xaf, 0xc4, 0xa9, 0xc6, 0xa4, 0xc5, 0x8b, 0xc6, 0xbd, 0xc3, 0xb6, 0xc4, 0x8d, - 0xc7, 0x80, 0xc6, 0x95, 0xc5, 0xb9, 0xc2, 0xae, 0xe1, 0x9a, 0xa4, 0x54, 0x69, 0xc3, - 0x9b, 0xc4, 0x8e, 0xc6, 0x9f, 0xc8, 0xb5, 0x65, 0xc5, 0x95, 0xcd, 0xb3, 0xc5, 0x9f, - 0xc7, 0xae, 0xc4, 0xa4, 0xc3, 0x83, 0xc3, 0x82, 0xe1, 0x9a, 0xa4, 0xc4, 0x93, 0xc7, - 0x88, 0x67, 0xc3, 0xaf, 0xc3, 0xb9, 0xc5, 0xb5, 0x46, 0xcd, 0xb1, 0x5e, 0x28, 0xe1, - 0x9a, 0xb6, 0xc6, 0x86, 0x67, 0xc3, 0xb9, 0xc5, 0xb2, 0xc5, 0x8c, 0xc4, 0xb5, 0xc3, - 0xba, 0xe1, 0x9a, 0xbe, 0xc6, 0x85, 0x5a, 0xcd, 0xb4, 0xe1, 0x9b, 0xa8, 0xc6, 0x86, - 0xc7, 0xb5, 0xc6, 0x83, 0xc3, 0x8d, 0xc4, 0xa0, 0xc7, 0x9d, 0xc6, 0xab, 0x57, 0xc4, - 0xa3, 0xc3, 0x9d, 0xc7, 0x88, 0x3f, 0xc8, 0x99, 0xc5, 0x98, 0xc4, 0x91, 0xe1, 0x9b, - 0x88, 0xe2, 0xb1, 0xa1, 0xc7, 0x97, 0xc5, 0x8d, 0xe1, 0x9a, 0xb8, 0xc8, 0xa8, 0xc2, - 0xac, 0x4d, 0xc6, 0xa2, 0xe2, 0xb1, 0xb8, 0x3f, 0xe2, 0xb1, 0xb8, 0xc8, 0xa4, 0xc7, - 0x98, 0xc7, 0x98, 0x63, 0xc6, 0xb3, 0xc5, 0x8f, 0xc8, 0x86, 0xc4, 0xbf, 0xe2, 0xb1, - 0xb8, 0xc8, 0xb6, 0xc4, 0x98, 0xc4, 0x8a, 0xc6, 0x93, 0xe1, 0x9b, 0x87, 0xc7, 0x93, - 0xc6, 0xbb, 0xc8, 0x84, 0xc7, 0x92, 0xc8, 0x97, 0xe2, 0xb1, 0xa2, 0xc6, 0x8b, 0xc5, - 0xa1, 0xc8, 0x8b, 0xc9, 0x8b, 0xc3, 0x9a, 0xe1, 0x9b, 0x81, 0xc2, 0xa2, 0xc6, 0x95, - 0xc8, 0x99, 0x38, 0xc4, 0xb2, 0x68, 0xc7, 0x83, 0xe1, 0x9a, 0xb2, 0xc4, 0xae, 0xc8, - 0x8d, 0xc5, 0xb6, 0xc5, 0x9e, 0x79, 0xc6, 0xa9, 0x45, 0xc6, 0x9f, 0xc7, 0x99, 0xc7, - 0x99, 0xe1, 0x9b, 0x9c, 0xe1, 0x9b, 0xa1, 0xc7, 0xbc, 0xc8, 0x88, 0xc6, 0xbe, 0xc4, - 0xb3, 0xc8, 0x90, 0x4c, 0xc8, 0xba, 0xc3, 0x9d, 0xe1, 0x9b, 0x8f, 0xe1, 0x9a, 0xb7, - 0xe2, 0xb1, 0xb6, 0xc4, 0x83, 0xc5, 0xa9, 0x5a, + 0xc5, 0x87, 0xe2, 0xb1, 0xbb, 0xc8, 0xa4, 0xc5, 0x85, 0xc4, 0x84, 0xe1, 0x9b, 0x99, + 0xc9, 0x85, 0xe1, 0x9a, 0xbe, 0xc4, 0x85, 0xc7, 0x8b, 0xe1, 0x9b, 0xa2, 0xc6, 0xa4, + 0x5a, 0xc6, 0xad, 0xc7, 0x80, 0x23, 0xc5, 0x9f, 0xc4, 0xb2, 0xe1, 0x9b, 0x94, 0xc3, + 0xb1, 0xc6, 0xae, 0xe1, 0x9a, 0xaa, 0x71, 0xc6, 0xa1, 0xc8, 0x9e, 0xc8, 0x97, 0xc6, + 0xac, 0xc3, 0x83, 0xc8, 0x9a, 0xc6, 0xa7, 0x41, 0xe1, 0x9a, 0xbf, 0xc2, 0xaa, 0xc8, + 0x9b, 0xc4, 0xa4, 0xc3, 0x97, 0xc8, 0x9d, 0x55, 0xc4, 0x92, 0xc5, 0xa2, 0xc5, 0x8b, + 0xc8, 0xaa, 0xc6, 0xa3, 0xc3, 0x81, 0xc6, 0x81, 0x7a, 0xcd, 0xb0, 0x6e, 0xc3, 0xb4, + 0xc4, 0x90, 0xc4, 0xaa, 0xe2, 0xb1, 0xa6, 0xc4, 0xa0, 0xc2, 0xbf, 0xc7, 0xa7, 0xc3, + 0xad, 0x5b, 0xc7, 0xa3, 0xc5, 0xb3, 0xc7, 0xbe, 0xc6, 0x9a, 0xc7, 0x80, 0xc2, 0xab, + 0xc5, 0x99, 0xe1, 0x9b, 0x91, 0xc6, 0x90, 0x68, 0xc4, 0xb9, 0xc6, 0x87, 0x66, 0xc3, + 0xb6, 0xc5, 0xb8, 0xc6, 0x9a, 0x7b, 0xc7, 0x81, 0xc5, 0x8b, 0xc5, 0x87, 0xc3, 0x9b, + 0xc6, 0x94, 0xc4, 0x8d, 0xc2, 0xb9, 0xe2, 0xb1, 0xbd, 0xc6, 0x9e, 0xc7, 0xbc, 0x68, + 0xc3, 0xaa, 0x5b, 0xc5, 0x85, 0xc9, 0x87, 0xe1, 0x9b, 0x85, 0x5d, 0xc9, 0x8c, 0xe1, + 0x9b, 0xa6, 0x5d, 0xcd, 0xb7, 0xc7, 0x9f, 0x30, 0xc4, 0x9d, 0xc2, 0xb7, 0xe1, 0x9b, + 0xa0, 0xc4, 0xab, 0xc2, 0xaf, 0xc5, 0xb2, 0xe1, 0x9b, 0xa6, 0xc3, 0x81, 0xc5, 0xab, + 0xc8, 0xa0, 0xe1, 0x9b, 0x9c, 0xc5, 0xa5, 0xc4, 0x9e, 0xc3, 0x94, 0xc6, 0xa0, 0x7e, + 0xc6, 0x8c, 0xc5, 0x80, 0xc8, 0x9a, 0xcd, 0xb6, 0xc6, 0xa4, 0xc5, 0x9b, 0xe1, 0x9b, + 0x87, 0xe1, 0x9a, 0xa4, 0x62, 0xe2, 0xb1, 0xa4, 0x35, 0x3f, 0xc2, 0xaa, 0xc7, 0xb0, + 0xc5, 0xb4, 0xc9, 0x82, 0xe1, 0x9a, 0xab, 0xc8, 0xb1, 0xc8, 0xae, 0xc6, 0xbc, 0xc8, + 0x98, 0x33, 0xc5, 0xa4, 0x31, 0xe1, 0x9a, 0xbd, 0xc8, 0xb7, 0xc4, 0xa2, 0x45, 0xc5, + 0x8a, 0xe1, 0x9a, 0xb0, 0xc2, 0xb2, 0xc6, 0x8f, 0xc8, 0x96, 0xc6, 0x93, 0xc6, 0x89, + 0xe2, 0xb1, 0xb4, 0xc7, 0xb9, 0xc3, 0x88, 0xc7, 0x9f, 0xc7, 0x85, 0xe2, 0xb1, 0xa8, + 0xc7, 0xa9, 0xc8, 0x99, 0xc4, 0x8c, 0xc4, 0xaf, 0xc4, 0x99, 0x3b, 0xc5, 0xa8, 0xe1, + 0x9a, 0xaa, 0xc6, 0x9e, 0xc6, 0x86, 0xc2, 0xb5, 0x43, 0xc2, 0xaa, 0xe1, 0x9b, 0x95, + 0xc8, 0xba, 0xc2, 0xac, 0xc7, 0x9e, 0xe2, 0xb1, 0xb5, 0xc8, 0xb3, 0xe1, 0x9b, 0xa4, + 0xc8, 0xa6, 0xc6, 0x8c, 0xc6, 0x99, 0xc6, 0x89, 0xc5, 0x82, 0xc7, 0xa4, 0x7c, 0xce, + 0x89, 0xc6, 0xbf, 0xc8, 0x9d, 0xc3, 0x92, 0xc6, 0xab, 0xe1, 0x9a, 0xab, 0xe1, 0x9b, + 0x84, 0xc6, 0x9e, 0x21, 0x79, 0xcd, 0xb1, 0xc4, 0xb1, 0xce, 0x8c, 0xe1, 0x9b, 0x98, + 0xe1, 0x9b, 0x8d, 0xc6, 0xb0, 0xe1, 0x9a, 0xa5, 0xc7, 0xb9, 0xe1, 0x9b, 0x9d, 0x48, + 0xc4, 0xbe, 0xc8, 0xaf, 0xc8, 0x89, 0xe1, 0x9b, 0xb0, 0xc2, 0xb8, 0xe2, 0xb1, 0xb1, + 0xc3, 0x96, 0xc5, 0xb1, 0x44, 0xc3, 0x9e, 0x6c, 0xe1, 0x9a, 0xbb, 0xc4, 0xaf, 0xc4, + 0x8c, 0xc2, 0xa1, 0xc3, 0xa1, 0xc3, 0x98, 0xc8, 0xac, 0xc3, 0xa3, 0xc8, 0xa2, 0xcd, + 0xbb, 0xc6, 0xb3, 0xe1, 0x9b, 0x9c, 0x51, 0xc5, 0xa3, 0xc5, 0xb3, 0x77, 0xc3, 0x87, + 0xc3, 0xbb, 0x3b, 0xc8, 0x98, 0xc5, 0xb9, 0x2a, 0x4a, 0xc5, 0xb7, 0xc9, 0x8c, 0x6e, + 0xe1, 0x9b, 0xa9, 0xc3, 0x94, 0xc3, 0x9f, 0xc3, 0xaa, 0xe1, 0x9b, 0xb0, 0xc3, 0x85, + 0x59, 0xc8, 0xbb, 0xc4, 0x87, 0xc7, 0xb2, 0xcd, 0xbe, 0xc5, 0xb4, 0x6c, 0xe2, 0xb1, + 0xad, 0x6d, 0xc2, 0xa9, 0xc4, 0x8b, 0xc6, 0xb6, ], - asset_id: [ - 0x61, 0xb6, 0x64, 0xff, 0x70, 0xb4, 0x5a, 0x10, 0x5a, 0x5e, 0x5e, 0x2a, 0x65, 0xbd, - 0x5b, 0x37, 0x7a, 0x0d, 0x89, 0xf0, 0x65, 0x6d, 0xb9, 0xe5, 0x72, 0x43, 0x2a, 0x3b, - 0x41, 0x09, 0xb8, 0xba, + asset_base: [ + 0xba, 0xb2, 0xba, 0xb5, 0x2d, 0x54, 0x67, 0xd4, 0xa6, 0x36, 0x0c, 0xb2, 0x74, 0xc9, + 0x2a, 0x7b, 0x8e, 0x0b, 0xc5, 0x02, 0x28, 0xa9, 0x68, 0x0f, 0xcd, 0xa0, 0x38, 0x17, + 0x62, 0x3f, 0x48, 0x91, ], }, TestVector { @@ -831,48 +831,48 @@ pub(crate) fn test_vectors() -> Vec { 0xbd, 0xb7, 0x75, 0x19, ], description: [ - 0xc4, 0xae, 0xc6, 0x83, 0xc3, 0xb4, 0xe1, 0x9b, 0xa2, 0xc6, 0x93, 0xc9, 0x86, 0xc4, - 0xa7, 0xe2, 0xb1, 0xb9, 0xc8, 0x9b, 0x3d, 0xcd, 0xbd, 0x3f, 0x54, 0xc8, 0xa9, 0xce, - 0x84, 0xc8, 0x87, 0xc4, 0x8d, 0xe1, 0x9b, 0x83, 0xc6, 0xac, 0xe1, 0x9b, 0x9f, 0xc5, - 0x83, 0xc7, 0x89, 0x66, 0xc4, 0x86, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, 0x8f, 0xc6, 0x99, - 0xc5, 0xb0, 0xc4, 0x8e, 0xc4, 0x8b, 0xc7, 0x93, 0xc5, 0x9b, 0xc5, 0xb7, 0xc8, 0x89, - 0xc3, 0x9b, 0x6e, 0xc5, 0xbd, 0xc2, 0xbe, 0xc4, 0x9e, 0x5f, 0xe1, 0x9b, 0x9a, 0xc4, - 0x86, 0xe2, 0xb1, 0xa2, 0x7c, 0xcd, 0xb7, 0xc3, 0xab, 0x43, 0xc7, 0xa7, 0xe2, 0xb1, - 0xa0, 0xcd, 0xbc, 0xc8, 0x90, 0xc7, 0x9f, 0xc7, 0xb4, 0xc8, 0x9d, 0xc4, 0x9e, 0xe1, - 0x9a, 0xb3, 0x38, 0xc6, 0xaa, 0xe2, 0xb1, 0xb4, 0xc8, 0x97, 0xc8, 0x96, 0xc6, 0x90, - 0xc7, 0xaf, 0xc7, 0x97, 0x77, 0x5f, 0xc4, 0x9d, 0xc7, 0xa9, 0xc8, 0x9f, 0xe1, 0x9a, - 0xb0, 0xc3, 0x90, 0x35, 0x49, 0xc4, 0xb9, 0xc5, 0x96, 0xcd, 0xbc, 0xc7, 0xb3, 0xc8, - 0xa4, 0x37, 0x46, 0xc2, 0xba, 0xe1, 0x9b, 0x89, 0xc5, 0x86, 0xc6, 0x84, 0xc5, 0x9b, - 0xe1, 0x9b, 0x93, 0xc7, 0x81, 0xc5, 0x8d, 0x29, 0xc4, 0x9c, 0xc6, 0xbe, 0xc4, 0xad, - 0xc8, 0x83, 0xe1, 0x9b, 0x81, 0xc4, 0xa2, 0xc8, 0x9d, 0xc4, 0x9c, 0xc7, 0xae, 0xc7, - 0x80, 0x35, 0xe1, 0x9a, 0xa6, 0xe1, 0x9a, 0xac, 0xc4, 0xb7, 0xe1, 0x9b, 0xa2, 0xc7, - 0xa6, 0xe2, 0xb1, 0xad, 0xc5, 0x89, 0xc6, 0x95, 0xc4, 0x98, 0xc8, 0x8d, 0xe2, 0xb1, - 0xa3, 0xc6, 0xb3, 0xc7, 0xaf, 0xe1, 0x9a, 0xb7, 0xc4, 0xb8, 0xe2, 0xb1, 0xa8, 0xc8, - 0xa9, 0xc8, 0xba, 0xc3, 0x97, 0xe1, 0x9b, 0x89, 0xc3, 0x93, 0xc5, 0x9a, 0xc4, 0x8b, - 0xc5, 0xa6, 0xc4, 0xad, 0xc5, 0xb3, 0xe2, 0xb1, 0xb5, 0x66, 0xc6, 0x9c, 0x40, 0xc2, - 0xa1, 0xc8, 0x96, 0xe2, 0xb1, 0xa3, 0xc3, 0xbf, 0xc5, 0xa5, 0xcd, 0xb0, 0xc8, 0xb8, - 0xc6, 0xa1, 0x33, 0xe1, 0x9a, 0xb1, 0xe1, 0x9a, 0xbd, 0x33, 0xc3, 0xa2, 0xc6, 0xb7, - 0xc4, 0xb9, 0xc7, 0xba, 0x30, 0xc5, 0x9f, 0xc8, 0xad, 0xc5, 0x9c, 0xc4, 0xa5, 0xc2, - 0xbc, 0xce, 0x88, 0x4c, 0xc8, 0x9f, 0x7c, 0xc5, 0xbd, 0xc5, 0xa2, 0xe2, 0xb1, 0xae, - 0xc3, 0xb2, 0xc7, 0xb6, 0xc4, 0x96, 0xc5, 0xaa, 0xc6, 0x87, 0xc5, 0xb6, 0xe1, 0x9b, - 0x9a, 0xc3, 0xb1, 0xcd, 0xbb, 0xc6, 0xbd, 0xcd, 0xb5, 0x70, 0xce, 0x88, 0xc4, 0x8a, - 0xc2, 0xa8, 0xc4, 0xa6, 0xc2, 0xb0, 0xc4, 0xaf, 0xc6, 0xb5, 0xcd, 0xbd, 0x34, 0xc4, - 0x9a, 0xc4, 0x93, 0xc8, 0xbb, 0xc5, 0x99, 0xc7, 0x9d, 0xc2, 0xb4, 0xc9, 0x86, 0xe1, - 0x9b, 0x91, 0xc4, 0x9b, 0xc8, 0x94, 0xc7, 0xae, 0xe1, 0x9b, 0x9c, 0xc8, 0xab, 0xe1, - 0x9b, 0xa9, 0xc3, 0x99, 0xc8, 0x9c, 0xc3, 0x83, 0x7a, 0xe1, 0x9b, 0x87, 0xe1, 0x9a, - 0xad, 0xc5, 0x8c, 0xe1, 0x9a, 0xaa, 0xc7, 0xbe, 0x5f, 0xc8, 0xb5, 0xc6, 0x99, 0xe1, - 0x9b, 0xa7, 0xc7, 0xb1, 0xc6, 0x90, 0xc7, 0xb0, 0xc4, 0xac, 0xc3, 0x90, 0x77, 0xc7, - 0xb8, 0xc6, 0xa9, 0xc7, 0xa7, 0xce, 0x88, 0xe1, 0x9a, 0xa1, 0x36, 0xc4, 0xbb, 0xc4, - 0xa1, 0xc8, 0x8c, 0xc3, 0xb4, 0xc2, 0xa2, 0xe1, 0x9a, 0xb9, 0x68, 0xc7, 0x9a, 0xc5, - 0x9e, 0x75, 0xcd, 0xb5, 0xe1, 0x9b, 0x98, 0xc7, 0x82, 0xce, 0x88, 0xe1, 0x9b, 0x9c, - 0xc5, 0xa6, 0xc7, 0x98, 0xc5, 0xa7, 0x30, 0xc8, 0xbf, 0xcd, 0xb6, 0xc5, 0xbe, 0xc7, - 0x97, 0x6e, 0xc6, 0xab, 0xc8, 0x92, 0xc8, 0x88, 0xc5, 0x87, 0xc7, 0x95, 0xc3, 0x97, - 0xc4, 0xbb, 0xc7, 0x9c, 0xc5, 0x80, 0xc2, 0xb6, + 0xc7, 0x93, 0xc6, 0xb5, 0xc4, 0x82, 0xc6, 0x85, 0xe1, 0x9a, 0xac, 0xc7, 0x91, 0xc4, + 0xad, 0xe1, 0x9b, 0x84, 0xe2, 0xb1, 0xbc, 0xc2, 0xbb, 0xc8, 0xa9, 0xc7, 0xaf, 0xc4, + 0xa6, 0x79, 0xc6, 0x8a, 0xc5, 0xac, 0xc6, 0x98, 0xe1, 0x9b, 0x8f, 0xc5, 0x8b, 0xc3, + 0x81, 0xe1, 0x9b, 0x84, 0xe1, 0x9a, 0xa9, 0xe2, 0xb1, 0xa2, 0xe1, 0x9b, 0x92, 0x40, + 0xe2, 0xb1, 0xa0, 0xc4, 0xa6, 0xc8, 0xac, 0xc7, 0xb9, 0xc9, 0x8d, 0xc7, 0xab, 0xc3, + 0x8a, 0xc6, 0xb8, 0x7c, 0xc5, 0xa1, 0xc8, 0xaf, 0xc4, 0x80, 0xc3, 0xb4, 0xc5, 0x82, + 0xc7, 0xb7, 0xc6, 0x8a, 0xc6, 0xb2, 0x2b, 0x6b, 0xc6, 0x9d, 0xe2, 0xb1, 0xb6, 0xc7, + 0x94, 0xcd, 0xb5, 0xc5, 0x96, 0xc7, 0xae, 0xc4, 0xb1, 0xc4, 0xb0, 0xe1, 0x9b, 0x8e, + 0xcd, 0xb2, 0xe1, 0x9b, 0x83, 0xc5, 0xb5, 0xc8, 0x84, 0xc6, 0x88, 0xcd, 0xb7, 0xe2, + 0xb1, 0xa5, 0xc8, 0xa6, 0xc5, 0x8c, 0xc5, 0x8f, 0x60, 0xc8, 0x83, 0xc6, 0x9f, 0xc4, + 0xa2, 0xc5, 0x9f, 0x5b, 0xc8, 0x97, 0xcd, 0xbc, 0xc4, 0xbb, 0xc5, 0x93, 0xc6, 0xa9, + 0xc3, 0x8e, 0x31, 0xe2, 0xb1, 0xae, 0x49, 0xc7, 0x93, 0xc2, 0xba, 0xc5, 0x9c, 0xc2, + 0xb4, 0xe1, 0x9a, 0xa6, 0xc9, 0x8b, 0x75, 0x36, 0xe1, 0x9b, 0x89, 0x6c, 0xc3, 0x95, + 0xc4, 0xba, 0x7e, 0x21, 0xc8, 0xac, 0xc4, 0xa0, 0x4f, 0xc5, 0xbc, 0x5b, 0xce, 0x88, + 0x37, 0x38, 0xc6, 0x8b, 0xc2, 0xb9, 0x58, 0xc3, 0x86, 0xc4, 0x96, 0x23, 0xc6, 0xbb, + 0xc8, 0xa3, 0x5a, 0xc6, 0xbc, 0xe1, 0x9b, 0x89, 0xc3, 0x82, 0xc3, 0x9d, 0x69, 0xe1, + 0x9a, 0xbe, 0xe1, 0x9b, 0x8d, 0xc3, 0xb6, 0x73, 0xc4, 0xb9, 0xe1, 0x9b, 0xaa, 0x6a, + 0xc2, 0xa8, 0xc6, 0xbb, 0xce, 0x85, 0xc7, 0x94, 0xc5, 0xaa, 0xc2, 0xb5, 0x5e, 0xc2, + 0xb5, 0xc3, 0xa1, 0xc6, 0x93, 0xc3, 0xb6, 0xc5, 0x95, 0xc6, 0x91, 0xc7, 0xb1, 0xc8, + 0xb3, 0x66, 0x21, 0xc4, 0x8a, 0xc7, 0xb9, 0xc5, 0x8d, 0x33, 0xc9, 0x8c, 0x5e, 0xc4, + 0xb6, 0xc7, 0x88, 0xc3, 0xae, 0xc5, 0x8e, 0xc7, 0xaf, 0x4e, 0xc4, 0xa6, 0xe1, 0x9b, + 0xad, 0xc7, 0x8c, 0xe1, 0x9a, 0xbf, 0xc7, 0x89, 0xc9, 0x88, 0xc6, 0xab, 0xe2, 0xb1, + 0xbf, 0xc7, 0x85, 0xc6, 0xa1, 0xc3, 0x86, 0xe1, 0x9b, 0x9c, 0x3b, 0xc2, 0xa6, 0x7c, + 0xc3, 0x94, 0x5c, 0xc8, 0x82, 0xc3, 0xad, 0xc7, 0x98, 0xc5, 0xab, 0xc7, 0xa1, 0xe1, + 0x9a, 0xa3, 0xc8, 0xa3, 0xc6, 0x96, 0xc5, 0x82, 0xe1, 0x9b, 0x84, 0xc8, 0xb0, 0xc2, + 0xaa, 0xc4, 0x94, 0x68, 0xc6, 0x8f, 0xe2, 0xb1, 0xb8, 0xc6, 0xae, 0x54, 0xe1, 0x9b, + 0x88, 0xc7, 0x82, 0xc3, 0x81, 0xc8, 0xaf, 0xc7, 0xa0, 0x3d, 0xc4, 0x98, 0xc4, 0x97, + 0xc7, 0xba, 0xe1, 0x9b, 0xa8, 0xc6, 0xba, 0xc3, 0x93, 0xc2, 0xa7, 0xc7, 0xa1, 0xc5, + 0x8d, 0xc7, 0x87, 0xc3, 0xa1, 0xc5, 0xa4, 0xc6, 0x9b, 0x21, 0xc5, 0xa8, 0xc8, 0xb2, + 0xc4, 0xb9, 0xc6, 0x81, 0xc7, 0xb6, 0xc8, 0xaa, 0xc3, 0x89, 0xe1, 0x9b, 0xac, 0x45, + 0xc3, 0xa0, 0xc4, 0xae, 0xe1, 0x9b, 0xa5, 0xc8, 0xad, 0xe1, 0x9a, 0xb6, 0x55, 0xe1, + 0x9b, 0x9d, 0xc4, 0x97, 0xc8, 0x89, 0xc8, 0xa8, 0xc5, 0xbe, 0xc7, 0x90, 0xc2, 0xab, + 0xc8, 0xbd, 0xc3, 0x96, 0xc7, 0x99, 0xc8, 0xa8, 0xc2, 0xa1, 0xe1, 0x9b, 0x80, 0xc7, + 0x9a, 0xc7, 0xba, 0xc5, 0xac, 0x26, 0xc5, 0x96, 0xe1, 0x9a, 0xa4, 0xc8, 0x9d, 0xc6, + 0xa6, 0xe1, 0x9a, 0xb9, 0xc4, 0x86, 0xe1, 0x9a, 0xbf, 0xc8, 0xab, 0xce, 0x87, 0xe1, + 0x9b, 0x94, 0xc4, 0x81, 0xc3, 0xaf, 0xc5, 0xb6, 0xc8, 0x8c, 0xe1, 0x9a, 0xbd, 0xc3, + 0xbc, 0xc3, 0x9b, 0xc4, 0xb5, 0x7b, 0xc8, 0xaf, ], - asset_id: [ - 0x8b, 0x7d, 0xde, 0x16, 0x1b, 0xad, 0x63, 0xb2, 0x3f, 0x2a, 0xa4, 0x2d, 0x23, 0xa3, - 0x7b, 0x5e, 0x0e, 0x33, 0x61, 0xa9, 0x85, 0x97, 0x47, 0x96, 0xf7, 0x10, 0xef, 0x46, - 0x4e, 0xa7, 0xa0, 0xaf, + asset_base: [ + 0x86, 0x7f, 0xd2, 0x6b, 0xe6, 0xf1, 0x84, 0x89, 0x32, 0x91, 0xf8, 0x22, 0x44, 0xee, + 0x64, 0xa0, 0x63, 0xac, 0x28, 0xd1, 0xb2, 0x32, 0x0e, 0x4b, 0x40, 0xca, 0x6a, 0xf2, + 0x0a, 0xa8, 0x11, 0xbe, ], }, TestVector { @@ -882,48 +882,48 @@ pub(crate) fn test_vectors() -> Vec { 0x79, 0xc0, 0x76, 0x27, ], description: [ - 0xc7, 0xa3, 0xc8, 0x83, 0xc6, 0xa9, 0xc6, 0x9c, 0xe1, 0x9b, 0x95, 0xc3, 0x94, 0xc2, - 0xa1, 0xc2, 0xa5, 0xc5, 0x92, 0xe2, 0xb1, 0xbe, 0xe1, 0x9a, 0xa9, 0x60, 0xc6, 0xbc, - 0x51, 0xe1, 0x9a, 0xa9, 0xe1, 0x9a, 0xb9, 0xe1, 0x9a, 0xae, 0xc8, 0xb1, 0xcd, 0xb7, - 0xc8, 0x9a, 0xc8, 0xa2, 0xc6, 0x91, 0xc5, 0x90, 0xc5, 0x8a, 0xc8, 0x94, 0xe1, 0x9a, - 0xbe, 0xce, 0x88, 0xc6, 0xb8, 0xc8, 0x8e, 0xc2, 0xbe, 0xce, 0x86, 0xc5, 0xb4, 0xe1, - 0x9a, 0xa1, 0xc5, 0xbe, 0xc2, 0xa1, 0x39, 0xc8, 0xbd, 0xc4, 0xbb, 0xc8, 0x96, 0xe1, - 0x9b, 0x98, 0x72, 0xc3, 0x98, 0xc8, 0x9e, 0x33, 0x40, 0xc3, 0x9c, 0xe1, 0x9b, 0x97, - 0xc8, 0x8e, 0xc7, 0xab, 0x4b, 0xc6, 0xa1, 0xc6, 0x91, 0xc3, 0x90, 0xc7, 0xa5, 0xc4, - 0x88, 0xc5, 0x96, 0xc5, 0xb2, 0xc9, 0x84, 0xc6, 0xa6, 0xe1, 0x9a, 0xb0, 0xe2, 0xb1, - 0xad, 0xc3, 0x99, 0x45, 0xc3, 0x9d, 0xc3, 0xaf, 0xc6, 0xb0, 0xc5, 0x9c, 0xc4, 0x83, - 0xc4, 0x86, 0xc5, 0x91, 0xc7, 0xbe, 0xc4, 0x98, 0xc4, 0xa8, 0x62, 0xc4, 0x9b, 0xc3, - 0xb0, 0xe1, 0x9a, 0xa3, 0xc6, 0xab, 0xc4, 0x95, 0xc8, 0x99, 0xc5, 0xa8, 0xe1, 0x9b, - 0x92, 0xc8, 0xae, 0x4d, 0xe1, 0x9a, 0xae, 0xcd, 0xb2, 0xc3, 0x95, 0xc4, 0x8f, 0xc6, - 0xa9, 0xc5, 0x83, 0xc2, 0xaf, 0xc2, 0xb6, 0x5b, 0xc9, 0x8b, 0xe1, 0x9a, 0xae, 0xc3, - 0x9e, 0xc5, 0xa1, 0xcd, 0xb0, 0xc6, 0x87, 0xe1, 0x9a, 0xaa, 0xe1, 0x9a, 0xb8, 0xc7, - 0x94, 0xc6, 0xbc, 0xc7, 0xb4, 0xe1, 0x9b, 0x98, 0xc3, 0xbf, 0xc4, 0xbc, 0xcd, 0xb6, - 0xc4, 0x9b, 0xc4, 0xb7, 0xc2, 0xa9, 0xc7, 0x8e, 0xc3, 0xa0, 0xc3, 0x82, 0xc8, 0x9a, - 0xce, 0x89, 0xc6, 0xac, 0xc4, 0x94, 0xc3, 0x84, 0xc7, 0xb5, 0xce, 0x85, 0xc8, 0xa8, - 0xc3, 0x8c, 0xc8, 0x8d, 0xc2, 0xa8, 0xc8, 0x9a, 0xc9, 0x8e, 0xc8, 0xaa, 0xc3, 0x90, - 0xc7, 0x9d, 0xc8, 0xb3, 0xc4, 0x92, 0xc6, 0x83, 0x77, 0xc5, 0xa8, 0x52, 0xc4, 0xa4, - 0xc8, 0x91, 0xc6, 0xbd, 0xe1, 0x9a, 0xb6, 0xc7, 0xa8, 0xc3, 0xbf, 0xc7, 0x93, 0xe1, - 0x9b, 0x87, 0xe1, 0x9b, 0xad, 0x6f, 0xc8, 0xaa, 0xc6, 0xbb, 0xc6, 0xa3, 0xc7, 0xbe, - 0xc5, 0xb4, 0xe1, 0x9a, 0xab, 0xc7, 0xaa, 0xc7, 0x88, 0xc8, 0x85, 0xc6, 0xaa, 0xce, - 0x8c, 0xe1, 0x9b, 0x94, 0xc5, 0xb4, 0xc3, 0xa5, 0x66, 0x45, 0xc7, 0x80, 0xc5, 0x8f, - 0xc2, 0xb4, 0xc9, 0x8f, 0x39, 0xc3, 0x90, 0xc5, 0xa8, 0xc3, 0x91, 0xc6, 0x9e, 0xc8, - 0xb5, 0x72, 0xc6, 0x99, 0x5d, 0x2b, 0xc8, 0xb4, 0xc7, 0xbb, 0x79, 0xc5, 0xb8, 0xc6, - 0xb9, 0xc7, 0x9d, 0xc7, 0xb0, 0xe1, 0x9b, 0xa9, 0xe1, 0x9b, 0x92, 0xcd, 0xb6, 0xce, - 0x85, 0x42, 0xc2, 0xba, 0xc7, 0x99, 0xc7, 0x9c, 0xc5, 0x89, 0xc6, 0xbc, 0x29, 0xc2, - 0xb4, 0xc3, 0x8a, 0xc8, 0x81, 0xc3, 0x84, 0xc8, 0x92, 0xc3, 0x97, 0xe1, 0x9b, 0x91, - 0xc8, 0xa7, 0xc6, 0x99, 0xc4, 0x88, 0xe1, 0x9b, 0x9e, 0xc5, 0xab, 0xce, 0x88, 0xc5, - 0x93, 0xcd, 0xb1, 0xe2, 0xb1, 0xbc, 0xc5, 0xa0, 0xe1, 0x9b, 0x83, 0xc9, 0x80, 0xc4, - 0xbb, 0x24, 0xc6, 0x90, 0xc3, 0x8c, 0xc7, 0xa0, 0xc8, 0x9d, 0xc3, 0x8a, 0xc4, 0xa0, - 0xc6, 0xac, 0x72, 0xe1, 0x9b, 0x82, 0xe1, 0x9a, 0xba, 0xc3, 0x8f, 0x6c, 0xe1, 0x9a, - 0xb4, 0xc4, 0xbe, 0xc4, 0xaf, 0xc4, 0x9a, 0xc5, 0xa7, 0x41, 0xe2, 0xb1, 0xbf, 0xe2, - 0xb1, 0xb3, 0xc5, 0x8a, 0xe1, 0x9b, 0xa7, 0xc3, 0xa0, 0xc5, 0xaf, 0xc9, 0x8e, 0x35, - 0x34, 0xc2, 0xa3, 0xc5, 0xa4, 0xc2, 0xb3, 0xcd, 0xb1, 0xc9, 0x85, 0xc4, 0xa3, 0xe1, - 0x9b, 0x9f, 0xe1, 0x9b, 0x84, 0xc7, 0xa6, 0x5a, + 0xc7, 0x95, 0xc7, 0xa0, 0xe2, 0xb1, 0xb9, 0xc4, 0xb2, 0x36, 0x48, 0x2b, 0xc5, 0x93, + 0xc7, 0xb1, 0xc3, 0xbc, 0xc6, 0x9c, 0xc8, 0x98, 0xc5, 0xba, 0xe2, 0xb1, 0xa4, 0xc5, + 0x89, 0xc5, 0x9d, 0x2a, 0xc7, 0xa9, 0xe1, 0x9a, 0xb1, 0x7e, 0xc6, 0x98, 0xc7, 0xa2, + 0xc4, 0x85, 0xc8, 0xa3, 0xc8, 0xbb, 0xc6, 0x81, 0xc6, 0x9c, 0xc3, 0xb7, 0xc6, 0x98, + 0xc6, 0x8e, 0xce, 0x86, 0xc8, 0xa0, 0xce, 0x85, 0xe2, 0xb1, 0xb4, 0xc4, 0xaa, 0xc6, + 0xbb, 0xc5, 0xb1, 0xc8, 0x9f, 0x69, 0x21, 0xe1, 0x9a, 0xa8, 0xc4, 0xa3, 0x6f, 0xc3, + 0x93, 0xe1, 0x9b, 0x99, 0xc4, 0xa2, 0xcd, 0xb5, 0xe1, 0x9a, 0xa7, 0xc5, 0x82, 0x32, + 0xc5, 0x80, 0xc2, 0xb0, 0xc7, 0x82, 0x41, 0xc7, 0x90, 0xc8, 0xb8, 0xc6, 0xbe, 0xc5, + 0xa0, 0xc6, 0x8c, 0xe1, 0x9a, 0xb8, 0xc3, 0xb6, 0xc4, 0xb2, 0xc4, 0xa4, 0xc9, 0x84, + 0xc5, 0x8d, 0xc4, 0xb1, 0x54, 0xc7, 0x8f, 0xc8, 0x8b, 0x54, 0xe1, 0x9b, 0x9e, 0xc9, + 0x84, 0xe1, 0x9b, 0x82, 0xc8, 0xb5, 0x73, 0xc6, 0xa4, 0xc4, 0xa8, 0xc4, 0xba, 0xc7, + 0xa7, 0x26, 0x3d, 0xe2, 0xb1, 0xae, 0xc4, 0xbc, 0xc8, 0x91, 0xe1, 0x9a, 0xbe, 0xc6, + 0xb7, 0xc5, 0xb3, 0xc8, 0xad, 0xc6, 0xb4, 0xe1, 0x9a, 0xab, 0x44, 0x77, 0xc5, 0x93, + 0xc5, 0xab, 0xc3, 0xbb, 0xe1, 0x9a, 0xbe, 0xc4, 0x81, 0xc2, 0xbe, 0xc7, 0xbd, 0xcd, + 0xbc, 0x70, 0x45, 0xc5, 0x9a, 0xc9, 0x8d, 0x32, 0x76, 0xe1, 0x9b, 0x97, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0x8a, 0xc3, 0x81, 0xc8, 0xad, 0x4c, 0xc3, 0x89, 0xc6, 0xbd, 0xc4, + 0x93, 0xc7, 0x9c, 0x62, 0x4c, 0xe2, 0xb1, 0xa1, 0xcd, 0xbc, 0xc8, 0xb7, 0xe1, 0x9a, + 0xaf, 0xe1, 0x9a, 0xb9, 0xc3, 0xb2, 0xc5, 0xaa, 0xe1, 0x9b, 0xad, 0xc5, 0x8d, 0xce, + 0x8a, 0x6a, 0xc4, 0xbf, 0xc7, 0x8b, 0xc7, 0xa2, 0x7e, 0x6e, 0xe1, 0x9a, 0xb1, 0x47, + 0x2b, 0xc9, 0x82, 0xc7, 0x8b, 0xcd, 0xba, 0xc6, 0xaf, 0xc4, 0x91, 0xc6, 0x86, 0x52, + 0xe1, 0x9b, 0x9b, 0xc9, 0x8e, 0xe2, 0xb1, 0xbd, 0xc2, 0xbd, 0xc4, 0xb2, 0xc7, 0xb5, + 0xc5, 0xb0, 0xc8, 0xb6, 0xe2, 0xb1, 0xa6, 0xc6, 0x92, 0xc4, 0xbf, 0x4a, 0xc4, 0xa9, + 0xc6, 0xb2, 0xe1, 0x9b, 0x96, 0xc3, 0xa4, 0x70, 0x3d, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, + 0x93, 0xc6, 0xa3, 0x4d, 0xc7, 0xa6, 0xc3, 0x8c, 0xc6, 0x8e, 0xc7, 0xbd, 0xc3, 0x90, + 0x54, 0xc5, 0x9b, 0xe1, 0x9b, 0x94, 0x37, 0xc3, 0x89, 0x79, 0x49, 0xe1, 0x9b, 0x86, + 0xe1, 0x9b, 0xa2, 0xc6, 0x8b, 0xc8, 0xb6, 0xc3, 0x8b, 0xc7, 0x83, 0xc8, 0xa2, 0xc8, + 0x92, 0xc4, 0x9e, 0xc8, 0xa4, 0xc5, 0x80, 0xc7, 0xa6, 0xc6, 0x99, 0x24, 0xe1, 0x9b, + 0xa2, 0xc6, 0x8c, 0xe1, 0x9a, 0xac, 0x39, 0x21, 0xc2, 0xa9, 0xc7, 0x89, 0xe1, 0x9a, + 0xbe, 0xce, 0x8a, 0xc3, 0x86, 0xe1, 0x9b, 0xa4, 0xc7, 0xb6, 0xc3, 0x90, 0xc3, 0x97, + 0xc5, 0x99, 0xc7, 0x80, 0xc8, 0x93, 0xc2, 0xa5, 0xe1, 0x9b, 0x86, 0xc7, 0xb7, 0xc3, + 0x81, 0xc7, 0x8a, 0xe1, 0x9b, 0x9c, 0xe1, 0x9a, 0xaf, 0xc4, 0x84, 0xc2, 0xb7, 0xc6, + 0x8b, 0xc6, 0xab, 0xc8, 0xb0, 0xc3, 0xa7, 0xcd, 0xb1, 0xe1, 0x9a, 0xa2, 0xc8, 0x83, + 0xc6, 0xa8, 0xc6, 0xaf, 0xe2, 0xb1, 0xa1, 0xc3, 0xa2, 0xc7, 0xb5, 0xc9, 0x87, 0xc7, + 0x9c, 0xe1, 0x9a, 0xb1, 0xc5, 0x93, 0xe1, 0x9b, 0x95, 0xe2, 0xb1, 0xaa, 0xe1, 0x9b, + 0x8c, 0xc7, 0x99, 0xc6, 0xbe, 0x47, 0xc9, 0x83, 0xc5, 0xa5, 0xc5, 0x83, 0xe1, 0x9b, + 0x8b, 0xc8, 0xba, 0xc5, 0xb4, 0xc2, 0xb6, 0xe2, 0xb1, 0xa1, 0xce, 0x88, 0x36, 0x21, + 0xe2, 0xb1, 0xa6, 0xe1, 0x9b, 0x91, 0xc3, 0xa7, ], - asset_id: [ - 0x6e, 0x9c, 0x7f, 0x1a, 0x04, 0x56, 0x32, 0x4e, 0x21, 0x55, 0xab, 0x2b, 0x82, 0xd5, - 0x01, 0x11, 0x4a, 0x02, 0xc2, 0x93, 0x32, 0x96, 0x34, 0x29, 0x8e, 0x73, 0x8a, 0x62, - 0x62, 0x36, 0xb9, 0x9b, + asset_base: [ + 0x3d, 0x73, 0x41, 0xcb, 0xb2, 0xd0, 0x56, 0xd3, 0xfa, 0x50, 0x77, 0x09, 0xd2, 0x62, + 0x75, 0xff, 0xee, 0xff, 0xa1, 0x64, 0xa4, 0xcd, 0xc9, 0x0d, 0x52, 0xf3, 0x56, 0xaa, + 0x67, 0x8e, 0xc6, 0xb6, ], }, TestVector { @@ -933,48 +933,48 @@ pub(crate) fn test_vectors() -> Vec { 0x46, 0xbb, 0x13, 0x3e, ], description: [ - 0xc2, 0xbd, 0x65, 0x3c, 0xe1, 0x9a, 0xb6, 0xe1, 0x9a, 0xa2, 0xc7, 0x9e, 0xe1, 0x9a, - 0xb5, 0x5f, 0xe1, 0x9b, 0x97, 0x65, 0xc2, 0xa4, 0xc8, 0xb9, 0xe1, 0x9a, 0xb8, 0xc7, - 0xbf, 0xc3, 0xb9, 0x52, 0x46, 0xc7, 0x9d, 0xc6, 0x9f, 0xe1, 0x9a, 0xbc, 0xc5, 0x9c, - 0xe2, 0xb1, 0xb1, 0xc6, 0x8b, 0xc2, 0xa3, 0xc4, 0xa8, 0xc8, 0x9e, 0xc6, 0xaa, 0xc3, - 0xa2, 0xc3, 0x84, 0xc3, 0x9d, 0xe1, 0x9b, 0x97, 0xc4, 0x81, 0xe2, 0xb1, 0xb0, 0xc5, - 0xb9, 0x29, 0xc9, 0x89, 0x60, 0xe1, 0x9a, 0xbd, 0x5c, 0xc4, 0xbe, 0xc4, 0xb4, 0xc7, - 0xa1, 0xc4, 0x93, 0xc4, 0x8c, 0xe1, 0x9a, 0xb9, 0xc2, 0xb0, 0xcd, 0xbd, 0xce, 0x8c, - 0xc7, 0x88, 0xc6, 0x8c, 0xc6, 0x93, 0xc5, 0xa8, 0xe2, 0xb1, 0xa4, 0xc6, 0x84, 0x39, - 0xc5, 0x81, 0x53, 0xc4, 0xa9, 0xc2, 0xa7, 0xc4, 0x8f, 0xe1, 0x9a, 0xba, 0xc4, 0xaf, - 0xe1, 0x9b, 0x9d, 0xc6, 0xbb, 0xc2, 0xbc, 0xc7, 0x95, 0xc6, 0xb0, 0xe1, 0x9b, 0x8f, - 0x42, 0xc2, 0xbe, 0xc6, 0xa7, 0xc8, 0xbc, 0xcd, 0xb7, 0xc8, 0xa7, 0xc8, 0x8b, 0xc8, - 0xb7, 0xc6, 0xa1, 0xc4, 0x87, 0xc7, 0xa7, 0xc3, 0xb5, 0xe2, 0xb1, 0xa1, 0xc2, 0xb2, - 0xe1, 0x9b, 0xa5, 0xc5, 0x87, 0xe1, 0x9a, 0xb3, 0xc7, 0xb3, 0x7a, 0xc6, 0x8b, 0xc4, - 0xbe, 0xc4, 0x8e, 0x56, 0x2d, 0xc9, 0x84, 0xc4, 0x84, 0xc7, 0xa3, 0xe2, 0xb1, 0xb6, - 0x5e, 0x46, 0xc3, 0x8f, 0xc7, 0x94, 0xc5, 0xa7, 0xc8, 0xa2, 0xc4, 0xa0, 0xc5, 0xa1, - 0xe1, 0x9b, 0xa4, 0xe1, 0x9b, 0x9f, 0xc3, 0x87, 0xc3, 0xb4, 0xc3, 0x81, 0xc4, 0x86, - 0xc7, 0xb7, 0xc4, 0xb3, 0xc2, 0xb5, 0xc6, 0x8c, 0xc8, 0xa0, 0xc4, 0x9c, 0xc7, 0x9e, - 0x30, 0xcd, 0xb4, 0xc3, 0xb7, 0xe1, 0x9a, 0xb1, 0xe1, 0x9b, 0x86, 0xc5, 0xab, 0xc6, - 0xa3, 0xc3, 0x9c, 0xc7, 0xbe, 0xc3, 0xbf, 0xc2, 0xa1, 0xe1, 0x9b, 0x89, 0xe1, 0x9a, - 0xb8, 0xc6, 0xb7, 0xc6, 0x85, 0xc8, 0x93, 0xc3, 0x9f, 0xc7, 0xbe, 0x2e, 0xce, 0x88, - 0xc9, 0x86, 0xe2, 0xb1, 0xa6, 0xc3, 0x94, 0x58, 0xc5, 0x84, 0xc4, 0xa1, 0x7d, 0xc7, - 0x92, 0xe1, 0x9b, 0x81, 0xc7, 0xbc, 0xe1, 0x9b, 0x9d, 0xc4, 0xb8, 0xe1, 0x9a, 0xa9, - 0xe1, 0x9a, 0xa1, 0xc3, 0x8d, 0xc6, 0xb6, 0x51, 0xc4, 0xbc, 0xc5, 0x91, 0xe1, 0x9a, - 0xb4, 0xc9, 0x8d, 0xe1, 0x9a, 0xaf, 0xc9, 0x84, 0xc7, 0xb7, 0xc6, 0x96, 0x38, 0xc3, - 0x89, 0xc6, 0xa6, 0xe1, 0x9b, 0x98, 0xc3, 0x83, 0xc3, 0x99, 0xc6, 0x99, 0xe2, 0xb1, - 0xa1, 0xcd, 0xbd, 0xc3, 0x8d, 0xc9, 0x8f, 0x3a, 0xc4, 0x81, 0xe1, 0x9a, 0xac, 0x4b, - 0xc6, 0x94, 0xc6, 0x9c, 0xe2, 0xb1, 0xaf, 0xe1, 0x9a, 0xb8, 0xc8, 0xb1, 0x6f, 0x70, - 0xc3, 0xae, 0xe1, 0x9b, 0x8a, 0xc7, 0xab, 0xc5, 0xad, 0x57, 0xc3, 0xb2, 0x55, 0xc6, - 0xb1, 0xc6, 0x84, 0xc3, 0xa4, 0x61, 0xc8, 0x9e, 0xc2, 0xb6, 0xc7, 0x8f, 0xc8, 0x95, - 0x30, 0x29, 0xe1, 0x9a, 0xb8, 0xc6, 0xa5, 0xc8, 0x97, 0xc7, 0xa9, 0xc9, 0x8d, 0xc8, - 0xa3, 0xc8, 0x98, 0xc2, 0xb4, 0xc7, 0x8d, 0xc7, 0x8b, 0xc7, 0xbc, 0xe2, 0xb1, 0xbf, - 0xc2, 0xa1, 0x2b, 0xe1, 0x9a, 0xac, 0xc2, 0xb4, 0xc4, 0xa6, 0xc2, 0xa5, 0x6e, 0xc5, - 0xa5, 0xe1, 0x9b, 0x8f, 0x2d, 0xe1, 0x9a, 0xae, 0x2c, 0x61, 0xe1, 0x9b, 0xb0, 0xc7, - 0x84, 0xc4, 0x8e, 0x44, 0xc7, 0xb0, 0xce, 0x86, 0xc6, 0x97, 0xc4, 0xa6, 0xc3, 0x94, - 0xc6, 0xbb, 0x2e, 0xc5, 0x95, 0xc4, 0x86, 0xc8, 0x8f, 0xc7, 0x94, 0xc9, 0x8b, 0x7b, - 0xc4, 0x9c, 0xc5, 0xb2, 0xc5, 0x8a, 0xc5, 0x8d, 0x4a, 0xe1, 0x9a, 0xbe, 0xc8, 0x90, - 0xc8, 0x9f, 0x70, 0xe1, 0x9b, 0x93, 0xc7, 0xbe, + 0xc5, 0x9b, 0xc3, 0xb8, 0xc4, 0x89, 0xc3, 0xbd, 0xc8, 0xa6, 0xc6, 0x8e, 0xc4, 0xb9, + 0xe1, 0x9a, 0xb9, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0xb0, 0xc3, 0x99, 0x31, 0xe1, 0x9b, + 0x90, 0xc2, 0xb2, 0xc7, 0xa5, 0x7a, 0xe1, 0x9b, 0x88, 0xc8, 0x94, 0x35, 0x5d, 0xc5, + 0x9a, 0xc3, 0x9c, 0x55, 0xc6, 0x82, 0xc3, 0xb8, 0xc6, 0xaf, 0xc3, 0xb8, 0xc4, 0xab, + 0x25, 0xc4, 0x91, 0xc4, 0xb6, 0xce, 0x86, 0xc3, 0x80, 0xc2, 0xba, 0x40, 0xc9, 0x8a, + 0xc4, 0xa2, 0xc7, 0xb4, 0xc4, 0x8f, 0xe1, 0x9b, 0x90, 0xe1, 0x9b, 0xab, 0xc8, 0x83, + 0xc7, 0x97, 0x28, 0xc3, 0x9c, 0xc6, 0x9b, 0xc8, 0xbb, 0xc2, 0xa6, 0xc4, 0x81, 0xc5, + 0xac, 0xe1, 0x9a, 0xa0, 0xc2, 0xaf, 0xc9, 0x8e, 0xc2, 0xa9, 0xc6, 0xa7, 0xc8, 0xaf, + 0xc8, 0x86, 0xc8, 0xae, 0xc4, 0x8d, 0xe1, 0x9b, 0xb0, 0xc6, 0xa7, 0xc4, 0x81, 0xc2, + 0xa8, 0xc9, 0x87, 0xe1, 0x9a, 0xbf, 0xc5, 0xb5, 0xc8, 0xa1, 0xc4, 0x88, 0xc8, 0xb2, + 0xc7, 0x89, 0xc8, 0xb9, 0xc8, 0xa3, 0xe2, 0xb1, 0xb1, 0xc3, 0xb5, 0xc5, 0xaa, 0xc7, + 0x9f, 0xcd, 0xba, 0xc3, 0x8f, 0xc7, 0x9f, 0xcd, 0xb4, 0x42, 0xc7, 0xb2, 0xe1, 0x9a, + 0xa3, 0xc7, 0xbc, 0xe1, 0x9b, 0x93, 0xc8, 0xb9, 0xc7, 0xbd, 0xc2, 0xbb, 0xc5, 0x81, + 0xc5, 0xa7, 0xc6, 0x89, 0x69, 0xe1, 0x9b, 0x87, 0x32, 0xc9, 0x80, 0xcd, 0xba, 0xc5, + 0x9c, 0xe1, 0x9a, 0xbc, 0x2a, 0x57, 0xc7, 0x84, 0xc8, 0x95, 0xc8, 0xa6, 0xe2, 0xb1, + 0xa4, 0xc2, 0xab, 0xc4, 0xad, 0xe2, 0xb1, 0xb6, 0xc2, 0xb3, 0xe1, 0x9b, 0x92, 0xcd, + 0xbe, 0xc4, 0xa5, 0xc7, 0xbc, 0xc5, 0x87, 0xc8, 0xbe, 0xc3, 0xbc, 0xc3, 0xb8, 0xc6, + 0x8e, 0xc6, 0xba, 0x48, 0xe1, 0x9b, 0xa4, 0x57, 0xc4, 0x8f, 0xe2, 0xb1, 0xab, 0xc4, + 0x9d, 0xc7, 0xa0, 0xe1, 0x9a, 0xb2, 0x48, 0xc5, 0xba, 0xce, 0x87, 0xc7, 0x86, 0xc5, + 0xa6, 0xc2, 0xa7, 0xc7, 0x9d, 0xc6, 0x8c, 0xe1, 0x9a, 0xb0, 0x65, 0xc4, 0xb5, 0xc6, + 0xbb, 0xc7, 0x82, 0xc4, 0xb3, 0xc4, 0x98, 0xc3, 0x85, 0x24, 0xe1, 0x9a, 0xa9, 0xc4, + 0x83, 0xc6, 0xba, 0xc3, 0xaa, 0xc5, 0xa0, 0xc4, 0x9e, 0x5f, 0x59, 0xc3, 0x90, 0x59, + 0xc2, 0xb2, 0xc6, 0xa9, 0xcd, 0xb5, 0xe1, 0x9a, 0xa0, 0xc4, 0x83, 0xc6, 0x92, 0xe2, + 0xb1, 0xb4, 0xc3, 0x98, 0xc6, 0xa8, 0xc6, 0x90, 0xe1, 0x9b, 0x8d, 0xc8, 0x93, 0xc4, + 0xac, 0xc8, 0x93, 0xc7, 0xae, 0xe1, 0x9a, 0xa9, 0xc3, 0xa9, 0xc6, 0x8f, 0xc5, 0x93, + 0xc8, 0x84, 0xe1, 0x9b, 0xad, 0xe2, 0xb1, 0xb7, 0xe1, 0x9b, 0x97, 0xc3, 0x87, 0xe1, + 0x9b, 0x89, 0xc3, 0x91, 0x46, 0x4f, 0xc5, 0x9d, 0xc9, 0x8e, 0xc5, 0x99, 0xc6, 0x9b, + 0xe1, 0x9a, 0xbb, 0xe1, 0x9b, 0xa8, 0x51, 0xc6, 0x8d, 0xc3, 0x8b, 0xc2, 0xa7, 0xc3, + 0xb6, 0xc8, 0x82, 0xc7, 0x8b, 0xc8, 0xb2, 0x6b, 0xc5, 0x9e, 0xc9, 0x8b, 0xc6, 0x84, + 0xc6, 0xac, 0xc4, 0xa7, 0xe1, 0x9b, 0xa7, 0xc3, 0xb6, 0xc7, 0xb2, 0xc3, 0x9a, 0xc6, + 0xab, 0xc3, 0x86, 0xc6, 0xa8, 0x52, 0xe1, 0x9a, 0xba, 0x2a, 0xe1, 0x9b, 0x90, 0xc4, + 0xb7, 0xc3, 0x9f, 0xc4, 0x8d, 0xc8, 0xba, 0xc7, 0x86, 0xc8, 0x95, 0xe1, 0x9b, 0x9a, + 0x40, 0xc3, 0xa9, 0xe1, 0x9a, 0xbe, 0xc8, 0xa6, 0xc8, 0xab, 0xc5, 0x90, 0xce, 0x86, + 0xe2, 0xb1, 0xad, 0xc3, 0xa5, 0xe1, 0x9b, 0xa9, 0xc5, 0x84, 0xc4, 0xbf, 0xc3, 0x88, + 0xc7, 0x8b, 0xe1, 0x9a, 0xad, 0xc8, 0x90, 0xc7, 0xbb, 0xe2, 0xb1, 0xa2, 0xc6, 0xaf, + 0xc2, 0xa7, 0xc3, 0xb4, 0xc6, 0x8e, 0x56, 0xc8, 0x80, 0xc6, 0x86, 0xe1, 0x9a, 0xa7, + 0xc6, 0xbc, 0xc2, 0xba, 0xc6, 0xb7, 0xc5, 0x99, ], - asset_id: [ - 0x54, 0xf5, 0xc9, 0x10, 0x86, 0xc5, 0x19, 0xcf, 0x5a, 0xa9, 0xc7, 0x4f, 0x07, 0x7c, - 0x07, 0xbc, 0xf7, 0xd7, 0x24, 0x35, 0x20, 0xe1, 0x4d, 0x2e, 0x27, 0x12, 0x79, 0x7c, - 0x74, 0xd2, 0x0e, 0x22, + asset_base: [ + 0x39, 0xa7, 0x8f, 0x76, 0x63, 0x81, 0xec, 0x69, 0xd9, 0x2e, 0x8c, 0xa6, 0xb6, 0x4e, + 0x92, 0x10, 0xe9, 0x94, 0x28, 0x32, 0x9f, 0xde, 0x85, 0xb2, 0xe1, 0xfb, 0xb7, 0x35, + 0x70, 0x86, 0x7a, 0xb2, ], }, TestVector { @@ -984,48 +984,48 @@ pub(crate) fn test_vectors() -> Vec { 0x59, 0x44, 0x2d, 0x11, ], description: [ - 0xc4, 0xaa, 0xe1, 0x9a, 0xb7, 0xc3, 0x99, 0xc6, 0x90, 0xc6, 0x96, 0xc3, 0x9b, 0x54, - 0xc9, 0x8c, 0xc8, 0x91, 0xc7, 0xba, 0xc2, 0xb9, 0xc7, 0x9b, 0xe2, 0xb1, 0xa8, 0xc3, - 0xa5, 0xc3, 0x87, 0xc9, 0x80, 0xc7, 0xbe, 0xe1, 0x9b, 0x97, 0xc5, 0x92, 0xc7, 0xa5, - 0xc8, 0x8e, 0xc7, 0x97, 0xe2, 0xb1, 0xb9, 0x49, 0xc8, 0xb4, 0xc7, 0xa8, 0x5e, 0xc5, - 0x8d, 0x5d, 0xc8, 0xbb, 0xce, 0x86, 0x29, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0x91, 0xc3, - 0x94, 0x46, 0xc8, 0x9a, 0xce, 0x84, 0xc7, 0x96, 0xe2, 0xb1, 0xb8, 0xc8, 0xa7, 0xc8, - 0xbb, 0xe2, 0xb1, 0xac, 0xe2, 0xb1, 0xbf, 0xc5, 0x80, 0xc2, 0xae, 0xc3, 0x85, 0xc6, - 0xaf, 0xc8, 0xbe, 0xc6, 0xb9, 0xe2, 0xb1, 0xb4, 0x66, 0xe1, 0x9a, 0xa1, 0x36, 0xc5, - 0x95, 0xc3, 0xb5, 0xe2, 0xb1, 0xbe, 0xc7, 0x89, 0xe1, 0x9a, 0xa5, 0xc7, 0xa0, 0x34, - 0xc9, 0x87, 0xe2, 0xb1, 0xac, 0xe2, 0xb1, 0xa9, 0xc7, 0x99, 0xc3, 0xa4, 0xe1, 0x9b, - 0x89, 0xc3, 0x9e, 0xc9, 0x89, 0xc3, 0xa5, 0xc3, 0xb1, 0xc3, 0x9e, 0xe2, 0xb1, 0xb4, - 0xc8, 0x87, 0x69, 0xc8, 0x81, 0xc3, 0x81, 0xc8, 0x9c, 0xc7, 0x80, 0xe1, 0x9b, 0x9a, - 0xe1, 0x9b, 0xa4, 0x49, 0xc7, 0x97, 0x6e, 0x6f, 0xe1, 0x9b, 0x80, 0xc7, 0xa5, 0x5d, - 0x3d, 0xc3, 0xab, 0xc5, 0x88, 0xc3, 0x8c, 0xe2, 0xb1, 0xb5, 0xc4, 0xa2, 0xe2, 0xb1, - 0xa7, 0xe1, 0x9b, 0xad, 0xc6, 0xb0, 0xe1, 0x9b, 0x8f, 0xc6, 0x97, 0xe2, 0xb1, 0xb8, - 0xc2, 0xa9, 0xc7, 0xb0, 0xe2, 0xb1, 0xbd, 0x65, 0xc3, 0xb3, 0xe2, 0xb1, 0xaa, 0xc6, - 0xb3, 0xc5, 0x96, 0xc5, 0xbd, 0xe2, 0xb1, 0xb6, 0xe2, 0xb1, 0xb5, 0xe1, 0x9a, 0xb2, - 0xc5, 0xb5, 0x61, 0x28, 0x58, 0xc5, 0x80, 0x74, 0x5b, 0xc8, 0xa8, 0xe2, 0xb1, 0xb7, - 0x30, 0x6a, 0xc3, 0xaa, 0xe1, 0x9b, 0x9e, 0xc8, 0x9b, 0x33, 0x54, 0xc6, 0xad, 0xc6, - 0x99, 0xc4, 0x9b, 0xc7, 0x87, 0xe1, 0x9b, 0xb0, 0xc7, 0x9a, 0xc7, 0x99, 0xc6, 0xa4, - 0xc6, 0xb8, 0xe2, 0xb1, 0xb7, 0xc7, 0x93, 0x60, 0xe1, 0x9b, 0x9e, 0xc7, 0x98, 0xc8, - 0xa8, 0xce, 0x86, 0xe1, 0x9a, 0xb2, 0xc6, 0xaf, 0xc3, 0xb7, 0xc3, 0x81, 0xc7, 0x89, - 0xc7, 0x93, 0x25, 0xc7, 0xaf, 0xc4, 0x9c, 0xe2, 0xb1, 0xba, 0xe1, 0x9b, 0x90, 0xe1, - 0x9b, 0xa8, 0xc7, 0xbe, 0xc3, 0xb9, 0xc7, 0xb4, 0xc5, 0xb1, 0xe2, 0xb1, 0xa3, 0xcd, - 0xb6, 0xc5, 0x8d, 0x76, 0xc5, 0xb9, 0xe2, 0xb1, 0xae, 0x4e, 0x36, 0xc8, 0xa1, 0x50, - 0xc6, 0x95, 0xc4, 0x84, 0xc8, 0x94, 0xe1, 0x9b, 0x9f, 0xc8, 0x9e, 0xc7, 0x85, 0xcd, - 0xb0, 0xc4, 0xb3, 0x58, 0xc6, 0x98, 0xc4, 0xb0, 0xc8, 0x99, 0xe2, 0xb1, 0xb6, 0xc5, - 0xa4, 0xc6, 0x84, 0xc6, 0xbd, 0xc6, 0x96, 0xe2, 0xb1, 0xb7, 0xc5, 0xb7, 0xc6, 0xaa, - 0xc8, 0x85, 0x70, 0xc7, 0xbe, 0xc4, 0xb4, 0xe1, 0x9a, 0xba, 0x30, 0xc8, 0xae, 0xe2, - 0xb1, 0xb3, 0x32, 0xc3, 0x89, 0xe2, 0xb1, 0xa1, 0xc3, 0x90, 0xc5, 0xba, 0xe1, 0x9b, - 0xa2, 0xc3, 0xb3, 0xe1, 0x9b, 0xa8, 0xce, 0x86, 0xc6, 0xb2, 0x29, 0x5e, 0xc8, 0xb7, - 0xc5, 0x8a, 0xc3, 0xa1, 0xc7, 0xac, 0xc5, 0x96, 0xc3, 0x8c, 0xc2, 0xaa, 0xc6, 0xb0, - 0xc8, 0x84, 0x5d, 0xc8, 0x8a, 0xc2, 0xaf, 0xc5, 0x90, 0x51, 0xe1, 0x9b, 0xa3, 0xc7, - 0x92, 0xc3, 0x9a, 0xc8, 0x81, 0xc8, 0xa5, 0x61, 0xc8, 0x95, 0xc7, 0x96, 0xe2, 0xb1, - 0xa3, 0xc8, 0xb5, 0xe1, 0x9a, 0xa6, 0xc4, 0xb1, 0xe1, 0x9b, 0xac, 0xc7, 0xaf, 0x2b, - 0xe1, 0x9b, 0x8b, 0xc4, 0xa0, 0xc7, 0xa1, 0xc7, 0xb6, 0xc6, 0x81, 0xc3, 0xb5, 0xe2, - 0xb1, 0xb4, 0xc2, 0xa1, 0xe2, 0xb1, 0xb2, 0x5a, + 0xc6, 0xbd, 0xc2, 0xa5, 0x6f, 0xe2, 0xb1, 0xb0, 0x64, 0xc5, 0xb2, 0x39, 0xc8, 0x9d, + 0xcd, 0xb0, 0xc3, 0x8d, 0xc5, 0xa5, 0xc7, 0xb7, 0xe1, 0x9b, 0xa5, 0xcd, 0xb4, 0xcd, + 0xb6, 0xc6, 0x96, 0xc5, 0xa2, 0xe1, 0x9b, 0x87, 0x68, 0xe1, 0x9a, 0xb2, 0xe1, 0x9b, + 0xa0, 0xc4, 0x99, 0xe1, 0x9a, 0xa5, 0xc9, 0x8f, 0x61, 0xe2, 0xb1, 0xa7, 0xc5, 0x8b, + 0xc4, 0xbb, 0xe1, 0x9a, 0xb9, 0xc8, 0xab, 0xc6, 0x99, 0xc7, 0xaa, 0x21, 0xcd, 0xbc, + 0xc4, 0xa6, 0xc2, 0xb4, 0xe1, 0x9b, 0x9b, 0x52, 0x7a, 0xc2, 0xb1, 0xc7, 0x97, 0x5a, + 0xc6, 0xba, 0xc6, 0xb5, 0xc5, 0xbd, 0xc6, 0xb3, 0xc2, 0xb9, 0xc3, 0xac, 0xc8, 0x93, + 0xe1, 0x9a, 0xa7, 0xc6, 0x80, 0xc6, 0x86, 0xce, 0x86, 0xc7, 0x86, 0xc4, 0xa9, 0xc5, + 0x9b, 0x4d, 0x21, 0xc8, 0xa8, 0x2b, 0xc6, 0x9b, 0xc3, 0x9f, 0xe1, 0x9a, 0xbf, 0x60, + 0xe1, 0x9b, 0x86, 0xe2, 0xb1, 0xbc, 0xcd, 0xb1, 0xc5, 0xb1, 0xc4, 0xa3, 0x21, 0xc6, + 0xb2, 0xc4, 0x95, 0xc2, 0xbe, 0xe1, 0x9b, 0x93, 0xc6, 0x88, 0xe1, 0x9a, 0xa9, 0xc7, + 0xbb, 0xc7, 0xb4, 0xc3, 0x84, 0xc9, 0x8e, 0xc7, 0xb3, 0x43, 0xc8, 0x87, 0xce, 0x85, + 0x55, 0xc3, 0xbd, 0xc3, 0x9c, 0xc7, 0x81, 0xc6, 0x9b, 0xc6, 0xa1, 0x6b, 0xc5, 0x9e, + 0xc6, 0xa1, 0xc5, 0xaa, 0x6e, 0xc5, 0xbc, 0xc4, 0xb0, 0xc8, 0x84, 0xc9, 0x80, 0xc7, + 0xb3, 0xc5, 0xb3, 0xc9, 0x88, 0x33, 0xc4, 0x83, 0xe1, 0x9b, 0x8c, 0xc9, 0x86, 0x6d, + 0xc8, 0xa5, 0xc3, 0xaf, 0xe1, 0x9b, 0xa0, 0xc2, 0xb1, 0xe2, 0xb1, 0xba, 0xc5, 0xae, + 0x3e, 0x79, 0xc4, 0xa4, 0xe1, 0x9b, 0xad, 0x33, 0xc7, 0xaa, 0xc4, 0x8c, 0xc8, 0xb6, + 0xe2, 0xb1, 0xa8, 0xe2, 0xb1, 0xb2, 0xe1, 0x9b, 0x94, 0xc8, 0x8e, 0xc5, 0xb2, 0xc4, + 0xb5, 0xc4, 0xad, 0xc8, 0xb5, 0xc7, 0xa5, 0xe2, 0xb1, 0xbd, 0x3b, 0xe1, 0x9b, 0x9f, + 0xc6, 0x8d, 0xc5, 0x84, 0xe1, 0x9b, 0xae, 0xc5, 0x8d, 0x23, 0x6f, 0x6f, 0xc5, 0x83, + 0xc5, 0xa7, 0xc4, 0x84, 0xc8, 0xa4, 0xc4, 0xb2, 0xc5, 0xba, 0xe2, 0xb1, 0xa5, 0xc8, + 0xa2, 0x3f, 0xc8, 0x86, 0xc8, 0x8b, 0xe1, 0x9b, 0x9e, 0xc5, 0x91, 0xe1, 0x9a, 0xaf, + 0xe1, 0x9b, 0x9b, 0xc4, 0xb7, 0xc6, 0x97, 0xc7, 0xbb, 0xe1, 0x9b, 0x9c, 0xc7, 0xa8, + 0xc7, 0x9a, 0xe1, 0x9b, 0xab, 0xc4, 0x93, 0x2f, 0xc6, 0xa3, 0xc6, 0x9d, 0xc6, 0xa6, + 0xc3, 0x86, 0xe1, 0x9b, 0x89, 0xc5, 0x84, 0xc6, 0x92, 0xc7, 0xa9, 0xc7, 0x91, 0xc5, + 0x99, 0xc6, 0x88, 0xc5, 0x98, 0x71, 0xe2, 0xb1, 0xa6, 0xcd, 0xbe, 0x5c, 0xc6, 0x8a, + 0xc3, 0xae, 0xc4, 0x80, 0xe1, 0x9a, 0xa6, 0x2d, 0xc6, 0x83, 0xc6, 0xa0, 0xc8, 0x8c, + 0xc7, 0xa9, 0xc6, 0xb1, 0xe1, 0x9b, 0x81, 0xe2, 0xb1, 0xb5, 0xc7, 0x8b, 0x43, 0xc8, + 0xad, 0xc4, 0xa4, 0xc7, 0x81, 0xc2, 0xbc, 0x4b, 0xc6, 0xb5, 0x67, 0xc2, 0xa2, 0xcd, + 0xba, 0xc6, 0xaa, 0xc2, 0xb8, 0xe1, 0x9b, 0xa5, 0x3c, 0xcd, 0xba, 0xc4, 0x94, 0xe2, + 0xb1, 0xaa, 0xe2, 0xb1, 0xbf, 0x48, 0x45, 0xc7, 0xba, 0xc5, 0xa0, 0xc2, 0xae, 0x2b, + 0xc2, 0xb7, 0xc6, 0xad, 0xc4, 0xa5, 0xc4, 0x93, 0xe1, 0x9a, 0xbd, 0xc3, 0xb2, 0xe1, + 0x9a, 0xa7, 0x66, 0xc7, 0x8b, 0xc2, 0xa7, 0x5c, 0xc7, 0x96, 0xc4, 0xb2, 0xe1, 0x9a, + 0xbc, 0xe2, 0xb1, 0xab, 0x43, 0xc9, 0x8f, 0xc5, 0x8e, 0x58, 0xe1, 0x9a, 0xa9, 0xe1, + 0x9b, 0x96, 0x59, 0xc5, 0x93, 0xe1, 0x9b, 0x89, 0xc7, 0xb1, 0xe1, 0x9a, 0xaf, 0xc9, + 0x82, 0xe2, 0xb1, 0xaf, 0xc7, 0xb4, 0xc4, 0xa5, 0x62, 0xc8, 0x93, 0xc5, 0xae, 0xc4, + 0xae, 0xce, 0x8c, 0xc8, 0xa8, 0xe1, 0x9a, 0xa0, ], - asset_id: [ - 0x9d, 0xf4, 0x24, 0x6f, 0x24, 0x26, 0xa5, 0xd4, 0x87, 0xb1, 0xc9, 0x7d, 0x71, 0x92, - 0xf6, 0x90, 0x79, 0x85, 0x5d, 0x30, 0x08, 0xde, 0x89, 0x7b, 0xf0, 0x57, 0x06, 0xb4, - 0x5b, 0xe3, 0xe3, 0xae, + asset_base: [ + 0xca, 0x81, 0x0e, 0x15, 0xe1, 0x48, 0x19, 0x50, 0xde, 0x77, 0xab, 0x5f, 0x02, 0xa1, + 0xa6, 0x37, 0xf0, 0x5c, 0x3f, 0x12, 0x64, 0xbb, 0x93, 0x65, 0xf5, 0x0a, 0x91, 0x10, + 0x4d, 0x52, 0x2b, 0x9e, ], }, ] diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 35cc1acbf..02c9cfc78 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -17,6 +17,7 @@ pub(crate) struct TestVector { pub(crate) internal_ivk: [u8; 32], pub(crate) internal_ovk: [u8; 32], pub(crate) internal_dk: [u8; 32], + pub(crate) asset: [u8; 32], pub(crate) note_v: u64, pub(crate) note_rho: [u8; 32], pub(crate) note_rseed: [u8; 32], @@ -106,6 +107,11 @@ pub(crate) fn test_vectors() -> Vec { 0xfc, 0x27, 0x59, 0xd4, 0xf4, 0xd6, 0x84, 0xb2, 0xc5, 0x05, 0x6d, 0x5b, 0x17, 0x7a, 0xf0, 0xfa, 0x8a, 0xa9, ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], note_v: 15643327852135767324, note_rho: [ 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, @@ -207,6 +213,11 @@ pub(crate) fn test_vectors() -> Vec { 0x9e, 0xca, 0x3c, 0x00, 0xd3, 0x98, 0xae, 0xde, 0x1f, 0xdc, 0x2a, 0xbf, 0xfc, 0x88, 0x35, 0x38, 0x59, 0xaf, ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], note_v: 4481649511318637270, note_rho: [ 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, @@ -308,6 +319,11 @@ pub(crate) fn test_vectors() -> Vec { 0x68, 0xc6, 0x3c, 0x36, 0xf3, 0x32, 0xe7, 0x45, 0x57, 0xe9, 0x16, 0x05, 0x0f, 0x0b, 0x91, 0x11, 0x17, 0x9b, ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], note_v: 14496603531126387959, note_rho: [ 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, @@ -409,6 +425,11 @@ pub(crate) fn test_vectors() -> Vec { 0xc7, 0x5e, 0xe4, 0x21, 0xb4, 0x20, 0x4b, 0xb6, 0xf3, 0xc5, 0xd0, 0xfc, 0x43, 0x28, 0x49, 0xaa, 0x71, 0x61, ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], note_v: 6792346249443327211, note_rho: [ 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, 0xbc, @@ -510,6 +531,11 @@ pub(crate) fn test_vectors() -> Vec { 0x70, 0xeb, 0xd0, 0x55, 0xe4, 0xc7, 0xfd, 0x91, 0xc0, 0x20, 0xff, 0x43, 0x46, 0x1d, 0x14, 0xe0, 0x2f, 0x29, ], + asset: [ + 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, + 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, + 0x7a, 0x59, 0x70, 0x2f, + ], note_v: 4079549063511228677, note_rho: [ 0x26, 0x70, 0xdc, 0x82, 0xd3, 0x90, 0x26, 0xc6, 0xcb, 0x4c, 0xd4, 0xb0, 0xf7, 0xf5, @@ -611,6 +637,11 @@ pub(crate) fn test_vectors() -> Vec { 0xa2, 0x2c, 0x49, 0x1d, 0xc0, 0x9e, 0x1b, 0x12, 0x0f, 0x66, 0x93, 0xd6, 0x86, 0xec, 0xd4, 0x03, 0x0a, 0x00, ], + asset: [ + 0xaa, 0xce, 0xb5, 0x62, 0x18, 0xc6, 0xbd, 0x30, 0xf8, 0x37, 0x4a, 0xc1, 0x33, 0x86, + 0x79, 0x3f, 0x21, 0xa9, 0xfb, 0x80, 0xad, 0x03, 0xbc, 0x0c, 0xda, 0x4a, 0x44, 0x94, + 0x6c, 0x00, 0xe1, 0xb1, + ], note_v: 5706402952489856202, note_rho: [ 0xa1, 0xdf, 0x0e, 0x5b, 0x87, 0xb5, 0xbe, 0xce, 0x47, 0x7a, 0x70, 0x96, 0x49, 0xe9, @@ -623,14 +654,14 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x08, 0xcb, 0x05, ], note_cmx: [ - 0x63, 0xce, 0xe3, 0x7e, 0x3c, 0x7b, 0x4e, 0x6c, 0xc9, 0x39, 0xa2, 0xe6, 0x3a, 0xda, - 0x74, 0xf8, 0x5e, 0xa4, 0x8b, 0xa0, 0x7a, 0x4f, 0x92, 0xcc, 0xbd, 0x34, 0xfa, 0xa4, - 0x2d, 0xfd, 0x49, 0x16, + 0x71, 0x99, 0x1e, 0xeb, 0x4b, 0x51, 0x7e, 0xd9, 0xd4, 0x31, 0xdc, 0xa9, 0xa2, 0xbb, + 0xcf, 0x1c, 0xe8, 0x75, 0xe8, 0x55, 0xdf, 0xf4, 0x8c, 0x69, 0xf4, 0xef, 0x51, 0x01, + 0x1e, 0x86, 0x1e, 0x07, ], note_nf: [ - 0x4c, 0x99, 0xbf, 0xa8, 0xc2, 0x0d, 0xba, 0x59, 0xbb, 0x73, 0x47, 0xda, 0x16, 0xc4, - 0x3b, 0x73, 0xc8, 0x87, 0x94, 0xc9, 0xeb, 0xcd, 0x0d, 0xd2, 0xb2, 0x5e, 0xe7, 0xbb, - 0x83, 0x6f, 0x95, 0x20, + 0xdf, 0x79, 0xd4, 0xa4, 0x6e, 0xca, 0xfd, 0x34, 0x50, 0x9d, 0x41, 0xfc, 0xfb, 0x61, + 0x3e, 0x1f, 0xdc, 0xbc, 0x0d, 0x3b, 0xa0, 0xaa, 0x8d, 0xe5, 0x04, 0xd6, 0xf2, 0x54, + 0xcd, 0x55, 0x12, 0x32, ], }, TestVector { @@ -712,329 +743,349 @@ pub(crate) fn test_vectors() -> Vec { 0xe6, 0xb8, 0xf6, 0xd1, 0x0a, 0x74, 0x7f, 0xed, 0x2a, 0x1c, 0x91, 0xcb, 0xe1, 0x42, 0x47, 0x5c, 0x30, 0x82, ], + asset: [ + 0x23, 0x6c, 0x29, 0xaf, 0x39, 0x23, 0x10, 0x17, 0x56, 0xd9, 0xfa, 0x4b, 0xd0, 0xf7, + 0xd2, 0xdd, 0xaa, 0xcb, 0x6b, 0x0f, 0x86, 0xa2, 0x65, 0x8e, 0x0a, 0x07, 0xa0, 0x5a, + 0xc5, 0xb9, 0x50, 0x05, + ], note_v: 2558469029534639129, note_rho: [ - 0x72, 0x2d, 0xb0, 0x41, 0xa3, 0xef, 0x66, 0xfa, 0x48, 0x3a, 0xfd, 0x3c, 0x2e, 0x19, - 0xe5, 0x94, 0x44, 0xa6, 0x4a, 0xdd, 0x6d, 0xf1, 0xd9, 0x63, 0xf5, 0xdd, 0x5b, 0x50, - 0x10, 0xd3, 0xd0, 0x25, + 0x34, 0x10, 0x80, 0x6e, 0xa6, 0xf2, 0x88, 0xf8, 0x73, 0x6c, 0x23, 0x35, 0x7c, 0x85, + 0xf4, 0x57, 0x91, 0xe1, 0x70, 0x80, 0x29, 0xd9, 0x82, 0x4d, 0x90, 0x70, 0x46, 0x07, + 0xf3, 0x87, 0xa0, 0x3e, ], note_rseed: [ - 0xf0, 0x28, 0x7c, 0x4c, 0xf1, 0x9c, 0x75, 0xf3, 0x3d, 0x51, 0xdd, 0xdd, 0xba, 0x5d, - 0x65, 0x7b, 0x43, 0xee, 0x8d, 0xa6, 0x45, 0x44, 0x38, 0x14, 0xcc, 0x73, 0x29, 0xf3, - 0xe9, 0xb4, 0xe5, 0x4c, + 0x49, 0xbf, 0x98, 0x36, 0x57, 0x44, 0x31, 0x34, 0x5a, 0x78, 0x77, 0xef, 0xaa, 0x8a, + 0x08, 0xe7, 0x30, 0x81, 0xef, 0x8d, 0x62, 0xcb, 0x78, 0x0a, 0xb6, 0x88, 0x3a, 0x50, + 0xa0, 0xd4, 0x70, 0x19, ], note_cmx: [ - 0x1e, 0x61, 0x9e, 0x46, 0xbb, 0x62, 0xb6, 0x1d, 0x4e, 0x1c, 0xf3, 0x62, 0x2e, 0xa7, - 0x0a, 0x90, 0x8d, 0xe7, 0xf0, 0x76, 0xec, 0xf8, 0x7f, 0x54, 0x1e, 0x0b, 0x7b, 0x48, - 0xad, 0x4a, 0x26, 0x01, + 0x94, 0x81, 0xcb, 0xac, 0x4e, 0xb0, 0xc0, 0x8d, 0x12, 0x83, 0x47, 0x13, 0xb5, 0x15, + 0xfd, 0x8c, 0x61, 0x0d, 0x44, 0xc1, 0x29, 0x50, 0x97, 0xcc, 0x20, 0x13, 0x4d, 0xe2, + 0x1c, 0x63, 0x6c, 0x29, ], note_nf: [ - 0x3b, 0x94, 0x8d, 0xb2, 0x16, 0x08, 0xe9, 0xac, 0xb2, 0x2a, 0x54, 0x17, 0xb9, 0x8c, - 0x0d, 0xed, 0xd5, 0x27, 0xa9, 0x64, 0x87, 0x81, 0x4e, 0x64, 0x20, 0xcb, 0xff, 0x6e, - 0x4e, 0xee, 0x4e, 0x31, + 0x44, 0xc8, 0x8d, 0x03, 0x10, 0x21, 0x56, 0x11, 0x25, 0x6a, 0xad, 0x07, 0x34, 0x99, + 0x43, 0x08, 0x94, 0x59, 0x73, 0x17, 0x15, 0x75, 0xae, 0x7e, 0x89, 0xf5, 0x8d, 0x44, + 0xde, 0xa2, 0x67, 0x10, ], }, TestVector { sk: [ - 0x23, 0x6c, 0x29, 0xaf, 0x39, 0x23, 0x10, 0x17, 0x56, 0xd9, 0xfa, 0x4b, 0xd0, 0xf7, - 0xd2, 0xdd, 0xaa, 0xcb, 0x6b, 0x0f, 0x86, 0xa2, 0x65, 0x8e, 0x0a, 0x07, 0xa0, 0x5a, - 0xc5, 0xb9, 0x50, 0x05, + 0x0d, 0xfb, 0xa1, 0x0a, 0x85, 0x7f, 0x82, 0x84, 0x2d, 0x38, 0x25, 0xb3, 0xd6, 0xda, + 0x05, 0x73, 0xd3, 0x16, 0xeb, 0x16, 0x0d, 0xc0, 0xb7, 0x16, 0xc4, 0x8f, 0xbd, 0x46, + 0x7f, 0x75, 0xb7, 0x80, ], ask: [ - 0xb4, 0xde, 0xd9, 0x0d, 0x62, 0x11, 0x7f, 0x18, 0xf3, 0xdd, 0x5f, 0xdb, 0x22, 0x23, - 0x8a, 0x35, 0xca, 0x37, 0xc4, 0x0f, 0xee, 0xc8, 0x45, 0xce, 0x5f, 0xc2, 0x7f, 0xe8, - 0xbc, 0xa5, 0xef, 0x0f, + 0x10, 0x10, 0x16, 0x60, 0x30, 0x07, 0x06, 0x52, 0x6a, 0x03, 0xb2, 0x63, 0x24, 0x13, + 0x5b, 0xbd, 0xd2, 0x33, 0xfc, 0xf6, 0x96, 0xca, 0x7f, 0xd2, 0x12, 0xf2, 0x82, 0x55, + 0x9e, 0x78, 0x12, 0x3b, ], ak: [ - 0x4e, 0xfd, 0x5a, 0x2e, 0xf1, 0xff, 0xa9, 0x9a, 0x0f, 0xf6, 0x2b, 0x76, 0x7d, 0x44, - 0xb3, 0x65, 0x1f, 0xfa, 0x1c, 0x69, 0x69, 0x15, 0xac, 0x00, 0xa2, 0x5e, 0xa3, 0xac, - 0x7d, 0xff, 0x99, 0x01, + 0xeb, 0x1e, 0xd7, 0xf9, 0x37, 0x17, 0xd5, 0xdf, 0x15, 0xdd, 0xb6, 0xb2, 0xb2, 0xb0, + 0x17, 0x76, 0xf9, 0xa1, 0x91, 0xfb, 0x08, 0xa6, 0x8a, 0xe1, 0x32, 0x4f, 0x29, 0x13, + 0xe0, 0x6f, 0xa7, 0x10, ], isk: [ - 0x3d, 0xa9, 0x08, 0x88, 0xba, 0x18, 0x24, 0xc8, 0x16, 0x29, 0x2d, 0x7f, 0x17, 0x33, - 0xac, 0x4c, 0xbe, 0x72, 0x2c, 0x6a, 0x12, 0x1c, 0xc7, 0x80, 0x17, 0x06, 0x26, 0xb7, - 0x0a, 0x26, 0x95, 0x28, + 0x90, 0x16, 0x58, 0x59, 0x87, 0x32, 0xd6, 0x5b, 0xea, 0x90, 0x17, 0xdb, 0x74, 0x38, + 0x76, 0xc5, 0x86, 0xbc, 0xa7, 0x45, 0x54, 0xd7, 0x60, 0xf4, 0x9b, 0xa6, 0x59, 0xe4, + 0xe2, 0x1c, 0xbb, 0x14, ], ik: [ - 0x16, 0xa8, 0xff, 0x29, 0xb5, 0x17, 0xb5, 0xa8, 0xf7, 0xd0, 0x9b, 0x4e, 0x5e, 0x71, - 0x3a, 0x9a, 0x78, 0x4c, 0x74, 0x04, 0xd6, 0x1e, 0x3a, 0xf5, 0x30, 0x19, 0xc3, 0x47, - 0x0e, 0x90, 0x95, 0x22, + 0xa1, 0xe5, 0xf8, 0xab, 0x90, 0x24, 0x01, 0x9a, 0x67, 0x10, 0x53, 0x90, 0x86, 0x72, + 0x65, 0xb4, 0xc5, 0x16, 0x40, 0xe6, 0x5d, 0xb3, 0xcb, 0xcd, 0x7d, 0xf0, 0x04, 0x88, + 0xf8, 0x9e, 0x68, 0x35, ], nk: [ - 0x02, 0xab, 0x99, 0x5c, 0xe9, 0x8f, 0x63, 0x02, 0x5f, 0xb6, 0x24, 0x28, 0xa0, 0xfb, - 0xf5, 0x2f, 0x25, 0x22, 0xe6, 0xa2, 0x72, 0x61, 0x07, 0x8a, 0x9f, 0x4d, 0x6a, 0x36, - 0xa1, 0xc0, 0x5d, 0x39, + 0xf6, 0x42, 0x02, 0x4d, 0x49, 0xe8, 0x4b, 0x65, 0x33, 0xed, 0x2c, 0x37, 0x65, 0x06, + 0x06, 0x39, 0xfc, 0x27, 0x82, 0xd3, 0x9f, 0x87, 0x69, 0xdb, 0x80, 0x6b, 0x37, 0xde, + 0xb1, 0xf0, 0x9c, 0x2b, ], rivk: [ - 0xd9, 0x84, 0x0d, 0x0b, 0xd8, 0x95, 0x20, 0xab, 0xbc, 0xa7, 0xf1, 0x0b, 0xe6, 0xeb, - 0xa3, 0x66, 0xf8, 0x6e, 0xc3, 0xb7, 0x8d, 0xbd, 0xf1, 0xeb, 0xfe, 0x20, 0xd9, 0x95, - 0x12, 0xaf, 0x15, 0x15, + 0xe8, 0x2d, 0xad, 0xba, 0x81, 0x82, 0x3b, 0x52, 0xaf, 0x0b, 0xb5, 0xfc, 0x22, 0x79, + 0xaf, 0xfb, 0xff, 0xf8, 0x9c, 0x2d, 0xb2, 0x93, 0xbc, 0x5e, 0x30, 0x78, 0xa1, 0x31, + 0x91, 0x71, 0x66, 0x39, ], ivk: [ - 0x58, 0xf5, 0xbb, 0x5c, 0x32, 0x31, 0x15, 0x25, 0x29, 0x42, 0x3b, 0x67, 0xfa, 0x43, - 0x28, 0x79, 0x11, 0x26, 0x35, 0xcd, 0xa0, 0xda, 0x2e, 0xc2, 0x41, 0x9c, 0x6f, 0xe9, - 0x1e, 0xa4, 0x8d, 0x24, + 0xbd, 0xa0, 0xc1, 0x5b, 0x01, 0x4c, 0x15, 0x59, 0xf3, 0x34, 0x14, 0x97, 0xeb, 0x67, + 0xe7, 0x49, 0x5b, 0x73, 0x87, 0xbb, 0x6c, 0x2c, 0xbe, 0xa5, 0x95, 0x46, 0x9e, 0xc1, + 0xd2, 0xa8, 0x23, 0x3a, ], ovk: [ - 0x78, 0xf5, 0xd3, 0x48, 0x67, 0x2e, 0x8d, 0x20, 0x9c, 0x41, 0xb7, 0x83, 0xf8, 0xca, - 0x14, 0xa7, 0x7b, 0x3e, 0xa3, 0xe6, 0x00, 0x4c, 0xa4, 0xe0, 0xc2, 0x5a, 0xa4, 0x45, - 0x63, 0x98, 0x1d, 0xcb, + 0xd3, 0x8e, 0x31, 0xbd, 0x8a, 0xbd, 0xc5, 0x05, 0xfb, 0x3b, 0x0f, 0x03, 0xa5, 0x8a, + 0x73, 0x4f, 0xce, 0x58, 0x3b, 0x51, 0x4f, 0x32, 0xb3, 0x03, 0xf4, 0x6c, 0x5a, 0x69, + 0x01, 0x85, 0xa9, 0xb0, ], dk: [ - 0x5d, 0x7f, 0xe3, 0x96, 0xbb, 0xfd, 0x22, 0x67, 0xac, 0xa7, 0x11, 0xab, 0x5b, 0x3e, - 0x1f, 0x02, 0x4f, 0x49, 0x11, 0xf3, 0xa1, 0x81, 0x73, 0x2f, 0x13, 0x22, 0xa1, 0x59, - 0x2f, 0x9e, 0x0e, 0xbe, + 0x9a, 0x5b, 0x8c, 0xdc, 0x9f, 0x7b, 0xe7, 0x47, 0x6f, 0x7b, 0x5b, 0x73, 0x70, 0x71, + 0x90, 0xb6, 0x17, 0x20, 0xf8, 0x4b, 0xb4, 0x84, 0x47, 0x5c, 0x84, 0xd1, 0xce, 0xf1, + 0x5c, 0xa8, 0x15, 0x92, ], default_d: [ - 0x2f, 0xbe, 0x4b, 0x4b, 0x1e, 0xdf, 0xf3, 0x31, 0x23, 0xce, 0x65, + 0x46, 0x48, 0x8d, 0x15, 0x40, 0x98, 0x39, 0x66, 0x05, 0xf3, 0xc8, ], default_pk_d: [ - 0xeb, 0x2c, 0x6f, 0xee, 0x34, 0x1e, 0xad, 0xe0, 0x7d, 0x74, 0x87, 0x99, 0x7a, 0xa7, - 0x23, 0x69, 0x7d, 0x05, 0xe6, 0x29, 0x60, 0xdf, 0x37, 0x9c, 0x9e, 0x4a, 0x8d, 0x47, - 0x6d, 0xfa, 0xc5, 0xbf, + 0x28, 0xa3, 0x18, 0xf5, 0x04, 0x30, 0x43, 0x03, 0xee, 0xfd, 0x42, 0x87, 0x9c, 0x9f, + 0xc4, 0xf6, 0x27, 0x51, 0x90, 0xc6, 0x37, 0x63, 0x09, 0xb9, 0x13, 0xcc, 0xab, 0x3a, + 0x56, 0x95, 0x94, 0x28, ], internal_rivk: [ - 0x66, 0x3b, 0x67, 0xd3, 0xac, 0x15, 0x99, 0x27, 0xf0, 0x6e, 0x6c, 0x8d, 0xab, 0x80, - 0xa5, 0x89, 0x67, 0xc5, 0x45, 0xda, 0xac, 0x3d, 0x98, 0x72, 0x9a, 0x0b, 0xcc, 0x41, - 0xfd, 0x53, 0x6d, 0x2b, + 0xdd, 0xa7, 0x37, 0x26, 0xb1, 0x7b, 0xfb, 0x17, 0x82, 0xc5, 0x73, 0xa7, 0x5b, 0x54, + 0xfe, 0x6a, 0x37, 0xff, 0x66, 0x0c, 0x9b, 0x0f, 0x08, 0x64, 0xa5, 0x4f, 0x77, 0xe6, + 0x25, 0x8d, 0x69, 0x39, ], internal_ivk: [ - 0xaa, 0x6a, 0xcc, 0x8a, 0x7a, 0xa9, 0xa8, 0x05, 0x20, 0x04, 0xff, 0x93, 0x83, 0x3f, - 0x4a, 0xbb, 0x15, 0x3b, 0x45, 0x79, 0x7f, 0xd9, 0x07, 0xe3, 0x05, 0xc8, 0x92, 0x7b, - 0xb0, 0x37, 0x82, 0x20, + 0x71, 0x67, 0x63, 0x93, 0xce, 0x07, 0x32, 0xfc, 0x42, 0x42, 0x83, 0x1d, 0x94, 0xe7, + 0xf8, 0xc3, 0xf8, 0xa0, 0x78, 0x4d, 0xee, 0xa2, 0xae, 0xcd, 0x79, 0xdd, 0x54, 0x10, + 0x2a, 0x72, 0x89, 0x13, ], internal_ovk: [ - 0xbf, 0xd1, 0x09, 0x67, 0x27, 0xb6, 0xd5, 0xa2, 0xe1, 0x7a, 0xcb, 0xc5, 0xb2, 0x46, - 0x80, 0xcb, 0x88, 0xdb, 0x34, 0xcf, 0x53, 0xb6, 0xb7, 0x46, 0x6c, 0xef, 0x67, 0x6f, - 0xb3, 0xf7, 0x22, 0x29, + 0x4e, 0x71, 0xe6, 0xc1, 0x84, 0x5a, 0x5a, 0x36, 0xcf, 0x46, 0x03, 0x0f, 0xe6, 0x81, + 0xfd, 0xb0, 0xce, 0x39, 0xf4, 0x61, 0x31, 0x47, 0xbb, 0xcd, 0x10, 0xae, 0x42, 0x9c, + 0x81, 0x94, 0xb2, 0x05, ], internal_dk: [ - 0x47, 0xbd, 0xf9, 0x27, 0x1e, 0xcc, 0x50, 0xe7, 0x05, 0xc5, 0x21, 0xcd, 0x0d, 0xbb, - 0xaf, 0x1c, 0x4e, 0x6a, 0x96, 0x2f, 0xc9, 0x14, 0x13, 0x48, 0xb8, 0xbd, 0x7b, 0x35, - 0xc4, 0x00, 0x1e, 0x62, + 0x06, 0x31, 0xff, 0x9b, 0x81, 0xac, 0xf2, 0x1f, 0xb6, 0xe1, 0xf0, 0x81, 0xb5, 0x50, + 0xa5, 0x4e, 0xa1, 0x54, 0x49, 0x8e, 0x52, 0x98, 0x73, 0xe2, 0x58, 0x82, 0xf0, 0x66, + 0xb7, 0x3b, 0x6b, 0x8c, + ], + asset: [ + 0x0c, 0x05, 0x36, 0xac, 0xdd, 0xf6, 0xf1, 0xae, 0xab, 0x01, 0x6b, 0x6b, 0xc1, 0xec, + 0x14, 0x4b, 0x4e, 0x55, 0x3a, 0xcf, 0xd6, 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, + 0x06, 0x77, 0xe3, 0x1b, ], - note_v: 15425828902564319772, + note_v: 17683470315120269844, note_rho: [ - 0x73, 0x6c, 0x23, 0x35, 0x7c, 0x85, 0xf4, 0x57, 0x91, 0xe1, 0x70, 0x80, 0x29, 0xd9, - 0x82, 0x4d, 0x90, 0x70, 0x46, 0x07, 0xf3, 0x87, 0xa0, 0x3e, 0x49, 0xbf, 0x98, 0x36, - 0x57, 0x44, 0x31, 0x34, + 0xa4, 0x59, 0xb4, 0x4e, 0x30, 0x77, 0x68, 0x95, 0x8f, 0xe3, 0x78, 0x9d, 0x41, 0xc2, + 0xb1, 0xff, 0x43, 0x4c, 0xb3, 0x0e, 0x15, 0x91, 0x4f, 0x01, 0xbc, 0x6b, 0xc2, 0x30, + 0x7b, 0x48, 0x8d, 0x25, ], note_rseed: [ - 0x5a, 0x78, 0x77, 0xef, 0xaa, 0x8a, 0x08, 0xe7, 0x30, 0x81, 0xef, 0x8d, 0x62, 0xcb, - 0x78, 0x0a, 0xb6, 0x88, 0x3a, 0x50, 0xa0, 0xd4, 0x70, 0x19, 0x0d, 0xfb, 0xa1, 0x0a, - 0x85, 0x7f, 0x82, 0x84, + 0x56, 0xd7, 0xb7, 0x38, 0x0e, 0xa4, 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, + 0xb9, 0x45, 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, + 0xe5, 0xe1, 0x71, 0x1c, ], note_cmx: [ - 0xc8, 0x52, 0x8f, 0x72, 0x2c, 0xd3, 0xe4, 0x7d, 0xc9, 0x9e, 0x1e, 0x38, 0x80, 0x56, - 0x37, 0x08, 0x15, 0xa9, 0xd0, 0x37, 0x97, 0x3d, 0x85, 0xca, 0xc7, 0xea, 0x38, 0xb5, - 0xa7, 0x16, 0xfa, 0x3b, + 0xfe, 0x09, 0xf5, 0x89, 0x7c, 0xed, 0xc7, 0x67, 0x7c, 0xf5, 0x80, 0xc5, 0xf0, 0xd1, + 0x83, 0xed, 0x3b, 0xc0, 0x94, 0x5c, 0xb1, 0xc3, 0x85, 0xf3, 0x88, 0xf9, 0x3f, 0x94, + 0x3e, 0xff, 0x2a, 0x2f, ], note_nf: [ - 0xac, 0xc2, 0xed, 0x2c, 0x7e, 0x3b, 0x19, 0x7e, 0x5c, 0xdb, 0x4a, 0x57, 0x63, 0x57, - 0xd5, 0xf1, 0x35, 0x39, 0x16, 0x26, 0xc7, 0xa8, 0x25, 0xd1, 0x0a, 0xa2, 0x60, 0xae, - 0x0b, 0x95, 0x81, 0x28, + 0x80, 0xdf, 0x21, 0xbf, 0xeb, 0x46, 0x06, 0x16, 0x06, 0x29, 0x61, 0x03, 0x86, 0xc7, + 0x99, 0x02, 0xef, 0x49, 0x8b, 0x61, 0xb1, 0x55, 0x0c, 0xbd, 0x10, 0x55, 0xf8, 0x26, + 0x94, 0xfa, 0x5b, 0x03, ], }, TestVector { sk: [ - 0x2d, 0x38, 0x25, 0xb3, 0xd6, 0xda, 0x05, 0x73, 0xd3, 0x16, 0xeb, 0x16, 0x0d, 0xc0, - 0xb7, 0x16, 0xc4, 0x8f, 0xbd, 0x46, 0x7f, 0x75, 0xb7, 0x80, 0x14, 0x9a, 0xe8, 0x80, - 0x8f, 0x4e, 0x68, 0xf5, + 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, 0x3d, 0xa0, + 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, 0x0d, 0x02, 0xe0, 0xf0, 0x5d, 0x4b, + 0xec, 0x95, 0x12, 0xbf, ], ask: [ - 0x2d, 0x6e, 0x97, 0x3e, 0x17, 0x54, 0xd4, 0x17, 0x87, 0x93, 0x4c, 0x34, 0x55, 0x8c, - 0xfe, 0x99, 0x38, 0x44, 0x19, 0x99, 0x72, 0xd9, 0xa6, 0x34, 0x8b, 0x7a, 0x3d, 0xad, - 0xfc, 0xb6, 0x77, 0x2a, + 0x6e, 0x61, 0x4e, 0x28, 0x21, 0x35, 0x2a, 0xce, 0xd4, 0x53, 0x3e, 0x86, 0x42, 0x75, + 0x18, 0xc7, 0x42, 0xbf, 0xda, 0x68, 0x79, 0x65, 0x07, 0xa7, 0x01, 0xdd, 0xa3, 0x7d, + 0xaf, 0x20, 0xb3, 0x17, ], ak: [ - 0x76, 0x21, 0x59, 0xa4, 0x14, 0xf5, 0x74, 0xb5, 0x39, 0x75, 0x0f, 0x22, 0xc8, 0x86, - 0x3b, 0x02, 0xd2, 0x5c, 0xc1, 0x0c, 0x90, 0x71, 0xfc, 0x02, 0x19, 0xe9, 0x7f, 0x93, - 0x92, 0xd0, 0x67, 0x0c, + 0xed, 0x6e, 0x79, 0xae, 0xd5, 0x75, 0x2e, 0x64, 0xc6, 0xe4, 0xb7, 0x9c, 0x06, 0xa4, + 0x43, 0xb8, 0xef, 0x32, 0xf7, 0xef, 0xa1, 0xf8, 0xf3, 0x5b, 0x54, 0x12, 0x63, 0xaa, + 0x66, 0xaf, 0xd7, 0x0a, ], isk: [ - 0x01, 0x65, 0x33, 0x68, 0x4f, 0xb9, 0x81, 0x15, 0xa4, 0x05, 0xc9, 0xc7, 0xad, 0x47, - 0x72, 0x76, 0xab, 0x7c, 0x72, 0xfd, 0x67, 0x1a, 0x27, 0xe3, 0x6c, 0x0a, 0x7a, 0xbe, - 0x0a, 0x76, 0x90, 0x09, + 0x91, 0xfe, 0x60, 0x36, 0x9d, 0x03, 0x63, 0x66, 0xc2, 0x45, 0x79, 0xec, 0x10, 0xb5, + 0x38, 0x1e, 0x8f, 0x1e, 0xda, 0x89, 0x5f, 0xe0, 0xb6, 0x76, 0xa2, 0xc8, 0x0b, 0x25, + 0xaf, 0x98, 0x67, 0x11, ], ik: [ - 0xff, 0xd7, 0x5f, 0x6f, 0x9e, 0xf4, 0x27, 0xf3, 0x26, 0xcd, 0xbf, 0x3a, 0x98, 0xbc, - 0xb5, 0x93, 0x63, 0x5a, 0x2c, 0x1a, 0xd7, 0x2b, 0x39, 0x99, 0x12, 0x61, 0xe2, 0x75, - 0xa9, 0xec, 0x6f, 0x10, + 0xfe, 0x7e, 0xfc, 0x8b, 0x60, 0x72, 0x1b, 0x3c, 0x8e, 0x88, 0xdc, 0xc8, 0x86, 0xcb, + 0x04, 0x8f, 0xad, 0x5b, 0x48, 0x07, 0xf2, 0xae, 0xe4, 0xae, 0xc6, 0xe1, 0xc3, 0xfa, + 0x51, 0x44, 0x03, 0x1c, ], nk: [ - 0x25, 0x91, 0xed, 0xf7, 0xef, 0x4c, 0xf2, 0x18, 0x4c, 0x34, 0xbe, 0x93, 0xfc, 0xf6, - 0x12, 0x91, 0x50, 0x42, 0xf1, 0x5a, 0xb5, 0x08, 0x4b, 0x14, 0xe1, 0x66, 0x79, 0x5b, - 0x09, 0xce, 0xa1, 0x33, + 0xb1, 0xe9, 0x25, 0x85, 0x1e, 0x8c, 0xbf, 0x94, 0x28, 0xaf, 0x98, 0xfc, 0x71, 0x4c, + 0xc9, 0xf2, 0x41, 0x30, 0x1a, 0x3d, 0x0f, 0xea, 0x55, 0xe1, 0x29, 0x26, 0xbf, 0x4e, + 0x84, 0x0d, 0x49, 0x16, ], rivk: [ - 0x75, 0x8f, 0xb2, 0x50, 0xdd, 0x29, 0x50, 0xe5, 0xd2, 0xb2, 0xee, 0xd7, 0xff, 0xcf, - 0x94, 0xae, 0x67, 0xcd, 0xe1, 0x25, 0xb9, 0x5b, 0x47, 0x9e, 0x23, 0x77, 0x81, 0x3a, - 0x85, 0xa0, 0x3d, 0x2f, + 0x85, 0x45, 0x0e, 0x25, 0xbf, 0x7d, 0x7a, 0xed, 0x86, 0xc7, 0xab, 0xd3, 0x5e, 0xfb, + 0x8c, 0x62, 0x86, 0x77, 0x96, 0xf3, 0x47, 0x67, 0xd3, 0xd3, 0xfe, 0xf6, 0x49, 0x42, + 0x1c, 0x13, 0x32, 0x2f, ], ivk: [ - 0x6e, 0xa4, 0x36, 0x3c, 0xb2, 0xdf, 0x62, 0xb1, 0x0d, 0xa1, 0x30, 0x8a, 0x0b, 0x96, - 0x79, 0xbd, 0x0f, 0x74, 0x95, 0xff, 0xe7, 0xd4, 0xe2, 0x61, 0x8f, 0x54, 0xdf, 0x9b, - 0x67, 0x0c, 0x33, 0x16, + 0xe5, 0xe7, 0xaf, 0x47, 0xbe, 0x07, 0x6f, 0xf1, 0xc6, 0x5b, 0x2e, 0xd3, 0x2c, 0xcc, + 0xab, 0xad, 0x90, 0xd6, 0x7e, 0xff, 0x93, 0x5c, 0xcc, 0x29, 0xb1, 0x42, 0xe2, 0xd6, + 0x88, 0x01, 0x8e, 0x0c, ], ovk: [ - 0xa6, 0x3c, 0xbc, 0xd3, 0x1b, 0xa1, 0x36, 0xd8, 0x3b, 0x8f, 0x1e, 0x88, 0xef, 0xb6, - 0x00, 0x55, 0xef, 0x6f, 0x98, 0x25, 0x2d, 0xdb, 0xd7, 0x5f, 0x62, 0x5f, 0x44, 0xdc, - 0xb6, 0x63, 0x2c, 0x72, + 0xb4, 0x08, 0x5e, 0xe4, 0xeb, 0xd2, 0xd2, 0x80, 0xd5, 0xbf, 0x29, 0x35, 0xfb, 0xb1, + 0x6c, 0x8c, 0xa1, 0x29, 0x25, 0x4b, 0x92, 0x87, 0x2a, 0x1d, 0x12, 0x4a, 0xbb, 0x85, + 0x34, 0x8b, 0x1a, 0x88, ], dk: [ - 0x02, 0xf0, 0x74, 0x08, 0xf3, 0x3e, 0x87, 0x12, 0xe4, 0xc9, 0xec, 0x42, 0xde, 0x56, - 0x04, 0x20, 0x01, 0x09, 0x86, 0x17, 0x24, 0xd3, 0x3e, 0xb6, 0x36, 0x8b, 0x70, 0xf6, - 0x5e, 0x0a, 0x16, 0x21, + 0xb3, 0xa5, 0x2b, 0xdc, 0x62, 0xaa, 0xfa, 0xda, 0x4c, 0x40, 0xb4, 0xa6, 0xcd, 0x09, + 0x07, 0x09, 0x83, 0x35, 0xfc, 0xb7, 0x9a, 0x6f, 0xd6, 0xd3, 0x10, 0xc7, 0x26, 0xc0, + 0x1b, 0x39, 0xb3, 0x9d, ], default_d: [ - 0x08, 0xdf, 0x1d, 0x4b, 0x45, 0xc6, 0x73, 0xa4, 0x59, 0xff, 0x58, + 0xd8, 0x4c, 0x41, 0xf7, 0xb6, 0xb4, 0x33, 0x93, 0x65, 0xe3, 0x41, ], default_pk_d: [ - 0x26, 0x8c, 0xc2, 0x4b, 0x38, 0xa6, 0x28, 0x80, 0xb6, 0xee, 0x3c, 0xbc, 0xb8, 0x5a, - 0x71, 0x2f, 0xa6, 0x86, 0xcf, 0xfc, 0xa6, 0xdb, 0x2f, 0xee, 0xc5, 0xf3, 0xc3, 0x56, - 0x6f, 0x84, 0x21, 0x8f, + 0x0b, 0x85, 0x8b, 0x0e, 0x24, 0x56, 0x8b, 0x98, 0x4d, 0xa8, 0x96, 0xb3, 0xfb, 0x46, + 0xbe, 0xe7, 0x32, 0xac, 0x8c, 0x3d, 0xde, 0x34, 0xe7, 0x6b, 0xe7, 0x59, 0x90, 0xc8, + 0xd7, 0xc9, 0xc5, 0x04, ], internal_rivk: [ - 0x00, 0x57, 0x37, 0x74, 0x61, 0xf2, 0x19, 0x1a, 0x7e, 0xca, 0x2b, 0x02, 0xed, 0xfd, - 0x9c, 0x9b, 0x44, 0x84, 0x5d, 0x2f, 0xdb, 0x8a, 0x99, 0xc7, 0x61, 0x20, 0x52, 0x7e, - 0x53, 0xdd, 0x09, 0x17, + 0xad, 0x13, 0x65, 0x45, 0x09, 0xf3, 0x0a, 0x80, 0xa3, 0x2f, 0xcd, 0xb9, 0x78, 0x93, + 0xaa, 0x32, 0x7c, 0x3e, 0x56, 0x7f, 0x67, 0xb4, 0x40, 0x45, 0x5f, 0x0d, 0xeb, 0x68, + 0xc3, 0x24, 0xb6, 0x39, ], internal_ivk: [ - 0x81, 0x62, 0x97, 0x35, 0x09, 0x47, 0x0c, 0x44, 0x24, 0x19, 0x11, 0xc0, 0x6d, 0x04, - 0x02, 0x9f, 0x5f, 0x1f, 0x0e, 0x98, 0x51, 0xe3, 0x2b, 0xa6, 0x9b, 0x18, 0xe5, 0x81, - 0x05, 0xdd, 0x4e, 0x2b, + 0xfa, 0xb6, 0xa5, 0x05, 0xa6, 0xee, 0x92, 0x55, 0x0d, 0xf5, 0xd5, 0xce, 0xbc, 0x37, + 0x9c, 0xd6, 0x24, 0x6c, 0xd2, 0xcc, 0x17, 0x43, 0xa8, 0x1f, 0xb5, 0xf9, 0x8a, 0xa0, + 0xf5, 0xea, 0x8f, 0x0d, ], internal_ovk: [ - 0x69, 0x47, 0x91, 0x0e, 0xa3, 0xe7, 0x33, 0x1d, 0x15, 0xa7, 0x1a, 0x64, 0xb2, 0xa8, - 0xc1, 0x6a, 0x6d, 0xa0, 0x8e, 0x6f, 0x34, 0x29, 0xdb, 0x26, 0xf9, 0x37, 0xab, 0x9d, - 0xd1, 0x33, 0xb5, 0xfd, + 0x8d, 0x08, 0x28, 0xa8, 0x3a, 0xc9, 0x94, 0x33, 0x8a, 0x87, 0xe9, 0x72, 0x68, 0xd4, + 0xaf, 0x0a, 0x87, 0x3b, 0x7c, 0x5b, 0x68, 0xec, 0x60, 0x13, 0x38, 0x51, 0x51, 0xf0, + 0x2d, 0xb1, 0x06, 0x1b, ], internal_dk: [ - 0x32, 0x7f, 0x76, 0xcc, 0x42, 0x44, 0xce, 0x0a, 0x91, 0x48, 0xa3, 0x5a, 0x7e, 0xa6, - 0x22, 0x8d, 0x44, 0x1c, 0x4c, 0x7b, 0x05, 0xbd, 0x02, 0x65, 0x7c, 0xea, 0xab, 0xb6, - 0x09, 0xbc, 0x3c, 0x52, + 0x31, 0xe2, 0x98, 0x37, 0xcc, 0x3d, 0xdd, 0x80, 0xdd, 0x80, 0x97, 0x19, 0x7b, 0xfa, + 0x66, 0x46, 0x67, 0x96, 0x2b, 0x09, 0x05, 0x5e, 0x50, 0x7f, 0x39, 0x7d, 0x94, 0xae, + 0xad, 0x84, 0xd8, 0x48, ], - note_v: 12606128263924155660, + asset: [ + 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, + 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, 0x99, 0xc7, 0x1f, 0x18, 0x93, 0x41, 0xac, 0x9b, + 0x78, 0xa2, 0x69, 0x16, + ], + note_v: 12104108071547302835, note_rho: [ - 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, - 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, - 0x43, 0x6a, 0x10, 0x2f, + 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, 0x54, 0xa8, 0x94, 0x32, 0x28, 0x48, 0xcc, 0xbd, + 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, 0x68, 0xaf, 0xac, 0x87, 0xff, 0xa0, 0x05, 0xc3, + 0x12, 0x24, 0x1c, 0x2d, ], note_rseed: [ - 0xca, 0x4b, 0x97, 0x69, 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, - 0x0d, 0x02, 0xe0, 0xf0, 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, - 0x29, 0x6e, 0xfa, 0xa7, + 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, + 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, + 0xcd, 0xdb, 0x41, 0x87, ], note_cmx: [ - 0x6a, 0x11, 0x95, 0xaa, 0x05, 0x36, 0xf6, 0x0e, 0xcf, 0xae, 0xcb, 0xdf, 0x53, 0x74, - 0xe4, 0x94, 0xea, 0x07, 0x2a, 0x2b, 0x86, 0x7b, 0x5f, 0x69, 0x43, 0x40, 0xc9, 0x6f, - 0xc3, 0x70, 0xa9, 0x10, + 0x5e, 0x54, 0xfe, 0x7e, 0x59, 0x52, 0xa6, 0xea, 0x26, 0xba, 0xbc, 0x32, 0xcf, 0xed, + 0xf5, 0xe6, 0x0b, 0x56, 0x82, 0x58, 0x98, 0x0d, 0x92, 0xc1, 0xe5, 0xdd, 0x3f, 0xdf, + 0x3e, 0x48, 0x7e, 0x1d, ], note_nf: [ - 0xb0, 0xf1, 0x60, 0x2a, 0x2b, 0x1a, 0xf2, 0xfc, 0x55, 0xf1, 0x59, 0x50, 0xa6, 0x83, - 0x83, 0x85, 0xe5, 0xe3, 0x9f, 0xec, 0xfd, 0x05, 0xcc, 0xec, 0x79, 0x9b, 0x75, 0xc6, - 0x5c, 0x8d, 0xa2, 0x35, + 0x45, 0x5f, 0xd0, 0xe5, 0x2e, 0x59, 0x33, 0x62, 0x57, 0x2d, 0x12, 0xdb, 0x44, 0xbb, + 0xf0, 0xe0, 0x95, 0x8a, 0xf9, 0xd5, 0x8f, 0xbd, 0xf9, 0x7b, 0x85, 0x22, 0x8e, 0xca, + 0xd0, 0xde, 0x7f, 0x05, ], }, TestVector { sk: [ - 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, - 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, - 0x84, 0x1e, 0x75, 0x17, + 0x2c, 0xfc, 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, 0x3d, 0xbf, + 0xf9, 0x30, 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, + 0x33, 0x92, 0xde, 0xb8, ], ask: [ - 0x28, 0xdc, 0x45, 0xf1, 0x15, 0x44, 0x42, 0x5c, 0x1b, 0xef, 0x86, 0x61, 0xda, 0x11, - 0x15, 0x5f, 0xdb, 0xb7, 0xe3, 0xbc, 0xfc, 0x0f, 0x0d, 0x49, 0xe6, 0xf1, 0x31, 0xe7, - 0xc0, 0x9d, 0x35, 0x2f, + 0x33, 0x4c, 0x49, 0x70, 0x7d, 0x93, 0x52, 0x5e, 0x70, 0x45, 0x5d, 0xd2, 0xc0, 0xdd, + 0xb4, 0x2d, 0x49, 0xc9, 0x39, 0x9f, 0x96, 0x14, 0x7f, 0xc0, 0x5e, 0x79, 0xec, 0x49, + 0x1b, 0xd9, 0xad, 0x07, ], ak: [ - 0x0d, 0x21, 0x1a, 0x90, 0x60, 0xfb, 0xaa, 0x66, 0x4e, 0x41, 0xa7, 0x34, 0xad, 0x1d, - 0x8d, 0x4b, 0x02, 0x5f, 0x8c, 0xc1, 0x60, 0xe1, 0xf4, 0xe9, 0x5f, 0x0a, 0x85, 0x3e, - 0xbc, 0x41, 0x6a, 0x2b, + 0xd3, 0xc0, 0xa4, 0xdc, 0x7e, 0x33, 0x47, 0xa5, 0x0b, 0xf0, 0x58, 0x44, 0xe0, 0xcb, + 0xfc, 0xd4, 0x41, 0x4a, 0x80, 0x9c, 0x0c, 0x30, 0xb1, 0x43, 0xbc, 0xe4, 0xa7, 0xc6, + 0x5c, 0xf0, 0x7f, 0x36, ], isk: [ - 0x76, 0x08, 0x32, 0x9d, 0xfa, 0x77, 0xc4, 0x2c, 0x4f, 0xc7, 0x6a, 0xc2, 0x95, 0x94, - 0xa2, 0x72, 0x83, 0x93, 0x4f, 0x5a, 0x93, 0x40, 0x71, 0xb9, 0xf8, 0xcd, 0x34, 0x4e, - 0x1f, 0x98, 0x45, 0x0e, + 0xb3, 0x72, 0x5b, 0x89, 0x31, 0xc4, 0x93, 0xdb, 0x21, 0x97, 0xe2, 0x87, 0x8e, 0xd3, + 0x62, 0x67, 0x0a, 0x18, 0xb9, 0x29, 0x31, 0x2e, 0xdd, 0x64, 0x4d, 0x74, 0xf9, 0xf3, + 0x23, 0xc6, 0x5e, 0x14, ], ik: [ - 0x72, 0xa0, 0xac, 0x97, 0x8a, 0x2d, 0xa1, 0x61, 0xf4, 0x1f, 0x5b, 0x7a, 0x40, 0xbd, - 0x83, 0xc0, 0x58, 0x41, 0xf8, 0x1b, 0xc5, 0x11, 0x40, 0x67, 0xb8, 0x85, 0x98, 0x7f, - 0x48, 0xca, 0x52, 0x2d, + 0xc5, 0x12, 0x36, 0x0c, 0x13, 0x59, 0xa6, 0x4f, 0x2a, 0xbb, 0x9e, 0xb3, 0xab, 0x43, + 0xe4, 0x99, 0x8e, 0xd6, 0xd5, 0x1d, 0x17, 0xbd, 0x9d, 0x70, 0x64, 0xa3, 0x91, 0x67, + 0x41, 0x98, 0xea, 0x1a, ], nk: [ - 0x3e, 0x88, 0xf2, 0x07, 0x1f, 0xd9, 0xa2, 0xbb, 0x26, 0xcd, 0xa2, 0xea, 0x85, 0x6a, - 0xa0, 0xfb, 0x3a, 0x80, 0xa8, 0x7d, 0x2f, 0xb6, 0x13, 0x6f, 0xab, 0x85, 0xe3, 0x6c, - 0x5b, 0x38, 0xd8, 0x24, + 0xc6, 0xb5, 0xe9, 0x28, 0x83, 0x73, 0x52, 0x14, 0x90, 0x20, 0xcc, 0x1f, 0x68, 0xf0, + 0xfb, 0xf8, 0x6a, 0x79, 0x89, 0xcb, 0x4e, 0x09, 0xb3, 0xb5, 0x44, 0x87, 0xb5, 0xcf, + 0x59, 0x00, 0x7c, 0x38, ], rivk: [ - 0x2c, 0x37, 0x38, 0x82, 0xc4, 0x08, 0xcd, 0x5f, 0xd4, 0x82, 0xa0, 0xc9, 0x81, 0x6f, - 0xc3, 0x22, 0x03, 0xa1, 0x0f, 0xbf, 0xce, 0x0e, 0x20, 0x0c, 0xcf, 0xd9, 0xee, 0x30, - 0x7c, 0x5e, 0x12, 0x24, + 0xe9, 0x38, 0xcf, 0x40, 0xc9, 0x83, 0x1a, 0x1a, 0x28, 0x48, 0xbc, 0x80, 0x22, 0x03, + 0x10, 0x81, 0x0b, 0x8f, 0x6a, 0xfd, 0xe1, 0x6c, 0xdd, 0x1e, 0xa1, 0x29, 0x98, 0xd3, + 0x74, 0xd1, 0xbb, 0x08, ], ivk: [ - 0xbb, 0x9e, 0x20, 0xb2, 0x99, 0x1c, 0x99, 0x6d, 0xa2, 0x1e, 0x3e, 0xcd, 0x39, 0xfb, - 0x7b, 0x3a, 0xa2, 0xba, 0xbc, 0x6b, 0xde, 0x18, 0x6f, 0x7d, 0xd8, 0xa8, 0x75, 0xd1, - 0x0c, 0x51, 0xa4, 0x30, + 0x80, 0x78, 0xd4, 0x95, 0x71, 0x1d, 0xc8, 0xc9, 0xba, 0xea, 0xdf, 0x84, 0xee, 0xfa, + 0x78, 0x26, 0xe5, 0x74, 0x3c, 0x5f, 0x92, 0x26, 0x99, 0xf3, 0xfa, 0x56, 0xeb, 0xa3, + 0xe0, 0xe0, 0x77, 0x3c, ], ovk: [ - 0x93, 0x21, 0x83, 0x8a, 0x2d, 0xb7, 0xf1, 0x68, 0xf0, 0xce, 0x77, 0xc4, 0x5b, 0x21, - 0x1f, 0xfb, 0xb9, 0xb3, 0x65, 0xe8, 0x5e, 0x67, 0x31, 0xd9, 0x09, 0x70, 0x05, 0x53, - 0xde, 0x49, 0x2b, 0x28, + 0x6c, 0xc7, 0xf9, 0xdc, 0xb8, 0x16, 0x9c, 0x38, 0x90, 0x97, 0x2f, 0xd3, 0x51, 0x04, + 0x13, 0x60, 0x4d, 0x0d, 0xdf, 0x82, 0xff, 0xfa, 0x0d, 0xc4, 0x58, 0xef, 0x5c, 0xd6, + 0xbb, 0x2f, 0x0d, 0x89, ], dk: [ - 0x3d, 0xf5, 0x83, 0x36, 0x1b, 0x33, 0x38, 0xbb, 0x68, 0x15, 0xf8, 0x58, 0x72, 0xe3, - 0x9f, 0x04, 0xdf, 0x50, 0x08, 0x52, 0x48, 0x84, 0xaf, 0x0f, 0x8c, 0x55, 0x97, 0x16, - 0xfc, 0xb1, 0x49, 0x58, + 0xf8, 0xa0, 0x79, 0x29, 0x1e, 0x32, 0xce, 0x94, 0x4f, 0x0f, 0xfe, 0x65, 0x8e, 0xd8, + 0xfb, 0xdb, 0xfd, 0xb9, 0xa2, 0xd6, 0x96, 0x86, 0xe7, 0x44, 0xa5, 0xf7, 0xb5, 0x96, + 0xf1, 0x22, 0x57, 0xee, ], default_d: [ - 0x4c, 0x40, 0x64, 0xc4, 0x7a, 0x5c, 0xa6, 0xe7, 0x5d, 0x46, 0x44, + 0x5c, 0x1b, 0x2f, 0x77, 0x6e, 0x19, 0x81, 0x35, 0xd0, 0xfd, 0x1f, ], default_pk_d: [ - 0xf5, 0x17, 0x17, 0x4b, 0xe2, 0x58, 0x92, 0x32, 0x78, 0xcf, 0x45, 0x89, 0x08, 0xc0, - 0x73, 0x56, 0x49, 0xf1, 0x89, 0x9d, 0xb9, 0x9c, 0x3b, 0xa9, 0x00, 0x3f, 0x4b, 0xa3, - 0x0a, 0xb0, 0xd2, 0x10, + 0x2a, 0x91, 0x7a, 0xe2, 0x42, 0x40, 0xb1, 0xa6, 0xaa, 0x67, 0x5b, 0x83, 0xa3, 0x78, + 0x25, 0x03, 0xeb, 0x71, 0x26, 0xd9, 0x99, 0x04, 0x9f, 0xb5, 0x7c, 0x70, 0x5e, 0xbc, + 0x01, 0x4e, 0x6b, 0x8f, ], internal_rivk: [ - 0xd8, 0x09, 0xa2, 0xa3, 0xd3, 0x6e, 0xf9, 0x6d, 0xc5, 0x63, 0xf8, 0xa7, 0xb4, 0x13, - 0x90, 0x8b, 0xfd, 0xff, 0xc0, 0x6d, 0x51, 0x06, 0x48, 0x49, 0xef, 0x88, 0x6b, 0x6a, - 0x1d, 0x1d, 0x7c, 0x3f, + 0xcd, 0x1d, 0xd3, 0x5e, 0xb9, 0xfa, 0xd9, 0x42, 0xb8, 0x69, 0xc8, 0x6f, 0xa1, 0x31, + 0x09, 0x83, 0x04, 0x78, 0x59, 0xfa, 0xe9, 0x09, 0xae, 0x97, 0x69, 0x7d, 0xa7, 0x0f, + 0xd5, 0x72, 0xa3, 0x16, ], internal_ivk: [ - 0xae, 0x18, 0xa9, 0xa4, 0x25, 0x12, 0x38, 0x7f, 0x92, 0xee, 0xc1, 0x34, 0xbd, 0xe5, - 0x28, 0xb6, 0x2b, 0x61, 0xe9, 0x95, 0x6f, 0x9f, 0xb3, 0xc7, 0xd6, 0x5e, 0x19, 0x45, - 0xda, 0x34, 0xf3, 0x09, + 0xa3, 0x36, 0xaa, 0x7a, 0xe3, 0xf6, 0xb5, 0x98, 0x3d, 0xad, 0xf0, 0x54, 0x93, 0xd5, + 0x76, 0xbe, 0x17, 0x31, 0x89, 0x7d, 0x36, 0x44, 0x83, 0x2b, 0x91, 0x81, 0xdd, 0xa1, + 0xbf, 0x7e, 0x1d, 0x17, ], internal_ovk: [ - 0x67, 0xa6, 0xd8, 0x4a, 0x81, 0x66, 0x32, 0x6c, 0xf3, 0x4c, 0xed, 0xff, 0xd4, 0x29, - 0x8a, 0x13, 0xb8, 0x01, 0xcb, 0x12, 0x2d, 0x5f, 0x33, 0x29, 0xa1, 0x59, 0x9f, 0x31, - 0xea, 0xdf, 0x5b, 0x17, + 0x9f, 0xa3, 0xc3, 0xb0, 0x3a, 0xf8, 0xc3, 0xf7, 0x87, 0x44, 0x1a, 0x8c, 0x34, 0x07, + 0x8f, 0x6f, 0x36, 0xbb, 0xdc, 0xfc, 0x9b, 0x11, 0x0d, 0x3e, 0x27, 0x59, 0x57, 0xc4, + 0x43, 0x9a, 0x25, 0x48, ], internal_dk: [ - 0xa0, 0x07, 0x3a, 0xdd, 0xfb, 0x89, 0xc9, 0xcc, 0x34, 0x9e, 0xad, 0x5a, 0x92, 0xb7, - 0xd4, 0x17, 0xfe, 0x0e, 0x61, 0xf4, 0xa7, 0xe5, 0x66, 0x69, 0xc9, 0x07, 0xd4, 0x17, - 0x46, 0xc0, 0x72, 0xb9, + 0x0c, 0xac, 0x83, 0xbf, 0x12, 0xf9, 0xc0, 0x56, 0x68, 0xa8, 0x3d, 0x27, 0x3d, 0x44, + 0x13, 0x85, 0x30, 0xd7, 0xa7, 0xf8, 0x76, 0x60, 0x21, 0xc5, 0x5b, 0x65, 0x03, 0xb1, + 0xda, 0xcc, 0xe5, 0x92, + ], + asset: [ + 0xe6, 0x10, 0x62, 0x0f, 0x71, 0xcd, 0xa8, 0xfc, 0x87, 0x76, 0x25, 0xf2, 0xc5, 0xbb, + 0x04, 0xcb, 0xe1, 0x22, 0x8b, 0x1e, 0x88, 0x6f, 0x40, 0x50, 0xaf, 0xd8, 0xfe, 0x94, + 0xe9, 0x7d, 0x2e, 0x9e, ], - note_v: 625536973899669523, + note_v: 17139625070743016316, note_rho: [ - 0x03, 0xfd, 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, - 0x92, 0xee, 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, - 0x64, 0x0a, 0x69, 0x30, + 0x6c, 0x0b, 0x38, 0x99, 0xd4, 0x12, 0x22, 0xba, 0xce, 0x76, 0x0e, 0xe9, 0xc8, 0x81, + 0x8d, 0xed, 0x59, 0x9e, 0x34, 0xc5, 0x6d, 0x73, 0x72, 0xaf, 0x1e, 0xb8, 0x68, 0x52, + 0xf2, 0xa7, 0x32, 0x10, ], note_rseed: [ - 0x1a, 0x52, 0xa3, 0x8d, 0x4d, 0x9f, 0x9f, 0x95, 0x7a, 0xe3, 0x5a, 0xf7, 0x16, 0x71, - 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, 0x15, 0x81, - 0xa1, 0x55, 0xfa, 0x3a, + 0x4b, 0xdb, 0x75, 0x07, 0x39, 0xde, 0x6c, 0x2c, 0x6e, 0x0f, 0x9e, 0xb7, 0xcb, 0x17, + 0xf1, 0x94, 0x2b, 0xfc, 0x9f, 0x4f, 0xd6, 0xeb, 0xb6, 0xb4, 0xcd, 0xd4, 0xda, 0x2b, + 0xca, 0x26, 0xfa, 0xc4, ], note_cmx: [ - 0xf7, 0x0e, 0xbf, 0x0f, 0x5e, 0xe5, 0xda, 0x6c, 0x6c, 0xde, 0xff, 0x8f, 0xec, 0x2f, - 0x8e, 0xed, 0x65, 0xc8, 0x8e, 0x67, 0x55, 0xda, 0xf1, 0x14, 0xd5, 0x54, 0xaf, 0x19, - 0x67, 0xa7, 0xf4, 0x0a, + 0xdf, 0x1e, 0x28, 0x2c, 0x9b, 0xf3, 0x09, 0x72, 0xb2, 0x8c, 0x46, 0xed, 0x8a, 0x54, + 0x42, 0x6d, 0xae, 0xc1, 0xae, 0x38, 0x1a, 0x38, 0x5d, 0xf2, 0x5f, 0xff, 0xfa, 0x66, + 0x79, 0x53, 0xd3, 0x33, ], note_nf: [ - 0x95, 0x64, 0x97, 0x28, 0x46, 0x5e, 0x68, 0x2a, 0xc0, 0x57, 0xad, 0x87, 0x62, 0x94, - 0xd7, 0x00, 0xc2, 0x7f, 0xeb, 0xa2, 0xf7, 0x50, 0x92, 0x2f, 0x95, 0x51, 0x85, 0x70, - 0x62, 0x61, 0xc3, 0x0c, + 0x97, 0x0a, 0xff, 0xd7, 0xf1, 0x0d, 0x5b, 0x71, 0x23, 0x27, 0xe8, 0x39, 0x7e, 0x51, + 0x45, 0x3f, 0x85, 0xf4, 0xc2, 0x0f, 0x80, 0x1e, 0x97, 0xe5, 0xe6, 0x40, 0x0e, 0xb0, + 0xed, 0xc4, 0xbb, 0x03, ], }, ] From 563b4e5502f0498675ae7a0f8a889eb0b5257e35 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 21 Apr 2023 14:34:50 +0200 Subject: [PATCH 23/92] Circuit: Update value_commit_orchard to take into account asset (#50) In the circuit, we update value_commit_orchard to take into account asset. Previously, value_commit_orchard returns cv_net = [v_net] ValueCommitV + [rcv] ValueCommitR.. Now, value_commit_orchard returns cv_net = [v_net] asset + [rcv] ValueCommitR. ValueCommitV and ValueCommitR are constants v_net is equal to sign * magnitude where sign is in {-1, 1} and magnitude is an unsigned integer on 64 bits. To evaluate [v_net] asset where v_net = sign * magnitude, we perform the following steps 1. verify that magnitude is on 64 bits 2. evaluate commitment=[magnitude]asset with the variable-base long-scalar multiplication 3. evaluate result=[sign]commitment with the new mul_sign gate --- Cargo.toml | 6 +- src/circuit.rs | 124 +- src/circuit/gadget.rs | 46 +- src/circuit/value_commit_orchard.rs | 341 ++ src/circuit_description | 4928 ++++++++++----------------- src/circuit_proof_test_case.bin | Bin 5154 -> 5186 bytes 6 files changed, 2251 insertions(+), 3194 deletions(-) create mode 100644 src/circuit/value_commit_orchard.rs diff --git a/Cargo.toml b/Cargo.toml index 5a09720a7..e482b0f76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,8 +29,8 @@ blake2b_simd = "1" ff = "0.12" fpe = "0.5" group = { version = "0.12.1", features = ["wnaf-memuse"] } -halo2_gadgets = "0.2" -halo2_proofs = "0.2" +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } +halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } hex = "0.4" lazy_static = "1" memuse = { version = "0.2.1", features = ["nonempty"] } @@ -52,7 +52,7 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] criterion = "0.3" -halo2_gadgets = { version = "0.2", features = ["test-dependencies"] } +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" , features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" zcash_note_encryption = { version = "0.2", features = ["pre-zip-212"] } diff --git a/src/circuit.rs b/src/circuit.rs index 7ac075eea..c5bfc0444 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -46,7 +46,7 @@ use crate::{ use halo2_gadgets::{ ecc::{ chip::{EccChip, EccConfig}, - FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarFixedShort, ScalarVar, + FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar, }, poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, sinsemilla::{ @@ -62,6 +62,7 @@ use halo2_gadgets::{ mod commit_ivk; pub mod gadget; mod note_commit; +mod value_commit_orchard; /// Size of the Orchard circuit. const K: u32 = 11; @@ -109,7 +110,6 @@ pub struct Circuit { pub(crate) psi_old: Value, pub(crate) rcm_old: Value, pub(crate) cm_old: Value, - pub(crate) asset_old: Value, pub(crate) alpha: Value, pub(crate) ak: Value, pub(crate) nk: Value, @@ -119,8 +119,8 @@ pub struct Circuit { pub(crate) v_new: Value, pub(crate) psi_new: Value, pub(crate) rcm_new: Value, - pub(crate) asset_new: Value, pub(crate) rcv: Value, + pub(crate) asset: Value, pub(crate) split_flag: Value, } @@ -175,7 +175,6 @@ impl Circuit { psi_old: Value::known(psi_old), rcm_old: Value::known(rcm_old), cm_old: Value::known(spend.note.commitment()), - asset_old: Value::known(spend.note.asset()), alpha: Value::known(alpha), ak: Value::known(spend.fvk.clone().into()), nk: Value::known(*spend.fvk.nk()), @@ -185,8 +184,8 @@ impl Circuit { v_new: Value::known(output_note.value()), psi_new: Value::known(psi_new), rcm_new: Value::known(rcm_new), - asset_new: Value::known(output_note.asset()), rcv: Value::known(rcv), + asset: Value::known(spend.note.asset()), split_flag: Value::known(spend.split_flag), } } @@ -475,23 +474,6 @@ impl plonk::Circuit for Circuit { (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) }; - // Verify that asset_old and asset_new are equals - { - let asset_old = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness asset_old"), - self.asset_old - .map(|asset_old| asset_old.cv_base().to_affine()), - )?; - let asset_new = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "asset equality"), - self.asset_new - .map(|asset_new| asset_new.cv_base().to_affine()), - )?; - asset_old.constrain_equal(layouter.namespace(|| "asset equality"), &asset_new)?; - } - // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). let root = { let path = self @@ -549,22 +531,25 @@ impl plonk::Circuit for Circuit { (magnitude, sign) }; - let v_net = ScalarFixedShort::new( - ecc_chip.clone(), - layouter.namespace(|| "v_net"), - v_net_magnitude_sign.clone(), - )?; let rcv = ScalarFixed::new( ecc_chip.clone(), layouter.namespace(|| "rcv"), self.rcv.as_ref().map(|rcv| rcv.inner()), )?; + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + self.asset.map(|asset| asset.cv_base().to_affine()), + )?; + let cv_net = gadget::value_commit_orchard( - layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"), + config.sinsemilla_chip_1(), ecc_chip.clone(), - v_net, + v_net_magnitude_sign.clone(), rcv, + asset, )?; // Constrain cv_net to equal public input @@ -1033,7 +1018,6 @@ mod tests { use rand::{rngs::OsRng, RngCore}; use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; - use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; use crate::note::AssetBase; use crate::{ keys::SpendValidatingKey, @@ -1074,7 +1058,6 @@ mod tests { psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), cm_old: Value::known(spent_note.commitment()), - asset_old: Value::known(spent_note.asset()), alpha: Value::known(alpha), ak: Value::known(ak), nk: Value::known(nk), @@ -1084,8 +1067,8 @@ mod tests { v_new: Value::known(output_note.value()), psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - asset_new: Value::known(output_note.asset()), rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), split_flag: Value::known(false), }, Instance { @@ -1128,8 +1111,8 @@ mod tests { K as usize, &circuits[0], ); - assert_eq!(usize::from(circuit_cost.proof_size(1)), 4992); - assert_eq!(usize::from(circuit_cost.proof_size(2)), 7264); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 5024); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7296); usize::from(circuit_cost.proof_size(instances.len())) }; @@ -1156,74 +1139,6 @@ mod tests { assert_eq!(proof.0.len(), expected_proof_size); } - #[test] - fn test_not_equal_asset_ids() { - use halo2_proofs::dev::{ - metadata::Column, metadata::Region, FailureLocation, VerifyFailure, - }; - use halo2_proofs::plonk::Any::Advice; - - let mut rng = OsRng; - - let (mut circuit, instance) = generate_circuit_instance(&mut rng); - - // We would like to test that if the asset of the spent note (called asset_old) and the - // asset of the output note (called asset_new) are not equal, the proof is not verified. - // To do that, we attribute a random value to asset_new. - let random_asset_id = { - let sk = SpendingKey::random(&mut rng); - let isk = IssuanceAuthorizingKey::from(&sk); - let ik = IssuanceValidatingKey::from(&isk); - let asset_descr = "zsa_asset"; - AssetBase::derive(&ik, asset_descr) - }; - circuit.asset_new = Value::known(random_asset_id); - - assert_eq!( - MockProver::run( - K, - &circuit, - instance - .to_halo2_instance() - .iter() - .map(|p| p.to_vec()) - .collect() - ) - .unwrap() - .verify(), - Err(vec![ - VerifyFailure::Permutation { - column: Column::from((Advice, 0)), - location: FailureLocation::InRegion { - region: Region::from((9, "witness non-identity point".to_string())), - offset: 0 - } - }, - VerifyFailure::Permutation { - column: Column::from((Advice, 0)), - location: FailureLocation::InRegion { - region: Region::from((10, "witness non-identity point".to_string())), - offset: 0 - } - }, - VerifyFailure::Permutation { - column: Column::from((Advice, 1)), - location: FailureLocation::InRegion { - region: Region::from((9, "witness non-identity point".to_string())), - offset: 0 - } - }, - VerifyFailure::Permutation { - column: Column::from((Advice, 1)), - location: FailureLocation::InRegion { - region: Region::from((10, "witness non-identity point".to_string())), - offset: 0 - } - } - ]) - ); - } - #[test] fn serialized_proof_test_case() { use std::io::{Read, Write}; @@ -1305,7 +1220,7 @@ mod tests { let test_case_bytes = include_bytes!("circuit_proof_test_case.bin"); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.0.len(), 4992); + assert_eq!(proof.0.len(), 5024); assert!(proof.verify(&vk, &[instance]).is_ok()); } @@ -1331,7 +1246,6 @@ mod tests { psi_old: Value::unknown(), rcm_old: Value::unknown(), cm_old: Value::unknown(), - asset_old: Value::unknown(), alpha: Value::unknown(), ak: Value::unknown(), nk: Value::unknown(), @@ -1341,8 +1255,8 @@ mod tests { v_new: Value::unknown(), psi_new: Value::unknown(), rcm_new: Value::unknown(), - asset_new: Value::unknown(), rcv: Value::unknown(), + asset: Value::unknown(), split_flag: Value::unknown(), }; halo2_proofs::dev::CircuitLayout::default() diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 21d24333f..9864d65b0 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -4,15 +4,9 @@ use ff::Field; use pasta_curves::pallas; use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip}; -use crate::constants::{ - NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - ValueCommitV, -}; +use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; use halo2_gadgets::{ - ecc::{ - chip::EccChip, EccInstructions, FixedPoint, FixedPointBaseField, FixedPointShort, Point, - ScalarFixed, ScalarFixedShort, X, - }, + ecc::{chip::EccChip, EccInstructions, FixedPointBaseField, Point, X}, poseidon::{ primitives::{self as poseidon, ConstantLength}, Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, @@ -107,41 +101,6 @@ where ) } -/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. -/// -/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit -pub(in crate::circuit) fn value_commit_orchard< - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - ecc_chip: EccChip, - v: ScalarFixedShort, - rcv: ScalarFixed, -) -> Result, plonk::Error> { - // commitment = [v] ValueCommitV - let (commitment, _) = { - let value_commit_v = ValueCommitV; - let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); - value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v)? - }; - - // blind = [rcv] ValueCommitR - let (blind, _rcv) = { - let value_commit_r = OrchardFixedBasesFull::ValueCommitR; - let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r); - - // [rcv] ValueCommitR - value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)? - }; - - // [v] ValueCommitV + [rcv] ValueCommitR - commitment.add(layouter.namespace(|| "cv"), &blind) -} - /// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. /// /// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers @@ -202,3 +161,4 @@ pub(in crate::circuit) fn derive_nullifier< pub(in crate::circuit) use crate::circuit::commit_ivk::gadgets::commit_ivk; pub(in crate::circuit) use crate::circuit::note_commit::gadgets::note_commit; +pub(in crate::circuit) use crate::circuit::value_commit_orchard::gadgets::value_commit_orchard; diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs new file mode 100644 index 000000000..078e9378f --- /dev/null +++ b/src/circuit/value_commit_orchard.rs @@ -0,0 +1,341 @@ +pub(in crate::circuit) mod gadgets { + use pasta_curves::pallas; + + use crate::constants::{ + OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, + }; + use halo2_gadgets::{ + ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, + sinsemilla::{self, chip::SinsemillaChip}, + }; + use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter}, + plonk, + }; + + /// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. + /// + /// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit + pub(in crate::circuit) fn value_commit_orchard( + mut layouter: impl Layouter, + sinsemilla_chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >, + ecc_chip: EccChip, + v_net_magnitude_sign: ( + AssignedCell, + AssignedCell, + ), + rcv: ScalarFixed>, + asset: NonIdentityPoint>, + ) -> Result>, plonk::Error> { + // Check that magnitude is 64 bits. + { + let lookup_config = sinsemilla_chip.config().lookup_config(); + let (magnitude_words, magnitude_extra_bits) = (6, 4); + assert_eq!( + magnitude_words * sinsemilla::primitives::K + magnitude_extra_bits, + 64 + ); + let magnitude_zs = lookup_config.copy_check( + layouter.namespace(|| "magnitude lowest 60 bits"), + v_net_magnitude_sign.0.clone(), + magnitude_words, // 6 windows of 10 bits. + false, // Do not constrain the result here. + )?; + assert_eq!(magnitude_zs.len(), magnitude_words + 1); + lookup_config.copy_short_check( + layouter.namespace(|| "magnitude highest 4 bits"), + magnitude_zs[magnitude_words].clone(), + magnitude_extra_bits, // The 7th window must be a 4 bits value. + )?; + } + + // Multiply asset by magnitude, using the long scalar mul. + // TODO: implement a new variable base multiplication which is optimized for 64-bit scalar + // (the long scalar mul is optimized for pallas::Base scalar (~255-bits)) + // + // commitment = [magnitude] asset + let commitment = { + let magnitude_scalar = ScalarVar::from_base( + ecc_chip.clone(), + layouter.namespace(|| "magnitude"), + &v_net_magnitude_sign.0, + )?; + let (commitment, _) = + asset.mul(layouter.namespace(|| "[magnitude] asset"), magnitude_scalar)?; + commitment + }; + + // signed_commitment = [sign] commitment = [v_net_magnitude_sign] asset + let signed_commitment = commitment.mul_sign( + layouter.namespace(|| "[sign] commitment"), + &v_net_magnitude_sign.1, + )?; + + // blind = [rcv] ValueCommitR + let (blind, _rcv) = { + let value_commit_r = OrchardFixedBasesFull::ValueCommitR; + let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r); + + // [rcv] ValueCommitR + value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)? + }; + + // [v] ValueCommitV + [rcv] ValueCommitR + signed_commitment.add(layouter.namespace(|| "cv"), &blind) + } +} + +#[cfg(test)] +mod tests { + use crate::{ + circuit::gadget::{assign_free_advice, value_commit_orchard}, + circuit::K, + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, + keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}, + note::AssetBase, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, + }; + use halo2_gadgets::{ + ecc::{ + chip::{EccChip, EccConfig}, + NonIdentityPoint, ScalarFixed, + }, + sinsemilla::chip::{SinsemillaChip, SinsemillaConfig}, + utilities::lookup_range_check::LookupRangeCheckConfig, + }; + + use group::Curve; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, + }; + use pasta_curves::pallas; + + use rand::{rngs::OsRng, RngCore}; + + #[test] + fn test_value_commit_orchard() { + #[derive(Clone, Debug)] + pub struct MyConfig { + primary: Column, + advices: [Column; 10], + ecc_config: EccConfig, + // Sinsemilla config is only used to initialize the table_idx lookup table in the same + // way as in the Orchard circuit + sinsemilla_config: + SinsemillaConfig, + } + #[derive(Default)] + struct MyCircuit { + v_old: Value, + v_new: Value, + rcv: Value, + asset: Value, + split_flag: Value, + } + + impl Circuit for MyCircuit { + type Config = MyConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + meta.enable_constant(lagrange_coeffs[0]); + + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + + let sinsemilla_config = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[6], + lagrange_coeffs[0], + lookup, + range_check, + ); + + MyConfig { + primary, + advices, + ecc_config: EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ), + sinsemilla_config, + } + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Load the Sinsemilla generator lookup table. + SinsemillaChip::load(config.sinsemilla_config.clone(), &mut layouter)?; + + // Construct an ECC chip + let ecc_chip = EccChip::construct(config.ecc_config); + + let sinsemilla_chip = SinsemillaChip::construct(config.sinsemilla_config.clone()); + + // Witness the magnitude and sign of v_net = v_old - v_new + let v_net_magnitude_sign = { + // v_net is equal to + // (-v_new) if split_flag = true + // v_old - v_new if split_flag = false + let v_net = self.split_flag.and_then(|split_flag| { + if split_flag { + Value::known(crate::value::NoteValue::zero()) - self.v_new + } else { + self.v_old - self.v_new + } + }); + + let magnitude_sign = v_net.map(|v_net| { + let (magnitude, sign) = v_net.magnitude_sign(); + ( + // magnitude is guaranteed to be an unsigned 64-bit value. + // Therefore, we can move it into the base field. + pallas::Base::from(magnitude), + match sign { + crate::value::Sign::Positive => pallas::Base::one(), + crate::value::Sign::Negative => -pallas::Base::one(), + }, + ) + }); + + let magnitude = assign_free_advice( + layouter.namespace(|| "v_net magnitude"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.0), + )?; + let sign = assign_free_advice( + layouter.namespace(|| "v_net sign"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.1), + )?; + (magnitude, sign) + }; + + // Witness rcv + let rcv = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcv"), + self.rcv.as_ref().map(|rcv| rcv.inner()), + )?; + + // Witness asset + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + self.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + // Evaluate cv_net with value_commit_orchard + let cv_net = value_commit_orchard( + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), + sinsemilla_chip, + ecc_chip, + v_net_magnitude_sign, + rcv, + asset, + )?; + + // Constrain cv_net to equal public input + layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, 0)?; + layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, 1) + } + } + + // Test different circuits + let mut rng = OsRng; + let mut circuits = vec![]; + let mut instances = vec![]; + let native_asset = AssetBase::native(); + let random_asset = { + let sk = SpendingKey::random(&mut rng); + let isk = IssuanceAuthorizingKey::from(&sk); + let ik = IssuanceValidatingKey::from(&isk); + let asset_descr = "zsa_asset"; + AssetBase::derive(&ik, asset_descr) + }; + for split_flag in [false, true] { + for asset in [native_asset, random_asset] { + let v_old = NoteValue::from_raw(rng.next_u64()); + let v_new = NoteValue::from_raw(rng.next_u64()); + let rcv = ValueCommitTrapdoor::random(&mut rng); + let v_net = if split_flag { + NoteValue::zero() - v_new + } else { + v_old - v_new + }; + circuits.push(MyCircuit { + v_old: Value::known(v_old), + v_new: Value::known(v_new), + rcv: Value::known(rcv), + asset: Value::known(asset), + split_flag: Value::known(split_flag), + }); + let expected_cv_net = ValueCommitment::derive(v_net, rcv, asset); + instances.push([[expected_cv_net.x(), expected_cv_net.y()]]); + } + } + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + let prover = MockProver::::run( + K, + circuit, + instance.iter().map(|p| p.to_vec()).collect(), + ) + .unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } +} diff --git a/src/circuit_description b/src/circuit_description index 66bdfeadc..212da733f 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -7,7 +7,7 @@ PinnedVerificationKey { omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, }, cs: PinnedConstraintSystem { - num_fixed_columns: 29, + num_fixed_columns: 30, num_advice_columns: 10, num_instance_columns: 1, num_selectors: 56, @@ -17,32 +17,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -57,7 +41,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -72,7 +56,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -87,7 +71,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -129,32 +113,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -169,7 +137,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -184,7 +152,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -199,7 +167,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -272,32 +240,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -312,7 +264,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -327,7 +279,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -342,7 +294,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -388,32 +340,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -428,7 +364,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -443,7 +379,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -458,7 +394,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -500,32 +436,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -540,7 +460,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -555,7 +475,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -570,7 +490,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -612,32 +532,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -652,7 +556,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -667,7 +571,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -682,7 +586,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -735,32 +639,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -775,7 +663,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -790,7 +678,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -805,7 +693,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -851,32 +739,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -891,7 +763,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -906,7 +778,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -921,7 +793,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -970,21 +842,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -998,8 +886,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1009,12 +897,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1088,21 +976,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1116,8 +1020,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1127,12 +1031,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1214,7 +1118,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1338,7 +1242,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -1502,7 +1406,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -1652,7 +1556,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -1778,7 +1682,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -1917,7 +1821,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2061,7 +1965,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2205,7 +2109,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2347,7 +2251,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2489,7 +2393,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2589,7 +2493,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2689,7 +2593,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2789,7 +2693,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -2889,7 +2793,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -3018,7 +2922,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -3109,32 +3013,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -3149,7 +3037,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -3164,7 +3052,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3179,7 +3067,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -3278,53 +3166,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3334,12 +3190,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3349,12 +3205,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3385,53 +3241,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3441,12 +3265,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3456,12 +3280,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3492,53 +3316,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3548,12 +3340,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3563,12 +3355,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3632,53 +3424,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3688,12 +3448,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3703,12 +3463,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3864,53 +3624,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3920,12 +3648,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3935,12 +3663,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -4033,53 +3761,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -4089,12 +3785,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -4104,12 +3800,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -4298,37 +3994,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4342,8 +4022,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4357,8 +4037,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4372,8 +4052,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4438,37 +4118,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4482,8 +4146,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4497,8 +4161,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4512,8 +4176,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4670,37 +4334,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4714,8 +4362,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4729,8 +4377,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4744,8 +4392,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4839,37 +4487,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4883,8 +4515,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4898,8 +4530,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -4913,8 +4545,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -5049,7 +4681,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -5195,20 +4827,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5222,8 +4854,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5237,8 +4869,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5252,8 +4884,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5286,20 +4918,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5313,8 +4945,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5328,8 +4960,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5343,8 +4975,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5377,20 +5009,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5404,8 +5036,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5419,8 +5051,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5434,8 +5066,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5501,20 +5133,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5528,8 +5160,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5543,8 +5175,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5558,8 +5190,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5717,20 +5349,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5744,8 +5376,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5759,8 +5391,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5774,8 +5406,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5870,20 +5502,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5897,8 +5529,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5912,8 +5544,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -5927,8 +5559,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7602,16 +7234,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7626,7 +7274,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -7641,7 +7289,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -7710,16 +7358,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7734,7 +7398,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -7749,7 +7413,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -7847,16 +7511,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -7871,7 +7551,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -7886,7 +7566,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -9732,16 +9412,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -9756,7 +9452,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -9771,7 +9467,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -9812,16 +9508,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -9836,7 +9548,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -9851,7 +9563,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -9892,16 +9604,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -9916,7 +9644,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -9931,7 +9659,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -9985,16 +9713,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10009,7 +9753,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -10024,7 +9768,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10069,16 +9813,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10093,7 +9853,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10108,7 +9868,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10142,16 +9902,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10166,7 +9942,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10181,7 +9957,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10231,16 +10007,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10255,7 +10047,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10270,7 +10062,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10348,16 +10140,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10372,7 +10180,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10387,7 +10195,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10421,16 +10229,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10445,7 +10269,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10460,7 +10284,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10533,16 +10357,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10557,7 +10397,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10572,7 +10412,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10613,16 +10453,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10637,7 +10493,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10652,7 +10508,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10700,16 +10556,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -10724,7 +10596,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -10739,7 +10611,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -10802,20 +10674,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10825,12 +10697,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10840,12 +10712,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11147,20 +11019,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11170,12 +11042,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11185,12 +11057,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11492,20 +11364,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11515,12 +11387,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11530,12 +11402,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11845,7 +11717,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -12001,7 +11873,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -12409,7 +12281,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -12565,7 +12437,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -12712,21 +12584,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 24, - column_index: 24, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12740,8 +12628,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12755,8 +12643,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12796,21 +12684,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 24, - column_index: 24, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12824,8 +12728,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12839,8 +12743,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12880,21 +12784,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 24, - column_index: 24, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12908,8 +12828,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12923,8 +12843,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -12955,21 +12875,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 24, - column_index: 24, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -12979,12 +12931,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -12994,12 +12946,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -13468,7 +13420,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -13577,7 +13529,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -13686,7 +13638,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -13727,53 +13679,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13783,12 +13703,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13798,12 +13718,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13848,53 +13768,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13904,12 +13792,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13919,12 +13807,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13993,53 +13881,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -14049,12 +13905,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -14064,12 +13920,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -14112,53 +13968,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -14168,12 +13992,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -14183,12 +14007,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -14234,20 +14058,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -14261,8 +14085,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -14276,8 +14100,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -14291,8 +14115,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -14306,8 +14130,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -14739,37 +14563,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14779,12 +14587,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14794,12 +14602,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14809,12 +14617,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14824,12 +14632,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14896,37 +14704,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14936,12 +14728,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14951,12 +14743,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14966,12 +14758,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -14981,12 +14773,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15053,37 +14845,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15093,12 +14869,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15108,12 +14884,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15123,12 +14899,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15138,12 +14914,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15181,37 +14957,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15221,12 +14981,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15236,12 +14996,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15251,12 +15011,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15266,12 +15026,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15318,37 +15078,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15358,12 +15102,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15373,12 +15117,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15388,12 +15132,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15403,12 +15147,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15479,37 +15223,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15519,12 +15247,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15534,12 +15262,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15549,12 +15277,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15564,12 +15292,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15614,37 +15342,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15654,12 +15366,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15669,12 +15381,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15684,12 +15396,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15699,12 +15411,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -15788,7 +15500,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -15900,7 +15612,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16012,7 +15724,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16143,7 +15855,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16262,7 +15974,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16393,7 +16105,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16536,7 +16248,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16641,7 +16353,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16746,7 +16458,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16865,7 +16577,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16970,7 +16682,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -17075,7 +16787,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -17180,7 +16892,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -17311,7 +17023,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -17431,7 +17143,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17543,7 +17255,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17655,7 +17367,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17813,7 +17525,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17925,7 +17637,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18037,7 +17749,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18112,8 +17824,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -18124,8 +17836,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -18135,12 +17847,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -18150,12 +17862,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -18165,12 +17877,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -18180,12 +17892,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -18230,32 +17942,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -18270,7 +17966,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18285,7 +17981,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18300,7 +17996,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18315,7 +18011,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18358,32 +18054,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -18398,7 +18078,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18413,7 +18093,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18428,7 +18108,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18443,7 +18123,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18505,32 +18185,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -18545,7 +18209,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18560,7 +18224,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18575,7 +18239,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18590,7 +18254,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18633,32 +18297,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -18673,7 +18321,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18688,7 +18336,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18703,7 +18351,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18718,7 +18366,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18768,32 +18416,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -18808,7 +18440,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18823,7 +18455,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18838,7 +18470,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18853,7 +18485,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18915,32 +18547,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -18955,7 +18571,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18970,7 +18586,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18985,7 +18601,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19000,7 +18616,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19050,32 +18666,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19090,7 +18690,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19105,7 +18705,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19120,7 +18720,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19135,7 +18735,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19171,32 +18771,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19211,7 +18795,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19226,7 +18810,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19241,7 +18825,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19256,7 +18840,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19292,32 +18876,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19332,7 +18900,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19347,7 +18915,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19362,7 +18930,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19377,7 +18945,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19413,32 +18981,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19453,7 +19005,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19468,7 +19020,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19483,7 +19035,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19498,7 +19050,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19560,32 +19112,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19600,7 +19136,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19615,7 +19151,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19630,7 +19166,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19645,7 +19181,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19707,32 +19243,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19747,7 +19267,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19762,7 +19282,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19777,7 +19297,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19792,7 +19312,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19828,32 +19348,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19868,7 +19372,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19883,7 +19387,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19898,7 +19402,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19913,7 +19417,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19951,20 +19455,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19974,12 +19478,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19989,12 +19493,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -20004,12 +19508,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -20019,12 +19523,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -20034,12 +19538,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -20106,7 +19610,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20253,7 +19757,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20400,7 +19904,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20521,7 +20025,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20657,7 +20161,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20816,7 +20320,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20963,7 +20467,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -21084,7 +20588,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -21205,7 +20709,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -21341,7 +20845,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21469,7 +20973,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21616,7 +21120,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21763,7 +21267,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21898,7 +21402,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -22019,7 +21523,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -22140,7 +21644,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -22276,7 +21780,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -22404,7 +21908,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -22532,7 +22036,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -22706,7 +22210,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22834,7 +22338,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22962,7 +22466,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -23136,7 +22640,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23188,20 +22692,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23211,12 +22715,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23226,12 +22730,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23241,12 +22745,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23256,12 +22760,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23271,12 +22775,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23316,20 +22820,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23339,12 +22843,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23354,12 +22858,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23369,12 +22873,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23384,12 +22888,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23399,12 +22903,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -23471,7 +22975,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -23599,7 +23103,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -23749,7 +23253,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -23896,7 +23400,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24031,7 +23535,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24152,7 +23656,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24273,7 +23777,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24409,7 +23913,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24556,7 +24060,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24703,7 +24207,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24824,7 +24328,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24960,7 +24464,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -25039,974 +24543,11 @@ PinnedVerificationKey { Advice { query_index: 6, column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000010, - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x4000000000000000000000000000000000000000000000000000000000000000, - ), - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000010, - ), - ), - Constant( - 0x0000000000000000000000000000100000000000000000000000000000000000, - ), - ), - Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), - ), - ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000200, - ), - ), - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0200000000000000000000000000000000000000000000000000000000000000, - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x4000000000000000000000000000000000000000000000000000000000000000, - ), - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000200, - ), - ), - Constant( - 0x0000000000000000000000000000000400000000000000000000000000000000, - ), - ), - Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), - ), - ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, + rotation: Rotation( + 0, + ), + }, + ), ), ), Product( @@ -26113,21 +24654,47 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), ), - }, - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, ), - }, + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), ), ), Product( @@ -26234,21 +24801,47 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), ), - }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), ), - }, + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), ), ), Product( @@ -26342,7 +24935,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -26356,6 +24949,13 @@ PinnedVerificationKey { ), ), Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, Advice { query_index: 9, column_index: 9, @@ -26363,20 +24963,6 @@ PinnedVerificationKey { 0, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), - ), ), ), Product( @@ -26470,7 +25056,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -26483,47 +25069,21 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 16, - column_index: 5, + query_index: 18, + column_index: 7, rotation: Rotation( 1, ), }, - Negated( - Sum( - Sum( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + 1, ), - ), + }, ), ), Product( @@ -26631,21 +25191,14 @@ PinnedVerificationKey { ), ), Sum( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - Negated( + Sum( Sum( Sum( Advice { - query_index: 16, - column_index: 5, + query_index: 7, + column_index: 7, rotation: Rotation( - 1, + 0, ), }, Scaled( @@ -26656,20 +25209,39 @@ PinnedVerificationKey { 0, ), }, - 0x0400000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000200, ), ), Scaled( Advice { - query_index: 9, - column_index: 9, + query_index: 22, + column_index: 6, rotation: Rotation( - 0, + 1, ), }, - 0x4000000000000000000000000000000000000000000000000000000000000000, + 0x0200000000000000000000000000000000000000000000000000000000000000, ), ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -26780,13 +25352,25 @@ PinnedVerificationKey { Sum( Sum( Sum( - Advice { - query_index: 16, - column_index: 5, - rotation: Rotation( - 1, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, ), - }, + ), Constant( 0x0000000000000000000000000000000400000000000000000000000000000000, ), @@ -26914,17 +25498,17 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 9, - column_index: 9, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, Advice { - query_index: 8, - column_index: 8, + query_index: 22, + column_index: 6, rotation: Rotation( - 0, + 1, ), }, ), @@ -27035,17 +25619,17 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 9, - column_index: 9, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, Advice { - query_index: 18, - column_index: 7, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, ), @@ -27154,6 +25738,254 @@ PinnedVerificationKey { ), ), ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 16, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 16, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Advice { + query_index: 16, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, Product( Advice { query_index: 9, @@ -27672,6 +26504,15 @@ PinnedVerificationKey { 0, ), ), + ( + Column { + index: 29, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), ], permutation: Argument { columns: [ @@ -28342,47 +27183,48 @@ PinnedVerificationKey { (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), - (0x0ba01714529dc85dd2460cdbf014b71e7638d18a35eacf06868020c27c28232d, 0x2dcbb2c3191f582b6882cc9c5e6cac1a0361d0534f8f4c814e33a272b8e8da8d), - (0x0f8fb02c096c0957230639133087e8ae516d04d1678ace6ab0495a8e8576c0db, 0x2842b28258744140b09e0d27559d84e1d8f1d55350b0af37237879d14f8eb2a1), - (0x36f2f0410d5ab00d5296bf101cbd91008551d4afe2b5ac45fc437aa157c731aa, 0x19e8c688f0c92a3db3e74b66075d2e0771d5c744e77090c487ffca245a7f7f96), - (0x09ce7fd65bf8af2b554230465003160d3d0b7bfc495f6d33f5f0704cb57d6320, 0x38d3478df8841a4f7a74a3c1fe7788e6e1cbb1076d5f7358be729fa2572c9530), - (0x2abaec8c54bde721f7f2aea685764c80b0b935447c00173ff34209ac8d96b633, 0x36957cf784345bfbdb97f0fad0b74d3e5d683fcc80ee407d6a6bedfe097c0011), - (0x3f1845e758196892c66d920980dc29cc2e1844fa03575668bf84349071094207, 0x1873355bc49aeed1faee56e6d21907a5277fcd0283a3f51fface877e1c59f046), - (0x04e5834f610cf806911a2e9c14519132a49ac55f40095c3156e3b20d09a2f250, 0x2ea666b99d148e1090b42fd2f67fd34c7e94ca505447c1431485eca09ed1fe0b), - (0x35de09079a5b05d25f756479ea044c654c97043bc4a79b34f860faa9b049337a, 0x06c4cc500093cfdc9bd284f3c44a2a8856cfc8ce70786dd65787397292e4fe53), - (0x235b63a940346f07c5a669831067ba59acb3b9936db7d66c4a4cf6746af5f97e, 0x0d838f859fb1386034263d43ace744961a310f548f7274586f133aa4ddc779a9), - (0x02adb7cbc9ebbbd87d7d6a41fc40cb4cf57585c6243aa204f757c9026ef20fd3, 0x327fc06fee179c6a57ed95336f9fb7854420d80dd191251a40935664ff6c8067), - (0x2d00d4ec8aa5e4b3d035131f559e4a97f896e8dbc39badb92b58a8d46b5e91df, 0x37046fb32ed8eb4ba0b4da8e1c9b56cd3832fa2ed4788f7faf4fee1f76a94c32), - (0x1e5ddb2d4ee82f8d1982eb0333d98528efeb71f4d413fea2f1eed9e2c4d19dc3, 0x3e092c6d429d9f7d5b5a729af533e7b9e943752835b540060a2e0e31aa25958e), - (0x02c283cbde85f2ad26daddeabe01b1574ce7de68f0e329ec95a4154dd4713f29, 0x208cf96aa5255b543933ee3e9bdd054d4f15265a7c8921aaee89c192af2fd284), - (0x1f777f0e4263ec4a19f30813739c640335ffa951cc3cc586b6c4095e737f95be, 0x061c07fb12cb19582eefd858a08e689acd970c8cb9ed8f7b928d88e691a2f586), - (0x13d0bd76da4ace22c0e90b098d6073551322b8c734bf37eeca67fbf19687f550, 0x3d996cc9da5a31cefb453390b906eabbcc75797bc6a6b9c9e3af2fe7b6b8beed), - (0x088ced578c98f9634cd7aba72b2ff3c6a43109aca67cd1cdc0717a70da32aebf, 0x1a17c29333cc59a199472807282d2b8364baf57ac00e8c29f51dcde32f0b6549), - (0x0525a1d721b05a02ee6e9580254e13213ada10c168213fbfebc7c1c71de072d2, 0x2edc5a41f195c2cc25cefce1405af856721c23dadb1728b2ff3335f08118c4c6), - (0x02e4214937491f7c86b1e37516f7ad0d030beeeab0149ef9062a7ec77604890e, 0x3d1763bcb3f7b989fccb1376b291dfbaef0e139ce4e3f43854fe507bbaad59d5), - (0x3f9542a72fadf26c1931411e1d690e89fef20b05a20f9706f1231e23adb00082, 0x0676af65a2925d168339df2b8dcee0139cbbfaec9470ed902ad600362602737d), - (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), - (0x1e355d783cffccafc120f462461fb312773442762383ac444009653f3d8d4be6, 0x3c60e17b18492aa2c41798b409d2bcc1857ca57ee9d2fb0001584cedc8e141d6), - (0x18909046614ff6e61f755dbbb92989aac36dfa3d92fb8b54a37600ccb8cfba82, 0x053ec2a2bdc4e2771bfd6bc883c02db47d38d199bdab01adea7b1a272f223b7c), - (0x23a3dcd68c8a837c9eb84436ab2a184973d6fd3a1ba05d92d6fd747d23c799b0, 0x3f3802f0cfeaaae7f5f766bd3231299654bfd0a5d27b7f1d2ea93bee3d95b4b8), - (0x2331a44c6cf195b1afed0198fbe5a39da809e9815252a0aaa71a45803c81fb3b, 0x3223527d36e068b4821c95d09de240340564a5884bd6363ffd0c2f1961871651), - (0x2aa6286d3aba61beb097804a736279e5d0df5be592d21bdf04b1c418a2a20c69, 0x2d48db2dceacb16afe698d7a8314a2870939101a5cac866a70a946f3c46c3e73), - (0x1a81a317cb5b7169c17c6568fb7641cbe98969f8bee26164544c8cf3b8b4ac3b, 0x003012d4d94fc0502d0c8fd0322de8d1317a30fd8282a07f3eed945c678faf3e), + (0x212ebe88f06142f838a0c5c4496fa768ae3ca10f1ce9022c562b26bfbdc498c3, 0x2b6528f6317e63892bed284c67f112218631e191be7d5fdc5cdf7b9e92c72e05), + (0x034445b7457e04150c75a6c82e6f83ce2e1adf0e54aae2cfef0531b24dde111f, 0x30a7f9ce9bd574162a4729f71d8c7f0c61a4b7de6aa0181eefad3693aeb09c10), + (0x2a119980555858bc332f02295311e188f6125be71b5e591fff068a5024571aee, 0x23803ce939432804d484b29078c9c161015408e5e383a8cfc8c13a30502c9400), + (0x085620965e456f2f2b98a365768c7be2e43577bd0ef92a50cc278d521e983e9f, 0x3f1f003651d27a02d609eb61fbba5e74bb61c63b5afcce2c683948c5caa22791), + (0x3dc695372b0d52f554c7ab1cee168937f45f3abdd2e8fdf65f3b523ec85a499a, 0x33ef73e550024b2285b082816eb8818e80255973d9560fd437387cdb870190f1), + (0x1028b99218dd2642e60b90b28ae9cecd4be814de17a429314530f9a8695ce1c8, 0x2592dc76f783462d5b3bed02626ef2514deb59b7a6a8438ff64fdf6aafa00d4f), + (0x10fea717c33f17c73458742a1431679d61a436da080918e030b1760627a9538b, 0x0faf9983733b318f75d91c0c1131cfe7c67ef5474657d36c5ecd566b9629b6cf), + (0x3c242ccdb145d93f2cf312fbaab513b66b4cacd30de01fe193984aec912dd1a0, 0x1fa195c07847db8e31bdf7993ea787c9656a9d86babdeeddb76817d3c546348c), + (0x3229e787cb7ce31299dedd67d2631c480399a333098f84e7577132aac163ec8d, 0x3822eb1cc8eb19179373ea6b66b25b26ac8c915f0c9382800dd45a5a408fd1fc), + (0x10f84d5a9fad7c64be8a3529d1dd98c0961df4bb677b6a60714ddb053792998e, 0x0f032b93492b60aed3339d5646e15d2a9a46557cb01621b8d3d1392207ed0021), + (0x1d5193db32232d750432a8ec23f74307ad8194a0a4ad273c9b761b4e0f365d0b, 0x0b73549978b1c24dcbb39570d9fab795337f6030f2fffb9452b5edba0dcd2906), + (0x12967b9d3412c47744d16acede02d8214db2def9bfa643cc3da724f3f4edecaf, 0x3744e1519dcf0ae6bdc813ef1a123fd7978c073232164050a9a24fcd57d9a0a2), + (0x02602bfa02be45cec73e24099a3ff88e66386fc8a55f60af328afe5a68007233, 0x3db6b250fdd9abcc16f17275cc83ac66c9a2d91954dce867f23497a3ad85a85e), + (0x274c6a300449842b07918941f243beac24a66bd9870bf0b1c59b0b6056200a73, 0x1a19946639473486c5aebb6f2c7f0ed9bfa6a072a37857b9cbd801174b6a152a), + (0x2280ada329e3a43f320cdd86e0cfbea20620a02c772fccb8f34091832b9c4e1c, 0x0f47924c100e3c314835e8e1112a21a9aa54122548b5a2fbf1ddca681f64d148), + (0x2cde628fe6b43f6d0a2406f020530790a1c03642bec15a27e4883830f1906f75, 0x269f42895d8fb9cdc21fe307bf0cf994bc8d4f57f5c9757d7e7f491f67218f41), + (0x385b8c0d2d99558538cb3a9f9032a5aa40e73909f80c72d4b56dabbd35da1edf, 0x3926c421e68c459e921bc92c452b6d471810358c9c9941d0e15255f07e81f52a), + (0x365be6624d5ddbced07b7759377bd70f42ef5c0727849dcf4295e2be882a1229, 0x2379fbecf58b756b83626b73e0a4fe3043b6f6f7d3cca1c35ae298993be00b55), + (0x3992f02cfe9f649c235efb0b12057bf4a6a23de1e9186ecd4755cde6af9f18a1, 0x3defc298ff6d6e34e250f303089cc3ff36f9960f3c37dbff959ec4d722c21354), + (0x0b89c282c8f2d54e66c7a11e6b4338a2f06a7c9430f7d3376328f12fa001cac5, 0x098b5c8ee6548183ccb4e60cdfee10b509db34ed136daf3530a426e8f200e89d), + (0x2f7f85b86b6adcf714d0df7878f4604d33fd319f39bd00fd5c34378247a155b5, 0x3a2f025447b83b65d148e99c93fe8bb991a81ef6d2f827f010680467361c47fc), + (0x1c2d777a98c9dbcf31b45d5a7584b154daed974f3263b6a93831d53bf593e6c2, 0x234766a4b905ed9627f6a200a7b0b50315203613a5b211494a94cf21fb4c386b), + (0x2ebbe4228a40b24bc3f05a07484c2d470ca997d5fd030a26c3c475fd24c5f71b, 0x00f27b013a7a80f1221a9fcf44332b3842ac2af0af4a7108e966f765d8ccebab), + (0x1484b5ee3bd870af246676953341b0825bac76cbe5a753c014bbd04c499c3946, 0x09860840096085811328952d906cdf7bdb748db7e08157d96b3252f909cbc6a9), + (0x13c4224160178c41c828d952f78a8a0d58321a7894cee8f2884c5d1d9e3246ac, 0x3699ad2eb29f2cd4825c0e7cbde86eb19889a00f4afd8cbe40d2eed7c7efd565), + (0x3e6b0d18402a8533aa2c9a681ef0c9c3636154feb1a95b6a50c522833f6e2cb1, 0x20336e540af50c99ef3208ff5dc2f4f0deb2c8beb8f1b3da046eebb05e39deee), + (0x16e89e0cf09f1d68ce3f16728839b4973604d9cad2a6ae3114ce75ce5cb7edeb, 0x1db108cbdb6e1af19ca087d3649ac673d59ced15e6780957d26a83aa8865f116), ], permutation: VerifyingKey { commitments: [ - (0x39c3094020a1b893afa09240d88a468f5803f8c67efd9bb4b1c0bfb94dab6271, 0x0416775ce28cc7214bd6573f9c5e3f2972abb9f4468c1acf8dd5005dcfc3841f), - (0x1eee618d6829a4cbe8bcaad592b532e181af07bdc5074bcfed31b08ade1e27a8, 0x1bcec4c593b72804ac2e9eaa9706b38aae13ad1898cfc11c547741c73e63c3c6), - (0x37be1e93e1e474611af94327cb85b27f652a1b1bbfd952bf3ee45be138918fe0, 0x250bffe2eacca2244b2ae88dccc8c0678f8d3b0ba4d1e4f663dcd95eff0be5cf), - (0x2d95cfb99fce4d1ce1ab680674b4344cb0689c82bb667953a88d25f73a07a3a6, 0x30b015209e497612526ce2b940f38b73608a791bf1b9081ec6592aa4a3b3d6e2), - (0x20384319aa772450c3f144ad974a5ba707e863419e0d035d8c60debaaeff9283, 0x3909e58668259a03f10d849f032963686cf15e49ff5c993bbbf4b913c1e57d6b), - (0x1240cf41a87879f67dab54f4580882aea1d1b5154b821c0c40b15b9635d0487e, 0x1792251c1ac4a5e689b6d75696d7cfd3d157561e5dd5c48508add90da16d7a51), - (0x0546256e9b7ed28e1bd03fba20aab2f954f477856c7cd26e81c11e31065a0820, 0x1ff390755b1b4a2568762672a7a62e147f12a1cbe8a898dd4b078f5b7bf47253), - (0x322ad473ba02ff5d65ef29f0593b823a974cee815177a9f946bd1dd09f5d8fd3, 0x3dc0527f997c8c0948b32dbaf41e1d8c5cd057152fe54a6c8ea9f7d20285c111), - (0x2ab170c47a1311a82abf11d9f34b6fb47f4955740987f6a2afee3c9a7544dfb3, 0x0513f4a2c077a7c6ed881afe96c90e8e13d31c22b5f53a4203f75c7011bc72f5), - (0x085e66ccf3a3667cdbb2d5abaa37d339b594c079e3a06bf2cda8345a2fffcd88, 0x36da573fe8112eec770349dbcae747acb8a513b0504606285970d653bf25c2e2), - (0x2aa7abe46cd3f3786469fd351047535d2596525d93573a6af9044a223e1fc170, 0x246a8655cc204e81045bdc047627c364f7e501ac24a89372a1dbcb8a515d6016), - (0x1ad163c8b2e5840d94fe2925b62824788b50bd130c6deb3dc01f2f77d246c6eb, 0x2f3657736db088a93fba26e49be620728061d989717ba60899d22e22dfd7ec6f), + (0x12dbf09e55d044102f1ae361e8d266b69e1718e1d624b96e77b3cfa1feceb732, 0x31caaac60ce9718af01c87d262fec2c754c77550d8bb35e63f8b07fa9c89fc66), + (0x22da488fb2f178bb8139f14a2aec59c91799533c774af776e94c104f7687c421, 0x2af740c09b699a113bfc6e74b029298d54af6bfb0b92da9c1b0bded28625f450), + (0x2b48b45f4a5a2b4d3605d823a561d7cf0e0ba56c0cbc5d40b58b1b8ea7e36ae5, 0x1035a22259f1b163d3aeb91785cbda566f1501d75011335fa62a0f904c1cb318), + (0x16940bc043dab8afc2a1459edac40382bd790dee8c14db086c4619dc53ebb2e9, 0x1ad505a146f27451d13f90c75b8651eb10a3f67cc6609ea75ca71eee7c1c157d), + (0x3a3ed02c9cbf7b5d099b4c7e3f12f46f3fd898e07f8e7a4f707b1df7f5de3ac3, 0x1d90e34b6d292a48989e3fd47d0eee2ecdffe086ce57e43e1c98dd63ced3fcda), + (0x1f622082868867262854bb7e8cf99d8414bbb244abffde123330b8aed84bd92d, 0x244be4573a4986eaff1e2a6beaa0aecdcdb361540f0b8cf4db289242c6eaefc2), + (0x2d8cbc3dc5fada2ddb980b66a31f57cb02af14982712cb1a12c0d11945811a0e, 0x330cc47c866342bdcd769f9c4ac214a022894aaa4f706182ac5b9e7abac7b2ee), + (0x0367c84844db2532b1fe3833504c46fb366ed8a6b91053a64bb820b5407ba0f1, 0x17fab750fb792623f23d091a07bbc30ce0a669d7270ea36ca38b934bb3caa135), + (0x088b09cd2e59ab2d95dd62077692f366604d9dbda58f7915e5b7c4874cb7ac17, 0x3ce41c4b67191c663c5c5e2413b5359bf55f2d59b65f91b086a2aadfaf4816a2), + (0x230701deaa69a778874d4fa8682366c61954107150807386f5d335157eb93395, 0x000d66512afd16ccc26d6d086a116dfd6f246ec5e4817a71832244218ac6fd9b), + (0x3b7b47bca87fc15cd5565b546ce7624078f7cbf71d4ef78360740cecc16a6415, 0x20ab204faaa0df261b922ee76d97057b4bfa1fb7f2e50015b2aae29d4dbb820c), + (0x07ff65506877a9a21905ddfa323607a02794f495d6448484fda71859af8d51db, 0x0fb1605d3e8d4a77121e70e1339b819825cf04c10edf28b4bf5238a836608c74), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index fe636afae568d1de011e6fded98e266980089870..5dd1fc5e7183999c1b9ac0de02fe9397a2e426e6 100644 GIT binary patch literal 5186 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

5z4f$eYFG}{=|M7 zj-)dQb8+2}Tkk)PwcmP3`)=vk1YQJbjZgkM%$|>q`za+&^-#mebwakBfkQ@jHEIbm zH~5W>azj2XZ^8sb=Gf-y{soU4rPxEUAgp$njsWQv7l~zh+u)`Ft`P|_c(RIUtAd6Q z+IK7G8%#_J#Sz|HD&TL}YX649Cot)@nw(zvCR%+_FDZ@F=Oqf~f_=n=3ktx;hmf4{ zTz^scMM563CFYyMTNj5UKVD2M>SNnfNl8;Iuz*X|?R3J^1znLL-N7V0DUImd&8>7;) zu?s{nwQ@$JPsTJdBumCaI6N#lrGD>uqML9_ zF&5dbS(8(`1J><;h)xHA%4$=xG2UEdDw^%L@JI1fn2q zk?2SfbaZraH-U8D2MBB+?qG0DSXSMJQEFtJxv<2L8OJ!W-UT?I=bL&(8({QUfs0)f zVZaI8kO33iY-kO}0(((xnth+;3T60p7ym%1Jbe?e)$vg7NYGzirqNjN<$o6?{{!(z z=~ZWw30A1ynpj6Z2vQZefNP`$1?Mvs>@9x_{2pPf){xW-rme_qtv*>U_u=NThCa32 zn*U&1QRgCxt|u?L4Ji-a?s+Puz((n}RyW@XX!Di8-0 zOA0P6Ss%TUo;_=voo~$)Z)(4Q5BA)>`Kg;iA|}id%GhFE9n4#(uQ?sT|C!nWH?{bE zsE~B78JdD*j5)GS!(9w*c%pNNClG(0>=Em<^xAnrAg1IBnk+RYvw-7qrgj@Fo@c*X zJ#il`N~=6DVdOiWS~o0O;Y&(DdK(?D__sTUzmA_pNy z58u$qw7tUK+yurk38Ws-TLWo1fxn8j>`MaNM;VAgF0ST8C?PW)e{Zo4kNYhV%3F#> zHgX&+nWtrHK=0J#>DAr5C_=f-SFD03Iye0ynbp%oR6}jQN8Yeg`RXwa3z;l-Csds< zLw)i&gj?tzT*%d9yRZ|eY%u0bL|jXZq<5kDBao=c<5YB129eo6w|3J2q&96@o04bf z?vqrI{X>AUQ?Y9%LHnNYnB{xR;AgS1#Thu&{$89!LnW{seU3w{(1qRa!7m*UD&cH_ z`F>uY-Ha!EvI8ZI^x#q}aeI&UVK_IFL}Rcg5$~Ghem%E$rQ+LKLps2lSKd`k!l6eE z2KAzdKDV=A5e(e}JN!892oX#5^@8OBMFJ88aM0jnHD3VGub=nM7LJlvoL((n56p Date: Tue, 25 Apr 2023 14:46:26 +0200 Subject: [PATCH 24/92] Constant-time note commitment for ZEC and ZSA (#54) We would like to have a constant-time evaluation of the note commitment for both ZEC and ZSA. ZEC_note_commitment=Extract_P(SinsemillaHashToPoint(zec_personalization, common_bits) + [rcm]R) ZSA_note_commitment=Extract_P(SinsemillaHashToPoint(zsa_personalization, common_bits || asset) + [rcm]R) R is the same constant for ZEC and ZSA note commitments. --- Cargo.toml | 4 +- src/note/commitment.rs | 96 +++++++--- src/test_vectors/keys.rs | 63 ++++--- src/test_vectors/note_encryption_v3.rs | 240 ++++++++++++------------- 4 files changed, 223 insertions(+), 180 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e482b0f76..17656f550 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ ff = "0.12" fpe = "0.5" group = { version = "0.12.1", features = ["wnaf-memuse"] } halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } -halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } +halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1"} hex = "0.4" lazy_static = "1" memuse = { version = "0.2.1", features = ["nonempty"] } @@ -52,7 +52,7 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] criterion = "0.3" -halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" , features = ["test-dependencies"] } +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" zcash_note_encryption = { version = "0.2", features = ["pre-zip-212"] } diff --git a/src/note/commitment.rs b/src/note/commitment.rs index f95d8be82..18024afe8 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -4,7 +4,7 @@ use bitvec::{array::BitArray, order::Lsb0}; use group::ff::{PrimeField, PrimeFieldBits}; use halo2_gadgets::sinsemilla::primitives as sinsemilla; use pasta_curves::pallas; -use subtle::{ConstantTimeEq, CtOption}; +use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption}; use crate::{ constants::{ @@ -56,35 +56,42 @@ impl NoteCommitment { let rho_bits = rho.to_le_bits(); let psi_bits = psi.to_le_bits(); - let zec_note_bits = iter::empty() + let common_note_bits = iter::empty() .chain(g_d_bits.iter().by_vals()) .chain(pk_d_bits.iter().by_vals()) .chain(v_bits.iter().by_vals()) .chain(rho_bits.iter().by_vals().take(L_ORCHARD_BASE)) - .chain(psi_bits.iter().by_vals().take(L_ORCHARD_BASE)); - - // TODO: make this constant-time. - if asset.is_native().into() { - // Commit to ZEC notes as per the Orchard protocol. - Self::commit(NOTE_COMMITMENT_PERSONALIZATION, zec_note_bits, rcm) - } else { - // Commit to non-ZEC notes as per the ZSA protocol. - // Append the note type to the Orchard note encoding. - let type_bits = BitArray::<_, Lsb0>::new(asset.to_bytes()); - let zsa_note_bits = zec_note_bits.chain(type_bits.iter().by_vals()); - - // Commit in a different domain than Orchard notes. - Self::commit(NOTE_ZSA_COMMITMENT_PERSONALIZATION, zsa_note_bits, rcm) - } - } - - fn commit( - personalization: &str, - bits: impl Iterator, - rcm: NoteCommitTrapdoor, - ) -> CtOption { - let domain = sinsemilla::CommitDomain::new(personalization); - domain.commit(bits, &rcm.0).map(NoteCommitment) + .chain(psi_bits.iter().by_vals().take(L_ORCHARD_BASE)) + .collect::>(); + + let zec_note_bits = common_note_bits.clone().into_iter(); + + let type_bits = BitArray::<_, Lsb0>::new(asset.to_bytes()); + let zsa_note_bits = common_note_bits + .into_iter() + .chain(type_bits.iter().by_vals()); + + let zec_domain = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); + let zsa_domain = sinsemilla::CommitDomain::new_with_personalization( + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + NOTE_COMMITMENT_PERSONALIZATION, + ); + + let zec_hash_point = zec_domain.M.hash_to_point(zec_note_bits); + let zsa_hash_point = zsa_domain.M.hash_to_point(zsa_note_bits); + + // Select the desired hash point in constant-time + let hash_point = zsa_hash_point.and_then(|zsa_hash| { + zec_hash_point.map(|zec_hash| { + pallas::Point::conditional_select(&zsa_hash, &zec_hash, asset.is_native()) + }) + }); + + // To evaluate the commitment from the hash_point, we could use either zec_domain or + // zsa_domain because they have both the same `R` constant. + zec_domain + .commit_from_hash_point(hash_point, &rcm.0) + .map(NoteCommitment) } } @@ -140,3 +147,40 @@ impl PartialEq for ExtractedNoteCommitment { } impl Eq for ExtractedNoteCommitment {} + +#[cfg(test)] +mod tests { + use crate::constants::fixed_bases::{ + NOTE_COMMITMENT_PERSONALIZATION, NOTE_ZSA_COMMITMENT_PERSONALIZATION, + }; + use crate::note::commitment::NoteCommitTrapdoor; + use ff::Field; + use halo2_gadgets::sinsemilla::primitives as sinsemilla; + use pasta_curves::pallas; + use rand::{rngs::OsRng, Rng}; + + #[test] + fn test_commit_in_several_steps() { + let mut os_rng = OsRng::default(); + let msg: Vec = (0..36).map(|_| os_rng.gen::()).collect(); + + let rcm = NoteCommitTrapdoor(pallas::Scalar::random(&mut os_rng)); + + let domain_zec = sinsemilla::CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); + let domain_zsa = sinsemilla::CommitDomain::new_with_personalization( + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + NOTE_COMMITMENT_PERSONALIZATION, + ); + + let expected_commit = domain_zsa.commit(msg.clone().into_iter(), &rcm.0); + + // Evaluating the commitment in one step with `commit` or in two steps with `hash_to_point` + // and `commit_from_hash_point` must give the same commitment. + let hash_point = domain_zsa.M.hash_to_point(msg.into_iter()); + let commit_r_zsa = domain_zsa.commit_from_hash_point(hash_point, &rcm.0); + assert_eq!(expected_commit.unwrap(), commit_r_zsa.unwrap()); + + // ZEC and ZSA note commitments must use the same R constant + assert_eq!(domain_zec.R(), domain_zsa.R()); + } +} diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 02c9cfc78..8fa650a37 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -1,4 +1,4 @@ -//! Test vectors for Orchard key components. +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_key_components) pub(crate) struct TestVector { pub(crate) sk: [u8; 32], @@ -26,7 +26,6 @@ pub(crate) struct TestVector { } pub(crate) fn test_vectors() -> Vec { - // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_key_components.py vec![ TestVector { sk: [ @@ -654,14 +653,14 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x08, 0xcb, 0x05, ], note_cmx: [ - 0x71, 0x99, 0x1e, 0xeb, 0x4b, 0x51, 0x7e, 0xd9, 0xd4, 0x31, 0xdc, 0xa9, 0xa2, 0xbb, - 0xcf, 0x1c, 0xe8, 0x75, 0xe8, 0x55, 0xdf, 0xf4, 0x8c, 0x69, 0xf4, 0xef, 0x51, 0x01, - 0x1e, 0x86, 0x1e, 0x07, + 0xf1, 0x34, 0x33, 0x5c, 0x60, 0xf3, 0x17, 0xec, 0x48, 0xd6, 0x7b, 0x49, 0x34, 0x58, + 0xde, 0x26, 0xb4, 0x06, 0xfd, 0xd2, 0x10, 0xf8, 0x60, 0xb1, 0x81, 0xaf, 0x7b, 0x82, + 0xcd, 0xe9, 0x4e, 0x37, ], note_nf: [ - 0xdf, 0x79, 0xd4, 0xa4, 0x6e, 0xca, 0xfd, 0x34, 0x50, 0x9d, 0x41, 0xfc, 0xfb, 0x61, - 0x3e, 0x1f, 0xdc, 0xbc, 0x0d, 0x3b, 0xa0, 0xaa, 0x8d, 0xe5, 0x04, 0xd6, 0xf2, 0x54, - 0xcd, 0x55, 0x12, 0x32, + 0x75, 0x6c, 0x1f, 0x4b, 0xfa, 0xae, 0xc5, 0x5b, 0x42, 0x0a, 0x4f, 0x88, 0x12, 0xdb, + 0x6c, 0x43, 0x2e, 0x48, 0x61, 0x6f, 0xb8, 0xd1, 0xbb, 0x2b, 0x1d, 0xd1, 0xe7, 0x2c, + 0x0a, 0xa3, 0xdb, 0x3a, ], }, TestVector { @@ -760,14 +759,14 @@ pub(crate) fn test_vectors() -> Vec { 0xa0, 0xd4, 0x70, 0x19, ], note_cmx: [ - 0x94, 0x81, 0xcb, 0xac, 0x4e, 0xb0, 0xc0, 0x8d, 0x12, 0x83, 0x47, 0x13, 0xb5, 0x15, - 0xfd, 0x8c, 0x61, 0x0d, 0x44, 0xc1, 0x29, 0x50, 0x97, 0xcc, 0x20, 0x13, 0x4d, 0xe2, - 0x1c, 0x63, 0x6c, 0x29, + 0x07, 0x1c, 0x49, 0x8b, 0x02, 0x6b, 0x8b, 0x1a, 0x7a, 0x1e, 0x84, 0x00, 0x13, 0x87, + 0x20, 0x82, 0x3d, 0x80, 0xec, 0xa4, 0x99, 0xac, 0xd2, 0x91, 0xfc, 0x07, 0xfd, 0x2f, + 0x41, 0x6e, 0x83, 0x38, ], note_nf: [ - 0x44, 0xc8, 0x8d, 0x03, 0x10, 0x21, 0x56, 0x11, 0x25, 0x6a, 0xad, 0x07, 0x34, 0x99, - 0x43, 0x08, 0x94, 0x59, 0x73, 0x17, 0x15, 0x75, 0xae, 0x7e, 0x89, 0xf5, 0x8d, 0x44, - 0xde, 0xa2, 0x67, 0x10, + 0x22, 0x55, 0x5e, 0xe7, 0x85, 0x46, 0x8c, 0xc7, 0x70, 0xca, 0xf9, 0x0f, 0x82, 0x61, + 0x1b, 0x80, 0x15, 0xb0, 0x3d, 0xd8, 0x85, 0x6c, 0xc9, 0xa2, 0x7c, 0xbf, 0x7f, 0x5c, + 0x31, 0x3d, 0x96, 0x0e, ], }, TestVector { @@ -866,14 +865,14 @@ pub(crate) fn test_vectors() -> Vec { 0xe5, 0xe1, 0x71, 0x1c, ], note_cmx: [ - 0xfe, 0x09, 0xf5, 0x89, 0x7c, 0xed, 0xc7, 0x67, 0x7c, 0xf5, 0x80, 0xc5, 0xf0, 0xd1, - 0x83, 0xed, 0x3b, 0xc0, 0x94, 0x5c, 0xb1, 0xc3, 0x85, 0xf3, 0x88, 0xf9, 0x3f, 0x94, - 0x3e, 0xff, 0x2a, 0x2f, + 0x7b, 0xc1, 0xdd, 0xba, 0x52, 0x06, 0x14, 0xdd, 0x4e, 0x44, 0x3e, 0xaa, 0xf2, 0x5b, + 0xea, 0xa0, 0x14, 0xc2, 0x78, 0x6d, 0x15, 0x0a, 0x3b, 0x6f, 0xea, 0x97, 0x6a, 0x9b, + 0xdf, 0x27, 0x02, 0x04, ], note_nf: [ - 0x80, 0xdf, 0x21, 0xbf, 0xeb, 0x46, 0x06, 0x16, 0x06, 0x29, 0x61, 0x03, 0x86, 0xc7, - 0x99, 0x02, 0xef, 0x49, 0x8b, 0x61, 0xb1, 0x55, 0x0c, 0xbd, 0x10, 0x55, 0xf8, 0x26, - 0x94, 0xfa, 0x5b, 0x03, + 0x78, 0x31, 0xe9, 0xc5, 0x1c, 0xc1, 0xdc, 0xa6, 0xda, 0x89, 0x1a, 0xde, 0xad, 0x3a, + 0x79, 0x24, 0xff, 0x26, 0x4b, 0xe4, 0x25, 0x0b, 0xec, 0x05, 0xc5, 0x92, 0xd3, 0x14, + 0x52, 0x6b, 0x1a, 0x2f, ], }, TestVector { @@ -972,14 +971,14 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0xdb, 0x41, 0x87, ], note_cmx: [ - 0x5e, 0x54, 0xfe, 0x7e, 0x59, 0x52, 0xa6, 0xea, 0x26, 0xba, 0xbc, 0x32, 0xcf, 0xed, - 0xf5, 0xe6, 0x0b, 0x56, 0x82, 0x58, 0x98, 0x0d, 0x92, 0xc1, 0xe5, 0xdd, 0x3f, 0xdf, - 0x3e, 0x48, 0x7e, 0x1d, + 0xea, 0xf9, 0x49, 0x1c, 0xab, 0xca, 0x20, 0x07, 0xba, 0x91, 0xea, 0xc9, 0xb3, 0xc0, + 0xa1, 0x1c, 0x58, 0xef, 0x5f, 0xe0, 0x71, 0x86, 0x8c, 0x66, 0xf1, 0xc5, 0xf5, 0x9c, + 0x7c, 0x99, 0x25, 0x14, ], note_nf: [ - 0x45, 0x5f, 0xd0, 0xe5, 0x2e, 0x59, 0x33, 0x62, 0x57, 0x2d, 0x12, 0xdb, 0x44, 0xbb, - 0xf0, 0xe0, 0x95, 0x8a, 0xf9, 0xd5, 0x8f, 0xbd, 0xf9, 0x7b, 0x85, 0x22, 0x8e, 0xca, - 0xd0, 0xde, 0x7f, 0x05, + 0x3a, 0xbc, 0x17, 0xad, 0xee, 0x2a, 0xa8, 0x8d, 0xf8, 0x93, 0x99, 0x4f, 0x1a, 0xf2, + 0x71, 0x51, 0xc1, 0x8b, 0xa6, 0xa9, 0x89, 0xc4, 0xbf, 0xfb, 0xb9, 0xa9, 0x18, 0xd5, + 0x50, 0x71, 0x95, 0x02, ], }, TestVector { @@ -1078,14 +1077,14 @@ pub(crate) fn test_vectors() -> Vec { 0xca, 0x26, 0xfa, 0xc4, ], note_cmx: [ - 0xdf, 0x1e, 0x28, 0x2c, 0x9b, 0xf3, 0x09, 0x72, 0xb2, 0x8c, 0x46, 0xed, 0x8a, 0x54, - 0x42, 0x6d, 0xae, 0xc1, 0xae, 0x38, 0x1a, 0x38, 0x5d, 0xf2, 0x5f, 0xff, 0xfa, 0x66, - 0x79, 0x53, 0xd3, 0x33, + 0x22, 0x0c, 0xf6, 0xb7, 0xbd, 0x7d, 0xf1, 0x1a, 0xeb, 0x46, 0xb8, 0xf6, 0x52, 0x19, + 0x71, 0xe4, 0xf5, 0xce, 0xc6, 0x0e, 0x2c, 0x3a, 0xd1, 0x9e, 0x3b, 0x3f, 0x40, 0x7e, + 0x69, 0x4b, 0xe8, 0x01, ], note_nf: [ - 0x97, 0x0a, 0xff, 0xd7, 0xf1, 0x0d, 0x5b, 0x71, 0x23, 0x27, 0xe8, 0x39, 0x7e, 0x51, - 0x45, 0x3f, 0x85, 0xf4, 0xc2, 0x0f, 0x80, 0x1e, 0x97, 0xe5, 0xe6, 0x40, 0x0e, 0xb0, - 0xed, 0xc4, 0xbb, 0x03, + 0x0d, 0x35, 0x9b, 0x02, 0xf6, 0x2d, 0x72, 0x18, 0xc8, 0x93, 0xd0, 0x4e, 0xc0, 0xed, + 0xd4, 0x89, 0xb2, 0x33, 0xa3, 0xc6, 0x60, 0x15, 0xaf, 0x93, 0x93, 0x0b, 0x23, 0x30, + 0x35, 0x82, 0x07, 0x3f, ], }, ] diff --git a/src/test_vectors/note_encryption_v3.rs b/src/test_vectors/note_encryption_v3.rs index 0ea5da482..79b514869 100644 --- a/src/test_vectors/note_encryption_v3.rs +++ b/src/test_vectors/note_encryption_v3.rs @@ -2287,9 +2287,9 @@ pub(crate) fn test_vectors() -> Vec { 0xbc, 0xf8, 0x63, 0x37, ], cmx: [ - 0x85, 0xec, 0x16, 0xe8, 0x78, 0x77, 0x33, 0x37, 0x07, 0x9a, 0xec, 0xf3, 0x2c, 0x45, - 0x5e, 0xbf, 0x16, 0x96, 0x8d, 0xa1, 0xd4, 0x34, 0x51, 0xb7, 0xa3, 0x06, 0x87, 0x6c, - 0xa3, 0x08, 0xea, 0x3c, + 0x20, 0x43, 0xa5, 0x58, 0x39, 0x9e, 0x2e, 0xed, 0x91, 0xd9, 0x5d, 0x32, 0xe6, 0xd6, + 0x7c, 0x93, 0xdb, 0x08, 0xe2, 0x15, 0x15, 0x02, 0x85, 0x8d, 0x8b, 0x77, 0x54, 0x87, + 0x5f, 0x10, 0x89, 0x32, ], esk: [ 0x05, 0x18, 0xdd, 0xc0, 0xc4, 0x7b, 0x7f, 0x77, 0xed, 0xcd, 0x39, 0x16, 0x0f, 0xe5, @@ -2403,9 +2403,9 @@ pub(crate) fn test_vectors() -> Vec { 0xc3, 0xcf, 0xc9, 0xca, 0xd8, 0xdb, 0x82, 0x3f, 0xbd, 0x74, ], ock: [ - 0xc6, 0x7c, 0x23, 0x33, 0xc3, 0xcf, 0x4a, 0xc4, 0x6e, 0xde, 0x34, 0xe3, 0xe3, 0xe0, - 0xdb, 0xff, 0x1e, 0x96, 0xb7, 0xa7, 0x8f, 0x16, 0xaa, 0xef, 0x1c, 0x74, 0xa3, 0xef, - 0x07, 0xc5, 0x97, 0x16, + 0x9b, 0x8e, 0x79, 0x56, 0x76, 0x38, 0xa2, 0xee, 0x38, 0x72, 0x5a, 0x94, 0x28, 0x99, + 0xa5, 0xa3, 0xbd, 0xd6, 0x88, 0xdb, 0x76, 0x38, 0x99, 0x7c, 0x77, 0x27, 0x6d, 0x27, + 0x0c, 0x87, 0xd2, 0xa3, ], op: [ 0x05, 0x82, 0x53, 0xd4, 0x85, 0x76, 0x44, 0x88, 0x5e, 0x26, 0xa9, 0x09, 0xc8, 0x38, @@ -2415,12 +2415,12 @@ pub(crate) fn test_vectors() -> Vec { 0xe0, 0xd2, 0x9b, 0x35, 0x9a, 0xc4, 0xfa, 0x2c, ], c_out: [ - 0xe4, 0xba, 0x0e, 0xa2, 0x92, 0x3b, 0x40, 0x19, 0xac, 0x8a, 0xbc, 0xd1, 0x9b, 0xe6, - 0x1c, 0x90, 0xf1, 0x8e, 0xef, 0xae, 0x87, 0xc4, 0xed, 0x8c, 0x76, 0x70, 0x85, 0xba, - 0xa8, 0x3b, 0x4d, 0x61, 0x0c, 0xf3, 0x63, 0x70, 0xda, 0x07, 0x90, 0x1e, 0xad, 0x6d, - 0x4f, 0x4b, 0x71, 0xdc, 0xae, 0x31, 0x1f, 0xa0, 0x36, 0x40, 0x6d, 0x64, 0x7b, 0x7e, - 0xe1, 0x41, 0x1e, 0xf5, 0xae, 0xe0, 0x34, 0x68, 0xb1, 0x09, 0x13, 0xc9, 0x90, 0xcb, - 0x61, 0x61, 0x22, 0xeb, 0xbe, 0x49, 0xda, 0x67, 0x81, 0xc2, + 0xe6, 0xe7, 0xa3, 0x48, 0xf3, 0x3a, 0xdd, 0x64, 0x22, 0x87, 0xc5, 0xf8, 0xf0, 0x9a, + 0x5a, 0xae, 0xd7, 0x9d, 0xf6, 0x70, 0xcc, 0x29, 0x74, 0x78, 0xc2, 0x27, 0x11, 0xe3, + 0x4e, 0xfa, 0x00, 0x88, 0x1d, 0x34, 0xb8, 0x7c, 0x0f, 0x69, 0xcb, 0x55, 0xd9, 0x1d, + 0x91, 0x1d, 0x2d, 0x84, 0x1e, 0x5e, 0xf6, 0x40, 0x38, 0x24, 0xdc, 0x9d, 0x7c, 0x55, + 0x1c, 0xdb, 0xae, 0xb4, 0xa6, 0xfb, 0x46, 0x8e, 0xc0, 0x39, 0xbc, 0x84, 0x17, 0x79, + 0xa0, 0xd7, 0xbf, 0xc3, 0x1b, 0xe2, 0x0b, 0x34, 0xee, 0x25, ], }, TestVector { @@ -2505,9 +2505,9 @@ pub(crate) fn test_vectors() -> Vec { 0xb6, 0xf6, 0x4c, 0x26, ], cmx: [ - 0x40, 0x8f, 0x59, 0x4f, 0xdd, 0xc5, 0x0c, 0x67, 0xf5, 0x47, 0xe1, 0xeb, 0x3e, 0xa2, - 0x99, 0xa3, 0x1f, 0x69, 0xf5, 0x7f, 0xc9, 0x92, 0x03, 0x01, 0x42, 0x90, 0x35, 0xa6, - 0xc2, 0x49, 0x79, 0x1a, + 0xf0, 0x32, 0x44, 0xf8, 0x87, 0xe7, 0x5e, 0x45, 0x2f, 0xf0, 0x06, 0x89, 0x64, 0x44, + 0x2c, 0x9b, 0xc1, 0x03, 0x48, 0xec, 0xa6, 0xc2, 0xbc, 0x46, 0xcc, 0x85, 0xda, 0x5d, + 0x34, 0x0b, 0x43, 0x35, ], esk: [ 0xcb, 0xfc, 0x51, 0x10, 0xff, 0x2f, 0xe9, 0xc5, 0xd5, 0x9e, 0xef, 0x08, 0xbd, 0xf6, @@ -2621,9 +2621,9 @@ pub(crate) fn test_vectors() -> Vec { 0x83, 0x95, 0xa3, 0x99, 0x63, 0x65, 0xa2, 0x0c, 0x22, 0x9e, ], ock: [ - 0x2f, 0x88, 0x37, 0x27, 0xb5, 0x4d, 0x06, 0x25, 0xcf, 0xdc, 0x19, 0x5a, 0xce, 0x10, - 0xca, 0xc0, 0x26, 0x8a, 0xba, 0x3d, 0xe2, 0x8a, 0xd6, 0x08, 0x88, 0x06, 0x50, 0x6d, - 0x69, 0xc4, 0xdd, 0x8e, + 0xb9, 0x64, 0x28, 0x18, 0x81, 0x8d, 0x69, 0x17, 0x6d, 0x6c, 0xe6, 0x08, 0x88, 0x7d, + 0x75, 0x70, 0x58, 0xc7, 0x35, 0x42, 0x74, 0xac, 0xa2, 0xb8, 0x7b, 0x50, 0xf7, 0xa6, + 0x38, 0x52, 0x51, 0x1b, ], op: [ 0x7a, 0xfc, 0xa0, 0x5d, 0x04, 0x2c, 0x84, 0x3e, 0xec, 0xdc, 0x37, 0x24, 0x10, 0x52, @@ -2633,12 +2633,12 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0x3b, 0x57, 0xc3, 0x45, 0xa9, 0x87, 0x2f, ], c_out: [ - 0x99, 0x96, 0x90, 0xd4, 0xcd, 0xd9, 0xe7, 0x6b, 0x07, 0x2c, 0x3c, 0x4c, 0x41, 0xbf, - 0xc7, 0x9a, 0xaa, 0xc6, 0x7f, 0xdc, 0x0f, 0x41, 0xe8, 0x0e, 0x95, 0x48, 0x80, 0x0e, - 0xef, 0xbc, 0x95, 0x74, 0xf1, 0x5d, 0x64, 0xa6, 0x9e, 0x44, 0x47, 0xc4, 0x5b, 0x07, - 0x0c, 0x6c, 0x9f, 0x50, 0x0a, 0xdd, 0xef, 0x6f, 0x57, 0x14, 0xa5, 0x76, 0x22, 0x1f, - 0x3f, 0xbc, 0x61, 0x22, 0x8d, 0x95, 0xc3, 0xac, 0xe4, 0x21, 0x4b, 0xb6, 0xcf, 0x5b, - 0xd9, 0x69, 0x84, 0xd7, 0x78, 0x96, 0x0d, 0xe9, 0x0c, 0x02, + 0xa2, 0xd6, 0x5e, 0x96, 0x7e, 0x98, 0x89, 0x0e, 0x9c, 0x42, 0xf9, 0xb3, 0x4b, 0xf8, + 0x45, 0xfb, 0x8e, 0xaa, 0xf9, 0x20, 0x45, 0x0b, 0x29, 0xec, 0x06, 0x16, 0xb3, 0xf0, + 0x82, 0xea, 0x90, 0x8c, 0x66, 0x87, 0xf4, 0xf9, 0x74, 0x1a, 0xe8, 0xab, 0x81, 0x30, + 0x15, 0x35, 0xfd, 0x10, 0x30, 0x35, 0x7a, 0x78, 0xb2, 0x07, 0xf1, 0xc4, 0x42, 0x77, + 0xf5, 0x03, 0xdb, 0x42, 0xa2, 0xc4, 0xdd, 0x20, 0x25, 0x33, 0x2f, 0x49, 0x5e, 0x88, + 0x31, 0x1b, 0x4c, 0x2f, 0x66, 0xb6, 0x07, 0x29, 0x04, 0x89, ], }, TestVector { @@ -2723,9 +2723,9 @@ pub(crate) fn test_vectors() -> Vec { 0x1d, 0x40, 0x9b, 0x33, ], cmx: [ - 0x9e, 0x3d, 0x61, 0x35, 0x6b, 0x0d, 0x88, 0x95, 0x9e, 0x3f, 0x0f, 0xcc, 0x4a, 0x93, - 0x2e, 0x93, 0x2e, 0xac, 0xbc, 0x80, 0x1d, 0x48, 0xc0, 0x19, 0x5b, 0x9c, 0x8b, 0xd1, - 0x05, 0x5a, 0x8e, 0x2e, + 0xf5, 0x3a, 0x98, 0x99, 0xcd, 0x37, 0xf6, 0x2c, 0x94, 0x85, 0x84, 0xb9, 0x67, 0x7c, + 0x78, 0x4c, 0x73, 0x48, 0x43, 0x40, 0x1a, 0x3a, 0x61, 0x0a, 0xcb, 0x28, 0x2f, 0x04, + 0x30, 0xfd, 0x18, 0x3c, ], esk: [ 0x1b, 0x52, 0x63, 0x2d, 0x2a, 0x8d, 0x58, 0xd1, 0x63, 0x57, 0xa9, 0x19, 0xa2, 0x06, @@ -2839,9 +2839,9 @@ pub(crate) fn test_vectors() -> Vec { 0x1c, 0x60, 0x78, 0xb0, 0x8d, 0x72, 0x2d, 0xc4, 0x4a, 0xb7, ], ock: [ - 0x9c, 0xba, 0xd2, 0xf3, 0x8b, 0xf8, 0x8f, 0x39, 0x47, 0xce, 0xf6, 0x4d, 0xe7, 0xa6, - 0xf4, 0x3e, 0x4c, 0xbb, 0x41, 0xe6, 0xe0, 0x37, 0xf1, 0x42, 0x01, 0xae, 0xe8, 0xab, - 0xfd, 0xf8, 0xa2, 0x35, + 0x67, 0x0e, 0xa5, 0x94, 0x8e, 0x85, 0x29, 0xa9, 0x52, 0xb2, 0x0a, 0xcc, 0x17, 0x70, + 0xe2, 0xa9, 0xc0, 0x67, 0xb0, 0x7b, 0x89, 0xfd, 0xaa, 0xf7, 0x84, 0xdf, 0x83, 0xfd, + 0x53, 0x7b, 0xdd, 0x86, ], op: [ 0x84, 0xda, 0x49, 0x6b, 0x16, 0x0a, 0x81, 0x72, 0xc4, 0x8d, 0x76, 0xb4, 0xfb, 0x08, @@ -2851,12 +2851,12 @@ pub(crate) fn test_vectors() -> Vec { 0x25, 0xec, 0xff, 0x47, 0x72, 0x16, 0x8c, 0x05, ], c_out: [ - 0xf6, 0x25, 0xcd, 0x3d, 0x19, 0x97, 0xb0, 0xd3, 0xf2, 0x29, 0x5a, 0xac, 0xc0, 0x3a, - 0xe0, 0xc9, 0x47, 0x28, 0xb3, 0x3c, 0xc4, 0xf1, 0x6f, 0xd4, 0x28, 0xd6, 0x5f, 0x3c, - 0x78, 0x5e, 0x8c, 0x0b, 0xb4, 0x66, 0xc1, 0x33, 0xd4, 0x83, 0xdf, 0xc5, 0xb1, 0xb3, - 0x15, 0x1d, 0xa2, 0xd5, 0xf2, 0x4a, 0x2b, 0x32, 0x0d, 0x8e, 0x9c, 0xd3, 0x41, 0x5c, - 0x25, 0xb6, 0xf9, 0x76, 0x1f, 0x42, 0x70, 0x04, 0xce, 0xe5, 0x4f, 0x75, 0xf1, 0x25, - 0xbc, 0x50, 0x5e, 0xf6, 0x26, 0xef, 0xc9, 0xdd, 0x63, 0x66, + 0x20, 0xe0, 0x0c, 0xab, 0xc6, 0xc7, 0x06, 0xfa, 0x38, 0x19, 0x16, 0x78, 0x26, 0x44, + 0x90, 0x28, 0x9e, 0x0e, 0xd3, 0x2b, 0x9c, 0x77, 0x6d, 0xa2, 0xab, 0xe0, 0x21, 0x4f, + 0x89, 0x9b, 0xf9, 0x7b, 0x08, 0x3b, 0xe5, 0x8e, 0xdd, 0xbb, 0x57, 0x97, 0x28, 0x22, + 0xbb, 0x10, 0x8e, 0x2c, 0xad, 0xfc, 0x76, 0xab, 0xe6, 0x13, 0x13, 0x9e, 0x94, 0x1c, + 0x2c, 0xa1, 0x59, 0x21, 0x98, 0x91, 0xb1, 0x52, 0x83, 0xd8, 0x5a, 0x0d, 0xc9, 0x4d, + 0x59, 0xf9, 0x7b, 0x6c, 0x3c, 0x53, 0x6f, 0xcf, 0x93, 0x98, ], }, TestVector { @@ -2941,9 +2941,9 @@ pub(crate) fn test_vectors() -> Vec { 0x14, 0x7a, 0x27, 0x10, ], cmx: [ - 0xf2, 0x04, 0x22, 0x51, 0xa0, 0x59, 0xa2, 0xf5, 0x8a, 0xb8, 0xe9, 0x0b, 0x52, 0x64, - 0xd0, 0xa4, 0x3f, 0x96, 0xd7, 0x7e, 0xdd, 0x54, 0xf8, 0x0f, 0xf4, 0x9d, 0x43, 0x86, - 0x81, 0x4d, 0x73, 0x2e, + 0x82, 0x9c, 0x4a, 0x9c, 0x2a, 0x01, 0x66, 0xc9, 0xba, 0x2e, 0x16, 0x9e, 0xdd, 0xda, + 0xe6, 0xdb, 0x59, 0xf0, 0x12, 0xa7, 0x26, 0x29, 0xce, 0x34, 0xf6, 0xc2, 0x88, 0x7e, + 0xfb, 0xe1, 0xd9, 0x3f, ], esk: [ 0xb5, 0x9a, 0x18, 0x4d, 0x24, 0xe6, 0x1b, 0x9f, 0x9d, 0x37, 0x1d, 0xa4, 0xb1, 0x44, @@ -3057,9 +3057,9 @@ pub(crate) fn test_vectors() -> Vec { 0xbc, 0x7a, 0xf6, 0x72, 0xb2, 0x0d, 0x7a, 0x16, 0xec, 0x48, ], ock: [ - 0x97, 0x9b, 0x31, 0x5d, 0x3e, 0x1f, 0x5c, 0xa1, 0x8a, 0x92, 0x86, 0xd9, 0x2c, 0xc8, - 0x8e, 0x63, 0x62, 0x4b, 0x39, 0x9b, 0x29, 0x19, 0xbf, 0x4e, 0x67, 0xda, 0x7c, 0xd3, - 0x94, 0xf4, 0x5c, 0x49, + 0xa8, 0xa5, 0x77, 0x53, 0x40, 0x60, 0x3d, 0xad, 0x7d, 0x52, 0x3c, 0x94, 0x64, 0x4b, + 0x4d, 0x3f, 0x61, 0x92, 0xfb, 0x19, 0x8e, 0x8d, 0xe5, 0x70, 0x61, 0x52, 0xf4, 0x55, + 0x68, 0x24, 0x58, 0x73, ], op: [ 0x04, 0x47, 0x12, 0x42, 0xe1, 0xf4, 0x2b, 0xf0, 0x81, 0xf0, 0x8e, 0x9d, 0x71, 0xfe, @@ -3069,12 +3069,12 @@ pub(crate) fn test_vectors() -> Vec { 0xaf, 0x2b, 0xd1, 0xa0, 0x8c, 0x67, 0xd9, 0x3f, ], c_out: [ - 0x83, 0xf7, 0xa1, 0xda, 0x72, 0x4d, 0xd1, 0x54, 0xe7, 0xd9, 0x47, 0xc0, 0xfc, 0x83, - 0x42, 0x87, 0xf3, 0x3c, 0xd4, 0xb3, 0x4a, 0xfa, 0xc0, 0xda, 0x55, 0xe4, 0x37, 0xaf, - 0xae, 0x67, 0xa9, 0x9c, 0xbd, 0x89, 0x75, 0xc9, 0x54, 0xcf, 0x41, 0xaa, 0x1e, 0x9a, - 0x8f, 0x99, 0x98, 0x3d, 0x58, 0x6f, 0x5e, 0x35, 0x37, 0xda, 0xb7, 0x2a, 0xe1, 0x82, - 0x7a, 0xa5, 0xdf, 0xc9, 0xdd, 0xad, 0x06, 0x26, 0x78, 0x84, 0x6f, 0xf8, 0x09, 0x3d, - 0xfd, 0x15, 0xf6, 0x3d, 0x47, 0xe5, 0xa3, 0xbb, 0x74, 0x39, + 0xe3, 0x49, 0x59, 0x73, 0x78, 0x12, 0xaf, 0x29, 0xef, 0x95, 0x78, 0x3d, 0xcf, 0xb2, + 0xfd, 0x19, 0xab, 0x10, 0xd2, 0x17, 0xdd, 0x7d, 0x7f, 0xa6, 0x9e, 0x45, 0x21, 0xfe, + 0x8e, 0xce, 0x1a, 0x86, 0xee, 0x5b, 0xaf, 0x9d, 0xe8, 0x51, 0x2f, 0x84, 0xa2, 0xb9, + 0x12, 0xbf, 0xa3, 0x2e, 0x50, 0xc9, 0x1e, 0xfc, 0xfa, 0x14, 0x50, 0xb7, 0xdb, 0x82, + 0xd5, 0xa2, 0xa9, 0x9d, 0x40, 0xf7, 0xbd, 0x6d, 0x66, 0xd5, 0xaa, 0x9a, 0x13, 0xec, + 0xc1, 0x61, 0x05, 0x74, 0x0a, 0x68, 0xdb, 0xd9, 0x5e, 0x0a, ], }, TestVector { @@ -3159,9 +3159,9 @@ pub(crate) fn test_vectors() -> Vec { 0xb9, 0xd0, 0xb7, 0x32, ], cmx: [ - 0xe1, 0xc7, 0x67, 0xf3, 0x30, 0x15, 0xb5, 0xe2, 0x4a, 0x9a, 0xa5, 0x8b, 0x64, 0x7b, - 0x6b, 0x61, 0x32, 0x3c, 0xd3, 0x47, 0xe7, 0x21, 0x4c, 0x29, 0x1d, 0x09, 0x95, 0xc0, - 0xf5, 0xa6, 0x93, 0x2f, + 0xde, 0x71, 0x70, 0xc9, 0xd8, 0x0f, 0x64, 0x00, 0x29, 0x73, 0xc2, 0xc7, 0x58, 0x02, + 0x7b, 0xc4, 0x38, 0xe5, 0x83, 0x68, 0x56, 0xa7, 0x40, 0x03, 0x20, 0xb1, 0xbd, 0xe2, + 0xed, 0xa1, 0x7d, 0x31, ], esk: [ 0xc0, 0xdb, 0x43, 0x69, 0x10, 0x03, 0x45, 0x7d, 0x61, 0xfb, 0x58, 0x93, 0x20, 0x26, @@ -3275,9 +3275,9 @@ pub(crate) fn test_vectors() -> Vec { 0xb7, 0xd7, 0xef, 0xa4, 0xf4, 0xd0, 0x18, 0x2d, 0xa4, 0xc4, ], ock: [ - 0x55, 0x0e, 0xbf, 0x98, 0x83, 0x6c, 0xce, 0x43, 0x52, 0x25, 0xa1, 0x4b, 0xa6, 0x52, - 0xa7, 0xd5, 0x58, 0xcf, 0x5f, 0x3f, 0x7a, 0xfb, 0x00, 0xb0, 0x24, 0x70, 0xe8, 0xe4, - 0xd2, 0x6d, 0xb7, 0x9c, + 0x9d, 0x33, 0x8d, 0x19, 0x91, 0xba, 0x13, 0xfe, 0xe7, 0x37, 0x70, 0x9b, 0x7a, 0xbb, + 0x50, 0x77, 0x8d, 0xe1, 0xd8, 0x2f, 0xdb, 0x6b, 0x34, 0x7f, 0x58, 0xdd, 0xf5, 0x78, + 0xdd, 0x54, 0x42, 0xd7, ], op: [ 0x49, 0x19, 0x01, 0x2e, 0x40, 0x43, 0x82, 0xeb, 0xee, 0x8e, 0x60, 0xe9, 0xd4, 0xf1, @@ -3287,12 +3287,12 @@ pub(crate) fn test_vectors() -> Vec { 0x44, 0x72, 0x83, 0xf9, 0x4e, 0xd5, 0x95, 0x3d, ], c_out: [ - 0x9a, 0x01, 0xb7, 0x5e, 0x27, 0xea, 0x97, 0x51, 0x45, 0x5d, 0x54, 0xf2, 0xa5, 0x2b, - 0x88, 0x4b, 0x45, 0x6a, 0x6f, 0xc3, 0xda, 0xdb, 0xec, 0x79, 0xbf, 0x4d, 0x10, 0xbe, - 0x06, 0x7b, 0xef, 0x3e, 0xa2, 0xa5, 0xc0, 0x59, 0x81, 0xd4, 0x06, 0x05, 0x6a, 0x2f, - 0xf6, 0x4c, 0xb4, 0xc6, 0xfd, 0x46, 0x7d, 0xa8, 0x0b, 0xa1, 0x17, 0x48, 0xe9, 0xe2, - 0xae, 0x07, 0xb7, 0x62, 0xdf, 0x9d, 0x4a, 0x23, 0x58, 0x77, 0xf5, 0x8f, 0x43, 0x24, - 0xd8, 0x00, 0x3c, 0x32, 0x4f, 0xd9, 0xc6, 0x39, 0xbc, 0xa6, + 0x1f, 0x61, 0xfa, 0x64, 0x74, 0xce, 0xd5, 0x5b, 0xcf, 0xc9, 0x40, 0x5f, 0x9b, 0x07, + 0xc6, 0x02, 0xb9, 0x71, 0x4b, 0xf4, 0x02, 0x1d, 0x59, 0x4d, 0x72, 0xcf, 0xc6, 0x46, + 0x13, 0xd9, 0x01, 0x0c, 0x92, 0x4a, 0x7a, 0xc6, 0x74, 0x5d, 0x04, 0x8b, 0x15, 0xcc, + 0x94, 0xc4, 0x86, 0x4d, 0x1e, 0x0b, 0x4b, 0x43, 0x55, 0xac, 0x8e, 0xbb, 0x40, 0xee, + 0x36, 0x14, 0x00, 0x11, 0xf4, 0xc0, 0x1b, 0x3f, 0x53, 0xc0, 0xf6, 0x3a, 0xb5, 0x64, + 0x74, 0x81, 0x27, 0x73, 0x0e, 0x6c, 0x58, 0x4a, 0xf9, 0xb3, ], }, TestVector { @@ -3377,9 +3377,9 @@ pub(crate) fn test_vectors() -> Vec { 0x41, 0x84, 0x28, 0x2a, ], cmx: [ - 0xd7, 0x60, 0xac, 0xdb, 0xca, 0xda, 0xd1, 0x88, 0x08, 0x4f, 0xe4, 0x1a, 0x5c, 0x03, - 0xc2, 0xc8, 0xce, 0x34, 0xe1, 0x5f, 0x9d, 0xf4, 0x7b, 0x86, 0x9c, 0x44, 0xc7, 0x21, - 0x13, 0xa4, 0x0c, 0x3d, + 0x1e, 0xaa, 0x25, 0x97, 0xb0, 0x8f, 0x7c, 0x9c, 0x57, 0x9c, 0xe1, 0x43, 0xb7, 0xfb, + 0x2b, 0x10, 0x33, 0x82, 0xff, 0x63, 0x77, 0xb1, 0xc8, 0xbf, 0xbc, 0xcd, 0x8d, 0xa2, + 0x97, 0xe0, 0xa9, 0x0c, ], esk: [ 0x9b, 0x32, 0x77, 0x19, 0x3b, 0x63, 0x60, 0x8e, 0x6a, 0x3d, 0xdf, 0x7c, 0xe2, 0xd2, @@ -3493,9 +3493,9 @@ pub(crate) fn test_vectors() -> Vec { 0x2d, 0xb3, 0x35, 0x6e, 0x11, 0x4d, 0xbc, 0xa3, 0xc5, 0xd8, ], ock: [ - 0x53, 0x29, 0x6e, 0xed, 0x43, 0xb4, 0xeb, 0x30, 0xa4, 0x3d, 0x88, 0x90, 0x2f, 0x74, - 0x04, 0x26, 0x62, 0x1d, 0x85, 0x21, 0x3a, 0x36, 0xc5, 0x20, 0xa1, 0x84, 0xa4, 0x3a, - 0xfb, 0xd4, 0x89, 0x6d, + 0x3c, 0x85, 0x16, 0x2e, 0x48, 0x67, 0xfc, 0x45, 0x89, 0xf6, 0xc6, 0x07, 0x69, 0x3b, + 0x8f, 0x4a, 0x7e, 0x85, 0xe0, 0x19, 0xf2, 0x33, 0x2f, 0xeb, 0xff, 0x08, 0xcb, 0xad, + 0x99, 0x4b, 0x3e, 0x81, ], op: [ 0x64, 0xce, 0xac, 0xec, 0x3c, 0x2e, 0xa7, 0x9c, 0x4c, 0xd3, 0xe2, 0xf0, 0xfb, 0xb9, @@ -3505,12 +3505,12 @@ pub(crate) fn test_vectors() -> Vec { 0x86, 0x48, 0x56, 0x2c, 0xbd, 0x86, 0x3f, 0x09, ], c_out: [ - 0x38, 0xee, 0x14, 0xef, 0xb0, 0x63, 0x94, 0x64, 0x44, 0x6f, 0x5f, 0xb8, 0x79, 0x5d, - 0x23, 0xf8, 0x8c, 0xf5, 0x65, 0x37, 0xe6, 0x4e, 0x1a, 0x46, 0x63, 0x17, 0xb3, 0x6f, - 0x22, 0x2e, 0x00, 0x5b, 0x92, 0x4c, 0xc9, 0x10, 0xd6, 0x29, 0x06, 0x6e, 0x05, 0x07, - 0xcb, 0x91, 0x2b, 0x0b, 0xc1, 0xd3, 0x16, 0xc2, 0x00, 0xb1, 0xa9, 0x56, 0x49, 0xc0, - 0xc5, 0x30, 0xb4, 0xf3, 0xd0, 0x43, 0x06, 0x8e, 0xf6, 0xf4, 0x2d, 0xcb, 0xef, 0xd0, - 0x2a, 0x34, 0x80, 0xe3, 0x2a, 0xa4, 0x5e, 0x33, 0xce, 0x25, + 0x92, 0x05, 0x27, 0xe0, 0x4a, 0xa5, 0x39, 0xdd, 0x95, 0x62, 0x23, 0x36, 0xea, 0x92, + 0xa8, 0xd5, 0x7a, 0x34, 0xd8, 0x7d, 0xac, 0x1c, 0x8d, 0xfd, 0x1b, 0x95, 0x4d, 0xfb, + 0x17, 0x70, 0x72, 0xfc, 0xbd, 0x1b, 0xa0, 0x7c, 0x28, 0x45, 0x1b, 0xa0, 0x99, 0xd6, + 0x3a, 0xb0, 0xb0, 0x51, 0x6d, 0x41, 0xe4, 0xb4, 0x3f, 0x04, 0xc7, 0xe3, 0xb5, 0x3a, + 0xec, 0xd0, 0xa0, 0x48, 0x34, 0x24, 0x48, 0xa8, 0x17, 0x60, 0xa4, 0x1e, 0x6e, 0x85, + 0x48, 0x02, 0x25, 0x43, 0xd6, 0x39, 0xb8, 0x9e, 0xa7, 0x46, ], }, TestVector { @@ -3595,9 +3595,9 @@ pub(crate) fn test_vectors() -> Vec { 0x4e, 0xb3, 0xa2, 0x08, ], cmx: [ - 0x8f, 0x56, 0xd1, 0x3f, 0xd9, 0xc8, 0x3e, 0xb7, 0x1b, 0x95, 0x87, 0x7a, 0x4f, 0x29, - 0x39, 0x64, 0xbf, 0x3f, 0x73, 0x1d, 0x8d, 0xf2, 0x04, 0x32, 0x2c, 0xed, 0xcb, 0x38, - 0x68, 0x21, 0x90, 0x3c, + 0xb5, 0x62, 0x5f, 0xa5, 0xfb, 0xeb, 0xa7, 0xc9, 0xea, 0xff, 0xff, 0x7d, 0xf4, 0x75, + 0xdc, 0x82, 0x33, 0x22, 0xee, 0x88, 0x01, 0x70, 0x56, 0x45, 0xe5, 0x62, 0x7e, 0x4a, + 0xca, 0x36, 0x6c, 0x02, ], esk: [ 0x24, 0x50, 0xae, 0xde, 0xb9, 0x7e, 0x62, 0xd7, 0x9c, 0xcb, 0x44, 0xb0, 0xb0, 0x4f, @@ -3711,9 +3711,9 @@ pub(crate) fn test_vectors() -> Vec { 0xb9, 0x5e, 0x7f, 0x63, 0xcb, 0x5c, 0xfa, 0xf5, 0xca, 0xc1, ], ock: [ - 0x2a, 0x2e, 0x0d, 0x99, 0x69, 0xf0, 0x2e, 0xbd, 0xb6, 0xd9, 0xc8, 0xe7, 0xe6, 0xfd, - 0xde, 0x20, 0x85, 0x12, 0x4b, 0x19, 0xad, 0x70, 0x90, 0xcc, 0x26, 0x15, 0x1d, 0x4d, - 0xa4, 0x2a, 0x00, 0x3e, + 0xc3, 0xd1, 0x04, 0x73, 0x14, 0x50, 0x57, 0x52, 0x3a, 0x55, 0xb7, 0x25, 0xcb, 0x2b, + 0x25, 0xd4, 0xe1, 0xe0, 0x5b, 0xc2, 0xfe, 0x4b, 0xbe, 0xbe, 0xb4, 0xd4, 0x2a, 0x61, + 0x8a, 0xbc, 0xd8, 0xbc, ], op: [ 0x9a, 0xe4, 0x94, 0xa9, 0xfc, 0xff, 0x9b, 0x74, 0x49, 0x14, 0x53, 0x31, 0x04, 0x4f, @@ -3723,12 +3723,12 @@ pub(crate) fn test_vectors() -> Vec { 0xa9, 0xec, 0x88, 0x17, 0x18, 0x65, 0x40, 0x33, ], c_out: [ - 0x74, 0x6a, 0xae, 0x9d, 0xa6, 0x1c, 0x02, 0xae, 0xaa, 0x8b, 0xed, 0xbe, 0x2b, 0x6c, - 0x84, 0x1b, 0xc4, 0x36, 0x17, 0x3c, 0x7c, 0x91, 0x13, 0x66, 0x3a, 0x39, 0xc1, 0x74, - 0x69, 0x29, 0x0b, 0xd2, 0x19, 0xea, 0xdc, 0x4a, 0x97, 0x5a, 0xd0, 0x52, 0xd0, 0x5d, - 0xc0, 0xa3, 0x08, 0xf3, 0x63, 0xf9, 0x22, 0x68, 0x2d, 0x75, 0x21, 0x9d, 0xaa, 0x33, - 0x6f, 0x69, 0xb5, 0x9e, 0x86, 0x7c, 0x85, 0xd9, 0x37, 0x34, 0x4c, 0x19, 0xd3, 0x88, - 0x01, 0x63, 0x19, 0xb3, 0xf6, 0x0f, 0x76, 0xd0, 0x28, 0x93, + 0x74, 0xd2, 0x40, 0xe8, 0xbe, 0x49, 0xb2, 0xa1, 0xad, 0x31, 0x8c, 0xfe, 0xf8, 0x43, + 0x5b, 0x79, 0x7f, 0x71, 0xfa, 0x8b, 0xda, 0x90, 0xed, 0x98, 0x4b, 0x15, 0x69, 0x7c, + 0x3e, 0x34, 0x81, 0x8f, 0x48, 0x96, 0x53, 0x79, 0x0f, 0xe7, 0x04, 0xc8, 0x16, 0x62, + 0xd9, 0xfb, 0x70, 0xde, 0x53, 0x63, 0xca, 0x17, 0xf6, 0x26, 0x2b, 0xae, 0xe2, 0x4b, + 0x2f, 0x2a, 0x80, 0x46, 0x8b, 0x03, 0x94, 0x1f, 0x55, 0x6a, 0x93, 0x0c, 0x37, 0x50, + 0xe6, 0x9a, 0xce, 0xcc, 0x79, 0xc0, 0xe4, 0x72, 0x0f, 0xe5, ], }, TestVector { @@ -3813,9 +3813,9 @@ pub(crate) fn test_vectors() -> Vec { 0x4c, 0x3f, 0x8d, 0x26, ], cmx: [ - 0x69, 0x4b, 0x6f, 0x3a, 0xb8, 0x37, 0xa9, 0x26, 0xd6, 0x77, 0x3e, 0xc4, 0xa6, 0x76, - 0x5d, 0xef, 0x82, 0x89, 0x33, 0x74, 0x2d, 0x93, 0x29, 0xfc, 0x88, 0x67, 0x1c, 0xcd, - 0x81, 0x21, 0xa4, 0x23, + 0x4c, 0x6c, 0x39, 0xec, 0xcf, 0xc0, 0xce, 0xe9, 0x0b, 0x46, 0xdb, 0x88, 0x98, 0xe0, + 0xd1, 0x8b, 0x2c, 0x7a, 0x61, 0x63, 0x0a, 0xb2, 0x71, 0x5c, 0x77, 0x07, 0x17, 0x37, + 0xca, 0x2a, 0x18, 0x13, ], esk: [ 0xaa, 0x84, 0x16, 0x79, 0xd4, 0xd2, 0x40, 0xb0, 0xab, 0xc4, 0xa5, 0xd8, 0x9a, 0xa8, @@ -3929,9 +3929,9 @@ pub(crate) fn test_vectors() -> Vec { 0xa1, 0x85, 0x5a, 0xf9, 0x90, 0xcd, 0xb6, 0x77, 0xaf, 0x0d, ], ock: [ - 0x67, 0x1c, 0xed, 0xd6, 0xf5, 0x73, 0xa4, 0x6f, 0xf1, 0xea, 0xd0, 0x48, 0x21, 0x98, - 0x56, 0x36, 0xe2, 0x3f, 0xb1, 0x5c, 0x6f, 0x48, 0x05, 0xfd, 0x57, 0x63, 0x12, 0xc2, - 0x07, 0x02, 0xa4, 0x24, + 0x2b, 0x28, 0x4c, 0xea, 0xca, 0x3e, 0xe7, 0x05, 0x2b, 0xb4, 0xad, 0x16, 0x7e, 0xc4, + 0x4f, 0xbf, 0x14, 0x4f, 0x7a, 0xef, 0x67, 0x8a, 0x37, 0xe6, 0x1e, 0x0b, 0x1f, 0x6b, + 0xdc, 0x24, 0xa0, 0x0d, ], op: [ 0xcc, 0x18, 0xe4, 0xb6, 0x5f, 0x89, 0x34, 0x06, 0x31, 0x5d, 0xb7, 0x1f, 0xac, 0x06, @@ -3941,12 +3941,12 @@ pub(crate) fn test_vectors() -> Vec { 0x6a, 0x72, 0xcb, 0x74, 0xfb, 0x18, 0xd1, 0x17, ], c_out: [ - 0x59, 0x97, 0x53, 0xe4, 0x0a, 0xda, 0xea, 0xff, 0x6f, 0xaa, 0xf5, 0xa6, 0xf3, 0x0e, - 0x39, 0x13, 0x8f, 0xde, 0x82, 0x0f, 0x7b, 0xec, 0x7c, 0x8d, 0x0f, 0xd8, 0x4b, 0x48, - 0x36, 0x94, 0xe5, 0x0c, 0x4b, 0xdd, 0xee, 0x2f, 0xb1, 0xa4, 0xf9, 0x95, 0xb1, 0xa3, - 0xba, 0x40, 0xf4, 0x66, 0xb4, 0x2e, 0x8b, 0x5d, 0x01, 0x38, 0xfd, 0x30, 0xbf, 0xf6, - 0xae, 0x8c, 0xb1, 0x55, 0xf4, 0x0c, 0xdc, 0x37, 0x39, 0xfa, 0xbf, 0x2f, 0x00, 0xda, - 0x3a, 0xc6, 0xa7, 0x36, 0x3b, 0xc2, 0xf4, 0xaa, 0x10, 0xfe, + 0x4b, 0x9a, 0x5a, 0x4a, 0x4d, 0xda, 0x98, 0xfb, 0x92, 0x9a, 0xe9, 0x7b, 0x11, 0xb2, + 0x09, 0xae, 0x23, 0x42, 0x5e, 0x52, 0x26, 0x9a, 0xad, 0xca, 0x13, 0x23, 0x9c, 0xb9, + 0xb3, 0x8f, 0xbf, 0xfb, 0x85, 0x29, 0x58, 0x41, 0xd0, 0xf3, 0x2b, 0xea, 0xd9, 0x2c, + 0x4d, 0x3c, 0x88, 0xe6, 0xe7, 0x2a, 0x1b, 0xe1, 0xd6, 0x64, 0x9b, 0x1c, 0xee, 0x43, + 0x0e, 0xad, 0x38, 0x44, 0x56, 0x07, 0xc4, 0xa9, 0xb6, 0x02, 0x51, 0x83, 0x56, 0x1e, + 0x6c, 0xff, 0x55, 0x2a, 0xf0, 0x88, 0x98, 0xd4, 0x09, 0xa6, ], }, TestVector { @@ -4031,9 +4031,9 @@ pub(crate) fn test_vectors() -> Vec { 0x4b, 0xc8, 0x45, 0x10, ], cmx: [ - 0x76, 0xf1, 0xbd, 0x50, 0xf9, 0xb9, 0x06, 0xcb, 0x9f, 0xf2, 0xdd, 0x91, 0x8a, 0x36, - 0x7e, 0x5f, 0xb1, 0xa2, 0xef, 0x39, 0xf1, 0x4f, 0x6c, 0xe9, 0x4f, 0xf9, 0xf0, 0x91, - 0x55, 0xf8, 0xc2, 0x11, + 0x06, 0x65, 0x7e, 0xd7, 0x3d, 0x2a, 0x26, 0xfa, 0xfd, 0xe2, 0xb5, 0xb3, 0x73, 0xf4, + 0x60, 0x07, 0x89, 0xf5, 0x23, 0x2b, 0x57, 0x3b, 0x4e, 0xcf, 0xd5, 0x3c, 0x14, 0x03, + 0x9b, 0xeb, 0x15, 0x1c, ], esk: [ 0x2f, 0x98, 0x2d, 0xec, 0xa7, 0x60, 0x51, 0x41, 0xd9, 0xc9, 0xa1, 0xe6, 0xfb, 0x57, @@ -4147,9 +4147,9 @@ pub(crate) fn test_vectors() -> Vec { 0x4e, 0x59, 0x80, 0x45, 0x8c, 0x51, 0xfb, 0x1c, 0xd8, 0x46, ], ock: [ - 0x57, 0x97, 0xef, 0x48, 0x70, 0xb0, 0x86, 0x50, 0xfa, 0x99, 0xad, 0xae, 0x58, 0x85, - 0x19, 0x9e, 0x3b, 0x04, 0x4b, 0x2a, 0x0a, 0x8c, 0xe1, 0x61, 0x43, 0x42, 0xb5, 0xdc, - 0xb2, 0x8e, 0x6e, 0x09, + 0x59, 0xb8, 0x10, 0x2e, 0x91, 0x7f, 0xf5, 0xa4, 0x23, 0x60, 0x50, 0x7c, 0xce, 0x30, + 0xcc, 0x5b, 0xda, 0xb7, 0x76, 0x18, 0x61, 0x9f, 0x52, 0xda, 0xfa, 0xbd, 0xf5, 0x5a, + 0x3f, 0x64, 0xc1, 0xee, ], op: [ 0x6f, 0xce, 0x26, 0xab, 0xe6, 0xc0, 0xb6, 0x84, 0x37, 0x36, 0x96, 0x46, 0xee, 0xe1, @@ -4159,12 +4159,12 @@ pub(crate) fn test_vectors() -> Vec { 0xb9, 0x5f, 0xc8, 0x7e, 0xa7, 0x37, 0x3e, 0x2f, ], c_out: [ - 0xb8, 0xb4, 0x6c, 0x7e, 0xc4, 0xa8, 0x74, 0x2a, 0x22, 0xd3, 0xcd, 0x11, 0x74, 0x1c, - 0x23, 0x04, 0x22, 0x1c, 0xa5, 0x97, 0x29, 0x4e, 0x08, 0xa4, 0xc7, 0x1b, 0x17, 0xc7, - 0x26, 0x5d, 0x4d, 0xa7, 0x7c, 0xfe, 0x84, 0xb8, 0x7e, 0x76, 0xed, 0xaa, 0xec, 0xc2, - 0x24, 0xb8, 0x36, 0xde, 0x22, 0x4c, 0x73, 0x58, 0x13, 0x19, 0xa0, 0xba, 0x27, 0x88, - 0xdb, 0xf8, 0x3b, 0xcf, 0x47, 0xa4, 0x8e, 0xeb, 0x02, 0xb4, 0x3a, 0x18, 0x02, 0x7b, - 0x8f, 0x59, 0x11, 0x65, 0xc2, 0x86, 0xe8, 0xb6, 0x54, 0xec, + 0x7e, 0xaf, 0x92, 0x5e, 0x3e, 0x5c, 0xd2, 0x0c, 0xc9, 0x34, 0x9f, 0x17, 0x4b, 0xdc, + 0x8c, 0x46, 0x45, 0x65, 0xb8, 0x04, 0x68, 0x9d, 0x79, 0x8d, 0x63, 0x2f, 0x58, 0xaa, + 0x26, 0x7a, 0x2f, 0x4e, 0x65, 0xed, 0x07, 0x33, 0xc4, 0x18, 0x67, 0x7b, 0xda, 0x1a, + 0xf5, 0x6e, 0xa9, 0xfd, 0xec, 0xcc, 0xcc, 0xdc, 0x10, 0xa9, 0xb6, 0xda, 0xa4, 0x92, + 0x4b, 0x46, 0x2f, 0x1e, 0x9d, 0x08, 0x65, 0xba, 0xc3, 0xab, 0x71, 0x7a, 0xb8, 0x4f, + 0x54, 0x2c, 0x2f, 0x8d, 0x46, 0xe3, 0x20, 0x5f, 0xb0, 0x33, ], }, TestVector { @@ -4249,9 +4249,9 @@ pub(crate) fn test_vectors() -> Vec { 0x7f, 0x28, 0x4b, 0x2e, ], cmx: [ - 0x89, 0xe6, 0xa2, 0xb9, 0x70, 0x84, 0xe3, 0xd3, 0x34, 0x4f, 0xee, 0xb4, 0x64, 0x65, - 0x05, 0x72, 0x51, 0xb1, 0x9d, 0xa0, 0xce, 0xdf, 0x79, 0x71, 0x94, 0xc5, 0x97, 0xf9, - 0xf7, 0x7e, 0xf2, 0x1f, + 0x7a, 0xd4, 0xd8, 0xf5, 0xd4, 0xe7, 0xa9, 0x79, 0xfa, 0x73, 0x93, 0xed, 0x26, 0xf1, + 0x7d, 0x14, 0x2b, 0x65, 0xf5, 0x3b, 0xb4, 0x6d, 0xa6, 0x0a, 0x50, 0x22, 0x28, 0xc0, + 0x7b, 0x2c, 0xda, 0x27, ], esk: [ 0xe4, 0x00, 0x13, 0x04, 0x47, 0xc1, 0xbd, 0x1a, 0x0c, 0x13, 0x02, 0xf5, 0x10, 0xe9, @@ -4365,9 +4365,9 @@ pub(crate) fn test_vectors() -> Vec { 0x8f, 0x2c, 0xc4, 0x5a, 0xeb, 0x43, 0x52, 0x9e, 0x7d, 0x08, ], ock: [ - 0x95, 0x83, 0xf1, 0x0f, 0xed, 0x70, 0xa4, 0x1e, 0x45, 0x8c, 0x65, 0x5c, 0xc0, 0x14, - 0xe2, 0x35, 0x5a, 0x7f, 0x99, 0xae, 0xbc, 0xfe, 0xf7, 0x4a, 0x55, 0x9a, 0xcd, 0x24, - 0x25, 0xfa, 0x21, 0xcf, + 0x89, 0x5c, 0x90, 0x04, 0xec, 0x4c, 0x50, 0xd6, 0xd5, 0xfd, 0x6a, 0x51, 0x71, 0x2a, + 0xcc, 0xa4, 0x77, 0x1e, 0x1c, 0xe0, 0xb9, 0x94, 0x30, 0xf0, 0x45, 0x9d, 0x43, 0xff, + 0x16, 0x6a, 0x93, 0xf8, ], op: [ 0x3e, 0x5e, 0x46, 0xeb, 0x0f, 0xe8, 0xe6, 0xf0, 0xcf, 0x6a, 0xab, 0x2b, 0x41, 0xfb, @@ -4377,12 +4377,12 @@ pub(crate) fn test_vectors() -> Vec { 0xc4, 0x69, 0x2d, 0x0c, 0x1b, 0x30, 0x33, 0x01, ], c_out: [ - 0xb8, 0x3b, 0x74, 0x5c, 0x9c, 0x0b, 0x04, 0xdd, 0xc7, 0xf1, 0x38, 0x16, 0x94, 0x38, - 0x99, 0x55, 0x3a, 0x30, 0x6a, 0x4a, 0xd0, 0xf2, 0xf5, 0x70, 0x92, 0x2a, 0x89, 0x9b, - 0xab, 0xb9, 0xda, 0xca, 0xd2, 0xbb, 0xc9, 0x5c, 0xf6, 0x5b, 0x73, 0x08, 0x55, 0x0d, - 0xce, 0xdb, 0x64, 0x9e, 0xf1, 0x5e, 0x0b, 0x1a, 0x09, 0x1f, 0xad, 0x5a, 0x93, 0x92, - 0xd0, 0x71, 0xb7, 0x5a, 0xb5, 0x1a, 0x7e, 0x35, 0x06, 0xad, 0x58, 0xd1, 0x71, 0x95, - 0xc9, 0x9f, 0x29, 0x8a, 0xc3, 0x14, 0xec, 0x05, 0xa6, 0x6a, + 0xc7, 0xf4, 0x90, 0x67, 0x45, 0x7f, 0x0c, 0xa0, 0xbf, 0x73, 0x0e, 0x55, 0x17, 0x06, + 0x7d, 0x49, 0x39, 0x9a, 0xce, 0xb7, 0xa6, 0x32, 0x85, 0x34, 0x63, 0x90, 0x76, 0xc1, + 0x44, 0xb2, 0x96, 0xc4, 0xce, 0xd1, 0x5a, 0x49, 0xd3, 0xba, 0xe5, 0x8e, 0xc5, 0xf8, + 0xc0, 0xb5, 0x48, 0x06, 0x33, 0x4e, 0x63, 0xc1, 0x14, 0x1c, 0xb8, 0xd3, 0x04, 0x49, + 0x2a, 0xf5, 0xff, 0x0b, 0x5c, 0x14, 0x75, 0x8d, 0x45, 0x60, 0x30, 0x82, 0x0a, 0xbd, + 0xd6, 0x8f, 0x2e, 0x67, 0xa5, 0x87, 0xb2, 0x60, 0xf0, 0x48, ], }, ] From ea0fd59ec74f13ac99465dbe068ef1e8b64bd94d Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 4 May 2023 15:40:14 +0300 Subject: [PATCH 25/92] Add tracking for supply info inside verify_issue_bundle (#55) 1. Added a new error, `ValueSumOverflow`, that occurs if the sum value overflows when adding new supply amounts. 2. Created a new `supply_info` module containing `SupplyInfo` and `AssetSupply` structures, with `add_supply` function and unit tests for it. 3. Renamed the `are_note_asset_ids_derived_correctly` function to `verify_supply`, changed its behavior to verify and compute asset supply, added unit tests for it. 4. Updated the `verify_issue_bundle` function to use the changes mentioned above, updated its description, and added new unit tests. 5. Renamed errors with `...NoteType` suffix in the name to `...AssetBase`. 6. Added `update_finalization_set` method to `SupplyInfo` and use after the calls of `verify_issue_bundle function` (if needed), instead of mutating the finalization set inside `verify_issue_bundle`. --- src/issuance.rs | 445 ++++++++++++++++++++++++++++++++++----------- src/lib.rs | 1 + src/supply_info.rs | 194 ++++++++++++++++++++ tests/zsa.rs | 2 +- 4 files changed, 536 insertions(+), 106 deletions(-) create mode 100644 src/supply_info.rs diff --git a/src/issuance.rs b/src/issuance.rs index f3da1523b..af243358e 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -7,21 +7,23 @@ use std::fmt; use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; use crate::issuance::Error::{ - IssueActionAlreadyFinalized, IssueActionIncorrectNoteType, IssueActionNotFound, - IssueActionPreviouslyFinalizedNoteType, IssueBundleIkMismatchNoteType, - IssueBundleInvalidSignature, WrongAssetDescSize, + IssueActionAlreadyFinalized, IssueActionIncorrectAssetBase, IssueActionNotFound, + IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, + IssueBundleInvalidSignature, ValueSumOverflow, WrongAssetDescSize, }; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use crate::note::asset_base::is_asset_desc_of_valid_size; use crate::note::{AssetBase, Nullifier}; use crate::primitives::redpallas::Signature; -use crate::value::NoteValue; +use crate::value::{NoteValue, ValueSum}; use crate::{ primitives::redpallas::{self, SpendAuth}, Address, Note, }; +use crate::supply_info::{AssetSupply, SupplyInfo}; + /// A bundle of actions to be applied to the ledger. #[derive(Debug, Clone)] pub struct IssueBundle { @@ -83,27 +85,54 @@ impl IssueAction { self.finalize } - /// Return the `AssetBase` if the provided `ik` is used to derive the `asset_id` for **all** internal notes. - fn are_note_asset_ids_derived_correctly( - &self, - ik: &IssuanceValidatingKey, - ) -> Result { - match self - .notes - .iter() - .try_fold(self.notes().head.asset(), |asset, ¬e| { - // Fail if not all note types are equal + /// Verifies and computes the new asset supply for an `IssueAction`. + /// + /// This function calculates the total value (supply) of the asset by summing the values + /// of all its notes and ensures that all note types are equal. It returns the asset and + /// its supply as a tuple (`AssetBase`, `AssetSupply`) or an error if the asset was not + /// properly derived or an overflow occurred during the supply amount calculation. + /// + /// # Arguments + /// + /// * `ik` - A reference to the `IssuanceValidatingKey` used for deriving the asset. + /// + /// # Returns + /// + /// A `Result` containing a tuple with an `AssetBase` and an `AssetSupply`, or an `Error`. + /// + /// # Errors + /// + /// This function may return an error in any of the following cases: + /// + /// * `IssueActionIncorrectAssetBase`: If the asset type of any note in the `IssueAction` is + /// not equal to the asset type of the first note. + /// + /// * `ValueSumOverflow`: If the total amount value of all notes in the `IssueAction` overflows. + /// + /// * `IssueBundleIkMismatchAssetBase`: If the provided `ik` is not used to derive the + /// `AssetBase` for **all** internal notes. + fn verify_supply(&self, ik: &IssuanceValidatingKey) -> Result<(AssetBase, AssetSupply), Error> { + // Calculate the value of the asset as a sum of values of all its notes + // and ensure all note types are equal + let (asset, value_sum) = self.notes.iter().try_fold( + (self.notes().head.asset(), ValueSum::zero()), + |(asset, value_sum), ¬e| { + // All assets should have the same `AssetBase` note.asset() .eq(&asset) - .then(|| asset) - .ok_or(IssueActionIncorrectNoteType) - }) { - Ok(asset) => asset // check that the asset was properly derived. - .eq(&AssetBase::derive(ik, &self.asset_desc)) - .then(|| asset) - .ok_or(IssueBundleIkMismatchNoteType), - Err(e) => Err(e), - } + .then(|| ()) + .ok_or(IssueActionIncorrectAssetBase)?; + + // The total amount should not overflow + Ok((asset, (value_sum + note.value()).ok_or(ValueSumOverflow)?)) + }, + )?; + + // Return the asset and its supply (or an error if the asset was not properly derived) + asset + .eq(&AssetBase::derive(ik, &self.asset_desc)) + .then(|| Ok((asset, AssetSupply::new(value_sum, self.is_finalized())))) + .ok_or(IssueBundleIkMismatchAssetBase)? } } @@ -309,9 +338,8 @@ impl IssueBundle { // Make sure the `expected_ik` matches the `asset` for all notes. self.actions.iter().try_for_each(|action| { - action - .are_note_asset_ids_derived_correctly(&expected_ik) - .map(|_| ()) // Transform Result into Result<(),Error)>. + action.verify_supply(&expected_ik)?; + Ok(()) })?; Ok(IssueBundle { @@ -354,8 +382,7 @@ impl IssueBundle { /// Validation for Orchard IssueBundles /// -/// A set of previously finalized asset types must be provided. -/// In case of success, `finalized` will contain a set of the provided **and** the newly finalized `AssetBase`s +/// A set of previously finalized asset types must be provided in `finalized` argument. /// /// The following checks are performed: /// * For the `IssueBundle`: @@ -365,44 +392,60 @@ impl IssueBundle { /// * `AssetBase` for the `IssueAction` has not been previously finalized. /// * For each `Note` inside an `IssueAction`: /// * All notes have the same, correct `AssetBase`. +/// +// # Returns +/// +/// A Result containing a SupplyInfo struct, which stores supply information in a HashMap. +/// The HashMap uses AssetBase as the key, and an AssetSupply struct as the value. The +/// AssetSupply contains a ValueSum (representing the total value of all notes for the asset) +/// and a bool indicating whether the asset is finalized. +/// +/// # Errors +/// +/// * `IssueBundleInvalidSignature`: This error occurs if the signature verification +/// for the provided `sighash` fails. +/// * `WrongAssetDescSize`: This error is raised if the asset description size for any +/// asset in the bundle is incorrect. +/// * `IssueActionPreviouslyFinalizedAssetBase`: This error occurs if the asset has already been +/// finalized (inserted into the `finalized` collection). +/// * `IssueActionIncorrectAssetBase`: This error occurs if any note has an incorrect note type. +/// * `ValueSumOverflow`: This error occurs if an overflow happens during the calculation of +/// the value sum for the notes in the asset. +/// * `IssueBundleIkMismatchAssetBase`: This error is raised if the `AssetBase` derived from +/// the `ik` (Issuance Validating Key) and the `asset_desc` (Asset Description) does not match +/// the expected `AssetBase`. pub fn verify_issue_bundle( bundle: &IssueBundle, sighash: [u8; 32], - finalized: &mut HashSet, // The finalization set. -) -> Result<(), Error> { - if let Err(e) = bundle.ik.verify(&sighash, &bundle.authorization.signature) { - return Err(IssueBundleInvalidSignature(e)); - }; - - let s = &mut HashSet::::new(); - - let newly_finalized = bundle - .actions() - .iter() - .try_fold(s, |newly_finalized, action| { - if !is_asset_desc_of_valid_size(action.asset_desc()) { - return Err(WrongAssetDescSize); - } + finalized: &HashSet, // The finalization set. +) -> Result { + bundle + .ik + .verify(&sighash, &bundle.authorization.signature) + .map_err(IssueBundleInvalidSignature)?; + + let supply_info = + bundle + .actions() + .iter() + .try_fold(SupplyInfo::new(), |mut supply_info, action| { + if !is_asset_desc_of_valid_size(action.asset_desc()) { + return Err(WrongAssetDescSize); + } - // Fail if any note in the IssueAction has incorrect note type. - let asset = action.are_note_asset_ids_derived_correctly(bundle.ik())?; + let (asset, supply) = action.verify_supply(bundle.ik())?; - // Fail if the asset was previously finalized. - if finalized.contains(&asset) || newly_finalized.contains(&asset) { - return Err(IssueActionPreviouslyFinalizedNoteType(asset)); - } + // Fail if the asset was previously finalized. + if finalized.contains(&asset) { + return Err(IssueActionPreviouslyFinalizedAssetBase(asset)); + } - // Add to the finalization set, if needed. - if action.is_finalized() { - newly_finalized.insert(asset); - } + supply_info.add_supply(asset, supply)?; - // Proceed with the new finalization set. - Ok(newly_finalized) - })?; + Ok(supply_info) + })?; - finalized.extend(newly_finalized.iter()); - Ok(()) + Ok(supply_info) } /// Errors produced during the issuance process @@ -412,18 +455,21 @@ pub enum Error { IssueActionAlreadyFinalized, /// The requested IssueAction not exists in the bundle. IssueActionNotFound, - /// Not all `NoteType`s are the same inside the action. - IssueActionIncorrectNoteType, + /// Not all `AssetBase`s are the same inside the action. + IssueActionIncorrectAssetBase, /// The provided `isk` and the driven `ik` does not match at least one note type. - IssueBundleIkMismatchNoteType, + IssueBundleIkMismatchAssetBase, /// `asset_desc` should be between 1 and 512 bytes. WrongAssetDescSize, /// Verification errors: /// Invalid signature. IssueBundleInvalidSignature(reddsa::Error), - /// The provided `NoteType` has been previously finalized. - IssueActionPreviouslyFinalizedNoteType(AssetBase), + /// The provided `AssetBase` has been previously finalized. + IssueActionPreviouslyFinalizedAssetBase(AssetBase), + + /// Overflow error occurred while calculating the value of the asset + ValueSumOverflow, } impl std::error::Error for Error {} @@ -440,10 +486,10 @@ impl fmt::Display for Error { IssueActionNotFound => { write!(f, "the requested IssueAction not exists in the bundle.") } - IssueActionIncorrectNoteType => { - write!(f, "not all `NoteType`s are the same inside the action") + IssueActionIncorrectAssetBase => { + write!(f, "not all `AssetBase`s are the same inside the action") } - IssueBundleIkMismatchNoteType => { + IssueBundleIkMismatchAssetBase => { write!( f, "the provided `isk` and the driven `ik` does not match at least one note type" @@ -455,8 +501,14 @@ impl fmt::Display for Error { IssueBundleInvalidSignature(_) => { write!(f, "invalid signature") } - IssueActionPreviouslyFinalizedNoteType(_) => { - write!(f, "the provided `NoteType` has been previously finalized") + IssueActionPreviouslyFinalizedAssetBase(_) => { + write!(f, "the provided `AssetBase` has been previously finalized") + } + ValueSumOverflow => { + write!( + f, + "overflow error occurred while calculating the value of the asset" + ) } } } @@ -464,10 +516,10 @@ impl fmt::Display for Error { #[cfg(test)] mod tests { - use super::IssueBundle; + use super::{AssetSupply, IssueBundle}; use crate::issuance::Error::{ - IssueActionAlreadyFinalized, IssueActionIncorrectNoteType, IssueActionNotFound, - IssueActionPreviouslyFinalizedNoteType, IssueBundleIkMismatchNoteType, + IssueActionAlreadyFinalized, IssueActionIncorrectAssetBase, IssueActionNotFound, + IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, WrongAssetDescSize, }; use crate::issuance::{verify_issue_bundle, IssueAction, Signed}; @@ -475,7 +527,7 @@ mod tests { FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; use crate::note::{AssetBase, Nullifier}; - use crate::value::NoteValue; + use crate::value::{NoteValue, ValueSum}; use crate::{Address, Note}; use nonempty::NonEmpty; use rand::rngs::OsRng; @@ -492,11 +544,12 @@ mod tests { [u8; 32], ) { let mut rng = OsRng; + let sk = SpendingKey::random(&mut rng); let isk: IssuanceAuthorizingKey = (&sk).into(); let ik: IssuanceValidatingKey = (&isk).into(); - let fvk = FullViewingKey::from(&sk); + let fvk = FullViewingKey::from(&SpendingKey::random(&mut rng)); let recipient = fvk.address_at(0u32, Scope::External); let mut sighash = [0u8; 32]; @@ -505,6 +558,102 @@ mod tests { (rng, isk, ik, recipient, sighash) } + fn setup_verify_supply_test_params( + note1_value: u64, + note2_value: u64, + note1_asset_desc: &str, + note2_asset_desc: Option<&str>, // if None, both notes use the same asset + finalize: bool, + ) -> (IssuanceValidatingKey, AssetBase, IssueAction) { + let (mut rng, _, ik, recipient, _) = setup_params(); + + let asset = AssetBase::derive(&ik, note1_asset_desc); + let note2_asset = note2_asset_desc.map_or(asset, |desc| AssetBase::derive(&ik, desc)); + + let note1 = Note::new( + recipient, + NoteValue::from_raw(note1_value), + asset, + Nullifier::dummy(&mut rng), + &mut rng, + ); + + let note2 = Note::new( + recipient, + NoteValue::from_raw(note2_value), + note2_asset, + Nullifier::dummy(&mut rng), + &mut rng, + ); + + ( + ik, + asset, + IssueAction::from_parts( + note1_asset_desc.into(), + NonEmpty { + head: note1, + tail: vec![note2], + }, + finalize, + ), + ) + } + + #[test] + fn test_verify_supply_valid() { + let (ik, test_asset, action) = + setup_verify_supply_test_params(10, 20, "Asset 1", None, false); + + let result = action.verify_supply(&ik); + + assert!(result.is_ok()); + + let (asset, supply) = result.unwrap(); + + assert_eq!(asset, test_asset); + assert_eq!(supply.amount, ValueSum::from_raw(30)); + assert!(!supply.is_finalized); + } + + #[test] + fn test_verify_supply_finalized() { + let (ik, test_asset, action) = + setup_verify_supply_test_params(10, 20, "Asset 1", None, true); + + let result = action.verify_supply(&ik); + + assert!(result.is_ok()); + + let (asset, supply) = result.unwrap(); + + assert_eq!(asset, test_asset); + assert_eq!(supply.amount, ValueSum::from_raw(30)); + assert!(supply.is_finalized); + } + + #[test] + fn test_verify_supply_incorrect_asset_base() { + let (ik, _, action) = + setup_verify_supply_test_params(10, 20, "Asset 1", Some("Asset 2"), false); + + assert_eq!( + action.verify_supply(&ik), + Err(IssueActionIncorrectAssetBase) + ); + } + + #[test] + fn test_verify_supply_ik_mismatch_asset_base() { + let (_, _, action) = setup_verify_supply_test_params(10, 20, "Asset 1", None, false); + let (_, _, ik, _, _) = setup_params(); + + assert_eq!( + action.verify_supply(&ik), + Err(IssueBundleIkMismatchAssetBase) + ); + } + #[test] fn issue_bundle_basic() { let (rng, _, ik, recipient, _) = setup_params(); @@ -714,7 +863,7 @@ mod tests { .sign(rng, &wrong_isk) .expect_err("should not be able to sign"); - assert_eq!(err, IssueBundleIkMismatchNoteType); + assert_eq!(err, IssueBundleIkMismatchAssetBase); } #[test] @@ -755,7 +904,7 @@ mod tests { .sign(rng, &isk) .expect_err("should not be able to sign"); - assert_eq!(err, IssueActionIncorrectNoteType); + assert_eq!(err, IssueActionIncorrectAssetBase); } #[test] @@ -775,11 +924,12 @@ mod tests { .unwrap(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); - let prev_finalized = &mut HashSet::new(); - let res = verify_issue_bundle(&signed, sighash, prev_finalized); - assert!(res.is_ok()); + let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); + + supply_info.update_finalization_set(prev_finalized); + assert!(prev_finalized.is_empty()); } @@ -800,16 +950,97 @@ mod tests { .unwrap(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); - let prev_finalized = &mut HashSet::new(); - let res = verify_issue_bundle(&signed, sighash, prev_finalized); - assert!(res.is_ok()); - assert!(prev_finalized.contains(&AssetBase::derive( - &ik, - &String::from("Verify with finalize") - ))); + let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); + + supply_info.update_finalization_set(prev_finalized); + assert_eq!(prev_finalized.len(), 1); + assert!(prev_finalized.contains(&AssetBase::derive(&ik, "Verify with finalize"))); + } + + #[test] + fn issue_bundle_verify_with_supply_info() { + let (rng, isk, ik, recipient, sighash) = setup_params(); + + let mut bundle = IssueBundle::new(ik.clone()); + + let asset1_desc = "Verify with supply info 1"; + let asset2_desc = "Verify with supply info 2"; + let asset3_desc = "Verify with supply info 3"; + + let asset1_base = AssetBase::derive(&ik, &String::from(asset1_desc)); + let asset2_base = AssetBase::derive(&ik, &String::from(asset2_desc)); + let asset3_base = AssetBase::derive(&ik, &String::from(asset3_desc)); + + bundle + .add_recipient( + String::from(asset1_desc), + recipient, + NoteValue::from_raw(7), + false, + rng, + ) + .unwrap(); + + bundle + .add_recipient( + String::from(asset1_desc), + recipient, + NoteValue::from_raw(8), + true, + rng, + ) + .unwrap(); + + bundle + .add_recipient( + String::from(asset2_desc), + recipient, + NoteValue::from_raw(10), + true, + rng, + ) + .unwrap(); + + bundle + .add_recipient( + String::from(asset3_desc), + recipient, + NoteValue::from_raw(5), + false, + rng, + ) + .unwrap(); + + let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let prev_finalized = &mut HashSet::new(); + + let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); + + supply_info.update_finalization_set(prev_finalized); + + assert_eq!(prev_finalized.len(), 2); + + assert!(prev_finalized.contains(&asset1_base)); + assert!(prev_finalized.contains(&asset2_base)); + assert!(!prev_finalized.contains(&asset3_base)); + + assert_eq!(supply_info.assets.len(), 3); + + assert_eq!( + supply_info.assets.get(&asset1_base), + Some(&AssetSupply::new(ValueSum::from_raw(15), true)) + ); + assert_eq!( + supply_info.assets.get(&asset2_base), + Some(&AssetSupply::new(ValueSum::from_raw(10), true)) + ); + assert_eq!( + supply_info.assets.get(&asset3_base), + Some(&AssetSupply::new(ValueSum::from_raw(5), false)) + ); } #[test] @@ -835,10 +1066,9 @@ mod tests { prev_finalized.insert(final_type); - let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); assert_eq!( - finalized.unwrap_err(), - IssueActionPreviouslyFinalizedNoteType(final_type) + verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), + IssueActionPreviouslyFinalizedAssetBase(final_type) ); } @@ -873,7 +1103,7 @@ mod tests { signature: wrong_isk.sign(&mut rng, &sighash), }); - let prev_finalized = &mut HashSet::new(); + let prev_finalized = &HashSet::new(); assert_eq!( verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), @@ -898,13 +1128,10 @@ mod tests { let sighash: [u8; 32] = bundle.commitment().into(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); - let prev_finalized = &mut HashSet::new(); - - // 2. Try empty description - let finalized = verify_issue_bundle(&signed, random_sighash, prev_finalized); + let prev_finalized = &HashSet::new(); assert_eq!( - finalized.unwrap_err(), + verify_issue_bundle(&signed, random_sighash, prev_finalized).unwrap_err(), IssueBundleInvalidSignature(InvalidSignature) ); } @@ -944,10 +1171,12 @@ mod tests { .borrow_mut() .push(note); - let prev_finalized = &mut HashSet::new(); - let err = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(); + let prev_finalized = &HashSet::new(); - assert_eq!(err, IssueActionIncorrectNoteType); + assert_eq!( + verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), + IssueActionIncorrectAssetBase + ); } #[test] @@ -985,10 +1214,12 @@ mod tests { signed.actions.first_mut().unwrap().notes = NonEmpty::new(note); - let prev_finalized = &mut HashSet::new(); - let err = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(); + let prev_finalized = &HashSet::new(); - assert_eq!(err, IssueBundleIkMismatchNoteType); + assert_eq!( + verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), + IssueBundleIkMismatchAssetBase + ); } #[test] @@ -1015,7 +1246,7 @@ mod tests { .unwrap(); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); - let prev_finalized = &mut HashSet::new(); + let prev_finalized = HashSet::new(); // 1. Try too long description signed @@ -1023,9 +1254,11 @@ mod tests { .first_mut() .unwrap() .modify_descr(String::from_utf8(vec![b'X'; 513]).unwrap()); - let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); - assert_eq!(finalized.unwrap_err(), WrongAssetDescSize); + assert_eq!( + verify_issue_bundle(&signed, sighash, &prev_finalized).unwrap_err(), + WrongAssetDescSize + ); // 2. Try empty description signed @@ -1033,9 +1266,11 @@ mod tests { .first_mut() .unwrap() .modify_descr("".to_string()); - let finalized = verify_issue_bundle(&signed, sighash, prev_finalized); - assert_eq!(finalized.unwrap_err(), WrongAssetDescSize); + assert_eq!( + verify_issue_bundle(&signed, sighash, &prev_finalized).unwrap_err(), + WrongAssetDescSize + ); } } diff --git a/src/lib.rs b/src/lib.rs index 76d9c41c0..417116df2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ mod constants; pub mod issuance; pub mod keys; pub mod note; +pub mod supply_info; // pub mod note_encryption; // disabled until backward compatability is implemented. pub mod note_encryption_v3; pub mod primitives; diff --git a/src/supply_info.rs b/src/supply_info.rs new file mode 100644 index 000000000..6bd96df34 --- /dev/null +++ b/src/supply_info.rs @@ -0,0 +1,194 @@ +//! Structs and logic related to supply information management for assets. + +use std::collections::{hash_map, HashMap, HashSet}; + +use crate::{issuance::Error, note::AssetBase, value::ValueSum}; + +/// Represents the amount of an asset and its finalization status. +#[derive(Debug, Clone, Copy)] +#[cfg_attr(test, derive(PartialEq))] +pub struct AssetSupply { + /// The amount of the asset. + pub amount: ValueSum, + /// Whether or not the asset is finalized. + pub is_finalized: bool, +} + +impl AssetSupply { + /// Creates a new AssetSupply instance with the given amount and finalization status. + pub fn new(amount: ValueSum, is_finalized: bool) -> Self { + Self { + amount, + is_finalized, + } + } +} + +/// Contains information about the supply of assets. +#[derive(Debug, Clone)] +pub struct SupplyInfo { + /// A map of asset bases to their respective supply information. + pub assets: HashMap, +} + +impl SupplyInfo { + /// Creates a new, empty `SupplyInfo` instance. + pub fn new() -> Self { + Self { + assets: HashMap::new(), + } + } + + /// Inserts or updates an asset's supply information in the supply info map. + /// If the asset exists, adds the amounts (unconditionally) and updates the finalization status + /// (only if the new supply is finalized). If the asset is not found, inserts the new supply. + pub fn add_supply(&mut self, asset: AssetBase, new_supply: AssetSupply) -> Result<(), Error> { + match self.assets.entry(asset) { + hash_map::Entry::Occupied(entry) => { + let supply = entry.into_mut(); + supply.amount = + (supply.amount + new_supply.amount).ok_or(Error::ValueSumOverflow)?; + supply.is_finalized |= new_supply.is_finalized; + } + hash_map::Entry::Vacant(entry) => { + entry.insert(new_supply); + } + } + + Ok(()) + } + + /// Updates the set of finalized assets based on the supply information stored in + /// the `SupplyInfo` instance. + pub fn update_finalization_set(&self, finalization_set: &mut HashSet) { + finalization_set.extend( + self.assets + .iter() + .filter_map(|(asset, supply)| supply.is_finalized.then(|| asset)), + ); + } +} + +impl Default for SupplyInfo { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn create_test_asset(asset_desc: &str) -> AssetBase { + use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; + + let sk = SpendingKey::from_bytes([0u8; 32]).unwrap(); + let isk: IssuanceAuthorizingKey = (&sk).into(); + + AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc) + } + + fn sum<'a, T: IntoIterator>(supplies: T) -> Option { + supplies + .into_iter() + .map(|supply| supply.amount) + .try_fold(ValueSum::from_raw(0), |sum, value| sum + value) + } + + #[test] + fn test_add_supply_valid() { + let mut supply_info = SupplyInfo::new(); + + let asset1 = create_test_asset("Asset 1"); + let asset2 = create_test_asset("Asset 2"); + + let supply1 = AssetSupply::new(ValueSum::from_raw(20), false); + let supply2 = AssetSupply::new(ValueSum::from_raw(30), true); + let supply3 = AssetSupply::new(ValueSum::from_raw(10), false); + let supply4 = AssetSupply::new(ValueSum::from_raw(10), true); + let supply5 = AssetSupply::new(ValueSum::from_raw(50), false); + + assert_eq!(supply_info.assets.len(), 0); + + // Add supply1 + assert!(supply_info.add_supply(asset1, supply1).is_ok()); + assert_eq!(supply_info.assets.len(), 1); + assert_eq!( + supply_info.assets.get(&asset1), + Some(&AssetSupply::new(sum([&supply1]).unwrap(), false)) + ); + + // Add supply2 + assert!(supply_info.add_supply(asset1, supply2).is_ok()); + assert_eq!(supply_info.assets.len(), 1); + assert_eq!( + supply_info.assets.get(&asset1), + Some(&AssetSupply::new(sum([&supply1, &supply2]).unwrap(), true)) + ); + + // Add supply3 + assert!(supply_info.add_supply(asset1, supply3).is_ok()); + assert_eq!(supply_info.assets.len(), 1); + assert_eq!( + supply_info.assets.get(&asset1), + Some(&AssetSupply::new( + sum([&supply1, &supply2, &supply3]).unwrap(), + true + )) + ); + + // Add supply4 + assert!(supply_info.add_supply(asset1, supply4).is_ok()); + assert_eq!(supply_info.assets.len(), 1); + assert_eq!( + supply_info.assets.get(&asset1), + Some(&AssetSupply::new( + sum([&supply1, &supply2, &supply3, &supply4]).unwrap(), + true + )) + ); + + // Add supply5 + assert!(supply_info.add_supply(asset2, supply5).is_ok()); + assert_eq!(supply_info.assets.len(), 2); + assert_eq!( + supply_info.assets.get(&asset1), + Some(&AssetSupply::new( + sum([&supply1, &supply2, &supply3, &supply4]).unwrap(), + true + )) + ); + assert_eq!( + supply_info.assets.get(&asset2), + Some(&AssetSupply::new(sum([&supply5]).unwrap(), false)) + ); + } + + #[test] + fn test_update_finalization_set() { + let mut supply_info = SupplyInfo::new(); + + let asset1 = create_test_asset("Asset 1"); + let asset2 = create_test_asset("Asset 2"); + let asset3 = create_test_asset("Asset 3"); + + let supply1 = AssetSupply::new(ValueSum::from_raw(10), false); + let supply2 = AssetSupply::new(ValueSum::from_raw(20), true); + let supply3 = AssetSupply::new(ValueSum::from_raw(40), false); + let supply4 = AssetSupply::new(ValueSum::from_raw(50), true); + + assert!(supply_info.add_supply(asset1, supply1).is_ok()); + assert!(supply_info.add_supply(asset1, supply2).is_ok()); + assert!(supply_info.add_supply(asset2, supply3).is_ok()); + assert!(supply_info.add_supply(asset3, supply4).is_ok()); + + let mut finalization_set = HashSet::new(); + + supply_info.update_finalization_set(&mut finalization_set); + + assert_eq!(finalization_set.len(), 2); + + assert!(finalization_set.contains(&asset1)); + assert!(finalization_set.contains(&asset3)); + } +} diff --git a/tests/zsa.rs b/tests/zsa.rs index 5b1ea4437..e597ff5c5 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -169,7 +169,7 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { assert!(verify_issue_bundle( &issue_bundle, issue_bundle.commitment().into(), - &mut HashSet::new(), + &HashSet::new(), ) .is_ok()); From 9a35108155bbad1f73c0e8bc7d79f81d8bfe3273 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 10 May 2023 10:23:48 +0300 Subject: [PATCH 26/92] Add getter method for Bundle.burn field (#58) - Add getter method for Bundle.burn field --- src/bundle.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bundle.rs b/src/bundle.rs index d7a75875b..c702d8655 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -206,6 +206,11 @@ impl Bundle { &self.value_balance } + /// Returns assets intended for burning + pub fn burn(&self) -> &Vec<(AssetBase, V)> { + &self.burn + } + /// Returns the root of the Orchard commitment tree that this bundle commits to. pub fn anchor(&self) -> &Anchor { &self.anchor From aeb993403badb1f21c8c58fb1c01290a43d29a8d Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 23 May 2023 13:03:56 +0200 Subject: [PATCH 27/92] Circuit: Update note_commit to take into account asset (#56) In the circuit, we update note_commit to take into account asset. Previously, note_commit returns cm = hash(Q_ZEC, msg) + [rcm]R. Now, note_commit returns - cm = hash(Q_ZEC, msg) + [rcm]R for ZEC note - cm = hash(Q_ZSA, msg || asset) + [rcm]R for ZSA note We now evaluate note_commit with the following steps 1. evaluate **hash_zec = hash(Q_ZEC, msg)** 2. evaluate **hash_zsa = hash(Q_ZSA, msg || asset)** 3. select **hash = hash_zec if is_native_asset** **= hash_zsa otherwise** 4. evaluate **cm = hash + [rcm]R** 5. check some constraints on msg and asset and their decompositions 6. return **cm** The following modifications are required to update note_commit: - add a is_native_asset witness (and check that it is a boolean and its value is correct according to asset) - add a MUX chip to evaluate a multiplexer on Pallas points Warning: we increased the size of the Orchard circuit ! --- Cargo.toml | 2 +- src/circuit.rs | 165 +- src/circuit/gadget.rs | 28 + src/circuit/gadget/mux_chip.rs | 338 + src/circuit/note_commit.rs | 678 +- src/circuit/value_commit_orchard.rs | 9 +- src/circuit_description | 9448 ++++++++++++++++----------- src/circuit_proof_test_case.bin | Bin 5186 -> 5250 bytes src/constants/sinsemilla.rs | 43 +- src/note/asset_base.rs | 14 +- src/note/commitment.rs | 4 +- tests/zsa.rs | 2 +- 12 files changed, 6648 insertions(+), 4083 deletions(-) create mode 100644 src/circuit/gadget/mux_chip.rs diff --git a/Cargo.toml b/Cargo.toml index 21b273eaa..6d12d29eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,4 +95,4 @@ debug = true [patch.crates-io] zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", rev = "07c377ddedf71ab7c7a266d284b054a2dafc2ed4" } bridgetree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "ea1686e8f8f6c1e41aa97251a7eb4fadfd33df47" } -incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "ea1686e8f8f6c1e41aa97251a7eb4fadfd33df47" } \ No newline at end of file +incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree.git", rev = "ea1686e8f8f6c1e41aa97251a7eb4fadfd33df47" } diff --git a/src/circuit.rs b/src/circuit.rs index 24f3d2e86..9b2f9b766 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -2,6 +2,7 @@ use core::fmt; +use ff::Field; use group::{Curve, GroupEncoding}; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, @@ -20,12 +21,13 @@ use self::{ commit_ivk::{CommitIvkChip, CommitIvkConfig}, gadget::{ add_chip::{AddChip, AddConfig}, - assign_free_advice, + assign_free_advice, assign_is_native_asset, }, note_commit::{NoteCommitChip, NoteCommitConfig}, }; use crate::{ builder::SpendInfo, + circuit::gadget::mux_chip::{MuxChip, MuxConfig}, constants::{ OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, MERKLE_DEPTH_ORCHARD, @@ -65,7 +67,7 @@ mod note_commit; mod value_commit_orchard; /// Size of the Orchard circuit. -const K: u32 = 11; +const K: u32 = 12; // Absolute offsets for public inputs. const ANCHOR: usize = 0; @@ -96,6 +98,7 @@ pub struct Config { commit_ivk_config: CommitIvkConfig, old_note_commit_config: NoteCommitConfig, new_note_commit_config: NoteCommitConfig, + mux_config: MuxConfig, } /// The Orchard Action circuit. @@ -220,6 +223,8 @@ impl plonk::Circuit for Circuit { // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). // Constrain split_flag = 1 or nf_old = nf_old_pub + // Constrain is_native_asset to be boolean + // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -239,8 +244,23 @@ impl plonk::Circuit for Circuit { let nf_old = meta.query_advice(advices[9], Rotation::cur()); let nf_old_pub = meta.query_advice(advices[0], Rotation::next()); + let is_native_asset = meta.query_advice(advices[1], Rotation::next()); + let asset_x = meta.query_advice(advices[2], Rotation::next()); + let asset_y = meta.query_advice(advices[3], Rotation::next()); + let diff_asset_x_inv = meta.query_advice(advices[4], Rotation::next()); + let diff_asset_y_inv = meta.query_advice(advices[5], Rotation::next()); + let one = Expression::Constant(pallas::Base::one()); + let native_asset = AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap(); + + let diff_asset_x = asset_x - Expression::Constant(*native_asset.x()); + let diff_asset_y = asset_y - Expression::Constant(*native_asset.y()); + Constraints::with_selector( q_orchard, [ @@ -265,7 +285,30 @@ impl plonk::Circuit for Circuit { ), ( "split_flag = 1 or nf_old = nf_old_pub", - (one - split_flag) * (nf_old - nf_old_pub), + (one.clone() - split_flag) * (nf_old - nf_old_pub), + ), + ( + "bool_check is_native_asset", + bool_check(is_native_asset.clone()), + ), + ( + "(is_native_asset = 1) => (asset_x = native_asset_x)", + is_native_asset.clone() * diff_asset_x.clone(), + ), + ( + "(is_native_asset = 1) => (asset_y = native_asset_y)", + is_native_asset.clone() * diff_asset_y.clone(), + ), + // To prove that `asset` is not equal to `native_asset`, we will prove that at + // least one of `x(asset) - x(native_asset)` or `y(asset) - y(native_asset)` is + // not equal to zero. + // To prove that `x(asset) - x(native_asset)` (resp `y(asset) - y(native_asset)`) + // is not equal to zero, we will prove that it is invertible. + ( + "(is_native_asset = 0) => (asset != native_asset)", + (one.clone() - is_native_asset) + * (diff_asset_x * diff_asset_x_inv - one.clone()) + * (diff_asset_y * diff_asset_y_inv - one), ), ], ) @@ -383,6 +426,8 @@ impl plonk::Circuit for Circuit { let new_note_commit_config = NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); + let mux_config = MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); + Config { primary, q_orchard, @@ -397,6 +442,7 @@ impl plonk::Circuit for Circuit { commit_ivk_config, old_note_commit_config, new_note_commit_config, + mux_config, } } @@ -413,7 +459,7 @@ impl plonk::Circuit for Circuit { let ecc_chip = config.ecc_chip(); // Witness private inputs that are used across multiple checks. - let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) = { + let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset) = { // Witness psi_old let psi_old = assign_free_advice( layouter.namespace(|| "witness psi_old"), @@ -471,9 +517,27 @@ impl plonk::Circuit for Circuit { self.v_new, )?; - (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) + // Witness asset + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + self.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + ( + psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, + ) }; + // Witness is_native_asset which is equal to + // 1 if asset is equal to native asset, and + // 0 if asset is not equal to native asset. + let is_native_asset = assign_is_native_asset( + layouter.namespace(|| "witness is_native_asset"), + config.advices[0], + self.asset, + )?; + // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). let root = { let path = self @@ -537,19 +601,13 @@ impl plonk::Circuit for Circuit { self.rcv.as_ref().map(|rcv| rcv.inner()), )?; - let asset = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness asset"), - self.asset.map(|asset| asset.cv_base().to_affine()), - )?; - let cv_net = gadget::value_commit_orchard( layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"), config.sinsemilla_chip_1(), ecc_chip.clone(), v_net_magnitude_sign.clone(), rcv, - asset, + asset.clone(), )?; // Constrain cv_net to equal public input @@ -658,12 +716,15 @@ impl plonk::Circuit for Circuit { config.sinsemilla_chip_1(), config.ecc_chip(), config.note_commit_chip_old(), + config.mux_chip(), g_d_old.inner(), pk_d_old.inner(), v_old.clone(), rho_old, psi_old, + asset.inner(), rcm_old, + is_native_asset.clone(), )?; // Constrain derived cm_old to equal witnessed cm_old @@ -716,12 +777,15 @@ impl plonk::Circuit for Circuit { config.sinsemilla_chip_2(), config.ecc_chip(), config.note_commit_chip_new(), + config.mux_chip(), g_d_new.inner(), pk_d_new.inner(), v_new.clone(), rho_new, psi_new, + asset.inner(), rcm_new, + is_native_asset.clone(), )?; let cmx = cm_new.extract_p(); @@ -795,6 +859,72 @@ impl plonk::Circuit for Circuit { 1, )?; + is_native_asset.copy_advice( + || "is_native_asset", + &mut region, + config.advices[1], + 1, + )?; + asset + .inner() + .x() + .copy_advice(|| "asset_x", &mut region, config.advices[2], 1)?; + asset + .inner() + .y() + .copy_advice(|| "asset_y", &mut region, config.advices[3], 1)?; + + // `diff_asset_x_inv` and `diff_asset_y_inv` will be used to prove that + // if is_native_asset = 0, then asset != native_asset. + region.assign_advice( + || "diff_asset_x_inv", + config.advices[4], + 1, + || { + self.asset.map(|asset| { + let asset_x = *asset.cv_base().to_affine().coordinates().unwrap().x(); + let native_asset_x = *AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap() + .x(); + + let diff_asset_x = asset_x - native_asset_x; + + if diff_asset_x == pallas::Base::zero() { + pallas::Base::zero() + } else { + diff_asset_x.invert().unwrap() + } + }) + }, + )?; + region.assign_advice( + || "diff_asset_y_inv", + config.advices[5], + 1, + || { + self.asset.map(|asset| { + let asset_y = *asset.cv_base().to_affine().coordinates().unwrap().y(); + let native_asset_y = *AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap() + .y(); + + let diff_asset_y = asset_y - native_asset_y; + + if diff_asset_y == pallas::Base::zero() { + pallas::Base::zero() + } else { + diff_asset_y.invert().unwrap() + } + }) + }, + )?; + config.q_orchard.enable(&mut region, 0) }, )?; @@ -1111,8 +1241,8 @@ mod tests { K, &circuits[0], ); - assert_eq!(usize::from(circuit_cost.proof_size(1)), 5024); - assert_eq!(usize::from(circuit_cost.proof_size(2)), 7296); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 5088); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7360); usize::from(circuit_cost.proof_size(instances.len())) }; @@ -1141,6 +1271,7 @@ mod tests { #[test] fn serialized_proof_test_case() { + use std::fs; use std::io::{Read, Write}; let vk = VerifyingKey::build(); @@ -1209,7 +1340,7 @@ mod tests { let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); assert!(proof.verify(&vk, instances).is_ok()); - let file = std::fs::File::create("circuit_proof_test_case.bin")?; + let file = std::fs::File::create("src/circuit_proof_test_case.bin")?; write_test_case(file, &instance, &proof) }; create_proof().expect("should be able to write new proof"); @@ -1217,10 +1348,10 @@ mod tests { // Parse the hardcoded proof test case. let (instance, proof) = { - let test_case_bytes = include_bytes!("circuit_proof_test_case.bin"); + let test_case_bytes = fs::read("src/circuit_proof_test_case.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.0.len(), 5024); + assert_eq!(proof.0.len(), 5088); assert!(proof.verify(&vk, &[instance]).is_ok()); } diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 8c0440aef..646bef288 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -5,6 +5,7 @@ use pasta_curves::pallas; use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip}; use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; +use crate::note::AssetBase; use halo2_gadgets::{ ecc::{chip::EccChip, EccInstructions, FixedPointBaseField, Point, X}, poseidon::{ @@ -19,6 +20,7 @@ use halo2_proofs::{ }; pub(in crate::circuit) mod add_chip; +pub(in crate::circuit) mod mux_chip; impl super::Config { pub(super) fn add_chip(&self) -> add_chip::AddChip { @@ -68,6 +70,10 @@ impl super::Config { pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { NoteCommitChip::construct(self.old_note_commit_config.clone()) } + + pub(super) fn mux_chip(&self) -> mux_chip::MuxChip { + mux_chip::MuxChip::construct(self.mux_config.clone()) + } } /// An instruction set for adding two circuit words (field elements). @@ -100,6 +106,28 @@ where ) } +/// Witnesses is_native_asset. +pub(in crate::circuit) fn assign_is_native_asset( + layouter: impl Layouter, + column: Column, + asset: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + asset.map(|asset| { + if bool::from(asset.is_native()) { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) +} + /// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. /// /// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers diff --git a/src/circuit/gadget/mux_chip.rs b/src/circuit/gadget/mux_chip.rs new file mode 100644 index 000000000..dbe54ed40 --- /dev/null +++ b/src/circuit/gadget/mux_chip.rs @@ -0,0 +1,338 @@ +use halo2_gadgets::ecc::chip::EccPoint; +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{self, Advice, Column, ConstraintSystem, Constraints, Expression, Selector}, + poly::Rotation, +}; +use pasta_curves::pallas; + +#[derive(Clone, Debug)] +pub(in crate::circuit) struct MuxConfig { + choice: Column, + left: Column, + right: Column, + out: Column, + q_mux: Selector, +} + +/// A chip implementing a multiplexer on a single row. +/// +/// out = if (choice == 0) {left} else {right} +/// +/// `choice` must be constrained to {0, 1} separately. +#[derive(Clone, Debug)] +pub(in crate::circuit) struct MuxChip { + config: MuxConfig, +} + +impl Chip for MuxChip { + type Config = MuxConfig; + type Loaded = (); + + fn config(&self) -> &Self::Config { + &self.config + } + + fn loaded(&self) -> &Self::Loaded { + &() + } +} + +impl MuxChip { + pub(in crate::circuit) fn configure( + meta: &mut ConstraintSystem, + choice: Column, + left: Column, + right: Column, + out: Column, + ) -> MuxConfig { + let q_mux = meta.selector(); + meta.create_gate("Field element multiplexer", |meta| { + let q_mux = meta.query_selector(q_mux); + let choice = meta.query_advice(choice, Rotation::cur()); + let left = meta.query_advice(left, Rotation::cur()); + let right = meta.query_advice(right, Rotation::cur()); + let out = meta.query_advice(out, Rotation::cur()); + + let one = Expression::Constant(pallas::Base::one()); + + let should_be_zero = (one - choice.clone()) * left + choice * right - out; + + Constraints::with_selector(q_mux, Some(should_be_zero)) + }); + + MuxConfig { + choice, + left, + right, + out, + q_mux, + } + } + + pub(in crate::circuit) fn construct(config: MuxConfig) -> Self { + Self { config } + } +} + +/// An instruction set for multiplexing two points. +pub(crate) trait MuxInstructions { + /// Constraints `MUX(choice, left, right)` and returns the selected point. + fn mux( + &self, + layouter: impl Layouter, + choice: &AssignedCell, + left: &EccPoint, + right: &EccPoint, + ) -> Result; +} + +impl MuxInstructions for MuxChip { + fn mux( + &self, + mut layouter: impl Layouter, + choice: &AssignedCell, + left: &EccPoint, + right: &EccPoint, + ) -> Result { + let x_cell = layouter.assign_region( + || "mux x", + |mut region| { + self.config.q_mux.enable(&mut region, 0)?; + + choice.copy_advice(|| "copy choice", &mut region, self.config.choice, 0)?; + left.x() + .copy_advice(|| "copy left_x", &mut region, self.config.left, 0)?; + right + .x() + .copy_advice(|| "copy right_x", &mut region, self.config.right, 0)?; + + let out_val = (Value::known(pallas::Base::one()) - choice.value()) + * left.x().value() + + choice.value() * right.x().value(); + + region.assign_advice(|| "out x", self.config.out, 0, || out_val) + }, + )?; + let y_cell = layouter.assign_region( + || "mux y", + |mut region| { + self.config.q_mux.enable(&mut region, 0)?; + + choice.copy_advice(|| "copy choice", &mut region, self.config.choice, 0)?; + left.y() + .copy_advice(|| "copy left_y", &mut region, self.config.left, 0)?; + right + .y() + .copy_advice(|| "copy right_y", &mut region, self.config.right, 0)?; + + let out_val = (Value::known(pallas::Base::one()) - choice.value()) + * left.y().value() + + choice.value() * right.y().value(); + + region.assign_advice(|| "out y", self.config.out, 0, || out_val) + }, + )?; + + Ok(EccPoint::from_coordinates_unchecked( + x_cell.into(), + y_cell.into(), + )) + } +} + +#[cfg(test)] +mod tests { + use crate::circuit::gadget::mux_chip::{MuxChip, MuxConfig, MuxInstructions}; + + use crate::{circuit::gadget::assign_free_advice, circuit::K, constants::OrchardFixedBases}; + use halo2_gadgets::{ + ecc::{ + chip::{EccChip, EccConfig}, + Point, + }, + utilities::lookup_range_check::LookupRangeCheckConfig, + }; + + use group::{cofactor::CofactorCurveAffine, Curve, Group}; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, + }; + use pasta_curves::arithmetic::CurveAffine; + use pasta_curves::{pallas, EpAffine}; + + use rand::rngs::OsRng; + + #[test] + fn test_mux_chip() { + #[derive(Clone, Debug)] + pub struct MyConfig { + primary: Column, + advice: Column, + mux_config: MuxConfig, + ecc_config: EccConfig, + } + #[derive(Default)] + struct MyCircuit { + left_point: Value, + right_point: Value, + choice: Value, + } + + impl Circuit for MyCircuit { + type Config = MyConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + let mux_config = + MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); + + let table_idx = meta.lookup_table_column(); + + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + meta.enable_constant(lagrange_coeffs[0]); + + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + MyConfig { + primary, + advice: advices[0], + mux_config, + ecc_config, + } + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Construct a MUX chip + let mux_chip = MuxChip::construct(config.mux_config); + + // Construct an ECC chip + let ecc_chip = EccChip::construct(config.ecc_config); + + // Assign left point + let left_point = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "left point"), + self.left_point.map(|left_point| left_point), + )?; + + // Assign right point + let right_point = Point::new( + ecc_chip, + layouter.namespace(|| "right point"), + self.right_point.map(|right_point| right_point), + )?; + + // Assign choice + let choice = assign_free_advice( + layouter.namespace(|| "choice"), + config.advice, + self.choice, + )?; + + // Apply mux + let result = mux_chip.mux( + layouter.namespace(|| "MUX"), + &choice, + left_point.inner(), + right_point.inner(), + )?; + + // Check equality with instance + layouter.constrain_instance(result.x().cell(), config.primary, 0)?; + layouter.constrain_instance(result.y().cell(), config.primary, 1) + } + } + + // Test different circuits + let mut circuits = vec![]; + let mut instances = vec![]; + for choice in [false, true] { + let choice_value = if choice { + pallas::Base::one() + } else { + pallas::Base::zero() + }; + for left_point in [ + pallas::Point::identity().to_affine(), + pallas::Point::random(OsRng).to_affine(), + ] { + for right_point in [ + pallas::Point::identity().to_affine(), + pallas::Point::random(OsRng).to_affine(), + ] { + circuits.push(MyCircuit { + left_point: Value::known(left_point), + right_point: Value::known(right_point), + choice: Value::known(choice_value), + }); + let expected_output = if choice { right_point } else { left_point }; + let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { + (pallas::Base::zero(), pallas::Base::zero()) + } else { + let coords = expected_output.coordinates().unwrap(); + (*coords.x(), *coords.y()) + }; + instances.push([[expected_x, expected_y]]); + } + } + } + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + let prover = MockProver::::run( + K, + circuit, + instance.iter().map(|p| p.to_vec()).collect(), + ) + .unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } +} diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index 9daa685f2..47e2fda1c 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -9,6 +9,7 @@ use halo2_proofs::{ use pasta_curves::pallas; use crate::{ + circuit::gadget::mux_chip::{MuxChip, MuxInstructions}, constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}, value::NoteValue, }; @@ -575,13 +576,16 @@ impl DecomposeG { ) } } - -/// h = h_0 || h_1 || h_2 -/// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits +/// h_zec = h_0 || h_1 || h_2_zec +/// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits /// -/// | A_6 | A_7 | A_8 | q_notecommit_h | -/// ------------------------------------ -/// | h | h_0 | h_1 | 1 | +/// h_zsa = h_0 || h_1 || h_2_zsa +/// = (bits 249..=253 of psi) || (bit 254 of psi) || (bits 0..=3 of x(asset)) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_h | +/// -------------------------------------------- +/// | h_zec | h_0 | h_1 | 1 | +/// | h_zsa | h_2_zsa | | 0 | /// /// #[derive(Clone, Debug)] @@ -599,27 +603,38 @@ impl DecomposeH { col_m: Column, col_r: Column, two_pow_5: pallas::Base, + two_pow_6: pallas::Base, ) -> Self { let q_notecommit_h = meta.selector(); meta.create_gate("NoteCommit MessagePiece h", |meta| { let q_notecommit_h = meta.query_selector(q_notecommit_h); - // h has been constrained to 10 bits by the Sinsemilla hash. - let h = meta.query_advice(col_l, Rotation::cur()); + // h_zec has been constrained to 10 bits by the Sinsemilla hash. + let h_zec = meta.query_advice(col_l, Rotation::cur()); // h_0 has been constrained to be 5 bits outside this gate. let h_0 = meta.query_advice(col_m, Rotation::cur()); // This gate constrains h_1 to be boolean. let h_1 = meta.query_advice(col_r, Rotation::cur()); - // h = h_0 + (2^5) h_1 - let decomposition_check = h - (h_0 + h_1.clone() * two_pow_5); + // h_zsa has been constrained to 10 bits by the Sinsemilla hash. + let h_zsa = meta.query_advice(col_l, Rotation::next()); + // h_2_zsa has been constrained to be 4 bits outside this gate. + let h_2_zsa = meta.query_advice(col_m, Rotation::next()); + + // h_zec = h_0 + (2^5) h_1 + let zec_decomposition_check = h_zec - (h_0.clone() + h_1.clone() * two_pow_5); + + // h_zsa = h_0 + (2^5) h_1 + (2^6) h_2_zsa + let zsa_decomposition_check = + h_zsa - (h_0 + h_1.clone() * two_pow_5 + h_2_zsa * two_pow_6); Constraints::with_selector( q_notecommit_h, [ ("bool_check h_1", bool_check(h_1)), - ("decomposition", decomposition_check), + ("zec_decomposition", zec_decomposition_check), + ("zsa_decomposition", zsa_decomposition_check), ], ) }); @@ -638,11 +653,14 @@ impl DecomposeH { chip: SinsemillaChip, layouter: &mut impl Layouter, psi: &AssignedCell, + asset: &NonIdentityEccPoint, ) -> Result< ( + NoteCommitPiece, NoteCommitPiece, RangeConstrained>, RangeConstrained>, + RangeConstrained>, ), Error, > { @@ -657,9 +675,17 @@ impl DecomposeH { // h_1 will be boolean-constrained in the gate. let h_1 = RangeConstrained::bitrange_of(psi.value(), 254..255); - let h = MessagePiece::from_subpieces( - chip, - layouter.namespace(|| "h"), + // Constrain h_2_zsa to be 4 bits. + let h_2_zsa = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "h_2_zsa"), + asset.x().value(), + 0..4, + )?; + + let h_zec = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "h_zec"), [ h_0.value(), h_1, @@ -667,34 +693,164 @@ impl DecomposeH { ], )?; - Ok((h, h_0, h_1)) + let h_zsa = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "h_zsa"), + [h_0.value(), h_1, h_2_zsa.value()], + )?; + + Ok((h_zec, h_zsa, h_0, h_1, h_2_zsa)) } fn assign( &self, layouter: &mut impl Layouter, - h: NoteCommitPiece, + h_zec: NoteCommitPiece, + h_zsa: NoteCommitPiece, h_0: RangeConstrained>, h_1: RangeConstrained>, + h_2_zsa: RangeConstrained>, ) -> Result, Error> { layouter.assign_region( || "NoteCommit MessagePiece h", |mut region| { self.q_notecommit_h.enable(&mut region, 0)?; - h.inner() + h_zec + .inner() .cell_value() - .copy_advice(|| "h", &mut region, self.col_l, 0)?; + .copy_advice(|| "h_zec", &mut region, self.col_l, 0)?; h_0.inner() .copy_advice(|| "h_0", &mut region, self.col_m, 0)?; let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?; + h_zsa + .inner() + .cell_value() + .copy_advice(|| "h_zsa", &mut region, self.col_l, 1)?; + + h_2_zsa + .inner() + .copy_advice(|| "h_2_zsa", &mut region, self.col_m, 1)?; + Ok(h_1) }, ) } } +/// j = j_0 || j_1 +/// = (bit 254 of x(asset)) || (ỹ bit of asset) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_j | +/// ------------------------------------ +/// | j | j_0 | j_1 | 1 | +/// +/// https://p.z.cash/orchard-0.1:note-commit-decomposition-j?partial +#[derive(Clone, Debug)] +struct DecomposeJ { + q_notecommit_j: Selector, + col_l: Column, + col_m: Column, + col_r: Column, +} + +impl DecomposeJ { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two: pallas::Base, + ) -> Self { + let q_notecommit_j = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece j", |meta| { + let q_notecommit_j = meta.query_selector(q_notecommit_j); + + // j has been constrained to 10 bits by the Sinsemilla hash. + let j = meta.query_advice(col_l, Rotation::cur()); + // This gate constrains j_0 to be boolean. + let j_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains j_1 to be boolean. + let j_1 = meta.query_advice(col_r, Rotation::cur()); + + // j = j_0 + (2) j_1 + let decomposition_check = j - (j_0.clone() + j_1.clone() * two); + + Constraints::with_selector( + q_notecommit_j, + [ + ("bool_check j_0", bool_check(j_0)), + ("bool_check j_1", bool_check(j_1)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_j, + col_l, + col_m, + col_r, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + chip: SinsemillaChip, + layouter: &mut impl Layouter, + asset: &NonIdentityEccPoint, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + // j_0, j_1 will be boolean-constrained in the gate. + let j_0 = RangeConstrained::bitrange_of(asset.x().value(), 254..255); + let j_1 = RangeConstrained::bitrange_of(asset.y().value(), 0..1); + + let j = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "j"), + [ + j_0, + j_1, + RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..8), + ], + )?; + + Ok((j, j_0, j_1)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + j: NoteCommitPiece, + j_0: RangeConstrained>, + j_1: RangeConstrained>, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece j", + |mut region| { + self.q_notecommit_j.enable(&mut region, 0)?; + + j.inner() + .cell_value() + .copy_advice(|| "j", &mut region, self.col_l, 0)?; + let j_0 = region.assign_advice(|| "j_0", self.col_m, 0, || *j_0.inner())?; + j_1.inner() + .copy_advice(|| "j_1", &mut region, self.col_r, 0)?; + + Ok(j_0) + }, + ) + } +} + /// | A_6 | A_7 | A_8 | A_9 | q_notecommit_g_d | /// ----------------------------------------------------------- /// | x(g_d) | b_0 | a | z13_a | 1 | @@ -811,23 +967,29 @@ impl GdCanonicity { ) } } - -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d | -/// ------------------------------------------------------------------- -/// | x(pk_d) | b_3 | c | z13_c | 1 | -/// | | d_0 | b3_c_prime | z14_b3_c_prime | 0 | +/// For pk_d +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d_asset | +/// ------------------------------------------------------------------------- +/// | x(pk_d) | b_3 | c | z13_c | 1 | +/// | | d_0 | b3_c_prime | z14_b3_c_prime | 0 | +/// +/// For asset +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d_asset | +/// ------------------------------------------------------------------------------ +/// | x(asset) | h_2_zsa | i | z13_i | 1 | +/// | | j_0 | h2_i_prime | z14_h2_i_prime | 0 | /// /// #[derive(Clone, Debug)] -struct PkdCanonicity { - q_notecommit_pk_d: Selector, +struct PkdAssetCanonicity { + q_notecommit_pk_d_asset: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, } -impl PkdCanonicity { +impl PkdAssetCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -840,10 +1002,13 @@ impl PkdCanonicity { two_pow_254: pallas::Base, t_p: Expression, ) -> Self { - let q_notecommit_pk_d = meta.selector(); + let q_notecommit_pk_d_asset = meta.selector(); - meta.create_gate("NoteCommit input pk_d", |meta| { - let q_notecommit_pk_d = meta.query_selector(q_notecommit_pk_d); + meta.create_gate("NoteCommit input pk_d or asset", |meta| { + // The comments and variable names are for `pk_d` + // This gate is also used with `asset`. + // We have just to replace `pk_d`, `b_3`, `c`, `d_0` by `asset`, `h_2_zsa`, `i`, `j_0` + let q_notecommit_pk_d_asset = meta.query_selector(q_notecommit_pk_d_asset); let pkd_x = meta.query_advice(col_l, Rotation::cur()); @@ -876,7 +1041,7 @@ impl PkdCanonicity { .map(move |(name, poly)| (name, d_0.clone() * poly)); Constraints::with_selector( - q_notecommit_pk_d, + q_notecommit_pk_d_asset, iter::empty() .chain(Some(("decomposition", decomposition_check))) .chain(Some(("b3_c_prime_check", b3_c_prime_check))) @@ -885,7 +1050,7 @@ impl PkdCanonicity { }); Self { - q_notecommit_pk_d, + q_notecommit_pk_d_asset, col_l, col_m, col_r, @@ -895,6 +1060,9 @@ impl PkdCanonicity { #[allow(clippy::too_many_arguments)] fn assign( + // This function is used for `pk_d` and `asset`. + // For `pk_d`, inputs are `pk_d`, `b_3`, `c`, `d_0`, `b3_c_prime`, `z13_c`, `z14_b3_c_prime` + // For `asset`, inputs are `asset`, `h_2_zsa`, `i`, `j_0`, `h2_i_prime`, `z13_i`, `z14_h2_i_prime` &self, layouter: &mut impl Layouter, pk_d: &NonIdentityEccPoint, @@ -906,7 +1074,7 @@ impl PkdCanonicity { z14_b3_c_prime: AssignedCell, ) -> Result<(), Error> { layouter.assign_region( - || "NoteCommit input pk_d", + || "NoteCommit input pk_d or asset", |mut region| { pk_d.x() .copy_advice(|| "pkd_x", &mut region, self.col_l, 0)?; @@ -923,7 +1091,7 @@ impl PkdCanonicity { z13_c.copy_advice(|| "z13_c", &mut region, self.col_z, 0)?; z14_b3_c_prime.copy_advice(|| "z14_b3_c_prime", &mut region, self.col_z, 1)?; - self.q_notecommit_pk_d.enable(&mut region, 0) + self.q_notecommit_pk_d_asset.enable(&mut region, 0) }, ) } @@ -1418,8 +1586,9 @@ pub struct NoteCommitConfig { e: DecomposeE, g: DecomposeG, h: DecomposeH, + j: DecomposeJ, g_d: GdCanonicity, - pk_d: PkdCanonicity, + pk_d_asset: PkdAssetCanonicity, value: ValueCanonicity, rho: RhoCanonicity, psi: PsiCanonicity, @@ -1474,7 +1643,8 @@ impl NoteCommitChip { let d = DecomposeD::configure(meta, col_l, col_m, col_r, two, two_pow_2, two_pow_10); let e = DecomposeE::configure(meta, col_l, col_m, col_r, two_pow_6); let g = DecomposeG::configure(meta, col_l, col_m, two, two_pow_10); - let h = DecomposeH::configure(meta, col_l, col_m, col_r, two_pow_5); + let h = DecomposeH::configure(meta, col_l, col_m, col_r, two_pow_5, two_pow_6); + let j = DecomposeJ::configure(meta, col_l, col_m, col_r, two); let g_d = GdCanonicity::configure( meta, @@ -1488,7 +1658,7 @@ impl NoteCommitChip { t_p.clone(), ); - let pk_d = PkdCanonicity::configure( + let pk_d_asset = PkdAssetCanonicity::configure( meta, col_l, col_m, @@ -1545,8 +1715,9 @@ impl NoteCommitChip { e, g, h, + j, g_d, - pk_d, + pk_d_asset, value, rho, psi, @@ -1574,12 +1745,15 @@ pub(in crate::circuit) mod gadgets { chip: SinsemillaChip, ecc_chip: EccChip, note_commit_chip: NoteCommitChip, + mux_chip: MuxChip, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, value: AssignedCell, rho: AssignedCell, psi: AssignedCell, + asset: &NonIdentityEccPoint, rcm: ScalarFixed>, + is_native_asset: AssignedCell, ) -> Result>, Error> { let lookup_config = chip.config().lookup_config(); @@ -1623,10 +1797,22 @@ pub(in crate::circuit) mod gadgets { let (g, g_0, g_1) = DecomposeG::decompose(&lookup_config, chip.clone(), &mut layouter, &rho, &psi)?; - // h = h_0 || h_1 || h_2 + // h_zec = h_0 || h_1 || h_2_zec // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits - let (h, h_0, h_1) = - DecomposeH::decompose(&lookup_config, chip.clone(), &mut layouter, &psi)?; + // h_zsa = h_0 || h_1 || h_2_zsa + // = (bits 249..=253 of psi) || (bit 254 of psi) || (bits 0..=3 of x(asset)) + let (h_zec, h_zsa, h_0, h_1, h_2_zsa) = + DecomposeH::decompose(&lookup_config, chip.clone(), &mut layouter, &psi, asset)?; + + // i = bits 4..=253 of asset + let i = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "i"), + [RangeConstrained::bitrange_of(asset.x().value(), 4..254)], + )?; + + // j = j_0 || j_1 || j_2 = (bit 254 of x(asset)) || (ỹ bit of asset) || 8 zero bits + let (j, j_0, j_1) = DecomposeJ::decompose(chip.clone(), &mut layouter, asset)?; // Check decomposition of `y(g_d)`. let b_2 = y_canonicity( @@ -1644,6 +1830,14 @@ pub(in crate::circuit) mod gadgets { pk_d.y(), d_1, )?; + // Check decomposition of `y(asset)`. + let j_1 = y_canonicity( + &lookup_config, + ¬e_commit_chip.config.y_canon, + layouter.namespace(|| "y(asset) decomposition"), + asset.y(), + j_1, + )?; // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) // @@ -1654,7 +1848,21 @@ pub(in crate::circuit) mod gadgets { // https://p.z.cash/ZKS:action-cm-old-integrity?partial // https://p.z.cash/ZKS:action-cmx-new-integrity?partial let (cm, zs) = { - let message = Message::from_pieces( + let message_zec = Message::from_pieces( + chip.clone(), + vec![ + a.clone(), + b.clone(), + c.clone(), + d.clone(), + e.clone(), + f.clone(), + g.clone(), + h_zec.clone(), + ], + ); + + let message_zsa = Message::from_pieces( chip.clone(), vec![ a.clone(), @@ -1664,18 +1872,61 @@ pub(in crate::circuit) mod gadgets { e.clone(), f.clone(), g.clone(), - h.clone(), + h_zsa.clone(), + i.clone(), + j.clone(), ], ); - let domain = CommitDomain::new(chip, ecc_chip, &OrchardCommitDomains::NoteCommit); - domain.commit( - layouter.namespace(|| "Process NoteCommit inputs"), - message, - rcm, - )? + + let zec_domain = CommitDomain::new( + chip.clone(), + ecc_chip.clone(), + &OrchardCommitDomains::NoteCommit, + ); + let zsa_domain = + CommitDomain::new(chip, ecc_chip.clone(), &OrchardCommitDomains::NoteZsaCommit); + + // We evaluate `hash_point_zec=hash(Q_ZEC, message_zec)` and `hash_point_zsa(Q_ZSA, message_zsa) + // and then perform a MUX to select the desired hash_point + // TODO: We can optimize the evaluation of hash_point by mutualizing a portion of the + // hash evaluation process between hash_point_zec and hash_point_zsa. + // 1. common_bits = a || b || c || d || e || f || g + // 2. suffix_zec = h_zec + // 3. suffix_zsa = h_zsa || i || j + // 4. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} + // 5. hash_prefix = hash(Q, common_bits) // this part is mutualized + // 6. hash_zec = hash(hash_prefix, suffix_zec) + // 7. hash_zsa = hash(hash_prefix, suffix_zsa) + // 8. hash_point = if (is_native_asset == 0) {hash_zsa} else {hash_zec} + let (hash_point_zec, _zs_zec) = + zec_domain.hash(layouter.namespace(|| "hash ZEC note"), message_zec)?; + let (hash_point_zsa, zs_zsa) = + zsa_domain.hash(layouter.namespace(|| "hash ZSA note"), message_zsa)?; + + // Perform a MUX to select the desired hash point + // hash_point = hash_zec if is_native_asset is true + // hash_point = hash_zsa if is_native_asset is false + let hash_point = Point::from_inner( + ecc_chip, + mux_chip.mux( + layouter.namespace(|| "mux on hash point"), + &is_native_asset, + &(hash_point_zsa.inner().clone().into()), + &(hash_point_zec.inner().clone().into()), + )?, + ); + + // To evaluate the blinding factor, we could use either zec_domain or zsa_domain + // because they have both the same `R` constant. + let blinding_factor = + zec_domain.blinding_factor(layouter.namespace(|| "[r] R"), rcm)?; + let commitment = + hash_point.add(layouter.namespace(|| "M + [r] R"), &blinding_factor)?; + + (commitment, zs_zsa) }; - // `CommitDomain::commit` returns the running sum for each `MessagePiece`. Grab + // `CommitDomain::hash` returns the running sum for each `MessagePiece`. Grab // the outputs that we will need for canonicity checks. let z13_a = zs[0][13].clone(); let z13_c = zs[2][13].clone(); @@ -1684,6 +1935,7 @@ pub(in crate::circuit) mod gadgets { let z1_g = zs[6][1].clone(); let g_2 = z1_g.clone(); let z13_g = zs[6][13].clone(); + let z13_i = zs[8][13].clone(); // Witness and constrain the bounds we need to ensure canonicity. let (a_prime, z13_a_prime) = canon_bitshift_130( @@ -1692,13 +1944,20 @@ pub(in crate::circuit) mod gadgets { a.inner().cell_value(), )?; - let (b3_c_prime, z14_b3_c_prime) = pkd_x_canonicity( + let (b3_c_prime, z14_b3_c_prime) = pkd_asset_x_canonicity( &lookup_config, layouter.namespace(|| "x(pk_d) canonicity"), b_3.clone(), c.inner().cell_value(), )?; + let (h2_i_prime, z14_h2_i_prime) = pkd_asset_x_canonicity( + &lookup_config, + layouter.namespace(|| "x(asset) canonicity"), + h_2_zsa.clone(), + i.inner().cell_value(), + )?; + let (e1_f_prime, z14_e1_f_prime) = rho_canonicity( &lookup_config, layouter.namespace(|| "rho canonicity"), @@ -1730,12 +1989,21 @@ pub(in crate::circuit) mod gadgets { .g .assign(&mut layouter, g, g_0, g_1.clone(), z1_g.clone())?; - let h_1 = cfg.h.assign(&mut layouter, h, h_0.clone(), h_1)?; + let h_1 = cfg.h.assign( + &mut layouter, + h_zec, + h_zsa, + h_0.clone(), + h_1, + h_2_zsa.clone(), + )?; + + let j_0 = cfg.j.assign(&mut layouter, j, j_0, j_1)?; cfg.g_d .assign(&mut layouter, g_d, a, b_0, b_1, a_prime, z13_a, z13_a_prime)?; - cfg.pk_d.assign( + cfg.pk_d_asset.assign( &mut layouter, pk_d, b_3, @@ -1746,6 +2014,17 @@ pub(in crate::circuit) mod gadgets { z14_b3_c_prime, )?; + cfg.pk_d_asset.assign( + &mut layouter, + asset, + h_2_zsa, + i, + j_0, + h2_i_prime, + z13_i, + z14_h2_i_prime, + )?; + cfg.value.assign(&mut layouter, value, d_2, z1_d, e_0)?; cfg.rho.assign( @@ -1810,15 +2089,16 @@ pub(in crate::circuit) mod gadgets { Ok((a_prime, zs[13].clone())) } - /// Check canonicity of `x(pk_d)` encoding. + /// Check canonicity of `x(pk_d)` and `x(asset)` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-pk_d?partial). - fn pkd_x_canonicity( + fn pkd_asset_x_canonicity( lookup_config: &LookupRangeCheckConfig, mut layouter: impl Layouter, b_3: RangeConstrained>, c: AssignedCell, ) -> Result { + // Example for `x(pk_d)`: // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` // - d_0 = 1 => b_3 + 2^4 c < t_P // - 0 ≤ b_3 + 2^4 c < 2^134 @@ -1828,6 +2108,7 @@ pub(in crate::circuit) mod gadgets { // - z_13 of SinsemillaHash(c) == 0 constrains bits 4..=253 of pkd_x // to 130 bits. z13_c is directly checked in the gate. // - 0 ≤ b_3 + 2^4 c + 2^140 - t_P < 2^140 (14 ten-bit lookups) + // For `x(asset)`, we have to replace `pk_d`, `b_3`, `c`, `d_0` by `asset`, `h_2_zsa`, `i`, `j_0` // Decompose the low 140 bits of b3_c_prime = b_3 + 2^4 c + 2^140 - t_P, // and output the running sum at the end of it. @@ -2013,18 +2294,17 @@ pub(in crate::circuit) mod gadgets { #[cfg(test)] mod tests { - use core::iter; - use super::NoteCommitConfig; use crate::{ circuit::{ - gadget::assign_free_advice, + gadget::{ + assign_free_advice, assign_is_native_asset, + mux_chip::{MuxChip, MuxConfig}, + }, note_commit::{gadgets, NoteCommitChip}, }, - constants::{ - fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, - OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q, - }, + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_Q}, + note::{commitment::NoteCommitTrapdoor, AssetBase, NoteCommitment}, value::NoteValue, }; use halo2_gadgets::{ @@ -2033,18 +2313,17 @@ mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::chip::SinsemillaChip, - sinsemilla::primitives::CommitDomain, utilities::lookup_range_check::LookupRangeCheckConfig, }; - use ff::{Field, PrimeField, PrimeFieldBits}; - use group::Curve; + use ff::{Field, PrimeField}; + use group::{Curve, Group, GroupEncoding}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, dev::MockProver, plonk::{Circuit, ConstraintSystem, Error}, }; - use pasta_curves::{arithmetic::CurveAffine, pallas}; + use pasta_curves::{arithmetic::CurveAffine, pallas, EpAffine}; use rand::{rngs::OsRng, RngCore}; @@ -2052,16 +2331,15 @@ mod tests { fn note_commit() { #[derive(Default)] struct MyCircuit { - gd_x: Value, - gd_y_lsb: Value, - pkd_x: Value, - pkd_y_lsb: Value, + g_d: Value, + pk_d: Value, rho: Value, psi: Value, + asset: Value, } impl Circuit for MyCircuit { - type Config = (NoteCommitConfig, EccConfig); + type Config = (NoteCommitConfig, EccConfig, MuxConfig); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -2130,7 +2408,10 @@ mod tests { range_check, ); - (note_commit_config, ecc_config) + let mux_config = + MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); + + (note_commit_config, ecc_config, mux_config) } fn synthesize( @@ -2138,7 +2419,7 @@ mod tests { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let (note_commit_config, ecc_config) = config; + let (note_commit_config, ecc_config, mux_config) = config; // Load the Sinsemilla generator lookup table used by the whole circuit. SinsemillaChip::< @@ -2157,41 +2438,22 @@ mod tests { // Construct a NoteCommit chip let note_commit_chip = NoteCommitChip::construct(note_commit_config.clone()); + // Construct a Mux chip + let mux_chip = MuxChip::construct(mux_config); + // Witness g_d - let g_d = { - let g_d = self.gd_x.zip(self.gd_y_lsb).map(|(x, y_lsb)| { - // Calculate y = (x^3 + 5).sqrt() - let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); - if bool::from(y.is_odd() ^ y_lsb.is_odd()) { - y = -y; - } - pallas::Affine::from_xy(x, y).unwrap() - }); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness g_d"), - g_d, - )? - }; + let g_d = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d"), + self.g_d, + )?; // Witness pk_d - let pk_d = { - let pk_d = self.pkd_x.zip(self.pkd_y_lsb).map(|(x, y_lsb)| { - // Calculate y = (x^3 + 5).sqrt() - let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); - if bool::from(y.is_odd() ^ y_lsb.is_odd()) { - y = -y; - } - pallas::Affine::from_xy(x, y).unwrap() - }); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness pk_d"), - pk_d, - )? - }; + let pk_d = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d"), + self.pk_d, + )?; // Witness a random non-negative u64 note value // A note value cannot be negative. @@ -2228,54 +2490,52 @@ mod tests { Value::known(rcm), )?; + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + self.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + let is_native_asset = assign_is_native_asset( + layouter.namespace(|| "witness is_native_asset"), + note_commit_config.advices[0], + self.asset, + )?; let cm = gadgets::note_commit( layouter.namespace(|| "Hash NoteCommit pieces"), sinsemilla_chip, ecc_chip.clone(), note_commit_chip, + mux_chip, g_d.inner(), pk_d.inner(), value_var, rho, psi, + asset.inner(), rcm_gadget, + is_native_asset, )?; let expected_cm = { - let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi - let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one(); let point = self - .gd_x - .zip(self.gd_y_lsb) - .zip(self.pkd_x.zip(self.pkd_y_lsb)) + .g_d + .zip(self.pk_d) .zip(self.rho.zip(self.psi)) - .map(|(((gd_x, gd_y_lsb), (pkd_x, pkd_y_lsb)), (rho, psi))| { - domain - .commit( - iter::empty() - .chain( - gd_x.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ) - .chain(Some(lsb(gd_y_lsb))) - .chain( - pkd_x - .to_le_bits() - .iter() - .by_vals() - .take(L_ORCHARD_BASE), - ) - .chain(Some(lsb(pkd_y_lsb))) - .chain(value.to_le_bits().iter().by_vals().take(L_VALUE)) - .chain( - rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ) - .chain( - psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ), - &rcm, - ) - .unwrap() - .to_affine() + .zip(self.asset) + .map(|(((g_d, pk_d), (rho, psi)), asset)| { + NoteCommitment::derive( + g_d.to_bytes(), + pk_d.to_bytes(), + value, + asset, + rho, + psi, + NoteCommitTrapdoor(rcm), + ) + .unwrap() + .inner() + .to_affine() }); NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)? }; @@ -2283,74 +2543,132 @@ mod tests { } } + fn affine_point_from_coordinates(x_coord: pallas::Base, y_lsb: pallas::Base) -> EpAffine { + // Calculate y = (x^3 + 5).sqrt() + let mut y = (x_coord.square() * x_coord + pallas::Affine::b()) + .sqrt() + .unwrap(); + if bool::from(y.is_odd() ^ y_lsb.is_odd()) { + y = -y; + } + pallas::Affine::from_xy(x_coord, y).unwrap() + } + let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); + let mut rng = OsRng; + let random_asset = AssetBase::random(&mut rng); + // Test different values of `ak`, `nk` - let circuits = [ + let mut circuits = vec![]; + for asset in [random_asset, AssetBase::native()] { // `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points) // `rho` = 0, `psi` = 0 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::one()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), rho: Value::known(pallas::Base::zero()), psi: Value::known(pallas::Base::zero()), - }, + asset: Value::known(asset), + }); // `rho` = T_Q - 1, `psi` = T_Q - 1 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::zero()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), rho: Value::known(pallas::Base::from_u128(T_Q - 1)), psi: Value::known(pallas::Base::from_u128(T_Q - 1)), - }, + asset: Value::known(asset), + }); // `rho` = T_Q, `psi` = T_Q - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), rho: Value::known(pallas::Base::from_u128(T_Q)), psi: Value::known(pallas::Base::from_u128(T_Q)), - }, + asset: Value::known(asset), + }); // `rho` = 2^127 - 1, `psi` = 2^127 - 1 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::zero()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::one()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)), psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)), - }, + asset: Value::known(asset), + }); // `rho` = 2^127, `psi` = 2^127 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::zero()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), rho: Value::known(pallas::Base::from_u128(1 << 127)), psi: Value::known(pallas::Base::from_u128(1 << 127)), - }, + asset: Value::known(asset), + }); // `rho` = 2^254 - 1, `psi` = 2^254 - 1 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::one()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), rho: Value::known(two_pow_254 - pallas::Base::one()), psi: Value::known(two_pow_254 - pallas::Base::one()), - }, + asset: Value::known(asset), + }); // `rho` = 2^254, `psi` = 2^254 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), + circuits.push(MyCircuit { + g_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::one(), + )), + pk_d: Value::known(affine_point_from_coordinates( + -pallas::Base::one(), + pallas::Base::zero(), + )), rho: Value::known(two_pow_254), psi: Value::known(two_pow_254), - }, - ]; + asset: Value::known(asset), + }); + // Random values + circuits.push(MyCircuit { + g_d: Value::known(pallas::Point::random(rng).to_affine()), + pk_d: Value::known(pallas::Point::random(rng).to_affine()), + rho: Value::known(pallas::Base::random(&mut rng)), + psi: Value::known(pallas::Base::random(&mut rng)), + asset: Value::known(asset), + }); + } for circuit in circuits.iter() { let prover = MockProver::::run(11, circuit, vec![]).unwrap(); diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs index 078e9378f..4e4dfa36d 100644 --- a/src/circuit/value_commit_orchard.rs +++ b/src/circuit/value_commit_orchard.rs @@ -95,7 +95,6 @@ mod tests { circuit::gadget::{assign_free_advice, value_commit_orchard}, circuit::K, constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, - keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}, note::AssetBase, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, }; @@ -299,13 +298,7 @@ mod tests { let mut circuits = vec![]; let mut instances = vec![]; let native_asset = AssetBase::native(); - let random_asset = { - let sk = SpendingKey::random(&mut rng); - let isk = IssuanceAuthorizingKey::from(&sk); - let ik = IssuanceValidatingKey::from(&isk); - let asset_descr = "zsa_asset"; - AssetBase::derive(&ik, asset_descr) - }; + let random_asset = AssetBase::random(&mut rng); for split_flag in [false, true] { for asset in [native_asset, random_asset] { let v_old = NoteValue::from_raw(rng.next_u64()); diff --git a/src/circuit_description b/src/circuit_description index 212da733f..247c89889 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -2,46 +2,30 @@ PinnedVerificationKey { base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", domain: PinnedEvaluationDomain { - k: 11, - extended_k: 14, - omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + k: 12, + extended_k: 15, + omega: 0x028961bbd9c63b7bd7c75f72e02a9727d14d99e7985184470d34cd1b8ef03001, }, cs: PinnedConstraintSystem { num_fixed_columns: 30, num_advice_columns: 10, num_instance_columns: 1, - num_selectors: 56, + num_selectors: 59, gates: [ Product( Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -56,7 +40,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -71,7 +55,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -112,32 +96,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -152,7 +120,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -167,7 +135,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -239,32 +207,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -279,7 +231,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -294,7 +246,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -339,32 +291,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -379,7 +315,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -394,7 +330,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -435,32 +371,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -475,7 +395,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -490,7 +410,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -531,32 +451,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -571,7 +475,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -586,7 +490,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -638,32 +542,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -678,7 +566,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -693,7 +581,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -706,31 +594,27 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), ), ), ), @@ -738,29 +622,13 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, @@ -778,7 +646,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -793,7 +661,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -806,34 +674,27 @@ PinnedVerificationKey { ), ), ), - Sum( - Product( - Scaled( - Advice { - query_index: 12, - column_index: 9, - rotation: Rotation( - -1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, + Product( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, ), + }, + Sum( Advice { - query_index: 11, - column_index: 9, + query_index: 12, + column_index: 2, rotation: Rotation( 1, ), }, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, + Negated( + Constant( + 0x2f70597a8e3d0f42f7a86a704f9bb232fe04a37f2b5a7c8c2aa7bd6e3af94367, ), - }, + ), ), ), ), @@ -841,48 +702,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -897,7 +726,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -910,53 +739,79 @@ PinnedVerificationKey { ), ), ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( Advice { - query_index: 0, - column_index: 0, + query_index: 11, + column_index: 1, rotation: Rotation( - 0, + 1, ), }, - ), - Sum( Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Constant( + 0x2d0e5169311919af1e917f63136d6c421d9ea766a7ffe3dba413c47eaf5af28e, + ), + ), + ), + ), + ), + Product( + Product( + Product( Product( - Advice { - query_index: 1, - column_index: 1, + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, ), - }, - ), - Negated( - Product( - Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 0, - column_index: 0, + Negated( + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, ), - Advice { - query_index: 0, - column_index: 0, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -964,145 +819,98 @@ PinnedVerificationKey { ), ), ), - Negated( + Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, ), ), ), - ), - Product( Product( Product( - Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + Sum( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, + Sum( + Advice { + query_index: 12, + column_index: 2, rotation: Rotation( - 0, + 1, ), }, - Sum( + Negated( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, + 0x2f70597a8e3d0f42f7a86a704f9bb232fe04a37f2b5a7c8c2aa7bd6e3af94367, ), ), ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, ), - ), + }, ), - Sum( + Negated( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), ), ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), ), - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - Sum( Sum( Product( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Constant( + 0x2d0e5169311919af1e917f63136d6c421d9ea766a7ffe3dba413c47eaf5af28e, + ), ), - }, + ), Advice { - query_index: 1, - column_index: 1, + query_index: 15, + column_index: 5, rotation: Rotation( - 0, + 1, ), }, ), Negated( - Product( - Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), ), ), - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - ), ), ), Product( @@ -1110,20 +918,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1137,8 +945,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1152,8 +960,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1163,54 +971,29 @@ PinnedVerificationKey { ), Sum( Sum( - Product( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Product( - Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), - ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, ), Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -1219,8 +1002,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1231,8 +1014,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1242,12 +1025,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1261,8 +1044,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1272,44 +1055,70 @@ PinnedVerificationKey { ), Sum( Product( - Product( - Sum( - Sum( - Advice { - query_index: 13, - column_index: 2, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, + Scaled( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + -1, ), - Advice { - query_index: 0, - column_index: 0, + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), ), Sum( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), Negated( - Advice { - query_index: 2, - column_index: 2, + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -1318,17 +1127,67 @@ PinnedVerificationKey { ), ), Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( Advice { - query_index: 0, - column_index: 0, + query_index: 1, + column_index: 1, rotation: Rotation( 0, ), }, - Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), Advice { - query_index: 2, - column_index: 2, + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), @@ -1337,45 +1196,128 @@ PinnedVerificationKey { ), ), Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( Product( - Sum( - Advice { - query_index: 1, - column_index: 1, + Product( + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), Negated( - Advice { - query_index: 3, - column_index: 3, + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, ), ), - Sum( - Advice { - query_index: 1, - column_index: 1, + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), }, - Negated( + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( Advice { - query_index: 3, - column_index: 3, + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), }, ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, ), ), ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), ), ), Product( @@ -1391,7 +1333,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1435,82 +1377,56 @@ PinnedVerificationKey { ), ), Sum( - Product( - Sum( - Advice { - query_index: 14, - column_index: 3, - rotation: Rotation( - 1, - ), - }, + Sum( + Product( Advice { - query_index: 3, - column_index: 3, + query_index: 1, + column_index: 1, rotation: Rotation( 0, ), }, - ), - Sum( Advice { - query_index: 0, - column_index: 0, + query_index: 1, + column_index: 1, rotation: Rotation( 0, ), }, - Negated( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - ), ), - ), - Negated( - Product( - Sum( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - Negated( + Negated( + Product( + Product( Advice { - query_index: 3, - column_index: 3, + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), }, ), - ), - Sum( Advice { - query_index: 2, - column_index: 2, + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), }, - Negated( - Advice { - query_index: 13, - column_index: 2, - rotation: Rotation( - 1, - ), - }, - ), ), ), ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), ), ), Product( @@ -1541,7 +1457,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -1569,16 +1485,54 @@ PinnedVerificationKey { ), ), ), - Product( - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, ), - }, - Negated( + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( Advice { query_index: 0, column_index: 0, @@ -1586,49 +1540,49 @@ PinnedVerificationKey { 0, ), }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), ), ), - Sum( + Negated( Product( Sum( Advice { - query_index: 2, - column_index: 2, + query_index: 1, + column_index: 1, rotation: Rotation( 0, ), }, Negated( Advice { - query_index: 0, - column_index: 0, + query_index: 3, + column_index: 3, rotation: Rotation( 0, ), }, ), ), - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), - Negated( Sum( Advice { - query_index: 3, - column_index: 3, + query_index: 1, + column_index: 1, rotation: Rotation( 0, ), }, Negated( Advice { - query_index: 1, - column_index: 1, + query_index: 3, + column_index: 3, rotation: Rotation( 0, ), @@ -1667,7 +1621,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -1695,34 +1649,36 @@ PinnedVerificationKey { ), ), ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Sum( + Product( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, ), - Negated( - Product( - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - Negated( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, ), + }, + Negated( Advice { - query_index: 5, - column_index: 5, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), @@ -1730,12 +1686,9 @@ PinnedVerificationKey { ), ), ), - Sum( + Negated( Product( - Product( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), + Sum( Advice { query_index: 1, column_index: 1, @@ -1743,33 +1696,30 @@ PinnedVerificationKey { 0, ), }, - ), - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Product( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Product( + Negated( Advice { - query_index: 0, - column_index: 0, + query_index: 3, + column_index: 3, rotation: Rotation( 0, ), }, + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( Advice { - query_index: 0, - column_index: 0, + query_index: 12, + column_index: 2, rotation: Rotation( - 0, + 1, ), }, ), @@ -1835,61 +1785,34 @@ PinnedVerificationKey { ), ), Product( - Product( - Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - ), - Sum( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( Advice { - query_index: 2, - column_index: 2, + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), }, - Negated( + ), + ), + Sum( + Product( + Sum( Advice { - query_index: 0, - column_index: 0, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), }, - ), - ), - ), - Sum( - Sum( - Sum( - Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), Negated( Advice { query_index: 0, @@ -1900,24 +1823,33 @@ PinnedVerificationKey { }, ), ), - Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( Advice { - query_index: 2, - column_index: 2, + query_index: 3, + column_index: 3, rotation: Rotation( 0, ), }, - ), - ), - Negated( - Advice { - query_index: 13, - column_index: 2, - rotation: Rotation( - 1, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, ), - }, + ), ), ), ), @@ -1979,72 +1911,46 @@ PinnedVerificationKey { ), ), Product( - Product( - Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - Negated( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), Sum( - Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, Sum( Advice { - query_index: 0, - column_index: 0, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), }, Negated( Advice { - query_index: 13, - column_index: 2, + query_index: 0, + column_index: 0, rotation: Rotation( - 1, + 0, ), }, ), ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, ), - Negated( + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), Advice { query_index: 1, column_index: 1, @@ -2053,16 +1959,37 @@ PinnedVerificationKey { ), }, ), - ), - Negated( Advice { - query_index: 14, - column_index: 3, + query_index: 4, + column_index: 4, rotation: Rotation( - 1, + 0, ), }, ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), ), ), ), @@ -2142,19 +2069,21 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 1, - column_index: 1, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), ), ), Sum( @@ -2198,7 +2127,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2284,19 +2213,21 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 1, - column_index: 1, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), ), ), Sum( @@ -2319,7 +2250,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -2340,7 +2271,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -2407,22 +2338,125 @@ PinnedVerificationKey { ), ), Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, ), - Negated( - Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( Advice { - query_index: 0, - column_index: 0, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), }, - Advice { - query_index: 6, - column_index: 6, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -2431,14 +2465,30 @@ PinnedVerificationKey { ), ), Sum( - Advice { - query_index: 13, - column_index: 2, - rotation: Rotation( - 1, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, Advice { query_index: 2, column_index: 2, @@ -2447,6 +2497,71 @@ PinnedVerificationKey { ), }, ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), ), ), ), @@ -2532,16 +2647,16 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, - column_index: 3, + query_index: 12, + column_index: 2, rotation: Rotation( 1, ), }, Negated( Advice { - query_index: 3, - column_index: 3, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), @@ -2614,15 +2729,15 @@ PinnedVerificationKey { Negated( Product( Advice { - query_index: 2, - column_index: 2, + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), }, Advice { - query_index: 7, - column_index: 7, + query_index: 6, + column_index: 6, rotation: Rotation( 0, ), @@ -2633,15 +2748,15 @@ PinnedVerificationKey { Sum( Advice { query_index: 13, - column_index: 2, + column_index: 3, rotation: Rotation( 1, ), }, Negated( Advice { - query_index: 0, - column_index: 0, + query_index: 3, + column_index: 3, rotation: Rotation( 0, ), @@ -2732,16 +2847,16 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, - column_index: 3, + query_index: 12, + column_index: 2, rotation: Rotation( 1, ), }, Negated( Advice { - query_index: 1, - column_index: 1, + query_index: 0, + column_index: 0, rotation: Rotation( 0, ), @@ -2808,17 +2923,117 @@ PinnedVerificationKey { ), Product( Sum( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, ), - Negated( - Product( - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( 0, ), }, @@ -2871,7 +3086,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -3000,7 +3215,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3012,37 +3227,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3052,12 +3251,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3067,12 +3266,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -3093,14 +3292,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -3109,7 +3308,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3120,14 +3319,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -3136,7 +3335,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3166,21 +3365,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3190,12 +3421,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3205,12 +3436,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3241,51 +3472,83 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( + Product( + Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, ), ), ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3303,7 +3566,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 17, + query_index: 11, column_index: 1, rotation: Rotation( 1, @@ -3316,21 +3579,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3340,12 +3635,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3355,12 +3650,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3380,7 +3675,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -3406,7 +3701,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -3424,21 +3719,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3448,12 +3775,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3463,12 +3790,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3592,7 +3919,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -3624,21 +3951,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3648,12 +4007,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3663,12 +4022,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3697,7 +4056,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3761,36 +4120,68 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 19, - column_index: 19, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( + Product( + Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), }, - ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3800,12 +4191,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -3833,7 +4224,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3920,14 +4311,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -3936,7 +4327,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3947,14 +4338,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -3963,7 +4354,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -3994,16 +4385,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -4018,7 +4425,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -4033,7 +4440,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -4048,7 +4455,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -4073,7 +4480,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4099,7 +4506,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4118,16 +4525,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -4142,7 +4565,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -4157,7 +4580,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -4172,7 +4595,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -4301,7 +4724,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4334,16 +4757,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -4358,7 +4797,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -4373,7 +4812,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -4388,7 +4827,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -4422,7 +4861,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4487,16 +4926,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -4511,7 +4966,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -4526,7 +4981,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -4541,7 +4996,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -4574,7 +5029,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -4658,7 +5113,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -4672,16 +5127,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -4696,7 +5167,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -4711,7 +5182,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -4726,7 +5197,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -4759,7 +5230,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -4994,7 +5465,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 17, + query_index: 11, column_index: 1, rotation: Rotation( 1, @@ -5682,7 +6153,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -5749,16 +6220,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -5773,7 +6260,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -5788,7 +6275,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -5803,7 +6290,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -5873,16 +6360,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -5897,7 +6400,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -5912,7 +6415,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -5927,7 +6430,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -6089,16 +6592,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -6113,7 +6632,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -6128,7 +6647,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -6143,7 +6662,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -6242,16 +6761,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -6266,7 +6801,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -6281,7 +6816,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -6296,7 +6831,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -6427,16 +6962,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -6451,7 +7002,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -6466,7 +7017,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -6481,7 +7032,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -6497,7 +7048,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -6509,7 +7060,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -6525,7 +7076,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -6537,7 +7088,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -6555,16 +7106,32 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -6579,7 +7146,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -6594,7 +7161,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -6609,7 +7176,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -6626,7 +7193,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -6638,7 +7205,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -6674,7 +7241,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -6686,7 +7253,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 12, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -6722,8 +7289,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6734,8 +7301,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6745,12 +7312,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6760,12 +7327,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6775,12 +7342,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6832,8 +7399,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6844,8 +7411,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6855,12 +7422,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6870,12 +7437,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6885,12 +7452,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6930,8 +7497,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6942,8 +7509,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6953,12 +7520,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6968,12 +7535,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -6983,12 +7550,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7026,8 +7593,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7038,8 +7605,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7049,12 +7616,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7064,12 +7631,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7079,12 +7646,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7115,8 +7682,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7127,8 +7694,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7138,12 +7705,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7153,12 +7720,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7168,12 +7735,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -7235,21 +7802,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7263,8 +7846,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7278,8 +7861,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7293,8 +7876,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7305,7 +7888,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7331,7 +7914,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7359,21 +7942,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7387,8 +7986,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7402,8 +8001,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7417,8 +8016,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7430,7 +8029,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7465,7 +8064,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7512,21 +8111,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 21, - column_index: 21, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7540,8 +8155,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7555,8 +8170,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7570,8 +8185,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -7583,7 +8198,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7618,7 +8233,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7648,7 +8263,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 17, + query_index: 11, column_index: 1, rotation: Rotation( 1, @@ -7684,7 +8299,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7710,7 +8325,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7739,7 +8354,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7768,7 +8383,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7797,7 +8412,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7826,7 +8441,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7855,7 +8470,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7884,7 +8499,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7947,7 +8562,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -7984,7 +8599,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8006,7 +8621,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8044,7 +8659,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8066,7 +8681,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8088,7 +8703,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8127,7 +8742,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8149,7 +8764,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8171,7 +8786,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8193,7 +8808,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8233,7 +8848,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8255,7 +8870,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8277,7 +8892,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8299,7 +8914,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8321,7 +8936,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8362,7 +8977,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8384,7 +8999,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8406,7 +9021,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8428,7 +9043,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8450,7 +9065,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8472,7 +9087,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8514,7 +9129,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8536,7 +9151,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8558,7 +9173,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8580,7 +9195,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8602,7 +9217,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8624,7 +9239,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -8646,7 +9261,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -13272,14 +13887,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, ), }, Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -13299,14 +13914,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, ), }, Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -13325,7 +13940,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 11, column_index: 1, rotation: Rotation( 1, @@ -13366,7 +13981,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -13755,7 +14370,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, @@ -13842,7 +14457,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 11, column_index: 1, rotation: Rotation( 1, @@ -13854,7 +14469,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -13936,7 +14551,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -14022,7 +14637,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 17, + query_index: 11, column_index: 1, rotation: Rotation( 1, @@ -14031,7 +14646,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -14039,7 +14654,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 14, + query_index: 13, column_index: 3, rotation: Rotation( 1, @@ -14250,7 +14865,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -14336,7 +14951,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -14448,113 +15063,1235 @@ PinnedVerificationKey { ), ), ), - ), - Product( - Sum( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, - ), - }, + ), + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), - Sum( - Advice { - query_index: 16, - column_index: 5, + Negated( + Fixed { + query_index: 25, + column_index: 25, rotation: Rotation( - 1, + 0, ), }, - Negated( - Sum( - Sum( - Product( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), - Negated( - Advice { - query_index: 16, - column_index: 5, - rotation: Rotation( - 1, - ), - }, - ), - ), - Negated( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), ), ), ), - ), - Product( - Scaled( - Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( Fixed { - query_index: 13, - column_index: 13, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), }, - Sum( - Fixed { - query_index: 13, - column_index: 13, - rotation: Rotation( - 0, - ), - }, - Negated( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - ), - ), ), - 0x0000000000000000000000000000000000000000000000000000000000000002, ), - Advice { - query_index: 19, - column_index: 8, + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, rotation: Rotation( - 1, + 0, ), }, ), ), ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), ), ), Product( @@ -14587,7 +16324,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -14602,7 +16339,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -14647,45 +16384,34 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 2, + column_index: 2, rotation: Rotation( 0, ), }, Negated( Sum( - Product( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Sum( Advice { - query_index: 6, - column_index: 6, + query_index: 3, + column_index: 3, rotation: Rotation( 0, ), }, - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, ), + ), + Scaled( Advice { query_index: 5, column_index: 5, @@ -14693,6 +16419,7 @@ PinnedVerificationKey { 0, ), }, + 0x0000000000000000000000000000000000000000000000000000000000000020, ), ), ), @@ -14728,7 +16455,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -14743,7 +16470,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -14788,52 +16515,30 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 12, + column_index: 2, rotation: Rotation( - 0, - ), - }, - Negated( - Sum( - Product( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, ), + }, + Scaled( Advice { - query_index: 6, - column_index: 6, + query_index: 14, + column_index: 4, rotation: Rotation( - 0, + 1, ), }, + 0x0000000000000000000000000000000000000000000000000000000000000200, ), ), ), @@ -14869,7 +16574,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -14884,7 +16589,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -14927,28 +16632,47 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Sum( Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), ), - Negated( + Scaled( Advice { - query_index: 9, - column_index: 9, + query_index: 4, + column_index: 4, rotation: Rotation( 0, ), }, + 0x4000000000000000000000000000000000000000000000000000000000000000, ), ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), ), ), Product( @@ -14996,7 +16720,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -15041,30 +16765,52 @@ PinnedVerificationKey { ), Sum( Sum( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), ), - }, - Negated( Scaled( Advice { - query_index: 16, - column_index: 5, + query_index: 13, + column_index: 3, rotation: Rotation( 1, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000400, + 0x0020000000000000000000000000000000000000000000000000000000000000, ), ), + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), ), Negated( Advice { - query_index: 11, - column_index: 9, + query_index: 10, + column_index: 0, rotation: Rotation( 1, ), @@ -15117,7 +16863,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -15160,61 +16906,21 @@ PinnedVerificationKey { ), ), ), - Sum( - Sum( - Advice { - query_index: 16, - column_index: 5, - rotation: Rotation( - 1, - ), - }, - Scaled( - Sum( - Sum( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - Negated( - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), - ), - 0x0001000000000000000000000000000000000000000000000000000000000000, + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, ), - ), - Negated( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, ), ), Product( @@ -15262,7 +16968,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -15305,35 +17011,21 @@ PinnedVerificationKey { ), ), ), - Sum( - Sum( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - Scaled( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, ), - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, ), ), Product( @@ -15381,7 +17073,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -15425,33 +17117,33 @@ PinnedVerificationKey { ), ), Sum( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - Negated( + Sum( Sum( Advice { - query_index: 18, - column_index: 7, + query_index: 1, + column_index: 1, rotation: Rotation( - 1, + 0, ), }, - Scaled( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, ), ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -15551,20 +17243,13 @@ PinnedVerificationKey { 0, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, ), - ), + }, ), ), Product( @@ -15657,26 +17342,19 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 15, + query_index: 14, column_index: 4, rotation: Rotation( 1, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 15, - column_index: 4, - rotation: Rotation( - 1, - ), - }, + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, ), - ), + }, ), ), Product( @@ -15767,47 +17445,21 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 2, - column_index: 2, + query_index: 14, + column_index: 4, rotation: Rotation( - 0, + 1, ), }, - Negated( - Sum( - Sum( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000010, - ), - ), - Scaled( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, - ), + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, ), - ), + }, ), ), Product( @@ -15899,34 +17551,46 @@ PinnedVerificationKey { ), ), Sum( - Advice { - query_index: 13, - column_index: 2, - rotation: Rotation( - 1, - ), - }, - Negated( + Sum( Sum( - Advice { - query_index: 14, - column_index: 3, - rotation: Rotation( - 1, - ), - }, - Scaled( + Sum( Advice { - query_index: 15, - column_index: 4, + query_index: 5, + column_index: 5, rotation: Rotation( - 1, + 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000200, + Scaled( + Advice { + query_index: 11, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, ), ), ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), ), ), Product( @@ -16017,47 +17681,21 @@ PinnedVerificationKey { ), ), ), - Sum( - Sum( - Sum( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - 0x0400000000000000000000000000000000000000000000000000000000000000, - ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, ), - Scaled( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - 0x4000000000000000000000000000000000000000000000000000000000000000, + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, ), - ), - Negated( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), + }, ), ), Product( @@ -16120,7 +17758,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16148,59 +17786,28 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, Sum( - Sum( - Sum( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 17, - column_index: 1, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, - ), - ), - Scaled( - Advice { - query_index: 14, - column_index: 3, - rotation: Rotation( - 1, - ), - }, - 0x0020000000000000000000000000000000000000000000000000000000000000, - ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), - Scaled( + Negated( Advice { - query_index: 15, - column_index: 4, + query_index: 8, + column_index: 8, rotation: Rotation( - 1, + 0, ), }, - 0x4000000000000000000000000000000000000000000000000000000000000000, ), ), - Negated( - Advice { - query_index: 10, - column_index: 0, - rotation: Rotation( - 1, - ), - }, - ), ), ), Product( @@ -16263,7 +17870,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16293,19 +17900,26 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 4, - column_index: 4, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), - }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), ), ), Product( @@ -16368,7 +17982,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16396,14 +18010,7 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, + Sum( Advice { query_index: 6, column_index: 6, @@ -16411,6 +18018,51 @@ PinnedVerificationKey { 0, ), }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), ), ), Product( @@ -16473,7 +18125,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16488,7 +18140,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -16501,35 +18153,28 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, Sum( - Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Advice { - query_index: 1, - column_index: 1, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, - Constant( - 0x0000000000000000000000000000000400000000000000000000000000000000, - ), - ), - Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), ), ), - Negated( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - ), ), ), Product( @@ -16592,7 +18237,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16607,7 +18252,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -16621,13 +18266,6 @@ PinnedVerificationKey { ), ), Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, Advice { query_index: 8, column_index: 8, @@ -16635,6 +18273,20 @@ PinnedVerificationKey { 0, ), }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), ), ), Product( @@ -16697,7 +18349,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16712,7 +18364,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -16725,21 +18377,59 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 15, - column_index: 4, + query_index: 6, + column_index: 6, rotation: Rotation( - 1, + 0, ), }, - Advice { - query_index: 14, - column_index: 3, - rotation: Rotation( - 1, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), ), - }, + ), ), ), Product( @@ -16749,8 +18439,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16761,8 +18451,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16772,12 +18462,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16787,12 +18477,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16806,8 +18496,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16821,8 +18511,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16830,21 +18520,35 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 15, - column_index: 4, - rotation: Rotation( - 1, - ), - }, + Sum( Advice { - query_index: 22, + query_index: 6, column_index: 6, rotation: Rotation( - 1, + 0, ), }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), ), ), Product( @@ -16854,8 +18558,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16866,8 +18570,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16881,8 +18585,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16892,12 +18596,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16911,8 +18615,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16926,8 +18630,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16935,47 +18639,28 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, Sum( - Sum( - Sum( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 17, - column_index: 1, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, - ), - ), - Constant( - 0x0000000000000000000000000000100000000000000000000000000000000000, - ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, ), ), - Negated( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - ), ), ), Product( @@ -16985,8 +18670,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -16997,8 +18682,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17012,8 +18697,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17023,12 +18708,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17042,8 +18727,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17057,8 +18742,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17066,21 +18751,47 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 15, - column_index: 4, + query_index: 6, + column_index: 6, rotation: Rotation( - 1, + 0, ), }, - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), ), - }, + ), ), ), Product( @@ -17090,8 +18801,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17102,8 +18813,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17117,8 +18828,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17132,8 +18843,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17143,12 +18854,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17162,8 +18873,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17202,8 +18913,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17214,8 +18925,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17229,8 +18940,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17244,8 +18955,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17255,12 +18966,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17274,8 +18985,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17283,26 +18994,33 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 18, - column_index: 7, + query_index: 6, + column_index: 6, rotation: Rotation( - 1, + 0, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( + Negated( + Sum( Advice { - query_index: 18, + query_index: 7, column_index: 7, rotation: Rotation( - 1, + 0, ), }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), ), ), ), @@ -17314,8 +19032,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17326,8 +19044,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17341,8 +19059,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17356,8 +19074,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17367,12 +19085,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17386,8 +19104,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17397,40 +19115,28 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 6, + query_index: 22, column_index: 6, rotation: Rotation( - 0, + 1, ), }, Negated( Sum( Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000010, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), - ), + }, Scaled( Advice { - query_index: 18, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( - 1, + 0, ), }, 0x0000000000000000000000000000000000000000000000000000000000000020, @@ -17438,8 +19144,8 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, - column_index: 8, + query_index: 18, + column_index: 7, rotation: Rotation( 1, ), @@ -17457,8 +19163,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17469,8 +19175,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17484,8 +19190,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17499,8 +19205,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17514,8 +19220,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17525,12 +19231,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17569,8 +19275,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17581,8 +19287,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17596,8 +19302,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17611,8 +19317,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17626,8 +19332,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17637,12 +19343,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17681,8 +19387,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17693,8 +19399,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17708,8 +19414,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17723,8 +19429,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17738,8 +19444,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17749,12 +19455,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -17772,46 +19478,22 @@ PinnedVerificationKey { }, Negated( Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000004, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), - ), + }, Scaled( Advice { - query_index: 19, + query_index: 8, column_index: 8, rotation: Rotation( - 1, + 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000400, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), ), ), @@ -17847,7 +19529,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -17862,7 +19544,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -17877,7 +19559,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17892,7 +19574,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17906,33 +19588,45 @@ PinnedVerificationKey { ), ), Sum( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - Negated( + Sum( Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, Scaled( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000040, + 0x0400000000000000000000000000000000000000000000000000000000000000, ), ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -17981,7 +19675,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -17996,7 +19690,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18011,7 +19705,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18024,28 +19718,35 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, + Sum( Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( + Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), ), ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), ), ), Product( @@ -18093,7 +19794,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18108,7 +19809,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18123,7 +19824,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18136,47 +19837,21 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 6, - column_index: 6, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, - Negated( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), - ), + }, ), ), Product( @@ -18239,7 +19914,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18254,7 +19929,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18269,26 +19944,19 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 8, - column_index: 8, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, ), - ), + }, ), ), Product( @@ -18351,7 +20019,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18366,7 +20034,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18379,35 +20047,21 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 6, - column_index: 6, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, - Negated( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, - ), + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, ), - ), + }, ), ), Product( @@ -18416,21 +20070,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18440,12 +20110,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18455,12 +20125,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18470,12 +20140,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18485,12 +20155,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18502,21 +20172,21 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, Scaled( Advice { - query_index: 7, - column_index: 7, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, - 0x0400000000000000000000000000000000000000000000000000000000000000, + 0x0000000000000000000000000000000000000000000000000000000000000010, ), ), Scaled( @@ -18547,21 +20217,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18571,12 +20257,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18586,12 +20272,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18601,12 +20287,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18616,12 +20302,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18632,15 +20318,27 @@ PinnedVerificationKey { Sum( Sum( Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, ), - }, + ), Constant( - 0x0000000000000000000000000000000400000000000000000000000000000000, + 0x0000000000000000000000000000100000000000000000000000000000000000, ), ), Negated( @@ -18666,21 +20364,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18690,12 +20404,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18705,12 +20419,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18720,12 +20434,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18735,12 +20449,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18757,8 +20471,8 @@ PinnedVerificationKey { ), }, Advice { - query_index: 7, - column_index: 7, + query_index: 9, + column_index: 9, rotation: Rotation( 0, ), @@ -18771,21 +20485,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18795,12 +20525,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18810,12 +20540,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18825,12 +20555,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18840,12 +20570,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18862,10 +20592,10 @@ PinnedVerificationKey { ), }, Advice { - query_index: 9, + query_index: 16, column_index: 9, rotation: Rotation( - 0, + 1, ), }, ), @@ -18876,21 +20606,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18900,12 +20646,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18915,12 +20661,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18930,12 +20676,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18945,12 +20691,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -18958,21 +20704,47 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000100, + ), ), - }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000400000000000000, ), - }, + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), ), ), Product( @@ -18981,21 +20753,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19005,12 +20793,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19020,12 +20808,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19035,12 +20823,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19050,12 +20838,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19112,21 +20900,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19136,12 +20940,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19151,12 +20955,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19166,12 +20970,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19181,12 +20985,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19243,126 +21047,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( + Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( - 0, - ), - }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19372,12 +21087,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( - Fixed { - query_index: 26, - column_index: 26, + Fixed { + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19387,12 +21102,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19402,12 +21117,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19417,12 +21132,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -19439,10 +21154,10 @@ PinnedVerificationKey { ), }, Advice { - query_index: 11, + query_index: 9, column_index: 9, rotation: Rotation( - 1, + 0, ), }, ), @@ -19463,7 +21178,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -19478,7 +21193,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19551,47 +21266,21 @@ PinnedVerificationKey { ), ), ), - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000100, - ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, ), - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000400000000000000, + }, + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, ), - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), + }, ), ), Product( @@ -19625,7 +21314,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19640,7 +21329,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19701,22 +21390,34 @@ PinnedVerificationKey { Sum( Sum( Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, ), - }, + ), Scaled( Advice { - query_index: 8, - column_index: 8, + query_index: 22, + column_index: 6, rotation: Rotation( - 0, + 1, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000010, + 0x0200000000000000000000000000000000000000000000000000000000000000, ), ), Scaled( @@ -19772,7 +21473,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19787,7 +21488,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19864,11 +21565,11 @@ PinnedVerificationKey { 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000010, + 0x0000000000000000000000000000000000000000000000000000000000000200, ), ), Constant( - 0x0000000000000000000000000000100000000000000000000000000000000000, + 0x0000000000000000000000000000000400000000000000000000000000000000, ), ), Negated( @@ -19919,7 +21620,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -19934,7 +21635,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20001,10 +21702,10 @@ PinnedVerificationKey { ), }, Advice { - query_index: 9, - column_index: 9, + query_index: 22, + column_index: 6, rotation: Rotation( - 0, + 1, ), }, ), @@ -20040,7 +21741,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20055,7 +21756,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20122,10 +21823,10 @@ PinnedVerificationKey { ), }, Advice { - query_index: 11, + query_index: 9, column_index: 9, rotation: Rotation( - 1, + 0, ), }, ), @@ -20176,7 +21877,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20234,59 +21935,21 @@ PinnedVerificationKey { ), ), ), - Sum( - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000200, - ), - ), - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0200000000000000000000000000000000000000000000000000000000000000, - ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x4000000000000000000000000000000000000000000000000000000000000000, + }, + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, ), - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), + }, ), ), Product( @@ -20335,7 +21998,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20350,7 +22013,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -20393,47 +22056,28 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000200, - ), - ), - Constant( - 0x0000000000000000000000000000000400000000000000000000000000000000, - ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, ), ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), ), ), Product( @@ -20482,7 +22126,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20497,7 +22141,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -20540,21 +22184,47 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 18, - column_index: 7, + query_index: 15, + column_index: 5, rotation: Rotation( 1, ), }, - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, + Negated( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), ), - }, + ), ), ), Product( @@ -20603,7 +22273,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20618,7 +22288,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -20661,21 +22331,47 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, + Sum( Advice { - query_index: 9, - column_index: 9, + query_index: 5, + column_index: 5, rotation: Rotation( 0, ), }, + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), ), ), Product( @@ -20724,7 +22420,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20739,7 +22435,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -20782,21 +22478,35 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, + Sum( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), ), - }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), ), - }, + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), ), ), Product( @@ -20860,7 +22570,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -20911,20 +22621,13 @@ PinnedVerificationKey { 0, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, ), - ), + }, ), ), Product( @@ -20988,7 +22691,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21031,47 +22734,21 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 16, - column_index: 5, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, - Negated( - Sum( - Sum( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, ), - ), + }, ), ), Product( @@ -21135,7 +22812,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21172,54 +22849,28 @@ PinnedVerificationKey { query_index: 27, column_index: 27, rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - Negated( - Sum( - Sum( - Advice { - query_index: 16, - column_index: 5, - rotation: Rotation( - 1, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0400000000000000000000000000000000000000000000000000000000000000, + 0, ), - ), - Scaled( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - 0x4000000000000000000000000000000000000000000000000000000000000000, - ), + }, ), ), ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), ), Product( Product( @@ -21282,7 +22933,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21297,7 +22948,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21325,34 +22976,27 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, Sum( - Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Advice { - query_index: 16, - column_index: 5, + query_index: 8, + column_index: 8, rotation: Rotation( - 1, + 0, ), }, - Constant( - 0x0000000000000000000000000000000400000000000000000000000000000000, - ), ), - Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), - ), - ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, ), ), ), @@ -21417,7 +23061,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21432,7 +23076,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21462,19 +23106,26 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 9, - column_index: 9, + query_index: 18, + column_index: 7, rotation: Rotation( - 0, + 1, ), }, - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), - }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), ), ), Product( @@ -21538,7 +23189,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21553,7 +23204,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21581,21 +23232,59 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 9, - column_index: 9, + query_index: 6, + column_index: 6, rotation: Rotation( 0, ), }, - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), ), - }, + ), ), ), Product( @@ -21659,7 +23348,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21674,7 +23363,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21689,7 +23378,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -21704,19 +23393,26 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 9, - column_index: 9, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), - }, + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), ), ), Product( @@ -21795,7 +23491,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21810,7 +23506,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -21923,56 +23619,87 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { query_index: 27, column_index: 27, rotation: Rotation( - 0, + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, ), }, + 0x0000000000000000000000000000000000000000000000000000000000000400, ), ), ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, - ), - Negated( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - ), - ), ), ), Product( @@ -21983,20 +23710,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22006,12 +23733,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22021,12 +23748,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22036,12 +23763,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22055,8 +23782,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22070,8 +23797,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22089,43 +23816,19 @@ PinnedVerificationKey { }, Negated( Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000010, - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000020, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), - ), + }, Scaled( Advice { - query_index: 19, + query_index: 8, column_index: 8, rotation: Rotation( - 1, + 0, ), }, 0x0000000000000000000000000000000000000000000000000000000000000040, @@ -22142,8 +23845,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22154,8 +23857,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22165,12 +23868,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22180,12 +23883,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22195,12 +23898,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22210,12 +23913,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22229,8 +23932,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22270,8 +23973,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22282,8 +23985,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22293,12 +23996,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22308,12 +24011,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22323,12 +24026,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22338,12 +24041,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22357,8 +24060,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22366,26 +24069,45 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 8, - column_index: 8, + query_index: 6, + column_index: 6, rotation: Rotation( 0, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), - }, + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), ), ), ), @@ -22398,8 +24120,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22410,8 +24132,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22425,8 +24147,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22436,12 +24158,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22451,12 +24173,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22466,12 +24188,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22485,8 +24207,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22494,57 +24216,26 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 6, - column_index: 6, + query_index: 8, + column_index: 8, rotation: Rotation( 0, ), }, - Negated( - Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000004, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, ), - ), - Scaled( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), + }, ), ), ), @@ -22557,8 +24248,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22569,8 +24260,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22584,8 +24275,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22595,12 +24286,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22610,12 +24301,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22625,12 +24316,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22640,12 +24331,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -22678,7 +24369,7 @@ PinnedVerificationKey { 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000040, + 0x0000000000000000000000000000000000000000000000000000000000000020, ), ), ), @@ -22700,7 +24391,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -22715,7 +24406,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -22788,26 +24479,45 @@ PinnedVerificationKey { ), ), ), - Product( + Sum( Advice { - query_index: 7, - column_index: 7, + query_index: 22, + column_index: 6, rotation: Rotation( - 0, + 1, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, ), - }, + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), ), ), ), @@ -22828,7 +24538,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -22843,7 +24553,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -22858,7 +24568,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -22916,45 +24626,26 @@ PinnedVerificationKey { ), ), ), - Sum( + Product( Advice { - query_index: 6, - column_index: 6, + query_index: 7, + column_index: 7, rotation: Rotation( 0, ), }, - Negated( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 22, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), - ), - Scaled( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), + }, ), ), ), @@ -22990,7 +24681,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -23005,7 +24696,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23118,7 +24809,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -23133,7 +24824,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23216,7 +24907,7 @@ PinnedVerificationKey { 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000020, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), ), ), @@ -23268,7 +24959,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23283,7 +24974,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -23415,7 +25106,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23430,7 +25121,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -23550,7 +25241,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23565,7 +25256,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -23671,7 +25362,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23686,7 +25377,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -23792,7 +25483,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -23807,7 +25498,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -23859,7 +25550,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -23928,7 +25619,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -23943,7 +25634,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -24075,7 +25766,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24090,7 +25781,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -24222,7 +25913,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24237,7 +25928,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -24343,7 +26034,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24358,7 +26049,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -24395,7 +26086,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -24479,7 +26170,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -24494,7 +26185,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -24554,69 +26245,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24626,12 +26269,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24641,12 +26284,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24701,69 +26344,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24773,12 +26368,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24788,12 +26383,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24803,114 +26398,66 @@ PinnedVerificationKey { ), Sum( Sum( - Sum( - Sum( - Advice { - query_index: 7, - column_index: 7, - rotation: Rotation( - 0, - ), - }, - Scaled( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000010, - ), - ), - Constant( - 0x0000000000000000000000000000100000000000000000000000000000000000, - ), - ), - Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), - ), - ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - Product( - Product( - Product( - Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, ), ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24920,12 +26467,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24935,12 +26482,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -24969,69 +26516,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25041,12 +26540,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25056,12 +26555,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25078,7 +26577,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -25090,69 +26589,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25162,12 +26613,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25177,12 +26628,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25249,69 +26700,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25321,12 +26724,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25336,12 +26739,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25396,69 +26799,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25468,12 +26823,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25483,12 +26838,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25517,69 +26872,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25589,12 +26896,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25604,12 +26911,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25638,69 +26945,94 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 16, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25710,12 +27042,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25725,12 +27057,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -25738,31 +27070,6 @@ PinnedVerificationKey { ), ), ), - Product( - Advice { - query_index: 18, - column_index: 7, - rotation: Rotation( - 1, - ), - }, - Advice { - query_index: 11, - column_index: 9, - rotation: Rotation( - 1, - ), - }, - ), - ), - Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, - ), - }, Product( Advice { query_index: 9, @@ -25788,16 +27095,64 @@ PinnedVerificationKey { ), ), Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -25839,13 +27194,61 @@ PinnedVerificationKey { ), ), Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Advice { query_index: 5, @@ -25858,7 +27261,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -25890,18 +27293,66 @@ PinnedVerificationKey { ), ), Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Sum( Sum( Advice { - query_index: 16, + query_index: 15, column_index: 5, rotation: Rotation( 1, @@ -25912,30 +27363,78 @@ PinnedVerificationKey { ), ), Negated( - Constant( - 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, - ), + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, ), ), - Negated( - Advice { - query_index: 19, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), ), - ), - Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, - ), - }, Product( Advice { query_index: 9, @@ -25954,13 +27453,61 @@ PinnedVerificationKey { ), ), Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Product( Advice { query_index: 9, @@ -25979,13 +27526,61 @@ PinnedVerificationKey { ), ), Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Product( Advice { query_index: 9, @@ -25995,7 +27590,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -26003,6 +27598,115 @@ PinnedVerificationKey { }, ), ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), ], advice_queries: [ ( @@ -26106,7 +27810,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 1, column_type: Advice, }, Rotation( @@ -26115,16 +27819,16 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 2, column_type: Advice, }, Rotation( - -1, + 1, ), ), ( Column { - index: 2, + index: 3, column_type: Advice, }, Rotation( @@ -26133,7 +27837,7 @@ PinnedVerificationKey { ), ( Column { - index: 3, + index: 4, column_type: Advice, }, Rotation( @@ -26142,7 +27846,7 @@ PinnedVerificationKey { ), ( Column { - index: 4, + index: 5, column_type: Advice, }, Rotation( @@ -26151,7 +27855,7 @@ PinnedVerificationKey { ), ( Column { - index: 5, + index: 9, column_type: Advice, }, Rotation( @@ -26160,11 +27864,11 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 9, column_type: Advice, }, Rotation( - 1, + -1, ), ), ( @@ -26609,7 +28313,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 11, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -26712,7 +28416,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 13, + query_index: 12, column_index: 2, rotation: Rotation( 1, @@ -27180,51 +28884,51 @@ PinnedVerificationKey { minimum_degree: None, }, fixed_commitments: [ - (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), - (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), - (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), - (0x212ebe88f06142f838a0c5c4496fa768ae3ca10f1ce9022c562b26bfbdc498c3, 0x2b6528f6317e63892bed284c67f112218631e191be7d5fdc5cdf7b9e92c72e05), - (0x034445b7457e04150c75a6c82e6f83ce2e1adf0e54aae2cfef0531b24dde111f, 0x30a7f9ce9bd574162a4729f71d8c7f0c61a4b7de6aa0181eefad3693aeb09c10), - (0x2a119980555858bc332f02295311e188f6125be71b5e591fff068a5024571aee, 0x23803ce939432804d484b29078c9c161015408e5e383a8cfc8c13a30502c9400), - (0x085620965e456f2f2b98a365768c7be2e43577bd0ef92a50cc278d521e983e9f, 0x3f1f003651d27a02d609eb61fbba5e74bb61c63b5afcce2c683948c5caa22791), - (0x3dc695372b0d52f554c7ab1cee168937f45f3abdd2e8fdf65f3b523ec85a499a, 0x33ef73e550024b2285b082816eb8818e80255973d9560fd437387cdb870190f1), - (0x1028b99218dd2642e60b90b28ae9cecd4be814de17a429314530f9a8695ce1c8, 0x2592dc76f783462d5b3bed02626ef2514deb59b7a6a8438ff64fdf6aafa00d4f), - (0x10fea717c33f17c73458742a1431679d61a436da080918e030b1760627a9538b, 0x0faf9983733b318f75d91c0c1131cfe7c67ef5474657d36c5ecd566b9629b6cf), - (0x3c242ccdb145d93f2cf312fbaab513b66b4cacd30de01fe193984aec912dd1a0, 0x1fa195c07847db8e31bdf7993ea787c9656a9d86babdeeddb76817d3c546348c), - (0x3229e787cb7ce31299dedd67d2631c480399a333098f84e7577132aac163ec8d, 0x3822eb1cc8eb19179373ea6b66b25b26ac8c915f0c9382800dd45a5a408fd1fc), - (0x10f84d5a9fad7c64be8a3529d1dd98c0961df4bb677b6a60714ddb053792998e, 0x0f032b93492b60aed3339d5646e15d2a9a46557cb01621b8d3d1392207ed0021), - (0x1d5193db32232d750432a8ec23f74307ad8194a0a4ad273c9b761b4e0f365d0b, 0x0b73549978b1c24dcbb39570d9fab795337f6030f2fffb9452b5edba0dcd2906), - (0x12967b9d3412c47744d16acede02d8214db2def9bfa643cc3da724f3f4edecaf, 0x3744e1519dcf0ae6bdc813ef1a123fd7978c073232164050a9a24fcd57d9a0a2), - (0x02602bfa02be45cec73e24099a3ff88e66386fc8a55f60af328afe5a68007233, 0x3db6b250fdd9abcc16f17275cc83ac66c9a2d91954dce867f23497a3ad85a85e), - (0x274c6a300449842b07918941f243beac24a66bd9870bf0b1c59b0b6056200a73, 0x1a19946639473486c5aebb6f2c7f0ed9bfa6a072a37857b9cbd801174b6a152a), - (0x2280ada329e3a43f320cdd86e0cfbea20620a02c772fccb8f34091832b9c4e1c, 0x0f47924c100e3c314835e8e1112a21a9aa54122548b5a2fbf1ddca681f64d148), - (0x2cde628fe6b43f6d0a2406f020530790a1c03642bec15a27e4883830f1906f75, 0x269f42895d8fb9cdc21fe307bf0cf994bc8d4f57f5c9757d7e7f491f67218f41), - (0x385b8c0d2d99558538cb3a9f9032a5aa40e73909f80c72d4b56dabbd35da1edf, 0x3926c421e68c459e921bc92c452b6d471810358c9c9941d0e15255f07e81f52a), - (0x365be6624d5ddbced07b7759377bd70f42ef5c0727849dcf4295e2be882a1229, 0x2379fbecf58b756b83626b73e0a4fe3043b6f6f7d3cca1c35ae298993be00b55), - (0x3992f02cfe9f649c235efb0b12057bf4a6a23de1e9186ecd4755cde6af9f18a1, 0x3defc298ff6d6e34e250f303089cc3ff36f9960f3c37dbff959ec4d722c21354), - (0x0b89c282c8f2d54e66c7a11e6b4338a2f06a7c9430f7d3376328f12fa001cac5, 0x098b5c8ee6548183ccb4e60cdfee10b509db34ed136daf3530a426e8f200e89d), - (0x2f7f85b86b6adcf714d0df7878f4604d33fd319f39bd00fd5c34378247a155b5, 0x3a2f025447b83b65d148e99c93fe8bb991a81ef6d2f827f010680467361c47fc), - (0x1c2d777a98c9dbcf31b45d5a7584b154daed974f3263b6a93831d53bf593e6c2, 0x234766a4b905ed9627f6a200a7b0b50315203613a5b211494a94cf21fb4c386b), - (0x2ebbe4228a40b24bc3f05a07484c2d470ca997d5fd030a26c3c475fd24c5f71b, 0x00f27b013a7a80f1221a9fcf44332b3842ac2af0af4a7108e966f765d8ccebab), - (0x1484b5ee3bd870af246676953341b0825bac76cbe5a753c014bbd04c499c3946, 0x09860840096085811328952d906cdf7bdb748db7e08157d96b3252f909cbc6a9), - (0x13c4224160178c41c828d952f78a8a0d58321a7894cee8f2884c5d1d9e3246ac, 0x3699ad2eb29f2cd4825c0e7cbde86eb19889a00f4afd8cbe40d2eed7c7efd565), - (0x3e6b0d18402a8533aa2c9a681ef0c9c3636154feb1a95b6a50c522833f6e2cb1, 0x20336e540af50c99ef3208ff5dc2f4f0deb2c8beb8f1b3da046eebb05e39deee), - (0x16e89e0cf09f1d68ce3f16728839b4973604d9cad2a6ae3114ce75ce5cb7edeb, 0x1db108cbdb6e1af19ca087d3649ac673d59ced15e6780957d26a83aa8865f116), + (0x3a83a8e762ebade712aa5cf3c41c730a79369475085bf1155579f7f7682408e2, 0x25b00d3ee1da9a6bbd36b35ba461da45abd931c767b863ec4a604f8ce094e4eb), + (0x1caeb4d7ebb44a717f83ee5afd35446a5e2124f6a4075342ba4eff589523fb57, 0x3a8c431a13632a5b5f035eb4b804d37f2591e84d05d765ba3f70a3d61b907ebb), + (0x107d95a6361fc98df9042f32451faa4fd48c1381653be7847d97cf997a55a4ad, 0x31ebf6a2e352108bb180c3278e72d88bb5bab723d3b38aa47c144fc37fb8a962), + (0x090c0e45d81111bd494b9ce7c16fb0e0bbc953911c1701e42a5de5f36389afbc, 0x23ab5bd08aed9eee6c7e78f15652ef51633694b92b1632f9e51ccd31b286066b), + (0x10b2c2af49d17b962211ad5bbb682532940839026d0d242b254b907a50d136ba, 0x1a59a77fd094078d6075a3bdb691bb0b8808a97d2e06092cb6afa767fcdf4cbb), + (0x2b98cb6188d5afb90a5bc94d9f6c23086164284107dfb04a4504b61833a5f9dc, 0x205725733d9c55704a574a244fd4c0038e001261c9f978a2ddbe2ffd33bc026c), + (0x31711515cf172b14651f22ff63fa42011b6de4daa3b71e28a0ce57ae65be3e18, 0x1da5bab80180265242efdfe09c64caf1e987a16384d9eb3bf80343cdd0154dd4), + (0x33548b13c1aeadbbebeced0618b28498d0f95cc26a0413dc6c6b12d305bc9de7, 0x04769755bd24a459f3b86018e78e1f4d14796ba33aa7a08684529e47860f215c), + (0x03e2f4d89dd13482c272721bcffc31fad53b5deb7f402cc2522d2c10cda6bbbd, 0x3b5af207073d98eb42123895069f5a1b726a476ad1ec2945ea63395c284447ec), + (0x3518a704cfc4622b72b4ff3cbc7382fe91fcd77d861e4ef7f2a9830150066746, 0x12639d3e4aa8d1d82cd591fa2e58b1679b677e5e99711a733746dcd47b36a987), + (0x035cc4fa63ce607b7dfdfc08beb5380e3f837090ec4b812b1772ad03ca97156c, 0x14e9d0f3ffedac7d9857fc47f68ccb943f602577a0037e0e3c972b9996f96d71), + (0x00f8d7b4c395ef38584c0182319952b12a25f9d51b75293d4c62f7a5f4405a72, 0x37fa03464d244314d298ecfe5ab9fd9d99d63f38e6c6d54b97efa04b3acc6fb4), + (0x3c0f3f0d7b2306490dac7d578d4846c63adcc76988ce322d8691c3b8b5b0f623, 0x12d81ca672a1c18f6e0d9b7eb8fbabdbe450fae6667cf349c1a0e63ca9a0824e), + (0x27d13b33003ffddcd36efb731fe94db93d181bd994e0c057e945402bc8501789, 0x0e1dde94ea3b35e0d0a66350163ba2ff9dd5070500912b7d076747816965ffd2), + (0x3049e9c8a3e6c7fe628660121f04915e03546b7a2dcb8a3e59fa99546e4f7f86, 0x2dcebc740917584f788b776f4cf1e3cd96b4a29e9df7224fd8e5f428d4112546), + (0x245ebb4ccefa7c4e2d5a9d7b1746b8277abc25f74cd11b2dbb752d49612f248e, 0x145f605111205a7c3e4620ac035b3cccb6375f8d3c3469b7900e427607c401c9), + (0x1751912a19fa0009ece61b686342d6b4385415e942159e8db3f174ad24d612b9, 0x0f31114ef566211d46914d0bc2d1a27a0e34eeda04dab53a0af7a37024f057a1), + (0x091c6c4854fa5d9ed8a966f2a1c4946b41f6872de6c19fa8b521a0a8eb2bd899, 0x29100b4e15344d750fae4a81c82faca1e8e0573336b1f54b394946e95e7baad0), + (0x210297af23386f0691220f2a0e3504336a815cdba5167277a13f0a7b992b8e43, 0x2a184bc5b1981e303cbc0a18f4a01b4dc49695b9a319bd7e713d55e46d1235ae), + (0x05cd80ee69394fb4efe616ef91593c3b8e6e142f2269524f01476ab78a67c9f6, 0x23a7840c00619fe55078a6bffb8a061913f929a7669861ebe99859a48136f12d), + (0x34c8b83a2cc924f1b0237978c8f911e6a54375c509ba46456a011fbb74c8698c, 0x260cc681c222535c0030f702172ee8855b681c16d706b1b9a786165e06705de6), + (0x3dcb136a22551e524212c0325331a9dae5ad6ff356175e6b82a54039475be1ef, 0x3bbbd0d20ea0ebb0f36d740910947d1934bcb93ba16325ea42f124ec0cde7a81), + (0x3bb657ca32617e6242b6c6a0b166a1db205024d0441d091b8d45fb478cd4782c, 0x3189ce1b97103345fc0eafd287eed80ab186151171f22af2c9befc71a0957529), + (0x25578b0a6d546cf38dc84329fad41e59690a2bd94a0db5fddb42e0db8c267827, 0x03448e4552625dda62a96318bcafcc305deafd6a028f8379d8c8d9ffa0f86e64), + (0x30d1828d7463255ad75b39ee4c718de05a762c45c5d717d059496fe05d1575b4, 0x0a8eb70a9b252ee9ee57b29e4dab191cbb29665821830b2ab60fdd5d3414de45), + (0x2b18121165b0ebf2ab46c207d973f44f135c24efecc1cc48d47d38769969aa2e, 0x1a829739cf7eb6422f581f64632c65073aa49819e62e80489b6aae61e6edd6a0), + (0x23ae57d2095a4324262aa76f345fe7bc21d8ad7b3203a8167bf8315e64a11d25, 0x1a871041d826e0e3bd7520e03dca1f56211065b049b2bebc59d8e01b4addb1d3), + (0x029871a070ccef21bb6d1d5d7e51597b0dd8f38208f1b304bd372b48aaea0a3f, 0x3205e4b0ab706647e6f45cf2b2091afd69636a8f61426504983bf44d47d676ec), + (0x0bd7a66e0b566e724536f77fe659014db82286485859c1ae9d95f42cb898f763, 0x358962c131dc5dd41db0fe6a8fe5315b75dd9204682d1de05470184c8a331a8a), + (0x336245b9b67f39852776a1f6ba5072ad3776f38d9b0659568d3afb2e6d3750d3, 0x1ae68f5f91a6d28b62a9fb9240ee53f86e0ac434286429024c253bf85325033e), ], permutation: VerifyingKey { commitments: [ - (0x12dbf09e55d044102f1ae361e8d266b69e1718e1d624b96e77b3cfa1feceb732, 0x31caaac60ce9718af01c87d262fec2c754c77550d8bb35e63f8b07fa9c89fc66), - (0x22da488fb2f178bb8139f14a2aec59c91799533c774af776e94c104f7687c421, 0x2af740c09b699a113bfc6e74b029298d54af6bfb0b92da9c1b0bded28625f450), - (0x2b48b45f4a5a2b4d3605d823a561d7cf0e0ba56c0cbc5d40b58b1b8ea7e36ae5, 0x1035a22259f1b163d3aeb91785cbda566f1501d75011335fa62a0f904c1cb318), - (0x16940bc043dab8afc2a1459edac40382bd790dee8c14db086c4619dc53ebb2e9, 0x1ad505a146f27451d13f90c75b8651eb10a3f67cc6609ea75ca71eee7c1c157d), - (0x3a3ed02c9cbf7b5d099b4c7e3f12f46f3fd898e07f8e7a4f707b1df7f5de3ac3, 0x1d90e34b6d292a48989e3fd47d0eee2ecdffe086ce57e43e1c98dd63ced3fcda), - (0x1f622082868867262854bb7e8cf99d8414bbb244abffde123330b8aed84bd92d, 0x244be4573a4986eaff1e2a6beaa0aecdcdb361540f0b8cf4db289242c6eaefc2), - (0x2d8cbc3dc5fada2ddb980b66a31f57cb02af14982712cb1a12c0d11945811a0e, 0x330cc47c866342bdcd769f9c4ac214a022894aaa4f706182ac5b9e7abac7b2ee), - (0x0367c84844db2532b1fe3833504c46fb366ed8a6b91053a64bb820b5407ba0f1, 0x17fab750fb792623f23d091a07bbc30ce0a669d7270ea36ca38b934bb3caa135), - (0x088b09cd2e59ab2d95dd62077692f366604d9dbda58f7915e5b7c4874cb7ac17, 0x3ce41c4b67191c663c5c5e2413b5359bf55f2d59b65f91b086a2aadfaf4816a2), - (0x230701deaa69a778874d4fa8682366c61954107150807386f5d335157eb93395, 0x000d66512afd16ccc26d6d086a116dfd6f246ec5e4817a71832244218ac6fd9b), - (0x3b7b47bca87fc15cd5565b546ce7624078f7cbf71d4ef78360740cecc16a6415, 0x20ab204faaa0df261b922ee76d97057b4bfa1fb7f2e50015b2aae29d4dbb820c), - (0x07ff65506877a9a21905ddfa323607a02794f495d6448484fda71859af8d51db, 0x0fb1605d3e8d4a77121e70e1339b819825cf04c10edf28b4bf5238a836608c74), + (0x1dcbd758066eec5488296ece96ea7fd0eb814479bf5cf04418c109e0c6e3b65f, 0x16f9507e843611c3891c03a5acbb47cb2d8c591575911c12815cb1e031cab8af), + (0x2388cbed968c22e32b6bd4a1b2395ec1d940135e0136e1df5600f2d759748a64, 0x251608eff7019c64b80df6b45d2a561208e59247da23c0c41f29268ebebcc989), + (0x25d09b3bd46f027633197dae5164cb90c8cf4358598bcd747791b9d95370b1e3, 0x0e94d8861f8b7a6c4f7edf780b131fe2b89757c46cf0b2da24a3592c8824c692), + (0x019398cb329abefa110b3c4d12af9685272f7a611599f5e9c54cd644f0882a51, 0x2a5d9081f77f6e389a355fcc45425a3d4d6de28cb34b26bf54ba66fbd34b8f86), + (0x04596f22bde8d6e02fa2426ea314dd115fd757bc58a60e7349669dd090e5d756, 0x09ead6fcd376d620681f3b14c89337d25ec795cde09fab7da0376bf07bbd402b), + (0x0f7bd41cab58414151f520efc629836da3052d911e95ec09301e25a36e10e9fb, 0x008998b3c16c01c66bd471eca4c16d87adfa0856886b11bff2d04e281e45f234), + (0x122e03591cfc43c812fbfcd45a3062d845b6beecd5e9591fc78cd07734fd5eab, 0x3bb6a66ca91558265efcd59482b2f016ccd34e6b916410e5a198e142ff9257c1), + (0x1656a1c579376b8b92f00c907dc544843231a13b0e0b58be652c9ef44e0d8957, 0x0608dca2d8f9ad5ce0d7b0545a3d148371e4e3993249db87ae4e8a95034e330a), + (0x1d8dd2ef5d363793653c385ef62f382f48d21234caf6dce0806f9295d0f63f47, 0x3aa78867d1d8cc02a50e0ed804a07b0572ae191f0b1c495072fd11f6d2aea2ef), + (0x2cb9fe3cfca45f22aab479b9c54d7731bd165a236bc2d0bfea9af9bdaf8969eb, 0x2acc3469ecb12ba57992881873adeda3f8380262977b53175a99f4009d082405), + (0x1f56f0d66eb5c9f86a680efda44e992322f4934c10b83895ffe60aca9305c5f3, 0x20cb980461e94d5e6a5b5beaf4361b77680f5cdd4f3c4398473aeaca212ada1f), + (0x3f821ad8e7fe3fb349c6e9b316bba2505648a219f337f9e5f1265572b606fb4f, 0x3f4472a3137db52586f3adad1584ee57dc0946595c62f6a39420183814cb3a42), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 027e09fba4a2bfba0be636799cd3f6c55bbd7d1a..a6199f11455998fbbe3d3b83f1149313c158b811 100644 GIT binary patch literal 5250 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 Ib7Nu#GPHCAVgLXD literal 5186 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 [bool; K] { #[derive(Clone, Debug, Eq, PartialEq)] pub enum OrchardHashDomains { NoteCommit, + NoteZsaCommit, CommitIvk, MerkleCrh, } @@ -96,6 +109,11 @@ impl HashDomains for OrchardHashDomains { pallas::Base::from_repr(Q_NOTE_COMMITMENT_M_GENERATOR.1).unwrap(), ) .unwrap(), + OrchardHashDomains::NoteZsaCommit => pallas::Affine::from_xy( + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.0).unwrap(), + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.1).unwrap(), + ) + .unwrap(), OrchardHashDomains::MerkleCrh => pallas::Affine::from_xy( pallas::Base::from_repr(Q_MERKLE_CRH.0).unwrap(), pallas::Base::from_repr(Q_MERKLE_CRH.1).unwrap(), @@ -108,6 +126,7 @@ impl HashDomains for OrchardHashDomains { #[derive(Clone, Debug, Eq, PartialEq)] pub enum OrchardCommitDomains { NoteCommit, + NoteZsaCommit, CommitIvk, } @@ -115,6 +134,8 @@ impl CommitDomains for Or fn r(&self) -> OrchardFixedBasesFull { match self { Self::NoteCommit => OrchardFixedBasesFull::NoteCommitR, + // For ZSA note commitment, we use the same `R` than for ZEC note commitment. + Self::NoteZsaCommit => OrchardFixedBasesFull::NoteCommitR, Self::CommitIvk => OrchardFixedBasesFull::CommitIvkR, } } @@ -122,6 +143,7 @@ impl CommitDomains for Or fn hash_domain(&self) -> OrchardHashDomains { match self { Self::NoteCommit => OrchardHashDomains::NoteCommit, + Self::NoteZsaCommit => OrchardHashDomains::NoteZsaCommit, Self::CommitIvk => OrchardHashDomains::CommitIvk, } } @@ -131,7 +153,10 @@ impl CommitDomains for Or mod tests { use super::*; use crate::constants::{ - fixed_bases::{COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION}, + fixed_bases::{ + COMMIT_IVK_PERSONALIZATION, NOTE_COMMITMENT_PERSONALIZATION, + NOTE_ZSA_COMMITMENT_PERSONALIZATION, + }, sinsemilla::MERKLE_CRH_PERSONALIZATION, }; use group::{ff::PrimeField, Curve}; @@ -192,6 +217,22 @@ mod tests { ); } + #[test] + fn q_note_zsa_commitment_m() { + let domain = CommitDomain::new(NOTE_ZSA_COMMITMENT_PERSONALIZATION); + let point = domain.Q(); + let coords = point.to_affine().coordinates().unwrap(); + + assert_eq!( + *coords.x(), + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.0).unwrap() + ); + assert_eq!( + *coords.y(), + pallas::Base::from_repr(Q_NOTE_ZSA_COMMITMENT_M_GENERATOR.1).unwrap() + ); + } + #[test] fn q_commit_ivk_m() { let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 1079e4a6c..63da3a5f8 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -2,6 +2,7 @@ use blake2b_simd::{Hash as Blake2bHash, Params}; use group::GroupEncoding; use halo2_proofs::arithmetic::CurveExt; use pasta_curves::pallas; +use rand::RngCore; use std::hash::{Hash, Hasher}; use subtle::{Choice, ConstantTimeEq, CtOption}; @@ -9,7 +10,7 @@ use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::constants::fixed_bases::{ NATIVE_ASSET_BASE_V_BYTES, VALUE_COMMITMENT_PERSONALIZATION, ZSA_ASSET_BASE_PERSONALIZATION, }; -use crate::keys::IssuanceValidatingKey; +use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; /// Note type identifier. #[derive(Clone, Copy, Debug, Eq)] @@ -86,6 +87,17 @@ impl AssetBase { pub fn is_native(&self) -> Choice { self.0.ct_eq(&Self::native().0) } + + /// Generates a ZSA random asset. + /// + /// This is only used in tests. + pub(crate) fn random(rng: &mut impl RngCore) -> Self { + let sk = SpendingKey::random(rng); + let isk = IssuanceAuthorizingKey::from(&sk); + let ik = IssuanceValidatingKey::from(&isk); + let asset_descr = "zsa_asset"; + AssetBase::derive(&ik, asset_descr) + } } impl Hash for AssetBase { diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 18024afe8..995b13693 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -17,7 +17,7 @@ use crate::{ }; #[derive(Clone, Debug)] -pub(crate) struct NoteCommitTrapdoor(pub(super) pallas::Scalar); +pub(crate) struct NoteCommitTrapdoor(pub(crate) pallas::Scalar); impl NoteCommitTrapdoor { pub(crate) fn inner(&self) -> pallas::Scalar { @@ -41,7 +41,7 @@ impl NoteCommitment { /// Defined in [Zcash Protocol Spec § 5.4.8.4: Sinsemilla commitments][concretesinsemillacommit]. /// /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit - pub(super) fn derive( + pub(crate) fn derive( g_d: [u8; 32], pk_d: [u8; 32], v: NoteValue, diff --git a/tests/zsa.rs b/tests/zsa.rs index ec53b93eb..ca8c1b874 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -259,7 +259,7 @@ fn build_and_verify_bundle( }; // Verify the shielded bundle, currently without the proof. - verify_bundle(&shielded_bundle, &keys.vk, false); + verify_bundle(&shielded_bundle, &keys.vk, true); assert_eq!(shielded_bundle.actions().len(), expected_num_actions); Ok(()) } From b4f628133e8c6cdbc05038b312abe78f0ce7ba10 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 25 May 2023 16:01:50 +0200 Subject: [PATCH 28/92] Circuit: Use nf_old_pub to evaluate new note commitment (with rho_new = nf_old_pub) (#62) Currently, every new note commitment is calculated using rho_new = nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old). For split notes, we would like to evaluate the new note commitment with rho_new = nf_old_pub (a random nullifier which is stored in the instance nf_old_pub). For all remaining notes, nf_old = nf_old_pub. As such, implementing rho_new = nf_old_pub for all notes will not affect those remaining notes (and only affect split notes). --- src/circuit.rs | 28 +++++++++------ src/circuit_description | 58 ++++++++++++++++---------------- src/circuit_proof_test_case.bin | Bin 5250 -> 5250 bytes 3 files changed, 47 insertions(+), 39 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 9b2f9b766..7d5cb389f 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -459,7 +459,7 @@ impl plonk::Circuit for Circuit { let ecc_chip = config.ecc_chip(); // Witness private inputs that are used across multiple checks. - let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset) = { + let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, nf_old_pub) = { // Witness psi_old let psi_old = assign_free_advice( layouter.namespace(|| "witness psi_old"), @@ -524,8 +524,22 @@ impl plonk::Circuit for Circuit { self.asset.map(|asset| asset.cv_base().to_affine()), )?; + // Witness nf_old_pub + let nf_old_pub = layouter.assign_region( + || "load nf_old pub", + |mut region| { + region.assign_advice_from_instance( + || "load nf_old pub", + config.primary, + NF_OLD, + config.advices[0], + 1, + ) + }, + )?; + ( - psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, + psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, nf_old_pub, ) }; @@ -754,7 +768,7 @@ impl plonk::Circuit for Circuit { }; // ρ^new = nf^old - let rho_new = nf_old.inner().clone(); + let rho_new = nf_old_pub.clone(); // Witness psi_new let psi_new = assign_free_advice( @@ -851,13 +865,7 @@ impl plonk::Circuit for Circuit { nf_old .inner() .copy_advice(|| "nf_old", &mut region, config.advices[9], 0)?; - region.assign_advice_from_instance( - || "nf_old pub", - config.primary, - NF_OLD, - config.advices[0], - 1, - )?; + nf_old_pub.copy_advice(|| "nf_old", &mut region, config.advices[0], 1)?; is_native_asset.copy_advice( || "is_native_asset", diff --git a/src/circuit_description b/src/circuit_description index 247c89889..32ecbe8ea 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -28887,48 +28887,48 @@ PinnedVerificationKey { (0x3a83a8e762ebade712aa5cf3c41c730a79369475085bf1155579f7f7682408e2, 0x25b00d3ee1da9a6bbd36b35ba461da45abd931c767b863ec4a604f8ce094e4eb), (0x1caeb4d7ebb44a717f83ee5afd35446a5e2124f6a4075342ba4eff589523fb57, 0x3a8c431a13632a5b5f035eb4b804d37f2591e84d05d765ba3f70a3d61b907ebb), (0x107d95a6361fc98df9042f32451faa4fd48c1381653be7847d97cf997a55a4ad, 0x31ebf6a2e352108bb180c3278e72d88bb5bab723d3b38aa47c144fc37fb8a962), - (0x090c0e45d81111bd494b9ce7c16fb0e0bbc953911c1701e42a5de5f36389afbc, 0x23ab5bd08aed9eee6c7e78f15652ef51633694b92b1632f9e51ccd31b286066b), - (0x10b2c2af49d17b962211ad5bbb682532940839026d0d242b254b907a50d136ba, 0x1a59a77fd094078d6075a3bdb691bb0b8808a97d2e06092cb6afa767fcdf4cbb), - (0x2b98cb6188d5afb90a5bc94d9f6c23086164284107dfb04a4504b61833a5f9dc, 0x205725733d9c55704a574a244fd4c0038e001261c9f978a2ddbe2ffd33bc026c), - (0x31711515cf172b14651f22ff63fa42011b6de4daa3b71e28a0ce57ae65be3e18, 0x1da5bab80180265242efdfe09c64caf1e987a16384d9eb3bf80343cdd0154dd4), - (0x33548b13c1aeadbbebeced0618b28498d0f95cc26a0413dc6c6b12d305bc9de7, 0x04769755bd24a459f3b86018e78e1f4d14796ba33aa7a08684529e47860f215c), - (0x03e2f4d89dd13482c272721bcffc31fad53b5deb7f402cc2522d2c10cda6bbbd, 0x3b5af207073d98eb42123895069f5a1b726a476ad1ec2945ea63395c284447ec), - (0x3518a704cfc4622b72b4ff3cbc7382fe91fcd77d861e4ef7f2a9830150066746, 0x12639d3e4aa8d1d82cd591fa2e58b1679b677e5e99711a733746dcd47b36a987), - (0x035cc4fa63ce607b7dfdfc08beb5380e3f837090ec4b812b1772ad03ca97156c, 0x14e9d0f3ffedac7d9857fc47f68ccb943f602577a0037e0e3c972b9996f96d71), - (0x00f8d7b4c395ef38584c0182319952b12a25f9d51b75293d4c62f7a5f4405a72, 0x37fa03464d244314d298ecfe5ab9fd9d99d63f38e6c6d54b97efa04b3acc6fb4), + (0x340633bc671d4839c9245701bd7877dffa14caa8516fc2b2d97ab743abff31b2, 0x2d44e13f4cbd8767746e33ca3780ca730de2e81c68fd2eac2856405c810ea835), + (0x0686df606b54c901940689a81e292bbf35653bed36d07d565e6c1bb2f04f7f16, 0x109273b534b0bcdf7d3b651b87631202e692e9799f300b93bdde0c1084644f98), + (0x3b5c55541e5ecbed649a67e81c69ecf846b0d8bb5b3fb0dca7cc855508a60291, 0x2c2d977d9db18dac2bfeb6863e04603fbe577260b77d83de7a40440d0d7e96e0), + (0x377b4690b84709cca9b5f7557a4946907582090395704a279bc3d0474649649c, 0x19d8a463645acaf5e80a0eae028da3175fe3fd07a8afa7b357266951fabf15a2), + (0x01b35d8bd7fff98c6eca9e68b04159d9e04c8c97ee823cbfb25c72759a0f1bff, 0x2f690ea00d11748a56994db1d5086cc14feb4e182950aa3bd78a5e7c39f1c438), + (0x14322512145256db0a887e0d44cb0ca576d199cd60dd6c0fc592974f5bfc982c, 0x14f0d717d83c30687335f599f0e0b313e1f908d8cb539273271d61b6c0c7a977), + (0x2cfd5a6eebaf22de42df01c35ea51d5149528799a4dae214ff5ea4964384549a, 0x0241a066241ababd11a9d336f30a68d2eb40b15a1a74ce7ebb8284818341195f), + (0x1a104a92aae262af0c12ae8e460b8a050d0609236881b44523a51ade8d58fb59, 0x1b4826150f81242668cdf5ac67894f1aaa4f958b4e26af911fcca643c4cd5265), + (0x1973139bb6cfd1f498c01fda7934f1b9954a52bb7e3778814745f73a03f1ec21, 0x0984409ed6f0dfbf0b25a658c4838327096519bd700e0b7ccd69528d971da6d4), (0x3c0f3f0d7b2306490dac7d578d4846c63adcc76988ce322d8691c3b8b5b0f623, 0x12d81ca672a1c18f6e0d9b7eb8fbabdbe450fae6667cf349c1a0e63ca9a0824e), (0x27d13b33003ffddcd36efb731fe94db93d181bd994e0c057e945402bc8501789, 0x0e1dde94ea3b35e0d0a66350163ba2ff9dd5070500912b7d076747816965ffd2), (0x3049e9c8a3e6c7fe628660121f04915e03546b7a2dcb8a3e59fa99546e4f7f86, 0x2dcebc740917584f788b776f4cf1e3cd96b4a29e9df7224fd8e5f428d4112546), (0x245ebb4ccefa7c4e2d5a9d7b1746b8277abc25f74cd11b2dbb752d49612f248e, 0x145f605111205a7c3e4620ac035b3cccb6375f8d3c3469b7900e427607c401c9), (0x1751912a19fa0009ece61b686342d6b4385415e942159e8db3f174ad24d612b9, 0x0f31114ef566211d46914d0bc2d1a27a0e34eeda04dab53a0af7a37024f057a1), (0x091c6c4854fa5d9ed8a966f2a1c4946b41f6872de6c19fa8b521a0a8eb2bd899, 0x29100b4e15344d750fae4a81c82faca1e8e0573336b1f54b394946e95e7baad0), - (0x210297af23386f0691220f2a0e3504336a815cdba5167277a13f0a7b992b8e43, 0x2a184bc5b1981e303cbc0a18f4a01b4dc49695b9a319bd7e713d55e46d1235ae), - (0x05cd80ee69394fb4efe616ef91593c3b8e6e142f2269524f01476ab78a67c9f6, 0x23a7840c00619fe55078a6bffb8a061913f929a7669861ebe99859a48136f12d), + (0x1a5bb6ffd1af2165203df63414021a531f0f2bfcec85443a180993cc222b40af, 0x0d6b8b0d2363607d15746434b670008845ed0524406c1d8a221cb6f58ee2d4ed), + (0x3b31f6e48472e06a9f21145e3a37744fa0ceb6188485ce44b1a131ae47661e17, 0x382d47f03a6703a3018d8582a6123e0e61c549d695f1e2a40bb578bc2ca0e6f2), (0x34c8b83a2cc924f1b0237978c8f911e6a54375c509ba46456a011fbb74c8698c, 0x260cc681c222535c0030f702172ee8855b681c16d706b1b9a786165e06705de6), - (0x3dcb136a22551e524212c0325331a9dae5ad6ff356175e6b82a54039475be1ef, 0x3bbbd0d20ea0ebb0f36d740910947d1934bcb93ba16325ea42f124ec0cde7a81), + (0x1b7a61e8a9b32fe558433feec9aaf51204e5486aa468d7215087ed35fd6ecbe5, 0x1f36dc6852f92c141ba800f721d079ffc553c7449b85d16e7487e0c3009c7835), (0x3bb657ca32617e6242b6c6a0b166a1db205024d0441d091b8d45fb478cd4782c, 0x3189ce1b97103345fc0eafd287eed80ab186151171f22af2c9befc71a0957529), (0x25578b0a6d546cf38dc84329fad41e59690a2bd94a0db5fddb42e0db8c267827, 0x03448e4552625dda62a96318bcafcc305deafd6a028f8379d8c8d9ffa0f86e64), (0x30d1828d7463255ad75b39ee4c718de05a762c45c5d717d059496fe05d1575b4, 0x0a8eb70a9b252ee9ee57b29e4dab191cbb29665821830b2ab60fdd5d3414de45), - (0x2b18121165b0ebf2ab46c207d973f44f135c24efecc1cc48d47d38769969aa2e, 0x1a829739cf7eb6422f581f64632c65073aa49819e62e80489b6aae61e6edd6a0), - (0x23ae57d2095a4324262aa76f345fe7bc21d8ad7b3203a8167bf8315e64a11d25, 0x1a871041d826e0e3bd7520e03dca1f56211065b049b2bebc59d8e01b4addb1d3), - (0x029871a070ccef21bb6d1d5d7e51597b0dd8f38208f1b304bd372b48aaea0a3f, 0x3205e4b0ab706647e6f45cf2b2091afd69636a8f61426504983bf44d47d676ec), - (0x0bd7a66e0b566e724536f77fe659014db82286485859c1ae9d95f42cb898f763, 0x358962c131dc5dd41db0fe6a8fe5315b75dd9204682d1de05470184c8a331a8a), - (0x336245b9b67f39852776a1f6ba5072ad3776f38d9b0659568d3afb2e6d3750d3, 0x1ae68f5f91a6d28b62a9fb9240ee53f86e0ac434286429024c253bf85325033e), + (0x21c6cc32a998a56e0184238756f9bc06c034326644fa797d58d37a4ce04862ad, 0x0a3215ded9e38470be699055ba4776fda0751bc3d0b893e49c71f2817e12c354), + (0x2b8641a13009b6e2c57fb902961c97d5a37fe9e7012c48a27e644ab86c6e798c, 0x31dc90911a15d74e74ad51ac80cbfca12b1eb06038bb3d5aecc0498c5bd5ff68), + (0x10b4ec889583134fa09dc3e6f0fac585f2dbf6dddcc1eea2c95bab4b8de05be5, 0x0eb4092d1a27658602828702d73145b842f9dbe4b113b61b10049ebe406d625c), + (0x0b9493ff319556d1792c2b1ccef1c52d6097620601b22c8a6cc9f3da9608a3df, 0x098fabd4f3443138f8c72fa5991a7012266cd3d574a65083a611688aec7c631d), + (0x2574aa02cd03503fc37ade3434a4d426f97f94e5f98ae5ea8f3d1324589670a5, 0x22b31bec6726ce49ea837dc05d3576d2e71536ada0d7db4efcd06c34b2129e2c), ], permutation: VerifyingKey { commitments: [ - (0x1dcbd758066eec5488296ece96ea7fd0eb814479bf5cf04418c109e0c6e3b65f, 0x16f9507e843611c3891c03a5acbb47cb2d8c591575911c12815cb1e031cab8af), - (0x2388cbed968c22e32b6bd4a1b2395ec1d940135e0136e1df5600f2d759748a64, 0x251608eff7019c64b80df6b45d2a561208e59247da23c0c41f29268ebebcc989), - (0x25d09b3bd46f027633197dae5164cb90c8cf4358598bcd747791b9d95370b1e3, 0x0e94d8861f8b7a6c4f7edf780b131fe2b89757c46cf0b2da24a3592c8824c692), - (0x019398cb329abefa110b3c4d12af9685272f7a611599f5e9c54cd644f0882a51, 0x2a5d9081f77f6e389a355fcc45425a3d4d6de28cb34b26bf54ba66fbd34b8f86), - (0x04596f22bde8d6e02fa2426ea314dd115fd757bc58a60e7349669dd090e5d756, 0x09ead6fcd376d620681f3b14c89337d25ec795cde09fab7da0376bf07bbd402b), - (0x0f7bd41cab58414151f520efc629836da3052d911e95ec09301e25a36e10e9fb, 0x008998b3c16c01c66bd471eca4c16d87adfa0856886b11bff2d04e281e45f234), - (0x122e03591cfc43c812fbfcd45a3062d845b6beecd5e9591fc78cd07734fd5eab, 0x3bb6a66ca91558265efcd59482b2f016ccd34e6b916410e5a198e142ff9257c1), - (0x1656a1c579376b8b92f00c907dc544843231a13b0e0b58be652c9ef44e0d8957, 0x0608dca2d8f9ad5ce0d7b0545a3d148371e4e3993249db87ae4e8a95034e330a), - (0x1d8dd2ef5d363793653c385ef62f382f48d21234caf6dce0806f9295d0f63f47, 0x3aa78867d1d8cc02a50e0ed804a07b0572ae191f0b1c495072fd11f6d2aea2ef), - (0x2cb9fe3cfca45f22aab479b9c54d7731bd165a236bc2d0bfea9af9bdaf8969eb, 0x2acc3469ecb12ba57992881873adeda3f8380262977b53175a99f4009d082405), - (0x1f56f0d66eb5c9f86a680efda44e992322f4934c10b83895ffe60aca9305c5f3, 0x20cb980461e94d5e6a5b5beaf4361b77680f5cdd4f3c4398473aeaca212ada1f), - (0x3f821ad8e7fe3fb349c6e9b316bba2505648a219f337f9e5f1265572b606fb4f, 0x3f4472a3137db52586f3adad1584ee57dc0946595c62f6a39420183814cb3a42), + (0x09d1106babba44f67eace95337e3b9916cf02d0b143d5993cf212ba4fa6e2d81, 0x2046a60feac842a629a24189de9d914da26b2254440c142cf851f6d4d5c586a4), + (0x26086868fee3f97d3171042e8ad377782aa845dd3e5c6c86f5d1251b41b8ff03, 0x2f60015e46a7e2bc0e30413be4782c648ec5e9dedc92ce9052fd2857a779a4cd), + (0x00d54c6162e5654355cbaa6951f86836cea891242793df30e4ae74d522747d01, 0x0f9d6c7108000d07ff766c16757c7a02cc8bcaa1ce3001c476bda543db4b52fb), + (0x131a626c24a64b23cb9a554921462f8b3848294a5a12110528b11362fe80f59c, 0x3e8076404262e3d7b5a6d2a3dbdf0fb151e2f3fe4a9239365dfd63853bfd8b8d), + (0x00aae2c83a8cb88fd04c9c631ea69362f38d41688624f519c6aab8fb15110931, 0x0294f0e5b376a7bc9fd190f34c00201c0ffa2a019148d27e1a578effba915450), + (0x2022cd25023adefba897a064d43365c59df92f547eea992189040ecf23eb1b89, 0x2d5ada0189acf8d400ed967e8537e7de7979d2bd6ad5430aa009e200edcad889), + (0x30e4290b63621db78bfadf242ac8a940179ddd601127f4fe05df818dda0de8b5, 0x13ab4dd58054df7dc7c4e59fcf5745373889113fccc60d8a79957dcbc4a1a79e), + (0x17ee4b08749d802b2cb5a8d72df1d27c4a521293347698bac389f473f573888f, 0x19efafbfa1bc8c4e62cb0d8893905ac7a30da08a9ffc18ac26f741c6419f2fe1), + (0x1a5804444e8f54cdff0f38ee9fc051672b5fcb0cf39cc608e20db884c18c2ae0, 0x11b297659614cacbc3fe5b6b8506d7b31d04ec061329c791714478f480215263), + (0x22bbc74dac7b42add29982d2d276b548b38b2fdc8628d4fd331f5d09cae93881, 0x0808f95123e9339e6643594561b28d0a4b6d7d52bdf0b60e3ab698336cfefe06), + (0x07201f37d78f79f85a69d9333e60682fd709fcb7b9fbc843d0baef7885a79246, 0x3b01c7b445dd60b44309c172d55cd2bfed068fa420f8c2cbf316eac3bda6985b), + (0x3998aad0ccd62e9339c4ca91363bec2524ec945bb780efd9984fec68b4f51efb, 0x32cdaa4c65f29fa0675df2196f3190b849dd1dc4a48d615602e57b282cb34673), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index a6199f11455998fbbe3d3b83f1149313c158b811..7fe92dc3d1d910ff5b4a2044c05f15fa7afb872c 100644 GIT binary patch literal 5250 zcmV-|6n*P~xU_b;fhbt`k_*LOM;@_`#gb>k&yej6H_8dei)K5i+*|`g8yfmp$BEVq z23+KO>Dh8*7?A{o1c>_?cykn-_tvM}{pSTSdvd4jx%6dB8vlM9Ax#Hm=#NEr-axBt>wd& zPX15lxd?gBv4j+s--^^kI4LK4-W{<^$jP58o;7rNt`h&~?v5~Wf`*MHEX_2}hpnz< zbYWrN3f?yL0g`_wO5+x)U*$aF|Ns7ta++hlEs2}-BiYkw1fhlPsAoXbkwto!&Ygy@jDn3v`8x#F_we3V$+Ho$0yQ+=$Vap?9pB zJeU7N{vjp7uPl&_I{&IM0(c-)#j9D~1U}?7R4C*!T9sE=Vh=Wz zjkyokA5|`^ltR}jT@AdC!*{A&v&}AhVEgEhy|zrn?yw^Jtjac2H$bsrmrGx9d5GJ* zz`Vz<+LiUga?dJ^c=o5#bJuKTtY~s8mxuO zk_IfSYr~ypatn*3Vu`y)&L9!iHY2)7yXmJ{G!R%alMlVoVPW$NUQJA|#5d7i2?$*JoKs1jc7XY;)Acv*$8 z6S4n~xHWkzuMz81{^RKS;C~LfAJF$+fXIsx(!!+UKADEqCF{>P*&bO)ay5KgUUd z73nj(?w>zbl0NqsQK|U>ngHm6J@=AU`gZ<+2Y_=xPpw4(-q$+F8sh>b{4p@;vj9X` zSNj7+vEIia6sHaHt1HjG>#A9cm) zmS+0qEC|u2&n1awmpLd=7-SL)0^8KxGVEaSQX}xqcuwAsy-+jDgnq9$FY9SkltP2C=n!W$2bgqA_=|Z0g4s-hPw`;bKi1Ew@kE~*uXwH9PE-l_)mwx2-9R@h(B?Di+lMy9K-84pS5_0Dro@f?7AYr`gwl%W%UZ z@oMiNo0W}AB*$MlLkiosqwyY9i9i?*!C(}GlL=)eW+ceHT=LzGqMlQ&bhSn zqfRg=7vJ4sXetB}!c$L5%aa-{n52&vD_Z{?E*%kD&$6o!#E{@Y2cY7EC?2i&vW=U$ z)Dm8hKQY7G{T?|WBDD|J0XGq*dV7(Xb#~$c#E>t<`^Cn2Ix0!s_z$_0Z5ZGp{Y-+q zT^WeRSYlS4+#1wFapqhkM03Fx|qq*VP85B8QNTVQt~jbl{pMiBAE(JZ(BIhcjyMN z5>`ubK^4jrItVj)vS){X0xPg+5kjQQYrk2j_Rs^6R@{DqceyV{&2EI+NF6U1Ug{D+xq}5C$mA99xOIGEIqvdiZ9rHT(8Q+2&DYn8?`J>AEL(XisLX@D-`uOE$6Bjhe(F0Y25m&rPbiDY)e^)<0nk0p zQ}>K_kBE<#6Id17bHmtdOlQpy@$OfsFXSBt3TOZ9Jl9EDj!ip<0rW3D{m~%etvqWW zNoe0VU3&fD5cm&zF_`+8Y#mW#FP3c|$m0mXv+Q$U8dt;Sik5Z+5%k*T^s^{2BkJGv zh0cE*14=%Keu^iK#GgCDNAt+IC0s-SL-;0V2E6k3m2Ayqn>dK%bK%0mDlYx6cGM5q zE=oflAc=;a4rzyPUPNGfw-jWZvRL8uAp#%1Gxd<(KVVs5;e3TgHe&Hz#~V^(o1W0u-YYUAA>YA^8 zUE3pfR<~Rc_FDkMXOwyzHrV{O!~Wj2{9hk==zVgR43ETSMW(;<-Jp_C9(mS1C7up& zn~=xLI&~R>*#_>9d#L5W+-DvCQpp3rxYZ{;JdG&CjY}TGS{{=D62hw~i7`n8EU=sk zGNI_oW+Z?T9w@VIZ0k^ZvN|*d9?utufEktN57ucbNh^S!^{u@M9guLJNC@I82eY&r z66o?mwk#gx?tXSTV>f^KW4@<^BZE~VKRhrU&$=fr6&C^pA+lHcDZz~KHuW8WB%Cj} z325w352-R$O(^DIwkZZ&rkkb<8VQW1()rG;vwD?tJ3y{u3VC|nqN>%Zuh~ssok~cU zz5|sB9LL+_#Y+I$9fD|kt8X5m+gvFy?DWYX)ix}(6j&RM+;2P*@!)tCCwY?o8dV2@gZO@G-g%#xb}NeoWlzb> zB@`_L+gGueLedENTi%$q6p;(IWGe6HY@AxU_wD!NYXnvZ?6@RKe zlyE$_{M^tgOzCUUU0QTVQ#ZW1K{fUF_b6Gh0}@4?hMxkp7UM%X_EZwE%^%DI#j%Js z6Q!$Zi)kEY0p{JMBB_&t=upWg`&L`GUPw*{dGN0r@4mu-0!z0`4!%c}g+CmYRj!8k-}fi4CDy!IoQ1*~N;zBtB}NStIC@gBfzzW8r3qY(CJgRiZh&9F`w z9WsgyEZ&sTL*^4S1BjPGBy$=*BXvlT)dVyb&D}9ABQw@QF;ULw(6(r)H93KWSupg- zDc)GLCN{`RZhR4(9a17!N7qDiOC7&!jmUqGOQ75@=0EUVrkIj7QO<-?0OiZB4UpKp zM>kdIYn;II+Q{S+Ofh@6DzG&KU~wGA`5 zE{%Z6EWaU}$>kjGThnWYs62**9;czVA$lv#YZ0Dz0$O64_22hE8qoW`t2M*YIVC}M7LqmxHh^TrN^`F?1qL}1 zV?DnO#08k0??xtlp|p>niYnmpDG`Z0Y4?N1^q^?B-h=YZqV#f7d=@1Td&3>E*+Gv} z9e8__D4>mH;ohZ|hLN@>-2l+k-0BDE{^HU`|wE zHJ@NTZ7lx;2Znhz4x5Mu(owd35>mssz_>%tKUPWa3d*JO?7!gy+8ypFJEmkzjFEiTrV6>BbWJC{+ zhn%$*q3z7V1BYj81bb=HBntb^q?ga~1ZmcWe0^7o@hl55@>!-|GL4IV^Nvh>9a(O` z%(wu`K+q_I6}oirwwj*=;gw2$J^4`$=93a*<;ACBBKMR6=4-!p)W?_|eJRg;wk)yp z3a~PwxKZu;+wI5lY_#bdg5|Un3~;oM*3VX@>^WyA1Wx8@#ksTCE(_jf7<+Hex%#mj z#O23kQyO@7S@sUY^RZ$S+&Ci29XxQv>J3Ah5%BpCt zylj*R5;(FEuQYkOMlON@gf3ucxV!JM9E*}X>)PN`XQC!)}=czW6t!<1%ex)U;P3IH1z>_)`qCvW*^-yt*J;?LKyWiVmyP)X-9Q3P#EZ$@1oX z7ipY3!0$>{F?kLC&}T|BfCB`V*ZijuYVDj;T>h@7VIK}ZoG+@Td23AR}`T_U6jf! zVpJ4AXfL>+)6C`E6&ZsjqiXUIpY@o;XWwv_8q0^aNhRb=n_4YC;a6DE2bn=sBsa@= z<&Xcy*IkFwNOFH{m3h0e^Wg5B9M?8FAK6rhy(>WummzS|ZR>0vXf92Q8}`F0zPI|s zb;e-mjMWR=khcr^iZ@}sv7%0kzA@03HokB7knj;NM5%yTpA^@BtdM}Jd6v`YOA8ca zBN;Sr6LEZ6g*+)T_bv1FsxHzd7prw@#GqE8ZWtlCqXikE3mR3wDW9uVum;M;gwlR} z*R_B=96cy1LCz&d5{0Wu1{b3b4>o6ZphJ`&hYML0#;maf zOBy)Z=zf^rxiK+pyEYRor_j7s3Ch3lnX_)16@$5xCbgoBRer;4DkRS3@$tU}7yKu-^XxJ8jsY<`=F}dNblUu3dO6B?p{pAz zeAu_((N#plGIC{>-j3YKNTd(VSvx1ph#!5Bwr6L^^+W{Gp4nC=)+ zA1E$fTvFIgX^=Jn0qW>v%WZ7od<5N=zGc=UM}0sZPr0DPKeVIg9q&qU7t56|nzzB8 z?y|2pRCI360fx7B%RRfn{&>T!)%{EEGq_X3cmIwnghDK$!zt+{c;y9S|DoDHh2N4p z25q9J2FAN&Yn72SRMwT8Ew_RwNUaz+xBGt0sNz&aV{69>mB9h9J8HBl_{GK|5i<4K zLBQYvm4;T_eT%K7N5N8V0i%8c6v+v|I`%p#ko9{Xz1_iQLr;1GSAg+Z&;*d*B1UkH zhtD`|gxVW7qs(2IDSprF!BMi7N7RnVE5@Ie2iLuVvVlCQQ%10Uu4Q=IIb=>jXXtXy z&mt+IdW|pRtYCXwJ=k?5Cp}+U=B#y&?1+yY5lGT@_{1}hH39i@$EMq zs8MzDQKAbm)M&QG;M%YIsGhl%WL@TWhQ3|Dw?`hT`n?81HRs2iX2AYtUN_q5qg9xFvP_y zwI8{kPaZ7fCwkJ60SNW%>!Rk9iHXN zyxf0X*;;%^zr!oDm8BI!1+Q9z4F^3k;M^>!r$ttu=*5rG+7g~r9_BS|TvUQI>(8gq zle79M3OOx^oCTK%o$*ZFZqeH!dP)?i={k8r@Z5Emc7v**Tc32lp!V@Wn-i|^L?1_r zT7nUX7GbKP+r}zNge5Pfdg^R25TzgI(`b%XUi&k;6|V9_qu=ALW^JYV+3)xrG;>*S zh62^N{WvbXYXG4X0ESP49MH*SHZy9&A@hyq3=C!B5GFr3oQxwgePf+?E$I!D87S*= z7){=k=Inu1ft@79`bPaK(G$pa%3N) zCvlL%^H9O=>pxRIf>g8zz#^E@ssSu86@|y5 zHr`>@jMKQ4(4zHqUe&!JL`@~iqLvlYeQ6{I0kYBD+}qDEFDiRuuh;J$YI20gLxi95 zE5@f5@nW%WAE-+{MZ^LJ!(o3o*C&F=pAOb##k8WNvPQctdYhqrP zI*u|JSaEw83@Ev6Bp-)S+SZyamAUB?ml)3#DcCQ$;cqM)I2q)9U_$PC z8i!M{KaXjoEv0Gg@v%eE>27mfAD6^?R#AUF`s2Mqyn#{NE9YfhnC1Bg@J4)ONJlFU z<6eClI${h@pwiutTs^^l3H6AkrXF`>$>*T*A23Q&#{Ui_;G^ams(G5rwic+DJE)hQ zGsN0}{lk786p2e~=?O<6sxN3vLV7sEC8RoZ2Yf)@lE&_ssgJ94AE6Yg*MgJ=#&R!V z1=+CZTf9A#GJyya*0Q^Ygk={adF_8Je{%D2bO&>+m;ZKspQ6 zk^cC-Uq0V(yZy%QtmLnho!@vjlYrc(Jin+N*6D%(qCw)hv1c?JaRx10 z)gd}-5xy0k<&6(!F3B+1I0J%qwG^oH`KonzHkx;=b4hfWcGFCu;X$?z9zavbyBon+ z+667<5G}9>R1+$H;iB{=Ix4&J@(AM0Hbb2#Cc4+S*?bMZnFlSKH2$gaZJ@qc8&wO% z(avf50?E&40zz9P)ds8?ps%32iUM$R!9S}>PomGwlkOr89&R=W(MR#(YE}|TOF~ULG~7Dcr-rM$UH5^D^M+sPV*uos5?aH*6BlY!ru^rV z5VhH$;O56X4T8CIlfz8M#JC|Q1L(R8eOiduA7fHl`}zZ`<;hhR|JYp6J*x9v7QX%r zFmL5^rWll!z$@Cq)-A!mXEE9@9-8eFb8evHC9LOoHOP#=2)$Jv(Z-qL#9Jfy{=A$G zcAy0JTz-*LyE@}HJ8K2SE_HvvBxRpB#AYg5$Tk!F^%XL9C(S~8JK zQ1tn24eilU$?qfZc2WnkC$wa7Jr+0quY(cpUT8R*k9#g~JZ6w%SXmDG!fK1iJaDTD zcR#6c6+mZBK{|zu@CyiCB-ZGxB{6zY1CBy&?zO6BxHg{Z?nc8sV;1^Y?W$LKF@-@1 zUA4n(9H068I@>^7K5B!Z!Ym~RI&GCs+oqo^5WIcxGnD2O2ioYZ3Rf>+#vSnQXGoz+ z7VD3nI|}Ux4&6&AgfhX4+zg4dP|In+w3dNZhyw#)8?b40IIoKz9tCvd+D9Ph@#aH3#|66EB~sI{9&4AF_Y>DOtM{>0d?c79n*!7uL=TfwiP3cwDnfT>cF zvOA7e0Dp6pa@V&SZyU^xlp}vIZ#lJ30@n$?tx7}mtN`BFfX!zPLkJ^Ss=NIZ{jX_L z2>l?hDGzKp*yPYze_SZoL+#tGO65~>lF_eI{?I6AT}?Al8WnavrT(CxO|&TNc^^<- zY}#xYDP93qHzG7u>X;042geDB-8i-zU@-v$`!}o@kM}r>W=Q)DcWI3+OmzND3r*{? z2GGPVA`&;~46g{nwUIdJL`z{#GHGuwB#nLfgXDuN`k*UGAB|n!kMy|LXK%`JDskUsrK;=k z4}cWl#tv?L`fkt%CoYLFZICn`Z{sJ@CZzA^xMC=*7)LwWC$xtc$cIrSLn)NOQ9|p* z_pKiJ=Wyr?n4j7CtjUes7rx}^kbk-0qA}~)WHi$6l2wP05 zv&eDd6v~Wl!Qj*u1a5|Al;v^8;EWq@Nmw(mZr4uu;<1;m=EskUF0%!V#!`hf)1JN7 zuMv*2)-DHo7-nhiQm&|;<90-r9Bv+03>5T~EkKtX`d6yp#{jW`w@X;IjyeT|fUS`a zCM5rhL}@DaR4%7*8hFnzphgFq9f9(3^2C|L(lJ`H(831_|AhEyO+~-C8Y%E~m2u zUU@|9_$vR74k27cqi4FN(=vN1ySKLnER(C27SrX$U?U7n<#ccMd1J!$ztYhDfQVq9 zsq6w3%#HLfH}@K2yG+pR%_zJv3$;k5R>cuq8japxgsIK)SG^{a8<3G8YEQb|7{)}y zSEvu)k9DeOz0=LOVtTdOM1vYoz96Ea>d=zJvhn#&dj#U_6j0!LNr8n? z1x}828r$umz1FYs3a@NKQnIIGT}MJtY@B@aA)I!o3f`<#AVj#dAd`GxL2s{Dz&}pX zKP4~rNZ{7cbbc)O8}P}a%(H4Z8h<~brJ&P(pP=`>W~)$sQJguf{c8#*Bi`m$ZOzRy z9x_9z&vQ^;aECvK5Zb?o3};++?AxANII7q6uwN)1r-*Ee87E=iaI-LgbDTa&6b;Uq zLS@u9H-Gv=22L|aRy1GQN*8~T11j89Q)RKD-R>R_l^$V@D7ot>G+o~(z=Ialzmni~ zjsX4gj-%Ct?|WI$tad}W+8`fQg0;$Va+kdXbhI^fEwrvQmSYP6=Tp=G(XP<5KY$^8*EJ1T z*CD#k?8cGoJ5Qzt(}6j}EjLbcg{YIuMo-!!R|5})L)f!c>mlt39JRoT=M?DuLgizg z!i^XEz9;L)i~|e(tut5mSJR$5LbI4)DwM`c;>^a2GFm&Z zJCtgGd~>@}j=m-y?nBZIogA74-iSQo?Z^Y@3TI`~&W&4?FWOFDz;z~Uf0Ge_t&BblOREY)EV<0be|%tKmP@(EJ1VcE!b_t> zLo+UodD%aKxt8$Lwwapsjygy;D}aDvAmewCa;K zx)-s1p(%whJulnK(J|t+NX`P4?RZA|iL~&m4x5+r!xhOMk#zh=?>h=F^0PX~*6c*x zj|66rC{g!zrGEovvDg_2ggnkz@00Ay*hm!`HvH@d`Ig?SPxbx5{R_T(yz8|Ik=ZK~ zqtoMab^?iR2De$(W;*VZa;gv?`@bt*BkUi1KgK8*Ik?fIEy+Oay%E!&$hm_SqR8!6 ztlLNuBZ=}HlDps2b;RY!Ss3VS(~7O(3vCvTs=@#5W_|?J8l$@wBPxJxAL-KkXmhp( z7RSk62<0u{kr^mZB;2>Gi&$QHsxkb!JI(2V(R$JP8h3Y(C}n$QjUS>AWGK7KA&t4S zl55hTKBKym$UxF9=NhH1s@AF|itfOhZT~cFupYfpFK}vQ!1?TnFk%w+%#q3mCa)q( zv)B6$m3FgX5#w}kFp2&4rbOa3{qSt2D3-Bv2n7VAOsDh;usq!-lX@h4hsycam%HtG z<7u4TG0U6_Exc665r*{lsT8&MSk`9@!|-{PdPRx5*-E`ULa`YdbYrUz+yEC)%)tr=Nh(SmAI z1?y0gabfp-)nk9sHHCzffz&HixHm`PZrW~xkqg^|&6-~CF<+faogr=13yDLJdg#eC zFhYxM8Z+{$y;Ga09A-rtJY-XEGV>&PUuFwy{M@>KI!Nxs$siB2g-^G#^-1T#daPeH z?sgw!pD0pcZosFqIeGdbsFv~lAYddz7i0;V&JvNmM3?}nsthyA3u+95y`Sid75r0K zj|w0d)@euy*gJ{-IEXB{*IH`gYZP%;J<>4LhADJqJ&Uc)5cG+Nn&~v)7TkgrIXG-L Ib7Nu#GPHCAVgLXD From 95fcf884079b40e5e1a0f484b09c849799ae2faa Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 29 May 2023 12:06:30 +0200 Subject: [PATCH 29/92] Circuit: Check pk_d_old = derived_pk_d_old only when split_flag = 0 (#64) In the circuit derived_pk_d_old is evaluated from rivk, ak, nk and g_d_old. rivk, ak and nk comes from the FullViewingKey stored in the spent note. For split note, the FullViewingKey stored in the spent note is random in order to derive a random Nullifier nf_old. Thus, the constraint pk_d_old = derived_pk_d_old must not be checked for split note (split_flag=1). --- src/circuit.rs | 63 +++- src/circuit_description | 588 +++++++++++++++++++++----------- src/circuit_proof_test_case.bin | Bin 5250 -> 5250 bytes 3 files changed, 435 insertions(+), 216 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 7d5cb389f..4db6a9fa7 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -225,6 +225,7 @@ impl plonk::Circuit for Circuit { // Constrain split_flag = 1 or nf_old = nf_old_pub // Constrain is_native_asset to be boolean // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset + // Constraint split_flag = 1 or derived_pk_d_old = pk_d_old let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -261,6 +262,11 @@ impl plonk::Circuit for Circuit { let diff_asset_x = asset_x - Expression::Constant(*native_asset.x()); let diff_asset_y = asset_y - Expression::Constant(*native_asset.y()); + let pk_d_old_x = meta.query_advice(advices[6], Rotation::next()); + let pk_d_old_y = meta.query_advice(advices[7], Rotation::next()); + let derived_pk_d_old_x = meta.query_advice(advices[8], Rotation::next()); + let derived_pk_d_old_y = meta.query_advice(advices[9], Rotation::next()); + Constraints::with_selector( q_orchard, [ @@ -285,7 +291,7 @@ impl plonk::Circuit for Circuit { ), ( "split_flag = 1 or nf_old = nf_old_pub", - (one.clone() - split_flag) * (nf_old - nf_old_pub), + (one.clone() - split_flag.clone()) * (nf_old - nf_old_pub), ), ( "bool_check is_native_asset", @@ -308,7 +314,22 @@ impl plonk::Circuit for Circuit { "(is_native_asset = 0) => (asset != native_asset)", (one.clone() - is_native_asset) * (diff_asset_x * diff_asset_x_inv - one.clone()) - * (diff_asset_y * diff_asset_y_inv - one), + * (diff_asset_y * diff_asset_y_inv - one.clone()), + ), + // Constrain derived pk_d_old to equal witnessed pk_d_old + // + // This equality constraint is technically superfluous, because the assigned + // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see + // an explicit connection between circuit-synthesized values, and explicit + // prover witnesses. We could get the best of both worlds with a write-on-copy + // abstraction (https://github.com/zcash/halo2/issues/334). + ( + "split_flag = 1 or pk_d_old_x = derived_pk_d_old_x", + (one.clone() - split_flag.clone()) * (pk_d_old_x - derived_pk_d_old_x), + ), + ( + "split_flag = 1 or pk_d_old_y = derived_pk_d_old_y", + (one - split_flag) * (pk_d_old_y - derived_pk_d_old_y), ), ], ) @@ -669,7 +690,7 @@ impl plonk::Circuit for Circuit { } // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). - let pk_d_old = { + let (derived_pk_d_old, pk_d_old) = { let ivk = { let ak = ak_P.extract_p().inner().clone(); let rivk = ScalarFixed::new( @@ -696,22 +717,13 @@ impl plonk::Circuit for Circuit { let (derived_pk_d_old, _ivk) = g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; - // Constrain derived pk_d_old to equal witnessed pk_d_old - // - // This equality constraint is technically superfluous, because the assigned - // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see - // an explicit connection between circuit-synthesized values, and explicit - // prover witnesses. We could get the best of both worlds with a write-on-copy - // abstraction (https://github.com/zcash/halo2/issues/334). let pk_d_old = NonIdentityPoint::new( ecc_chip.clone(), layouter.namespace(|| "witness pk_d_old"), self.pk_d_old.map(|pk_d_old| pk_d_old.inner().to_affine()), )?; - derived_pk_d_old - .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; - pk_d_old + (derived_pk_d_old, pk_d_old) }; // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). @@ -933,6 +945,31 @@ impl plonk::Circuit for Circuit { }, )?; + pk_d_old.inner().x().copy_advice( + || "pk_d_old_x", + &mut region, + config.advices[6], + 1, + )?; + pk_d_old.inner().y().copy_advice( + || "pk_d_old_y", + &mut region, + config.advices[7], + 1, + )?; + derived_pk_d_old.inner().x().copy_advice( + || "derived_pk_d_old_x", + &mut region, + config.advices[8], + 1, + )?; + derived_pk_d_old.inner().y().copy_advice( + || "derived_pk_d_old_y", + &mut region, + config.advices[9], + 1, + )?; + config.q_orchard.enable(&mut region, 0) }, )?; diff --git a/src/circuit_description b/src/circuit_description index 32ecbe8ea..ffb19ab6f 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -913,6 +913,188 @@ PinnedVerificationKey { ), ), ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 17, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 19, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), Product( Product( Product( @@ -1057,7 +1239,7 @@ PinnedVerificationKey { Product( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -1066,7 +1248,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000400, ), Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -3675,7 +3857,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -3701,7 +3883,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -3919,7 +4101,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -4480,7 +4662,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -4506,7 +4688,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -4724,7 +4906,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -5223,7 +5405,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -5239,7 +5421,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -5250,14 +5432,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -5266,7 +5448,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -5558,7 +5740,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -5584,7 +5766,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -5786,7 +5968,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -5907,7 +6089,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -6059,7 +6241,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -6146,7 +6328,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -6162,7 +6344,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -6173,14 +6355,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -6189,7 +6371,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -6315,7 +6497,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -6341,7 +6523,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -6559,7 +6741,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -6696,7 +6878,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -6864,7 +7046,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -6948,7 +7130,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -7048,7 +7230,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -7060,7 +7242,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -7076,7 +7258,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -7088,7 +7270,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -7193,7 +7375,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -7205,7 +7387,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -7224,7 +7406,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 21, + query_index: 22, column_index: 1, rotation: Rotation( -1, @@ -7241,7 +7423,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -7253,7 +7435,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 20, column_index: 9, rotation: Rotation( -1, @@ -7273,7 +7455,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 21, + query_index: 22, column_index: 1, rotation: Rotation( -1, @@ -7468,7 +7650,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -7668,7 +7850,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -7778,7 +7960,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -7789,7 +7971,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -7888,7 +8070,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -7914,7 +8096,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -8029,7 +8211,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -8064,7 +8246,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -8198,7 +8380,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -8233,7 +8415,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -10595,7 +10777,7 @@ PinnedVerificationKey { }, Sum( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -10701,7 +10883,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -10710,7 +10892,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -10727,7 +10909,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -10736,7 +10918,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -10832,7 +11014,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -11252,7 +11434,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -11620,7 +11802,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -11965,7 +12147,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -12310,7 +12492,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -12850,7 +13032,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -12860,7 +13042,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -12871,7 +13053,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -13006,7 +13188,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -13016,7 +13198,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -13027,7 +13209,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -13162,7 +13344,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -13172,7 +13354,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -13183,7 +13365,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -13270,7 +13452,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -13286,7 +13468,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -13386,7 +13568,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -13477,7 +13659,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -15067,14 +15249,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -15094,14 +15276,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -15120,7 +15302,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -15161,7 +15343,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -15678,7 +15860,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -15797,7 +15979,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -15809,7 +15991,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -15923,7 +16105,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -16041,7 +16223,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -16050,7 +16232,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -16058,7 +16240,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -17454,7 +17636,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -17584,7 +17766,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -17690,7 +17872,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -17900,7 +18082,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -17912,7 +18094,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -18042,7 +18224,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -18053,7 +18235,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -18409,7 +18591,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -18420,7 +18602,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -18771,7 +18953,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -18782,7 +18964,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -19115,7 +19297,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -19144,7 +19326,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -19610,7 +19792,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -19740,7 +19922,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -19839,7 +20021,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -19944,7 +20126,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -20049,14 +20231,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -20191,7 +20373,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -20349,7 +20531,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -20464,7 +20646,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -20585,14 +20767,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -20874,7 +21056,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -21032,7 +21214,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -21147,7 +21329,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -21268,14 +21450,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -21411,7 +21593,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -21422,7 +21604,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -21580,7 +21762,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -21695,14 +21877,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -21816,7 +21998,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -21937,14 +22119,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -22215,7 +22397,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -22500,7 +22682,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -22743,7 +22925,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -22864,7 +23046,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -23106,7 +23288,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -23118,7 +23300,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -23264,7 +23446,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -23275,7 +23457,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -23679,7 +23861,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -23690,7 +23872,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -24089,7 +24271,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -24100,7 +24282,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -24481,7 +24663,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -24510,7 +24692,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -25040,7 +25222,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -25186,7 +25368,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -25301,7 +25483,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -25422,7 +25604,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -25543,14 +25725,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -25685,7 +25867,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -25843,7 +26025,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -25958,7 +26140,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -26079,14 +26261,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -26320,7 +26502,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -26430,7 +26612,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -26497,7 +26679,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -26570,14 +26752,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -26665,7 +26847,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -26676,7 +26858,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -26786,7 +26968,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -26853,14 +27035,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -26926,7 +27108,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -26999,14 +27181,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -27181,7 +27363,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -27370,7 +27552,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 18, column_index: 8, rotation: Rotation( 1, @@ -27517,7 +27699,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -27590,7 +27772,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -27855,7 +28037,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 6, column_type: Advice, }, Rotation( @@ -27864,16 +28046,16 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 7, column_type: Advice, }, Rotation( - -1, + 1, ), ), ( Column { - index: 7, + index: 8, column_type: Advice, }, Rotation( @@ -27882,7 +28064,7 @@ PinnedVerificationKey { ), ( Column { - index: 8, + index: 9, column_type: Advice, }, Rotation( @@ -27891,7 +28073,7 @@ PinnedVerificationKey { ), ( Column { - index: 6, + index: 9, column_type: Advice, }, Rotation( @@ -27900,7 +28082,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 6, column_type: Advice, }, Rotation( @@ -27909,11 +28091,11 @@ PinnedVerificationKey { ), ( Column { - index: 6, + index: 1, column_type: Advice, }, Rotation( - 1, + -1, ), ), ( @@ -28313,7 +28495,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 16, + query_index: 19, column_index: 9, rotation: Rotation( 1, @@ -28673,7 +28855,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 18, + query_index: 17, column_index: 7, rotation: Rotation( 1, @@ -28887,15 +29069,15 @@ PinnedVerificationKey { (0x3a83a8e762ebade712aa5cf3c41c730a79369475085bf1155579f7f7682408e2, 0x25b00d3ee1da9a6bbd36b35ba461da45abd931c767b863ec4a604f8ce094e4eb), (0x1caeb4d7ebb44a717f83ee5afd35446a5e2124f6a4075342ba4eff589523fb57, 0x3a8c431a13632a5b5f035eb4b804d37f2591e84d05d765ba3f70a3d61b907ebb), (0x107d95a6361fc98df9042f32451faa4fd48c1381653be7847d97cf997a55a4ad, 0x31ebf6a2e352108bb180c3278e72d88bb5bab723d3b38aa47c144fc37fb8a962), - (0x340633bc671d4839c9245701bd7877dffa14caa8516fc2b2d97ab743abff31b2, 0x2d44e13f4cbd8767746e33ca3780ca730de2e81c68fd2eac2856405c810ea835), - (0x0686df606b54c901940689a81e292bbf35653bed36d07d565e6c1bb2f04f7f16, 0x109273b534b0bcdf7d3b651b87631202e692e9799f300b93bdde0c1084644f98), - (0x3b5c55541e5ecbed649a67e81c69ecf846b0d8bb5b3fb0dca7cc855508a60291, 0x2c2d977d9db18dac2bfeb6863e04603fbe577260b77d83de7a40440d0d7e96e0), - (0x377b4690b84709cca9b5f7557a4946907582090395704a279bc3d0474649649c, 0x19d8a463645acaf5e80a0eae028da3175fe3fd07a8afa7b357266951fabf15a2), - (0x01b35d8bd7fff98c6eca9e68b04159d9e04c8c97ee823cbfb25c72759a0f1bff, 0x2f690ea00d11748a56994db1d5086cc14feb4e182950aa3bd78a5e7c39f1c438), - (0x14322512145256db0a887e0d44cb0ca576d199cd60dd6c0fc592974f5bfc982c, 0x14f0d717d83c30687335f599f0e0b313e1f908d8cb539273271d61b6c0c7a977), - (0x2cfd5a6eebaf22de42df01c35ea51d5149528799a4dae214ff5ea4964384549a, 0x0241a066241ababd11a9d336f30a68d2eb40b15a1a74ce7ebb8284818341195f), - (0x1a104a92aae262af0c12ae8e460b8a050d0609236881b44523a51ade8d58fb59, 0x1b4826150f81242668cdf5ac67894f1aaa4f958b4e26af911fcca643c4cd5265), - (0x1973139bb6cfd1f498c01fda7934f1b9954a52bb7e3778814745f73a03f1ec21, 0x0984409ed6f0dfbf0b25a658c4838327096519bd700e0b7ccd69528d971da6d4), + (0x23d190a42430492732de147e7560ae1387a0e8c6b0dc405b893c99c34d124152, 0x0f7f1cb9cd7c701f22270a68d9cb484b4fffdc6144c8ce3f4eca5b646f8a939f), + (0x2b0f9d7b69e1f353868a4d542b7a23f24f39335b16c3a46fca1edb12a69bb350, 0x1e4ac9f6f6d4ba4fa4cd21e669b8293e3be8c143c795d2eb31503a9389ad4314), + (0x28f1ed28efc008bcec444c440ddbe60a8e58fe5b9a6047f0bf4d8abf599cc4ed, 0x180eef569a332ec094a76dd55de8f8ef4f087465bb2abc8dd5f7a265e048e84f), + (0x36608273abc0c47131ee4cb410b4e936fe693e9e034c686e188438d5eab134cd, 0x304e3ffef142c51a5a081a977f9c2581fa18a356e080d20cf10a044e46a3c802), + (0x355228aaa5e1134d08305d64d86cca7abac7c4114252a2a71df6a40d6a3633a9, 0x2d492e1c28cf94f9a074b14cb4cfd0cabd46121faa034d887c5f07cb743464e2), + (0x31fe923865ff58a9e59393bf64ebff3f25831371afbd2de5ddf147519ad6160a, 0x30449e9123aee5a61d3ed4c9e5822e2f60184a6c4234cfd61575e9f9572f370e), + (0x0e24cddb59a4615d0595e5439fca547a3f1ed39c4a2b0879d7e8603306d9e4b5, 0x35ab4acd6912b9bc66c19ebc9845886a4828bac17246137e36f924df2f9be175), + (0x3bd9f4407fcbb3e4ec812de2c53e70fb9203381f5a1c0f4c5e5fa52b932f5ac1, 0x06d8356f6b642427ddfad6e3642e40c0b29034baf9adb19c8a3ab251b16f39ef), + (0x21e3606f857180611036daa84bee713ff0b360b6282adc5bbaa40a5f6f7e6bc7, 0x3bff3cd61a5ae314f5eead93e3084c60a31e8b794186061a24ffa5a5dcd7e0f5), (0x3c0f3f0d7b2306490dac7d578d4846c63adcc76988ce322d8691c3b8b5b0f623, 0x12d81ca672a1c18f6e0d9b7eb8fbabdbe450fae6667cf349c1a0e63ca9a0824e), (0x27d13b33003ffddcd36efb731fe94db93d181bd994e0c057e945402bc8501789, 0x0e1dde94ea3b35e0d0a66350163ba2ff9dd5070500912b7d076747816965ffd2), (0x3049e9c8a3e6c7fe628660121f04915e03546b7a2dcb8a3e59fa99546e4f7f86, 0x2dcebc740917584f788b776f4cf1e3cd96b4a29e9df7224fd8e5f428d4112546), @@ -28903,32 +29085,32 @@ PinnedVerificationKey { (0x1751912a19fa0009ece61b686342d6b4385415e942159e8db3f174ad24d612b9, 0x0f31114ef566211d46914d0bc2d1a27a0e34eeda04dab53a0af7a37024f057a1), (0x091c6c4854fa5d9ed8a966f2a1c4946b41f6872de6c19fa8b521a0a8eb2bd899, 0x29100b4e15344d750fae4a81c82faca1e8e0573336b1f54b394946e95e7baad0), (0x1a5bb6ffd1af2165203df63414021a531f0f2bfcec85443a180993cc222b40af, 0x0d6b8b0d2363607d15746434b670008845ed0524406c1d8a221cb6f58ee2d4ed), - (0x3b31f6e48472e06a9f21145e3a37744fa0ceb6188485ce44b1a131ae47661e17, 0x382d47f03a6703a3018d8582a6123e0e61c549d695f1e2a40bb578bc2ca0e6f2), + (0x0e3ead6853e036099146875357a97c73327ac7aac89df7af91e8e126cf1adb3d, 0x16e19a920aa5d52ec2bb18e595b12cc3f65ae6703af8c088c3741ec59acdde8a), (0x34c8b83a2cc924f1b0237978c8f911e6a54375c509ba46456a011fbb74c8698c, 0x260cc681c222535c0030f702172ee8855b681c16d706b1b9a786165e06705de6), - (0x1b7a61e8a9b32fe558433feec9aaf51204e5486aa468d7215087ed35fd6ecbe5, 0x1f36dc6852f92c141ba800f721d079ffc553c7449b85d16e7487e0c3009c7835), + (0x3dcb136a22551e524212c0325331a9dae5ad6ff356175e6b82a54039475be1ef, 0x3bbbd0d20ea0ebb0f36d740910947d1934bcb93ba16325ea42f124ec0cde7a81), (0x3bb657ca32617e6242b6c6a0b166a1db205024d0441d091b8d45fb478cd4782c, 0x3189ce1b97103345fc0eafd287eed80ab186151171f22af2c9befc71a0957529), (0x25578b0a6d546cf38dc84329fad41e59690a2bd94a0db5fddb42e0db8c267827, 0x03448e4552625dda62a96318bcafcc305deafd6a028f8379d8c8d9ffa0f86e64), (0x30d1828d7463255ad75b39ee4c718de05a762c45c5d717d059496fe05d1575b4, 0x0a8eb70a9b252ee9ee57b29e4dab191cbb29665821830b2ab60fdd5d3414de45), - (0x21c6cc32a998a56e0184238756f9bc06c034326644fa797d58d37a4ce04862ad, 0x0a3215ded9e38470be699055ba4776fda0751bc3d0b893e49c71f2817e12c354), - (0x2b8641a13009b6e2c57fb902961c97d5a37fe9e7012c48a27e644ab86c6e798c, 0x31dc90911a15d74e74ad51ac80cbfca12b1eb06038bb3d5aecc0498c5bd5ff68), - (0x10b4ec889583134fa09dc3e6f0fac585f2dbf6dddcc1eea2c95bab4b8de05be5, 0x0eb4092d1a27658602828702d73145b842f9dbe4b113b61b10049ebe406d625c), - (0x0b9493ff319556d1792c2b1ccef1c52d6097620601b22c8a6cc9f3da9608a3df, 0x098fabd4f3443138f8c72fa5991a7012266cd3d574a65083a611688aec7c631d), - (0x2574aa02cd03503fc37ade3434a4d426f97f94e5f98ae5ea8f3d1324589670a5, 0x22b31bec6726ce49ea837dc05d3576d2e71536ada0d7db4efcd06c34b2129e2c), + (0x1bdd262015bc4b15fd90dcb6dea748cb9032fed094df3edfc0ca96c419c6ea9f, 0x28bad5ad4461b66303cb84925b54258e27953e8ef5e67c1057c823091a8562b9), + (0x09e15af05d50016fd1c475fbd3ae0be95289f239f13962f755f8b39732c73feb, 0x03760949d5057f33c30391474cbc3d447858da57e8b72487a98827b339993e60), + (0x0460fc7f74c9808eea035e8df3ac031c2d05ecafd8f0189f2d6ddac3274752fb, 0x2bc99ad7317625f1a1d6bca1781557b87e8b9976cdcaf994c827a0087d1ce182), + (0x31b7012d949d0668d34cb20200d4e159262aa0dd92114d3aa5e8aa84af51a802, 0x2eb9c55ed473e18e62dc273a8606f955690a984551fbc38e80d65199ab8d0c3d), + (0x33dced988c6a1d40aff3da1710a0e36a6b787fd6dae51ebe3dda7835c2dbea15, 0x3b54a967115d43feccf77c385dcfc6e89f30343457bc8921e017c930a381b5b0), ], permutation: VerifyingKey { commitments: [ - (0x09d1106babba44f67eace95337e3b9916cf02d0b143d5993cf212ba4fa6e2d81, 0x2046a60feac842a629a24189de9d914da26b2254440c142cf851f6d4d5c586a4), - (0x26086868fee3f97d3171042e8ad377782aa845dd3e5c6c86f5d1251b41b8ff03, 0x2f60015e46a7e2bc0e30413be4782c648ec5e9dedc92ce9052fd2857a779a4cd), - (0x00d54c6162e5654355cbaa6951f86836cea891242793df30e4ae74d522747d01, 0x0f9d6c7108000d07ff766c16757c7a02cc8bcaa1ce3001c476bda543db4b52fb), - (0x131a626c24a64b23cb9a554921462f8b3848294a5a12110528b11362fe80f59c, 0x3e8076404262e3d7b5a6d2a3dbdf0fb151e2f3fe4a9239365dfd63853bfd8b8d), - (0x00aae2c83a8cb88fd04c9c631ea69362f38d41688624f519c6aab8fb15110931, 0x0294f0e5b376a7bc9fd190f34c00201c0ffa2a019148d27e1a578effba915450), - (0x2022cd25023adefba897a064d43365c59df92f547eea992189040ecf23eb1b89, 0x2d5ada0189acf8d400ed967e8537e7de7979d2bd6ad5430aa009e200edcad889), - (0x30e4290b63621db78bfadf242ac8a940179ddd601127f4fe05df818dda0de8b5, 0x13ab4dd58054df7dc7c4e59fcf5745373889113fccc60d8a79957dcbc4a1a79e), - (0x17ee4b08749d802b2cb5a8d72df1d27c4a521293347698bac389f473f573888f, 0x19efafbfa1bc8c4e62cb0d8893905ac7a30da08a9ffc18ac26f741c6419f2fe1), - (0x1a5804444e8f54cdff0f38ee9fc051672b5fcb0cf39cc608e20db884c18c2ae0, 0x11b297659614cacbc3fe5b6b8506d7b31d04ec061329c791714478f480215263), - (0x22bbc74dac7b42add29982d2d276b548b38b2fdc8628d4fd331f5d09cae93881, 0x0808f95123e9339e6643594561b28d0a4b6d7d52bdf0b60e3ab698336cfefe06), - (0x07201f37d78f79f85a69d9333e60682fd709fcb7b9fbc843d0baef7885a79246, 0x3b01c7b445dd60b44309c172d55cd2bfed068fa420f8c2cbf316eac3bda6985b), - (0x3998aad0ccd62e9339c4ca91363bec2524ec945bb780efd9984fec68b4f51efb, 0x32cdaa4c65f29fa0675df2196f3190b849dd1dc4a48d615602e57b282cb34673), + (0x01b2f977b5e96e2d00052aa77013b4a7522b714ed1265e5b761a90add04a677d, 0x06ae5604d2abf710e3720ab4ca37bc7a75cec4772624973990fe7acb95d2b90e), + (0x3487595fd169aea1e2055c38daf7b83a923600084a12f6beb068e9ef0886884b, 0x2094e9bc4aead08e32eb63939e7b365f7c4dbe7bb9e4fe439fe7855da2a8ef59), + (0x34b7b5583a32b3a2a188214b041b0402948759fbdf47b4b50421905728b78148, 0x10fafdf7f63a938d87eb031cbe61c6dd5915612ecb71865e94a7d7fdcb96f9c8), + (0x38b9b1352ef7da340b69e7d152d86c26abaa7eb8da2b2049c75eb908bc42dae1, 0x2b7880c4c7790b2bd4f603a95561e7e1f4fba95eba4096f6d44b89e4b0a16519), + (0x08b55ac77535aa391210533786aa9a62215fe2cb6950b60dde6563f8c4f47d58, 0x1ca42aafc1ae6e8554a933225daae97222e08a59c866024a936f66e45455c47b), + (0x3b23fca8ae9ee4f186c654428419b16169777a1b5cf7e959f73de3fd21cf1403, 0x3ff330b5247e4a88c38452e3bbaf20c79cff67a4a5b91c5ac3c6614d8cc17119), + (0x39c00327041f3b0a21cc10acacd55a94f968770121fb55e8bee01e146ea024a1, 0x38c3af47f4278d74e808aeecaf9407b17757384e9d50b59500604c7bb86687cd), + (0x0fe245acf5779d18b38c28fd4f6d921bb5487579d1fd257b7ea48f8d6de2db2f, 0x1f8a5b90451fa159c9c517a0b7250787d86c63555659298bb7ca10c537e94e12), + (0x13f4c48990bdcadf99fc60d63b04eb82f26dc2c59b515f265a66c2732abd0205, 0x20dbafa9a43baccfc5ee6947bc408b1e8974af2f5c141f3f704a747e194f04f0), + (0x16d8e8e787a2dfde1ec419ce969aa5a6c23b9d703a7440a6f085cb1fbbb21a57, 0x217624d76f302eb4f3a4f9bd3968fa79f66e4b06b5bc72048b979fb58b1f29d7), + (0x0f74011b79a40415b90f8f22db1a1433b7336307801cfe97b84f60bf7cb15d44, 0x10f2a0765e05ab426d0b183ad84616438187efbfb6122540d768895324d42667), + (0x2139a7b9a8c74648139b556ae77015620edcc81cf0a89cc960a57e16c4346a0b, 0x0295889e3496dac3174b2ba3c5399b78d9ecf042730cede62d37f6f0bfc021b6), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 7fe92dc3d1d910ff5b4a2044c05f15fa7afb872c..9d541d63f1f5e947978137c33c8705bebd8de2b4 100644 GIT binary patch literal 5250 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 Date: Mon, 29 May 2023 15:06:53 +0300 Subject: [PATCH 30/92] Protect bundle burn from adding assets with zero amount (#60) Prevent the burning of assets with zero value. --- src/builder.rs | 5 +++++ tests/zsa.rs | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 1739ef12d..419b12fe8 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -397,6 +397,11 @@ impl Builder { if asset.is_native().into() { return Err("Burning is only possible for non-native assets"); } + + if value.inner() == 0 { + return Err("Burning is not possible for zero values"); + } + let cur = *self.burn.get(&asset).unwrap_or(&ValueSum::zero()); let sum = (cur + value).ok_or("Orchard ValueSum operation overflowed")?; self.burn.insert(asset, sum); diff --git a/tests/zsa.rs b/tests/zsa.rs index ca8c1b874..b80956ec4 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -508,4 +508,21 @@ fn zsa_issue_and_transfer() { Ok(_) => panic!("Test should fail"), Err(error) => assert_eq!(error, "Burning is only possible for non-native assets"), } + + // 12. Try to burn zero value - should fail + let result = build_and_verify_bundle( + vec![&zsa_spend_1], + vec![TestOutputInfo { + value: zsa_spend_1.note.value(), + asset: zsa_spend_1.note.asset(), + }], + vec![(zsa_spend_1.note.asset(), NoteValue::from_raw(0))], + anchor, + 2, + &keys, + ); + match result { + Ok(_) => panic!("Test should fail"), + Err(error) => assert_eq!(error, "Burning is not possible for zero values"), + } } From bedc732d6fe7b43afa335d6bed64e7897cca0e5f Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 1 Jun 2023 10:15:24 +0200 Subject: [PATCH 31/92] Circuit: Add tests for orchard circuit (#63) Add some positive and negative tests for Orchard circuit --- src/circuit.rs | 241 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 234 insertions(+), 7 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 4db6a9fa7..67833b013 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1188,20 +1188,24 @@ mod tests { use core::iter; use ff::Field; + use group::{Curve, Group, GroupEncoding}; use halo2_proofs::{circuit::Value, dev::MockProver}; use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; - use crate::note::AssetBase; + use crate::builder::SpendInfo; + use crate::note::commitment::NoteCommitTrapdoor; + use crate::note::{AssetBase, Nullifier}; + use crate::primitives::redpallas::VerificationKey; use crate::{ - keys::SpendValidatingKey, - note::Note, + keys::{FullViewingKey, Scope, SpendValidatingKey, SpendingKey}, + note::{Note, NoteCommitment}, tree::MerklePath, - value::{ValueCommitTrapdoor, ValueCommitment}, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, }; - fn generate_circuit_instance(mut rng: R) -> (Circuit, Instance) { + fn generate_dummy_circuit_instance(mut rng: R) -> (Circuit, Instance) { let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); let sender_address = spent_note.recipient(); @@ -1264,7 +1268,7 @@ mod tests { let mut rng = OsRng; let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) - .map(|()| generate_circuit_instance(&mut rng)) + .map(|()| generate_dummy_circuit_instance(&mut rng)) .unzip(); let vk = VerifyingKey::build(); @@ -1378,7 +1382,7 @@ mod tests { let create_proof = || -> std::io::Result<()> { let mut rng = OsRng; - let (circuit, instance) = generate_circuit_instance(OsRng); + let (circuit, instance) = generate_dummy_circuit_instance(OsRng); let instances = &[instance.clone()]; let pk = ProvingKey::build(); @@ -1441,4 +1445,227 @@ mod tests { .render(K, &circuit, &root) .unwrap(); } + + fn check_proof_of_orchard_circuit(circuit: &Circuit, instance: &Instance, should_pass: bool) { + let proof_verify = MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect(), + ) + .unwrap() + .verify(); + if should_pass { + assert!(proof_verify.is_ok()); + } else { + assert!(proof_verify.is_err()); + } + } + + fn generate_circuit_instance( + is_native_asset: bool, + split_flag: bool, + mut rng: R, + ) -> (Circuit, Instance) { + // Create asset + let asset_base = if is_native_asset { + AssetBase::native() + } else { + AssetBase::random(&mut rng) + }; + + // Create spent_note + let (spent_note_fvk, spent_note) = { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + let sender_address = fvk.address_at(0u32, Scope::External); + let rho_old = Nullifier::dummy(&mut rng); + let spent_note = Note::new( + sender_address, + NoteValue::from_raw(40), + asset_base, + rho_old, + &mut rng, + ); + (fvk, spent_note) + }; + + let output_value = NoteValue::from_raw(10); + + let (dummy_sk, fvk, scope, nf_old, v_net) = if split_flag { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + ( + Some(sk), + fvk.clone(), + Scope::External, + spent_note.nullifier(&fvk), + // Split notes do not contribute to v_net. + // Therefore, if split_flag is true, v_net = - output_value + NoteValue::zero() - output_value, + ) + } else { + ( + None, + spent_note_fvk.clone(), + spent_note_fvk + .scope_for_address(&spent_note.recipient()) + .unwrap(), + spent_note.nullifier(&spent_note_fvk), + spent_note.value() - output_value, + ) + }; + let ak: SpendValidatingKey = fvk.clone().into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let output_note = { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + let sender_address = fvk.address_at(0u32, Scope::External); + + Note::new(sender_address, output_value, asset_base, nf_old, &mut rng) + }; + + let cmx = output_note.commitment().into(); + + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(v_net, rcv, asset_base); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let spend_info = SpendInfo { + dummy_sk, + fvk, + scope, + note: spent_note, + merkle_path: path, + split_flag, + }; + + ( + Circuit::from_action_context_unchecked(spend_info, output_note, alpha, rcv), + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + }, + ) + } + + fn random_note_commitment(mut rng: impl RngCore) -> NoteCommitment { + NoteCommitment::derive( + pallas::Point::random(&mut rng).to_affine().to_bytes(), + pallas::Point::random(&mut rng).to_affine().to_bytes(), + NoteValue::from_raw(rng.next_u64()), + AssetBase::random(&mut rng), + pallas::Base::random(&mut rng), + pallas::Base::random(&mut rng), + NoteCommitTrapdoor(pallas::Scalar::random(&mut rng)), + ) + .unwrap() + } + + #[test] + fn orchard_circuit_negative_test() { + let mut rng = OsRng; + + for is_native_asset in [true, false] { + for split_flag in [true, false] { + let (circuit, instance) = + generate_circuit_instance(is_native_asset, split_flag, &mut rng); + + check_proof_of_orchard_circuit(&circuit, &instance, true); + + // Set cv_net to zero + // The proof should fail + let instance_wrong_cv_net = Instance { + anchor: instance.anchor, + cv_net: ValueCommitment::from_bytes(&[0u8; 32]).unwrap(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_cv_net, false); + + // Set rk_pub to dummy VerificationKey + // The proof should fail + let instance_wrong_rk = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: VerificationKey::dummy(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_rk, false); + + // Set cm_old to random NoteCommitment + // The proof should fail + let circuit_wrong_cm_old = Circuit { + path: circuit.path, + pos: circuit.pos, + g_d_old: circuit.g_d_old, + pk_d_old: circuit.pk_d_old, + v_old: circuit.v_old, + rho_old: circuit.rho_old, + psi_old: circuit.psi_old, + rcm_old: circuit.rcm_old.clone(), + cm_old: Value::known(random_note_commitment(&mut rng)), + alpha: circuit.alpha, + ak: circuit.ak.clone(), + nk: circuit.nk, + rivk: circuit.rivk, + g_d_new: circuit.g_d_new, + pk_d_new: circuit.pk_d_new, + v_new: circuit.v_new, + psi_new: circuit.psi_new, + rcm_new: circuit.rcm_new.clone(), + rcv: circuit.rcv, + asset: circuit.asset, + split_flag: circuit.split_flag, + }; + check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); + + // Set cmx_pub to random NoteCommitment + // The proof should fail + let instance_wrong_cmx_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: random_note_commitment(&mut rng).into(), + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_cmx_pub, false); + + // If split_flag=0, set nf_old_pub to random Nullifier + // The proof should fail + if !split_flag { + let instance_wrong_nf_old_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net, + nf_old: Nullifier::dummy(&mut rng), + rk: instance.rk, + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); + } + } + } + } } From 32eee6e0838d20c392d2b2710840b61c6ea23ebf Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 6 Jun 2023 08:46:52 +0200 Subject: [PATCH 32/92] Do not create split notes with native asset (#65) Due to privacy considerations, we might incorporate dummy or split notes while generating a bundle. However, to maintain consistency with the previous version, we choose not to include split notes for native asset. In addition, we use a new dummy/split notes for each extend in order to have different nullifiers. --- src/builder.rs | 49 ++++++++++++++++++++++++++++++++++++++++-------- tests/zsa.rs | 51 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 81 insertions(+), 19 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 419b12fe8..2b9729c0c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -167,9 +167,28 @@ impl SpendInfo { } } - /// Return a copy of this note with the split flag set to `true`. - fn create_split_spend(&self) -> Self { - SpendInfo::new(self.fvk.clone(), self.note, self.merkle_path.clone(), true).unwrap() + /// Creates a split spend, which is identical to origin normal spend except that we use a random + /// fvk to generate a different nullifier. In addition, the split_flag is raised. + /// + /// Defined in [Transfer and Burn of Zcash Shielded Assets ZIP-0226 § Split Notes (DRAFT PR)][TransferZSA]. + /// + /// [TransferZSA]: https://qed-it.github.io/zips/zip-0226.html#split-notes + fn create_split_spend(&self, rng: &mut impl RngCore) -> Self { + let note = self.note; + let merkle_path = self.merkle_path.clone(); + + let sk = SpendingKey::random(rng); + let fvk: FullViewingKey = (&sk).into(); + + SpendInfo { + dummy_sk: Some(sk), + fvk, + // We use external scope to avoid unnecessary derivations + scope: Scope::External, + note, + merkle_path, + split_flag: true, + } } } @@ -467,12 +486,12 @@ impl Builder { .cloned() .unwrap(); - // use the first spend to create split spend(s) or create a dummy if empty. - let dummy_spend = spends.first().map_or_else( - || SpendInfo::dummy(asset, &mut rng), - |s| s.create_split_spend(), + let first_spend = spends.first().cloned(); + + spends.extend( + iter::repeat_with(|| pad_spend(first_spend.as_ref(), asset, &mut rng)) + .take(num_actions - num_spends), ); - spends.extend(iter::repeat_with(|| dummy_spend.clone()).take(num_actions - num_spends)); // Extend the recipients with dummy values. recipients.extend( @@ -574,6 +593,20 @@ fn partition_by_asset( hm } +/// Returns a dummy/split notes to extend the spends. +fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) -> SpendInfo { + if asset.is_native().into() { + // For native asset, extends with dummy notes + SpendInfo::dummy(asset, &mut rng) + } else { + // For ZSA asset, extends with + // - dummy notes if first spend is empty + // - split notes otherwise. + let dummy = SpendInfo::dummy(asset, &mut rng); + spend.map_or_else(|| dummy, |s| s.create_split_spend(&mut rng)) + } +} + /// Marker trait representing bundle signatures in the process of being created. pub trait InProgressSignatures: fmt::Debug { /// The authorization type of an Orchard action in the process of being authorized. diff --git a/tests/zsa.rs b/tests/zsa.rs index b80956ec4..cbda7fc19 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -261,9 +261,25 @@ fn build_and_verify_bundle( // Verify the shielded bundle, currently without the proof. verify_bundle(&shielded_bundle, &keys.vk, true); assert_eq!(shielded_bundle.actions().len(), expected_num_actions); + assert!(verify_unique_spent_nullifiers(&shielded_bundle)); Ok(()) } +fn verify_unique_spent_nullifiers(bundle: &Bundle) -> bool { + let mut unique_nulifiers = Vec::new(); + let spent_nullifiers = bundle + .actions() + .iter() + .map(|action| *action.nullifier()) + .collect::>(); + spent_nullifiers.iter().enumerate().all(|(i, item)| { + unique_nulifiers.push(*item); + // Check if the item is already in the unique_nullifiers vector by checking that the first + // position of the item is equal to the current index i. + unique_nulifiers.iter().position(|x| x == item) == Some(i) + }) +} + /// Issue several ZSA and native notes and spend them in different combinations, e.g. split and join #[test] fn zsa_issue_and_transfer() { @@ -315,23 +331,28 @@ fn zsa_issue_and_transfer() { ) .unwrap(); - // 2. Split single ZSA note into 2 notes - let delta = 2; // arbitrary number for value manipulation + // 2. Split single ZSA note into 3 notes + let delta_1 = 2; // arbitrary number for value manipulation + let delta_2 = 5; // arbitrary number for value manipulation build_and_verify_bundle( vec![&zsa_spend_1], vec![ TestOutputInfo { - value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta), + value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta_1 - delta_2), asset: zsa_spend_1.note.asset(), }, TestOutputInfo { - value: NoteValue::from_raw(delta), + value: NoteValue::from_raw(delta_1), + asset: zsa_spend_1.note.asset(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_2), asset: zsa_spend_1.note.asset(), }, ], vec![], anchor, - 2, + 3, &keys, ) .unwrap(); @@ -357,11 +378,11 @@ fn zsa_issue_and_transfer() { vec![&zsa_spend_1, &zsa_spend_2], vec![ TestOutputInfo { - value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta), + value: NoteValue::from_raw(zsa_spend_1.note.value().inner() - delta_1), asset: zsa_spend_1.note.asset(), }, TestOutputInfo { - value: NoteValue::from_raw(zsa_spend_2.note.value().inner() + delta), + value: NoteValue::from_raw(zsa_spend_2.note.value().inner() + delta_1), asset: zsa_spend_2.note.asset(), }, ], @@ -401,13 +422,21 @@ fn zsa_issue_and_transfer() { asset: zsa_spend_1.note.asset(), }, TestOutputInfo { - value: native_spend.note.value(), + value: NoteValue::from_raw(native_spend.note.value().inner() - delta_1 - delta_2), + asset: AssetBase::native(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_1), + asset: AssetBase::native(), + }, + TestOutputInfo { + value: NoteValue::from_raw(delta_2), asset: AssetBase::native(), }, ], vec![], native_anchor, - 4, + 5, &keys, ) .unwrap(); @@ -450,11 +479,11 @@ fn zsa_issue_and_transfer() { vec![&zsa_spend_t7_1, &zsa_spend_t7_2], vec![ TestOutputInfo { - value: NoteValue::from_raw(zsa_spend_t7_1.note.value().inner() + delta), + value: NoteValue::from_raw(zsa_spend_t7_1.note.value().inner() + delta_1), asset: zsa_spend_t7_1.note.asset(), }, TestOutputInfo { - value: NoteValue::from_raw(zsa_spend_t7_2.note.value().inner() - delta), + value: NoteValue::from_raw(zsa_spend_t7_2.note.value().inner() - delta_1), asset: zsa_spend_t7_2.note.asset(), }, ], From 02fa582c80c6aef05e7790621ba7599085d5d25c Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 6 Jun 2023 12:40:06 +0200 Subject: [PATCH 33/92] Global padding for bundle (#67) Each bundle must contain at least two actions for privacy concerns. Previously, we pad bundle to have at least two actions per asset. Now, we pad bundle globally, and add dummy/split actions to have at least two actions per bundle. --- src/builder.rs | 22 +++++++++++++++++----- tests/zsa.rs | 8 ++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 2b9729c0c..fa7c2f93a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -464,6 +464,18 @@ impl Builder { i64::try_from(value_balance).and_then(|i| V::try_from(i).map_err(|_| value::OverflowError)) } + /// Returns the number of actions to add to this bundle in order to contain at least MIN_ACTION actions. + fn num_missing_actions(&self) -> usize { + let num_actions = [self.spends.len(), self.recipients.len()] + .iter() + .max() + .cloned() + .unwrap(); + (num_actions < MIN_ACTIONS) + .then(|| MIN_ACTIONS - num_actions) + .unwrap_or(0) + } + /// Builds a bundle containing the given spent notes and recipients. /// /// The returned bundle will have no proof or signatures; these can be applied with @@ -480,11 +492,11 @@ impl Builder { { let num_spends = spends.len(); let num_recipients = recipients.len(); - let num_actions = [num_spends, num_recipients, MIN_ACTIONS] - .iter() - .max() - .cloned() - .unwrap(); + let mut num_actions = [num_spends, num_recipients].iter().max().cloned().unwrap(); + // We might have to add dummy/split actions only for the first asset to reach MIN_ACTIONS. + pre_actions + .is_empty() + .then(|| num_actions += self.num_missing_actions()); let first_spend = spends.first().cloned(); diff --git a/tests/zsa.rs b/tests/zsa.rs index cbda7fc19..17c0a4b60 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -408,7 +408,7 @@ fn zsa_issue_and_transfer() { ], vec![], anchor, - 4, + 2, &keys, ) .unwrap(); @@ -436,7 +436,7 @@ fn zsa_issue_and_transfer() { ], vec![], native_anchor, - 5, + 4, &keys, ) .unwrap(); @@ -468,7 +468,7 @@ fn zsa_issue_and_transfer() { ], vec![], anchor_t7, - 4, + 2, &keys, ) .unwrap(); @@ -489,7 +489,7 @@ fn zsa_issue_and_transfer() { ], vec![], anchor_t7, - 4, + 2, &keys, ) .unwrap(); From 9965a6d06b64f71de5a2a9b23fa044f137e2aed6 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 6 Jun 2023 17:11:27 +0200 Subject: [PATCH 34/92] Add serialization of finalize flag (#68) Add a function `flags` to serialize the `finalize` flag of an IssueAction to a byte. This function will be used by the client. --- src/issuance.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/issuance.rs b/src/issuance.rs index af243358e..88719eb72 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -61,6 +61,23 @@ impl IssueAction { } } + /// Constructs a new `IssueAction`. + pub fn new_with_finalize(asset_desc: String, note: &Note, flags: u8) -> Option { + let finalize = match flags { + 0b0000_0000 => false, + 0b0000_0001 => true, + _ => return None, + }; + Some(IssueAction { + asset_desc, + notes: NonEmpty { + head: *note, + tail: vec![], + }, + finalize, + }) + } + /// Constructs an `IssueAction` from its constituent parts. pub fn from_parts(asset_desc: String, notes: NonEmpty, finalize: bool) -> Self { IssueAction { @@ -134,6 +151,11 @@ impl IssueAction { .then(|| Ok((asset, AssetSupply::new(value_sum, self.is_finalized())))) .ok_or(IssueBundleIkMismatchAssetBase)? } + + /// Serialize `finalize` flag to a byte + pub fn flags(&self) -> u8 { + self.finalize.then(|| 0b0000_0001).unwrap_or(0b0000_0000) + } } /// Defines the authorization type of an Issue bundle. @@ -1272,6 +1294,23 @@ mod tests { WrongAssetDescSize ); } + + #[test] + fn test_finalize_flag_serialization() { + let mut rng = OsRng; + let (_, _, note) = Note::dummy(&mut rng, None, AssetBase::native()); + + let action = + IssueAction::new_with_finalize(String::from("Asset description"), ¬e, 0u8).unwrap(); + assert_eq!(action.flags(), 0b0000_0000); + + let action = + IssueAction::new_with_finalize(String::from("Asset description"), ¬e, 1u8).unwrap(); + assert_eq!(action.flags(), 0b0000_0001); + + let action = IssueAction::new_with_finalize(String::from("Asset description"), ¬e, 2u8); + assert!(action.is_none()); + } } /// Generators for property testing. From 7ad2bacf5d5e261634d6f5076d88c30630e5cf87 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 12 Jun 2023 17:20:20 +0200 Subject: [PATCH 35/92] Fix IssueBundle and IssueAction structures (#70) The vector of issue actions in an IssueBundle must not be empty. The vector of notes in an IssueAction could be empty when `finalize` is set to true. We could add some actions in an `IssueAction` even if `finalize` is set to true. Only the next block is affected by the `finalize` flag, not the current block. --- src/issuance.rs | 646 +++++++++++++++++++++++------------------------- tests/zsa.rs | 26 +- 2 files changed, 330 insertions(+), 342 deletions(-) diff --git a/src/issuance.rs b/src/issuance.rs index 88719eb72..d312b0dbe 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -7,8 +7,8 @@ use std::fmt; use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; use crate::issuance::Error::{ - IssueActionAlreadyFinalized, IssueActionIncorrectAssetBase, IssueActionNotFound, - IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, + IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, + IssueActionWithoutNoteNotFinalized, IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, ValueSumOverflow, WrongAssetDescSize, }; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; @@ -30,7 +30,7 @@ pub struct IssueBundle { /// The issuer key for the note being created. ik: IssuanceValidatingKey, /// The list of issue actions that make up this bundle. - actions: Vec, + actions: NonEmpty, /// The authorization for this action. authorization: T, } @@ -43,26 +43,23 @@ pub struct IssueAction { /// Asset description for verification. asset_desc: String, /// The newly issued notes. - notes: NonEmpty, + notes: Vec, /// `finalize` will prevent further issuance of the same asset type. finalize: bool, } -impl IssueAction { - /// Constructs a new `IssueAction`. - pub fn new(asset_desc: String, note: &Note) -> Self { - IssueAction { - asset_desc, - notes: NonEmpty { - head: *note, - tail: vec![], - }, - finalize: false, - } - } +/// The parameters required to add a Note into an IssueAction. +#[derive(Debug)] +pub struct IssueInfo { + /// The recipient of the funds. + pub recipient: Address, + /// The value of this note. + pub value: NoteValue, +} +impl IssueAction { /// Constructs a new `IssueAction`. - pub fn new_with_finalize(asset_desc: String, note: &Note, flags: u8) -> Option { + pub fn new_with_flags(asset_desc: String, notes: Vec, flags: u8) -> Option { let finalize = match flags { 0b0000_0000 => false, 0b0000_0001 => true, @@ -70,16 +67,13 @@ impl IssueAction { }; Some(IssueAction { asset_desc, - notes: NonEmpty { - head: *note, - tail: vec![], - }, + notes, finalize, }) } /// Constructs an `IssueAction` from its constituent parts. - pub fn from_parts(asset_desc: String, notes: NonEmpty, finalize: bool) -> Self { + pub fn from_parts(asset_desc: String, notes: Vec, finalize: bool) -> Self { IssueAction { asset_desc, notes, @@ -93,7 +87,7 @@ impl IssueAction { } /// Returns the issued notes. - pub fn notes(&self) -> &NonEmpty { + pub fn notes(&self) -> &Vec { &self.notes } @@ -121,35 +115,39 @@ impl IssueAction { /// /// This function may return an error in any of the following cases: /// - /// * `IssueActionIncorrectAssetBase`: If the asset type of any note in the `IssueAction` is - /// not equal to the asset type of the first note. - /// /// * `ValueSumOverflow`: If the total amount value of all notes in the `IssueAction` overflows. /// /// * `IssueBundleIkMismatchAssetBase`: If the provided `ik` is not used to derive the /// `AssetBase` for **all** internal notes. + /// + /// * `IssueActionWithoutNoteNotFinalized`:If the `IssueAction` contains no note and is not finalized. fn verify_supply(&self, ik: &IssuanceValidatingKey) -> Result<(AssetBase, AssetSupply), Error> { + if self.notes.is_empty() && !self.is_finalized() { + return Err(IssueActionWithoutNoteNotFinalized); + } + + let issue_asset = AssetBase::derive(ik, &self.asset_desc); + // Calculate the value of the asset as a sum of values of all its notes - // and ensure all note types are equal - let (asset, value_sum) = self.notes.iter().try_fold( - (self.notes().head.asset(), ValueSum::zero()), - |(asset, value_sum), ¬e| { - // All assets should have the same `AssetBase` + // and ensure all note types are equal the asset derived from asset_desc and ik. + let value_sum = self + .notes + .iter() + .try_fold(ValueSum::zero(), |value_sum, ¬e| { + // All assets should be derived correctly note.asset() - .eq(&asset) + .eq(&issue_asset) .then(|| ()) - .ok_or(IssueActionIncorrectAssetBase)?; + .ok_or(IssueBundleIkMismatchAssetBase)?; // The total amount should not overflow - Ok((asset, (value_sum + note.value()).ok_or(ValueSumOverflow)?)) - }, - )?; + (value_sum + note.value()).ok_or(ValueSumOverflow) + })?; - // Return the asset and its supply (or an error if the asset was not properly derived) - asset - .eq(&AssetBase::derive(ik, &self.asset_desc)) - .then(|| Ok((asset, AssetSupply::new(value_sum, self.is_finalized())))) - .ok_or(IssueBundleIkMismatchAssetBase)? + Ok(( + issue_asset, + AssetSupply::new(value_sum, self.is_finalized()), + )) } /// Serialize `finalize` flag to a byte @@ -199,7 +197,7 @@ impl IssueBundle { &self.ik } /// Return the actions for a given `IssueBundle`. - pub fn actions(&self) -> &Vec { + pub fn actions(&self) -> &NonEmpty { &self.actions } /// Return the notes from all actions for a given `IssueBundle`. @@ -238,7 +236,7 @@ impl IssueBundle { /// Constructs an `IssueBundle` from its constituent parts. pub fn from_parts( ik: IssuanceValidatingKey, - actions: Vec, + actions: NonEmpty, authorization: T, ) -> Self { IssueBundle { @@ -251,27 +249,77 @@ impl IssueBundle { impl IssueBundle { /// Constructs a new `IssueBundle`. - pub fn new(ik: IssuanceValidatingKey) -> IssueBundle { - IssueBundle { - ik, - actions: Vec::new(), - authorization: Unauthorized, + /// + /// If issue_info is None, the new `IssueBundle` will contain one `IssueAction` without notes + /// and with `finalize` set to true. + /// Otherwise, the new `IssueBundle` will contain one `IssueAction with one note created from + /// issue_info values and with `finalize` set to false. In this created note, rho will be + /// randomly sampled, similar to dummy note generation. + /// + /// # Errors + /// + /// This function may return an error in any of the following cases: + /// + /// * `WrongAssetDescSize`: If `asset_desc` is empty or longer than 512 bytes. + pub fn new( + ik: IssuanceValidatingKey, + asset_desc: String, + issue_info: Option, + mut rng: impl RngCore, + ) -> Result<(IssueBundle, AssetBase), Error> { + if !is_asset_desc_of_valid_size(&asset_desc) { + return Err(WrongAssetDescSize); } + + let asset = AssetBase::derive(&ik, &asset_desc); + + let action = match issue_info { + None => IssueAction { + asset_desc, + notes: vec![], + finalize: true, + }, + Some(issue_info) => { + let note = Note::new( + issue_info.recipient, + issue_info.value, + asset, + Nullifier::dummy(&mut rng), + &mut rng, + ); + + IssueAction { + asset_desc, + notes: vec![note], + finalize: false, + } + } + }; + + Ok(( + IssueBundle { + ik, + actions: NonEmpty::new(action), + authorization: Unauthorized, + }, + asset, + )) } /// Add a new note to the `IssueBundle`. /// /// Rho will be randomly sampled, similar to dummy note generation. /// - /// # Panics + /// # Errors /// - /// Panics if `asset_desc` is empty or longer than 512 bytes. + /// This function may return an error in any of the following cases: + /// + /// * `WrongAssetDescSize`: If `asset_desc` is empty or longer than 512 bytes. pub fn add_recipient( &mut self, asset_desc: String, recipient: Address, value: NoteValue, - finalize: bool, mut rng: impl RngCore, ) -> Result { if !is_asset_desc_of_valid_size(&asset_desc) { @@ -288,26 +336,25 @@ impl IssueBundle { &mut rng, ); - match self + let action = self .actions .iter_mut() - .find(|issue_action| issue_action.asset_desc.eq(&asset_desc)) - { - // Append to an existing IssueAction. + .find(|issue_action| issue_action.asset_desc.eq(&asset_desc)); + + match action { Some(action) => { - if action.finalize { - return Err(IssueActionAlreadyFinalized); - }; + // Append to an existing IssueAction. action.notes.push(note); - finalize.then(|| action.finalize = true); } - // Insert a new IssueAction. None => { - let mut action = IssueAction::new(asset_desc, ¬e); - finalize.then(|| action.finalize = true); - self.actions.push(action); + // Insert a new IssueAction. + self.actions.push(IssueAction { + asset_desc, + notes: vec![note], + finalize: false, + }); } - } + }; Ok(asset) } @@ -430,7 +477,6 @@ impl IssueBundle { /// asset in the bundle is incorrect. /// * `IssueActionPreviouslyFinalizedAssetBase`: This error occurs if the asset has already been /// finalized (inserted into the `finalized` collection). -/// * `IssueActionIncorrectAssetBase`: This error occurs if any note has an incorrect note type. /// * `ValueSumOverflow`: This error occurs if an overflow happens during the calculation of /// the value sum for the notes in the asset. /// * `IssueBundleIkMismatchAssetBase`: This error is raised if the `AssetBase` derived from @@ -473,16 +519,14 @@ pub fn verify_issue_bundle( /// Errors produced during the issuance process #[derive(Debug, PartialEq, Eq)] pub enum Error { - /// Unable to add note to the IssueAction since it has already been finalized. - IssueActionAlreadyFinalized, /// The requested IssueAction not exists in the bundle. IssueActionNotFound, - /// Not all `AssetBase`s are the same inside the action. - IssueActionIncorrectAssetBase, /// The provided `isk` and the driven `ik` does not match at least one note type. IssueBundleIkMismatchAssetBase, /// `asset_desc` should be between 1 and 512 bytes. WrongAssetDescSize, + /// The `IssueAction` is not finalized but contains no notes. + IssueActionWithoutNoteNotFinalized, /// Verification errors: /// Invalid signature. @@ -499,18 +543,9 @@ impl std::error::Error for Error {} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - IssueActionAlreadyFinalized => { - write!( - f, - "unable to add note to the IssueAction since it has already been finalized" - ) - } IssueActionNotFound => { write!(f, "the requested IssueAction not exists in the bundle.") } - IssueActionIncorrectAssetBase => { - write!(f, "not all `AssetBase`s are the same inside the action") - } IssueBundleIkMismatchAssetBase => { write!( f, @@ -520,6 +555,12 @@ impl fmt::Display for Error { WrongAssetDescSize => { write!(f, "`asset_desc` should be between 1 and 512 bytes") } + IssueActionWithoutNoteNotFinalized => { + write!( + f, + "this `IssueAction` contains no notes but is not finalized" + ) + } IssueBundleInvalidSignature(_) => { write!(f, "invalid signature") } @@ -538,11 +579,10 @@ impl fmt::Display for Error { #[cfg(test)] mod tests { - use super::{AssetSupply, IssueBundle}; + use super::{AssetSupply, IssueBundle, IssueInfo}; use crate::issuance::Error::{ - IssueActionAlreadyFinalized, IssueActionIncorrectAssetBase, IssueActionNotFound, - IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, - IssueBundleInvalidSignature, WrongAssetDescSize, + IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, + IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, WrongAssetDescSize, }; use crate::issuance::{verify_issue_bundle, IssueAction, Signed}; use crate::keys::{ @@ -551,11 +591,9 @@ mod tests { use crate::note::{AssetBase, Nullifier}; use crate::value::{NoteValue, ValueSum}; use crate::{Address, Note}; - use nonempty::NonEmpty; use rand::rngs::OsRng; use rand::RngCore; use reddsa::Error::InvalidSignature; - use std::borrow::BorrowMut; use std::collections::HashSet; fn setup_params() -> ( @@ -611,14 +649,7 @@ mod tests { ( ik, asset, - IssueAction::from_parts( - note1_asset_desc.into(), - NonEmpty { - head: note1, - tail: vec![note2], - }, - finalize, - ), + IssueAction::from_parts(note1_asset_desc.into(), vec![note1, note2], finalize), ) } @@ -661,7 +692,7 @@ mod tests { assert_eq!( action.verify_supply(&ik), - Err(IssueActionIncorrectAssetBase) + Err(IssueBundleIkMismatchAssetBase) ); } @@ -680,48 +711,55 @@ mod tests { fn issue_bundle_basic() { let (rng, _, ik, recipient, _) = setup_params(); - let mut bundle = IssueBundle::new(ik); - let str = String::from("Halo"); let str2 = String::from("Halo2"); assert_eq!( - bundle - .add_recipient( - String::from_utf8(vec![b'X'; 513]).unwrap(), + IssueBundle::new( + ik.clone(), + String::from_utf8(vec![b'X'; 513]).unwrap(), + Some(IssueInfo { recipient, - NoteValue::unsplittable(), - true, - rng, - ) - .unwrap_err(), + value: NoteValue::unsplittable() + }), + rng, + ) + .unwrap_err(), WrongAssetDescSize ); assert_eq!( - bundle - .add_recipient( - "".to_string(), + IssueBundle::new( + ik.clone(), + "".to_string(), + Some(IssueInfo { recipient, - NoteValue::unsplittable(), - true, - rng, - ) - .unwrap_err(), + value: NoteValue::unsplittable() + }), + rng, + ) + .unwrap_err(), WrongAssetDescSize ); - let asset = bundle - .add_recipient(str.clone(), recipient, NoteValue::from_raw(5), false, rng) - .unwrap(); + let (mut bundle, asset) = IssueBundle::new( + ik, + str.clone(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let another_asset = bundle - .add_recipient(str, recipient, NoteValue::from_raw(10), false, rng) + .add_recipient(str, recipient, NoteValue::from_raw(10), rng) .unwrap(); assert_eq!(asset, another_asset); let third_asset = bundle - .add_recipient(str2.clone(), recipient, NoteValue::from_raw(15), false, rng) + .add_recipient(str2.clone(), recipient, NoteValue::from_raw(15), rng) .unwrap(); assert_ne!(asset, third_asset); @@ -730,53 +768,39 @@ mod tests { let action = bundle.get_action_by_type(asset).unwrap(); assert_eq!(action.notes.len(), 2); - assert_eq!(action.notes.first().value().inner(), 5); - assert_eq!(action.notes.first().asset(), asset); - assert_eq!(action.notes.first().recipient(), recipient); + assert_eq!(action.notes.first().unwrap().value().inner(), 5); + assert_eq!(action.notes.first().unwrap().asset(), asset); + assert_eq!(action.notes.first().unwrap().recipient(), recipient); - assert_eq!(action.notes.tail().first().unwrap().value().inner(), 10); - assert_eq!(action.notes.tail().first().unwrap().asset(), asset); - assert_eq!(action.notes.tail().first().unwrap().recipient(), recipient); + assert_eq!(action.notes.get(1).unwrap().value().inner(), 10); + assert_eq!(action.notes.get(1).unwrap().asset(), asset); + assert_eq!(action.notes.get(1).unwrap().recipient(), recipient); let action2 = bundle.get_action(str2).unwrap(); assert_eq!(action2.notes.len(), 1); - assert_eq!(action2.notes().first().value().inner(), 15); - assert_eq!(action2.notes().first().asset(), third_asset); + assert_eq!(action2.notes().first().unwrap().value().inner(), 15); + assert_eq!(action2.notes().first().unwrap().asset(), third_asset); } #[test] fn issue_bundle_finalize_asset() { let (rng, _, ik, recipient, _) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("NFT"), + let (mut bundle, _) = IssueBundle::new( + ik, + String::from("NFT"), + Some(IssueInfo { recipient, - NoteValue::from_raw(u64::MIN), - false, - rng, - ) - .expect("Should properly add recipient"); + value: NoteValue::from_raw(u64::MIN), + }), + rng, + ) + .expect("Should properly add recipient"); bundle .finalize_action(String::from("NFT")) .expect("Should finalize properly"); - assert_eq!( - bundle - .add_recipient( - String::from("NFT"), - recipient, - NoteValue::unsplittable(), - false, - rng, - ) - .unwrap_err(), - IssueActionAlreadyFinalized - ); - assert_eq!( bundle .finalize_action(String::from("Another NFT")) @@ -795,46 +819,22 @@ mod tests { bundle.finalize_action("".to_string()).unwrap_err(), WrongAssetDescSize ); - - bundle - .add_recipient( - String::from("Another NFT"), - recipient, - NoteValue::unsplittable(), - true, - rng, - ) - .expect("should add and finalize"); - - assert_eq!( - bundle - .add_recipient( - String::from("Another NFT"), - recipient, - NoteValue::unsplittable(), - true, - rng, - ) - .unwrap_err(), - IssueActionAlreadyFinalized - ); } #[test] fn issue_bundle_prepare() { let (rng, _, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("Frost"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("Frost"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let prepared = bundle.prepare(sighash); assert_eq!(prepared.authorization().sighash, sighash); @@ -844,17 +844,16 @@ mod tests { fn issue_bundle_sign() { let (rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik.clone()); - - bundle - .add_recipient( - String::from("Sign"), + let (bundle, _) = IssueBundle::new( + ik.clone(), + String::from("Sign"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -866,17 +865,16 @@ mod tests { fn issue_bundle_invalid_isk_for_signature() { let (rng, _, ik, recipient, _) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("IssueBundle"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("IssueBundle"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let wrong_isk: IssuanceAuthorizingKey = (&SpendingKey::random(&mut OsRng)).into(); @@ -892,18 +890,17 @@ mod tests { fn issue_bundle_incorrect_asset_for_signature() { let (mut rng, isk, ik, recipient, _) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - // Add "normal" note - bundle - .add_recipient( - String::from("IssueBundle"), + // Create a bundle with "normal" note + let (mut bundle, _) = IssueBundle::new( + ik, + String::from("IssueBundle"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); // Add "bad" note let note = Note::new( @@ -913,37 +910,30 @@ mod tests { Nullifier::dummy(&mut rng), &mut rng, ); - bundle - .actions - .first_mut() - .unwrap() - .notes - .borrow_mut() - .push(note); + bundle.actions.first_mut().notes.push(note); let err = bundle .prepare([0; 32]) .sign(rng, &isk) .expect_err("should not be able to sign"); - assert_eq!(err, IssueActionIncorrectAssetBase); + assert_eq!(err, IssueBundleIkMismatchAssetBase); } #[test] fn issue_bundle_verify() { let (rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("Verify"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("Verify"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); let prev_finalized = &mut HashSet::new(); @@ -959,16 +949,19 @@ mod tests { fn issue_bundle_verify_with_finalize() { let (rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik.clone()); + let (mut bundle, _) = IssueBundle::new( + ik.clone(), + String::from("Verify with finalize"), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(7), + }), + rng, + ) + .unwrap(); bundle - .add_recipient( - String::from("Verify with finalize"), - recipient, - NoteValue::from_raw(7), - true, - rng, - ) + .finalize_action(String::from("Verify with finalize")) .unwrap(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -986,8 +979,6 @@ mod tests { fn issue_bundle_verify_with_supply_info() { let (rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik.clone()); - let asset1_desc = "Verify with supply info 1"; let asset2_desc = "Verify with supply info 2"; let asset3_desc = "Verify with supply info 3"; @@ -996,42 +987,44 @@ mod tests { let asset2_base = AssetBase::derive(&ik, &String::from(asset2_desc)); let asset3_base = AssetBase::derive(&ik, &String::from(asset3_desc)); - bundle - .add_recipient( - String::from(asset1_desc), + let (mut bundle, _) = IssueBundle::new( + ik, + String::from(asset1_desc), + Some(IssueInfo { recipient, - NoteValue::from_raw(7), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(7), + }), + rng, + ) + .unwrap(); bundle .add_recipient( String::from(asset1_desc), recipient, NoteValue::from_raw(8), - true, rng, ) .unwrap(); + bundle.finalize_action(String::from(asset1_desc)).unwrap(); + bundle .add_recipient( String::from(asset2_desc), recipient, NoteValue::from_raw(10), - true, rng, ) .unwrap(); + bundle.finalize_action(String::from(asset2_desc)).unwrap(); + bundle .add_recipient( String::from(asset3_desc), recipient, NoteValue::from_raw(5), - false, rng, ) .unwrap(); @@ -1069,17 +1062,16 @@ mod tests { fn issue_bundle_verify_fail_previously_finalized() { let (rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik.clone()); - - bundle - .add_recipient( - String::from("already final"), + let (bundle, _) = IssueBundle::new( + ik.clone(), + String::from("already final"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); let prev_finalized = &mut HashSet::new(); @@ -1105,17 +1097,16 @@ mod tests { let (mut rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("bad sig"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("bad sig"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let wrong_isk: IssuanceAuthorizingKey = (&SpendingKey::random(&mut rng)).into(); @@ -1136,17 +1127,16 @@ mod tests { #[test] fn issue_bundle_verify_fail_wrong_sighash() { let (rng, isk, ik, recipient, random_sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("Asset description"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("Asset description"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let sighash: [u8; 32] = bundle.commitment().into(); let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -1162,17 +1152,16 @@ mod tests { fn issue_bundle_verify_fail_incorrect_asset_description() { let (mut rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("Asset description"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("Asset description"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -1185,19 +1174,13 @@ mod tests { &mut rng, ); - signed - .actions - .first_mut() - .unwrap() - .notes - .borrow_mut() - .push(note); + signed.actions.first_mut().notes.push(note); let prev_finalized = &HashSet::new(); assert_eq!( verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), - IssueActionIncorrectAssetBase + IssueBundleIkMismatchAssetBase ); } @@ -1207,17 +1190,16 @@ mod tests { let (mut rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from(asset_description), + let (bundle, _) = IssueBundle::new( + ik, + String::from(asset_description), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -1234,7 +1216,7 @@ mod tests { &mut rng, ); - signed.actions.first_mut().unwrap().notes = NonEmpty::new(note); + signed.actions.first_mut().notes = vec![note]; let prev_finalized = &HashSet::new(); @@ -1255,17 +1237,16 @@ mod tests { let (rng, isk, ik, recipient, sighash) = setup_params(); - let mut bundle = IssueBundle::new(ik); - - bundle - .add_recipient( - String::from("Asset description"), + let (bundle, _) = IssueBundle::new( + ik, + String::from("Asset description"), + Some(IssueInfo { recipient, - NoteValue::from_raw(5), - false, - rng, - ) - .unwrap(); + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); let prev_finalized = HashSet::new(); @@ -1274,7 +1255,6 @@ mod tests { signed .actions .first_mut() - .unwrap() .modify_descr(String::from_utf8(vec![b'X'; 513]).unwrap()); assert_eq!( @@ -1283,11 +1263,7 @@ mod tests { ); // 2. Try empty description - signed - .actions - .first_mut() - .unwrap() - .modify_descr("".to_string()); + signed.actions.first_mut().modify_descr("".to_string()); assert_eq!( verify_issue_bundle(&signed, sighash, &prev_finalized).unwrap_err(), @@ -1301,14 +1277,17 @@ mod tests { let (_, _, note) = Note::dummy(&mut rng, None, AssetBase::native()); let action = - IssueAction::new_with_finalize(String::from("Asset description"), ¬e, 0u8).unwrap(); + IssueAction::new_with_flags(String::from("Asset description"), vec![note], 0u8) + .unwrap(); assert_eq!(action.flags(), 0b0000_0000); let action = - IssueAction::new_with_finalize(String::from("Asset description"), ¬e, 1u8).unwrap(); + IssueAction::new_with_flags(String::from("Asset description"), vec![note], 1u8) + .unwrap(); assert_eq!(action.flags(), 0b0000_0001); - let action = IssueAction::new_with_finalize(String::from("Asset description"), ¬e, 2u8); + let action = + IssueAction::new_with_flags(String::from("Asset description"), vec![note], 2u8); assert!(action.is_none()); } } @@ -1321,6 +1300,7 @@ pub mod testing { use crate::keys::testing::{arb_issuance_authorizing_key, arb_issuance_validating_key}; use crate::note::asset_base::testing::zsa_asset_id; use crate::note::testing::arb_zsa_note; + use nonempty::NonEmpty; use proptest::collection::vec; use proptest::prelude::*; use proptest::prop_compose; @@ -1335,7 +1315,11 @@ pub mod testing { ( note in arb_zsa_note(asset), )-> IssueAction { - IssueAction::new(asset_desc.clone(), ¬e) + IssueAction{ + asset_desc: asset_desc.clone(), + notes: vec![note], + finalize: false, + } } } @@ -1346,6 +1330,7 @@ pub mod testing { actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), ik in arb_issuance_validating_key() ) -> IssueBundle { + let actions = NonEmpty::from_vec(actions).unwrap(); IssueBundle { ik, actions, @@ -1363,6 +1348,7 @@ pub mod testing { ik in arb_issuance_validating_key(), fake_sighash in prop::array::uniform32(prop::num::u8::ANY) ) -> IssueBundle { + let actions = NonEmpty::from_vec(actions).unwrap(); IssueBundle { ik, actions, @@ -1383,7 +1369,7 @@ pub mod testing { fake_sighash in prop::array::uniform32(prop::num::u8::ANY) ) -> IssueBundle { let rng = StdRng::from_seed(rng_seed); - + let actions = NonEmpty::from_vec(actions).unwrap(); IssueBundle { ik, actions, diff --git a/tests/zsa.rs b/tests/zsa.rs index 17c0a4b60..af30ba5f1 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -4,7 +4,7 @@ use crate::builder::verify_bundle; use bridgetree::BridgeTree; use incrementalmerkletree::Hashable; use orchard::bundle::Authorized; -use orchard::issuance::{verify_issue_bundle, IssueBundle, Signed, Unauthorized}; +use orchard::issuance::{verify_issue_bundle, IssueBundle, IssueInfo, Signed, Unauthorized}; use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use orchard::note::{AssetBase, ExtractedNoteCommitment}; use orchard::note_encryption_v3::OrchardDomainV3; @@ -138,23 +138,25 @@ pub fn build_merkle_path_with_two_leaves( fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { let mut rng = OsRng; // Create a issuance bundle - let mut unauthorized = IssueBundle::new(keys.ik().clone()); + let unauthorized_asset = IssueBundle::new( + keys.ik().clone(), + asset_descr.to_string(), + Some(IssueInfo { + recipient: keys.recipient, + value: NoteValue::from_raw(40), + }), + &mut rng, + ); + + assert!(unauthorized_asset.is_ok()); + + let (mut unauthorized, _) = unauthorized_asset.unwrap(); - assert!(unauthorized - .add_recipient( - asset_descr.to_string(), - keys.recipient, - NoteValue::from_raw(40), - false, - &mut rng, - ) - .is_ok()); assert!(unauthorized .add_recipient( asset_descr.to_string(), keys.recipient, NoteValue::from_raw(2), - false, &mut rng, ) .is_ok()); From 950b80616db87bcf6685baba7a76f95e718568c7 Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Tue, 13 Jun 2023 13:12:08 +0530 Subject: [PATCH 36/92] Updates to TXID Digest and Authorizing Data Commitment (#66) This updates the computation of the transaction digest and authorizing data commitment for the issue bundle to be in line with the specification in ZIP 227. --- src/bundle/commitments.rs | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index dc6a0b65a..97cc8ab09 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -10,7 +10,9 @@ const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrc const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; -const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcZSAIssue"; +const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdSAIssueHash"; +const ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION: &[u8; 16] = b"ZTxIdIssuActHash"; +const ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION: &[u8; 16] = b"ZTxIdIAcNoteHash"; const ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION: &[u8; 16] = b"ZTxAuthZSAOrHash"; fn hasher(personal: &[u8; 16]) -> State { @@ -97,22 +99,34 @@ pub fn hash_bundle_auth_empty() -> Blake2bHash { /// Construct the commitment for the issue bundle pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) -> Blake2bHash { let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION); + let mut ia = hasher(ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION); + let mut ind = hasher(ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION); for action in bundle.actions().iter() { for note in action.notes().iter() { - h.update(¬e.recipient().to_raw_address_bytes()); - h.update(¬e.value().to_bytes()); - h.update(¬e.asset().to_bytes()); - h.update(¬e.rho().to_bytes()); - h.update(note.rseed().as_bytes()); + ind.update(¬e.recipient().to_raw_address_bytes()); + ind.update(¬e.value().to_bytes()); + ind.update(¬e.asset().to_bytes()); + ind.update(¬e.rho().to_bytes()); + ind.update(note.rseed().as_bytes()); } - h.update(action.asset_desc().as_bytes()); - h.update(&[u8::from(action.is_finalized())]); + ia.update(ind.finalize().as_bytes()); + ia.update(action.asset_desc().as_bytes()); + ia.update(&[u8::from(action.is_finalized())]); } + h.update(ia.finalize().as_bytes()); h.update(&bundle.ik().to_bytes()); h.finalize() } +/// Construct the commitment for the absent issue bundle as defined in +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] +/// +/// [zip227]: https://qed-it.github.io/zips/zip-0227 +pub fn hash_issue_bundle_txid_empty() -> Blake2bHash { + hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() +} + /// Construct the commitment to the authorizing data of an /// authorized issue bundle pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake2bHash { @@ -120,3 +134,11 @@ pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake h.update(&<[u8; 64]>::from(bundle.authorization().signature())); h.finalize() } + +/// Construct the commitment for an absent issue bundle as defined in +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] +/// +/// [zip227]: https://qed-it.github.io/zips/zip-0227 +pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { + hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION).finalize() +} From f49be89f351806c25387e2a83a6e0ee089c95ae8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 19 Jun 2023 10:01:51 +0200 Subject: [PATCH 37/92] Update code to refer to the upgraded version of librustzcash and reflect the corresponding changes --- Cargo.toml | 6 +++--- src/builder.rs | 1 - src/note_encryption_v3.rs | 26 ++++---------------------- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c8c88fe56..006f98c3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ reddsa = "0.5" nonempty = "0.7" serde = { version = "1.0", features = ["derive"] } subtle = "2.3" -zcash_note_encryption = "0.2" +zcash_note_encryption = "0.4" incrementalmerkletree = "0.4" # Logging @@ -57,7 +57,7 @@ criterion = "0.3" halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" -zcash_note_encryption = { version = "0.2", features = ["pre-zip-212"] } +zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.4", features = ["test-dependencies"] } [target.'cfg(unix)'.dev-dependencies] @@ -92,4 +92,4 @@ debug = true debug = true [patch.crates-io] -zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", rev = "07c377ddedf71ab7c7a266d284b054a2dafc2ed4" } +zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", branch = "upgrade_for_orchard_v05_new" } diff --git a/src/builder.rs b/src/builder.rs index 70cd3dc77..bf3c7b581 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -287,7 +287,6 @@ impl ActionInfo { let encryptor = OrchardNoteEncryption::new( self.output.ovk, note, - self.output.recipient, self.output.memo.unwrap_or_else(|| { let mut memo = [0; 512]; memo[0] = 0xf6; diff --git a/src/note_encryption_v3.rs b/src/note_encryption_v3.rs index 4333f6dba..7594b588d 100644 --- a/src/note_encryption_v3.rs +++ b/src/note_encryption_v3.rs @@ -16,7 +16,6 @@ use crate::{ OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, }, note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, - spec::diversify_hash, value::{NoteValue, ValueCommitment}, Address, Note, }; @@ -253,11 +252,7 @@ impl Domain for OrchardDomainV3 { secret.kdf_orchard(ephemeral_key) } - fn note_plaintext_bytes( - note: &Self::Note, - _: &Self::Recipient, - memo: &Self::Memo, - ) -> NotePlaintextBytes { + fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> NotePlaintextBytes { let mut np = [0u8; NOTE_PLAINTEXT_SIZE_V3]; np[0] = 0x03; np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); @@ -312,22 +307,9 @@ impl Domain for OrchardDomainV3 { fn parse_note_plaintext_without_memo_ovk( &self, pk_d: &Self::DiversifiedTransmissionKey, - esk: &Self::EphemeralSecretKey, - ephemeral_key: &EphemeralKeyBytes, plaintext: &CompactNotePlaintextBytes, ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { - if esk - .derive_public(diversify_hash(diversifier.as_array())) - .to_bytes() - .0 - == ephemeral_key.0 - { - Some(*pk_d) - } else { - None - } - }) + orchard_parse_note_plaintext_without_memo(self, plaintext, |_| Some(*pk_d)) } fn extract_memo( @@ -499,7 +481,7 @@ mod tests { let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; // Encode. - let mut plaintext = OrchardDomainV3::note_plaintext_bytes(¬e, ¬e.recipient(), memo); + let mut plaintext = OrchardDomainV3::note_plaintext_bytes(¬e, memo); // Decode. let domain = OrchardDomainV3 { rho: note.rho() }; @@ -622,7 +604,7 @@ mod tests { // Test encryption // - let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, recipient, tv.memo); + let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, tv.memo); assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); assert_eq!( From aa1d89561cd1e28578c0cbb6c594efa3806131da Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 20 Jun 2023 20:35:57 +0200 Subject: [PATCH 38/92] Fix issuance key derivation (#74) Updated constants for master (extended) issuance key according to ZIP 227. Previously, we used the same personalization for the master extended spending key and the master extended issuance key, as well as the same purpose constant for the spending master key and the issuance master key. Now, the following updates have been made: - Personalization for the master extended issuance key: ZIP32ZSAIssue_V1 - Purpose constant for the issuance master key: 227" --- src/issuance.rs | 15 ++-- src/keys.rs | 166 +++++++++++++++++++++++++++--------- src/note/asset_base.rs | 18 ++-- src/primitives/redpallas.rs | 4 +- src/supply_info.rs | 6 +- src/zip32.rs | 41 ++++++--- tests/zsa.rs | 8 +- 7 files changed, 180 insertions(+), 78 deletions(-) diff --git a/src/issuance.rs b/src/issuance.rs index d312b0dbe..e3c7e973b 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -586,7 +586,8 @@ mod tests { }; use crate::issuance::{verify_issue_bundle, IssueAction, Signed}; use crate::keys::{ - FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, + FullViewingKey, IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey, Scope, + SpendingKey, }; use crate::note::{AssetBase, Nullifier}; use crate::value::{NoteValue, ValueSum}; @@ -605,8 +606,8 @@ mod tests { ) { let mut rng = OsRng; - let sk = SpendingKey::random(&mut rng); - let isk: IssuanceAuthorizingKey = (&sk).into(); + let sk_iss = IssuanceKey::random(&mut rng); + let isk: IssuanceAuthorizingKey = (&sk_iss).into(); let ik: IssuanceValidatingKey = (&isk).into(); let fvk = FullViewingKey::from(&SpendingKey::random(&mut rng)); @@ -876,7 +877,7 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuanceAuthorizingKey = (&SpendingKey::random(&mut OsRng)).into(); + let wrong_isk: IssuanceAuthorizingKey = (&IssuanceKey::random(&mut OsRng)).into(); let err = bundle .prepare([0; 32]) @@ -1108,7 +1109,7 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuanceAuthorizingKey = (&SpendingKey::random(&mut rng)).into(); + let wrong_isk: IssuanceAuthorizingKey = (&IssuanceKey::random(&mut rng)).into(); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -1203,8 +1204,8 @@ mod tests { let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); - let incorrect_sk = SpendingKey::random(&mut rng); - let incorrect_isk: IssuanceAuthorizingKey = (&incorrect_sk).into(); + let incorrect_sk_iss = IssuanceKey::random(&mut rng); + let incorrect_isk: IssuanceAuthorizingKey = (&incorrect_sk_iss).into(); let incorrect_ik: IssuanceValidatingKey = (&incorrect_isk).into(); // Add "bad" note diff --git a/src/keys.rs b/src/keys.rs index 6842d182d..7853d4920 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -11,7 +11,7 @@ use group::{ prime::PrimeCurveAffine, Curve, GroupEncoding, }; -use pasta_curves::pallas; +use pasta_curves::{pallas, pallas::Scalar}; use rand::{CryptoRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_note_encryption::EphemeralKeyBytes; @@ -24,11 +24,15 @@ use crate::{ to_scalar, NonIdentityPallasPoint, NonZeroPallasBase, NonZeroPallasScalar, PreparedNonIdentityBase, PreparedNonZeroScalar, PrfExpand, }, - zip32::{self, ChildIndex, ExtendedSpendingKey}, + zip32::{ + self, ChildIndex, ExtendedSpendingKey, ZIP32_ORCHARD_PERSONALIZATION, + ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE, + }, }; const KDF_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_OrchardKDF"; const ZIP32_PURPOSE: u32 = 32; +const ZIP32_PURPOSE_FOR_ISSUANCE: u32 = 227; /// A spending key, from which all key material is derived. /// @@ -99,7 +103,8 @@ impl SpendingKey { ChildIndex::try_from(coin_type)?, ChildIndex::try_from(account)?, ]; - ExtendedSpendingKey::from_path(seed, path).map(|esk| esk.sk()) + ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION) + .map(|esk| esk.sk()) } } @@ -132,13 +137,17 @@ impl From<&SpendingKey> for SpendAuthorizingKey { // SpendingKey cannot be constructed such that this assertion would fail. assert!(!bool::from(ask.is_zero())); // TODO: Add TryFrom for SpendAuthorizingKey. - let ret = SpendAuthorizingKey(ask.to_repr().try_into().unwrap()); - // If the last bit of repr_P(ak) is 1, negate ask. - if (<[u8; 32]>::from(SpendValidatingKey::from(&ret).0)[31] >> 7) == 1 { - SpendAuthorizingKey((-ask).to_repr().try_into().unwrap()) - } else { - ret - } + SpendAuthorizingKey(conditionally_negate(ask)) + } +} + +// If the last bit of repr_P(ak) is 1, negate ask. +fn conditionally_negate(scalar: Scalar) -> redpallas::SigningKey { + let ret = redpallas::SigningKey::(scalar.to_repr().try_into().unwrap()); + if (<[u8; 32]>::from(redpallas::VerificationKey::::from(&ret).0)[31] >> 7) == 1 { + redpallas::SigningKey::((-scalar).to_repr().try_into().unwrap()) + } else { + ret } } @@ -178,7 +187,7 @@ impl SpendValidatingKey { self.0.randomize(randomizer) } - /// Converts this issuance validating key to its serialized form, + /// Converts this spend key to its serialized form, /// I2LEOSP_256(ak). pub(crate) fn to_bytes(&self) -> [u8; 32] { // This is correct because the wrapped point must have ỹ = 0, and @@ -194,9 +203,87 @@ impl SpendValidatingKey { } } +/// A function to check structural validity of the validating keys for authorizing transfers and +/// issuing assets +/// Structural validity checks for ak_P or ik_P: +/// - The point must not be the identity (which for Pallas is canonically encoded as all-zeroes). +/// - The compressed y-coordinate bit must be 0. +fn check_structural_validity( + verification_key_bytes: [u8; 32], +) -> Option> { + if verification_key_bytes != [0; 32] && verification_key_bytes[31] & 0x80 == 0 { + >::try_from(verification_key_bytes).ok() + } else { + None + } +} + /// We currently use `SpendAuth` as the `IssuanceAuth`. type IssuanceAuth = SpendAuth; +/// An issuance key, from which all key material is derived. +/// +/// $\mathsf{sk}$ as defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. +/// +/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents +#[derive(Debug, Copy, Clone)] +pub struct IssuanceKey([u8; 32]); + +impl From for IssuanceKey { + fn from(sk: SpendingKey) -> Self { + IssuanceKey(*sk.to_bytes()) + } +} + +impl ConstantTimeEq for IssuanceKey { + fn ct_eq(&self, other: &Self) -> Choice { + self.to_bytes().ct_eq(other.to_bytes()) + } +} + +impl IssuanceKey { + /// Generates a random issuance key. + /// + /// This is only used when generating a random AssetBase. + /// Real issuance keys should be derived according to [ZIP 32]. + /// + /// [ZIP 32]: https://zips.z.cash/zip-0032 + pub(crate) fn random(rng: &mut impl RngCore) -> Self { + SpendingKey::random(rng).into() + } + + /// Constructs an Orchard issuance key from uniformly-random bytes. + /// + /// Returns `None` if the bytes do not correspond to a valid Orchard issuance key. + pub fn from_bytes(sk_iss: [u8; 32]) -> CtOption { + let sk_iss = IssuanceKey(sk_iss); + // If isk = 0 (A scalar value), discard this key. + let isk = IssuanceAuthorizingKey::derive_inner(&sk_iss); + CtOption::new(sk_iss, !isk.is_zero()) + } + + /// Returns the raw bytes of the issuance key. + pub fn to_bytes(&self) -> &[u8; 32] { + &self.0 + } + + /// Derives the Orchard issuance key for the given seed, coin type, and account. + pub fn from_zip32_seed( + seed: &[u8], + coin_type: u32, + account: u32, + ) -> Result { + // Call zip32 logic + let path = &[ + ChildIndex::try_from(ZIP32_PURPOSE_FOR_ISSUANCE)?, + ChildIndex::try_from(coin_type)?, + ChildIndex::try_from(account)?, + ]; + ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE) + .map(|esk| esk.sk().into()) + } +} + /// An issuance authorizing key, used to create issuance authorization signatures. /// This type enforces that the corresponding public point (ik^ℙ) has ỹ = 0. /// @@ -208,9 +295,9 @@ type IssuanceAuth = SpendAuth; pub struct IssuanceAuthorizingKey(redpallas::SigningKey); impl IssuanceAuthorizingKey { - /// Derives isk from sk. Internal use only, does not enforce all constraints. - fn derive_inner(sk: &SpendingKey) -> pallas::Scalar { - to_scalar(PrfExpand::ZsaIsk.expand(&sk.0)) + /// Derives isk from sk_iss. Internal use only, does not enforce all constraints. + fn derive_inner(sk_iss: &IssuanceKey) -> pallas::Scalar { + to_scalar(PrfExpand::ZsaIsk.expand(&sk_iss.0)) } /// Sign the provided message using the `IssuanceAuthorizingKey`. @@ -223,18 +310,12 @@ impl IssuanceAuthorizingKey { } } -impl From<&SpendingKey> for IssuanceAuthorizingKey { - fn from(sk: &SpendingKey) -> Self { - let isk = Self::derive_inner(sk); +impl From<&IssuanceKey> for IssuanceAuthorizingKey { + fn from(sk_iss: &IssuanceKey) -> Self { + let isk = IssuanceAuthorizingKey::derive_inner(sk_iss); // IssuanceAuthorizingKey cannot be constructed such that this assertion would fail. assert!(!bool::from(isk.is_zero())); - let ret = IssuanceAuthorizingKey(isk.to_repr().try_into().unwrap()); - // If the last bit of repr_P(ik) is 1, negate isk. - if (<[u8; 32]>::from(IssuanceValidatingKey::from(&ret).0)[31] >> 7) == 1 { - IssuanceAuthorizingKey((-isk).to_repr().try_into().unwrap()) - } else { - ret - } + IssuanceAuthorizingKey(conditionally_negate(isk)) } } @@ -297,21 +378,6 @@ impl IssuanceValidatingKey { } } -/// A function to check structural validity of the validating keys for authorizing transfers and -/// issuing assets -/// Structural validity checks for ak_P or ik_P: -/// - The point must not be the identity (which for Pallas is canonically encoded as all-zeroes). -/// - The compressed y-coordinate bit must be 0. -fn check_structural_validity( - verification_key_bytes: [u8; 32], -) -> Option> { - if verification_key_bytes != [0; 32] && verification_key_bytes[31] & 0x80 == 0 { - >::try_from(verification_key_bytes).ok() - } else { - None - } -} - /// A key used to derive [`Nullifier`]s from [`Note`]s. /// /// $\mathsf{nk}$ as defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. @@ -1050,7 +1116,7 @@ impl SharedSecret { #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { use super::{ - DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuanceAuthorizingKey, + DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey, SpendingKey, }; use proptest::prelude::*; @@ -1070,6 +1136,20 @@ pub mod testing { } } + prop_compose! { + /// Generate a uniformly distributed Orchard issuance key. + pub fn arb_issuance_key()( + key in prop::array::uniform32(prop::num::u8::ANY) + .prop_map(IssuanceKey::from_bytes) + .prop_filter( + "Values must correspond to valid Orchard issuance keys.", + |opt| bool::from(opt.is_some()) + ) + ) -> IssuanceKey { + key.unwrap() + } + } + prop_compose! { /// Generate a uniformly distributed Orchard ephemeral secret key. pub fn arb_esk()( @@ -1106,7 +1186,7 @@ pub mod testing { /// Generate a uniformly distributed RedDSA issuance authorizing key. pub fn arb_issuance_authorizing_key()(rng_seed in prop::array::uniform32(prop::num::u8::ANY)) -> IssuanceAuthorizingKey { let mut rng = StdRng::from_seed(rng_seed); - IssuanceAuthorizingKey::from(&SpendingKey::random(&mut rng)) + IssuanceAuthorizingKey::from(&IssuanceKey::random(&mut rng)) } } @@ -1187,7 +1267,9 @@ mod tests { let ask: SpendAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask); - let isk: IssuanceAuthorizingKey = (&sk).into(); + let sk_iss = IssuanceKey::from_bytes(tv.sk).unwrap(); + + let isk: IssuanceAuthorizingKey = (&sk_iss).into(); assert_eq!(<[u8; 32]>::from(&isk.0), tv.isk); let ak: SpendValidatingKey = (&ask).into(); diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 63da3a5f8..500d84210 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -10,7 +10,7 @@ use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::constants::fixed_bases::{ NATIVE_ASSET_BASE_V_BYTES, VALUE_COMMITMENT_PERSONALIZATION, ZSA_ASSET_BASE_PERSONALIZATION, }; -use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; +use crate::keys::{IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey}; /// Note type identifier. #[derive(Clone, Copy, Debug, Eq)] @@ -92,8 +92,8 @@ impl AssetBase { /// /// This is only used in tests. pub(crate) fn random(rng: &mut impl RngCore) -> Self { - let sk = SpendingKey::random(rng); - let isk = IssuanceAuthorizingKey::from(&sk); + let sk_iss = IssuanceKey::random(rng); + let isk = IssuanceAuthorizingKey::from(&sk_iss); let ik = IssuanceValidatingKey::from(&isk); let asset_descr = "zsa_asset"; AssetBase::derive(&ik, asset_descr) @@ -126,13 +126,13 @@ pub mod testing { use proptest::prelude::*; - use crate::keys::{testing::arb_spending_key, IssuanceAuthorizingKey, IssuanceValidatingKey}; + use crate::keys::{testing::arb_issuance_key, IssuanceAuthorizingKey, IssuanceValidatingKey}; prop_compose! { /// Generate a uniformly distributed note type pub fn arb_asset_id()( is_native in prop::bool::ANY, - sk in arb_spending_key(), + sk in arb_issuance_key(), str in "[A-Za-z]{255}", ) -> AssetBase { if is_native { @@ -155,10 +155,10 @@ pub mod testing { prop_compose! { /// Generate an asset ID pub fn arb_zsa_asset_id()( - sk in arb_spending_key(), + sk_iss in arb_issuance_key(), str in "[A-Za-z]{255}" ) -> AssetBase { - let isk = IssuanceAuthorizingKey::from(&sk); + let isk = IssuanceAuthorizingKey::from(&sk_iss); AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) } } @@ -166,10 +166,10 @@ pub mod testing { prop_compose! { /// Generate an asset ID using a specific description pub fn zsa_asset_id(asset_desc: String)( - sk in arb_spending_key(), + sk_iss in arb_issuance_key(), ) -> AssetBase { assert!(super::is_asset_desc_of_valid_size(&asset_desc)); - let isk = IssuanceAuthorizingKey::from(&sk); + let isk = IssuanceAuthorizingKey::from(&sk_iss); AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) } } diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index 92fe165e4..a414bf285 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -23,7 +23,7 @@ impl SigType for Binding {} /// A RedPallas signing key. #[derive(Clone, Copy, Debug)] -pub struct SigningKey(reddsa::SigningKey); +pub struct SigningKey(pub(crate) reddsa::SigningKey); impl From> for [u8; 32] { fn from(sk: SigningKey) -> [u8; 32] { @@ -63,7 +63,7 @@ impl SigningKey { /// A RedPallas verification key. #[derive(Clone, Debug)] -pub struct VerificationKey(reddsa::VerificationKey); +pub struct VerificationKey(pub(crate) reddsa::VerificationKey); impl From> for [u8; 32] { fn from(vk: VerificationKey) -> [u8; 32] { diff --git a/src/supply_info.rs b/src/supply_info.rs index 6bd96df34..79e6b7d70 100644 --- a/src/supply_info.rs +++ b/src/supply_info.rs @@ -80,10 +80,10 @@ mod tests { use super::*; fn create_test_asset(asset_desc: &str) -> AssetBase { - use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey}; + use crate::keys::{IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey}; - let sk = SpendingKey::from_bytes([0u8; 32]).unwrap(); - let isk: IssuanceAuthorizingKey = (&sk).into(); + let sk_iss = IssuanceKey::from_bytes([0u8; 32]).unwrap(); + let isk: IssuanceAuthorizingKey = (&sk_iss).into(); AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc) } diff --git a/src/zip32.rs b/src/zip32.rs index 3ba8bd571..12427bf8d 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -10,8 +10,11 @@ use crate::{ spec::PrfExpand, }; -const ZIP32_ORCHARD_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Orchard"; const ZIP32_ORCHARD_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashOrchardFVFP"; +/// Personalization for the master extended spending key +pub const ZIP32_ORCHARD_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Orchard"; +/// Personalization for the master extended issuance key +pub const ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE: &[u8; 16] = b"ZIP32ZSAIssue_V1"; /// Errors produced in derivation of extended spending keys #[derive(Debug, PartialEq, Eq)] @@ -117,8 +120,12 @@ impl ExtendedSpendingKey { /// # Panics /// /// Panics if seed results in invalid spending key. - pub fn from_path(seed: &[u8], path: &[ChildIndex]) -> Result { - let mut xsk = Self::master(seed)?; + pub fn from_path( + seed: &[u8], + path: &[ChildIndex], + personalization: &[u8; 16], + ) -> Result { + let mut xsk = Self::master(seed, personalization)?; for i in path { xsk = xsk.derive_child(*i)?; } @@ -134,13 +141,13 @@ impl ExtendedSpendingKey { /// # Panics /// /// Panics if the seed is shorter than 32 bytes or longer than 252 bytes. - fn master(seed: &[u8]) -> Result { + fn master(seed: &[u8], personalization: &[u8; 16]) -> Result { assert!(seed.len() >= 32 && seed.len() <= 252); // I := BLAKE2b-512("ZcashIP32Orchard", seed) let I: [u8; 64] = { let mut I = Blake2bParams::new() .hash_length(64) - .personal(ZIP32_ORCHARD_PERSONALIZATION) + .personal(personalization) .to_state(); I.update(seed); I.finalize().as_bytes().try_into().unwrap() @@ -213,7 +220,7 @@ mod tests { #[test] fn derive_child() { let seed = [0; 32]; - let xsk_m = ExtendedSpendingKey::master(&seed).unwrap(); + let xsk_m = ExtendedSpendingKey::master(&seed, ZIP32_ORCHARD_PERSONALIZATION).unwrap(); let i_5 = 5; let xsk_5 = xsk_m.derive_child(i_5.try_into().unwrap()); @@ -224,20 +231,28 @@ mod tests { #[test] fn path() { let seed = [0; 32]; - let xsk_m = ExtendedSpendingKey::master(&seed).unwrap(); + let xsk_m = ExtendedSpendingKey::master(&seed, ZIP32_ORCHARD_PERSONALIZATION).unwrap(); let xsk_5h = xsk_m.derive_child(5.try_into().unwrap()).unwrap(); assert!(bool::from( - ExtendedSpendingKey::from_path(&seed, &[5.try_into().unwrap()]) - .unwrap() - .ct_eq(&xsk_5h) + ExtendedSpendingKey::from_path( + &seed, + &[5.try_into().unwrap()], + ZIP32_ORCHARD_PERSONALIZATION + ) + .unwrap() + .ct_eq(&xsk_5h) )); let xsk_5h_7 = xsk_5h.derive_child(7.try_into().unwrap()).unwrap(); assert!(bool::from( - ExtendedSpendingKey::from_path(&seed, &[5.try_into().unwrap(), 7.try_into().unwrap()]) - .unwrap() - .ct_eq(&xsk_5h_7) + ExtendedSpendingKey::from_path( + &seed, + &[5.try_into().unwrap(), 7.try_into().unwrap()], + ZIP32_ORCHARD_PERSONALIZATION + ) + .unwrap() + .ct_eq(&xsk_5h_7) )); } } diff --git a/tests/zsa.rs b/tests/zsa.rs index f0ee62c28..649d5e8cf 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -13,7 +13,10 @@ use orchard::{ builder::Builder, bundle::Flags, circuit::{ProvingKey, VerifyingKey}, - keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, + keys::{ + FullViewingKey, IssuanceKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, + SpendingKey, + }, value::NoteValue, Address, Anchor, Bundle, Note, }; @@ -58,7 +61,8 @@ fn prepare_keys() -> Keychain { let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); - let isk = IssuanceAuthorizingKey::from(&sk); + let sk_iss = IssuanceKey::from_bytes([0; 32]).unwrap(); + let isk = IssuanceAuthorizingKey::from(&sk_iss); let ik = IssuanceValidatingKey::from(&isk); Keychain { pk, From daf6269e89562c130b3d3d2ef90980994b5e2da4 Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Wed, 21 Jun 2023 15:53:38 +0530 Subject: [PATCH 39/92] Preventing Asset Base from being the identity point on the Pallas curve (#71) As in the title, this is done in two portions: - A protection is added to `AssetBase::derive()`, which panics if the output is going to be the identity point. This panic will occur with negligible probability due to the properties of the hash. - The `verify_supply()` function now returns an error if the Asset Base of the notes involved is the identity point. - A number of tests are added to ensure the `verify_supply`, `verify_issue_bundle` functions raise errors appropriately, and also to confirm that the issue bundle cannot be signed when the asset base is the identity point. --------- Co-authored-by: Paul <3682187+PaulLaux@users.noreply.github.com> --- src/issuance.rs | 115 +++++++++++++++++++++++++++++++++++++---- src/note/asset_base.rs | 22 +++++--- 2 files changed, 122 insertions(+), 15 deletions(-) diff --git a/src/issuance.rs b/src/issuance.rs index e3c7e973b..c2fc7ca28 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -1,5 +1,6 @@ //! Structs related to issuance bundles and the associated logic. use blake2b_simd::Hash as Blake2bHash; +use group::Group; use nonempty::NonEmpty; use rand::{CryptoRng, RngCore}; use std::collections::HashSet; @@ -7,7 +8,7 @@ use std::fmt; use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; use crate::issuance::Error::{ - IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, + AssetBaseCannotBeIdentityPoint, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueActionWithoutNoteNotFinalized, IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, ValueSumOverflow, WrongAssetDescSize, }; @@ -134,6 +135,11 @@ impl IssueAction { .notes .iter() .try_fold(ValueSum::zero(), |value_sum, ¬e| { + //The asset base should not be the identity point of the Pallas curve. + if bool::from(note.asset().cv_base().is_identity()) { + return Err(AssetBaseCannotBeIdentityPoint); + } + // All assets should be derived correctly note.asset() .eq(&issue_asset) @@ -527,6 +533,8 @@ pub enum Error { WrongAssetDescSize, /// The `IssueAction` is not finalized but contains no notes. IssueActionWithoutNoteNotFinalized, + /// The `AssetBase` is the Pallas identity point, which is invalid. + AssetBaseCannotBeIdentityPoint, /// Verification errors: /// Invalid signature. @@ -561,6 +569,12 @@ impl fmt::Display for Error { "this `IssueAction` contains no notes but is not finalized" ) } + AssetBaseCannotBeIdentityPoint => { + write!( + f, + "the AssetBase is the identity point of the Pallas curve, which is invalid." + ) + } IssueBundleInvalidSignature(_) => { write!(f, "invalid signature") } @@ -581,10 +595,11 @@ impl fmt::Display for Error { mod tests { use super::{AssetSupply, IssueBundle, IssueInfo}; use crate::issuance::Error::{ - IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, - IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, WrongAssetDescSize, + AssetBaseCannotBeIdentityPoint, IssueActionNotFound, + IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, + IssueBundleInvalidSignature, WrongAssetDescSize, }; - use crate::issuance::{verify_issue_bundle, IssueAction, Signed}; + use crate::issuance::{verify_issue_bundle, IssueAction, Signed, Unauthorized}; use crate::keys::{ FullViewingKey, IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey, Scope, SpendingKey, @@ -592,6 +607,9 @@ mod tests { use crate::note::{AssetBase, Nullifier}; use crate::value::{NoteValue, ValueSum}; use crate::{Address, Note}; + use group::{Group, GroupEncoding}; + use nonempty::NonEmpty; + use pasta_curves::pallas::{Point, Scalar}; use rand::rngs::OsRng; use rand::RngCore; use reddsa::Error::InvalidSignature; @@ -654,8 +672,49 @@ mod tests { ) } + // This function computes the identity point on the Pallas curve and returns an Asset Base with that value. + fn identity_point() -> AssetBase { + let identity_point = (Point::generator() * -Scalar::one()) + Point::generator(); + AssetBase::from_bytes(&identity_point.to_bytes()).unwrap() + } + + fn identity_point_test_params( + note1_value: u64, + note2_value: u64, + ) -> ( + OsRng, + IssuanceAuthorizingKey, + IssueBundle, + [u8; 32], + ) { + let (mut rng, isk, ik, recipient, sighash) = setup_params(); + + let note1 = Note::new( + recipient, + NoteValue::from_raw(note1_value), + identity_point(), + Nullifier::dummy(&mut rng), + &mut rng, + ); + + let note2 = Note::new( + recipient, + NoteValue::from_raw(note2_value), + identity_point(), + Nullifier::dummy(&mut rng), + &mut rng, + ); + + let action = + IssueAction::from_parts("arbitrary asset_desc".into(), vec![note1, note2], false); + + let bundle = IssueBundle::from_parts(ik, NonEmpty::new(action), Unauthorized); + + (rng, isk, bundle, sighash) + } + #[test] - fn test_verify_supply_valid() { + fn verify_supply_valid() { let (ik, test_asset, action) = setup_verify_supply_test_params(10, 20, "Asset 1", None, false); @@ -671,7 +730,17 @@ mod tests { } #[test] - fn test_verify_supply_finalized() { + fn verify_supply_invalid_for_asset_base_as_identity() { + let (_, _, bundle, _) = identity_point_test_params(10, 20); + + assert_eq!( + bundle.actions.head.verify_supply(&bundle.ik), + Err(AssetBaseCannotBeIdentityPoint) + ); + } + + #[test] + fn verify_supply_finalized() { let (ik, test_asset, action) = setup_verify_supply_test_params(10, 20, "Asset 1", None, true); @@ -687,7 +756,7 @@ mod tests { } #[test] - fn test_verify_supply_incorrect_asset_base() { + fn verify_supply_incorrect_asset_base() { let (ik, _, action) = setup_verify_supply_test_params(10, 20, "Asset 1", Some("Asset 2"), false); @@ -698,7 +767,7 @@ mod tests { } #[test] - fn test_verify_supply_ik_mismatch_asset_base() { + fn verify_supply_ik_mismatch_asset_base() { let (_, _, action) = setup_verify_supply_test_params(10, 20, "Asset 1", None, false); let (_, _, ik, _, _) = setup_params(); @@ -1273,7 +1342,35 @@ mod tests { } #[test] - fn test_finalize_flag_serialization() { + fn issue_bundle_cannot_be_signed_with_asset_base_identity_point() { + let (rng, isk, bundle, sighash) = identity_point_test_params(10, 20); + + assert_eq!( + bundle.prepare(sighash).sign(rng, &isk).unwrap_err(), + AssetBaseCannotBeIdentityPoint + ); + } + + #[test] + fn issue_bundle_verify_fail_asset_base_identity_point() { + let (mut rng, isk, bundle, sighash) = identity_point_test_params(10, 20); + + let signed = IssueBundle { + ik: bundle.ik, + actions: bundle.actions, + authorization: Signed { + signature: isk.sign(&mut rng, &sighash), + }, + }; + + assert_eq!( + verify_issue_bundle(&signed, sighash, &HashSet::new()).unwrap_err(), + AssetBaseCannotBeIdentityPoint + ); + } + + #[test] + fn finalize_flag_serialization() { let mut rng = OsRng; let (_, _, note) = Note::dummy(&mut rng, None, AssetBase::native()); diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 500d84210..41a284a8a 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -1,5 +1,5 @@ use blake2b_simd::{Hash as Blake2bHash, Params}; -use group::GroupEncoding; +use group::{Group, GroupEncoding}; use halo2_proofs::arithmetic::CurveExt; use pasta_curves::pallas; use rand::RngCore; @@ -54,10 +54,13 @@ impl AssetBase { /// /// # Panics /// - /// Panics if `asset_desc` is empty or greater than `MAX_ASSET_DESCRIPTION_SIZE`. + /// Panics if `asset_desc` is empty or greater than `MAX_ASSET_DESCRIPTION_SIZE` or if the derived Asset Base is the identity point. #[allow(non_snake_case)] pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &str) -> Self { - assert!(is_asset_desc_of_valid_size(asset_desc)); + assert!( + is_asset_desc_of_valid_size(asset_desc), + "The asset_desc string is not of valid size" + ); // EncodeAssetId(ik, asset_desc) = version_byte || ik || asset_desc let version_byte = [0x00]; @@ -65,10 +68,17 @@ impl AssetBase { let asset_digest = asset_digest(encode_asset_id); + let asset_base = + pallas::Point::hash_to_curve(ZSA_ASSET_BASE_PERSONALIZATION)(asset_digest.as_bytes()); + + // this will happen with negligible probability. + assert!( + bool::from(!asset_base.is_identity()), + "The Asset Base is the identity point, which is invalid." + ); + // AssetBase = ZSAValueBase(AssetDigest) - AssetBase( - pallas::Point::hash_to_curve(ZSA_ASSET_BASE_PERSONALIZATION)(asset_digest.as_bytes()), - ) + AssetBase(asset_base) } /// Note type for the "native" currency (zec), maintains backward compatibility with Orchard untyped notes. From 477f949bd29f1c758b33f1d0ce4b779144f87789 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 23 Jun 2023 11:40:27 +0200 Subject: [PATCH 40/92] Update random nullifier for split notes and circuit (#76) To be secure against roadblock attacks, we update the process to obtain a random nullifier for split notes. Now we have the following formula to evaluate nf_old - for non split_notes, nf_old = Extract_P([PRF^{nfOrchard}_{nk}(rho_old) + psi_nf) mod q_P] NullifierK + cm_old) - for split notes, nf_old = Extract_P([PRF^{nfOrchard}_{nk}(rho_old) + psi_nf) mod q_P] NullifierK + cm_old + NullifierL) where psi_nf is equal to - psi_old for non split notes - a random pallas Base element for split notes The following constraints have been updated into the circuit - nf_old = nf_old_pub for all notes - derived_pk_d_old = pk_d_old for all notes - if split_flag=0, then psi_old = psi_new --- src/builder.rs | 18 +- src/bundle.rs | 1 - src/circuit.rs | 192 ++++---- src/circuit/gadget.rs | 60 ++- src/circuit_description | 746 ++++++++++++-------------------- src/circuit_proof_test_case.bin | Bin 5250 -> 5250 bytes src/note.rs | 42 +- src/note/nullifier.rs | 12 +- 8 files changed, 472 insertions(+), 599 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 70cd3dc77..eb20033b2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -167,26 +167,20 @@ impl SpendInfo { } } - /// Creates a split spend, which is identical to origin normal spend except that we use a random - /// fvk to generate a different nullifier. In addition, the split_flag is raised. + /// Creates a split spend, which is identical to origin normal spend except that + /// `rseed_split_note` contains a random seed. In addition, the split_flag is raised. /// /// Defined in [Transfer and Burn of Zcash Shielded Assets ZIP-0226 § Split Notes (DRAFT PR)][TransferZSA]. /// /// [TransferZSA]: https://qed-it.github.io/zips/zip-0226.html#split-notes fn create_split_spend(&self, rng: &mut impl RngCore) -> Self { - let note = self.note; - let merkle_path = self.merkle_path.clone(); - - let sk = SpendingKey::random(rng); - let fvk: FullViewingKey = (&sk).into(); - SpendInfo { - dummy_sk: Some(sk), - fvk, + dummy_sk: None, + fvk: self.fvk.clone(), // We use external scope to avoid unnecessary derivations scope: Scope::External, - note, - merkle_path, + note: self.note.create_split_note(rng), + merkle_path: self.merkle_path.clone(), split_flag: true, } } diff --git a/src/bundle.rs b/src/bundle.rs index f6265761d..2e5d5a034 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -141,7 +141,6 @@ pub struct Bundle { /// This is the sum of Orchard spends minus the sum of Orchard outputs. value_balance: V, /// Assets intended for burning - /// TODO We need to add a consensus check to make sure that it is impossible to burn ZEC. burn: Vec<(AssetBase, V)>, /// The root of the Orchard commitment tree that this bundle commits to. anchor: Anchor, diff --git a/src/circuit.rs b/src/circuit.rs index 67833b013..99a35b1d9 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -21,7 +21,7 @@ use self::{ commit_ivk::{CommitIvkChip, CommitIvkConfig}, gadget::{ add_chip::{AddChip, AddConfig}, - assign_free_advice, assign_is_native_asset, + assign_free_advice, assign_is_native_asset, assign_split_flag, }, note_commit::{NoteCommitChip, NoteCommitConfig}, }; @@ -113,6 +113,7 @@ pub struct Circuit { pub(crate) psi_old: Value, pub(crate) rcm_old: Value, pub(crate) cm_old: Value, + pub(crate) psi_nf: Value, pub(crate) alpha: Value, pub(crate) ak: Value, pub(crate) nk: Value, @@ -164,6 +165,9 @@ impl Circuit { let psi_old = spend.note.rseed().psi(&rho_old); let rcm_old = spend.note.rseed().rcm(&rho_old); + let nf_rseed = spend.note.rseed_split_note().unwrap_or(*spend.note.rseed()); + let psi_nf = nf_rseed.psi(&rho_old); + let rho_new = output_note.rho(); let psi_new = output_note.rseed().psi(&rho_new); let rcm_new = output_note.rseed().rcm(&rho_new); @@ -178,6 +182,7 @@ impl Circuit { psi_old: Value::known(psi_old), rcm_old: Value::known(rcm_old), cm_old: Value::known(spend.note.commitment()), + psi_nf: Value::known(psi_nf), alpha: Value::known(alpha), ak: Value::known(spend.fvk.clone().into()), nk: Value::known(*spend.fvk.nk()), @@ -222,10 +227,9 @@ impl plonk::Circuit for Circuit { // Constrain v_old = 0 or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). - // Constrain split_flag = 1 or nf_old = nf_old_pub // Constrain is_native_asset to be boolean // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset - // Constraint split_flag = 1 or derived_pk_d_old = pk_d_old + // Constraint if split_flag = 0 then psi_old = psi_nf let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -242,14 +246,11 @@ impl plonk::Circuit for Circuit { let split_flag = meta.query_advice(advices[8], Rotation::cur()); - let nf_old = meta.query_advice(advices[9], Rotation::cur()); - let nf_old_pub = meta.query_advice(advices[0], Rotation::next()); - - let is_native_asset = meta.query_advice(advices[1], Rotation::next()); - let asset_x = meta.query_advice(advices[2], Rotation::next()); - let asset_y = meta.query_advice(advices[3], Rotation::next()); - let diff_asset_x_inv = meta.query_advice(advices[4], Rotation::next()); - let diff_asset_y_inv = meta.query_advice(advices[5], Rotation::next()); + let is_native_asset = meta.query_advice(advices[9], Rotation::cur()); + let asset_x = meta.query_advice(advices[0], Rotation::next()); + let asset_y = meta.query_advice(advices[1], Rotation::next()); + let diff_asset_x_inv = meta.query_advice(advices[2], Rotation::next()); + let diff_asset_y_inv = meta.query_advice(advices[3], Rotation::next()); let one = Expression::Constant(pallas::Base::one()); @@ -262,10 +263,8 @@ impl plonk::Circuit for Circuit { let diff_asset_x = asset_x - Expression::Constant(*native_asset.x()); let diff_asset_y = asset_y - Expression::Constant(*native_asset.y()); - let pk_d_old_x = meta.query_advice(advices[6], Rotation::next()); - let pk_d_old_y = meta.query_advice(advices[7], Rotation::next()); - let derived_pk_d_old_x = meta.query_advice(advices[8], Rotation::next()); - let derived_pk_d_old_y = meta.query_advice(advices[9], Rotation::next()); + let psi_old = meta.query_advice(advices[4], Rotation::next()); + let psi_nf = meta.query_advice(advices[5], Rotation::next()); Constraints::with_selector( q_orchard, @@ -289,10 +288,6 @@ impl plonk::Circuit for Circuit { "v_new = 0 or enable_outputs = 1", v_new * (one.clone() - enable_outputs), ), - ( - "split_flag = 1 or nf_old = nf_old_pub", - (one.clone() - split_flag.clone()) * (nf_old - nf_old_pub), - ), ( "bool_check is_native_asset", bool_check(is_native_asset.clone()), @@ -316,20 +311,9 @@ impl plonk::Circuit for Circuit { * (diff_asset_x * diff_asset_x_inv - one.clone()) * (diff_asset_y * diff_asset_y_inv - one.clone()), ), - // Constrain derived pk_d_old to equal witnessed pk_d_old - // - // This equality constraint is technically superfluous, because the assigned - // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see - // an explicit connection between circuit-synthesized values, and explicit - // prover witnesses. We could get the best of both worlds with a write-on-copy - // abstraction (https://github.com/zcash/halo2/issues/334). ( - "split_flag = 1 or pk_d_old_x = derived_pk_d_old_x", - (one.clone() - split_flag.clone()) * (pk_d_old_x - derived_pk_d_old_x), - ), - ( - "split_flag = 1 or pk_d_old_y = derived_pk_d_old_y", - (one - split_flag) * (pk_d_old_y - derived_pk_d_old_y), + "(split_flag = 0) => (psi_old = psi_nf)", + (one - split_flag) * (psi_old - psi_nf), ), ], ) @@ -480,7 +464,14 @@ impl plonk::Circuit for Circuit { let ecc_chip = config.ecc_chip(); // Witness private inputs that are used across multiple checks. - let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, nf_old_pub) = { + let (psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset) = { + // Witness psi_nf + let psi_nf = assign_free_advice( + layouter.namespace(|| "witness psi_nf"), + config.advices[0], + self.psi_nf, + )?; + // Witness psi_old let psi_old = assign_free_advice( layouter.namespace(|| "witness psi_old"), @@ -545,25 +536,18 @@ impl plonk::Circuit for Circuit { self.asset.map(|asset| asset.cv_base().to_affine()), )?; - // Witness nf_old_pub - let nf_old_pub = layouter.assign_region( - || "load nf_old pub", - |mut region| { - region.assign_advice_from_instance( - || "load nf_old pub", - config.primary, - NF_OLD, - config.advices[0], - 1, - ) - }, - )?; - ( - psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, nf_old_pub, + psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, ) }; + // Witness split_flag + let split_flag = assign_split_flag( + layouter.namespace(|| "witness split_flag"), + config.advices[0], + self.split_flag, + )?; + // Witness is_native_asset which is equal to // 1 if asset is equal to native asset, and // 0 if asset is not equal to native asset. @@ -656,16 +640,21 @@ impl plonk::Circuit for Circuit { // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). let nf_old = { let nf_old = gadget::derive_nullifier( - layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old)"), + layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), config.poseidon_chip(), config.add_chip(), ecc_chip.clone(), + config.mux_chip(), rho_old.clone(), - &psi_old, + &psi_nf, &cm_old, nk.clone(), + split_flag.clone(), )?; + // Constrain nf_old to equal public input + layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; + nf_old }; @@ -690,7 +679,7 @@ impl plonk::Circuit for Circuit { } // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). - let (derived_pk_d_old, pk_d_old) = { + let pk_d_old = { let ivk = { let ak = ak_P.extract_p().inner().clone(); let rivk = ScalarFixed::new( @@ -717,13 +706,22 @@ impl plonk::Circuit for Circuit { let (derived_pk_d_old, _ivk) = g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; + // Constrain derived pk_d_old to equal witnessed pk_d_old + // + // This equality constraint is technically superfluous, because the assigned + // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see + // an explicit connection between circuit-synthesized values, and explicit + // prover witnesses. We could get the best of both worlds with a write-on-copy + // abstraction (https://github.com/zcash/halo2/issues/334). let pk_d_old = NonIdentityPoint::new( ecc_chip.clone(), layouter.namespace(|| "witness pk_d_old"), self.pk_d_old.map(|pk_d_old| pk_d_old.inner().to_affine()), )?; + derived_pk_d_old + .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; - (derived_pk_d_old, pk_d_old) + pk_d_old }; // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). @@ -747,7 +745,7 @@ impl plonk::Circuit for Circuit { pk_d_old.inner(), v_old.clone(), rho_old, - psi_old, + psi_old.clone(), asset.inner(), rcm_old, is_native_asset.clone(), @@ -780,7 +778,7 @@ impl plonk::Circuit for Circuit { }; // ρ^new = nf^old - let rho_new = nf_old_pub.clone(); + let rho_new = nf_old.inner().clone(); // Witness psi_new let psi_new = assign_free_advice( @@ -864,41 +862,28 @@ impl plonk::Circuit for Circuit { 0, )?; - region.assign_advice( - || "split_flag", - config.advices[8], - 0, - || { - self.split_flag - .map(|split_flag| pallas::Base::from(split_flag as u64)) - }, - )?; - - nf_old - .inner() - .copy_advice(|| "nf_old", &mut region, config.advices[9], 0)?; - nf_old_pub.copy_advice(|| "nf_old", &mut region, config.advices[0], 1)?; + split_flag.copy_advice(|| "split_flag", &mut region, config.advices[8], 0)?; is_native_asset.copy_advice( || "is_native_asset", &mut region, - config.advices[1], - 1, + config.advices[9], + 0, )?; asset .inner() .x() - .copy_advice(|| "asset_x", &mut region, config.advices[2], 1)?; + .copy_advice(|| "asset_x", &mut region, config.advices[0], 1)?; asset .inner() .y() - .copy_advice(|| "asset_y", &mut region, config.advices[3], 1)?; + .copy_advice(|| "asset_y", &mut region, config.advices[1], 1)?; // `diff_asset_x_inv` and `diff_asset_y_inv` will be used to prove that // if is_native_asset = 0, then asset != native_asset. region.assign_advice( || "diff_asset_x_inv", - config.advices[4], + config.advices[2], 1, || { self.asset.map(|asset| { @@ -922,7 +907,7 @@ impl plonk::Circuit for Circuit { )?; region.assign_advice( || "diff_asset_y_inv", - config.advices[5], + config.advices[3], 1, || { self.asset.map(|asset| { @@ -945,30 +930,8 @@ impl plonk::Circuit for Circuit { }, )?; - pk_d_old.inner().x().copy_advice( - || "pk_d_old_x", - &mut region, - config.advices[6], - 1, - )?; - pk_d_old.inner().y().copy_advice( - || "pk_d_old_y", - &mut region, - config.advices[7], - 1, - )?; - derived_pk_d_old.inner().x().copy_advice( - || "derived_pk_d_old_x", - &mut region, - config.advices[8], - 1, - )?; - derived_pk_d_old.inner().y().copy_advice( - || "derived_pk_d_old_y", - &mut region, - config.advices[9], - 1, - )?; + psi_old.copy_advice(|| "psi_old", &mut region, config.advices[4], 1)?; + psi_nf.copy_advice(|| "psi_nf", &mut region, config.advices[5], 1)?; config.q_orchard.enable(&mut region, 0) }, @@ -1226,6 +1189,8 @@ mod tests { let path = MerklePath::dummy(&mut rng); let anchor = path.root(spent_note.commitment().into()); + let psi_old = spent_note.rseed().psi(&spent_note.rho()); + ( Circuit { path: Value::known(path.auth_path()), @@ -1234,9 +1199,11 @@ mod tests { pk_d_old: Value::known(*sender_address.pk_d()), v_old: Value::known(spent_note.value()), rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), + psi_old: Value::known(psi_old), rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), alpha: Value::known(alpha), ak: Value::known(ak), nk: Value::known(nk), @@ -1426,6 +1393,7 @@ mod tests { psi_old: Value::unknown(), rcm_old: Value::unknown(), cm_old: Value::unknown(), + psi_nf: Value::unknown(), alpha: Value::unknown(), ak: Value::unknown(), nk: Value::unknown(), @@ -1483,42 +1451,41 @@ mod tests { let fvk: FullViewingKey = (&sk).into(); let sender_address = fvk.address_at(0u32, Scope::External); let rho_old = Nullifier::dummy(&mut rng); - let spent_note = Note::new( + let note = Note::new( sender_address, NoteValue::from_raw(40), asset_base, rho_old, &mut rng, ); + let spent_note = if split_flag { + note.create_split_note(&mut rng) + } else { + note + }; (fvk, spent_note) }; let output_value = NoteValue::from_raw(10); - let (dummy_sk, fvk, scope, nf_old, v_net) = if split_flag { - let sk = SpendingKey::random(&mut rng); - let fvk: FullViewingKey = (&sk).into(); + let (scope, v_net) = if split_flag { ( - Some(sk), - fvk.clone(), Scope::External, - spent_note.nullifier(&fvk), // Split notes do not contribute to v_net. // Therefore, if split_flag is true, v_net = - output_value NoteValue::zero() - output_value, ) } else { ( - None, - spent_note_fvk.clone(), spent_note_fvk .scope_for_address(&spent_note.recipient()) .unwrap(), - spent_note.nullifier(&spent_note_fvk), spent_note.value() - output_value, ) }; - let ak: SpendValidatingKey = fvk.clone().into(); + + let nf_old = spent_note.nullifier(&spent_note_fvk); + let ak: SpendValidatingKey = spent_note_fvk.clone().into(); let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); @@ -1539,8 +1506,8 @@ mod tests { let anchor = path.root(spent_note.commitment().into()); let spend_info = SpendInfo { - dummy_sk, - fvk, + dummy_sk: None, + fvk: spent_note_fvk, scope, note: spent_note, merkle_path: path, @@ -1623,6 +1590,7 @@ mod tests { psi_old: circuit.psi_old, rcm_old: circuit.rcm_old.clone(), cm_old: Value::known(random_note_commitment(&mut rng)), + psi_nf: circuit.psi_nf, alpha: circuit.alpha, ak: circuit.ak.clone(), nk: circuit.nk, diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 646bef288..919b2c10b 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -1,13 +1,16 @@ //! Gadgets used in the Orchard circuit. use ff::Field; +use group::Curve; +use pasta_curves::arithmetic::CurveExt; use pasta_curves::pallas; use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip}; +use crate::circuit::gadget::mux_chip::{MuxChip, MuxInstructions}; use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; use crate::note::AssetBase; use halo2_gadgets::{ - ecc::{chip::EccChip, EccInstructions, FixedPointBaseField, Point, X}, + ecc::{chip::EccChip, chip::EccPoint, EccInstructions, FixedPointBaseField, Point, X}, poseidon::{ primitives::{self as poseidon, ConstantLength}, Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, @@ -128,6 +131,28 @@ where ) } +/// Witnesses split_flag. +pub(in crate::circuit) fn assign_split_flag( + layouter: impl Layouter, + column: Column, + split_flag: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + split_flag.map(|split_flag| { + if split_flag { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) +} + /// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. /// /// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers @@ -138,6 +163,7 @@ pub(in crate::circuit) fn derive_nullifier< EccChip: EccInstructions< pallas::Affine, FixedPoints = OrchardFixedBases, + Point = EccPoint, Var = AssignedCell, >, >( @@ -145,10 +171,12 @@ pub(in crate::circuit) fn derive_nullifier< poseidon_chip: PoseidonChip, add_chip: AddChip, ecc_chip: EccChip, + mux_chip: MuxChip, rho: AssignedCell, psi: &AssignedCell, cm: &Point, nk: AssignedCell, + split_flag: AssignedCell, ) -> Result, plonk::Error> { // hash = poseidon_hash(nk, rho) let hash = { @@ -173,17 +201,37 @@ pub(in crate::circuit) fn derive_nullifier< // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. // let product = { - let nullifier_k = FixedPointBaseField::from_inner(ecc_chip, NullifierK); + let nullifier_k = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK); nullifier_k.mul( layouter.namespace(|| "[poseidon_output + psi] NullifierK"), scalar, )? }; - // Add cm to multiplied fixed base to get nf - // cm + [poseidon_output + psi] NullifierK - cm.add(layouter.namespace(|| "nf"), &product) - .map(|res| res.extract_p()) + // Add cm to multiplied fixed base + // nf = cm + [poseidon_output + psi] NullifierK + let nf = cm.add(layouter.namespace(|| "nf"), &product)?; + + // Add NullifierL to nf + // split_note_nf = NullifierL + nf + let nullifier_l = Point::new_from_constant( + ecc_chip.clone(), + layouter.namespace(|| "witness NullifierL constant"), + pallas::Point::hash_to_curve("z.cash:Orchard")(b"L").to_affine(), + )?; + let split_note_nf = nullifier_l.add(layouter.namespace(|| "split_note_nf"), &nf)?; + + // Select the desired nullifier according to split_flag + Ok(Point::from_inner( + ecc_chip, + mux_chip.mux( + layouter.namespace(|| "mux on nf"), + &split_flag, + nf.inner(), + split_note_nf.inner(), + )?, + ) + .extract_p()) } pub(in crate::circuit) use crate::circuit::commit_ivk::gadgets::commit_ivk; diff --git a/src/circuit_description b/src/circuit_description index ffb19ab6f..8078e15f1 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -447,97 +447,6 @@ PinnedVerificationKey { ), ), ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), - ), - Sum( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - Negated( - Advice { - query_index: 10, - column_index: 0, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - ), Product( Product( Product( @@ -596,10 +505,10 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 11, - column_index: 1, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, Sum( @@ -608,10 +517,10 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 11, - column_index: 1, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, ), @@ -676,16 +585,16 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 11, - column_index: 1, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, Sum( Advice { - query_index: 12, - column_index: 2, + query_index: 10, + column_index: 0, rotation: Rotation( 1, ), @@ -756,16 +665,16 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 11, - column_index: 1, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, Sum( Advice { - query_index: 13, - column_index: 3, + query_index: 11, + column_index: 1, rotation: Rotation( 1, ), @@ -842,10 +751,10 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 11, - column_index: 1, + query_index: 9, + column_index: 9, rotation: Rotation( - 1, + 0, ), }, ), @@ -854,8 +763,8 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 12, - column_index: 2, + query_index: 10, + column_index: 0, rotation: Rotation( 1, ), @@ -867,8 +776,8 @@ PinnedVerificationKey { ), ), Advice { - query_index: 14, - column_index: 4, + query_index: 12, + column_index: 2, rotation: Rotation( 1, ), @@ -885,8 +794,8 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 13, - column_index: 3, + query_index: 11, + column_index: 1, rotation: Rotation( 1, ), @@ -898,8 +807,8 @@ PinnedVerificationKey { ), ), Advice { - query_index: 15, - column_index: 5, + query_index: 13, + column_index: 3, rotation: Rotation( 1, ), @@ -986,107 +895,16 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 16, - column_index: 6, - rotation: Rotation( - 1, - ), - }, - Negated( - Advice { - query_index: 18, - column_index: 8, - rotation: Rotation( - 1, - ), - }, - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 18, - column_index: 18, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), - ), - Sum( - Advice { - query_index: 17, - column_index: 7, + query_index: 14, + column_index: 4, rotation: Rotation( 1, ), }, Negated( Advice { - query_index: 19, - column_index: 9, + query_index: 15, + column_index: 5, rotation: Rotation( 1, ), @@ -1239,7 +1057,7 @@ PinnedVerificationKey { Product( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -1248,7 +1066,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000400, ), Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -1272,20 +1090,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1295,12 +1113,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1310,12 +1128,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1390,20 +1208,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1413,12 +1231,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1428,12 +1246,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -1515,7 +1333,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -1639,7 +1457,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1803,7 +1621,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -1953,7 +1771,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2079,7 +1897,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2218,7 +2036,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2362,7 +2180,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2506,7 +2324,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2648,7 +2466,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2790,7 +2608,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2890,7 +2708,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -2990,7 +2808,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3090,7 +2908,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3190,7 +3008,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3319,7 +3137,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -3410,8 +3228,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -3422,8 +3240,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -3437,8 +3255,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -3452,8 +3270,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 18, + column_index: 18, rotation: Rotation( 0, ), @@ -3857,7 +3675,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -3883,7 +3701,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4101,7 +3919,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4662,7 +4480,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4688,7 +4506,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -4906,7 +4724,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -5405,7 +5223,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -5421,7 +5239,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -5432,14 +5250,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -5448,7 +5266,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -5740,7 +5558,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -5766,7 +5584,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -5968,7 +5786,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -6089,7 +5907,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -6241,7 +6059,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -6328,7 +6146,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -6344,7 +6162,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -6355,14 +6173,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -6371,7 +6189,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -6497,7 +6315,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -6523,7 +6341,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -6741,7 +6559,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -6878,7 +6696,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -7046,7 +6864,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -7130,7 +6948,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -7230,7 +7048,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7242,7 +7060,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -7258,7 +7076,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7270,7 +7088,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -7375,7 +7193,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7387,7 +7205,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -7406,7 +7224,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 22, + query_index: 21, column_index: 1, rotation: Rotation( -1, @@ -7423,7 +7241,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -7435,7 +7253,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 20, + query_index: 17, column_index: 9, rotation: Rotation( -1, @@ -7455,7 +7273,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 21, column_index: 1, rotation: Rotation( -1, @@ -7650,7 +7468,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -7850,7 +7668,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -7960,7 +7778,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -7971,7 +7789,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -8070,7 +7888,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -8096,7 +7914,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -8211,7 +8029,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -8246,7 +8064,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -8380,7 +8198,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -8415,7 +8233,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -10777,7 +10595,7 @@ PinnedVerificationKey { }, Sum( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -10883,7 +10701,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -10892,7 +10710,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -10909,7 +10727,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -10918,7 +10736,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -11014,7 +10832,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -11434,7 +11252,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -11802,7 +11620,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -12147,7 +11965,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -12492,7 +12310,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -13032,7 +12850,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -13042,7 +12860,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -13053,7 +12871,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -13188,7 +13006,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -13198,7 +13016,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -13209,7 +13027,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -13344,7 +13162,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -13354,7 +13172,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -13365,7 +13183,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -13452,7 +13270,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 21, + query_index: 20, column_index: 6, rotation: Rotation( -1, @@ -13468,7 +13286,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -13568,7 +13386,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -13659,7 +13477,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -15249,14 +15067,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -15276,14 +15094,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -15302,7 +15120,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -15343,7 +15161,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -15860,7 +15678,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -15979,7 +15797,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -15991,7 +15809,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -16105,7 +15923,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -16223,7 +16041,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -16232,7 +16050,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -16240,7 +16058,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -17636,7 +17454,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -17766,7 +17584,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -17872,7 +17690,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -18082,7 +17900,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -18094,7 +17912,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -18224,7 +18042,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -18235,7 +18053,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -18591,7 +18409,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -18602,7 +18420,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -18953,7 +18771,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -18964,7 +18782,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -19297,7 +19115,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -19326,7 +19144,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -19792,7 +19610,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -19922,7 +19740,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -20021,7 +19839,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -20126,7 +19944,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -20231,14 +20049,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -20373,7 +20191,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -20531,7 +20349,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -20646,7 +20464,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -20767,14 +20585,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -21056,7 +20874,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -21214,7 +21032,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -21329,7 +21147,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -21450,14 +21268,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -21593,7 +21411,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -21604,7 +21422,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -21762,7 +21580,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -21877,14 +21695,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -21998,7 +21816,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -22119,14 +21937,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -22397,7 +22215,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -22682,7 +22500,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -22925,7 +22743,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -23046,7 +22864,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -23288,7 +23106,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -23300,7 +23118,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -23446,7 +23264,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -23457,7 +23275,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -23861,7 +23679,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -23872,7 +23690,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -24271,7 +24089,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -24282,7 +24100,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -24663,7 +24481,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -24692,7 +24510,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -25222,7 +25040,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -25368,7 +25186,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -25483,7 +25301,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -25604,7 +25422,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -25725,14 +25543,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -25867,7 +25685,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -26025,7 +25843,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -26140,7 +25958,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -26261,14 +26079,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -26502,7 +26320,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -26612,7 +26430,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -26679,7 +26497,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -26752,14 +26570,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -26847,7 +26665,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -26858,7 +26676,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -26968,7 +26786,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -27035,14 +26853,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -27108,7 +26926,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -27181,14 +26999,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -27363,7 +27181,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 16, + query_index: 22, column_index: 6, rotation: Rotation( 1, @@ -27552,7 +27370,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 8, rotation: Rotation( 1, @@ -27699,7 +27517,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -27772,7 +27590,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -28037,7 +27855,7 @@ PinnedVerificationKey { ), ( Column { - index: 6, + index: 9, column_type: Advice, }, Rotation( @@ -28046,16 +27864,16 @@ PinnedVerificationKey { ), ( Column { - index: 7, + index: 9, column_type: Advice, }, Rotation( - 1, + -1, ), ), ( Column { - index: 8, + index: 7, column_type: Advice, }, Rotation( @@ -28064,7 +27882,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 8, column_type: Advice, }, Rotation( @@ -28073,7 +27891,7 @@ PinnedVerificationKey { ), ( Column { - index: 9, + index: 6, column_type: Advice, }, Rotation( @@ -28082,7 +27900,7 @@ PinnedVerificationKey { ), ( Column { - index: 6, + index: 1, column_type: Advice, }, Rotation( @@ -28091,11 +27909,11 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 6, column_type: Advice, }, Rotation( - -1, + 1, ), ), ( @@ -28495,7 +28313,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 19, + query_index: 16, column_index: 9, rotation: Rotation( 1, @@ -28855,7 +28673,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 17, + query_index: 18, column_index: 7, rotation: Rotation( 1, @@ -29069,48 +28887,48 @@ PinnedVerificationKey { (0x3a83a8e762ebade712aa5cf3c41c730a79369475085bf1155579f7f7682408e2, 0x25b00d3ee1da9a6bbd36b35ba461da45abd931c767b863ec4a604f8ce094e4eb), (0x1caeb4d7ebb44a717f83ee5afd35446a5e2124f6a4075342ba4eff589523fb57, 0x3a8c431a13632a5b5f035eb4b804d37f2591e84d05d765ba3f70a3d61b907ebb), (0x107d95a6361fc98df9042f32451faa4fd48c1381653be7847d97cf997a55a4ad, 0x31ebf6a2e352108bb180c3278e72d88bb5bab723d3b38aa47c144fc37fb8a962), - (0x23d190a42430492732de147e7560ae1387a0e8c6b0dc405b893c99c34d124152, 0x0f7f1cb9cd7c701f22270a68d9cb484b4fffdc6144c8ce3f4eca5b646f8a939f), - (0x2b0f9d7b69e1f353868a4d542b7a23f24f39335b16c3a46fca1edb12a69bb350, 0x1e4ac9f6f6d4ba4fa4cd21e669b8293e3be8c143c795d2eb31503a9389ad4314), - (0x28f1ed28efc008bcec444c440ddbe60a8e58fe5b9a6047f0bf4d8abf599cc4ed, 0x180eef569a332ec094a76dd55de8f8ef4f087465bb2abc8dd5f7a265e048e84f), - (0x36608273abc0c47131ee4cb410b4e936fe693e9e034c686e188438d5eab134cd, 0x304e3ffef142c51a5a081a977f9c2581fa18a356e080d20cf10a044e46a3c802), - (0x355228aaa5e1134d08305d64d86cca7abac7c4114252a2a71df6a40d6a3633a9, 0x2d492e1c28cf94f9a074b14cb4cfd0cabd46121faa034d887c5f07cb743464e2), - (0x31fe923865ff58a9e59393bf64ebff3f25831371afbd2de5ddf147519ad6160a, 0x30449e9123aee5a61d3ed4c9e5822e2f60184a6c4234cfd61575e9f9572f370e), - (0x0e24cddb59a4615d0595e5439fca547a3f1ed39c4a2b0879d7e8603306d9e4b5, 0x35ab4acd6912b9bc66c19ebc9845886a4828bac17246137e36f924df2f9be175), - (0x3bd9f4407fcbb3e4ec812de2c53e70fb9203381f5a1c0f4c5e5fa52b932f5ac1, 0x06d8356f6b642427ddfad6e3642e40c0b29034baf9adb19c8a3ab251b16f39ef), - (0x21e3606f857180611036daa84bee713ff0b360b6282adc5bbaa40a5f6f7e6bc7, 0x3bff3cd61a5ae314f5eead93e3084c60a31e8b794186061a24ffa5a5dcd7e0f5), + (0x20700a506e3d86a64a39b130676dddce5f1b2bf0334fec71ed2551c204822c67, 0x3b6942d1884ab8af10fad654411308e22b2cd04efc964b92fd921678436c0c98), + (0x01050032408d33b1dfaede46b04fa62672309dd6068c0833589f4c8080e829a2, 0x0e3f605da6ff82b3aa6ad00dcf43b9478f05ff876599522bf6e560d3d014fc34), + (0x3de6d72fbecfa7c79cc390c6a7d5f80f1bcdb6ec66967002c0f003890ca6e1fb, 0x188d7336a6662b8e16e4b3a279958e60dbe1f86bfdbc1dca253db40235430f44), + (0x1581f8e414673d197d0cd5730da9bb65faae27e4a7aa70055f1c92d70fa31f7d, 0x3262ae14b4137e321618661aa7a5f4b817ff8b2846d9362813da34512c6bd965), + (0x21c96b5ae31bc87ecc34afaeb56d6c155b624b22f23f474ea80fc0bc7312735d, 0x123f4ffff944155267ab11f68de7573cb27a78b30d96ad315756086adfc75137), + (0x17a4fffca31db428439c483107a7b92f8b81451bb66892f2e8b2e4a3f2181083, 0x31f214f9e19e6282a502fd0984b81b9f7c761d66236e7600049e45ec7acfe778), + (0x31efd1ed8ab3ef69dd0a927b9c371fc0e9a2dfbd3586c5f596133f2605445850, 0x28da702b4e3f6df487b6530829a48751c10557127d11b0056c7c581091a8e03e), + (0x098c8a506a6d33d2744d0e1810c2b5070d49f597c8b87fcef67ee008da94f56c, 0x3d7dd49111a5e9834dbd5c1fee58ceae6ac758ee167522843fbb50bd95715cab), + (0x17c91b96eabea3a9ff280ae99e74bb96e80e14d770cf5d0a35814500c08159ac, 0x021d68cbd102f26c8c1b849312c3970f06d0e8c4733d325c5247137da3f940eb), (0x3c0f3f0d7b2306490dac7d578d4846c63adcc76988ce322d8691c3b8b5b0f623, 0x12d81ca672a1c18f6e0d9b7eb8fbabdbe450fae6667cf349c1a0e63ca9a0824e), (0x27d13b33003ffddcd36efb731fe94db93d181bd994e0c057e945402bc8501789, 0x0e1dde94ea3b35e0d0a66350163ba2ff9dd5070500912b7d076747816965ffd2), - (0x3049e9c8a3e6c7fe628660121f04915e03546b7a2dcb8a3e59fa99546e4f7f86, 0x2dcebc740917584f788b776f4cf1e3cd96b4a29e9df7224fd8e5f428d4112546), + (0x3fdc611a96e66e8f5c21c211bff2006204c4884b2c6df9b55d92420af8e32d15, 0x0a525125d5a85a579cbc8e4862b88800d7dbaf8a8adc18bd0181bbbab9434b8d), (0x245ebb4ccefa7c4e2d5a9d7b1746b8277abc25f74cd11b2dbb752d49612f248e, 0x145f605111205a7c3e4620ac035b3cccb6375f8d3c3469b7900e427607c401c9), (0x1751912a19fa0009ece61b686342d6b4385415e942159e8db3f174ad24d612b9, 0x0f31114ef566211d46914d0bc2d1a27a0e34eeda04dab53a0af7a37024f057a1), (0x091c6c4854fa5d9ed8a966f2a1c4946b41f6872de6c19fa8b521a0a8eb2bd899, 0x29100b4e15344d750fae4a81c82faca1e8e0573336b1f54b394946e95e7baad0), - (0x1a5bb6ffd1af2165203df63414021a531f0f2bfcec85443a180993cc222b40af, 0x0d6b8b0d2363607d15746434b670008845ed0524406c1d8a221cb6f58ee2d4ed), - (0x0e3ead6853e036099146875357a97c73327ac7aac89df7af91e8e126cf1adb3d, 0x16e19a920aa5d52ec2bb18e595b12cc3f65ae6703af8c088c3741ec59acdde8a), + (0x0f1d83f1dd2f4ba4d92cae2a2f40fc6d5d66fb2b6d1f1a2e981931cfc7c751af, 0x385ae95bb483cc65bb507d8418e447a7ad8346bc52b5114913d1e2c25c0fd11d), + (0x070664e70f0b48311a30b833a6b93cdf4ab06b872f28a723b935c88802275bd0, 0x1a3c22a9ff9d9d5434b8b979d6635d135d909b143927bc90a96cde88c6e93331), (0x34c8b83a2cc924f1b0237978c8f911e6a54375c509ba46456a011fbb74c8698c, 0x260cc681c222535c0030f702172ee8855b681c16d706b1b9a786165e06705de6), - (0x3dcb136a22551e524212c0325331a9dae5ad6ff356175e6b82a54039475be1ef, 0x3bbbd0d20ea0ebb0f36d740910947d1934bcb93ba16325ea42f124ec0cde7a81), + (0x1b7a61e8a9b32fe558433feec9aaf51204e5486aa468d7215087ed35fd6ecbe5, 0x1f36dc6852f92c141ba800f721d079ffc553c7449b85d16e7487e0c3009c7835), (0x3bb657ca32617e6242b6c6a0b166a1db205024d0441d091b8d45fb478cd4782c, 0x3189ce1b97103345fc0eafd287eed80ab186151171f22af2c9befc71a0957529), (0x25578b0a6d546cf38dc84329fad41e59690a2bd94a0db5fddb42e0db8c267827, 0x03448e4552625dda62a96318bcafcc305deafd6a028f8379d8c8d9ffa0f86e64), - (0x30d1828d7463255ad75b39ee4c718de05a762c45c5d717d059496fe05d1575b4, 0x0a8eb70a9b252ee9ee57b29e4dab191cbb29665821830b2ab60fdd5d3414de45), - (0x1bdd262015bc4b15fd90dcb6dea748cb9032fed094df3edfc0ca96c419c6ea9f, 0x28bad5ad4461b66303cb84925b54258e27953e8ef5e67c1057c823091a8562b9), - (0x09e15af05d50016fd1c475fbd3ae0be95289f239f13962f755f8b39732c73feb, 0x03760949d5057f33c30391474cbc3d447858da57e8b72487a98827b339993e60), - (0x0460fc7f74c9808eea035e8df3ac031c2d05ecafd8f0189f2d6ddac3274752fb, 0x2bc99ad7317625f1a1d6bca1781557b87e8b9976cdcaf994c827a0087d1ce182), - (0x31b7012d949d0668d34cb20200d4e159262aa0dd92114d3aa5e8aa84af51a802, 0x2eb9c55ed473e18e62dc273a8606f955690a984551fbc38e80d65199ab8d0c3d), - (0x33dced988c6a1d40aff3da1710a0e36a6b787fd6dae51ebe3dda7835c2dbea15, 0x3b54a967115d43feccf77c385dcfc6e89f30343457bc8921e017c930a381b5b0), + (0x3eab58caf9fc2aa3fee6d649cf087fe9bca284c27f57c08410b0f8a7e09d634c, 0x04b350dc56fe19a25da0882d2acb6622bdad1c4b3e2200d35acf689782c20da7), + (0x37e00880dbfd31f1c3f86201583025a666bf48745428ac39caa1d0a0acaa0bd9, 0x0ff8ef43177aa324665a296a9a444fb4a6666e250930a039a687e53acc43eddc), + (0x0934479f5c328fdb235ac47bf94cb8551784068de4fc26f0dcdca078138cb71d, 0x213f745ff2233ec74c310b142665e4e223643eb72607fc50b98aae5c7149c78f), + (0x1a98842473bddb61c943296a39cc0a8a41cec5aa02696bd0a97569ca9f839186, 0x08291ab77b541973368946a0d14c85c69a142bfda31f9021328c98b69be25e3c), + (0x34a41b2fa64d913ddc6df62a3b881658ee29bd5c69154dc30bee28d64acee443, 0x1d88f6fd73525eeb4e8b0531297edcd107bf3c2303dd615f34732d7fb01a9b16), + (0x0a6e085a051cab2808d58f29990b4ba83ed49fba5f363f67b78c329514ac79e5, 0x20b236e5722f4cff16ee1607ffa3bf60c63e9f866b27d85e85a0b06b0b8c58ec), ], permutation: VerifyingKey { commitments: [ - (0x01b2f977b5e96e2d00052aa77013b4a7522b714ed1265e5b761a90add04a677d, 0x06ae5604d2abf710e3720ab4ca37bc7a75cec4772624973990fe7acb95d2b90e), - (0x3487595fd169aea1e2055c38daf7b83a923600084a12f6beb068e9ef0886884b, 0x2094e9bc4aead08e32eb63939e7b365f7c4dbe7bb9e4fe439fe7855da2a8ef59), - (0x34b7b5583a32b3a2a188214b041b0402948759fbdf47b4b50421905728b78148, 0x10fafdf7f63a938d87eb031cbe61c6dd5915612ecb71865e94a7d7fdcb96f9c8), - (0x38b9b1352ef7da340b69e7d152d86c26abaa7eb8da2b2049c75eb908bc42dae1, 0x2b7880c4c7790b2bd4f603a95561e7e1f4fba95eba4096f6d44b89e4b0a16519), - (0x08b55ac77535aa391210533786aa9a62215fe2cb6950b60dde6563f8c4f47d58, 0x1ca42aafc1ae6e8554a933225daae97222e08a59c866024a936f66e45455c47b), - (0x3b23fca8ae9ee4f186c654428419b16169777a1b5cf7e959f73de3fd21cf1403, 0x3ff330b5247e4a88c38452e3bbaf20c79cff67a4a5b91c5ac3c6614d8cc17119), - (0x39c00327041f3b0a21cc10acacd55a94f968770121fb55e8bee01e146ea024a1, 0x38c3af47f4278d74e808aeecaf9407b17757384e9d50b59500604c7bb86687cd), - (0x0fe245acf5779d18b38c28fd4f6d921bb5487579d1fd257b7ea48f8d6de2db2f, 0x1f8a5b90451fa159c9c517a0b7250787d86c63555659298bb7ca10c537e94e12), - (0x13f4c48990bdcadf99fc60d63b04eb82f26dc2c59b515f265a66c2732abd0205, 0x20dbafa9a43baccfc5ee6947bc408b1e8974af2f5c141f3f704a747e194f04f0), - (0x16d8e8e787a2dfde1ec419ce969aa5a6c23b9d703a7440a6f085cb1fbbb21a57, 0x217624d76f302eb4f3a4f9bd3968fa79f66e4b06b5bc72048b979fb58b1f29d7), - (0x0f74011b79a40415b90f8f22db1a1433b7336307801cfe97b84f60bf7cb15d44, 0x10f2a0765e05ab426d0b183ad84616438187efbfb6122540d768895324d42667), - (0x2139a7b9a8c74648139b556ae77015620edcc81cf0a89cc960a57e16c4346a0b, 0x0295889e3496dac3174b2ba3c5399b78d9ecf042730cede62d37f6f0bfc021b6), + (0x3b61bede3f87e9208caf3626fbe7a645e1b9f9b241a96160c68b708196e86cbb, 0x0932e9c67d6bb593c9b3d6bd9697efe79bb2f81bee35abeaa8a2a0a828d8fcc6), + (0x07800024b352149368405f222a8dfbf373bd4603df89929a5d00f7ac9ffac504, 0x250be8a84de9a8ded91e85860f1b1751f6bd2c0aba96329ee2d6f0e377f4679f), + (0x3384b0dbfa6553ad5adf0b218df2cbe6243c33102a97774b4e023ec1dc2d83e9, 0x2873fe49458cd70b9d72419e0d6a6ceadb8070f4b62a0bb47c58a89269e0b583), + (0x38def0fd8f233ef8651a28ffb7ae6f1e4eaeb0acec19453a3e5a0d70b2058782, 0x0512c67736284a225f0b6617cabd76ac2e4a6805940af4480798ca884e02d277), + (0x26b6d69fd8c13013c6ab5fb74bd3fbe85d01b0abb57e149ff53e77a535c6bf40, 0x05ae4f52e4ab72ff3cf2b64df6d371fda270f4f78ed0bccce8e3138d4e30e4a0), + (0x3f1b6f3ea5a2b24646dbe1c6f7c7dbf797fe6602a344bed59668ba5413519631, 0x0401a6f6ed893aa112f234127f8c30ee6e09b45f75993351aea9974389b261d6), + (0x2f34843015cfc9c9ff59c7ecab3cbb6aea69dcf6f5af79e166f25d90f70353d5, 0x2bcfde5880412d171705b41124b404a323697c4d1008b2e8b2bf9966e5809d3d), + (0x1241f0e0058575ff769809aa569ab0ff12d5b2d7d840eae76912c16433be00ff, 0x33339365e1edbdb387b0a0b7dc5a9212c0313bb0a131c9302bc57db36174f3b0), + (0x240a361e73afa04a2e5cc578680e54bf28e3375dbb35a8918c3cdbc91f1bc25b, 0x161c53e65c1b6500b576d8fa982e2565dbe35954840b0bab8a3d912158b9dbe7), + (0x32f883bbd63b0700f0150ea8d71f6f5d7cdcc4463289983d71e9bc104d4a5c28, 0x33aeb42bec794138b8db28696bd7cef4946a8a89edcbf3f8289655ff9f9129ee), + (0x03f33d3064517ab1a8e538444013bd0d6b011f9923f8cb964763a88d6d7409e0, 0x16f534b6d12d9e011b951e374982f048f0bed808099fd3ed97cd827360f6fb65), + (0x0ee42598f7ed2c349d720bdcbe34f85d6650e1b3f2add5a71ab0bf330fcd4f51, 0x346a2c51d2895839bb3e556eb20e6af8f5248f2d538a1407622c9d69bde1448a), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 9d541d63f1f5e947978137c33c8705bebd8de2b4..695d163d99d1571649c59a9557e1362a49f391a5 100644 GIT binary patch literal 5250 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 IYufqsJ*i3!z5oCK literal 5250 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 Self { + let result: Vec = + a.0.iter() + .zip(b.0.iter()) + .map(|(a_i, b_i)| u8::conditional_select(a_i, b_i, choice)) + .collect(); + RandomSeed(<[u8; 32]>::try_from(result).unwrap()) + } +} + /// A discrete amount of funds received by an address. #[derive(Debug, Copy, Clone)] pub struct Note { @@ -104,6 +115,10 @@ pub struct Note { rho: Nullifier, /// The seed randomness for various note components. rseed: RandomSeed, + /// The seed randomness for split notes. + /// + /// If it is not a split note, this field is `None`. + rseed_split_note: CtOption, } impl PartialEq for Note { @@ -144,6 +159,7 @@ impl Note { asset, rho, rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()), }; CtOption::new(note, note.commitment_inner().is_some()) } @@ -219,6 +235,11 @@ impl Note { &self.rseed } + /// Returns the rseed_split_note value of this note. + pub fn rseed_split_note(&self) -> CtOption { + self.rseed_split_note + } + /// Derives the ephemeral secret key for this note. pub(crate) fn esk(&self) -> EphemeralSecretKey { EphemeralSecretKey(self.rseed.esk(&self.rho)) @@ -264,13 +285,25 @@ impl Note { /// Derives the nullifier for this note. pub fn nullifier(&self, fvk: &FullViewingKey) -> Nullifier { + let selected_rseed = self.rseed_split_note.unwrap_or(self.rseed); + Nullifier::derive( fvk.nk(), self.rho.0, - self.rseed.psi(&self.rho), + selected_rseed.psi(&self.rho), self.commitment(), + self.rseed_split_note.is_some(), ) } + + /// Create a split note which has the same values than the input note except for + /// `rseed_split_note` which is equal to a random seed. + pub fn create_split_note(self, rng: &mut impl RngCore) -> Self { + Note { + rseed_split_note: CtOption::new(RandomSeed::random(rng, &self.rho), 1u8.into()), + ..self + } + } } /// An encrypted note. @@ -308,6 +341,8 @@ pub mod testing { address::testing::arb_address, note::nullifier::testing::arb_nullifier, value::NoteValue, }; + use subtle::CtOption; + use super::{Note, RandomSeed}; prop_compose! { @@ -331,6 +366,7 @@ pub mod testing { asset, rho, rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()), } } } @@ -349,6 +385,7 @@ pub mod testing { asset: AssetBase::native(), rho, rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()) } } } @@ -367,6 +404,7 @@ pub mod testing { asset, rho, rseed, + rseed_split_note: CtOption::new(rseed, 0u8.into()), } } } diff --git a/src/note/nullifier.rs b/src/note/nullifier.rs index a18e77fef..51769fdbf 100644 --- a/src/note/nullifier.rs +++ b/src/note/nullifier.rs @@ -3,7 +3,7 @@ use halo2_proofs::arithmetic::CurveExt; use memuse::DynamicUsage; use pasta_curves::pallas; use rand::RngCore; -use subtle::CtOption; +use subtle::{Choice, ConditionallySelectable, CtOption}; use super::NoteCommitment; use crate::{ @@ -55,10 +55,18 @@ impl Nullifier { rho: pallas::Base, psi: pallas::Base, cm: NoteCommitment, + is_split_note: Choice, ) -> Self { let k = pallas::Point::hash_to_curve("z.cash:Orchard")(b"K"); + let l = pallas::Point::hash_to_curve("z.cash:Orchard")(b"L"); - Nullifier(extract_p(&(k * mod_r_p(nk.prf_nf(rho) + psi) + cm.0))) + let nullifier = k * mod_r_p(nk.prf_nf(rho) + psi) + cm.0; + let split_note_nullifier = nullifier + l; + + let selected_nullifier = + pallas::Point::conditional_select(&nullifier, &split_note_nullifier, is_split_note); + + Nullifier(extract_p(&(selected_nullifier))) } } From 21d7273e49ea5f82f2def32916c390aa039af9b6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 23 Jun 2023 13:06:48 +0200 Subject: [PATCH 41/92] Use tag instead of branch for zcash_note_encryption (librustzcash) ref in root Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 006f98c3a..484210f8d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,4 +92,4 @@ debug = true debug = true [patch.crates-io] -zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", branch = "upgrade_for_orchard_v05_new" } +zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", tag = "O.5_compatible" } From 62d4ae70aede0632bc9a6a6e226a55c3204aa23b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 23 Jun 2023 14:08:23 +0200 Subject: [PATCH 42/92] Change tag name for zcash_note_encryption in root Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 484210f8d..0e7f64ea6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,4 +92,4 @@ debug = true debug = true [patch.crates-io] -zcash_note_encryption = { git = "https://github.com/QED-it/librustzcash.git", tag = "O.5_compatible" } +zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/librustzcash.git", tag = "orchard_zsa_0.5.0_compatible" } From ff2ac96b247f5879b15ebbf09d0bd8fb36a69770 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 29 Jun 2023 13:03:27 +0200 Subject: [PATCH 43/92] Circuit: Add constraints (#77) Add the constraint: (split_flag=1) => (is_native_asset=0) Replace the constraint: (v_old=0) or (root=anchor) by the constraint: (v_old=0 and split_flag=0) or (root=anchor) Limit the version of half (< 2.3) because recent half versions required at least rust version 1.70. --- Cargo.toml | 1 + src/circuit.rs | 79 +++++++++++++++++++------- src/circuit_description | 96 +++++++++++++++++++++++++++++--- src/circuit_proof_test_case.bin | Bin 5250 -> 5250 bytes 4 files changed, 149 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0e7f64ea6..3ad6adfb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] bridgetree = "0.3" +half = ">= 1.8, < 2.3" criterion = "0.3" halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" diff --git a/src/circuit.rs b/src/circuit.rs index 99a35b1d9..a8164c7bc 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -224,12 +224,13 @@ impl plonk::Circuit for Circuit { // Constrain split_flag to be boolean // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - // Constrain v_old = 0 or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Constrain (v_old = 0 and split_flag = 0) or (calculated root = anchor) (https://p.z.cash/ZKS:action-merkle-path-validity?partial). // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). // Constrain is_native_asset to be boolean // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset // Constraint if split_flag = 0 then psi_old = psi_nf + // Constraint if split_flag = 1, then is_native_asset = 0 let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -276,9 +277,13 @@ impl plonk::Circuit for Circuit { - v_new.clone() - magnitude * sign, ), + // We already checked that + // * split_flag is boolean (just above), and + // * v_old is a 64 bit integer (in the note commitment evaluation). + // So, split_flag + v_old = 0 only when (split_flag = 0 and v_old = 0), no overflow can occur. ( - "v_old = 0 or root = anchor", - v_old.clone() * (root - anchor), + "(v_old = 0 and split_flag = 0) or (root = anchor)", + (v_old.clone() + split_flag.clone()) * (root - anchor), ), ( "v_old = 0 or enable_spends = 1", @@ -307,13 +312,17 @@ impl plonk::Circuit for Circuit { // is not equal to zero, we will prove that it is invertible. ( "(is_native_asset = 0) => (asset != native_asset)", - (one.clone() - is_native_asset) + (one.clone() - is_native_asset.clone()) * (diff_asset_x * diff_asset_x_inv - one.clone()) * (diff_asset_y * diff_asset_y_inv - one.clone()), ), ( "(split_flag = 0) => (psi_old = psi_nf)", - (one - split_flag) * (psi_old - psi_nf), + (one - split_flag.clone()) * (psi_old - psi_nf), + ), + ( + "(split_flag = 1) => (is_native_asset = 0)", + split_flag * is_native_asset, ), ], ) @@ -1550,9 +1559,11 @@ mod tests { let (circuit, instance) = generate_circuit_instance(is_native_asset, split_flag, &mut rng); - check_proof_of_orchard_circuit(&circuit, &instance, true); + let should_pass = !(matches!((is_native_asset, split_flag), (true, true))); + + check_proof_of_orchard_circuit(&circuit, &instance, should_pass); - // Set cv_net to zero + // Set cv_net to be zero // The proof should fail let instance_wrong_cv_net = Instance { anchor: instance.anchor, @@ -1565,7 +1576,7 @@ mod tests { }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_cv_net, false); - // Set rk_pub to dummy VerificationKey + // Set rk_pub to be a dummy VerificationKey // The proof should fail let instance_wrong_rk = Instance { anchor: instance.anchor, @@ -1578,7 +1589,7 @@ mod tests { }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_rk, false); - // Set cm_old to random NoteCommitment + // Set cm_old to be a random NoteCommitment // The proof should fail let circuit_wrong_cm_old = Circuit { path: circuit.path, @@ -1606,7 +1617,7 @@ mod tests { }; check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); - // Set cmx_pub to random NoteCommitment + // Set cmx_pub to be a random NoteCommitment // The proof should fail let instance_wrong_cmx_pub = Instance { anchor: instance.anchor, @@ -1619,19 +1630,47 @@ mod tests { }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_cmx_pub, false); - // If split_flag=0, set nf_old_pub to random Nullifier + // Set nf_old_pub to be a random Nullifier + // The proof should fail + let instance_wrong_nf_old_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: Nullifier::dummy(&mut rng), + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); + + // If split_flag = 0 , set psi_nf to be a random Pallas base element // The proof should fail if !split_flag { - let instance_wrong_nf_old_pub = Instance { - anchor: instance.anchor, - cv_net: instance.cv_net, - nf_old: Nullifier::dummy(&mut rng), - rk: instance.rk, - cmx: instance.cmx, - enable_spend: instance.enable_spend, - enable_output: instance.enable_output, + let circuit_wrong_psi_nf = Circuit { + path: circuit.path, + pos: circuit.pos, + g_d_old: circuit.g_d_old, + pk_d_old: circuit.pk_d_old, + v_old: circuit.v_old, + rho_old: circuit.rho_old, + psi_old: circuit.psi_old, + rcm_old: circuit.rcm_old.clone(), + cm_old: circuit.cm_old.clone(), + psi_nf: Value::known(pallas::Base::random(&mut rng)), + alpha: circuit.alpha, + ak: circuit.ak.clone(), + nk: circuit.nk, + rivk: circuit.rivk, + g_d_new: circuit.g_d_new, + pk_d_new: circuit.pk_d_new, + v_new: circuit.v_new, + psi_new: circuit.psi_new, + rcm_new: circuit.rcm_new.clone(), + rcv: circuit.rcv, + asset: circuit.asset, + split_flag: circuit.split_flag, }; - check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); + check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false); } } } diff --git a/src/circuit_description b/src/circuit_description index 8078e15f1..863c4e1e2 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -260,13 +260,22 @@ PinnedVerificationKey { ), ), Product( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), Sum( Advice { query_index: 4, @@ -913,6 +922,79 @@ PinnedVerificationKey { ), ), ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), Product( Product( Product( diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 695d163d99d1571649c59a9557e1362a49f391a5..5a8711554131107aeac547f3b033c40a9fc21d75 100644 GIT binary patch literal 5250 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 IeX+H@0}cNf+yDRo literal 5250 zcmV-|6n*Q>=*>gpSm06wtae#yYpwF`?{_#70dkip!bJ#dc;^sdRgzE`xqr+W)n)J! z*ra;dR>1)_>_q0w?Aa(5blH-tOXvcHO_3Ag0q`~p=W)t_fjBxiatVm-%?~nd=Xx=6 z36q?5Z-he(hrma=Opl!S+RrRYaey?qC&oBW8W%mU=P%EP@-75&)PR12f6-Y}Ufj-( zxBUjr%jjr;{nQ)*0Y9L;ZJO0KJp;4=x0NiieaQMChKJL48~GL;9zj|VxJMOClpD!W z4c0GN2zHu;y;VV9tTnW54(UaEJs+vUwdrcEAM-FNkUOA}W>=ZxnpufWXE;MGuphZdC>G0G*&CD;$vOM-cxB z)Npl)U8k|zvX7kHTQI7Uoxh%cKc$?m@rPxH0 zu!(T>1znO;Vt%`Jrx)j7wHHl=E2BBrtU()>Q2H>pm9qkR_f&5uA;icW(pGL3|I47U z7Z~p`A%3hilm1&q7RY;8Q+(&*?UPiHu>>%DYdE4jhFU<{#ME_SK!j(ZAZ-Xx(9J`G z1yWD~_wUiyJ2`g}mN%m}g|vuY`vUK1FV~qkoOE=B^%5^DB~Ll$c;kd56}dxQKViXm zD!zC*ktb#a`L~U-e*Dk|f?H$YyS=Jh0Ce5i&ugMBE#YIAV*0z}`|A(e1(pTZ5ZBXk-yvf@5OlcL7KnIYMlOuIjJ6F-8K zXNrRxoBXw5BX0}rCUwUZ_@donm1j#bMhB?t8H$5S_5)WzQKv<#fuo9Er@AzL4t&fu zBUzLj-xM+DpxPZ4p!B!97@kswC3>_u3S52M8{|qV$uMsma9OQxS%|AuEBa`M>UqTkN2$ z(16e{khvMsN1)d$De}q@`dL-{dr1XT@hsmAJy5)>sE}tNt}d(S67Bf6rSbEwWY#}G zmE~eShNdg$bn|f_Ine$a=+gh7oQ|!yW-F5Yhs3Yy|IrVLAl0JoF*qwKkWTk zhl*u~6+}pI9Rre89o-C_1-S|OM?`~m62?RMD{^is_23`pMFJ{gIj_wWY9G<~7^;m} zUiU=fiA>FRA~SS|JE`PH)Ctne0|+hghz&hFN`!}M@CHUNh>$mDFN)N!c9F6jWA`*d z$65Ner{f?IBi>oI)C%)0^%AQ~4pR0BEA@#%Vr!@3{YzE%x6-kk#K8RXBwWKJZK0AL_v~~(B@$&tIz?%oPMVq*I_YXEzqKt7Eu1a?nA0X)$8u_m zHda$cjx=;C6zt4rG@KqOC6lDQ`rRl> zjqrcm3|k9~=Vqkyy7&+aOn`>o(sE0k=fT%fY2 z&s|9UO+k4vcx7UU>fzOtJbprT2z8BN&2LN6;^Z7%3)NnJr{OtuO{j#c;8$AkhBUb1 z5=1N&W#CsMPH748&hu+L&U^&YwX7 zUk(Mq+YDvlO@4M={o2z!Jqp+H@7$52?p52KD}g*#q|n=t0uHf0v(<%Tj94@rGkG;Z zAnnv?T23+o_0LwM7ya|1%3z|!FVN+ zb{@x6-O9lAKCIJV62ah+L%n3JX1B_z8cX~Rlh{qlZhY)an(7qs2@z{>a{v(SRb9{- zG}Fx$;^n%cIPd-NUQB9*3z2ifC5H@Yc<^kjG4%z4FvcFfBu&j(S#^1;wwt0los3k; z1t#z$7*!>^IPL%#hhE@)@l_?AC)>zq^VWZr;2p@019Md+L|`&jhBUF+EC)#eG%oK34NO?t;%A2%$>ODAGqzgPl&tmw(}U z8QZ4wQcs@{&dVpXRQ%Qe0FH+`E-Dwr>mBm09w|gl@kW6`$^_5r>F#9VTxPQY1Og#*1B zEICYPf(CH5LNN~-eAiIcHKZq6WIAd&54@r(b9bVr0y7uFuot?<`!L4zp4^4`hps~p z!GC)!yBs!7cF;mk7oT-~@bKn&0{^`Bb2Dl7jHNAgcyLW!9DW8G+{?E6H0Yq)yFrK7 zwq@V|gi=b}|KE72H&Y{9RvlFHwf0?n1~BB1*1px`QKXw)mSL$tbLsd>!Y>?Hj=GO{ zZt`w_512$(SY*l7^j8^Tq=O;b$o%+zD_rFZ@mc+?V^4r2AFIpDr^M*p^IV`q+6@u@Chmn}PthVgOWQe7kbl_SrXa)51kF*Lu~ z6@7o@2JC|MA7EXkbx6{>E0d(m4>C3e%YaQI9K&q(62|nOkRj=O%ziz);q24fM#!d> z&UQse9VG<*KeC+hnuE-f#V&an3ocEL#)B)eb9FgA^O_2-lX*Xj2vZExn1-}tJEP`5 z!5MaEVAIh}6P;O`si7Up7ce=Zc#! zH1l}fW&B{VuD*U&`e$7^F)$94biDsEV+%N=vcbw z9dKpr-^2%{O_3f+5Tj}T66m{8-8z5r_{LnX+&x;YHAB6Ry?h1&5MDLO4K-C1Z}8&? zM&t*{5D7^U0~kT@2bLALA=c1mm2A}s4N_5LtFdXa;ZeBpMrvMGL$qD|$R$=Cg*A_$ z-)y@A9fL#S@e=&wt!!i9GKLkTO%7N6sIm;pY#XbA*QR0n4VfQL6yP$pZHe?82QAIT zk&E5G+$7{jH;-6}G%&u*C*a1Q^l}o5cI#LxA6gEXm~3i7J61vQKxJxiCE7L@A%I3Zy9^HvjRGlPGv=K2zL9vOlG^G^l+C-t?gV&2Fd}nBn9I> zY3MMw9IEb(to3(<^h9FW2$%z4O;nfa=X%Ftt#}(T0K8sHLi#+D?KI^O^o~i!7hb1HmTQ z1wpA$?W$@WwsP`O^M>#=_f9y5Jjxf|1*sU`Ay}(BLNm;PB;pO%iV}U_SNY-4<+4Hu z=%WDrRK{EH8sXrcJqIUe)*VL8Q=Ayl2e8tX_Piokv$P-FNrOBAB~xa7^Gf-8au9j* zU*7ZCG6EP{kBZw#=r4sJrz#JrEk%P#V6pW`4y|8VW}xzhRkW%+l^#(t305Dlp4Hi3 zH(!oR1yHv(L3E{^FSlMKi#y0I5-aB7rry-t@e`X{63v~<^5FrQetkq%Myudw^d!8M zUtsrMu~a$Lwnlxk6T1GwV1n@h_u`MNk+Me)Fa9~DNa%6VgNyGK)}>}`F&f<-b7{=R zuWo9RFCw|(*R-5<;0Kc{c;ZFR`R}8<1a{bDAvTStOBv%3rkO8=+Fso$f z-G_9=qTEZH23dhO46pLg%mqEx*{Iifx=caA6I`D;U;qhidKOVHx|L+*!Rlnn>eAL8o~Z-1-s|d_GBUmB|LQB*KSDFuUhhn{z9*UlFU*5vfjjuZ-489_Qj8_SqCTrhn6vtemLrOZp zUBWxBR%tvmvmycSQBB#VkbvFZIAEkgzjs;5dXfXJCA#6*jK4?TnY=#xa857j5Dz(7 zKExbdtH|X>rgrnim~i~~nbwUHE@y($4$`%Kxj`Z`Jho&_gV7Oov1>UkTT;(QkxSVh zmC1rO;hn?`dJKFswuC&k+@H3u@5|_l`c9IU4gLL2pcB$o(z z(e#7MKYW>WNNWFe$A!ItudKpparIle((R2OYf+#jlyFhhp8DuP)gX@(W(ri~;MOIn zo0|~G(44N={t{gYEm|=Qq*&kNTWw@*O^fUFuv|-BChmN93k;!*A}!mI?L%~InFd7i z?D?OwnBH2`qAAzm+g)T_q@_VQ{q?sD4^)8V8RJq45Qp3pSx)2@kOk|g1BZt;5IpBe zz%daARTkc>SUQ<}G=dEHh}Nn~lM_hFt6C3c-0+4sT5d8d@07KK#{ z1h%cR(ZeI3GG#7Nh7I02Z&^XEV|Uv5Lsrb0`xtxH9M%qB3F}g$-Clzt9s%6phS->p znPJacLTce7Y|2;ak72C2JG&3Qc7~TUVCNjn-_lPkkq3G_V2fHHiX#=m1juuZLbe|+ zZYR%gB6`=(T2i7tg8c~6;<&LnQ7(sXIekNdTv8GdqCAJ~TsR1cSy*&UNFj8A-zZS~ IYufqsJ*i3!z5oCK From 081513b3635e1bbec9de2424a3069898a23362ca Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 24 Jul 2023 16:53:10 +0200 Subject: [PATCH 44/92] Circuit: Fix balance violation (#78) To prevent balance violations, we have replaced the constraint "(v_old = 0 and split_flag = 0) or (root = anchor)" with the constraint "(v_old = 0 and is_native_asset = 1) or (root = anchor)". Previously, an adversary could use a zero-valued ZSA note to violate balance by setting v_old=0, v_new!=0, is_native_asset=0, split_flag=0. Limit the version of dashmap (< 5.5) because recent dashmap versions required rust version 1.64 or newer Limit the version of hashbrown (<0.13) because recent hashbrown versions required rust version 1.64 or newer --- Cargo.toml | 2 ++ src/circuit.rs | 12 ++++++------ src/circuit_description | 33 +++++++++++++++++++------------- src/circuit_proof_test_case.bin | Bin 5250 -> 5250 bytes 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3ad6adfb9..a0929100c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,8 @@ zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.4", features = ["test-dependencies"] } [target.'cfg(unix)'.dev-dependencies] +hashbrown = ">= 0.12, <0.13" +dashmap = ">= 5.4, <5.5" inferno = ">= 0.11, < 0.11.15" pprof = { version = "0.9", features = ["criterion", "flamegraph"] } # MSRV 1.56 diff --git a/src/circuit.rs b/src/circuit.rs index a8164c7bc..9d550e5d2 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -224,7 +224,7 @@ impl plonk::Circuit for Circuit { // Constrain split_flag to be boolean // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - // Constrain (v_old = 0 and split_flag = 0) or (calculated root = anchor) (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Constrain (v_old = 0 and is_native_asset = 1) or (calculated root = anchor) (https://p.z.cash/ZKS:action-merkle-path-validity?partial). // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). // Constrain is_native_asset to be boolean @@ -278,12 +278,12 @@ impl plonk::Circuit for Circuit { - magnitude * sign, ), // We already checked that - // * split_flag is boolean (just above), and - // * v_old is a 64 bit integer (in the note commitment evaluation). - // So, split_flag + v_old = 0 only when (split_flag = 0 and v_old = 0), no overflow can occur. + // * is_native_asset is boolean (just below), and + // * v_old is a 64 bit unsigned integer (in the note commitment evaluation). + // So, 1 - is_native_asset + v_old = 0 only when (is_native_asset = 1 and v_old = 0), no overflow can occur. ( - "(v_old = 0 and split_flag = 0) or (root = anchor)", - (v_old.clone() + split_flag.clone()) * (root - anchor), + "(v_old = 0 and is_native_asset = 1) or (root = anchor)", + (v_old.clone() + one.clone() - is_native_asset.clone()) * (root - anchor), ), ( "v_old = 0 or enable_spends = 1", diff --git a/src/circuit_description b/src/circuit_description index 863c4e1e2..7a9d35f07 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -261,20 +261,27 @@ PinnedVerificationKey { ), Product( Sum( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), - }, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), ), Sum( Advice { diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 5a8711554131107aeac547f3b033c40a9fc21d75..9005e06bc0beb164cc041c00bd0ac8707ebe8da9 100644 GIT binary patch literal 5250 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 I+uWQkC`hXiNdN!< literal 5250 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 IeX+H@0}cNf+yDRo From 139ecca07939f5fec2c66a4cf452d8bd6765c8d6 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 31 Aug 2023 09:23:44 +0200 Subject: [PATCH 45/92] Circuit: Add enable_zsa flag (#79) When enable_zsa flag is set to false, it is not possible to perform ZSA transactions (the circuit will fail). Fix the version of reddsa (=0.5.0) because recent versions required rust version 1.65 or newer Fix the version of tempfile (=3.5.0) because recent versions required rust version 1.63 or newer Limit the version of flate2 (<1.0.27) because recent versions raise some clippy issues --- Cargo.toml | 4 +- benches/circuit.rs | 2 +- benches/note_decryption.rs | 2 +- src/builder.rs | 4 +- src/bundle.rs | 28 +- src/circuit.rs | 70 ++++- src/circuit_description | 441 +++++++++++++++++++------------- src/circuit_proof_test_case.bin | Bin 5250 -> 5251 bytes tests/builder.rs | 4 +- tests/zsa.rs | 4 +- 10 files changed, 359 insertions(+), 200 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a0929100c..efcc06945 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,9 +35,10 @@ hex = "0.4" lazy_static = "1" memuse = { version = "0.2.1", features = ["nonempty"] } pasta_curves = "0.5" +tempfile = "= 3.5.0" # Last version required rust 1.63 proptest = { version = "1.0.0", optional = true } rand = "0.8" -reddsa = "0.5" +reddsa = "=0.5.0" # Last version required rust 1.65 nonempty = "0.7" serde = { version = "1.0", features = ["derive"] } subtle = "2.3" @@ -49,6 +50,7 @@ tracing = "0.1" # Developer tooling dependencies image = { version = ">= 0.24, < 0.24.5", optional = true } # 0.24.5 has MSRV 1.61 +flate2 = ">= 1.0, <1.0.27" # Clippy issues in last version plotters = { version = "0.3.0", optional = true } [dev-dependencies] diff --git a/benches/circuit.rs b/benches/circuit.rs index 03868a418..f26cc3507 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -28,7 +28,7 @@ fn criterion_benchmark(c: &mut Criterion) { let create_bundle = |num_recipients| { let mut builder = Builder::new( - Flags::from_parts(true, true), + Flags::from_parts(true, true, false), Anchor::from_bytes([0; 32]).unwrap(), ); for _ in 0..num_recipients { diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 6bd6fa10f..ce051cf03 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -47,7 +47,7 @@ fn bench_note_decryption(c: &mut Criterion) { let bundle = { let mut builder = Builder::new( - Flags::from_parts(true, true), + Flags::from_parts(true, true, false), Anchor::from_bytes([0; 32]).unwrap(), ); // The builder pads to two actions, and shuffles their order. Add two recipients diff --git a/src/builder.rs b/src/builder.rs index 06b8a431a..bae73569b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -947,7 +947,7 @@ pub mod testing { /// Create a bundle from the set of arbitrary bundle inputs. fn into_bundle + Copy + Into>(mut self) -> Bundle { let fvk = FullViewingKey::from(&self.sk); - let flags = Flags::from_parts(true, true); + let flags = Flags::from_parts(true, true, true); let mut builder = Builder::new(flags, self.anchor); for (note, path) in self.notes.into_iter() { @@ -1068,7 +1068,7 @@ mod tests { let recipient = fvk.address_at(0u32, Scope::External); let mut builder = Builder::new( - Flags::from_parts(true, true), + Flags::from_parts(true, true, false), EMPTY_ROOTS[MERKLE_DEPTH_ORCHARD].into(), ); diff --git a/src/bundle.rs b/src/bundle.rs index 2e5d5a034..23beb4a86 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -38,6 +38,7 @@ impl Action { cmx: *self.cmx(), enable_spend: flags.spends_enabled, enable_output: flags.outputs_enabled, + enable_zsa: flags.zsa_enabled, } } } @@ -57,18 +58,25 @@ pub struct Flags { /// guaranteed to be dummy notes. If `true`, the created notes may be either real or /// dummy notes. outputs_enabled: bool, + /// Flag denoting whether ZSA transaction is enabled. + /// + /// If `false`, all notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be notes with native asset. + zsa_enabled: bool, } const FLAG_SPENDS_ENABLED: u8 = 0b0000_0001; const FLAG_OUTPUTS_ENABLED: u8 = 0b0000_0010; -const FLAGS_EXPECTED_UNSET: u8 = !(FLAG_SPENDS_ENABLED | FLAG_OUTPUTS_ENABLED); +const FLAG_ZSA_ENABLED: u8 = 0b0000_0100; +const FLAGS_EXPECTED_UNSET: u8 = !(FLAG_SPENDS_ENABLED | FLAG_OUTPUTS_ENABLED | FLAG_ZSA_ENABLED); impl Flags { /// Construct a set of flags from its constituent parts - pub fn from_parts(spends_enabled: bool, outputs_enabled: bool) -> Self { + pub fn from_parts(spends_enabled: bool, outputs_enabled: bool, zsa_enabled: bool) -> Self { Flags { spends_enabled, outputs_enabled, + zsa_enabled, } } @@ -90,6 +98,14 @@ impl Flags { self.outputs_enabled } + /// Flag denoting whether ZSA transaction is enabled. + /// + /// If `false`, all notes within [`Action`]s in the transaction's [`Bundle`] are + /// guaranteed to be notes with native asset. + pub fn zsa_enabled(&self) -> bool { + self.zsa_enabled + } + /// Serialize flags to a byte as defined in [Zcash Protocol Spec § 7.1: Transaction /// Encoding And Consensus][txencoding]. /// @@ -102,6 +118,9 @@ impl Flags { if self.outputs_enabled { value |= FLAG_OUTPUTS_ENABLED; } + if self.zsa_enabled { + value |= FLAG_ZSA_ENABLED; + } value } @@ -116,6 +135,7 @@ impl Flags { Some(Self::from_parts( value & FLAG_SPENDS_ENABLED != 0, value & FLAG_OUTPUTS_ENABLED != 0, + value & FLAG_ZSA_ENABLED != 0, )) } else { None @@ -607,8 +627,8 @@ pub mod testing { prop_compose! { /// Create an arbitrary set of flags. - pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY) -> Flags { - Flags::from_parts(spends_enabled, outputs_enabled) + pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY, zsa_enabled in prop::bool::ANY) -> Flags { + Flags::from_parts(spends_enabled, outputs_enabled, zsa_enabled) } } diff --git a/src/circuit.rs b/src/circuit.rs index 9d550e5d2..d88bfa2a8 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -27,6 +27,7 @@ use self::{ }; use crate::{ builder::SpendInfo, + bundle::Flags, circuit::gadget::mux_chip::{MuxChip, MuxConfig}, constants::{ OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, @@ -79,6 +80,7 @@ const RK_Y: usize = 5; const CMX: usize = 6; const ENABLE_SPEND: usize = 7; const ENABLE_OUTPUT: usize = 8; +const ENABLE_ZSA: usize = 9; /// Configuration needed to use the Orchard Action circuit. #[derive(Clone, Debug)] @@ -231,6 +233,7 @@ impl plonk::Circuit for Circuit { // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset // Constraint if split_flag = 0 then psi_old = psi_nf // Constraint if split_flag = 1, then is_native_asset = 0 + // Constraint if enable_zsa = 0, then is_native_asset = 1 let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -267,6 +270,8 @@ impl plonk::Circuit for Circuit { let psi_old = meta.query_advice(advices[4], Rotation::next()); let psi_nf = meta.query_advice(advices[5], Rotation::next()); + let enable_zsa = meta.query_advice(advices[6], Rotation::next()); + Constraints::with_selector( q_orchard, [ @@ -318,11 +323,15 @@ impl plonk::Circuit for Circuit { ), ( "(split_flag = 0) => (psi_old = psi_nf)", - (one - split_flag.clone()) * (psi_old - psi_nf), + (one.clone() - split_flag.clone()) * (psi_old - psi_nf), ), ( "(split_flag = 1) => (is_native_asset = 0)", - split_flag * is_native_asset, + split_flag * is_native_asset.clone(), + ), + ( + "(enable_zsa = 0) => (is_native_asset = 1)", + (one.clone() - enable_zsa) * (one - is_native_asset), ), ], ) @@ -942,6 +951,14 @@ impl plonk::Circuit for Circuit { psi_old.copy_advice(|| "psi_old", &mut region, config.advices[4], 1)?; psi_nf.copy_advice(|| "psi_nf", &mut region, config.advices[5], 1)?; + region.assign_advice_from_instance( + || "enable zsa", + config.primary, + ENABLE_ZSA, + config.advices[6], + 1, + )?; + config.q_orchard.enable(&mut region, 0) }, )?; @@ -999,6 +1016,7 @@ pub struct Instance { pub(crate) cmx: ExtractedNoteCommitment, pub(crate) enable_spend: bool, pub(crate) enable_output: bool, + pub(crate) enable_zsa: bool, } impl Instance { @@ -1015,8 +1033,7 @@ impl Instance { nf_old: Nullifier, rk: VerificationKey, cmx: ExtractedNoteCommitment, - enable_spend: bool, - enable_output: bool, + flags: Flags, ) -> Self { Instance { anchor, @@ -1024,13 +1041,14 @@ impl Instance { nf_old, rk, cmx, - enable_spend, - enable_output, + enable_spend: flags.spends_enabled(), + enable_output: flags.outputs_enabled(), + enable_zsa: flags.zsa_enabled(), } } - fn to_halo2_instance(&self) -> [[vesta::Scalar; 9]; 1] { - let mut instance = [vesta::Scalar::zero(); 9]; + fn to_halo2_instance(&self) -> [[vesta::Scalar; 10]; 1] { + let mut instance = [vesta::Scalar::zero(); 10]; instance[ANCHOR] = self.anchor.inner(); instance[CV_NET_X] = self.cv_net.x(); @@ -1048,6 +1066,7 @@ impl Instance { instance[CMX] = self.cmx.inner(); instance[ENABLE_SPEND] = vesta::Scalar::from(u64::from(self.enable_spend)); instance[ENABLE_OUTPUT] = vesta::Scalar::from(u64::from(self.enable_output)); + instance[ENABLE_ZSA] = vesta::Scalar::from(u64::from(self.enable_zsa)); [instance] } @@ -1167,6 +1186,7 @@ mod tests { use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; use crate::builder::SpendInfo; + use crate::bundle::Flags; use crate::note::commitment::NoteCommitTrapdoor; use crate::note::{AssetBase, Nullifier}; use crate::primitives::redpallas::VerificationKey; @@ -1234,6 +1254,7 @@ mod tests { cmx, enable_spend: true, enable_output: true, + enable_zsa: false, }, ) } @@ -1314,6 +1335,7 @@ mod tests { w.write_all(&[ if instance.enable_spend { 1 } else { 0 }, if instance.enable_output { 1 } else { 0 }, + if instance.enable_zsa { 1 } else { 0 }, ])?; w.write_all(proof.as_ref())?; @@ -1344,8 +1366,15 @@ mod tests { crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); let enable_spend = read_bool(&mut r); let enable_output = read_bool(&mut r); - let instance = - Instance::from_parts(anchor, cv_net, nf_old, rk, cmx, enable_spend, enable_output); + let enable_zsa = read_bool(&mut r); + let instance = Instance::from_parts( + anchor, + cv_net, + nf_old, + rk, + cmx, + Flags::from_parts(enable_spend, enable_output, enable_zsa), + ); let mut proof_bytes = vec![]; r.read_to_end(&mut proof_bytes)?; @@ -1533,6 +1562,7 @@ mod tests { cmx, enable_spend: true, enable_output: true, + enable_zsa: true, }, ) } @@ -1573,6 +1603,7 @@ mod tests { cmx: instance.cmx, enable_spend: instance.enable_spend, enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_cv_net, false); @@ -1586,6 +1617,7 @@ mod tests { cmx: instance.cmx, enable_spend: instance.enable_spend, enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_rk, false); @@ -1627,6 +1659,7 @@ mod tests { cmx: random_note_commitment(&mut rng).into(), enable_spend: instance.enable_spend, enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_cmx_pub, false); @@ -1640,6 +1673,7 @@ mod tests { cmx: instance.cmx, enable_spend: instance.enable_spend, enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, }; check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); @@ -1672,6 +1706,22 @@ mod tests { }; check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false); } + + // If asset is not equal to the native asset, set enable_zsa = 0 + // The proof should fail + if !is_native_asset { + let instance_wrong_enable_zsa = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: false, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_enable_zsa, false); + } } } } diff --git a/src/circuit_description b/src/circuit_description index 7a9d35f07..cffc54ff8 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -1002,6 +1002,93 @@ PinnedVerificationKey { }, ), ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 16, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), Product( Product( Product( @@ -1146,7 +1233,7 @@ PinnedVerificationKey { Product( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -1155,7 +1242,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000400, ), Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -3764,7 +3851,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -3790,7 +3877,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -4008,7 +4095,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -4569,7 +4656,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -4595,7 +4682,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -4813,7 +4900,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -5312,7 +5399,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -5328,7 +5415,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -5339,14 +5426,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -5355,7 +5442,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -5647,7 +5734,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -5673,7 +5760,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -5875,7 +5962,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -5996,7 +6083,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -6148,7 +6235,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -6235,7 +6322,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -6251,7 +6338,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -6262,14 +6349,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -6278,7 +6365,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -6404,7 +6491,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -6430,7 +6517,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -6648,7 +6735,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -6785,7 +6872,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -6953,7 +7040,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -7037,7 +7124,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -7137,7 +7224,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -7149,7 +7236,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -7165,7 +7252,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -7177,7 +7264,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -7282,7 +7369,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -7294,7 +7381,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -7313,7 +7400,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 21, + query_index: 22, column_index: 1, rotation: Rotation( -1, @@ -7330,7 +7417,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -7342,7 +7429,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 17, + query_index: 18, column_index: 9, rotation: Rotation( -1, @@ -7362,7 +7449,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 21, + query_index: 22, column_index: 1, rotation: Rotation( -1, @@ -7557,7 +7644,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -7757,7 +7844,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -7867,7 +7954,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -7878,7 +7965,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -7977,7 +8064,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -8003,7 +8090,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -8118,7 +8205,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -8153,7 +8240,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -8287,7 +8374,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -8322,7 +8409,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -10684,7 +10771,7 @@ PinnedVerificationKey { }, Sum( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -10790,7 +10877,7 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -10799,7 +10886,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -10816,7 +10903,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -10825,7 +10912,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -10921,7 +11008,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -11341,7 +11428,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -11709,7 +11796,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -12054,7 +12141,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -12399,7 +12486,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -12939,7 +13026,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -12949,7 +13036,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -12960,7 +13047,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -13095,7 +13182,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -13105,7 +13192,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -13116,7 +13203,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -13251,7 +13338,7 @@ PinnedVerificationKey { Sum( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -13261,7 +13348,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -13272,7 +13359,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -13359,7 +13446,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 20, + query_index: 21, column_index: 6, rotation: Rotation( -1, @@ -13375,7 +13462,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -13475,7 +13562,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -13566,7 +13653,7 @@ PinnedVerificationKey { }, Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -15156,14 +15243,14 @@ PinnedVerificationKey { Product( Sum( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -15183,14 +15270,14 @@ PinnedVerificationKey { Sum( Product( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, ), }, Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -15209,7 +15296,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -15250,7 +15337,7 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000002, ), Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -15767,7 +15854,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -15886,7 +15973,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -15898,7 +15985,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -16012,7 +16099,7 @@ PinnedVerificationKey { Sum( Sum( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -16130,7 +16217,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -16139,7 +16226,7 @@ PinnedVerificationKey { Negated( Sum( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -16147,7 +16234,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -17543,7 +17630,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -17673,7 +17760,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -17779,7 +17866,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -17989,7 +18076,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -18001,7 +18088,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -18131,7 +18218,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -18142,7 +18229,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -18498,7 +18585,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -18509,7 +18596,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -18860,7 +18947,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -18871,7 +18958,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -19204,7 +19291,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -19233,7 +19320,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -19699,7 +19786,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -19829,7 +19916,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -19928,7 +20015,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -20033,7 +20120,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -20138,14 +20225,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -20280,7 +20367,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -20438,7 +20525,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -20553,7 +20640,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -20674,14 +20761,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -20963,7 +21050,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -21121,7 +21208,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -21236,7 +21323,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -21357,14 +21444,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -21500,7 +21587,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -21511,7 +21598,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -21669,7 +21756,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -21784,14 +21871,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -21905,7 +21992,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -22026,14 +22113,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -22304,7 +22391,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -22589,7 +22676,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -22832,7 +22919,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -22953,7 +23040,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -23195,7 +23282,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -23207,7 +23294,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -23353,7 +23440,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -23364,7 +23451,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -23768,7 +23855,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -23779,7 +23866,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -24178,7 +24265,7 @@ PinnedVerificationKey { }, Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -24189,7 +24276,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -24570,7 +24657,7 @@ PinnedVerificationKey { ), Sum( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -24599,7 +24686,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -25129,7 +25216,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -25275,7 +25362,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -25390,7 +25477,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -25511,7 +25598,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -25632,14 +25719,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -25774,7 +25861,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -25932,7 +26019,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -26047,7 +26134,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -26168,14 +26255,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -26409,7 +26496,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -26519,7 +26606,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -26586,7 +26673,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -26659,14 +26746,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -26754,7 +26841,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -26765,7 +26852,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -26875,7 +26962,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -26942,14 +27029,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -27015,7 +27102,7 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -27088,14 +27175,14 @@ PinnedVerificationKey { ), Product( Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -27270,7 +27357,7 @@ PinnedVerificationKey { ), Scaled( Advice { - query_index: 22, + query_index: 16, column_index: 6, rotation: Rotation( 1, @@ -27459,7 +27546,7 @@ PinnedVerificationKey { ), Negated( Advice { - query_index: 19, + query_index: 20, column_index: 8, rotation: Rotation( 1, @@ -27606,7 +27693,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -27679,7 +27766,7 @@ PinnedVerificationKey { ), }, Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -27942,6 +28029,15 @@ PinnedVerificationKey { 1, ), ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), ( Column { index: 9, @@ -27996,15 +28092,6 @@ PinnedVerificationKey { -1, ), ), - ( - Column { - index: 6, - column_type: Advice, - }, - Rotation( - 1, - ), - ), ( Column { index: 7, @@ -28402,7 +28489,7 @@ PinnedVerificationKey { Negated( Scaled( Advice { - query_index: 16, + query_index: 17, column_index: 9, rotation: Rotation( 1, @@ -28762,7 +28849,7 @@ PinnedVerificationKey { ), ), Advice { - query_index: 18, + query_index: 19, column_index: 7, rotation: Rotation( 1, @@ -29006,14 +29093,14 @@ PinnedVerificationKey { ], permutation: VerifyingKey { commitments: [ - (0x3b61bede3f87e9208caf3626fbe7a645e1b9f9b241a96160c68b708196e86cbb, 0x0932e9c67d6bb593c9b3d6bd9697efe79bb2f81bee35abeaa8a2a0a828d8fcc6), + (0x26d7150d98acf5efa7739440641d97629e2d6553547920432e43d747b998d49e, 0x3223285fb44e1736e7216cd51276087bce39f7e5c0fdb1ef49ab4c6de26b256d), (0x07800024b352149368405f222a8dfbf373bd4603df89929a5d00f7ac9ffac504, 0x250be8a84de9a8ded91e85860f1b1751f6bd2c0aba96329ee2d6f0e377f4679f), (0x3384b0dbfa6553ad5adf0b218df2cbe6243c33102a97774b4e023ec1dc2d83e9, 0x2873fe49458cd70b9d72419e0d6a6ceadb8070f4b62a0bb47c58a89269e0b583), (0x38def0fd8f233ef8651a28ffb7ae6f1e4eaeb0acec19453a3e5a0d70b2058782, 0x0512c67736284a225f0b6617cabd76ac2e4a6805940af4480798ca884e02d277), (0x26b6d69fd8c13013c6ab5fb74bd3fbe85d01b0abb57e149ff53e77a535c6bf40, 0x05ae4f52e4ab72ff3cf2b64df6d371fda270f4f78ed0bccce8e3138d4e30e4a0), (0x3f1b6f3ea5a2b24646dbe1c6f7c7dbf797fe6602a344bed59668ba5413519631, 0x0401a6f6ed893aa112f234127f8c30ee6e09b45f75993351aea9974389b261d6), (0x2f34843015cfc9c9ff59c7ecab3cbb6aea69dcf6f5af79e166f25d90f70353d5, 0x2bcfde5880412d171705b41124b404a323697c4d1008b2e8b2bf9966e5809d3d), - (0x1241f0e0058575ff769809aa569ab0ff12d5b2d7d840eae76912c16433be00ff, 0x33339365e1edbdb387b0a0b7dc5a9212c0313bb0a131c9302bc57db36174f3b0), + (0x082e9af26adc31f97c38ce587ffde9af5d8238d16ad61a236bbd3c805515f144, 0x051d36eb85b6402dfb2a55ae1507b358319d016483d7ecf6be49793bbb64e79e), (0x240a361e73afa04a2e5cc578680e54bf28e3375dbb35a8918c3cdbc91f1bc25b, 0x161c53e65c1b6500b576d8fa982e2565dbe35954840b0bab8a3d912158b9dbe7), (0x32f883bbd63b0700f0150ea8d71f6f5d7cdcc4463289983d71e9bc104d4a5c28, 0x33aeb42bec794138b8db28696bd7cef4946a8a89edcbf3f8289655ff9f9129ee), (0x03f33d3064517ab1a8e538444013bd0d6b011f9923f8cb964763a88d6d7409e0, 0x16f534b6d12d9e011b951e374982f048f0bed808099fd3ed97cd827360f6fb65), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 9005e06bc0beb164cc041c00bd0ac8707ebe8da9..83ca7c0535ed0da94d2aca22e3f9553b7fad9eed 100644 GIT binary patch literal 5251 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 J7OYxF0|4IM93B7w literal 5250 zcmV-|6n*O$b%uAr8c1>lt|YxRlS%)5inZ>xx&|y34|KR0(y}7Xq`pT9lNC7?GDP7s z+^*;IT!_k_)U!zZsRdo76lbsRA~k~!qsWFg8PUqbz?e% z`}K;frG46z7Qk{r4+V!4Vc2zVj?4Gl3pTC~oO|9st&1c{JXrQ=EwEPC8P z%jf>txRKAlb)TqtwmJ{K4Z_y}?C5tjLb{;MgxXy^dlh=lyeP`cPsmgGSnae(VB4QO)T`V zunAM0n4M>?x7xSpIyTql!VSxp0FfMw+n+(|r}0J_uEoI2mQSS)09G^h^jC@;x2 zlBCnq(MUnXv?xK-kLYBn%$0qsN7xhp9rDGE_w@hLWIM{dRk0|&iebihon1+XM@T5J z%hQqr$u7r4xmA+HB2i}8v~9R@_R%$$mz4(D$vVb9AjJPRUW^Kdr7=LTYb^)Ac97+K`0vi%{%jGOP59sjKM+DS|&+8Xl2^%XBg@Xi{s@k*`Y6%`48>wFhCsP$Dpw z6C(=@jBRd|>fCi0mizdj6~qNyNs`6>Jujc&Whu|UF=mh;tdhJO`E zJ&M7y%1Kgt7b+`3#X=|1}lga2RHsuK{!3*cr+B?lACg|wNL#{_<5r*Sq@ zgn8;KL%-NsHdDN)3tP(fiF}I2qC_mF!9_;OH2vlT$a`0QcfY4N-(A13VjGSa(%2s_gq%A$CzZ z123v+tU+a^F9b&^1`<|{92=No9CzNKp3&8r;FN(nR#U`mF;oO+DGI){oaZ=5Bzd-% zyGj&LX#ob4%WuxC@?zddG6s{t7}H876xn(XVLY+W+tT+gkOIG*tJ9bs20I3m9iX#> zJUdNq|8FpXq}4Hc!d^h!-5dS`C2oQ)X-ds+zEV*>7=VDdH5P7V?d=g*;^G4l+!L*) zr8psb0S`#uH#HrLHO6`Wy2(-AMrz%y64OHhvB5-@j@#4oY}r3*r-n{GGM9zQ+kWwk zJ-tVLLh-#%235@YBsRac-Dt!ddmMK}FWfG{7Jf8;tUV^XeI6D|O*UaIJnT~vP73Vo zbq0y{J>FsL%&b`x)0jz%!*&!REsnJG{5`IAd-BY>q8(F9JGuJmiomYZgJ;{ws^TyN z2&$n>C8c_eS~J<}D48KcH8pEmJb>(l)SW3LYu7wwjxqZsCP#AHPovu(EkIPN z07oHo1@t6Op7ro8=s=0$xO?_?2x94*N)C{VDsv&hw5+geV15SdcNVmC>C)fqCO>og zWhi-H=)`0B16@a;lHXvn_` zZ6DAJusP?<>(>|)WPoJ()!h2)Ec-vlIbKNmsOfKLzdH);24 zP$tmaX4ADGp^UH8JL(}M)U;Vb2wl7826>9H#5+F}L|pMM71T`aw(MNlGzo})!7i60 z*$J@yp$(C<0$vTaLOi(N2o327rT`=tGz9`rIRl$?ME|K&zXWQ@WD}lV>e=4%{&isO z@y~W1G1t=+ag5mi3gE5T{PwM-i?Wj*)3ehom_Yi}^T7-2D=&a_B+dLVD-*>bQ}D@u{QbU-tvL>SR`y#6x)Q+INhsc%DHS)xc=26QE16MG)= z5AM}liHl9EA@7kZF85nVEJUPiHnuowF9&PwAxOUk=4E&ON9(-O3mat%L=mVB}{B_v+Dd(7=ABSY&#Ravs& z0bZ%2GuAt5ljEEuPoKJ_ZnfnrU02m+3nj~`$E+k*7PlJeZ$iQ#R1Y-WP1%uGw>%a< zyj_@eMebv+0+Aq{Bw62PzLU~w231;9IvTflm$Tp}YKDE;fQunqjiC+8DvRze*cEi3 z!Xa{^|KRG%XLt2daj?Mx0Y-SV7&gU(0%67%*F{m8Ii^($!4Ch}_Pcy(;xdc&f6MaB zY#L9CFAWM2%qVN+j||cUB1>C=A&&m`E)Qpf;w2H1VvsX4ibnF7k0=O4b zsP^b=MF2gSf2_^O79N7pdHWniq!Ji~ujUXX8J`0|;s=2wHXiYVCy(4+kwVwd+;^ct zXL`Fhl9eRsB;aDUC>FmLgb~p^tV2N)Tu&OWwWh>hL$|DftGoJ^T>!W&%83+-Ej5gc^Sw&T;3mP8alk~Q|xEfU6#fU~`May`&brCrd@ z7`Cg&g~7oB}d6IJ2$O{vyKUg;@$tMUS!@5nmS8E zS1-UOdm_YbV4A0rD6N+{|KL8X_}+KMERk0o~N7f5?W5Uu!w(lE?fcLprR*{BJeXJE6~ z8_HKUW|#a~J$Vxjp_{#SZm^Aw8oZ*e7>FbD(QtBGLKZL6Z~^>R3UZQRV?8`oz3`&x=GsK7(1Fv32rB&*fqhU?EGN;@Ui-b4Apuy*q|m1?FOY zANhD~6)p4x_|E`%#_>DPIQM94(oR8W_s05K|EyRaE)Btp+(%zK&&chl(9<(6ur}xt zK5|`V04exHWXGQ~03T^v$3`6#$AL4v=! zM@#$N5%4%RzrNA<#k(5#A>!N!bSNdRQ^ecec=ICTQ=YP-=2I5P#Wi0K-ZI(u9P)t7 z$vTk}g1u83M?i)R9FVO*KdpXd!Oa0G=h2)A3j+>8P&lI^iZ0Tb-hVmERZdJM_|le7 zgQXyFblLrOFndO{O58l=P?fHU|BQp9qWMZotAaW&ij>fiSbEVB4Fx>Qcd%Ljm6{!# z@Ti&In2~yox7?<2Z7Oe))Cy354=uO9PfB#lyB(6{?QK42Gndr*&tDSAWzt0- z7V5EQfbeu~6tLPR0ubLJKBv$x)W$(`W3Zrt32p>x4I2q5pP&Fmr>q$t3UmW>)>o~_ ztYK@lB9bY$iV6p0K25G95GZl;Sa&?ci;}6PcX1#C70|qARJBIn5~C{Z59A^>eP1X&rU?KjE{t0xD2Kszo;xX7YWr~;L*rl5+w zfxRhM5RnjBZz9J~IF!RxYy8rJDF$(mfxYA7X9@(AhJNt^CjoYg!IwjFh(bvG^{=dc zNwxrmr!_P1{4Yj8X;aa)09t~Ecm8SKE(mxUH`p`0=@BUe!tTbz|cqz|Ze z(MK4*`I@>lO*fBwn67VL)g%~K16wd3mx_9$xIjJDi{V80&!gTUSGhyGFzSL6om`Yl z0|p1xFO+|opS!B&eF{Ojl%p005U+LZxq1 zg_(?FF#nsDYdlI5a^WWXdIG}2C=6X=6h%G6)0C;1eBgl+xZL~ucU&-!c?~3AZzW&D zXDPM{05}1Rqov_HJp4|J6JRV7)i?S$!sG;6c#Dw zaMe`=Smv}W*H@F7s?7p7;9Y#a={r`fldj{z0Jw)ZZz~d+NAgRXI+!br!>jwK576)0 z`@}84*ErfwD3-(v6gMQoMqL01^0-DToAQH$jh0+lWQscmaN>s~A%|KqkaJr~-MYY* z!-&LNwIP|DGj>Udy`Jet=HBlbSuXL^K80|{oo#y08x*34#@U>@wXs~d8KHwJS z8tm$<@MN!2S&#K{e!uDdj_>~7z=2DbVA0E{f9=bu8D%k68k4saeiAm<=jqz}Nfz zq`o#;E*l|4qN6`vk)c7u3rM(1^aLRp7{uqasWHlATh=SDln~bTtmI+hyi!a1a~SK( z(*K2?sFY$05kS|}VIPx!rB$iGdPSyi%mo$`oE`6lEeL@N1s8DOw0EaUHBgcqcFS%shst|T0vEMWCLpYflMVa(#_jSHILZO@pfji=^ZlYjF+^M z)VIU2%hKfZ*TxB7Gbxk3jx%!HHWx1cclAW?p#0*popH5a1FHhkwZC~ZWOZPcIeReg z!Nvn&hpUU{(&jy;=ejwy#QMsW?0htpr2FseYxaZXj1D^^=tf+~AWk~dt z({@lsY-&a(7H6*1h_pIR#Orkv^TJt~vmf^t-ki(!dju{avi_Q4(VI~n^n5Fu_y`xt zuV=*@w1>OLAxRDULV4Peiv{nOyhZ~4zl7thoBL${smQ8OyiQ6W-EX)Y?LCo{EiSnn zxdw|8F9~;aG6tK55+rjAF5~s2|aqomAcl*NKf9h6#eu>H&3V&pCWQ`pAkxpKi{>q>XZ@HARd*wMy$$DOE(dnmWfwY0U@RD;cCw&snIp#nnu|q0g4`jY2%TYUtmtx=N6@d1;M`X87Z)Fu{?09PN%?I7^zDnYf$;_XO I+uWQkC`hXiNdN!< diff --git a/tests/builder.rs b/tests/builder.rs index 506ef1154..5d69209ab 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -62,7 +62,7 @@ fn bundle_chain() { // Use the empty tree. let anchor = MerkleHashOrchard::empty_root(32.into()).into(); - let mut builder = Builder::new(Flags::from_parts(false, true), anchor); + let mut builder = Builder::new(Flags::from_parts(false, true, false), anchor); assert_eq!( builder.add_recipient( None, @@ -96,7 +96,7 @@ fn bundle_chain() { let (merkle_path, anchor) = build_merkle_path(¬e); - let mut builder = Builder::new(Flags::from_parts(true, true), anchor); + let mut builder = Builder::new(Flags::from_parts(true, true, false), anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!( builder.add_recipient( diff --git a/tests/zsa.rs b/tests/zsa.rs index 649d5e8cf..584b25b5b 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -189,7 +189,7 @@ fn create_native_note(keys: &Keychain) -> Note { // Use the empty tree. let anchor = MerkleHashOrchard::empty_root(32.into()).into(); - let mut builder = Builder::new(Flags::from_parts(false, true), anchor); + let mut builder = Builder::new(Flags::from_parts(false, true, false), anchor); assert_eq!( builder.add_recipient( None, @@ -244,7 +244,7 @@ fn build_and_verify_bundle( ) -> Result<(), String> { let rng = OsRng; let shielded_bundle: Bundle<_, i64> = { - let mut builder = Builder::new(Flags::from_parts(true, true), anchor); + let mut builder = Builder::new(Flags::from_parts(true, true, true), anchor); spends .iter() From 7937e5b25184652c8c56c5ee8fd7ec4deb0ab579 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 4 Oct 2023 15:23:57 +0300 Subject: [PATCH 46/92] Enhance and cleanup ivk-to-bytes-visibility-downgrade branch (#81) Added burn validation, fixes and minor additions. Bumped Rust version to 1.65 --------- Co-authored-by: alexeykoren <> Co-authored-by: Dmitry Demin Co-authored-by: Paul <3682187+PaulLaux@users.noreply.github.com> --- .circleci/config.yml | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/ci.yml | 10 +- .github/workflows/lints-stable.yml | 6 +- Cargo.toml | 28 +++--- README.md | 2 +- rust-toolchain.toml | 2 +- src/builder.rs | 8 +- src/bundle.rs | 1 + src/bundle/burn_validation.rs | 146 +++++++++++++++++++++++++++++ src/bundle/commitments.rs | 32 +++---- src/circuit.rs | 6 +- src/issuance.rs | 35 +++++-- src/primitives/redpallas.rs | 2 +- src/supply_info.rs | 4 +- tests/zsa.rs | 8 +- 16 files changed, 227 insertions(+), 67 deletions(-) create mode 100644 src/bundle/burn_validation.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index 9dead1280..d95cffad9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ jobs: # Specify the execution environment. You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub. # See: https://circleci.com/docs/2.0/configuration-reference/#docker-machine-macos-windows-executor docker: - - image: cimg/rust:1.61.0 + - image: cimg/rust:1.65.0 # Add steps to the job # See: https://circleci.com/docs/2.0/configuration-reference/#steps steps: diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index ba1ceea59..353f23ae4 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 override: true - name: Run benchmark run: cargo bench -- --output-format bencher | tee output.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac8a974df..be39382b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 override: true - name: Run tests uses: actions-rs/cargo@v1 @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 override: true # Build benchmarks to prevent bitrot - name: Build benchmarks @@ -62,7 +62,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 override: true - name: Setup mdBook uses: peaceiris/actions-mdbook@v1 @@ -106,7 +106,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 override: true - name: cargo fetch uses: actions-rs/cargo@v1 @@ -129,7 +129,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 override: true - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 diff --git a/.github/workflows/lints-stable.yml b/.github/workflows/lints-stable.yml index a000ab449..36ae77e06 100644 --- a/.github/workflows/lints-stable.yml +++ b/.github/workflows/lints-stable.yml @@ -5,19 +5,19 @@ on: pull_request jobs: clippy: - name: Clippy (1.61.0) + name: Clippy (1.65.0) timeout-minutes: 30 runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.61.0 + toolchain: 1.65.0 components: clippy override: true - name: Run Clippy uses: actions-rs/clippy-check@v1 with: - name: Clippy (1.61.0) + name: Clippy (1.65.0) token: ${{ secrets.GITHUB_TOKEN }} args: --all-features --all-targets -- -D warnings diff --git a/Cargo.toml b/Cargo.toml index efcc06945..1ed0fb0f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "Kris Nuttycombe ", ] edition = "2021" -rust-version = "1.61.0" +rust-version = "1.65" description = "The Orchard shielded transaction protocol" license-file = "LICENSE-BOSL" repository = "https://github.com/zcash/orchard" @@ -25,7 +25,7 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] [dependencies] aes = "0.8" bitvec = "1" -blake2b_simd = "1" +blake2b_simd = "=1.0.1" # Last version required rust 1.66 ff = "0.13" fpe = "0.6" group = { version = "0.13", features = ["wnaf-memuse"] } @@ -35,39 +35,35 @@ hex = "0.4" lazy_static = "1" memuse = { version = "0.2.1", features = ["nonempty"] } pasta_curves = "0.5" -tempfile = "= 3.5.0" # Last version required rust 1.63 proptest = { version = "1.0.0", optional = true } rand = "0.8" -reddsa = "=0.5.0" # Last version required rust 1.65 +reddsa = "0.5" nonempty = "0.7" serde = { version = "1.0", features = ["derive"] } subtle = "2.3" zcash_note_encryption = "0.4" -incrementalmerkletree = "0.4" +incrementalmerkletree = "0.5" # Logging tracing = "0.1" # Developer tooling dependencies -image = { version = ">= 0.24, < 0.24.5", optional = true } # 0.24.5 has MSRV 1.61 -flate2 = ">= 1.0, <1.0.27" # Clippy issues in last version +image = { version = "0.24", optional = true } plotters = { version = "0.3.0", optional = true } [dev-dependencies] -bridgetree = "0.3" -half = ">= 1.8, < 2.3" -criterion = "0.3" +bridgetree = "0.4" +criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] } -incrementalmerkletree = { version = "0.4", features = ["test-dependencies"] } +incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } [target.'cfg(unix)'.dev-dependencies] -hashbrown = ">= 0.12, <0.13" -dashmap = ">= 5.4, <5.5" -inferno = ">= 0.11, < 0.11.15" -pprof = { version = "0.9", features = ["criterion", "flamegraph"] } # MSRV 1.56 +inferno = "0.11" +clap = "=4.2.0" # Used by inferno. Last version required rust 1.70 +pprof = { version = "0.11", features = ["criterion", "flamegraph"] } [lib] bench = false @@ -97,4 +93,4 @@ debug = true debug = true [patch.crates-io] -zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/librustzcash.git", tag = "orchard_zsa_0.5.0_compatible" } +zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/librustzcash.git", branch = "zsa1-zebra" } diff --git a/README.md b/README.md index f761aa914..95c3782e6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # orchard [![Crates.io](https://img.shields.io/crates/v/orchard.svg)](https://crates.io/crates/orchard) [![CI checks](https://github.com/QED-it/orchard/actions/workflows/ci.yml/badge.svg?branch=zsa1)](https://github.com/QED-it/orchard/actions/workflows/ci.yml) # -Requires Rust 1.61+. +Requires Rust 1.65+. ## Documentation diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b54a9f45d..5ecda6e49 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.61.0" +channel = "1.65.0" components = [ "clippy", "rustfmt" ] diff --git a/src/builder.rs b/src/builder.rs index bae73569b..fe3857904 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -464,9 +464,11 @@ impl Builder { .max() .cloned() .unwrap(); - (num_actions < MIN_ACTIONS) - .then(|| MIN_ACTIONS - num_actions) - .unwrap_or(0) + if num_actions < MIN_ACTIONS { + MIN_ACTIONS - num_actions + } else { + 0 + } } /// Builds a bundle containing the given spent notes and recipients. diff --git a/src/bundle.rs b/src/bundle.rs index 23beb4a86..a8e429a7c 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -1,6 +1,7 @@ //! Structs related to bundles of Orchard actions. mod batch; +pub mod burn_validation; pub mod commitments; pub use batch::BatchValidator; diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs new file mode 100644 index 000000000..c0cfb84f1 --- /dev/null +++ b/src/bundle/burn_validation.rs @@ -0,0 +1,146 @@ +//! Validating burn operations on asset bundles. +//! +//! The module provides a function `validate_bundle_burn` that can be used to validate the burn values for the bundle. +//! +use std::fmt; + +use crate::note::AssetBase; + +/// Possible errors that can occur during bundle burn validation. +#[derive(Debug)] +#[cfg_attr(test, derive(PartialEq, Eq))] +pub enum BurnError { + /// Encountered a duplicate asset to burn. + DuplicateAsset, + /// Cannot burn a native asset. + NativeAsset, + /// Cannot burn an asset with a non-positive value. + NonPositiveAmount, +} + +/// Validates burn for a bundle by ensuring each asset is unique, non-native, and has a positive value. +/// +/// Each burn element is represented as a tuple of `AssetBase` and `i64` (value for the burn). +/// +/// # Arguments +/// +/// * `burn` - A vector of assets, where each asset is represented as a tuple of `AssetBase` and `i64` (value the burn). +/// +/// # Errors +/// +/// Returns a `BurnError` if: +/// * Any asset in the `burn` vector is not unique (`BurnError::DuplicateAsset`). +/// * Any asset in the `burn` vector is native (`BurnError::NativeAsset`). +/// * Any asset in the `burn` vector has a non-positive value (`BurnError::NonPositiveAmount`). +pub fn validate_bundle_burn(bundle_burn: &Vec<(AssetBase, i64)>) -> Result<(), BurnError> { + let mut asset_set = std::collections::HashSet::<&AssetBase>::new(); + + for (asset, value) in bundle_burn { + if !asset_set.insert(asset) { + return Err(BurnError::DuplicateAsset); + } + if asset.is_native().into() { + return Err(BurnError::NativeAsset); + } + if *value <= 0 { + return Err(BurnError::NonPositiveAmount); + } + } + + Ok(()) +} + +impl fmt::Display for BurnError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + BurnError::DuplicateAsset => write!(f, "Encountered a duplicate asset to burn."), + BurnError::NativeAsset => write!(f, "Cannot burn a native asset."), + BurnError::NonPositiveAmount => { + write!(f, "Cannot burn an asset with a non-positive value.") + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Creates an item of bundle burn list for a given asset description and value. + /// + /// This function is deterministic and guarantees that each call with the same parameters + /// will return the same result. It achieves determinism by using a static `IssuanceKey`. + /// + /// # Arguments + /// + /// * `asset_desc` - The asset description string. + /// * `value` - The value for the burn. + /// + /// # Returns + /// + /// A tuple `(AssetBase, Amount)` representing the burn list item. + /// + pub fn get_burn_tuple(asset_desc: &str, value: i64) -> (AssetBase, i64) { + use crate::keys::{IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey}; + + let sk_iss = IssuanceKey::from_bytes([0u8; 32]).unwrap(); + let isk: IssuanceAuthorizingKey = (&sk_iss).into(); + + ( + AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc), + value, + ) + } + + #[test] + fn validate_bundle_burn_success() { + let bundle_burn = vec![ + get_burn_tuple("Asset 1", 10), + get_burn_tuple("Asset 2", 20), + get_burn_tuple("Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert!(result.is_ok()); + } + + #[test] + fn validate_bundle_burn_duplicate_asset() { + let bundle_burn = vec![ + get_burn_tuple("Asset 1", 10), + get_burn_tuple("Asset 1", 20), + get_burn_tuple("Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert_eq!(result, Err(BurnError::DuplicateAsset)); + } + + #[test] + fn validate_bundle_burn_native_asset() { + let bundle_burn = vec![ + get_burn_tuple("Asset 1", 10), + (AssetBase::native(), 20), + get_burn_tuple("Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert_eq!(result, Err(BurnError::NativeAsset)); + } + + #[test] + fn validate_bundle_burn_zero_value() { + let bundle_burn = vec![ + get_burn_tuple("Asset 1", 10), + get_burn_tuple("Asset 2", 0), + get_burn_tuple("Asset 3", 10), + ]; + + let result = validate_bundle_burn(&bundle_burn); + + assert_eq!(result, Err(BurnError::NonPositiveAmount)); + } +} diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 97cc8ab09..f67b6b75a 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -96,6 +96,22 @@ pub fn hash_bundle_auth_empty() -> Blake2bHash { hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION).finalize() } +/// Construct the commitment for an absent issue bundle as defined in +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] +/// +/// [zip227]: https://qed-it.github.io/zips/zip-0227 +pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { + hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() +} + +/// Construct the commitment for an absent issue bundle as defined in +/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] +/// +/// [zip227]: https://qed-it.github.io/zips/zip-0227 +pub fn hash_issue_bundle_txid_empty() -> Blake2bHash { + hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() +} + /// Construct the commitment for the issue bundle pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) -> Blake2bHash { let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION); @@ -119,14 +135,6 @@ pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) h.finalize() } -/// Construct the commitment for the absent issue bundle as defined in -/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] -/// -/// [zip227]: https://qed-it.github.io/zips/zip-0227 -pub fn hash_issue_bundle_txid_empty() -> Blake2bHash { - hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() -} - /// Construct the commitment to the authorizing data of an /// authorized issue bundle pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake2bHash { @@ -134,11 +142,3 @@ pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake h.update(&<[u8; 64]>::from(bundle.authorization().signature())); h.finalize() } - -/// Construct the commitment for an absent issue bundle as defined in -/// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] -/// -/// [zip227]: https://qed-it.github.io/zips/zip-0227 -pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { - hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION).finalize() -} diff --git a/src/circuit.rs b/src/circuit.rs index d88bfa2a8..0bf473ac7 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1333,9 +1333,9 @@ mod tests { w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; w.write_all(&instance.cmx.to_bytes())?; w.write_all(&[ - if instance.enable_spend { 1 } else { 0 }, - if instance.enable_output { 1 } else { 0 }, - if instance.enable_zsa { 1 } else { 0 }, + u8::from(instance.enable_spend), + u8::from(instance.enable_output), + u8::from(instance.enable_zsa), ])?; w.write_all(proof.as_ref())?; diff --git a/src/issuance.rs b/src/issuance.rs index c2fc7ca28..29a95fda3 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -143,7 +143,7 @@ impl IssueAction { // All assets should be derived correctly note.asset() .eq(&issue_asset) - .then(|| ()) + .then_some(()) .ok_or(IssueBundleIkMismatchAssetBase)?; // The total amount should not overflow @@ -157,8 +157,13 @@ impl IssueAction { } /// Serialize `finalize` flag to a byte + #[allow(clippy::bool_to_int_with_if)] pub fn flags(&self) -> u8 { - self.finalize.then(|| 0b0000_0001).unwrap_or(0b0000_0000) + if self.finalize { + 0b0000_0001 + } else { + 0b0000_0000 + } } } @@ -1395,14 +1400,27 @@ mod tests { #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized}; - use crate::keys::testing::{arb_issuance_authorizing_key, arb_issuance_validating_key}; + use crate::keys::testing::arb_issuance_validating_key; use crate::note::asset_base::testing::zsa_asset_id; use crate::note::testing::arb_zsa_note; + use crate::primitives::redpallas::Signature; use nonempty::NonEmpty; use proptest::collection::vec; use proptest::prelude::*; use proptest::prop_compose; - use rand::{rngs::StdRng, SeedableRng}; + use reddsa::orchard::SpendAuth; + + prop_compose! { + /// Generate a uniformly distributed signature + pub(crate) fn arb_signature()( + half_bytes in prop::array::uniform32(prop::num::u8::ANY) + ) -> Signature { + // prop::array can only generate 32 elements max, so we duplicate it + let sig_bytes: [u8; 64] = [half_bytes, half_bytes].concat().try_into().unwrap(); + let sig: Signature = Signature::from(sig_bytes); + sig + } + } prop_compose! { /// Generate an issue action @@ -1462,17 +1480,14 @@ pub mod testing { ( actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), ik in arb_issuance_validating_key(), - isk in arb_issuance_authorizing_key(), - rng_seed in prop::array::uniform32(prop::num::u8::ANY), - fake_sighash in prop::array::uniform32(prop::num::u8::ANY) + fake_sig in arb_signature(), ) -> IssueBundle { - let rng = StdRng::from_seed(rng_seed); let actions = NonEmpty::from_vec(actions).unwrap(); IssueBundle { ik, actions, - authorization: Prepared { sighash: fake_sighash }, - }.sign(rng, &isk).unwrap() + authorization: Signed { signature: fake_sig }, + } } } } diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index a414bf285..7690312a9 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -101,7 +101,7 @@ impl Eq for VerificationKey {} impl PartialOrd for VerificationKey { fn partial_cmp(&self, other: &Self) -> Option { - <[u8; 32]>::from(self).partial_cmp(&<[u8; 32]>::from(other)) + Some(self.cmp(other)) } } diff --git a/src/supply_info.rs b/src/supply_info.rs index 79e6b7d70..1c2f346b1 100644 --- a/src/supply_info.rs +++ b/src/supply_info.rs @@ -6,7 +6,7 @@ use crate::{issuance::Error, note::AssetBase, value::ValueSum}; /// Represents the amount of an asset and its finalization status. #[derive(Debug, Clone, Copy)] -#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(test, derive(PartialEq, Eq))] pub struct AssetSupply { /// The amount of the asset. pub amount: ValueSum, @@ -64,7 +64,7 @@ impl SupplyInfo { finalization_set.extend( self.assets .iter() - .filter_map(|(asset, supply)| supply.is_finalized.then(|| asset)), + .filter_map(|(asset, supply)| supply.is_finalized.then_some(asset)), ); } } diff --git a/tests/zsa.rs b/tests/zsa.rs index 584b25b5b..d3dd1b922 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -77,12 +77,12 @@ fn prepare_keys() -> Keychain { fn sign_issue_bundle( unauthorized: IssueBundle, - mut rng: OsRng, + rng: OsRng, isk: &IssuanceAuthorizingKey, ) -> IssueBundle { let sighash = unauthorized.commitment().into(); let proven = unauthorized.prepare(sighash); - proven.sign(&mut rng, isk).unwrap() + proven.sign(rng, isk).unwrap() } fn build_and_sign_bundle( @@ -95,7 +95,7 @@ fn build_and_sign_bundle( let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(pk, &mut rng).unwrap(); proven - .apply_signatures(&mut rng, sighash, &[SpendAuthorizingKey::from(sk)]) + .apply_signatures(rng, sighash, &[SpendAuthorizingKey::from(sk)]) .unwrap() } @@ -203,7 +203,7 @@ fn create_native_note(keys: &Keychain) -> Note { let unauthorized = builder.build(&mut rng).unwrap(); let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(keys.pk(), &mut rng).unwrap(); - proven.apply_signatures(&mut rng, sighash, &[]).unwrap() + proven.apply_signatures(rng, sighash, &[]).unwrap() }; let ivk = keys.fvk().to_ivk(Scope::External); let (native_note, _, _) = shielding_bundle From 8b0560d64568c5abff876c01c85150ac21f4e8de Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 16 Oct 2023 11:54:09 +0200 Subject: [PATCH 47/92] Circuit: optimized short range check on 4 and 5 bits (#86) Short range checks on 4 and 5 bits are now performed with only one lookup (instead of 2). With this optimization, we could come back to k=11 in the circuit. --- src/circuit.rs | 13 +- src/circuit/commit_ivk.rs | 9 +- src/circuit/gadget/mux_chip.rs | 8 +- src/circuit/note_commit.rs | 9 +- src/circuit/value_commit_orchard.rs | 9 +- src/circuit_description | 5281 ++++++++++++++------------- src/circuit_proof_test_case.bin | Bin 5251 -> 5283 bytes 7 files changed, 2790 insertions(+), 2539 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 0bf473ac7..91a5fe13a 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -68,7 +68,7 @@ mod note_commit; mod value_commit_orchard; /// Size of the Orchard circuit. -const K: u32 = 12; +const K: u32 = 11; // Absolute offsets for public inputs. const ANCHOR: usize = 0; @@ -342,10 +342,12 @@ impl plonk::Circuit for Circuit { // Fixed columns for the Sinsemilla generator lookup table let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lookup = ( table_idx, meta.lookup_table_column(), meta.lookup_table_column(), + table_range_check_tag, ); // Instance column used for public inputs @@ -381,7 +383,8 @@ impl plonk::Circuit for Circuit { // We have a lot of free space in the right-most advice columns; use one of them // for all of our range checks. - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let range_check = + LookupRangeCheckConfig::configure(meta, advices[9], table_idx, table_range_check_tag); // Configuration for curve point operations. // This uses 10 advice columns and spans the whole circuit. @@ -1287,8 +1290,8 @@ mod tests { K, &circuits[0], ); - assert_eq!(usize::from(circuit_cost.proof_size(1)), 5088); - assert_eq!(usize::from(circuit_cost.proof_size(2)), 7360); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 5120); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7392); usize::from(circuit_cost.proof_size(instances.len())) }; @@ -1405,7 +1408,7 @@ mod tests { let test_case_bytes = fs::read("src/circuit_proof_test_case.bin").unwrap(); read_test_case(&test_case_bytes[..]).expect("proof must be valid") }; - assert_eq!(proof.0.len(), 5088); + assert_eq!(proof.0.len(), 5120); assert!(proof.verify(&vk, &[instance]).is_ok()); } diff --git a/src/circuit/commit_ivk.rs b/src/circuit/commit_ivk.rs index 33692a4a8..73c24a91f 100644 --- a/src/circuit/commit_ivk.rs +++ b/src/circuit/commit_ivk.rs @@ -734,10 +734,12 @@ mod tests { } let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lookup = ( table_idx, meta.lookup_table_column(), meta.lookup_table_column(), + table_range_check_tag, ); let lagrange_coeffs = [ meta.fixed_column(), @@ -750,7 +752,12 @@ mod tests { meta.fixed_column(), ]; - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let range_check = LookupRangeCheckConfig::configure( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let sinsemilla_config = SinsemillaChip::< OrchardHashDomains, OrchardCommitDomains, diff --git a/src/circuit/gadget/mux_chip.rs b/src/circuit/gadget/mux_chip.rs index dbe54ed40..fb81f8ea3 100644 --- a/src/circuit/gadget/mux_chip.rs +++ b/src/circuit/gadget/mux_chip.rs @@ -215,6 +215,7 @@ mod tests { MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lagrange_coeffs = [ meta.fixed_column(), @@ -228,7 +229,12 @@ mod tests { ]; meta.enable_constant(lagrange_coeffs[0]); - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let range_check = LookupRangeCheckConfig::configure( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let ecc_config = EccChip::::configure( meta, diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index 47e2fda1c..c5c8f44e8 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -2369,10 +2369,12 @@ mod tests { } let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lookup = ( table_idx, meta.lookup_table_column(), meta.lookup_table_column(), + table_range_check_tag, ); let lagrange_coeffs = [ meta.fixed_column(), @@ -2385,7 +2387,12 @@ mod tests { meta.fixed_column(), ]; - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let range_check = LookupRangeCheckConfig::configure( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let sinsemilla_config = SinsemillaChip::< OrchardHashDomains, OrchardCommitDomains, diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs index 4e4dfa36d..4356ad583 100644 --- a/src/circuit/value_commit_orchard.rs +++ b/src/circuit/value_commit_orchard.rs @@ -169,10 +169,12 @@ mod tests { meta.enable_equality(primary); let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); let lookup = ( table_idx, meta.lookup_table_column(), meta.lookup_table_column(), + table_range_check_tag, ); let lagrange_coeffs = [ @@ -187,7 +189,12 @@ mod tests { ]; meta.enable_constant(lagrange_coeffs[0]); - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let range_check = LookupRangeCheckConfig::configure( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); let sinsemilla_config = SinsemillaChip::configure( meta, diff --git a/src/circuit_description b/src/circuit_description index cffc54ff8..19578d04b 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -2,23 +2,23 @@ PinnedVerificationKey { base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", domain: PinnedEvaluationDomain { - k: 12, - extended_k: 15, - omega: 0x028961bbd9c63b7bd7c75f72e02a9727d14d99e7985184470d34cd1b8ef03001, + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, }, cs: PinnedConstraintSystem { - num_fixed_columns: 30, + num_fixed_columns: 33, num_advice_columns: 10, num_instance_columns: 1, - num_selectors: 59, + num_selectors: 61, gates: [ Product( Product( Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -29,8 +29,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -44,8 +44,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -59,8 +59,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -97,8 +97,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -109,8 +109,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -124,8 +124,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -139,8 +139,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -208,8 +208,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -220,8 +220,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -235,8 +235,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -250,8 +250,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -308,8 +308,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -320,8 +320,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -335,8 +335,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -350,8 +350,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -388,8 +388,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -400,8 +400,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -415,8 +415,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -430,8 +430,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -468,8 +468,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -480,8 +480,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -495,8 +495,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -510,8 +510,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -548,8 +548,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -560,8 +560,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -575,8 +575,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -590,8 +590,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -628,8 +628,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -640,8 +640,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -655,8 +655,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -670,8 +670,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -708,8 +708,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -720,8 +720,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -735,8 +735,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -750,8 +750,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -843,8 +843,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -855,8 +855,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -870,8 +870,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -885,8 +885,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -934,8 +934,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -946,8 +946,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -961,8 +961,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -976,8 +976,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1007,8 +1007,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1019,8 +1019,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1034,8 +1034,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1049,8 +1049,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1094,8 +1094,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1106,8 +1106,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1121,8 +1121,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1136,8 +1136,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1178,8 +1178,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1190,8 +1190,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1205,8 +1205,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1220,8 +1220,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1266,20 +1266,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1289,12 +1289,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1304,12 +1304,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1384,20 +1384,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1407,12 +1407,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1422,12 +1422,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 21, + column_index: 21, rotation: Rotation( 0, ), @@ -1501,20 +1501,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1528,8 +1528,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1543,8 +1543,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1610,8 +1610,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1622,8 +1622,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1633,12 +1633,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1652,8 +1652,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1774,8 +1774,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1786,8 +1786,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1797,12 +1797,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1816,8 +1816,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1909,8 +1909,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1921,8 +1921,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1936,8 +1936,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -1947,12 +1947,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2035,8 +2035,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2047,8 +2047,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2062,8 +2062,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2073,12 +2073,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2174,8 +2174,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2186,8 +2186,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2201,8 +2201,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2212,12 +2212,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2318,8 +2318,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2330,8 +2330,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2345,8 +2345,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2356,12 +2356,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2462,8 +2462,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2474,8 +2474,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2489,8 +2489,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2500,12 +2500,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2604,8 +2604,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2616,8 +2616,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2631,8 +2631,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2642,12 +2642,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2746,8 +2746,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2758,8 +2758,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2773,8 +2773,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2784,12 +2784,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2846,8 +2846,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2858,8 +2858,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2873,8 +2873,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2884,12 +2884,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2946,8 +2946,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2958,8 +2958,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2973,8 +2973,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -2984,12 +2984,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3046,8 +3046,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3058,8 +3058,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3073,8 +3073,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3084,12 +3084,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3146,8 +3146,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3158,8 +3158,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3173,8 +3173,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3184,12 +3184,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3275,8 +3275,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3287,8 +3287,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3302,8 +3302,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3313,12 +3313,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 19, - column_index: 19, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3404,8 +3404,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 18, - column_index: 18, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3416,8 +3416,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3431,8 +3431,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3446,8 +3446,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 18, - column_index: 18, + query_index: 22, + column_index: 22, rotation: Rotation( 0, ), @@ -3544,8 +3544,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3556,8 +3556,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3571,8 +3571,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3586,8 +3586,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3601,8 +3601,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3616,8 +3616,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3651,8 +3651,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3663,8 +3663,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3678,8 +3678,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3693,8 +3693,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3708,8 +3708,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3723,8 +3723,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3758,8 +3758,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3770,8 +3770,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3785,8 +3785,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3800,8 +3800,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3815,8 +3815,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3830,8 +3830,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3898,8 +3898,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3910,8 +3910,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3925,8 +3925,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3940,8 +3940,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3955,8 +3955,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -3970,8 +3970,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4130,8 +4130,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4142,8 +4142,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4157,8 +4157,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4172,8 +4172,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4187,8 +4187,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4202,8 +4202,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4299,8 +4299,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4311,8 +4311,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4326,8 +4326,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4341,8 +4341,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4356,8 +4356,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4371,8 +4371,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4563,8 +4563,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4575,8 +4575,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4590,8 +4590,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4605,8 +4605,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4620,8 +4620,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4635,8 +4635,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4703,8 +4703,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4715,8 +4715,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4730,8 +4730,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4745,8 +4745,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4760,8 +4760,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4775,8 +4775,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4935,8 +4935,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4947,8 +4947,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4962,8 +4962,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4977,8 +4977,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -4992,8 +4992,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5007,8 +5007,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5104,8 +5104,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5116,8 +5116,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5131,8 +5131,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5146,8 +5146,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5161,8 +5161,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5176,8 +5176,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5305,8 +5305,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5317,8 +5317,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5332,8 +5332,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5347,8 +5347,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5362,8 +5362,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5377,8 +5377,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -5474,8 +5474,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5486,8 +5486,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5501,8 +5501,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5516,8 +5516,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5531,8 +5531,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5565,8 +5565,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5577,8 +5577,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5592,8 +5592,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5607,8 +5607,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5622,8 +5622,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5656,8 +5656,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5668,8 +5668,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5683,8 +5683,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5698,8 +5698,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5713,8 +5713,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5780,8 +5780,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5792,8 +5792,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5807,8 +5807,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5822,8 +5822,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5837,8 +5837,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -5996,8 +5996,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6008,8 +6008,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6023,8 +6023,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6038,8 +6038,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6053,8 +6053,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6149,8 +6149,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6161,8 +6161,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6176,8 +6176,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6191,8 +6191,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6206,8 +6206,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -6398,8 +6398,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6410,8 +6410,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6425,8 +6425,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6440,8 +6440,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6455,8 +6455,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6470,8 +6470,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6538,8 +6538,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6550,8 +6550,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6565,8 +6565,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6580,8 +6580,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6595,8 +6595,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6610,8 +6610,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6770,8 +6770,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6782,8 +6782,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6797,8 +6797,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6812,8 +6812,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6827,8 +6827,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6842,8 +6842,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6939,8 +6939,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6951,8 +6951,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6966,8 +6966,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6981,8 +6981,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -6996,8 +6996,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7011,8 +7011,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7140,8 +7140,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7152,8 +7152,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7167,8 +7167,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7182,8 +7182,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7197,8 +7197,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7212,8 +7212,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7284,8 +7284,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7296,8 +7296,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7311,8 +7311,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7326,8 +7326,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7341,8 +7341,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7356,8 +7356,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7465,8 +7465,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7477,8 +7477,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7492,8 +7492,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7507,8 +7507,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7522,8 +7522,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7575,8 +7575,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7587,8 +7587,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7602,8 +7602,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7617,8 +7617,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7632,8 +7632,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7673,8 +7673,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7685,8 +7685,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7700,8 +7700,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7715,8 +7715,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7730,8 +7730,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7769,8 +7769,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7781,8 +7781,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7796,8 +7796,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7811,8 +7811,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7826,8 +7826,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7858,8 +7858,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7870,8 +7870,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7885,8 +7885,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7900,8 +7900,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7915,8 +7915,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -7980,8 +7980,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -7992,8 +7992,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8007,8 +8007,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8022,8 +8022,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8037,8 +8037,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8052,8 +8052,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8120,8 +8120,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8132,8 +8132,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8147,8 +8147,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8162,8 +8162,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8177,8 +8177,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8192,8 +8192,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8289,8 +8289,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8301,8 +8301,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8316,8 +8316,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8331,8 +8331,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8346,8 +8346,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8361,8 +8361,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 20, - column_index: 20, + query_index: 23, + column_index: 23, rotation: Rotation( 0, ), @@ -8451,8 +8451,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -8691,8 +8691,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -8715,7 +8715,7 @@ PinnedVerificationKey { ), Fixed { query_index: 0, - column_index: 3, + column_index: 4, rotation: Rotation( 0, ), @@ -8750,8 +8750,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 3, - column_index: 4, + query_index: 4, + column_index: 5, rotation: Rotation( 0, ), @@ -8809,8 +8809,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -8891,8 +8891,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -8996,8 +8996,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -9124,8 +9124,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -9275,8 +9275,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 8, - column_index: 9, + query_index: 9, + column_index: 10, rotation: Rotation( 0, ), @@ -9449,8 +9449,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 9, - column_index: 10, + query_index: 10, + column_index: 11, rotation: Rotation( 0, ), @@ -9470,8 +9470,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -9506,8 +9506,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 2, - column_index: 11, + query_index: 3, + column_index: 12, rotation: Rotation( 0, ), @@ -9517,8 +9517,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 22, - column_index: 22, + query_index: 25, + column_index: 25, rotation: Rotation( 0, ), @@ -9578,8 +9578,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -9602,7 +9602,7 @@ PinnedVerificationKey { ), Fixed { query_index: 0, - column_index: 3, + column_index: 4, rotation: Rotation( 0, ), @@ -9623,8 +9623,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 3, - column_index: 4, + query_index: 4, + column_index: 5, rotation: Rotation( 0, ), @@ -9654,8 +9654,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -9694,8 +9694,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -9743,8 +9743,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -9801,8 +9801,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -9868,8 +9868,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 8, - column_index: 9, + query_index: 9, + column_index: 10, rotation: Rotation( 0, ), @@ -9944,8 +9944,8 @@ PinnedVerificationKey { }, ), Fixed { - query_index: 9, - column_index: 10, + query_index: 10, + column_index: 11, rotation: Rotation( 0, ), @@ -9965,8 +9965,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -10001,8 +10001,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 2, - column_index: 11, + query_index: 3, + column_index: 12, rotation: Rotation( 0, ), @@ -10012,8 +10012,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -10073,8 +10073,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 23, - column_index: 23, + query_index: 26, + column_index: 26, rotation: Rotation( 0, ), @@ -10205,8 +10205,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10217,8 +10217,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10232,8 +10232,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10247,8 +10247,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10262,8 +10262,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10301,8 +10301,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10313,8 +10313,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10328,8 +10328,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10343,8 +10343,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10358,8 +10358,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10397,8 +10397,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10409,8 +10409,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10424,8 +10424,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10439,8 +10439,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10454,8 +10454,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10506,8 +10506,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10518,8 +10518,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10533,8 +10533,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10548,8 +10548,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10563,8 +10563,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10606,8 +10606,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10618,8 +10618,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10633,8 +10633,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10648,8 +10648,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10663,8 +10663,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10695,8 +10695,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10707,8 +10707,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10722,8 +10722,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10737,8 +10737,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10752,8 +10752,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10800,8 +10800,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10812,8 +10812,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10827,8 +10827,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10842,8 +10842,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10857,8 +10857,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10933,8 +10933,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10945,8 +10945,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10960,8 +10960,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10975,8 +10975,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -10990,8 +10990,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11022,8 +11022,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11034,8 +11034,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11049,8 +11049,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11064,8 +11064,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11079,8 +11079,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11150,8 +11150,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11162,8 +11162,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11177,8 +11177,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11192,8 +11192,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11207,8 +11207,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11246,8 +11246,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11258,8 +11258,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11273,8 +11273,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11288,8 +11288,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11303,8 +11303,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11349,8 +11349,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11361,8 +11361,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11376,8 +11376,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11391,8 +11391,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11406,8 +11406,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -11465,8 +11465,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11477,8 +11477,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11492,8 +11492,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11507,8 +11507,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11532,8 +11532,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11548,8 +11548,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11566,8 +11566,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11582,8 +11582,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11600,8 +11600,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11623,8 +11623,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11639,8 +11639,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11657,8 +11657,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11673,8 +11673,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11691,8 +11691,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11715,8 +11715,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -11731,8 +11731,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -11749,8 +11749,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -11765,8 +11765,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -11783,8 +11783,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -11810,8 +11810,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11822,8 +11822,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11837,8 +11837,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11852,8 +11852,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -11877,8 +11877,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11893,8 +11893,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11911,8 +11911,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11927,8 +11927,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11945,8 +11945,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -11968,8 +11968,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -11984,8 +11984,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12002,8 +12002,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12018,8 +12018,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12036,8 +12036,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12060,8 +12060,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12076,8 +12076,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12094,8 +12094,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12110,8 +12110,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12128,8 +12128,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12155,8 +12155,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12167,8 +12167,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12182,8 +12182,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12197,8 +12197,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12222,8 +12222,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12238,8 +12238,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12256,8 +12256,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12272,8 +12272,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12290,8 +12290,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12313,8 +12313,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12329,8 +12329,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12347,8 +12347,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12363,8 +12363,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12381,8 +12381,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12405,8 +12405,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12421,8 +12421,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12439,8 +12439,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12455,8 +12455,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12473,8 +12473,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12500,8 +12500,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12512,8 +12512,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12527,8 +12527,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12542,8 +12542,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12564,8 +12564,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12580,8 +12580,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12598,8 +12598,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12614,8 +12614,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12632,8 +12632,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 4, - column_index: 5, + query_index: 5, + column_index: 6, rotation: Rotation( 0, ), @@ -12656,8 +12656,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12668,8 +12668,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12683,8 +12683,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12698,8 +12698,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -12734,8 +12734,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12754,8 +12754,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12765,8 +12765,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -12795,8 +12795,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12815,8 +12815,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12826,8 +12826,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -12858,8 +12858,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12878,8 +12878,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12889,8 +12889,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -12919,8 +12919,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -12939,8 +12939,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -12950,8 +12950,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -12982,8 +12982,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -13002,8 +13002,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -13013,8 +13013,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 7, - column_index: 8, + query_index: 8, + column_index: 9, rotation: Rotation( 0, ), @@ -13064,8 +13064,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13076,8 +13076,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13091,8 +13091,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13106,8 +13106,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13139,8 +13139,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -13159,8 +13159,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -13170,8 +13170,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 8, - column_index: 9, + query_index: 9, + column_index: 10, rotation: Rotation( 0, ), @@ -13220,8 +13220,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13232,8 +13232,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13247,8 +13247,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13262,8 +13262,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -13295,8 +13295,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 5, - column_index: 6, + query_index: 6, + column_index: 7, rotation: Rotation( 0, ), @@ -13315,8 +13315,8 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 6, - column_index: 7, + query_index: 7, + column_index: 8, rotation: Rotation( 0, ), @@ -13326,8 +13326,8 @@ PinnedVerificationKey { ), ), Fixed { - query_index: 9, - column_index: 10, + query_index: 10, + column_index: 11, rotation: Rotation( 0, ), @@ -13377,8 +13377,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13389,8 +13389,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13404,8 +13404,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13419,8 +13419,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13434,8 +13434,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13477,8 +13477,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13489,8 +13489,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13504,8 +13504,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13519,8 +13519,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13534,8 +13534,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13577,8 +13577,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13589,8 +13589,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13604,8 +13604,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13619,8 +13619,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13634,8 +13634,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 21, - column_index: 21, + query_index: 24, + column_index: 24, rotation: Rotation( 0, ), @@ -13669,8 +13669,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -13681,8 +13681,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -13696,8 +13696,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -13711,8 +13711,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -13726,8 +13726,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -13741,8 +13741,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -13754,7 +13754,7 @@ PinnedVerificationKey { Scaled( Fixed { query_index: 0, - column_index: 3, + column_index: 4, rotation: Rotation( 0, ), @@ -13834,8 +13834,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -13919,8 +13919,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -14037,16 +14037,16 @@ PinnedVerificationKey { Negated( Product( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), }, Sum( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), @@ -14133,16 +14133,16 @@ PinnedVerificationKey { Scaled( Product( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), }, Sum( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), @@ -14173,8 +14173,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14185,8 +14185,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14200,8 +14200,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14215,8 +14215,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14282,8 +14282,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14294,8 +14294,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14309,8 +14309,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14324,8 +14324,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14391,8 +14391,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14403,8 +14403,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14418,8 +14418,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14433,8 +14433,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14471,8 +14471,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14483,8 +14483,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14498,8 +14498,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14513,8 +14513,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14560,8 +14560,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14572,8 +14572,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14587,8 +14587,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14602,8 +14602,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14673,8 +14673,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14685,8 +14685,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14700,8 +14700,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14715,8 +14715,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14760,8 +14760,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14772,8 +14772,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14787,8 +14787,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14802,8 +14802,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 24, - column_index: 24, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14849,8 +14849,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -14861,8 +14861,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -14876,8 +14876,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -14891,8 +14891,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -14906,8 +14906,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -14921,8 +14921,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -14933,8 +14933,8 @@ PinnedVerificationKey { Sum( Scaled( Fixed { - query_index: 3, - column_index: 4, + query_index: 4, + column_index: 5, rotation: Rotation( 0, ), @@ -15014,8 +15014,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -15099,8 +15099,8 @@ PinnedVerificationKey { ), Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -15217,16 +15217,16 @@ PinnedVerificationKey { Negated( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), }, Sum( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), @@ -15313,16 +15313,16 @@ PinnedVerificationKey { Scaled( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), }, Sum( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), @@ -15355,8 +15355,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15367,8 +15367,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15382,8 +15382,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15397,8 +15397,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15412,8 +15412,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15427,8 +15427,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15496,8 +15496,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15508,8 +15508,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15523,8 +15523,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15538,8 +15538,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15553,8 +15553,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15568,8 +15568,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15637,8 +15637,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15649,8 +15649,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15664,8 +15664,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15679,8 +15679,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15694,8 +15694,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15709,8 +15709,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15749,8 +15749,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15761,8 +15761,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15776,8 +15776,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15791,8 +15791,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15806,8 +15806,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15821,8 +15821,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15870,8 +15870,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15882,8 +15882,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15897,8 +15897,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15912,8 +15912,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15927,8 +15927,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15942,8 +15942,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16015,8 +16015,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16027,8 +16027,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16042,8 +16042,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16057,8 +16057,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16072,8 +16072,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16087,8 +16087,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16134,8 +16134,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16146,8 +16146,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16161,8 +16161,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16176,8 +16176,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16191,8 +16191,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16206,8 +16206,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16253,8 +16253,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16265,8 +16265,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16280,8 +16280,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16295,8 +16295,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16310,8 +16310,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16325,8 +16325,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16365,8 +16365,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16377,8 +16377,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16392,8 +16392,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16407,8 +16407,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16422,8 +16422,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16437,8 +16437,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16477,8 +16477,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16489,8 +16489,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16504,8 +16504,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16519,8 +16519,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16534,8 +16534,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16549,8 +16549,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16608,8 +16608,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16620,8 +16620,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16635,8 +16635,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16650,8 +16650,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16665,8 +16665,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16680,8 +16680,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16727,8 +16727,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16739,8 +16739,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16754,8 +16754,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16769,8 +16769,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16784,8 +16784,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16799,9 +16799,9 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, - rotation: Rotation( + query_index: 28, + column_index: 28, + rotation: Rotation( 0, ), }, @@ -16858,8 +16858,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16870,8 +16870,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16885,8 +16885,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16900,8 +16900,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16915,8 +16915,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16930,8 +16930,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17001,8 +17001,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17013,8 +17013,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17028,8 +17028,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17043,8 +17043,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17058,8 +17058,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17073,8 +17073,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17106,8 +17106,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17118,8 +17118,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17133,8 +17133,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17148,8 +17148,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17163,8 +17163,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17178,8 +17178,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17211,8 +17211,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17223,8 +17223,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17238,8 +17238,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17253,8 +17253,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17268,8 +17268,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17283,8 +17283,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17330,8 +17330,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17342,8 +17342,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17357,8 +17357,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17372,8 +17372,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17387,8 +17387,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17402,8 +17402,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17435,8 +17435,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17447,8 +17447,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17462,8 +17462,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17477,8 +17477,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17492,8 +17492,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17507,8 +17507,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17540,8 +17540,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17552,8 +17552,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17567,8 +17567,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17582,8 +17582,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17597,8 +17597,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17612,8 +17612,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17645,8 +17645,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17657,8 +17657,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17672,8 +17672,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17687,8 +17687,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17702,8 +17702,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17717,8 +17717,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17776,8 +17776,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17788,8 +17788,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17803,8 +17803,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17818,8 +17818,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17833,8 +17833,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17848,8 +17848,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17881,8 +17881,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17893,8 +17893,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17908,8 +17908,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17923,8 +17923,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17938,8 +17938,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17953,8 +17953,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -17993,8 +17993,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18005,8 +18005,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18020,8 +18020,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18035,8 +18035,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18050,8 +18050,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18065,8 +18065,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18105,8 +18105,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18117,8 +18117,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18132,8 +18132,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18147,8 +18147,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18162,8 +18162,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18177,8 +18177,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18248,8 +18248,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18260,8 +18260,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18275,8 +18275,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18290,8 +18290,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18305,8 +18305,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18320,8 +18320,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18360,8 +18360,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18372,8 +18372,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18387,8 +18387,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18402,8 +18402,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18417,8 +18417,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18432,8 +18432,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18472,8 +18472,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18484,8 +18484,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18499,8 +18499,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18514,8 +18514,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18529,8 +18529,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18544,8 +18544,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 25, - column_index: 25, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18615,8 +18615,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18627,8 +18627,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18642,8 +18642,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18657,8 +18657,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18672,8 +18672,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18687,8 +18687,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18734,8 +18734,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18746,8 +18746,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18761,8 +18761,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18776,8 +18776,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18791,8 +18791,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18806,8 +18806,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18846,8 +18846,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18858,8 +18858,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18873,8 +18873,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18888,8 +18888,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18903,8 +18903,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18918,8 +18918,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18977,8 +18977,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18989,8 +18989,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19004,8 +19004,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19019,8 +19019,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19034,8 +19034,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19049,8 +19049,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19089,8 +19089,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19101,8 +19101,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19116,8 +19116,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19131,8 +19131,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19146,8 +19146,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19161,8 +19161,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19208,8 +19208,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19220,8 +19220,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19235,8 +19235,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19250,8 +19250,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19265,8 +19265,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19280,8 +19280,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19339,8 +19339,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19351,8 +19351,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19366,8 +19366,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19381,8 +19381,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19396,8 +19396,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19411,8 +19411,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19451,8 +19451,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19463,8 +19463,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19478,8 +19478,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19493,8 +19493,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19508,8 +19508,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19523,8 +19523,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19563,8 +19563,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19575,8 +19575,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19590,8 +19590,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19605,8 +19605,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19620,8 +19620,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19635,8 +19635,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19682,9 +19682,9 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, - rotation: Rotation( + query_index: 29, + column_index: 29, + rotation: Rotation( 0, ), }, @@ -19694,8 +19694,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19709,8 +19709,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19724,8 +19724,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19739,8 +19739,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19754,8 +19754,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19813,8 +19813,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19825,8 +19825,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19840,8 +19840,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19855,8 +19855,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19870,8 +19870,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19885,8 +19885,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19932,8 +19932,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19944,8 +19944,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19959,8 +19959,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19974,8 +19974,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19989,8 +19989,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20004,8 +20004,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20037,8 +20037,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20049,8 +20049,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20064,8 +20064,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20079,8 +20079,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20094,8 +20094,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20109,8 +20109,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20142,8 +20142,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20154,8 +20154,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20169,8 +20169,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20184,8 +20184,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20199,8 +20199,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20214,8 +20214,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 26, - column_index: 26, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20248,8 +20248,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20260,8 +20260,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20275,8 +20275,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20290,8 +20290,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20305,8 +20305,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20320,8 +20320,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20335,8 +20335,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20395,8 +20395,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20407,8 +20407,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20422,8 +20422,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20437,8 +20437,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20452,8 +20452,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20467,8 +20467,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20482,8 +20482,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20542,8 +20542,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20554,8 +20554,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20569,8 +20569,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20584,8 +20584,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20599,8 +20599,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20614,8 +20614,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20629,8 +20629,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20663,8 +20663,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20675,8 +20675,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20690,8 +20690,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20705,8 +20705,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20720,8 +20720,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20735,8 +20735,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20750,8 +20750,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20784,8 +20784,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20796,8 +20796,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20811,8 +20811,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20826,8 +20826,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20841,8 +20841,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20856,8 +20856,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20871,8 +20871,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20931,8 +20931,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20943,8 +20943,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20958,8 +20958,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20973,8 +20973,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20988,8 +20988,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21003,8 +21003,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21018,8 +21018,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21078,8 +21078,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21090,8 +21090,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21105,8 +21105,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21120,8 +21120,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21135,8 +21135,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21150,8 +21150,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21165,8 +21165,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21225,8 +21225,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21237,8 +21237,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21252,8 +21252,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21267,8 +21267,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21282,8 +21282,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21297,8 +21297,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21312,8 +21312,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21346,8 +21346,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21358,8 +21358,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21373,8 +21373,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21388,8 +21388,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21403,8 +21403,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21418,8 +21418,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21433,8 +21433,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21467,8 +21467,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21479,8 +21479,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21494,8 +21494,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21509,8 +21509,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21524,8 +21524,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21539,8 +21539,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21554,8 +21554,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21626,8 +21626,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21638,8 +21638,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21653,8 +21653,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21668,8 +21668,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21683,8 +21683,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21698,8 +21698,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21713,8 +21713,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21773,8 +21773,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21785,8 +21785,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21800,8 +21800,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21815,8 +21815,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21830,8 +21830,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21845,8 +21845,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21860,8 +21860,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21894,8 +21894,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21906,8 +21906,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21921,8 +21921,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21936,8 +21936,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21951,8 +21951,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21966,8 +21966,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -21981,8 +21981,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22015,8 +22015,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22027,8 +22027,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22042,8 +22042,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22057,8 +22057,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22072,8 +22072,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22087,8 +22087,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22102,8 +22102,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22136,8 +22136,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22148,8 +22148,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22163,8 +22163,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22178,8 +22178,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22193,8 +22193,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22208,8 +22208,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22223,8 +22223,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22264,8 +22264,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22276,8 +22276,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22291,8 +22291,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22306,8 +22306,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22321,8 +22321,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22336,8 +22336,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22351,8 +22351,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22411,8 +22411,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22423,8 +22423,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22438,8 +22438,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22453,8 +22453,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22468,8 +22468,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22483,8 +22483,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22498,8 +22498,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22558,8 +22558,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22570,8 +22570,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22585,8 +22585,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22600,8 +22600,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22615,8 +22615,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22630,8 +22630,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22645,8 +22645,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22693,8 +22693,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22705,8 +22705,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22720,8 +22720,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22735,8 +22735,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22750,8 +22750,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22765,8 +22765,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22780,8 +22780,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22814,8 +22814,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22826,8 +22826,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22841,8 +22841,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22856,8 +22856,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22871,8 +22871,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22886,8 +22886,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22901,8 +22901,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22935,8 +22935,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22947,8 +22947,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22962,8 +22962,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22977,8 +22977,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -22992,8 +22992,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23007,8 +23007,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23022,8 +23022,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23056,8 +23056,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23068,8 +23068,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23083,8 +23083,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23098,8 +23098,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23113,8 +23113,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23128,8 +23128,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23143,8 +23143,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23184,8 +23184,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23196,8 +23196,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23211,8 +23211,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23226,8 +23226,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23241,8 +23241,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23256,8 +23256,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23271,8 +23271,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23312,8 +23312,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23324,8 +23324,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23339,8 +23339,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23354,8 +23354,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23369,8 +23369,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23384,8 +23384,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23399,8 +23399,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23471,8 +23471,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23483,8 +23483,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23498,8 +23498,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23513,8 +23513,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23528,8 +23528,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23543,8 +23543,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23558,8 +23558,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23599,8 +23599,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23611,8 +23611,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23626,8 +23626,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23641,8 +23641,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23656,8 +23656,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23671,8 +23671,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23686,8 +23686,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23727,8 +23727,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23739,8 +23739,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23754,8 +23754,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23769,8 +23769,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23784,8 +23784,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23799,8 +23799,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23814,8 +23814,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23886,8 +23886,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23898,8 +23898,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23913,8 +23913,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23928,8 +23928,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23943,8 +23943,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23958,8 +23958,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23973,8 +23973,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24021,8 +24021,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24033,8 +24033,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24048,8 +24048,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24063,8 +24063,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24078,8 +24078,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24093,8 +24093,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24108,8 +24108,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24149,8 +24149,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24161,8 +24161,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24176,8 +24176,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24191,8 +24191,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24206,8 +24206,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24221,8 +24221,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24236,8 +24236,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24296,8 +24296,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24308,8 +24308,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24323,8 +24323,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24338,8 +24338,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24353,8 +24353,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24368,8 +24368,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24383,8 +24383,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24424,8 +24424,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24436,8 +24436,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24451,8 +24451,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24466,8 +24466,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24481,8 +24481,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24496,8 +24496,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24511,8 +24511,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24559,8 +24559,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24571,8 +24571,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24586,8 +24586,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24601,8 +24601,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24616,8 +24616,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24631,8 +24631,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24646,8 +24646,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24706,8 +24706,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24718,8 +24718,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24733,8 +24733,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24748,8 +24748,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24763,8 +24763,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24778,8 +24778,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24793,8 +24793,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24834,8 +24834,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24846,8 +24846,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24861,8 +24861,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24876,8 +24876,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24891,8 +24891,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24906,8 +24906,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24921,8 +24921,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24962,8 +24962,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24974,8 +24974,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -24989,8 +24989,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25004,8 +25004,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25019,8 +25019,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25034,8 +25034,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25049,8 +25049,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25097,8 +25097,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25109,8 +25109,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25124,8 +25124,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25139,8 +25139,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25154,8 +25154,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25169,8 +25169,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25184,8 +25184,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25244,8 +25244,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25256,8 +25256,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25271,8 +25271,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25286,8 +25286,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25301,8 +25301,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25316,8 +25316,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25331,8 +25331,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25379,8 +25379,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25391,8 +25391,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25406,8 +25406,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25421,8 +25421,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25436,8 +25436,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25451,8 +25451,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25466,8 +25466,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25500,8 +25500,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25512,8 +25512,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25527,8 +25527,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25542,8 +25542,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25557,8 +25557,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25572,8 +25572,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25587,8 +25587,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25621,8 +25621,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25633,8 +25633,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25648,8 +25648,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25663,8 +25663,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25678,8 +25678,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25693,8 +25693,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25708,8 +25708,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25742,8 +25742,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25754,8 +25754,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25769,8 +25769,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25784,8 +25784,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25799,8 +25799,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25814,8 +25814,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25829,8 +25829,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25889,8 +25889,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25901,8 +25901,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25916,8 +25916,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25931,8 +25931,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25946,8 +25946,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25961,8 +25961,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -25976,8 +25976,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26036,8 +26036,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26048,8 +26048,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26063,8 +26063,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26078,8 +26078,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26093,8 +26093,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26108,8 +26108,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26123,8 +26123,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26157,8 +26157,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26169,8 +26169,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26184,8 +26184,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26199,8 +26199,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26214,8 +26214,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26229,8 +26229,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26244,8 +26244,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26278,8 +26278,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26290,8 +26290,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26305,8 +26305,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26320,8 +26320,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26335,8 +26335,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26350,8 +26350,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26365,8 +26365,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26422,8 +26422,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26434,8 +26434,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26449,8 +26449,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26464,8 +26464,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26521,8 +26521,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26533,8 +26533,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26548,8 +26548,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26563,8 +26563,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26620,8 +26620,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26632,8 +26632,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26647,8 +26647,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26662,8 +26662,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26693,8 +26693,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26705,8 +26705,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26720,8 +26720,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26735,8 +26735,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26766,8 +26766,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26778,8 +26778,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26793,8 +26793,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26808,8 +26808,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26877,8 +26877,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26889,8 +26889,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26904,8 +26904,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26919,8 +26919,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26976,8 +26976,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26988,8 +26988,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27003,8 +27003,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27018,8 +27018,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27049,8 +27049,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27061,8 +27061,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27076,8 +27076,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27091,8 +27091,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27122,8 +27122,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27134,8 +27134,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27149,8 +27149,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27164,8 +27164,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27195,8 +27195,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27207,8 +27207,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27222,8 +27222,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27237,8 +27237,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27275,8 +27275,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27287,8 +27287,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27302,8 +27302,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27317,8 +27317,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27374,8 +27374,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27386,8 +27386,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27401,8 +27401,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27416,8 +27416,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27473,8 +27473,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27485,8 +27485,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27500,8 +27500,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27515,8 +27515,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27560,8 +27560,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27572,8 +27572,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27587,8 +27587,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27602,8 +27602,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27633,8 +27633,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27645,8 +27645,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27660,8 +27660,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27675,8 +27675,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27706,8 +27706,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27718,8 +27718,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27733,8 +27733,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27748,8 +27748,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27779,8 +27779,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27791,8 +27791,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27806,8 +27806,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -27821,8 +27821,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -28125,7 +28125,7 @@ PinnedVerificationKey { fixed_queries: [ ( Column { - index: 3, + index: 4, column_type: Fixed, }, Rotation( @@ -28143,7 +28143,7 @@ PinnedVerificationKey { ), ( Column { - index: 11, + index: 1, column_type: Fixed, }, Rotation( @@ -28152,7 +28152,7 @@ PinnedVerificationKey { ), ( Column { - index: 4, + index: 12, column_type: Fixed, }, Rotation( @@ -28215,7 +28215,7 @@ PinnedVerificationKey { ), ( Column { - index: 12, + index: 11, column_type: Fixed, }, Rotation( @@ -28224,7 +28224,7 @@ PinnedVerificationKey { ), ( Column { - index: 1, + index: 13, column_type: Fixed, }, Rotation( @@ -28242,7 +28242,7 @@ PinnedVerificationKey { ), ( Column { - index: 13, + index: 3, column_type: Fixed, }, Rotation( @@ -28393,6 +28393,33 @@ PinnedVerificationKey { 0, ), ), + ( + Column { + index: 30, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 31, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 32, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), ], permutation: Argument { columns: [ @@ -28441,19 +28468,19 @@ PinnedVerificationKey { column_type: Advice, }, Column { - index: 3, + index: 4, column_type: Fixed, }, Column { - index: 8, + index: 9, column_type: Fixed, }, Column { - index: 9, + index: 10, column_type: Fixed, }, Column { - index: 10, + index: 11, column_type: Fixed, }, ], @@ -28463,40 +28490,111 @@ PinnedVerificationKey { input_expressions: [ Product( Fixed { - query_index: 14, - column_index: 14, + query_index: 15, + column_index: 15, rotation: Rotation( 0, ), }, Sum( Product( - Fixed { - query_index: 15, - column_index: 15, - rotation: Rotation( - 0, - ), - }, Sum( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), Negated( - Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( Advice { - query_index: 17, + query_index: 9, column_index: 9, rotation: Rotation( - 1, + 0, ), }, - 0x0000000000000000000000000000000000000000000000000000000000000400, + Negated( + Scaled( + Advice { + query_index: 17, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), ), + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, ), ), ), @@ -28506,13 +28604,36 @@ PinnedVerificationKey { 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Fixed { - query_index: 15, - column_index: 15, - rotation: Rotation( - 0, + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), ), ), Advice { @@ -28525,6 +28646,96 @@ PinnedVerificationKey { ), ), ), + Product( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), ], table_expressions: [ Fixed { @@ -28534,14 +28745,21 @@ PinnedVerificationKey { 0, ), }, + Fixed { + query_index: 2, + column_index: 1, + rotation: Rotation( + 0, + ), + }, ], }, Argument { input_expressions: [ Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -28559,8 +28777,8 @@ PinnedVerificationKey { Product( Sum( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), @@ -28568,16 +28786,16 @@ PinnedVerificationKey { Negated( Product( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), }, Sum( Fixed { - query_index: 10, - column_index: 12, + query_index: 11, + column_index: 13, rotation: Rotation( 0, ), @@ -28607,8 +28825,8 @@ PinnedVerificationKey { Sum( Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -28628,8 +28846,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -28642,8 +28860,8 @@ PinnedVerificationKey { Sum( Product( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -28757,8 +28975,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 16, - column_index: 16, + query_index: 19, + column_index: 19, rotation: Rotation( 0, ), @@ -28778,15 +28996,15 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 11, - column_index: 1, + query_index: 12, + column_index: 2, rotation: Rotation( 0, ), }, Fixed { - query_index: 12, - column_index: 2, + query_index: 13, + column_index: 3, rotation: Rotation( 0, ), @@ -28797,8 +29015,8 @@ PinnedVerificationKey { input_expressions: [ Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -28816,8 +29034,8 @@ PinnedVerificationKey { Product( Sum( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), @@ -28825,16 +29043,16 @@ PinnedVerificationKey { Negated( Product( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), }, Sum( Fixed { - query_index: 13, - column_index: 13, + query_index: 14, + column_index: 14, rotation: Rotation( 0, ), @@ -28864,8 +29082,8 @@ PinnedVerificationKey { Sum( Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -28885,8 +29103,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -28899,8 +29117,8 @@ PinnedVerificationKey { Sum( Product( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -29014,8 +29232,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 17, - column_index: 17, + query_index: 20, + column_index: 20, rotation: Rotation( 0, ), @@ -29035,15 +29253,15 @@ PinnedVerificationKey { ), }, Fixed { - query_index: 11, - column_index: 1, + query_index: 12, + column_index: 2, rotation: Rotation( 0, ), }, Fixed { - query_index: 12, - column_index: 2, + query_index: 13, + column_index: 3, rotation: Rotation( 0, ), @@ -29053,58 +29271,61 @@ PinnedVerificationKey { ], constants: [ Column { - index: 3, + index: 4, column_type: Fixed, }, ], minimum_degree: None, }, fixed_commitments: [ - (0x3a83a8e762ebade712aa5cf3c41c730a79369475085bf1155579f7f7682408e2, 0x25b00d3ee1da9a6bbd36b35ba461da45abd931c767b863ec4a604f8ce094e4eb), - (0x1caeb4d7ebb44a717f83ee5afd35446a5e2124f6a4075342ba4eff589523fb57, 0x3a8c431a13632a5b5f035eb4b804d37f2591e84d05d765ba3f70a3d61b907ebb), - (0x107d95a6361fc98df9042f32451faa4fd48c1381653be7847d97cf997a55a4ad, 0x31ebf6a2e352108bb180c3278e72d88bb5bab723d3b38aa47c144fc37fb8a962), - (0x20700a506e3d86a64a39b130676dddce5f1b2bf0334fec71ed2551c204822c67, 0x3b6942d1884ab8af10fad654411308e22b2cd04efc964b92fd921678436c0c98), - (0x01050032408d33b1dfaede46b04fa62672309dd6068c0833589f4c8080e829a2, 0x0e3f605da6ff82b3aa6ad00dcf43b9478f05ff876599522bf6e560d3d014fc34), - (0x3de6d72fbecfa7c79cc390c6a7d5f80f1bcdb6ec66967002c0f003890ca6e1fb, 0x188d7336a6662b8e16e4b3a279958e60dbe1f86bfdbc1dca253db40235430f44), - (0x1581f8e414673d197d0cd5730da9bb65faae27e4a7aa70055f1c92d70fa31f7d, 0x3262ae14b4137e321618661aa7a5f4b817ff8b2846d9362813da34512c6bd965), - (0x21c96b5ae31bc87ecc34afaeb56d6c155b624b22f23f474ea80fc0bc7312735d, 0x123f4ffff944155267ab11f68de7573cb27a78b30d96ad315756086adfc75137), - (0x17a4fffca31db428439c483107a7b92f8b81451bb66892f2e8b2e4a3f2181083, 0x31f214f9e19e6282a502fd0984b81b9f7c761d66236e7600049e45ec7acfe778), - (0x31efd1ed8ab3ef69dd0a927b9c371fc0e9a2dfbd3586c5f596133f2605445850, 0x28da702b4e3f6df487b6530829a48751c10557127d11b0056c7c581091a8e03e), - (0x098c8a506a6d33d2744d0e1810c2b5070d49f597c8b87fcef67ee008da94f56c, 0x3d7dd49111a5e9834dbd5c1fee58ceae6ac758ee167522843fbb50bd95715cab), - (0x17c91b96eabea3a9ff280ae99e74bb96e80e14d770cf5d0a35814500c08159ac, 0x021d68cbd102f26c8c1b849312c3970f06d0e8c4733d325c5247137da3f940eb), - (0x3c0f3f0d7b2306490dac7d578d4846c63adcc76988ce322d8691c3b8b5b0f623, 0x12d81ca672a1c18f6e0d9b7eb8fbabdbe450fae6667cf349c1a0e63ca9a0824e), - (0x27d13b33003ffddcd36efb731fe94db93d181bd994e0c057e945402bc8501789, 0x0e1dde94ea3b35e0d0a66350163ba2ff9dd5070500912b7d076747816965ffd2), - (0x3fdc611a96e66e8f5c21c211bff2006204c4884b2c6df9b55d92420af8e32d15, 0x0a525125d5a85a579cbc8e4862b88800d7dbaf8a8adc18bd0181bbbab9434b8d), - (0x245ebb4ccefa7c4e2d5a9d7b1746b8277abc25f74cd11b2dbb752d49612f248e, 0x145f605111205a7c3e4620ac035b3cccb6375f8d3c3469b7900e427607c401c9), - (0x1751912a19fa0009ece61b686342d6b4385415e942159e8db3f174ad24d612b9, 0x0f31114ef566211d46914d0bc2d1a27a0e34eeda04dab53a0af7a37024f057a1), - (0x091c6c4854fa5d9ed8a966f2a1c4946b41f6872de6c19fa8b521a0a8eb2bd899, 0x29100b4e15344d750fae4a81c82faca1e8e0573336b1f54b394946e95e7baad0), - (0x0f1d83f1dd2f4ba4d92cae2a2f40fc6d5d66fb2b6d1f1a2e981931cfc7c751af, 0x385ae95bb483cc65bb507d8418e447a7ad8346bc52b5114913d1e2c25c0fd11d), - (0x070664e70f0b48311a30b833a6b93cdf4ab06b872f28a723b935c88802275bd0, 0x1a3c22a9ff9d9d5434b8b979d6635d135d909b143927bc90a96cde88c6e93331), - (0x34c8b83a2cc924f1b0237978c8f911e6a54375c509ba46456a011fbb74c8698c, 0x260cc681c222535c0030f702172ee8855b681c16d706b1b9a786165e06705de6), - (0x1b7a61e8a9b32fe558433feec9aaf51204e5486aa468d7215087ed35fd6ecbe5, 0x1f36dc6852f92c141ba800f721d079ffc553c7449b85d16e7487e0c3009c7835), - (0x3bb657ca32617e6242b6c6a0b166a1db205024d0441d091b8d45fb478cd4782c, 0x3189ce1b97103345fc0eafd287eed80ab186151171f22af2c9befc71a0957529), - (0x25578b0a6d546cf38dc84329fad41e59690a2bd94a0db5fddb42e0db8c267827, 0x03448e4552625dda62a96318bcafcc305deafd6a028f8379d8c8d9ffa0f86e64), - (0x3eab58caf9fc2aa3fee6d649cf087fe9bca284c27f57c08410b0f8a7e09d634c, 0x04b350dc56fe19a25da0882d2acb6622bdad1c4b3e2200d35acf689782c20da7), - (0x37e00880dbfd31f1c3f86201583025a666bf48745428ac39caa1d0a0acaa0bd9, 0x0ff8ef43177aa324665a296a9a444fb4a6666e250930a039a687e53acc43eddc), - (0x0934479f5c328fdb235ac47bf94cb8551784068de4fc26f0dcdca078138cb71d, 0x213f745ff2233ec74c310b142665e4e223643eb72607fc50b98aae5c7149c78f), - (0x1a98842473bddb61c943296a39cc0a8a41cec5aa02696bd0a97569ca9f839186, 0x08291ab77b541973368946a0d14c85c69a142bfda31f9021328c98b69be25e3c), - (0x34a41b2fa64d913ddc6df62a3b881658ee29bd5c69154dc30bee28d64acee443, 0x1d88f6fd73525eeb4e8b0531297edcd107bf3c2303dd615f34732d7fb01a9b16), - (0x0a6e085a051cab2808d58f29990b4ba83ed49fba5f363f67b78c329514ac79e5, 0x20b236e5722f4cff16ee1607ffa3bf60c63e9f866b27d85e85a0b06b0b8c58ec), + (0x3887a29815d3a28d43c453904169e07def787baca6c9452505d2de78dd44b86f, 0x2f95e59472ab087725d62deea9c3b406ae490eff7c0318269d6f2b025934cc70), + (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), + (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), + (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), + (0x02656490d7b8420bfe91e220b7d95ff7e79bca851ec0d26cb2221772c25e8638, 0x0ee047851a6b3d0038ff02a38782e8d349febf23035d21227fb95693083eb710), + (0x1dd2f90c7130eabb75c1f83620474ecd7565c6751cac21e6b3400e2554cb30ae, 0x0135321193a6f63fd7bdcbe4ec21c79cf2705deb072779586e4eafdbd52cc0eb), + (0x29a5048146830326a4c86c7959158cb88e6be880e1980adaa3d4bbdc1e4aae22, 0x2b1c22a72f40fc3196890c6e8723a9df96a73c0d81c83c015af087f920da8465), + (0x0087eb927dee14807ad837123f7ed3e34accaa3739d3e6172467acc8671c2653, 0x351df64e5f2b6956c800cc9c5e3a0e875b6f700be165bc478b53caf05776f9e0), + (0x319b61505610a63e57bbc53df58f1086f5840a826163fd5ca22b8d4a3238abbe, 0x232fe2570f8b5df28088f667ca920fe603329464a3a9dcfdbc78497aee19193e), + (0x3dfff1fb77235cfc3c9b39b7c4f99b5df4e89e957155385507a4ea91750069a2, 0x0a60bb0d445d0cf8fa75d1625b6ad86944d150c6679f00e78016829bf47ffa12), + (0x37bdb76a767d836c13381bf59417e256c1b326df542851d623617f2a45c59992, 0x09509cfe95dca7401708bab0ce45a126bac7fc5051b1c45f119e54a4e5fd881d), + (0x2d482cf0c1c13d6d2afe85feac3f565d054238acc10b7ff78dc08cb9aea3a5ab, 0x2f7182906fc5aa8952982e96ae29891fc988d468623244e02ea8453b5b3c65f8), + (0x184b191b2c11511c81ace6f3a56f833c5b6465a7a394dad84226588b7750969b, 0x0d200f2a66888760d60a9e117a85d826abe27a0f7cf6211b2ddf843475667618), + (0x04fae4e51e99d50ff8a55a449c0234a9a613e996a9b202db18ef01e7ad42b052, 0x1d083ab8f2c454ea5e1f9cf81a419a4a55347136c4feff75ec8a0a19f909d558), + (0x12d6a260a08c59e9df032cd6c855f081d99321fe2f33d33508b4180411f0dadc, 0x31fbd5ce92f6cd283658690e93a0bcbb515b1aa9728024f5eb583f5f27da6a11), + (0x3aaa1190000787a9cc4008d68adf7a91b48ff5470fdfb3d3ee36f64df7cfd045, 0x2f1723e3595adf0106d4fe2f11af025978f616b6697036c27ebbd682a013928e), + (0x1bbe9643cceac1b79ea642312b57cf5b7739a2accb6641c7c902a0651f8c90b2, 0x3a7c2a5db44cd0fa31f5a26206fc3ea8e81fea14ddbcdab3204dbcd840a14184), + (0x39a9e0b36cd0cf9445f6533d02ea7187f1d8100085a6228509c8af4743f2eb24, 0x311a439a351fdadfaced9213ff8bcadca7a03d1bc18d9f4bb33ea1806bc2c6be), + (0x0957fb68f275d18d730f9c106de4b4cfd966b3eeb0434b1ea66ddfda2420a8ad, 0x1ae46e6b003224d3f30eb366fc3d9db07d07ded1c474d239602aed8ac859e895), + (0x3d5fc48944b2527964ab562447e540f7512a225c2468ba76398dbd6842bcd776, 0x22ca98fd09c21884a128d63511bcd366d7fa61d7b21271e0c0927b4677c7242f), + (0x03be84ba69d6def665955d6dc72a6f647cb206de2fc5cc6d0e1474354bb03f3e, 0x1eabb979cab6e3e9a82d7b692d18e9757b684f1b855845db1ed8925f3b9ad918), + (0x0c1fbfb10301c163416949dff37b9334f8c62372f154386e40882b4327d0cf98, 0x19f48dbe5b56cb8711943bed857307de739099a1cb78c12a1015770f8553c601), + (0x2096a01846851be44913d49936d7362716c296970aeba41f35b23946cc1fa41c, 0x3af057b14acc535df8dc9f159a1290d92b8fa875b1982d669b0df5a4429f59e6), + (0x334105dd96996a08df56e88261dcd87c5356cfc0f2b8ae0a9419899d5def147b, 0x09ddf24ae765eda056cf59b16ac14464240c83e253135682c02e6546f89dd396), + (0x0aa9bf3b3cae0bbeb70f32d96a43603853872c28ef246db1bb85c885e112b4c1, 0x0718dce6ad248d2cedc43f3a23ec6d4d7dd305cb6f8fc9a3098a11acf42b5967), + (0x06fe6f3926a9de1432ebf4934fef695942a41eaea45a2c42d6af795af6dd1f7b, 0x30342fc0dc2cdec7fdf1aab0eb28f7ca21b4dd478c596540444c0932d8dd56dc), + (0x12fb328eaf326033eb7376c6aa6aff345bbb300b7e5fab858feec8cd3e4bdf58, 0x28bdf84118d334220e557ae9959a091ceb54c36d4a6d1f8a1518948d8a8124c5), + (0x0558514fa4d8feae12519efa8c79b7e7fe327642f28455ae300cffdc21cf5a22, 0x22c8f7ede18bcf4083f7cb6bf94b1de06305107537bcc31027dd400a7455dded), + (0x0aa54dc82361b7d6f35e36d55290ede3e4962e85665475fb15e51b626c849f7f, 0x16927eaf3dcbd28a8e1eb1a19235a512da8858d10040d3b26425ec054ce0eb3a), + (0x39c1526f64989d617bd43b64427f26c5068485b3d635bbb746b6be5ebf8361c8, 0x398ab66905a4e1e36fc3e2da5d1b1e918bda970ad17d46cd08b852e51879ca6a), + (0x3aa89e6834df650fcbdc0a295b03a58002cdcd14198f8af3069eb222d2d17c66, 0x067ec4c41d0352ea32b5872af2b051c78882157d0ae87486dce3c4c2c29877f9), + (0x1394764de03aaa28c9a9d2b91798a25629d0412264057ef247c6faf21e4354e3, 0x1de01702d1d58eff7824e40712beb1429a101c1ed844fcaa7100519f85faffd7), + (0x261a83f8122eb036760791a4e9d52235df4939fdf8175f8d240a333e06557e7e, 0x184fb28734999d991d4bb862d1e47e3ae20336706f82ceb180609fa68fd85501), ], permutation: VerifyingKey { commitments: [ - (0x26d7150d98acf5efa7739440641d97629e2d6553547920432e43d747b998d49e, 0x3223285fb44e1736e7216cd51276087bce39f7e5c0fdb1ef49ab4c6de26b256d), - (0x07800024b352149368405f222a8dfbf373bd4603df89929a5d00f7ac9ffac504, 0x250be8a84de9a8ded91e85860f1b1751f6bd2c0aba96329ee2d6f0e377f4679f), - (0x3384b0dbfa6553ad5adf0b218df2cbe6243c33102a97774b4e023ec1dc2d83e9, 0x2873fe49458cd70b9d72419e0d6a6ceadb8070f4b62a0bb47c58a89269e0b583), - (0x38def0fd8f233ef8651a28ffb7ae6f1e4eaeb0acec19453a3e5a0d70b2058782, 0x0512c67736284a225f0b6617cabd76ac2e4a6805940af4480798ca884e02d277), - (0x26b6d69fd8c13013c6ab5fb74bd3fbe85d01b0abb57e149ff53e77a535c6bf40, 0x05ae4f52e4ab72ff3cf2b64df6d371fda270f4f78ed0bccce8e3138d4e30e4a0), - (0x3f1b6f3ea5a2b24646dbe1c6f7c7dbf797fe6602a344bed59668ba5413519631, 0x0401a6f6ed893aa112f234127f8c30ee6e09b45f75993351aea9974389b261d6), - (0x2f34843015cfc9c9ff59c7ecab3cbb6aea69dcf6f5af79e166f25d90f70353d5, 0x2bcfde5880412d171705b41124b404a323697c4d1008b2e8b2bf9966e5809d3d), - (0x082e9af26adc31f97c38ce587ffde9af5d8238d16ad61a236bbd3c805515f144, 0x051d36eb85b6402dfb2a55ae1507b358319d016483d7ecf6be49793bbb64e79e), - (0x240a361e73afa04a2e5cc578680e54bf28e3375dbb35a8918c3cdbc91f1bc25b, 0x161c53e65c1b6500b576d8fa982e2565dbe35954840b0bab8a3d912158b9dbe7), - (0x32f883bbd63b0700f0150ea8d71f6f5d7cdcc4463289983d71e9bc104d4a5c28, 0x33aeb42bec794138b8db28696bd7cef4946a8a89edcbf3f8289655ff9f9129ee), - (0x03f33d3064517ab1a8e538444013bd0d6b011f9923f8cb964763a88d6d7409e0, 0x16f534b6d12d9e011b951e374982f048f0bed808099fd3ed97cd827360f6fb65), - (0x0ee42598f7ed2c349d720bdcbe34f85d6650e1b3f2add5a71ab0bf330fcd4f51, 0x346a2c51d2895839bb3e556eb20e6af8f5248f2d538a1407622c9d69bde1448a), + (0x286d1f6ab2fb58b3ba974d1807c606914deea07b64615089452f1feaa06ef0db, 0x08bb42474059164d528fb06f0b80b08b3ebdc87cbe0c2718d0c6199984b2119d), + (0x31fd9e62ffdd86ec55a2ead7a4b74dd21ddcf56029dc5d334491bffc7bd2ffb3, 0x2f990b235ee3f35e09a77f1414d21fab06cc60fe8fe6f52407d7599204632cd4), + (0x2044e502b5716abe00c9dde5348392b4fc489b5097aca8f5401a5153820903dd, 0x155aa6b3f9ea3e01f25eca37b0a62d28fe24a1a96d033c074e6cb22b08d118d5), + (0x36599df2c3de06015c3167fe0b2b22aab1ae9587ff050977193d5d753c8be6a8, 0x32b02df0138a92f3b23556ad96f9ef9bee0c34c8900cb4ecaadf3252ae4e0edc), + (0x13631970b4bae5c49d31638a2af724495c8b2074bd015f3c1c06af24956ca995, 0x1b7e3517b6db255c9b71753707de5d6fb33f83825ad8416db482669daac81ba3), + (0x021eb6e340ea808444c833c25e326c03223ea3fb458771e814a7d9130eddeb74, 0x230be5c1f0b81145d7a45c032c4dbc68e53db1fbda374a0f0d2e0da702032b2f), + (0x18720c0f1f48ad21f6e1d0d33adc569ac901c68cdcb16d5398ac986b421f7038, 0x11cf59a013ad87f91ce8567087a80ee9395af8fc1383ac10e490d9c903290a09), + (0x007f8cdd8d1fcd8f5a32af8e1b3347ef4c8b41fb46c93eeac7895851009cc5da, 0x37b9278f063e6d6a578aa76657ff19dffd9d00d572711bfdfbfff13b16a6c6ce), + (0x20d64c097c7b989a44316bdc366ae83097832f00289736b772bea49c4e7b00e1, 0x3db86fbe002fea7ec1504b8c3a37781255f3990674df29c3df80b01c346599dc), + (0x3a80a8a3e35f9d6d83a547f054657216eea971085206d9a1fa1da905b4ebeff7, 0x18501e269b09e80f6465be2cdfdfea1140edda48656e7ea57f9134c1426a05bd), + (0x3aa059c2e0c14fe94e426dce09603ba37f6674a0643c3084822fd9c6f90a9208, 0x1512147967321b4ef9e690745a80b3f58a55706151c6661f112d84eed9e3f83c), + (0x00bccfb987b16c011682099a4600073bf54c652644cbf2e52c55654af4047592, 0x3a2ea83323de8bc350419de781b6ac0481845cf87d83430d29782e3d62d134d0), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 83ca7c0535ed0da94d2aca22e3f9553b7fad9eed..4dda7dc769a2a213c843fb2cb93181c282c89db1 100644 GIT binary patch literal 5283 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 literal 5251 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 J7OYxF0|4IM93B7w From 2810365f93442a80eedf25c550d25aab3689fccf Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 17 Oct 2023 10:11:00 +0200 Subject: [PATCH 48/92] Circuit: remove mutiplexer chip (#90) Remove the multiplexer chip from this repo (this chip has been moved into halo2 repo). --- src/circuit.rs | 7 +- src/circuit/gadget.rs | 9 +- src/circuit/gadget/mux_chip.rs | 344 --------------------------------- src/circuit/note_commit.rs | 18 +- 4 files changed, 19 insertions(+), 359 deletions(-) delete mode 100644 src/circuit/gadget/mux_chip.rs diff --git a/src/circuit.rs b/src/circuit.rs index 91a5fe13a..7c5ba1f18 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -28,7 +28,6 @@ use self::{ use crate::{ builder::SpendInfo, bundle::Flags, - circuit::gadget::mux_chip::{MuxChip, MuxConfig}, constants::{ OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, MERKLE_DEPTH_ORCHARD, @@ -59,7 +58,11 @@ use halo2_gadgets::{ MerklePath, }, }, - utilities::{bool_check, lookup_range_check::LookupRangeCheckConfig}, + utilities::{ + bool_check, + lookup_range_check::LookupRangeCheckConfig, + mux::{MuxChip, MuxConfig}, + }, }; mod commit_ivk; diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index 919b2c10b..fe0dc4cec 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -6,7 +6,6 @@ use pasta_curves::arithmetic::CurveExt; use pasta_curves::pallas; use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip}; -use crate::circuit::gadget::mux_chip::{MuxChip, MuxInstructions}; use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; use crate::note::AssetBase; use halo2_gadgets::{ @@ -16,6 +15,7 @@ use halo2_gadgets::{ Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, }, sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, + utilities::mux::{MuxChip, MuxInstructions}, }; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, @@ -23,7 +23,6 @@ use halo2_proofs::{ }; pub(in crate::circuit) mod add_chip; -pub(in crate::circuit) mod mux_chip; impl super::Config { pub(super) fn add_chip(&self) -> add_chip::AddChip { @@ -74,8 +73,8 @@ impl super::Config { NoteCommitChip::construct(self.old_note_commit_config.clone()) } - pub(super) fn mux_chip(&self) -> mux_chip::MuxChip { - mux_chip::MuxChip::construct(self.mux_config.clone()) + pub(super) fn mux_chip(&self) -> MuxChip { + MuxChip::construct(self.mux_config.clone()) } } @@ -224,7 +223,7 @@ pub(in crate::circuit) fn derive_nullifier< // Select the desired nullifier according to split_flag Ok(Point::from_inner( ecc_chip, - mux_chip.mux( + mux_chip.mux_on_points( layouter.namespace(|| "mux on nf"), &split_flag, nf.inner(), diff --git a/src/circuit/gadget/mux_chip.rs b/src/circuit/gadget/mux_chip.rs deleted file mode 100644 index fb81f8ea3..000000000 --- a/src/circuit/gadget/mux_chip.rs +++ /dev/null @@ -1,344 +0,0 @@ -use halo2_gadgets::ecc::chip::EccPoint; -use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{self, Advice, Column, ConstraintSystem, Constraints, Expression, Selector}, - poly::Rotation, -}; -use pasta_curves::pallas; - -#[derive(Clone, Debug)] -pub(in crate::circuit) struct MuxConfig { - choice: Column, - left: Column, - right: Column, - out: Column, - q_mux: Selector, -} - -/// A chip implementing a multiplexer on a single row. -/// -/// out = if (choice == 0) {left} else {right} -/// -/// `choice` must be constrained to {0, 1} separately. -#[derive(Clone, Debug)] -pub(in crate::circuit) struct MuxChip { - config: MuxConfig, -} - -impl Chip for MuxChip { - type Config = MuxConfig; - type Loaded = (); - - fn config(&self) -> &Self::Config { - &self.config - } - - fn loaded(&self) -> &Self::Loaded { - &() - } -} - -impl MuxChip { - pub(in crate::circuit) fn configure( - meta: &mut ConstraintSystem, - choice: Column, - left: Column, - right: Column, - out: Column, - ) -> MuxConfig { - let q_mux = meta.selector(); - meta.create_gate("Field element multiplexer", |meta| { - let q_mux = meta.query_selector(q_mux); - let choice = meta.query_advice(choice, Rotation::cur()); - let left = meta.query_advice(left, Rotation::cur()); - let right = meta.query_advice(right, Rotation::cur()); - let out = meta.query_advice(out, Rotation::cur()); - - let one = Expression::Constant(pallas::Base::one()); - - let should_be_zero = (one - choice.clone()) * left + choice * right - out; - - Constraints::with_selector(q_mux, Some(should_be_zero)) - }); - - MuxConfig { - choice, - left, - right, - out, - q_mux, - } - } - - pub(in crate::circuit) fn construct(config: MuxConfig) -> Self { - Self { config } - } -} - -/// An instruction set for multiplexing two points. -pub(crate) trait MuxInstructions { - /// Constraints `MUX(choice, left, right)` and returns the selected point. - fn mux( - &self, - layouter: impl Layouter, - choice: &AssignedCell, - left: &EccPoint, - right: &EccPoint, - ) -> Result; -} - -impl MuxInstructions for MuxChip { - fn mux( - &self, - mut layouter: impl Layouter, - choice: &AssignedCell, - left: &EccPoint, - right: &EccPoint, - ) -> Result { - let x_cell = layouter.assign_region( - || "mux x", - |mut region| { - self.config.q_mux.enable(&mut region, 0)?; - - choice.copy_advice(|| "copy choice", &mut region, self.config.choice, 0)?; - left.x() - .copy_advice(|| "copy left_x", &mut region, self.config.left, 0)?; - right - .x() - .copy_advice(|| "copy right_x", &mut region, self.config.right, 0)?; - - let out_val = (Value::known(pallas::Base::one()) - choice.value()) - * left.x().value() - + choice.value() * right.x().value(); - - region.assign_advice(|| "out x", self.config.out, 0, || out_val) - }, - )?; - let y_cell = layouter.assign_region( - || "mux y", - |mut region| { - self.config.q_mux.enable(&mut region, 0)?; - - choice.copy_advice(|| "copy choice", &mut region, self.config.choice, 0)?; - left.y() - .copy_advice(|| "copy left_y", &mut region, self.config.left, 0)?; - right - .y() - .copy_advice(|| "copy right_y", &mut region, self.config.right, 0)?; - - let out_val = (Value::known(pallas::Base::one()) - choice.value()) - * left.y().value() - + choice.value() * right.y().value(); - - region.assign_advice(|| "out y", self.config.out, 0, || out_val) - }, - )?; - - Ok(EccPoint::from_coordinates_unchecked( - x_cell.into(), - y_cell.into(), - )) - } -} - -#[cfg(test)] -mod tests { - use crate::circuit::gadget::mux_chip::{MuxChip, MuxConfig, MuxInstructions}; - - use crate::{circuit::gadget::assign_free_advice, circuit::K, constants::OrchardFixedBases}; - use halo2_gadgets::{ - ecc::{ - chip::{EccChip, EccConfig}, - Point, - }, - utilities::lookup_range_check::LookupRangeCheckConfig, - }; - - use group::{cofactor::CofactorCurveAffine, Curve, Group}; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, - }; - use pasta_curves::arithmetic::CurveAffine; - use pasta_curves::{pallas, EpAffine}; - - use rand::rngs::OsRng; - - #[test] - fn test_mux_chip() { - #[derive(Clone, Debug)] - pub struct MyConfig { - primary: Column, - advice: Column, - mux_config: MuxConfig, - ecc_config: EccConfig, - } - #[derive(Default)] - struct MyCircuit { - left_point: Value, - right_point: Value, - choice: Value, - } - - impl Circuit for MyCircuit { - type Config = MyConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - // Instance column used for public inputs - let primary = meta.instance_column(); - meta.enable_equality(primary); - - let mux_config = - MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); - - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - table_idx, - table_range_check_tag, - ); - - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); - - MyConfig { - primary, - advice: advices[0], - mux_config, - ecc_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Construct a MUX chip - let mux_chip = MuxChip::construct(config.mux_config); - - // Construct an ECC chip - let ecc_chip = EccChip::construct(config.ecc_config); - - // Assign left point - let left_point = Point::new( - ecc_chip.clone(), - layouter.namespace(|| "left point"), - self.left_point.map(|left_point| left_point), - )?; - - // Assign right point - let right_point = Point::new( - ecc_chip, - layouter.namespace(|| "right point"), - self.right_point.map(|right_point| right_point), - )?; - - // Assign choice - let choice = assign_free_advice( - layouter.namespace(|| "choice"), - config.advice, - self.choice, - )?; - - // Apply mux - let result = mux_chip.mux( - layouter.namespace(|| "MUX"), - &choice, - left_point.inner(), - right_point.inner(), - )?; - - // Check equality with instance - layouter.constrain_instance(result.x().cell(), config.primary, 0)?; - layouter.constrain_instance(result.y().cell(), config.primary, 1) - } - } - - // Test different circuits - let mut circuits = vec![]; - let mut instances = vec![]; - for choice in [false, true] { - let choice_value = if choice { - pallas::Base::one() - } else { - pallas::Base::zero() - }; - for left_point in [ - pallas::Point::identity().to_affine(), - pallas::Point::random(OsRng).to_affine(), - ] { - for right_point in [ - pallas::Point::identity().to_affine(), - pallas::Point::random(OsRng).to_affine(), - ] { - circuits.push(MyCircuit { - left_point: Value::known(left_point), - right_point: Value::known(right_point), - choice: Value::known(choice_value), - }); - let expected_output = if choice { right_point } else { left_point }; - let (expected_x, expected_y) = if bool::from(expected_output.is_identity()) { - (pallas::Base::zero(), pallas::Base::zero()) - } else { - let coords = expected_output.coordinates().unwrap(); - (*coords.x(), *coords.y()) - }; - instances.push([[expected_x, expected_y]]); - } - } - } - - for (circuit, instance) in circuits.iter().zip(instances.iter()) { - let prover = MockProver::::run( - K, - circuit, - instance.iter().map(|p| p.to_vec()).collect(), - ) - .unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } -} diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index c5c8f44e8..c41a61940 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -9,7 +9,6 @@ use halo2_proofs::{ use pasta_curves::pallas; use crate::{ - circuit::gadget::mux_chip::{MuxChip, MuxInstructions}, constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}, value::NoteValue, }; @@ -23,7 +22,10 @@ use halo2_gadgets::{ CommitDomain, Message, MessagePiece, }, utilities::{ - bool_check, lookup_range_check::LookupRangeCheckConfig, FieldValue, RangeConstrained, + bool_check, + lookup_range_check::LookupRangeCheckConfig, + mux::{MuxChip, MuxInstructions}, + FieldValue, RangeConstrained, }, }; @@ -1908,7 +1910,7 @@ pub(in crate::circuit) mod gadgets { // hash_point = hash_zsa if is_native_asset is false let hash_point = Point::from_inner( ecc_chip, - mux_chip.mux( + mux_chip.mux_on_points( layouter.namespace(|| "mux on hash point"), &is_native_asset, &(hash_point_zsa.inner().clone().into()), @@ -2297,10 +2299,7 @@ mod tests { use super::NoteCommitConfig; use crate::{ circuit::{ - gadget::{ - assign_free_advice, assign_is_native_asset, - mux_chip::{MuxChip, MuxConfig}, - }, + gadget::{assign_free_advice, assign_is_native_asset}, note_commit::{gadgets, NoteCommitChip}, }, constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_Q}, @@ -2313,7 +2312,10 @@ mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::chip::SinsemillaChip, - utilities::lookup_range_check::LookupRangeCheckConfig, + utilities::{ + lookup_range_check::LookupRangeCheckConfig, + mux::{MuxChip, MuxConfig}, + }, }; use ff::{Field, PrimeField}; From a680f410a4b52a5f6292faa7e7601f838c8682b5 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Wed, 18 Oct 2023 10:38:59 +0200 Subject: [PATCH 49/92] Circuit: optimize ZEC/ZSA hash computations in note commitment (#87) We optimized note_commitment evaluation by sharing a portion of the hash evaluation between ZEC and ZSA. 1. message_common_prefix = a || b || c || d || e || f || g 2. message_suffix_zec = h_zec 3. message_suffix_zsa = h_zsa || i || j 4. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} 5. common_hash = hash(Q, message_common_prefix) // this part is shared 6. hash_point_zec = hash(common_hash, message_suffix_zec) 7. hash_point_zsa = hash(common_hash, message_suffix_zsa) 8. hash_point = if (is_native_asset == 0) {hash_point_zsa} else {hash_point_zec} --- src/circuit/note_commit.rs | 117 +- src/circuit_description | 2976 +++++++++++++++++++++---------- src/circuit_proof_test_case.bin | Bin 5283 -> 5283 bytes 3 files changed, 2075 insertions(+), 1018 deletions(-) diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index c41a61940..857020c58 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -15,7 +15,7 @@ use crate::{ use halo2_gadgets::{ ecc::{ chip::{EccChip, NonIdentityEccPoint}, - Point, ScalarFixed, + NonIdentityPoint, Point, ScalarFixed, }, sinsemilla::{ chip::{SinsemillaChip, SinsemillaConfig}, @@ -1849,8 +1849,8 @@ pub(in crate::circuit) mod gadgets { // // https://p.z.cash/ZKS:action-cm-old-integrity?partial // https://p.z.cash/ZKS:action-cmx-new-integrity?partial - let (cm, zs) = { - let message_zec = Message::from_pieces( + let (cm, zs_common, zs_zsa_suffix) = { + let message_common_prefix = Message::from_pieces( chip.clone(), vec![ a.clone(), @@ -1860,26 +1860,24 @@ pub(in crate::circuit) mod gadgets { e.clone(), f.clone(), g.clone(), - h_zec.clone(), - ], - ); - - let message_zsa = Message::from_pieces( - chip.clone(), - vec![ - a.clone(), - b.clone(), - c.clone(), - d.clone(), - e.clone(), - f.clone(), - g.clone(), - h_zsa.clone(), - i.clone(), - j.clone(), ], ); + let message_suffix_zec = Message::from_pieces(chip.clone(), vec![h_zec.clone()]); + + let message_suffix_zsa = + Message::from_pieces(chip.clone(), vec![h_zsa.clone(), i.clone(), j.clone()]); + + // We will evaluate + // - `hash_point_zec = hash(Q_ZEC, message_common_prefix || message_suffix_zec)`, and + // - `hash_point_zsa = hash(Q_ZSA, message_common_prefix || message_suffix_zsa)`. + // by sharing a portion of the hash evaluation process between `hash_point_zec` and + // `hash_point_zsa`: + // 1. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} + // 2. common_hash = hash(Q, message_common_prefix) // this part is shared + // 3. hash_point_zec = hash(common_hash, message_suffix_zec) + // 4. hash_point_zsa = hash(common_hash, message_suffix_zsa) + // 5. hash_point = if (is_native_asset == 0) {hash_point_zsa} else {hash_point_zec} let zec_domain = CommitDomain::new( chip.clone(), ecc_chip.clone(), @@ -1888,22 +1886,53 @@ pub(in crate::circuit) mod gadgets { let zsa_domain = CommitDomain::new(chip, ecc_chip.clone(), &OrchardCommitDomains::NoteZsaCommit); - // We evaluate `hash_point_zec=hash(Q_ZEC, message_zec)` and `hash_point_zsa(Q_ZSA, message_zsa) - // and then perform a MUX to select the desired hash_point - // TODO: We can optimize the evaluation of hash_point by mutualizing a portion of the - // hash evaluation process between hash_point_zec and hash_point_zsa. - // 1. common_bits = a || b || c || d || e || f || g - // 2. suffix_zec = h_zec - // 3. suffix_zsa = h_zsa || i || j - // 4. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} - // 5. hash_prefix = hash(Q, common_bits) // this part is mutualized - // 6. hash_zec = hash(hash_prefix, suffix_zec) - // 7. hash_zsa = hash(hash_prefix, suffix_zsa) - // 8. hash_point = if (is_native_asset == 0) {hash_zsa} else {hash_zec} - let (hash_point_zec, _zs_zec) = - zec_domain.hash(layouter.namespace(|| "hash ZEC note"), message_zec)?; - let (hash_point_zsa, zs_zsa) = - zsa_domain.hash(layouter.namespace(|| "hash ZSA note"), message_zsa)?; + // Perform a MUX to select the desired initial Q point + // q_init = q_init_zec if is_native_asset is true + // q_init = q_init_zsa if is_native_asset is false + let q_init = { + let q_init_zec = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "q_init_zec"), + Value::known(zec_domain.q_init()), + )?; + + let q_init_zsa = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "q_init_zsa"), + Value::known(zsa_domain.q_init()), + )?; + + mux_chip.mux_on_non_identity_points( + layouter.namespace(|| "mux on hash point"), + &is_native_asset, + q_init_zsa.inner(), + q_init_zec.inner(), + )? + }; + + // common_hash = hash(q_init, message_common_prefix) + // + // To evaluate the different hash, we could use either zec_domain or zsa_domain + // because we use a private initial point. + let (common_hash, zs_common) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash common prefix note"), + &q_init, + message_common_prefix, + )?; + + // hash_point_zec = hash(common_hash, message_suffix_zec) = hash(q_init, message_zec) + let (hash_point_zec, _zs_zec) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash suffix ZEC note"), + common_hash.inner(), + message_suffix_zec, + )?; + + // hash_point_zsa = hash(common_hash, message_suffix_zsa) = hash(q_init, message_zsa) + let (hash_point_zsa, zs_zsa) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash suffix ZSA note"), + common_hash.inner(), + message_suffix_zsa, + )?; // Perform a MUX to select the desired hash point // hash_point = hash_zec if is_native_asset is true @@ -1925,19 +1954,19 @@ pub(in crate::circuit) mod gadgets { let commitment = hash_point.add(layouter.namespace(|| "M + [r] R"), &blinding_factor)?; - (commitment, zs_zsa) + (commitment, zs_common, zs_zsa) }; // `CommitDomain::hash` returns the running sum for each `MessagePiece`. Grab // the outputs that we will need for canonicity checks. - let z13_a = zs[0][13].clone(); - let z13_c = zs[2][13].clone(); - let z1_d = zs[3][1].clone(); - let z13_f = zs[5][13].clone(); - let z1_g = zs[6][1].clone(); + let z13_a = zs_common[0][13].clone(); + let z13_c = zs_common[2][13].clone(); + let z1_d = zs_common[3][1].clone(); + let z13_f = zs_common[5][13].clone(); + let z1_g = zs_common[6][1].clone(); let g_2 = z1_g.clone(); - let z13_g = zs[6][13].clone(); - let z13_i = zs[8][13].clone(); + let z13_g = zs_common[6][13].clone(); + let z13_i = zs_zsa_suffix[1][13].clone(); // Witness and constrain the bounds we need to ensure canonicity. let (a_prime, z13_a_prime) = canon_bitshift_130( diff --git a/src/circuit_description b/src/circuit_description index 19578d04b..903fb3017 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -10,7 +10,7 @@ PinnedVerificationKey { num_fixed_columns: 33, num_advice_columns: 10, num_instance_columns: 1, - num_selectors: 61, + num_selectors: 63, gates: [ Product( Product( @@ -13832,6 +13832,144 @@ PinnedVerificationKey { ), ), ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Advice { + query_index: 22, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), Product( Fixed { query_index: 19, @@ -14211,7 +14349,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -14320,7 +14458,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -14429,7 +14567,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -14470,21 +14608,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14494,12 +14664,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14509,12 +14679,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14559,21 +14729,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14583,12 +14785,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14598,12 +14800,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14672,21 +14874,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14696,12 +14930,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14711,12 +14945,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14759,21 +14993,53 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14783,12 +15049,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -14798,12 +15064,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 27, - column_index: 27, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15013,72 +15279,41 @@ PinnedVerificationKey { ), ), Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - Sum( + Product( Product( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Sum( - Sum( - Advice { - query_index: 15, - column_index: 5, - rotation: Rotation( - 1, - ), - }, - Sum( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, Sum( - Product( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Advice { - query_index: 5, - column_index: 5, + Fixed { + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), }, ), ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), Negated( - Advice { - query_index: 6, - column_index: 6, + Fixed { + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15086,9 +15321,44 @@ PinnedVerificationKey { ), ), ), - Advice { - query_index: 5, - column_index: 5, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15096,7 +15366,173 @@ PinnedVerificationKey { ), ), ), - ), + Sum( + Scaled( + Advice { + query_index: 21, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), Product( Fixed { query_index: 20, @@ -15355,8 +15791,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15367,8 +15803,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15382,8 +15818,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15397,8 +15833,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15412,8 +15848,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15427,8 +15863,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15496,8 +15932,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15508,8 +15944,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15523,8 +15959,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15538,8 +15974,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15553,8 +15989,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15568,8 +16004,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15637,8 +16073,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15649,8 +16085,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15664,8 +16100,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15679,8 +16115,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15694,8 +16130,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15709,8 +16145,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -15787,7 +16223,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -15908,7 +16344,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16053,7 +16489,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16172,7 +16608,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -16306,7 +16742,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16418,7 +16854,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16530,7 +16966,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16661,7 +17097,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16780,7 +17216,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16911,7 +17347,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17054,7 +17490,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17159,7 +17595,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17264,7 +17700,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17383,7 +17819,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17488,7 +17924,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17593,7 +18029,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17698,7 +18134,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17829,7 +18265,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -17949,7 +18385,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18061,7 +18497,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18173,7 +18609,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18248,8 +18684,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18260,8 +18696,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18275,8 +18711,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18286,12 +18722,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18301,12 +18737,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18316,12 +18752,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18360,8 +18796,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18372,8 +18808,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18387,8 +18823,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18398,12 +18834,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18413,12 +18849,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18428,12 +18864,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18472,8 +18908,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18484,8 +18920,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18499,8 +18935,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18510,12 +18946,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18525,12 +18961,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18540,12 +18976,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -18638,7 +19074,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -18653,7 +19089,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18772,7 +19208,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18787,7 +19223,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -18884,7 +19320,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -18899,7 +19335,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19030,7 +19466,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19045,7 +19481,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19142,7 +19578,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19157,7 +19593,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19261,7 +19697,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19276,7 +19712,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19338,21 +19774,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19362,12 +19814,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19377,12 +19829,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19392,12 +19844,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19407,12 +19859,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19450,21 +19902,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19474,12 +19942,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19489,12 +19957,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19504,12 +19972,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19519,12 +19987,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19562,21 +20030,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19586,12 +20070,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19601,12 +20085,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19616,12 +20100,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19631,12 +20115,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19681,21 +20165,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19705,12 +20205,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19720,12 +20220,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19735,12 +20235,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19750,12 +20250,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19812,21 +20312,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19836,12 +20352,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19851,12 +20367,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19866,12 +20382,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19881,12 +20397,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19931,21 +20447,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19955,12 +20487,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19970,12 +20502,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -19985,12 +20517,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20000,12 +20532,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20036,36 +20568,52 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20075,12 +20623,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20090,12 +20638,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20105,12 +20653,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20141,21 +20689,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 29, - column_index: 29, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 30, + column_index: 30, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20165,12 +20729,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20180,12 +20744,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20195,12 +20759,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20210,12 +20774,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -20256,7 +20820,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20271,7 +20835,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20403,7 +20967,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20418,7 +20982,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20550,7 +21114,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20565,7 +21129,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20671,7 +21235,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -20686,7 +21250,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20807,7 +21371,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20822,7 +21386,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20969,7 +21533,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20984,7 +21548,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21116,7 +21680,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21131,7 +21695,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21263,7 +21827,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21278,7 +21842,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21384,7 +21948,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21399,7 +21963,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21520,7 +22084,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21535,7 +22099,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21679,7 +22243,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21694,7 +22258,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21826,7 +22390,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21841,7 +22405,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21947,7 +22511,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21962,7 +22526,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22068,7 +22632,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -22083,7 +22647,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22204,7 +22768,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22219,7 +22783,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22332,7 +22896,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22347,7 +22911,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22479,7 +23043,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22494,7 +23058,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22626,7 +23190,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22641,7 +23205,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22761,7 +23325,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22776,7 +23340,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22882,7 +23446,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22897,7 +23461,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23003,7 +23567,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -23018,7 +23582,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23056,20 +23620,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23079,12 +23643,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23094,12 +23658,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23109,12 +23673,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23124,12 +23688,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23143,8 +23707,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23184,20 +23748,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23207,12 +23771,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23222,12 +23786,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23237,12 +23801,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23252,12 +23816,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23271,8 +23835,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23312,20 +23876,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23335,12 +23899,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23350,12 +23914,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23365,12 +23929,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23380,12 +23944,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23399,8 +23963,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23471,8 +24035,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23483,8 +24047,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23494,12 +24058,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23509,12 +24073,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23524,12 +24088,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23539,12 +24103,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23554,12 +24118,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23599,8 +24163,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23611,8 +24175,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23622,12 +24186,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23637,12 +24201,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23652,12 +24216,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23667,12 +24231,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23682,12 +24246,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23727,8 +24291,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23739,8 +24303,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23750,12 +24314,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23765,12 +24329,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23780,12 +24344,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23795,12 +24359,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23810,12 +24374,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -23894,7 +24458,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -23909,7 +24473,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24044,7 +24608,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24059,7 +24623,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24172,7 +24736,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24187,7 +24751,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24334,7 +24898,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24349,7 +24913,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24462,7 +25026,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24477,7 +25041,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24597,7 +25161,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24612,7 +25176,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24759,7 +25323,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24774,7 +25338,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -24887,7 +25451,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24902,7 +25466,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25015,7 +25579,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -25030,7 +25594,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25165,7 +25729,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25180,7 +25744,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25312,7 +25876,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25327,7 +25891,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25447,7 +26011,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25462,7 +26026,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25568,7 +26132,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25583,7 +26147,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25689,7 +26253,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25704,7 +26268,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25740,37 +26304,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25784,8 +26332,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25799,8 +26347,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25814,8 +26362,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25825,12 +26373,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25887,37 +26435,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25931,8 +26463,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25946,8 +26478,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25961,8 +26493,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -25972,12 +26504,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26034,37 +26566,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26078,8 +26594,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26093,8 +26609,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26108,8 +26624,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26119,12 +26635,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26155,37 +26671,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26199,8 +26699,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26214,8 +26714,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26229,8 +26729,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26240,12 +26740,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26276,37 +26776,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 31, - column_index: 31, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26320,8 +26804,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26335,8 +26819,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26350,8 +26834,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26365,8 +26849,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), @@ -26421,16 +26905,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -26445,7 +26961,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -26460,7 +26976,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26520,16 +27036,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -26544,7 +27092,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -26559,7 +27107,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26619,16 +27167,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -26643,7 +27223,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -26658,7 +27238,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26692,16 +27272,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -26716,7 +27328,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -26731,7 +27343,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26765,16 +27377,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26789,7 +27433,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -26804,7 +27448,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26876,16 +27520,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26900,7 +27576,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -26915,7 +27591,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26975,16 +27651,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26999,7 +27707,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -27014,7 +27722,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27048,16 +27756,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27072,7 +27812,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -27087,7 +27827,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27121,16 +27861,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27145,7 +27917,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -27160,7 +27932,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27194,16 +27966,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27218,7 +28022,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27233,7 +28037,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27274,16 +28078,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27298,7 +28134,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27313,7 +28149,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27362,27 +28198,59 @@ PinnedVerificationKey { rotation: Rotation( 1, ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000400, - ), - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27397,7 +28265,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27412,7 +28280,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27472,16 +28340,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27496,7 +28396,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27511,7 +28411,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27559,16 +28459,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27583,7 +28515,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27598,7 +28530,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27632,16 +28564,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27656,7 +28620,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27671,7 +28635,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27705,16 +28669,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27729,7 +28725,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27744,7 +28740,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -27778,16 +28774,48 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), ), - }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27802,7 +28830,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27817,7 +28845,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -29282,50 +30310,50 @@ PinnedVerificationKey { (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), - (0x02656490d7b8420bfe91e220b7d95ff7e79bca851ec0d26cb2221772c25e8638, 0x0ee047851a6b3d0038ff02a38782e8d349febf23035d21227fb95693083eb710), - (0x1dd2f90c7130eabb75c1f83620474ecd7565c6751cac21e6b3400e2554cb30ae, 0x0135321193a6f63fd7bdcbe4ec21c79cf2705deb072779586e4eafdbd52cc0eb), - (0x29a5048146830326a4c86c7959158cb88e6be880e1980adaa3d4bbdc1e4aae22, 0x2b1c22a72f40fc3196890c6e8723a9df96a73c0d81c83c015af087f920da8465), - (0x0087eb927dee14807ad837123f7ed3e34accaa3739d3e6172467acc8671c2653, 0x351df64e5f2b6956c800cc9c5e3a0e875b6f700be165bc478b53caf05776f9e0), - (0x319b61505610a63e57bbc53df58f1086f5840a826163fd5ca22b8d4a3238abbe, 0x232fe2570f8b5df28088f667ca920fe603329464a3a9dcfdbc78497aee19193e), - (0x3dfff1fb77235cfc3c9b39b7c4f99b5df4e89e957155385507a4ea91750069a2, 0x0a60bb0d445d0cf8fa75d1625b6ad86944d150c6679f00e78016829bf47ffa12), - (0x37bdb76a767d836c13381bf59417e256c1b326df542851d623617f2a45c59992, 0x09509cfe95dca7401708bab0ce45a126bac7fc5051b1c45f119e54a4e5fd881d), - (0x2d482cf0c1c13d6d2afe85feac3f565d054238acc10b7ff78dc08cb9aea3a5ab, 0x2f7182906fc5aa8952982e96ae29891fc988d468623244e02ea8453b5b3c65f8), - (0x184b191b2c11511c81ace6f3a56f833c5b6465a7a394dad84226588b7750969b, 0x0d200f2a66888760d60a9e117a85d826abe27a0f7cf6211b2ddf843475667618), - (0x04fae4e51e99d50ff8a55a449c0234a9a613e996a9b202db18ef01e7ad42b052, 0x1d083ab8f2c454ea5e1f9cf81a419a4a55347136c4feff75ec8a0a19f909d558), - (0x12d6a260a08c59e9df032cd6c855f081d99321fe2f33d33508b4180411f0dadc, 0x31fbd5ce92f6cd283658690e93a0bcbb515b1aa9728024f5eb583f5f27da6a11), - (0x3aaa1190000787a9cc4008d68adf7a91b48ff5470fdfb3d3ee36f64df7cfd045, 0x2f1723e3595adf0106d4fe2f11af025978f616b6697036c27ebbd682a013928e), - (0x1bbe9643cceac1b79ea642312b57cf5b7739a2accb6641c7c902a0651f8c90b2, 0x3a7c2a5db44cd0fa31f5a26206fc3ea8e81fea14ddbcdab3204dbcd840a14184), - (0x39a9e0b36cd0cf9445f6533d02ea7187f1d8100085a6228509c8af4743f2eb24, 0x311a439a351fdadfaced9213ff8bcadca7a03d1bc18d9f4bb33ea1806bc2c6be), - (0x0957fb68f275d18d730f9c106de4b4cfd966b3eeb0434b1ea66ddfda2420a8ad, 0x1ae46e6b003224d3f30eb366fc3d9db07d07ded1c474d239602aed8ac859e895), - (0x3d5fc48944b2527964ab562447e540f7512a225c2468ba76398dbd6842bcd776, 0x22ca98fd09c21884a128d63511bcd366d7fa61d7b21271e0c0927b4677c7242f), - (0x03be84ba69d6def665955d6dc72a6f647cb206de2fc5cc6d0e1474354bb03f3e, 0x1eabb979cab6e3e9a82d7b692d18e9757b684f1b855845db1ed8925f3b9ad918), - (0x0c1fbfb10301c163416949dff37b9334f8c62372f154386e40882b4327d0cf98, 0x19f48dbe5b56cb8711943bed857307de739099a1cb78c12a1015770f8553c601), - (0x2096a01846851be44913d49936d7362716c296970aeba41f35b23946cc1fa41c, 0x3af057b14acc535df8dc9f159a1290d92b8fa875b1982d669b0df5a4429f59e6), + (0x3fb934de80a76b78bb5daf3fb368ebcefabc5b6b9ebae5cddc1e39c82b122b48, 0x130a034bee7622c60e8a53f70216e48696f5d9457aade41f0ef09166091c66e7), + (0x19e589077358b9abcb3e21a71537113cf43c43aea7e300fdfb755bb29449a5b6, 0x1da596141c740b648dabc4961ed014ed0dd8dfcc03b2d02cf6ff9e8a3ff0e42e), + (0x1af56c46ba6aaab50db1acd46003c05c3fee103776681f61100b1b6aef07c284, 0x38eea07b7f5881eff963d114e50084bb5bf5cf359f023fc855f3a01b0ca1e432), + (0x0cfb7c9b0bfcf398a53c13d6e1068989805f1cf254dddcaa4ab57da05ad0616e, 0x37fcd5b873385ee44169fe3870a9feeadbf64c21fa2c4b130f718e47f29ff8dc), + (0x03c0cdbe7ea6296a9eb724d225d0adf451999dd9686aaa5659e23102b5daec07, 0x1ec2e8d39dd47c991a31f9476467800bf49655e7293efc4e5261b7ffb15af542), + (0x1314cd9c9d35b73165e86972dc6007ec35aab9ef8f6358cc090043cf68c4c2f5, 0x3d9e921baede6846e7fd2f0805deec1da2395e7d3f647ef8f6e5ecdb456c22c3), + (0x3e3c175e12e425f9f5b499541aba80122e8c346ab329e8d2400debb7a4298473, 0x3621561ea96a7834b55250be2bc137fffa02705ca49848c61955417883a289c1), + (0x0491089f80b3aa79defa2923388ba287c07ff7b5d805932133b249b674c69dcb, 0x2463e5cde6ef2b91fbd72d8d1511556bf6d9ec460f19b890544bc6886906741c), + (0x2b8e5f9c2efdb6cca222b066bd10be6c1ec15951b5f22f11e7bdad199936d91e, 0x2579a5ebe80abe31205c73ebfe4012559a9c00f9ed2a7303c08420dd46ecccc8), + (0x06abaaea1008f82ba485632d1e6d130e8bd9baf450cee1210b5780fae7df1012, 0x0b21835ef9aed7d7b1a0dc9b2af53fab3a6c4f1a8a3568c2570d06ba392a73a1), + (0x1f18cb4d7fc46f1fe4aecbaf07fae7d29a0cb49317f60c17161837443e2f32a0, 0x3827b12472ab9f40d713702752e542832f8e812ca73b14e975b42ab7c56f10b9), + (0x1880c0651fead5ccae365349f9158252d6846f24f3d4c1fa9c190ee0b9020f3f, 0x05fb1b7ad97f29412f5a50cd0369f7c2a4cc07f98e2e4ddc0b677a97ac3617a6), + (0x18b67544d4466429760be2b231418b43d35d79462f8743051c8e437dd710035d, 0x2ca31a6106310316da5633fe4e16e2a0affafc4541b280a9722ae86219127aa0), + (0x0477cc6f6292f9d3dcbcdb6b896dbc2b76b8716db8d80f36af610738a89e58e0, 0x0fb4d1d92e0606c83e4d1359ad9e607a936339871c9c606cc9218225c8a762d4), + (0x027f5c9006d53a989091caa780c6b4ec009e328d03836f95ee05bfb2178ba931, 0x2c7612c86a27585617aa8b0202e638d57b079417ca8722a4f47c3c12892cbea9), + (0x1b9d2736bed08950ac569b6bc5d2a8bdd48cec8a206030c306f665af83c4df12, 0x2b8e0e07c521db751c386d011504b5f4c8fd2b09ace077e54f05bd0fbe0a2def), + (0x3d7f0951711965e07ab0e4c1451361e5b536793dcf76176e4e854285a7bdabba, 0x13780fb58b9b717ebd2040e8d79be7bc7f32c5d9b31b0766c6eea63ccc6c6ff1), + (0x2ebee709b368779cf6bc2bec772f19fee25938985b94fef3a86c9950adcc9ae0, 0x18af23ba308d2e8a6d9bf544def217546a8e9816192ce2c29841379a935b74ff), + (0x2a9ef8f91987bd8f2f6101abfc05caf7e30c7d79faba1022d547a00b04333f7c, 0x153a1907977cf09f557085c0f256b877f72567b3a2f92179e33d468fbfc8b10a), (0x334105dd96996a08df56e88261dcd87c5356cfc0f2b8ae0a9419899d5def147b, 0x09ddf24ae765eda056cf59b16ac14464240c83e253135682c02e6546f89dd396), - (0x0aa9bf3b3cae0bbeb70f32d96a43603853872c28ef246db1bb85c885e112b4c1, 0x0718dce6ad248d2cedc43f3a23ec6d4d7dd305cb6f8fc9a3098a11acf42b5967), - (0x06fe6f3926a9de1432ebf4934fef695942a41eaea45a2c42d6af795af6dd1f7b, 0x30342fc0dc2cdec7fdf1aab0eb28f7ca21b4dd478c596540444c0932d8dd56dc), - (0x12fb328eaf326033eb7376c6aa6aff345bbb300b7e5fab858feec8cd3e4bdf58, 0x28bdf84118d334220e557ae9959a091ceb54c36d4a6d1f8a1518948d8a8124c5), - (0x0558514fa4d8feae12519efa8c79b7e7fe327642f28455ae300cffdc21cf5a22, 0x22c8f7ede18bcf4083f7cb6bf94b1de06305107537bcc31027dd400a7455dded), - (0x0aa54dc82361b7d6f35e36d55290ede3e4962e85665475fb15e51b626c849f7f, 0x16927eaf3dcbd28a8e1eb1a19235a512da8858d10040d3b26425ec054ce0eb3a), - (0x39c1526f64989d617bd43b64427f26c5068485b3d635bbb746b6be5ebf8361c8, 0x398ab66905a4e1e36fc3e2da5d1b1e918bda970ad17d46cd08b852e51879ca6a), - (0x3aa89e6834df650fcbdc0a295b03a58002cdcd14198f8af3069eb222d2d17c66, 0x067ec4c41d0352ea32b5872af2b051c78882157d0ae87486dce3c4c2c29877f9), - (0x1394764de03aaa28c9a9d2b91798a25629d0412264057ef247c6faf21e4354e3, 0x1de01702d1d58eff7824e40712beb1429a101c1ed844fcaa7100519f85faffd7), - (0x261a83f8122eb036760791a4e9d52235df4939fdf8175f8d240a333e06557e7e, 0x184fb28734999d991d4bb862d1e47e3ae20336706f82ceb180609fa68fd85501), + (0x2dac89c801000721a4422cb8bb1def97cd3bfce7c64ac6327e335b3c0071a049, 0x2e2575abf15aa7424617ae9c7c9749c67c38a3e68082c4f937e4dbcff98b4dfc), + (0x0b89c282c8f2d54e66c7a11e6b4338a2f06a7c9430f7d3376328f12fa001cac5, 0x098b5c8ee6548183ccb4e60cdfee10b509db34ed136daf3530a426e8f200e89d), + (0x2f7f85b86b6adcf714d0df7878f4604d33fd319f39bd00fd5c34378247a155b5, 0x3a2f025447b83b65d148e99c93fe8bb991a81ef6d2f827f010680467361c47fc), + (0x121fe2a31c21b4d21266dde870a72ca2e96ea0fd80ca2ca59436c8cad25ae150, 0x0d2aff2c6e65712a354da894209b75ff8479cb958ab050156f63f3760b8a05ca), + (0x14815e90ec334c51da36b50c69b8f192f1cfd63fcd3257c7a16691b7be2a1759, 0x0711e90858dbade5aac1c82b1000a59e2beccfd84db4e212368b1a5b5a8ecf3a), + (0x3bd7f461093bd6b774837199b58d3d6741f80ce738345b18800adf8fedf37286, 0x3f9162dc512623e1c62b2360fb6db7400f9c545b2028af0f4580d308fd44818c), + (0x1f64379a921e197082d9e2afe9baa825f2af8fa02bbfa653772604bf22125eaa, 0x348d5a1de410f8c0ec8f9fe4514709c6cbc0882dc8d6ec0f8562f05c535ab2a9), + (0x12e6bba88452419d3d1632edf16b02a63a5ac81241118845ea41ed70111f1f83, 0x3f0899ae3f41bea051afee8df4dddb13d78857773df79d2e6eeae02b0c8f423d), + (0x0f59f5bdf3fbc2551cff44f3444bdb84ca5956aa0ec424cb8d8318abc12370d8, 0x219d1021cfd377e3ea006ed15485437702218e0cc6e76975025f7632bd66d072), ], permutation: VerifyingKey { commitments: [ - (0x286d1f6ab2fb58b3ba974d1807c606914deea07b64615089452f1feaa06ef0db, 0x08bb42474059164d528fb06f0b80b08b3ebdc87cbe0c2718d0c6199984b2119d), - (0x31fd9e62ffdd86ec55a2ead7a4b74dd21ddcf56029dc5d334491bffc7bd2ffb3, 0x2f990b235ee3f35e09a77f1414d21fab06cc60fe8fe6f52407d7599204632cd4), - (0x2044e502b5716abe00c9dde5348392b4fc489b5097aca8f5401a5153820903dd, 0x155aa6b3f9ea3e01f25eca37b0a62d28fe24a1a96d033c074e6cb22b08d118d5), - (0x36599df2c3de06015c3167fe0b2b22aab1ae9587ff050977193d5d753c8be6a8, 0x32b02df0138a92f3b23556ad96f9ef9bee0c34c8900cb4ecaadf3252ae4e0edc), - (0x13631970b4bae5c49d31638a2af724495c8b2074bd015f3c1c06af24956ca995, 0x1b7e3517b6db255c9b71753707de5d6fb33f83825ad8416db482669daac81ba3), - (0x021eb6e340ea808444c833c25e326c03223ea3fb458771e814a7d9130eddeb74, 0x230be5c1f0b81145d7a45c032c4dbc68e53db1fbda374a0f0d2e0da702032b2f), - (0x18720c0f1f48ad21f6e1d0d33adc569ac901c68cdcb16d5398ac986b421f7038, 0x11cf59a013ad87f91ce8567087a80ee9395af8fc1383ac10e490d9c903290a09), - (0x007f8cdd8d1fcd8f5a32af8e1b3347ef4c8b41fb46c93eeac7895851009cc5da, 0x37b9278f063e6d6a578aa76657ff19dffd9d00d572711bfdfbfff13b16a6c6ce), - (0x20d64c097c7b989a44316bdc366ae83097832f00289736b772bea49c4e7b00e1, 0x3db86fbe002fea7ec1504b8c3a37781255f3990674df29c3df80b01c346599dc), - (0x3a80a8a3e35f9d6d83a547f054657216eea971085206d9a1fa1da905b4ebeff7, 0x18501e269b09e80f6465be2cdfdfea1140edda48656e7ea57f9134c1426a05bd), - (0x3aa059c2e0c14fe94e426dce09603ba37f6674a0643c3084822fd9c6f90a9208, 0x1512147967321b4ef9e690745a80b3f58a55706151c6661f112d84eed9e3f83c), - (0x00bccfb987b16c011682099a4600073bf54c652644cbf2e52c55654af4047592, 0x3a2ea83323de8bc350419de781b6ac0481845cf87d83430d29782e3d62d134d0), + (0x05625166f1bf876dd59af0e45b068df3dc22e28accb12418d5111fc12b563d4a, 0x102be9e1b4fe8a6d8c00ffbf6513e8410b9a940a7b559914fdeb45a2b170cdb3), + (0x2319a6b8fdaca310c4042b98fe068ce93913270e534c3d88029fc5f8ba6ab3d9, 0x1a4374fb532ec3d030217dc66c6e0db4ac456bee8641cfe049190973c8b5c72f), + (0x0765958f562227c7838c73baba821f9c2f40868c58654dcf675b718feef1a01e, 0x378fb34b8ab337872d942b99123219ffe532124adc9cd3c31437aa6a5becd763), + (0x1df175a3908c91e4d9c1e4fd6e8f30d3fde110f9dc379eec7db39ceaa53f2ad6, 0x3b419848016ad53c7aaa29602b85580c499016ceb49ccf8496f7e9b3f413d4df), + (0x171cad3d3e6e7a153ff12d86ee56a01505acc1ee38fb9a11b68abfa5ad1a1e46, 0x37343f7a56d7e180ddd2ae2ca4301d5128becaec07cafcad1b7d3610e49f453d), + (0x207970fdc943d5b65689b132d27fdc46ed25c8d84042acf0e855c8bb00a60f2b, 0x364ad7be4b0b40da9d5df01c50967ee14cabc8bd669872613c1d62ad1f52f38b), + (0x19a1a3391e950797dbb98811f2ba3b4622147959449f9cb1c7f454aa047afe76, 0x079ae13ad5b0083006b06de42808f517d9797e5f42fc87a9947c761fa8784fea), + (0x08035a60101d47769ed0a30ce647c0e5d5c7850f1630247af48f351c7ac5b6e7, 0x3b0c43b451b947f7adbffa12d9e4c7ca94ac5c12eda34cee77b640f25a42d04b), + (0x116e9d6aef40f13742fb573a0779c99f5a12f59fab1246d64a55d94e3856800c, 0x0d595f9d79e749dbd9d69ca28b15f80a17b5312be520568e1f959f1b958bf1aa), + (0x3bf0f0b99e15ad38e2d9d5a9e12aa428f55db0cb878e058ea592eee7d16edfb4, 0x32a0e3bb91ab0ee8f25ab4d8f93782724cd68675e823e66369f0c6a36ece62d8), + (0x2cdb9602b74f420b08e5307df902d13340d3b1b53d081b110149e01d731dd862, 0x0b7b5bbb0b5b19148a410ce3c2625364660d100aad28542e75282ff7cc5926a7), + (0x20dc0d54e1617ea5a6251e447e06e8a98030d79b426bbe946fe960f85550efa8, 0x25f833bd3ee582088cf25891465c3908192d77eca169f8c7d3d373fd12c2fade), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 4dda7dc769a2a213c843fb2cb93181c282c89db1..97e15d58205d44afb2165e5137b7b4e81b843d4d 100644 GIT binary patch literal 5283 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 literal 5283 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 From 7b943e197e0bd227f86405bdd2fbfa9d51ba0035 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 1 Nov 2023 10:37:43 +0100 Subject: [PATCH 50/92] Adopt Orchard ZSA for Zebra (introduce zcash_note_encryption_zsa alias, minor enhancements) (#89) This Pull Request introduces the `zcash_note_encryption_zsa` alias, ensuring compatibility with the Zebra project. This alias is used to prevent conflicts with the original `zcash_note_encryption` crate, which is also used in Zebra through the original `orchard` crate that is used in parallel with our `orchard` (Orchard ZSA) crate. Additionally, this PR includes minor enhancements to ensure compatibility with the Zebra project. --------- Co-authored-by: Dmitry Demin --- Cargo.toml | 7 ++----- benches/note_decryption.rs | 2 +- src/builder.rs | 2 +- src/bundle.rs | 2 +- src/issuance.rs | 6 +++--- src/keys.rs | 2 +- src/note_encryption.rs | 6 +++--- src/note_encryption_v2v3.rs | 9 ++++----- src/note_encryption_v3.rs | 6 +++--- src/primitives/redpallas.rs | 2 +- tests/builder.rs | 2 +- tests/zsa.rs | 2 +- 12 files changed, 22 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1ed0fb0f7..69165bdfc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ reddsa = "0.5" nonempty = "0.7" serde = { version = "1.0", features = ["derive"] } subtle = "2.3" -zcash_note_encryption = "0.4" +zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/librustzcash", branch = "zsa1-zebra" } incrementalmerkletree = "0.5" # Logging @@ -57,7 +57,7 @@ criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" -zcash_note_encryption = { version = "0.4", features = ["pre-zip-212"] } +zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/librustzcash", branch = "zsa1-zebra", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } [target.'cfg(unix)'.dev-dependencies] @@ -91,6 +91,3 @@ debug = true [profile.bench] debug = true - -[patch.crates-io] -zcash_note_encryption = { version = "0.4", git = "https://github.com/QED-it/librustzcash.git", branch = "zsa1-zebra" } diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index ce051cf03..ba0f62112 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -10,7 +10,7 @@ use orchard::{ Anchor, Bundle, }; use rand::rngs::OsRng; -use zcash_note_encryption::{batch, try_compact_note_decryption, try_note_decryption}; +use zcash_note_encryption_zsa::{batch, try_compact_note_decryption, try_note_decryption}; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; diff --git a/src/builder.rs b/src/builder.rs index fe3857904..5e51162e5 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -337,7 +337,7 @@ impl Builder { /// Adds a note to be spent in this transaction. /// /// - `note` is a spendable note, obtained by trial-decrypting an [`Action`] using the - /// [`zcash_note_encryption`] crate instantiated with [`OrchardDomain`]. + /// [`zcash_note_encryption_zsa`] crate instantiated with [`OrchardDomain`]. /// - `merkle_path` can be obtained using the [`incrementalmerkletree`] crate /// instantiated with [`MerkleHashOrchard`]. /// diff --git a/src/bundle.rs b/src/bundle.rs index a8e429a7c..f37011754 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -11,7 +11,7 @@ use core::fmt; use blake2b_simd::Hash as Blake2bHash; use memuse::DynamicUsage; use nonempty::NonEmpty; -use zcash_note_encryption::{try_note_decryption, try_output_recovery_with_ovk}; +use zcash_note_encryption_zsa::{try_note_decryption, try_output_recovery_with_ovk}; use crate::note::AssetBase; use crate::{ diff --git a/src/issuance.rs b/src/issuance.rs index 29a95fda3..8b5f200a4 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -26,7 +26,7 @@ use crate::{ use crate::supply_info::{AssetSupply, SupplyInfo}; /// A bundle of actions to be applied to the ledger. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct IssueBundle { /// The issuer key for the note being created. ik: IssuanceValidatingKey, @@ -39,7 +39,7 @@ pub struct IssueBundle { /// An issue action applied to the global ledger. /// /// Externally, this creates new zsa notes (adding a commitment to the global ledger). -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct IssueAction { /// Asset description for verification. asset_desc: String, @@ -181,7 +181,7 @@ pub struct Prepared { } /// Marker for an authorized bundle. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Signed { signature: redpallas::Signature, } diff --git a/src/keys.rs b/src/keys.rs index 7853d4920..4c6014f20 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -14,7 +14,7 @@ use group::{ use pasta_curves::{pallas, pallas::Scalar}; use rand::{CryptoRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; -use zcash_note_encryption::EphemeralKeyBytes; +use zcash_note_encryption_zsa::EphemeralKeyBytes; use crate::{ address::Address, diff --git a/src/note_encryption.rs b/src/note_encryption.rs index ca1b66013..6063f9c49 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -3,7 +3,7 @@ use blake2b_simd::{Hash, Params}; use group::ff::PrimeField; use std::fmt; -use zcash_note_encryption::{ +use zcash_note_encryption_zsa::{ BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; @@ -350,7 +350,7 @@ impl BatchDomain for OrchardDomainV2 { } /// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; +pub type OrchardNoteEncryption = zcash_note_encryption_zsa::NoteEncryption; impl ShieldedOutput for Action { fn ephemeral_key(&self) -> EphemeralKeyBytes { @@ -450,7 +450,7 @@ impl CompactAction { mod tests { use proptest::proptest; use rand::rngs::OsRng; - use zcash_note_encryption::{ + use zcash_note_encryption_zsa::{ try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; diff --git a/src/note_encryption_v2v3.rs b/src/note_encryption_v2v3.rs index 5d3eedf25..107184ab8 100644 --- a/src/note_encryption_v2v3.rs +++ b/src/note_encryption_v2v3.rs @@ -3,7 +3,7 @@ use blake2b_simd::{Hash, Params}; use core::fmt; use group::ff::PrimeField; -use zcash_note_encryption::{ +use zcash_note_encryption_zsa::{ BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; @@ -440,9 +440,8 @@ impl BatchDomain for OrchardDomain { } } - /// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; +pub type OrchardNoteEncryption = zcash_note_encryption_zsa::NoteEncryption; impl ShieldedOutput for Action { fn ephemeral_key(&self) -> EphemeralKeyBytes { @@ -548,7 +547,7 @@ impl CompactAction { mod tests { use proptest::prelude::*; use rand::rngs::OsRng; - use zcash_note_encryption::{ + use zcash_note_encryption_zsa::{ try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; @@ -571,7 +570,7 @@ mod tests { Address, Note, }; - use super::{version, orchard_parse_note_plaintext_without_memo}; + use super::{orchard_parse_note_plaintext_without_memo, version}; proptest! { #[test] diff --git a/src/note_encryption_v3.rs b/src/note_encryption_v3.rs index 7594b588d..ceff0cbe2 100644 --- a/src/note_encryption_v3.rs +++ b/src/note_encryption_v3.rs @@ -3,7 +3,7 @@ use blake2b_simd::{Hash, Params}; use core::fmt; use group::ff::PrimeField; -use zcash_note_encryption::{ +use zcash_note_encryption_zsa::{ BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; @@ -349,7 +349,7 @@ impl BatchDomain for OrchardDomainV3 { } /// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption::NoteEncryption; +pub type OrchardNoteEncryption = zcash_note_encryption_zsa::NoteEncryption; impl ShieldedOutput for Action { fn ephemeral_key(&self) -> EphemeralKeyBytes { @@ -449,7 +449,7 @@ impl CompactAction { mod tests { use proptest::prelude::*; use rand::rngs::OsRng; - use zcash_note_encryption::{ + use zcash_note_encryption_zsa::{ try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; diff --git a/src/primitives/redpallas.rs b/src/primitives/redpallas.rs index 7690312a9..f51b9e582 100644 --- a/src/primitives/redpallas.rs +++ b/src/primitives/redpallas.rs @@ -154,7 +154,7 @@ impl VerificationKey { } /// A RedPallas signature. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Signature(reddsa::Signature); impl From<[u8; 64]> for Signature { diff --git a/tests/builder.rs b/tests/builder.rs index 5d69209ab..903ab3eca 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -12,7 +12,7 @@ use orchard::{ Anchor, Bundle, Note, }; use rand::rngs::OsRng; -use zcash_note_encryption::try_note_decryption; +use zcash_note_encryption_zsa::try_note_decryption; pub fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey, verify_proof: bool) { if verify_proof { diff --git a/tests/zsa.rs b/tests/zsa.rs index d3dd1b922..5bf9063c8 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -22,7 +22,7 @@ use orchard::{ }; use rand::rngs::OsRng; use std::collections::HashSet; -use zcash_note_encryption::try_note_decryption; +use zcash_note_encryption_zsa::try_note_decryption; #[derive(Debug)] struct Keychain { From f38d6b9e4cac7b56ec88c6aae91a9783ec977017 Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:06:30 +0530 Subject: [PATCH 51/92] Rename `sk_iss` to `isk`, the `IssuanceKey` struct to `IssuanceAuthorizingKey`, and move to a two key structure (#92) This performs a consistent renaming of the issuance authorizing key to make it consistent with the ZIP. It also reworks the `IssuanceAuthorizingKey` struct in place of the `IssuanceKey` and `IssuanceAuthorizingKey` structs, as part of using a two key structure for issuance, as specified in ZIP 227. --- src/bundle/burn_validation.rs | 7 ++- src/issuance.rs | 17 +++---- src/keys.rs | 83 ++++++++++------------------------- src/note/asset_base.rs | 16 +++---- src/supply_info.rs | 5 +-- tests/zsa.rs | 8 +--- 6 files changed, 44 insertions(+), 92 deletions(-) diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs index c0cfb84f1..0fdf35dd1 100644 --- a/src/bundle/burn_validation.rs +++ b/src/bundle/burn_validation.rs @@ -69,7 +69,7 @@ mod tests { /// Creates an item of bundle burn list for a given asset description and value. /// /// This function is deterministic and guarantees that each call with the same parameters - /// will return the same result. It achieves determinism by using a static `IssuanceKey`. + /// will return the same result. It achieves determinism by using a static `IssuanceAuthorizingKey`. /// /// # Arguments /// @@ -81,10 +81,9 @@ mod tests { /// A tuple `(AssetBase, Amount)` representing the burn list item. /// pub fn get_burn_tuple(asset_desc: &str, value: i64) -> (AssetBase, i64) { - use crate::keys::{IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey}; + use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; - let sk_iss = IssuanceKey::from_bytes([0u8; 32]).unwrap(); - let isk: IssuanceAuthorizingKey = (&sk_iss).into(); + let isk = IssuanceAuthorizingKey::from_bytes([0u8; 32]).unwrap(); ( AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc), diff --git a/src/issuance.rs b/src/issuance.rs index 8b5f200a4..9fe38c82a 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -532,7 +532,7 @@ pub fn verify_issue_bundle( pub enum Error { /// The requested IssueAction not exists in the bundle. IssueActionNotFound, - /// The provided `isk` and the driven `ik` does not match at least one note type. + /// The provided `isk` and the derived `ik` does not match at least one note type. IssueBundleIkMismatchAssetBase, /// `asset_desc` should be between 1 and 512 bytes. WrongAssetDescSize, @@ -562,7 +562,7 @@ impl fmt::Display for Error { IssueBundleIkMismatchAssetBase => { write!( f, - "the provided `isk` and the driven `ik` does not match at least one note type" + "the provided `isk` and the derived `ik` do not match at least one note type" ) } WrongAssetDescSize => { @@ -606,8 +606,7 @@ mod tests { }; use crate::issuance::{verify_issue_bundle, IssueAction, Signed, Unauthorized}; use crate::keys::{ - FullViewingKey, IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey, Scope, - SpendingKey, + FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; use crate::note::{AssetBase, Nullifier}; use crate::value::{NoteValue, ValueSum}; @@ -629,8 +628,7 @@ mod tests { ) { let mut rng = OsRng; - let sk_iss = IssuanceKey::random(&mut rng); - let isk: IssuanceAuthorizingKey = (&sk_iss).into(); + let isk = IssuanceAuthorizingKey::random(&mut rng); let ik: IssuanceValidatingKey = (&isk).into(); let fvk = FullViewingKey::from(&SpendingKey::random(&mut rng)); @@ -951,7 +949,7 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuanceAuthorizingKey = (&IssuanceKey::random(&mut OsRng)).into(); + let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(&mut OsRng); let err = bundle .prepare([0; 32]) @@ -1183,7 +1181,7 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuanceAuthorizingKey = (&IssuanceKey::random(&mut rng)).into(); + let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(&mut rng); let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); @@ -1278,8 +1276,7 @@ mod tests { let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); - let incorrect_sk_iss = IssuanceKey::random(&mut rng); - let incorrect_isk: IssuanceAuthorizingKey = (&incorrect_sk_iss).into(); + let incorrect_isk = IssuanceAuthorizingKey::random(&mut rng); let incorrect_ik: IssuanceValidatingKey = (&incorrect_isk).into(); // Add "bad" note diff --git a/src/keys.rs b/src/keys.rs index 4c6014f20..4748bebdc 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -223,25 +223,25 @@ type IssuanceAuth = SpendAuth; /// An issuance key, from which all key material is derived. /// -/// $\mathsf{sk}$ as defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents]. +/// $\mathsf{isk}$ as defined in [ZIP 227][issuancekeycomponents]. /// -/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents +/// [issuancekeycomponents]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation #[derive(Debug, Copy, Clone)] -pub struct IssuanceKey([u8; 32]); +pub struct IssuanceAuthorizingKey([u8; 32]); -impl From for IssuanceKey { +impl From for IssuanceAuthorizingKey { fn from(sk: SpendingKey) -> Self { - IssuanceKey(*sk.to_bytes()) + IssuanceAuthorizingKey(*sk.to_bytes()) } } -impl ConstantTimeEq for IssuanceKey { +impl ConstantTimeEq for IssuanceAuthorizingKey { fn ct_eq(&self, other: &Self) -> Choice { self.to_bytes().ct_eq(other.to_bytes()) } } -impl IssuanceKey { +impl IssuanceAuthorizingKey { /// Generates a random issuance key. /// /// This is only used when generating a random AssetBase. @@ -255,11 +255,9 @@ impl IssuanceKey { /// Constructs an Orchard issuance key from uniformly-random bytes. /// /// Returns `None` if the bytes do not correspond to a valid Orchard issuance key. - pub fn from_bytes(sk_iss: [u8; 32]) -> CtOption { - let sk_iss = IssuanceKey(sk_iss); - // If isk = 0 (A scalar value), discard this key. - let isk = IssuanceAuthorizingKey::derive_inner(&sk_iss); - CtOption::new(sk_iss, !isk.is_zero()) + pub fn from_bytes(isk_bytes: [u8; 32]) -> CtOption { + let isk = IssuanceAuthorizingKey(isk_bytes); + CtOption::new(isk, 1u8.into()) } /// Returns the raw bytes of the issuance key. @@ -267,7 +265,7 @@ impl IssuanceKey { &self.0 } - /// Derives the Orchard issuance key for the given seed, coin type, and account. + /// Derives the Orchard-ZSA issuance key for the given seed, coin type, and account. pub fn from_zip32_seed( seed: &[u8], coin_type: u32, @@ -282,22 +280,10 @@ impl IssuanceKey { ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE) .map(|esk| esk.sk().into()) } -} -/// An issuance authorizing key, used to create issuance authorization signatures. -/// This type enforces that the corresponding public point (ik^ℙ) has ỹ = 0. -/// -/// $\mathsf{isk}$ as defined in -/// [Issuance of Zcash Shielded Assets ZIP-0227 § Asset Identifier Generation (DRAFT ZIP)][IssuanceZSA]. -/// -/// [IssuanceZSA]: https://qed-it.github.io/zips/draft-ZIP-0227.html#asset-identifier-generation -#[derive(Clone, Debug)] -pub struct IssuanceAuthorizingKey(redpallas::SigningKey); - -impl IssuanceAuthorizingKey { - /// Derives isk from sk_iss. Internal use only, does not enforce all constraints. - fn derive_inner(sk_iss: &IssuanceKey) -> pallas::Scalar { - to_scalar(PrfExpand::ZsaIsk.expand(&sk_iss.0)) + /// Derives the RedPallas signing key from isk. Internal use only, does not enforce all constraints. + fn derive_inner(&self) -> pallas::Scalar { + to_scalar(PrfExpand::ZsaIsk.expand(&self.0)) } /// Sign the provided message using the `IssuanceAuthorizingKey`. @@ -306,32 +292,23 @@ impl IssuanceAuthorizingKey { rng: &mut (impl RngCore + CryptoRng), msg: &[u8], ) -> redpallas::Signature { - self.0.sign(rng, msg) - } -} - -impl From<&IssuanceKey> for IssuanceAuthorizingKey { - fn from(sk_iss: &IssuanceKey) -> Self { - let isk = IssuanceAuthorizingKey::derive_inner(sk_iss); - // IssuanceAuthorizingKey cannot be constructed such that this assertion would fail. - assert!(!bool::from(isk.is_zero())); - IssuanceAuthorizingKey(conditionally_negate(isk)) + conditionally_negate(self.derive_inner()).sign(rng, msg) } } /// A key used to validate issuance authorization signatures. /// -/// Defined in [Issuance of Zcash Shielded Assets ZIP-0227 § Asset Identifier Generation (DRAFT PR)][IssuanceZSA]. +/// Defined in [ZIP 227: Issuance of Zcash Shielded Assets § Issuance Key Generation][IssuanceZSA]. /// Note that this is $\mathsf{ik}^\mathbb{P}$, which by construction is equivalent to /// $\mathsf{ik}$ but stored here as a RedPallas verification key. /// -/// [IssuanceZSA]: https://qed-it.github.io/zips/draft-ZIP-0227.html#asset-identifier-generation +/// [IssuanceZSA]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation #[derive(Debug, Clone, PartialOrd, Ord)] pub struct IssuanceValidatingKey(VerificationKey); impl From<&IssuanceAuthorizingKey> for IssuanceValidatingKey { fn from(isk: &IssuanceAuthorizingKey) -> Self { - IssuanceValidatingKey((&isk.0).into()) + IssuanceValidatingKey((&(conditionally_negate(isk.derive_inner()))).into()) } } @@ -1116,11 +1093,10 @@ impl SharedSecret { #[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] pub mod testing { use super::{ - DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuanceAuthorizingKey, IssuanceKey, + DiversifierIndex, DiversifierKey, EphemeralSecretKey, IssuanceAuthorizingKey, IssuanceValidatingKey, SpendingKey, }; use proptest::prelude::*; - use rand::{rngs::StdRng, SeedableRng}; prop_compose! { /// Generate a uniformly distributed Orchard spending key. @@ -1137,15 +1113,15 @@ pub mod testing { } prop_compose! { - /// Generate a uniformly distributed Orchard issuance key. - pub fn arb_issuance_key()( + /// Generate a uniformly distributed Orchard issuance master key. + pub fn arb_issuance_authorizing_key()( key in prop::array::uniform32(prop::num::u8::ANY) - .prop_map(IssuanceKey::from_bytes) + .prop_map(IssuanceAuthorizingKey::from_bytes) .prop_filter( "Values must correspond to valid Orchard issuance keys.", |opt| bool::from(opt.is_some()) ) - ) -> IssuanceKey { + ) -> IssuanceAuthorizingKey { key.unwrap() } } @@ -1182,14 +1158,6 @@ pub mod testing { } } - prop_compose! { - /// Generate a uniformly distributed RedDSA issuance authorizing key. - pub fn arb_issuance_authorizing_key()(rng_seed in prop::array::uniform32(prop::num::u8::ANY)) -> IssuanceAuthorizingKey { - let mut rng = StdRng::from_seed(rng_seed); - IssuanceAuthorizingKey::from(&IssuanceKey::random(&mut rng)) - } - } - prop_compose! { /// Generate a uniformly distributed RedDSA issuance validating key. pub fn arb_issuance_validating_key()(isk in arb_issuance_authorizing_key()) -> IssuanceValidatingKey { @@ -1267,10 +1235,7 @@ mod tests { let ask: SpendAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask); - let sk_iss = IssuanceKey::from_bytes(tv.sk).unwrap(); - - let isk: IssuanceAuthorizingKey = (&sk_iss).into(); - assert_eq!(<[u8; 32]>::from(&isk.0), tv.isk); + let isk = IssuanceAuthorizingKey::from_bytes(tv.sk).unwrap(); let ak: SpendValidatingKey = (&ask).into(); assert_eq!(<[u8; 32]>::from(ak.0), tv.ak); diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 41a284a8a..ba8c80825 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -10,7 +10,7 @@ use subtle::{Choice, ConstantTimeEq, CtOption}; use crate::constants::fixed_bases::{ NATIVE_ASSET_BASE_V_BYTES, VALUE_COMMITMENT_PERSONALIZATION, ZSA_ASSET_BASE_PERSONALIZATION, }; -use crate::keys::{IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey}; +use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; /// Note type identifier. #[derive(Clone, Copy, Debug, Eq)] @@ -102,8 +102,7 @@ impl AssetBase { /// /// This is only used in tests. pub(crate) fn random(rng: &mut impl RngCore) -> Self { - let sk_iss = IssuanceKey::random(rng); - let isk = IssuanceAuthorizingKey::from(&sk_iss); + let isk = IssuanceAuthorizingKey::random(rng); let ik = IssuanceValidatingKey::from(&isk); let asset_descr = "zsa_asset"; AssetBase::derive(&ik, asset_descr) @@ -136,19 +135,18 @@ pub mod testing { use proptest::prelude::*; - use crate::keys::{testing::arb_issuance_key, IssuanceAuthorizingKey, IssuanceValidatingKey}; + use crate::keys::{testing::arb_issuance_authorizing_key, IssuanceValidatingKey}; prop_compose! { /// Generate a uniformly distributed note type pub fn arb_asset_id()( is_native in prop::bool::ANY, - sk in arb_issuance_key(), + isk in arb_issuance_authorizing_key(), str in "[A-Za-z]{255}", ) -> AssetBase { if is_native { AssetBase::native() } else { - let isk = IssuanceAuthorizingKey::from(&sk); AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) } } @@ -165,10 +163,9 @@ pub mod testing { prop_compose! { /// Generate an asset ID pub fn arb_zsa_asset_id()( - sk_iss in arb_issuance_key(), + isk in arb_issuance_authorizing_key(), str in "[A-Za-z]{255}" ) -> AssetBase { - let isk = IssuanceAuthorizingKey::from(&sk_iss); AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) } } @@ -176,10 +173,9 @@ pub mod testing { prop_compose! { /// Generate an asset ID using a specific description pub fn zsa_asset_id(asset_desc: String)( - sk_iss in arb_issuance_key(), + isk in arb_issuance_authorizing_key(), ) -> AssetBase { assert!(super::is_asset_desc_of_valid_size(&asset_desc)); - let isk = IssuanceAuthorizingKey::from(&sk_iss); AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) } } diff --git a/src/supply_info.rs b/src/supply_info.rs index 1c2f346b1..1752fbd64 100644 --- a/src/supply_info.rs +++ b/src/supply_info.rs @@ -80,10 +80,9 @@ mod tests { use super::*; fn create_test_asset(asset_desc: &str) -> AssetBase { - use crate::keys::{IssuanceAuthorizingKey, IssuanceKey, IssuanceValidatingKey}; + use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; - let sk_iss = IssuanceKey::from_bytes([0u8; 32]).unwrap(); - let isk: IssuanceAuthorizingKey = (&sk_iss).into(); + let isk = IssuanceAuthorizingKey::from_bytes([0u8; 32]).unwrap(); AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc) } diff --git a/tests/zsa.rs b/tests/zsa.rs index 5bf9063c8..dec5dcc1f 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -13,10 +13,7 @@ use orchard::{ builder::Builder, bundle::Flags, circuit::{ProvingKey, VerifyingKey}, - keys::{ - FullViewingKey, IssuanceKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, - SpendingKey, - }, + keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, value::NoteValue, Address, Anchor, Bundle, Note, }; @@ -61,8 +58,7 @@ fn prepare_keys() -> Keychain { let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); - let sk_iss = IssuanceKey::from_bytes([0; 32]).unwrap(); - let isk = IssuanceAuthorizingKey::from(&sk_iss); + let isk = IssuanceAuthorizingKey::from_bytes([0; 32]).unwrap(); let ik = IssuanceValidatingKey::from(&isk); Keychain { pk, From 0ee75f5ea7127b59a69101cce18dbca917e4a600 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 18 Dec 2023 21:21:04 +0100 Subject: [PATCH 52/92] Circuit: move mux functionality into CondSwap chip (#94) In halo2 repository, the mux functionality has been moved into the CondSwap chip. --- src/circuit.rs | 14 +- src/circuit/gadget.rs | 10 +- src/circuit/note_commit.rs | 32 +- src/circuit_description | 3151 ++++++++++++------------------- src/circuit_proof_test_case.bin | Bin 5283 -> 5283 bytes src/note/commitment.rs | 6 +- 6 files changed, 1188 insertions(+), 2025 deletions(-) diff --git a/src/circuit.rs b/src/circuit.rs index 7c5ba1f18..0199d281f 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -60,8 +60,8 @@ use halo2_gadgets::{ }, utilities::{ bool_check, + cond_swap::{CondSwapChip, CondSwapConfig}, lookup_range_check::LookupRangeCheckConfig, - mux::{MuxChip, MuxConfig}, }, }; @@ -103,7 +103,7 @@ pub struct Config { commit_ivk_config: CommitIvkConfig, old_note_commit_config: NoteCommitConfig, new_note_commit_config: NoteCommitConfig, - mux_config: MuxConfig, + cond_swap_config: CondSwapConfig, } /// The Orchard Action circuit. @@ -455,7 +455,7 @@ impl plonk::Circuit for Circuit { let new_note_commit_config = NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); - let mux_config = MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); + let cond_swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); Config { primary, @@ -471,7 +471,7 @@ impl plonk::Circuit for Circuit { commit_ivk_config, old_note_commit_config, new_note_commit_config, - mux_config, + cond_swap_config, } } @@ -668,7 +668,7 @@ impl plonk::Circuit for Circuit { config.poseidon_chip(), config.add_chip(), ecc_chip.clone(), - config.mux_chip(), + config.cond_swap_chip(), rho_old.clone(), &psi_nf, &cm_old, @@ -764,7 +764,7 @@ impl plonk::Circuit for Circuit { config.sinsemilla_chip_1(), config.ecc_chip(), config.note_commit_chip_old(), - config.mux_chip(), + config.cond_swap_chip(), g_d_old.inner(), pk_d_old.inner(), v_old.clone(), @@ -825,7 +825,7 @@ impl plonk::Circuit for Circuit { config.sinsemilla_chip_2(), config.ecc_chip(), config.note_commit_chip_new(), - config.mux_chip(), + config.cond_swap_chip(), g_d_new.inner(), pk_d_new.inner(), v_new.clone(), diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index fe0dc4cec..dff412b72 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -15,7 +15,7 @@ use halo2_gadgets::{ Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, }, sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, - utilities::mux::{MuxChip, MuxInstructions}, + utilities::cond_swap::CondSwapChip, }; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter, Value}, @@ -73,8 +73,8 @@ impl super::Config { NoteCommitChip::construct(self.old_note_commit_config.clone()) } - pub(super) fn mux_chip(&self) -> MuxChip { - MuxChip::construct(self.mux_config.clone()) + pub(super) fn cond_swap_chip(&self) -> CondSwapChip { + CondSwapChip::construct(self.cond_swap_config.clone()) } } @@ -170,7 +170,7 @@ pub(in crate::circuit) fn derive_nullifier< poseidon_chip: PoseidonChip, add_chip: AddChip, ecc_chip: EccChip, - mux_chip: MuxChip, + cond_swap_chip: CondSwapChip, rho: AssignedCell, psi: &AssignedCell, cm: &Point, @@ -223,7 +223,7 @@ pub(in crate::circuit) fn derive_nullifier< // Select the desired nullifier according to split_flag Ok(Point::from_inner( ecc_chip, - mux_chip.mux_on_points( + cond_swap_chip.mux_on_points( layouter.namespace(|| "mux on nf"), &split_flag, nf.inner(), diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index 857020c58..934238e94 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -22,9 +22,7 @@ use halo2_gadgets::{ CommitDomain, Message, MessagePiece, }, utilities::{ - bool_check, - lookup_range_check::LookupRangeCheckConfig, - mux::{MuxChip, MuxInstructions}, + bool_check, cond_swap::CondSwapChip, lookup_range_check::LookupRangeCheckConfig, FieldValue, RangeConstrained, }, }; @@ -1747,7 +1745,7 @@ pub(in crate::circuit) mod gadgets { chip: SinsemillaChip, ecc_chip: EccChip, note_commit_chip: NoteCommitChip, - mux_chip: MuxChip, + cond_swap_chip: CondSwapChip, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, value: AssignedCell, @@ -1902,7 +1900,7 @@ pub(in crate::circuit) mod gadgets { Value::known(zsa_domain.q_init()), )?; - mux_chip.mux_on_non_identity_points( + cond_swap_chip.mux_on_non_identity_points( layouter.namespace(|| "mux on hash point"), &is_native_asset, q_init_zsa.inner(), @@ -1939,7 +1937,7 @@ pub(in crate::circuit) mod gadgets { // hash_point = hash_zsa if is_native_asset is false let hash_point = Point::from_inner( ecc_chip, - mux_chip.mux_on_points( + cond_swap_chip.mux_on_points( layouter.namespace(|| "mux on hash point"), &is_native_asset, &(hash_point_zsa.inner().clone().into()), @@ -2342,8 +2340,8 @@ mod tests { }, sinsemilla::chip::SinsemillaChip, utilities::{ + cond_swap::{CondSwapChip, CondSwapConfig}, lookup_range_check::LookupRangeCheckConfig, - mux::{MuxChip, MuxConfig}, }, }; @@ -2370,7 +2368,11 @@ mod tests { } impl Circuit for MyCircuit { - type Config = (NoteCommitConfig, EccConfig, MuxConfig); + type Config = ( + NoteCommitConfig, + EccConfig, + CondSwapConfig, + ); type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -2446,10 +2448,10 @@ mod tests { range_check, ); - let mux_config = - MuxChip::configure(meta, advices[0], advices[1], advices[2], advices[3]); + let cond_swap_config = + CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - (note_commit_config, ecc_config, mux_config) + (note_commit_config, ecc_config, cond_swap_config) } fn synthesize( @@ -2457,7 +2459,7 @@ mod tests { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let (note_commit_config, ecc_config, mux_config) = config; + let (note_commit_config, ecc_config, cond_swap_config) = config; // Load the Sinsemilla generator lookup table used by the whole circuit. SinsemillaChip::< @@ -2476,8 +2478,8 @@ mod tests { // Construct a NoteCommit chip let note_commit_chip = NoteCommitChip::construct(note_commit_config.clone()); - // Construct a Mux chip - let mux_chip = MuxChip::construct(mux_config); + // Construct a CondSwap chip + let cond_swap_chip = CondSwapChip::construct(cond_swap_config); // Witness g_d let g_d = NonIdentityPoint::new( @@ -2544,7 +2546,7 @@ mod tests { sinsemilla_chip, ecc_chip.clone(), note_commit_chip, - mux_chip, + cond_swap_chip, g_d.inner(), pk_d.inner(), value_var, diff --git a/src/circuit_description b/src/circuit_description index 903fb3017..6513b720e 100644 --- a/src/circuit_description +++ b/src/circuit_description @@ -10,7 +10,7 @@ PinnedVerificationKey { num_fixed_columns: 33, num_advice_columns: 10, num_instance_columns: 1, - num_selectors: 63, + num_selectors: 61, gates: [ Product( Product( @@ -13750,144 +13750,6 @@ PinnedVerificationKey { ), ), ), - Sum( - Scaled( - Fixed { - query_index: 0, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Product( - Sum( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - Negated( - Sum( - Sum( - Product( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - ), - Negated( - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - ), - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 27, - column_index: 27, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), Sum( Scaled( Advice { @@ -14349,7 +14211,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -14458,7 +14320,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -14567,7 +14429,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -14608,53 +14470,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14664,12 +14494,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14679,12 +14509,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14729,53 +14559,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14785,12 +14583,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14800,12 +14598,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14874,53 +14672,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14930,12 +14696,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14945,12 +14711,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -14993,53 +14759,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -15049,12 +14783,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -15064,12 +14798,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 28, - column_index: 28, + query_index: 27, + column_index: 27, rotation: Rotation( 0, ), @@ -15198,11 +14932,11 @@ PinnedVerificationKey { ), Sum( Scaled( - Fixed { - query_index: 4, - column_index: 5, + Advice { + query_index: 21, + column_index: 6, rotation: Rotation( - 0, + -1, ), }, 0x0000000000000000000000000000000000000000000000000000000000000002, @@ -15279,41 +15013,72 @@ PinnedVerificationKey { ), ), Product( - Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( Product( - Product( - Product( - Product( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, ), Negated( - Fixed { - query_index: 28, - column_index: 28, + Advice { + query_index: 5, + column_index: 5, rotation: Rotation( 0, ), }, ), ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), Negated( - Fixed { - query_index: 28, - column_index: 28, + Advice { + query_index: 6, + column_index: 6, rotation: Rotation( 0, ), @@ -15321,214 +15086,13 @@ PinnedVerificationKey { ), ), ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, - ), - Negated( - Fixed { - query_index: 28, - column_index: 28, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Scaled( - Advice { - query_index: 21, - column_index: 6, - rotation: Rotation( - -1, - ), - }, - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Product( - Sum( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), - Sum( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - Negated( - Sum( - Sum( - Product( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - ), - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - ), - ), - ), - ), - ), - Product( - Fixed { - query_index: 20, - column_index: 20, - rotation: Rotation( - 0, - ), - }, - Sum( - Product( - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 9, - column_index: 9, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Sum( - Sum( - Advice { - query_index: 15, - column_index: 5, - rotation: Rotation( - 1, - ), - }, - Sum( - Sum( - Product( - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 8, - column_index: 8, - rotation: Rotation( - 0, - ), - }, - ), - Negated( - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, - ), - ), - Negated( - Advice { - query_index: 6, - column_index: 6, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Advice { - query_index: 5, - column_index: 5, - rotation: Rotation( - 0, - ), - }, + }, ), ), ), @@ -15791,8 +15355,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15803,8 +15367,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15818,8 +15382,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15833,8 +15397,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15848,8 +15412,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15863,8 +15427,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15932,8 +15496,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15944,8 +15508,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15959,8 +15523,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15974,8 +15538,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -15989,8 +15553,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16004,8 +15568,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16073,8 +15637,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16085,8 +15649,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16100,8 +15664,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16115,8 +15679,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16130,8 +15694,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16145,8 +15709,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -16223,7 +15787,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16344,7 +15908,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16489,7 +16053,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16608,7 +16172,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -16742,7 +16306,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -16854,7 +16418,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -16966,7 +16530,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17097,7 +16661,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17216,7 +16780,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17347,7 +16911,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17490,7 +17054,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17595,7 +17159,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17700,7 +17264,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17819,7 +17383,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -17924,7 +17488,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18029,7 +17593,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18134,7 +17698,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18265,7 +17829,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -18385,7 +17949,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18497,7 +18061,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18609,7 +18173,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -18684,8 +18248,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18696,8 +18260,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18711,8 +18275,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18722,12 +18286,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18737,12 +18301,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18752,12 +18316,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18796,8 +18360,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18808,8 +18372,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18823,8 +18387,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18834,12 +18398,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18849,12 +18413,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18864,12 +18428,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18908,8 +18472,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18920,8 +18484,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18935,8 +18499,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18946,12 +18510,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18961,12 +18525,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -18976,12 +18540,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 29, - column_index: 29, + query_index: 28, + column_index: 28, rotation: Rotation( 0, ), @@ -19074,7 +18638,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -19089,7 +18653,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19208,7 +18772,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19223,7 +18787,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19320,7 +18884,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -19335,7 +18899,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19466,7 +19030,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19481,7 +19045,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19578,7 +19142,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19593,7 +19157,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19697,7 +19261,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -19712,7 +19276,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -19774,37 +19338,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19814,12 +19362,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19829,12 +19377,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19844,12 +19392,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19859,12 +19407,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19902,37 +19450,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19942,12 +19474,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19957,12 +19489,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19972,12 +19504,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -19987,12 +19519,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20030,37 +19562,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20070,12 +19586,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20085,12 +19601,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20100,12 +19616,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20115,12 +19631,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20165,37 +19681,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20205,12 +19705,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20220,12 +19720,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20235,12 +19735,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20250,12 +19750,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20312,37 +19812,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20352,12 +19836,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20367,12 +19851,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20382,12 +19866,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20397,12 +19881,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20447,37 +19931,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20487,12 +19955,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20502,12 +19970,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20517,12 +19985,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20532,12 +20000,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20568,37 +20036,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20608,12 +20060,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20623,12 +20075,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20638,12 +20090,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20653,12 +20105,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20689,37 +20141,21 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 30, - column_index: 30, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 29, + column_index: 29, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20729,12 +20165,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20744,12 +20180,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20759,12 +20195,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20774,12 +20210,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 30, - column_index: 30, + query_index: 29, + column_index: 29, rotation: Rotation( 0, ), @@ -20820,7 +20256,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20835,7 +20271,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -20967,7 +20403,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -20982,7 +20418,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21114,7 +20550,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -21129,7 +20565,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21235,7 +20671,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -21250,7 +20686,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21371,7 +20807,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -21386,7 +20822,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21533,7 +20969,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21548,7 +20984,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21680,7 +21116,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21695,7 +21131,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21827,7 +21263,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21842,7 +21278,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -21948,7 +21384,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -21963,7 +21399,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22084,7 +21520,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22099,7 +21535,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22243,7 +21679,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22258,7 +21694,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22390,7 +21826,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22405,7 +21841,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22511,7 +21947,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22526,7 +21962,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22632,7 +22068,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -22647,7 +22083,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22768,7 +22204,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22783,7 +22219,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -22896,7 +22332,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -22911,7 +22347,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -23043,7 +22479,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23058,7 +22494,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -23190,7 +22626,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23205,7 +22641,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -23325,7 +22761,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23340,7 +22776,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -23446,7 +22882,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23461,7 +22897,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -23567,7 +23003,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -23582,7 +23018,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -23620,20 +23056,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23643,12 +23079,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23658,12 +23094,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23673,12 +23109,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23688,12 +23124,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23707,8 +23143,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23748,20 +23184,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23771,12 +23207,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23786,12 +23222,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23801,12 +23237,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23816,12 +23252,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23835,8 +23271,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23876,20 +23312,20 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23899,12 +23335,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23914,12 +23350,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23929,12 +23365,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23944,12 +23380,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -23963,8 +23399,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24035,8 +23471,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24047,8 +23483,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24058,12 +23494,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24073,12 +23509,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24088,12 +23524,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24103,12 +23539,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24118,12 +23554,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24163,8 +23599,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24175,8 +23611,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24186,12 +23622,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24201,12 +23637,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24216,12 +23652,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24231,12 +23667,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24246,12 +23682,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24291,8 +23727,8 @@ PinnedVerificationKey { Product( Product( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24303,8 +23739,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24314,12 +23750,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24329,12 +23765,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24344,12 +23780,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24359,12 +23795,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24374,12 +23810,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000007, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { - query_index: 31, - column_index: 31, + query_index: 30, + column_index: 30, rotation: Rotation( 0, ), @@ -24458,7 +23894,7 @@ PinnedVerificationKey { }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -24473,7 +23909,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24608,7 +24044,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24623,7 +24059,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24736,7 +24172,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -24751,7 +24187,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24898,7 +24334,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -24913,7 +24349,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25026,7 +24462,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -25041,7 +24477,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25161,7 +24597,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -25176,7 +24612,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25323,7 +24759,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25338,7 +24774,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25451,7 +24887,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25466,7 +24902,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25579,7 +25015,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000005, ), Negated( Fixed { @@ -25594,7 +25030,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25729,7 +25165,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25744,7 +25180,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -25876,7 +25312,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -25891,7 +25327,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -26011,7 +25447,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26026,7 +25462,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -26132,7 +25568,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26147,7 +25583,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -26253,7 +25689,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000006, ), Negated( Fixed { @@ -26268,7 +25704,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { @@ -26304,21 +25740,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26332,8 +25784,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26347,8 +25799,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26362,8 +25814,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26373,12 +25825,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26435,21 +25887,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26463,8 +25931,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26478,8 +25946,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26493,8 +25961,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26504,12 +25972,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26566,21 +26034,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26594,8 +26078,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26609,8 +26093,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26624,8 +26108,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26635,12 +26119,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26671,21 +26155,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26699,8 +26199,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26714,8 +26214,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26729,8 +26229,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26740,12 +26240,12 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000007, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26776,21 +26276,37 @@ PinnedVerificationKey { Product( Product( Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, + Product( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 31, + column_index: 31, + rotation: Rotation( + 0, + ), + }, + ), ), - }, + ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26804,8 +26320,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26819,8 +26335,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26834,8 +26350,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26849,8 +26365,8 @@ PinnedVerificationKey { ), Negated( Fixed { - query_index: 32, - column_index: 32, + query_index: 31, + column_index: 31, rotation: Rotation( 0, ), @@ -26905,48 +26421,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -26961,7 +26445,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26976,7 +26460,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27036,50 +26520,18 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, - ), - Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( Fixed { query_index: 32, column_index: 32, @@ -27092,7 +26544,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27107,7 +26559,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27167,48 +26619,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27223,7 +26643,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27238,7 +26658,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27272,48 +26692,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27328,7 +26716,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27343,7 +26731,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27377,48 +26765,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27433,7 +26789,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27448,7 +26804,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27520,48 +26876,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27576,7 +26900,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27591,7 +26915,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27651,50 +26975,18 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Fixed { query_index: 32, column_index: 32, @@ -27707,7 +26999,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27722,7 +27014,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27756,48 +27048,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27812,7 +27072,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27827,7 +27087,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27861,48 +27121,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27917,7 +27145,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27932,7 +27160,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -27966,48 +27194,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28022,7 +27218,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28037,7 +27233,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28078,48 +27274,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28134,7 +27298,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28149,7 +27313,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28209,48 +27373,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28265,7 +27397,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28280,7 +27412,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28340,48 +27472,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28396,7 +27496,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28411,7 +27511,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28459,48 +27559,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28515,7 +27583,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28530,7 +27598,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28564,48 +27632,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28620,7 +27656,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28635,7 +27671,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28669,48 +27705,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28725,7 +27729,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28740,7 +27744,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000006, + 0x0000000000000000000000000000000000000000000000000000000000000004, ), Negated( Fixed { @@ -28774,8 +27778,18 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Fixed { query_index: 32, column_index: 32, @@ -28783,39 +27797,106 @@ PinnedVerificationKey { 0, ), }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Fixed { - query_index: 32, - column_index: 32, + Advice { + query_index: 4, + column_index: 4, rotation: Rotation( 0, ), }, ), ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -28830,7 +27911,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -28845,7 +27926,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000005, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -28859,56 +27940,136 @@ PinnedVerificationKey { ), ), Sum( - Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( Product( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, Sum( Constant( 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( - Advice { - query_index: 0, - column_index: 0, + Fixed { + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), }, ), ), - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, ), - Product( - Advice { - query_index: 0, - column_index: 0, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 32, + column_index: 32, rotation: Rotation( 0, ), }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( Advice { - query_index: 2, - column_index: 2, + query_index: 4, + column_index: 4, rotation: Rotation( 0, ), }, ), ), - Negated( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - ), ), ), ], @@ -30310,50 +29471,50 @@ PinnedVerificationKey { (0x0decb727cf32e573604ae3928a761b450d9460f2a7283c8cf88a2b38b796e575, 0x044c0a88bc6aa468e75fc709f9eb21b6e309dd8a6ca62f7a3da86299141ea3a9), (0x285e16cead69d5fef9441d4d4ac695fe8880120d209e1e631d8a4bc5f55e90e6, 0x3700fd2dfcfac5b2cb6d33c60ac79dfac3fb95518cd0aa97c75a51d62281f2c1), (0x2dc11f4f0000da15c59cd395ea5f32b4e79783d958c290c821c89e0bcb50eaf1, 0x2c53e12ce0a2022516ef31f0224b0bc1b119861078358f78d245ba5d2f180099), - (0x3fb934de80a76b78bb5daf3fb368ebcefabc5b6b9ebae5cddc1e39c82b122b48, 0x130a034bee7622c60e8a53f70216e48696f5d9457aade41f0ef09166091c66e7), - (0x19e589077358b9abcb3e21a71537113cf43c43aea7e300fdfb755bb29449a5b6, 0x1da596141c740b648dabc4961ed014ed0dd8dfcc03b2d02cf6ff9e8a3ff0e42e), - (0x1af56c46ba6aaab50db1acd46003c05c3fee103776681f61100b1b6aef07c284, 0x38eea07b7f5881eff963d114e50084bb5bf5cf359f023fc855f3a01b0ca1e432), - (0x0cfb7c9b0bfcf398a53c13d6e1068989805f1cf254dddcaa4ab57da05ad0616e, 0x37fcd5b873385ee44169fe3870a9feeadbf64c21fa2c4b130f718e47f29ff8dc), - (0x03c0cdbe7ea6296a9eb724d225d0adf451999dd9686aaa5659e23102b5daec07, 0x1ec2e8d39dd47c991a31f9476467800bf49655e7293efc4e5261b7ffb15af542), - (0x1314cd9c9d35b73165e86972dc6007ec35aab9ef8f6358cc090043cf68c4c2f5, 0x3d9e921baede6846e7fd2f0805deec1da2395e7d3f647ef8f6e5ecdb456c22c3), - (0x3e3c175e12e425f9f5b499541aba80122e8c346ab329e8d2400debb7a4298473, 0x3621561ea96a7834b55250be2bc137fffa02705ca49848c61955417883a289c1), - (0x0491089f80b3aa79defa2923388ba287c07ff7b5d805932133b249b674c69dcb, 0x2463e5cde6ef2b91fbd72d8d1511556bf6d9ec460f19b890544bc6886906741c), - (0x2b8e5f9c2efdb6cca222b066bd10be6c1ec15951b5f22f11e7bdad199936d91e, 0x2579a5ebe80abe31205c73ebfe4012559a9c00f9ed2a7303c08420dd46ecccc8), - (0x06abaaea1008f82ba485632d1e6d130e8bd9baf450cee1210b5780fae7df1012, 0x0b21835ef9aed7d7b1a0dc9b2af53fab3a6c4f1a8a3568c2570d06ba392a73a1), - (0x1f18cb4d7fc46f1fe4aecbaf07fae7d29a0cb49317f60c17161837443e2f32a0, 0x3827b12472ab9f40d713702752e542832f8e812ca73b14e975b42ab7c56f10b9), - (0x1880c0651fead5ccae365349f9158252d6846f24f3d4c1fa9c190ee0b9020f3f, 0x05fb1b7ad97f29412f5a50cd0369f7c2a4cc07f98e2e4ddc0b677a97ac3617a6), + (0x17e9ee15383a32a80bd1d4b3ae53c19389748922e9bf4dbc4884e20a472b10ef, 0x1947806a1f43a3f2b675ec6d46d1678d1f18374ef89ec2654152e454346b3add), + (0x365c3f7dfaa40ec708988a9392112df6725a65eb5f70b809025ee47e9dae145b, 0x1661613acd8709d05038f6d5ca5a8508c0dd881d5879d85dcd4ea48aa12875fc), + (0x178d86d072746921f193c4a1f24e0bc252c810e7fb4ca7dbb8258f7dfb45a547, 0x153d91d5ea619d522d5a4dfdbcef80686ed1328980f1dab8aea30357ce57bd0a), + (0x35d8b6e2ebbc57d08dea9e510d450b40b5a3dd4359f9f2a888610aff29ee3c23, 0x360e4b2ce85b08d0a9576207382c26de7ad35ce33f582b6eeedd72d406ff9cef), + (0x309fd7b620087579d276623592c791f36cd3424b2230a8e7d45dcaf586ed288b, 0x0e77ac0389e400aba724c636c13e01de338bbaa8c992a0174be3504204c15a26), + (0x3bd856be3b91aea580396400bc03d30de759946141fd92cda5d975b64b4f48c7, 0x1b8fb47363e53a6235dc03a8d1ee9e81ed13e8affb1ea7fc2228df24d6d795d5), + (0x15e059df5a9a5c7e33e31e5ab4f2629efc513bf6cffca27de6b279632b8f7b06, 0x2e715a322fad2b5bf21dbcb66c26dbffa26c4c00bb2a45ae30c456daa3a75a86), + (0x307aa50de381ca85af5aa98cb4b8f3c74d0e4b49d02929dda1e4f187de911e19, 0x032f3980542054f73b659cb328e7db6cef6ac537fc9cae3b09fb7b164cb542f5), + (0x0d0c4b42b87439e56df6f41f07d93367df6f5a64d273338b0d4c8c242b908849, 0x2ab0f7f461b85408e4d007d0fcb5fa6f70a18b42c373d515f7c1e55bc20c384c), + (0x251b9a858904eb93ea4b89b3a65ceacd637db066f16d1fa896eda84434d72950, 0x2c60a586cb79bcca811be1d1092a23131a6884ccb2d809f92e94c5a4d174b167), + (0x3b09db3011d8047afc6ea9c8f3787f9b1870affc14ab64a9433508050cd41d9f, 0x3903a28dcf729c1132353036fc2819a0d0dce6ceda266a388ae401026274e99a), + (0x244649d7c67dab9df822ad21a4a3e46afcc7e020c31c54563d78b81bc4ec4f18, 0x2d5ba72aca69c6a3d5a2c3fa22c5d0c4b91b340bd757b344caae739cece6efbe), (0x18b67544d4466429760be2b231418b43d35d79462f8743051c8e437dd710035d, 0x2ca31a6106310316da5633fe4e16e2a0affafc4541b280a9722ae86219127aa0), - (0x0477cc6f6292f9d3dcbcdb6b896dbc2b76b8716db8d80f36af610738a89e58e0, 0x0fb4d1d92e0606c83e4d1359ad9e607a936339871c9c606cc9218225c8a762d4), - (0x027f5c9006d53a989091caa780c6b4ec009e328d03836f95ee05bfb2178ba931, 0x2c7612c86a27585617aa8b0202e638d57b079417ca8722a4f47c3c12892cbea9), - (0x1b9d2736bed08950ac569b6bc5d2a8bdd48cec8a206030c306f665af83c4df12, 0x2b8e0e07c521db751c386d011504b5f4c8fd2b09ace077e54f05bd0fbe0a2def), - (0x3d7f0951711965e07ab0e4c1451361e5b536793dcf76176e4e854285a7bdabba, 0x13780fb58b9b717ebd2040e8d79be7bc7f32c5d9b31b0766c6eea63ccc6c6ff1), - (0x2ebee709b368779cf6bc2bec772f19fee25938985b94fef3a86c9950adcc9ae0, 0x18af23ba308d2e8a6d9bf544def217546a8e9816192ce2c29841379a935b74ff), - (0x2a9ef8f91987bd8f2f6101abfc05caf7e30c7d79faba1022d547a00b04333f7c, 0x153a1907977cf09f557085c0f256b877f72567b3a2f92179e33d468fbfc8b10a), + (0x1bc437a546b233020c7dfb4a62ec2720348e39160b45d0a6739df91eff962d75, 0x11f3c7e8df45cbd7d0e089000d0af3192b29e31edef31414897229edbf23b9e8), + (0x36579b3969fa8bb60eb3ea82410d5b440f5cadc10bba33c2f952d6e6e0647d2c, 0x332696aaf0ece706b633aeae97764c7b867e4be79c53f1a1ebed9053716d95df), + (0x2c47c46efa6b729a216455d1887eb910e21f50bedb97d48fd76f89e3abf4e5a4, 0x20da2ca8dde7430e2b663c22d10eeb6b511e341b6a29fe9dd094ab249da4f5db), + (0x12da47c8091b8de4fc979e49f7b173d352504f18ccc461ecc5bbe4a798078ba8, 0x2d7eb25b36bb9419d081f457f4424ffc9c3b47d558063bc5c58de550c041cdf9), + (0x33a7a93684fd8f5890cc6df73bfee688ff4c778b237afac6a00807d74750f07e, 0x09ba011a18d53d7cf20a020d179ba3a2dd93c1c5fa1c5906d51c16e78c15b2e1), + (0x00f0d0db9c11b86736183d8ef1c4e621a045ad11e4ece8b32e65cd3937193ff0, 0x173d130f6ce49e3ac2be51d550dc1854fec456c82f6ddaa46bcb4c29c9be3601), (0x334105dd96996a08df56e88261dcd87c5356cfc0f2b8ae0a9419899d5def147b, 0x09ddf24ae765eda056cf59b16ac14464240c83e253135682c02e6546f89dd396), - (0x2dac89c801000721a4422cb8bb1def97cd3bfce7c64ac6327e335b3c0071a049, 0x2e2575abf15aa7424617ae9c7c9749c67c38a3e68082c4f937e4dbcff98b4dfc), + (0x04706edf95516db26def46d92def64d6a61cb357ac5ace44a1015c33238778fa, 0x03560c6396e34aac8e541a7811eb0b7fb1b70262af59976f933135f3bf5b21b1), (0x0b89c282c8f2d54e66c7a11e6b4338a2f06a7c9430f7d3376328f12fa001cac5, 0x098b5c8ee6548183ccb4e60cdfee10b509db34ed136daf3530a426e8f200e89d), (0x2f7f85b86b6adcf714d0df7878f4604d33fd319f39bd00fd5c34378247a155b5, 0x3a2f025447b83b65d148e99c93fe8bb991a81ef6d2f827f010680467361c47fc), - (0x121fe2a31c21b4d21266dde870a72ca2e96ea0fd80ca2ca59436c8cad25ae150, 0x0d2aff2c6e65712a354da894209b75ff8479cb958ab050156f63f3760b8a05ca), - (0x14815e90ec334c51da36b50c69b8f192f1cfd63fcd3257c7a16691b7be2a1759, 0x0711e90858dbade5aac1c82b1000a59e2beccfd84db4e212368b1a5b5a8ecf3a), - (0x3bd7f461093bd6b774837199b58d3d6741f80ce738345b18800adf8fedf37286, 0x3f9162dc512623e1c62b2360fb6db7400f9c545b2028af0f4580d308fd44818c), - (0x1f64379a921e197082d9e2afe9baa825f2af8fa02bbfa653772604bf22125eaa, 0x348d5a1de410f8c0ec8f9fe4514709c6cbc0882dc8d6ec0f8562f05c535ab2a9), - (0x12e6bba88452419d3d1632edf16b02a63a5ac81241118845ea41ed70111f1f83, 0x3f0899ae3f41bea051afee8df4dddb13d78857773df79d2e6eeae02b0c8f423d), - (0x0f59f5bdf3fbc2551cff44f3444bdb84ca5956aa0ec424cb8d8318abc12370d8, 0x219d1021cfd377e3ea006ed15485437702218e0cc6e76975025f7632bd66d072), + (0x2f6abda2aac141daa71c4840e9219e8436e17490a00d8515671b680f46ffbfab, 0x2c75aee9bdf500ef2a0168b6fa0f10c842985c5c426815e19e6f6636d6cf398a), + (0x0efdfd083488fd21fd34b09babfcea5e011189a37a52b4dc0afb218d5e604059, 0x397ed924bd171cf27208fe866cc124716d635d44f0cba045700e4136a3185179), + (0x0bb5f4d46d728f99749505115a25d8c8f281f46b5fe187a5ed722a68c1f0d8ac, 0x3e31c0c30fb0b01202f35c9336e40e91791d6b92800b2ab62bc9e0d7736a91b8), + (0x2c129e36dba381b51ffea33bf3a8ee685044217aa05865845e870971284b3d80, 0x0a07fed35f5d06923fcec6487e015d1c591d1be2d0028445227fecf733d765b0), + (0x2341c41103ad0c10434f84c82e13070b4018d325e0340f71a980600bac88dba8, 0x18965a11e1ebaea864ccd67f34faf358b5aa34690213eecda9cd94f3ea0db644), + (0x045ceb3c0119d08391456db1c30335869ee9bd9d90898c4d9f65d6486f2e3a60, 0x138805b0eab5b97ecc613077f5d91c5690f642d1d40801e6ace05a2e4947aa0c), ], permutation: VerifyingKey { commitments: [ - (0x05625166f1bf876dd59af0e45b068df3dc22e28accb12418d5111fc12b563d4a, 0x102be9e1b4fe8a6d8c00ffbf6513e8410b9a940a7b559914fdeb45a2b170cdb3), - (0x2319a6b8fdaca310c4042b98fe068ce93913270e534c3d88029fc5f8ba6ab3d9, 0x1a4374fb532ec3d030217dc66c6e0db4ac456bee8641cfe049190973c8b5c72f), - (0x0765958f562227c7838c73baba821f9c2f40868c58654dcf675b718feef1a01e, 0x378fb34b8ab337872d942b99123219ffe532124adc9cd3c31437aa6a5becd763), - (0x1df175a3908c91e4d9c1e4fd6e8f30d3fde110f9dc379eec7db39ceaa53f2ad6, 0x3b419848016ad53c7aaa29602b85580c499016ceb49ccf8496f7e9b3f413d4df), - (0x171cad3d3e6e7a153ff12d86ee56a01505acc1ee38fb9a11b68abfa5ad1a1e46, 0x37343f7a56d7e180ddd2ae2ca4301d5128becaec07cafcad1b7d3610e49f453d), - (0x207970fdc943d5b65689b132d27fdc46ed25c8d84042acf0e855c8bb00a60f2b, 0x364ad7be4b0b40da9d5df01c50967ee14cabc8bd669872613c1d62ad1f52f38b), - (0x19a1a3391e950797dbb98811f2ba3b4622147959449f9cb1c7f454aa047afe76, 0x079ae13ad5b0083006b06de42808f517d9797e5f42fc87a9947c761fa8784fea), - (0x08035a60101d47769ed0a30ce647c0e5d5c7850f1630247af48f351c7ac5b6e7, 0x3b0c43b451b947f7adbffa12d9e4c7ca94ac5c12eda34cee77b640f25a42d04b), - (0x116e9d6aef40f13742fb573a0779c99f5a12f59fab1246d64a55d94e3856800c, 0x0d595f9d79e749dbd9d69ca28b15f80a17b5312be520568e1f959f1b958bf1aa), - (0x3bf0f0b99e15ad38e2d9d5a9e12aa428f55db0cb878e058ea592eee7d16edfb4, 0x32a0e3bb91ab0ee8f25ab4d8f93782724cd68675e823e66369f0c6a36ece62d8), - (0x2cdb9602b74f420b08e5307df902d13340d3b1b53d081b110149e01d731dd862, 0x0b7b5bbb0b5b19148a410ce3c2625364660d100aad28542e75282ff7cc5926a7), - (0x20dc0d54e1617ea5a6251e447e06e8a98030d79b426bbe946fe960f85550efa8, 0x25f833bd3ee582088cf25891465c3908192d77eca169f8c7d3d373fd12c2fade), + (0x0a10cdf73732c92a9bfccca2a25375be5b665c4bec263a273de481f9cf0b5295, 0x3a00666c4f8b7e78be743934fcde87d488bed7562c7d9058e6216eb6c02d913f), + (0x3e39086d109bc5cacb5876df02e676d8a45de411fb6060582dfde9935d4c9eb5, 0x23b2462b03a2f4a16fc1a85afb3add387576544976a9a79d6d8fa7b6470e7433), + (0x0113540e4a2c0f5abdd94d0cac1560ae76e123321f2eb00ab54b2af05a342d24, 0x35c1e8432935ea039417295e65156588fc7073b51ff6295c698e6a80a3b54d8f), + (0x365d7cd6bfef5ffe3ad7a119137e07c833648fe14e705cb4a1cf8ee26ea1a20a, 0x18ee51fd1b2a568be36f26daaebcb86cc6938fd2d5e46f072bcc275ad709fded), + (0x39d1e52ce9c0cafc4c1a1626b1e0d8bf6a656cf8766f01f6e56fa9636d751c09, 0x3b5d5f81057a46a881474047ded09537dddb788eec68649b41d115bf97ef2a7a), + (0x2489c689eb055e5b8e7905aba42e69cf32ff72f53413a0aff1a21111b22754c0, 0x05fc261835cd944336ec75d4dd2e763693b68137f79838b7e68a144190c2142a), + (0x0be557c80085a65b612710201b738d5b78966eb79515355dab5a95fbfe486dc6, 0x0b658d0f6f39f59dbd4b422edcf73303176a8d5ff2b4126786cce72c1222bd69), + (0x3b9be0eb6f48b9b85d25517d30e5e97da5a888c9cc0440945dbaa62836a996c2, 0x15f297866cfc657bcd6f0e2214fbcb7443a3d6cf3acba1702220949539ed22bf), + (0x178fe0b2e7f7bf3008b0f2b3cf31c0cb4feee66e1a77ae310d81274e357eca08, 0x396df2ba8eb452acc143f2d240ef7d0f641cc2b9601ef2b25b5258e4107b663f), + (0x3972e2487754d8ccc6cfffa905f883c9c2338334894bd59e379a2be11b367df7, 0x2d64ca17acc3ae2a3948b80c2943a40137806607e979d43a834e66ae6e6913aa), + (0x135852e8c481f1e13f3facb7a11ffb358046ef6463757e69208f430652eda7e1, 0x3eccd189556c08b0cad7659259b7ab3336815134c1c1e26a1a55437d17d7fa93), + (0x3a4d8286e222f01440ecedf6873305351edccac685093cdc42395043a6838ebc, 0x19dace40c3d00ae4a842708359d5c2e4c67d1490676b601a57285297f94d290f), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit_proof_test_case.bin b/src/circuit_proof_test_case.bin index 97e15d58205d44afb2165e5137b7b4e81b843d4d..e64bc990c57fa43775d9c4cd66922d7c0f00d09d 100644 GIT binary patch literal 5283 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 literal 5283 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 diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 995b13693..09a7d45f4 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -77,8 +77,8 @@ impl NoteCommitment { NOTE_COMMITMENT_PERSONALIZATION, ); - let zec_hash_point = zec_domain.M.hash_to_point(zec_note_bits); - let zsa_hash_point = zsa_domain.M.hash_to_point(zsa_note_bits); + let zec_hash_point = zec_domain.hash_to_point(zec_note_bits); + let zsa_hash_point = zsa_domain.hash_to_point(zsa_note_bits); // Select the desired hash point in constant-time let hash_point = zsa_hash_point.and_then(|zsa_hash| { @@ -176,7 +176,7 @@ mod tests { // Evaluating the commitment in one step with `commit` or in two steps with `hash_to_point` // and `commit_from_hash_point` must give the same commitment. - let hash_point = domain_zsa.M.hash_to_point(msg.into_iter()); + let hash_point = domain_zsa.hash_to_point(msg.into_iter()); let commit_r_zsa = domain_zsa.commit_from_hash_point(hash_point, &rcm.0); assert_eq!(expected_commit.unwrap(), commit_r_zsa.unwrap()); From 344b647d54ce59a3cf3d48d3fbfc130b5fbf1493 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Fri, 22 Dec 2023 09:28:00 +0300 Subject: [PATCH 53/92] Update zcash_note_encryption dependency reference (#95) This PR updates the dependency reference for `zcash_note_encryption` in `orchard` crate's `Cargo.toml`. Instead of using `zcash_note_encryption` crate from the `librustzcash` repository, we are now referencing the crate from the newly separate `zcash_note_encryption` repository. Co-authored-by: Dmitry Demin --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 69165bdfc..e30cba95e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ reddsa = "0.5" nonempty = "0.7" serde = { version = "1.0", features = ["derive"] } subtle = "2.3" -zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/librustzcash", branch = "zsa1-zebra" } +zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1" } incrementalmerkletree = "0.5" # Logging @@ -57,7 +57,7 @@ criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" -zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/librustzcash", branch = "zsa1-zebra", features = ["pre-zip-212"] } +zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } [target.'cfg(unix)'.dev-dependencies] From 1a1f3e7caeb72710b095e4e8197df66a5a9a4e76 Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Wed, 31 Jan 2024 22:38:24 +0530 Subject: [PATCH 54/92] Changing the Issuance Authorization Signature to the BIP 340 Schnorr scheme (#93) This changes the issuance authorization signature from the redpallas signature scheme to the BIP 340 Schnorr signature scheme, as detailed in ZIP 227. --- Cargo.toml | 9 +- src/action.rs | 6 +- src/bundle.rs | 6 +- src/bundle/burn_validation.rs | 2 +- src/circuit.rs | 4 +- src/circuit/note_commit.rs | 2 +- src/circuit/value_commit_orchard.rs | 2 +- src/issuance.rs | 119 ++- src/keys.rs | 160 ++-- src/note.rs | 4 +- src/note/asset_base.rs | 15 +- src/supply_info.rs | 2 +- src/test_vectors.rs | 3 +- src/test_vectors/asset_base.rs | 1032 ++++++++++++++++++++++++ src/test_vectors/asset_id.rs | 1032 ------------------------ src/test_vectors/issuance_auth_sig.rs | 277 +++++++ src/test_vectors/keys.rs | 1038 ++++++++++++------------- src/value.rs | 8 +- tests/zsa.rs | 7 +- 19 files changed, 2005 insertions(+), 1723 deletions(-) create mode 100644 src/test_vectors/asset_base.rs delete mode 100644 src/test_vectors/asset_id.rs create mode 100644 src/test_vectors/issuance_auth_sig.rs diff --git a/Cargo.toml b/Cargo.toml index e30cba95e..74dae4945 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ group = { version = "0.13", features = ["wnaf-memuse"] } halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } hex = "0.4" +k256 = { version = "0.13.0", features = ["arithmetic", "schnorr"] } lazy_static = "1" memuse = { version = "0.2.1", features = ["nonempty"] } pasta_curves = "0.5" @@ -53,16 +54,18 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] bridgetree = "0.4" -criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 +criterion = "0.4" #Pinned: 0.5 depends on clap 4 which has MSRV 1.70 halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } hex = "0.4" proptest = "1.0.0" zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } +ahash = "=0.8.6" #Pinned: 0.8.7 depends on Rust 1.72 +half = "=2.2.1" #Pinned: 2.3.1 requires Rust 1.70 [target.'cfg(unix)'.dev-dependencies] -inferno = "0.11" -clap = "=4.2.0" # Used by inferno. Last version required rust 1.70 +inferno = "0.11" #Pinned +clap = "=4.2.0" #Pinned: Used by inferno. Later version requires Rust 1.70 pprof = { version = "0.11", features = ["criterion", "flamegraph"] } [lib] diff --git a/src/action.rs b/src/action.rs index c9e989c27..58b273f17 100644 --- a/src/action.rs +++ b/src/action.rs @@ -126,7 +126,7 @@ pub(crate) mod testing { use proptest::prelude::*; - use crate::note::asset_base::testing::arb_asset_id; + use crate::note::asset_base::testing::arb_asset_base; use crate::{ note::{ commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, @@ -147,7 +147,7 @@ pub(crate) mod testing { nf in arb_nullifier(), rk in arb_spendauth_verification_key(), note in arb_note(output_value), - asset in arb_asset_id() + asset in arb_asset_base() ) -> Action<()> { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( @@ -180,7 +180,7 @@ pub(crate) mod testing { note in arb_note(output_value), rng_seed in prop::array::uniform32(prop::num::u8::ANY), fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - asset in arb_asset_id() + asset in arb_asset_base() ) -> Action> { let cmx = ExtractedNoteCommitment::from(note.commitment()); let cv_net = ValueCommitment::derive( diff --git a/src/bundle.rs b/src/bundle.rs index f37011754..60cd3d75f 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -553,7 +553,7 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; pub use crate::action::testing::{arb_action, arb_unauthorized_action}; - use crate::note::asset_base::testing::arb_zsa_asset_id; + use crate::note::asset_base::testing::arb_zsa_asset_base; use crate::note::AssetBase; use crate::value::testing::arb_value_sum; @@ -619,10 +619,10 @@ pub mod testing { /// Create an arbitrary vector of assets to burn. pub fn arb_asset_to_burn() ( - asset_id in arb_zsa_asset_id(), + asset_base in arb_zsa_asset_base(), value in arb_value_sum() ) -> (AssetBase, ValueSum) { - (asset_id, value) + (asset_base, value) } } diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs index 0fdf35dd1..d8ef0ce81 100644 --- a/src/bundle/burn_validation.rs +++ b/src/bundle/burn_validation.rs @@ -83,7 +83,7 @@ mod tests { pub fn get_burn_tuple(asset_desc: &str, value: i64) -> (AssetBase, i64) { use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; - let isk = IssuanceAuthorizingKey::from_bytes([0u8; 32]).unwrap(); + let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); ( AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc), diff --git a/src/circuit.rs b/src/circuit.rs index 0199d281f..0134ead77 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1486,7 +1486,7 @@ mod tests { let asset_base = if is_native_asset { AssetBase::native() } else { - AssetBase::random(&mut rng) + AssetBase::random() }; // Create spent_note @@ -1578,7 +1578,7 @@ mod tests { pallas::Point::random(&mut rng).to_affine().to_bytes(), pallas::Point::random(&mut rng).to_affine().to_bytes(), NoteValue::from_raw(rng.next_u64()), - AssetBase::random(&mut rng), + AssetBase::random(), pallas::Base::random(&mut rng), pallas::Base::random(&mut rng), NoteCommitTrapdoor(pallas::Scalar::random(&mut rng)), diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index 934238e94..47d928fc0 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -2596,7 +2596,7 @@ mod tests { let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); let mut rng = OsRng; - let random_asset = AssetBase::random(&mut rng); + let random_asset = AssetBase::random(); // Test different values of `ak`, `nk` let mut circuits = vec![]; diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs index 4356ad583..d9871a5bc 100644 --- a/src/circuit/value_commit_orchard.rs +++ b/src/circuit/value_commit_orchard.rs @@ -305,7 +305,7 @@ mod tests { let mut circuits = vec![]; let mut instances = vec![]; let native_asset = AssetBase::native(); - let random_asset = AssetBase::random(&mut rng); + let random_asset = AssetBase::random(); for split_flag in [false, true] { for asset in [native_asset, random_asset] { let v_old = NoteValue::from_raw(rng.next_u64()); diff --git a/src/issuance.rs b/src/issuance.rs index 9fe38c82a..f2eec90c6 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -1,8 +1,9 @@ //! Structs related to issuance bundles and the associated logic. use blake2b_simd::Hash as Blake2bHash; use group::Group; +use k256::schnorr; use nonempty::NonEmpty; -use rand::{CryptoRng, RngCore}; +use rand::RngCore; use std::collections::HashSet; use std::fmt; @@ -15,13 +16,9 @@ use crate::issuance::Error::{ use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use crate::note::asset_base::is_asset_desc_of_valid_size; use crate::note::{AssetBase, Nullifier}; -use crate::primitives::redpallas::Signature; use crate::value::{NoteValue, ValueSum}; -use crate::{ - primitives::redpallas::{self, SpendAuth}, - Address, Note, -}; +use crate::{Address, Note}; use crate::supply_info::{AssetSupply, SupplyInfo}; @@ -183,19 +180,14 @@ pub struct Prepared { /// Marker for an authorized bundle. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Signed { - signature: redpallas::Signature, + signature: schnorr::Signature, } impl Signed { /// Returns the signature for this authorization. - pub fn signature(&self) -> &redpallas::Signature { + pub fn signature(&self) -> &schnorr::Signature { &self.signature } - - /// Constructs an `Signed` from its constituent parts. - pub fn from_parts(signature: Signature) -> Self { - Signed { signature } - } } impl IssueAuth for Unauthorized {} @@ -408,12 +400,8 @@ impl IssueBundle { impl IssueBundle { /// Sign the `IssueBundle`. - /// The call makes sure that the provided `isk` matches the `ik` and the driven `asset` for each note in the bundle. - pub fn sign( - self, - mut rng: R, - isk: &IssuanceAuthorizingKey, - ) -> Result, Error> { + /// The call makes sure that the provided `isk` matches the `ik` and the derived `asset` for each note in the bundle. + pub fn sign(self, isk: &IssuanceAuthorizingKey) -> Result, Error> { let expected_ik: IssuanceValidatingKey = (isk).into(); // Make sure the `expected_ik` matches the `asset` for all notes. @@ -422,12 +410,15 @@ impl IssueBundle { Ok(()) })?; + // Make sure the signature can be generated. + let signature = isk + .try_sign(&self.authorization.sighash) + .map_err(|_| IssueBundleInvalidSignature)?; + Ok(IssueBundle { ik: self.ik, actions: self.actions, - authorization: Signed { - signature: isk.sign(&mut rng, &self.authorization.sighash), - }, + authorization: Signed { signature }, }) } } @@ -501,7 +492,7 @@ pub fn verify_issue_bundle( bundle .ik .verify(&sighash, &bundle.authorization.signature) - .map_err(IssueBundleInvalidSignature)?; + .map_err(|_| IssueBundleInvalidSignature)?; let supply_info = bundle @@ -543,7 +534,7 @@ pub enum Error { /// Verification errors: /// Invalid signature. - IssueBundleInvalidSignature(reddsa::Error), + IssueBundleInvalidSignature, /// The provided `AssetBase` has been previously finalized. IssueActionPreviouslyFinalizedAssetBase(AssetBase), @@ -551,8 +542,6 @@ pub enum Error { ValueSumOverflow, } -impl std::error::Error for Error {} - impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -580,7 +569,7 @@ impl fmt::Display for Error { "the AssetBase is the identity point of the Pallas curve, which is invalid." ) } - IssueBundleInvalidSignature(_) => { + IssueBundleInvalidSignature => { write!(f, "invalid signature") } IssueActionPreviouslyFinalizedAssetBase(_) => { @@ -616,7 +605,6 @@ mod tests { use pasta_curves::pallas::{Point, Scalar}; use rand::rngs::OsRng; use rand::RngCore; - use reddsa::Error::InvalidSignature; use std::collections::HashSet; fn setup_params() -> ( @@ -628,7 +616,7 @@ mod tests { ) { let mut rng = OsRng; - let isk = IssuanceAuthorizingKey::random(&mut rng); + let isk = IssuanceAuthorizingKey::random(); let ik: IssuanceValidatingKey = (&isk).into(); let fvk = FullViewingKey::from(&SpendingKey::random(&mut rng)); @@ -684,12 +672,7 @@ mod tests { fn identity_point_test_params( note1_value: u64, note2_value: u64, - ) -> ( - OsRng, - IssuanceAuthorizingKey, - IssueBundle, - [u8; 32], - ) { + ) -> (IssuanceAuthorizingKey, IssueBundle, [u8; 32]) { let (mut rng, isk, ik, recipient, sighash) = setup_params(); let note1 = Note::new( @@ -713,7 +696,7 @@ mod tests { let bundle = IssueBundle::from_parts(ik, NonEmpty::new(action), Unauthorized); - (rng, isk, bundle, sighash) + (isk, bundle, sighash) } #[test] @@ -734,7 +717,7 @@ mod tests { #[test] fn verify_supply_invalid_for_asset_base_as_identity() { - let (_, _, bundle, _) = identity_point_test_params(10, 20); + let (_, bundle, _) = identity_point_test_params(10, 20); assert_eq!( bundle.actions.head.verify_supply(&bundle.ik), @@ -928,7 +911,7 @@ mod tests { ) .unwrap(); - let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let signed = bundle.prepare(sighash).sign(&isk).unwrap(); ik.verify(&sighash, &signed.authorization.signature) .expect("signature should be valid"); @@ -949,11 +932,11 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(&mut OsRng); + let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(); let err = bundle .prepare([0; 32]) - .sign(rng, &wrong_isk) + .sign(&wrong_isk) .expect_err("should not be able to sign"); assert_eq!(err, IssueBundleIkMismatchAssetBase); @@ -987,7 +970,7 @@ mod tests { let err = bundle .prepare([0; 32]) - .sign(rng, &isk) + .sign(&isk) .expect_err("should not be able to sign"); assert_eq!(err, IssueBundleIkMismatchAssetBase); @@ -1008,7 +991,7 @@ mod tests { ) .unwrap(); - let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &mut HashSet::new(); let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); @@ -1037,7 +1020,7 @@ mod tests { .finalize_action(String::from("Verify with finalize")) .unwrap(); - let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &mut HashSet::new(); let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); @@ -1102,7 +1085,7 @@ mod tests { ) .unwrap(); - let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &mut HashSet::new(); let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap(); @@ -1146,7 +1129,7 @@ mod tests { ) .unwrap(); - let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &mut HashSet::new(); let final_type = AssetBase::derive(&ik, &String::from("already final")); @@ -1168,7 +1151,7 @@ mod tests { } } - let (mut rng, isk, ik, recipient, sighash) = setup_params(); + let (rng, isk, ik, recipient, sighash) = setup_params(); let (bundle, _) = IssueBundle::new( ik, @@ -1181,19 +1164,19 @@ mod tests { ) .unwrap(); - let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(&mut rng); + let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(); - let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let mut signed = bundle.prepare(sighash).sign(&isk).unwrap(); signed.set_authorization(Signed { - signature: wrong_isk.sign(&mut rng, &sighash), + signature: wrong_isk.try_sign(&sighash).unwrap(), }); let prev_finalized = &HashSet::new(); assert_eq!( verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(), - IssueBundleInvalidSignature(InvalidSignature) + IssueBundleInvalidSignature ); } @@ -1212,12 +1195,12 @@ mod tests { .unwrap(); let sighash: [u8; 32] = bundle.commitment().into(); - let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &HashSet::new(); assert_eq!( verify_issue_bundle(&signed, random_sighash, prev_finalized).unwrap_err(), - IssueBundleInvalidSignature(InvalidSignature) + IssueBundleInvalidSignature ); } @@ -1236,7 +1219,7 @@ mod tests { ) .unwrap(); - let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let mut signed = bundle.prepare(sighash).sign(&isk).unwrap(); // Add "bad" note let note = Note::new( @@ -1274,9 +1257,9 @@ mod tests { ) .unwrap(); - let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let mut signed = bundle.prepare(sighash).sign(&isk).unwrap(); - let incorrect_isk = IssuanceAuthorizingKey::random(&mut rng); + let incorrect_isk = IssuanceAuthorizingKey::random(); let incorrect_ik: IssuanceValidatingKey = (&incorrect_isk).into(); // Add "bad" note @@ -1320,7 +1303,7 @@ mod tests { ) .unwrap(); - let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap(); + let mut signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = HashSet::new(); // 1. Try too long description @@ -1345,23 +1328,23 @@ mod tests { #[test] fn issue_bundle_cannot_be_signed_with_asset_base_identity_point() { - let (rng, isk, bundle, sighash) = identity_point_test_params(10, 20); + let (isk, bundle, sighash) = identity_point_test_params(10, 20); assert_eq!( - bundle.prepare(sighash).sign(rng, &isk).unwrap_err(), + bundle.prepare(sighash).sign(&isk).unwrap_err(), AssetBaseCannotBeIdentityPoint ); } #[test] fn issue_bundle_verify_fail_asset_base_identity_point() { - let (mut rng, isk, bundle, sighash) = identity_point_test_params(10, 20); + let (isk, bundle, sighash) = identity_point_test_params(10, 20); let signed = IssueBundle { ik: bundle.ik, actions: bundle.actions, authorization: Signed { - signature: isk.sign(&mut rng, &sighash), + signature: isk.try_sign(&sighash).unwrap(), }, }; @@ -1398,24 +1381,20 @@ mod tests { pub mod testing { use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized}; use crate::keys::testing::arb_issuance_validating_key; - use crate::note::asset_base::testing::zsa_asset_id; + use crate::note::asset_base::testing::zsa_asset_base; use crate::note::testing::arb_zsa_note; - use crate::primitives::redpallas::Signature; + use k256::schnorr; use nonempty::NonEmpty; use proptest::collection::vec; use proptest::prelude::*; use proptest::prop_compose; - use reddsa::orchard::SpendAuth; prop_compose! { /// Generate a uniformly distributed signature pub(crate) fn arb_signature()( - half_bytes in prop::array::uniform32(prop::num::u8::ANY) - ) -> Signature { - // prop::array can only generate 32 elements max, so we duplicate it - let sig_bytes: [u8; 64] = [half_bytes, half_bytes].concat().try_into().unwrap(); - let sig: Signature = Signature::from(sig_bytes); - sig + sig_bytes in vec(prop::num::u8::ANY, 64) + ) -> schnorr::Signature { + schnorr::Signature::try_from(sig_bytes.as_slice()).unwrap() } } @@ -1423,7 +1402,7 @@ pub mod testing { /// Generate an issue action pub fn arb_issue_action(asset_desc: String) ( - asset in zsa_asset_id(asset_desc.clone()), + asset in zsa_asset_base(asset_desc.clone()), ) ( note in arb_zsa_note(asset), diff --git a/src/keys.rs b/src/keys.rs index 4748bebdc..418c57413 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,7 +1,10 @@ //! Key structures for Orchard. use core::mem; -use std::io::{self, Read, Write}; +use std::{ + fmt::{Debug, Formatter}, + io::{self, Read, Write}, +}; use aes::Aes256; use blake2b_simd::{Hash as Blake2bHash, Params}; @@ -11,8 +14,16 @@ use group::{ prime::PrimeCurveAffine, Curve, GroupEncoding, }; +use k256::{ + schnorr, + schnorr::{ + signature::hazmat::{PrehashSigner, PrehashVerifier}, + Signature, VerifyingKey, + }, + NonZeroScalar, +}; use pasta_curves::{pallas, pallas::Scalar}; -use rand::{CryptoRng, RngCore}; +use rand::{rngs::OsRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_note_encryption_zsa::EphemeralKeyBytes; @@ -218,28 +229,13 @@ fn check_structural_validity( } } -/// We currently use `SpendAuth` as the `IssuanceAuth`. -type IssuanceAuth = SpendAuth; - /// An issuance key, from which all key material is derived. /// /// $\mathsf{isk}$ as defined in [ZIP 227][issuancekeycomponents]. /// /// [issuancekeycomponents]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation -#[derive(Debug, Copy, Clone)] -pub struct IssuanceAuthorizingKey([u8; 32]); - -impl From for IssuanceAuthorizingKey { - fn from(sk: SpendingKey) -> Self { - IssuanceAuthorizingKey(*sk.to_bytes()) - } -} - -impl ConstantTimeEq for IssuanceAuthorizingKey { - fn ct_eq(&self, other: &Self) -> Choice { - self.to_bytes().ct_eq(other.to_bytes()) - } -} +#[derive(Copy, Clone)] +pub struct IssuanceAuthorizingKey(NonZeroScalar); impl IssuanceAuthorizingKey { /// Generates a random issuance key. @@ -248,21 +244,23 @@ impl IssuanceAuthorizingKey { /// Real issuance keys should be derived according to [ZIP 32]. /// /// [ZIP 32]: https://zips.z.cash/zip-0032 - pub(crate) fn random(rng: &mut impl RngCore) -> Self { - SpendingKey::random(rng).into() + pub(crate) fn random() -> Self { + IssuanceAuthorizingKey(NonZeroScalar::random(&mut OsRng)) } /// Constructs an Orchard issuance key from uniformly-random bytes. /// /// Returns `None` if the bytes do not correspond to a valid Orchard issuance key. - pub fn from_bytes(isk_bytes: [u8; 32]) -> CtOption { - let isk = IssuanceAuthorizingKey(isk_bytes); - CtOption::new(isk, 1u8.into()) + pub fn from_bytes(isk_bytes: [u8; 32]) -> Option { + NonZeroScalar::try_from(&isk_bytes as &[u8]) + .ok() + .map(IssuanceAuthorizingKey) } /// Returns the raw bytes of the issuance key. - pub fn to_bytes(&self) -> &[u8; 32] { - &self.0 + /// Unwrap call never fails since the issuance authorizing key is exactly 32 bytes. + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes().try_into().unwrap() } /// Derives the Orchard-ZSA issuance key for the given seed, coin type, and account. @@ -277,81 +275,74 @@ impl IssuanceAuthorizingKey { ChildIndex::try_from(coin_type)?, ChildIndex::try_from(account)?, ]; - ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE) - .map(|esk| esk.sk().into()) - } - /// Derives the RedPallas signing key from isk. Internal use only, does not enforce all constraints. - fn derive_inner(&self) -> pallas::Scalar { - to_scalar(PrfExpand::ZsaIsk.expand(&self.0)) + // we are reusing zip32 logic for deriving the key, zip32 should be updated as discussed + let &isk_bytes = + ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE)? + .sk() + .to_bytes(); + + IssuanceAuthorizingKey::from_bytes(isk_bytes).ok_or(zip32::Error::InvalidSpendingKey) } /// Sign the provided message using the `IssuanceAuthorizingKey`. - pub fn sign( - &self, - rng: &mut (impl RngCore + CryptoRng), - msg: &[u8], - ) -> redpallas::Signature { - conditionally_negate(self.derive_inner()).sign(rng, msg) + /// Only supports signing of messages of length 32 bytes, since we will only be using it to sign 32 byte SIGHASH values. + pub fn try_sign(&self, msg: &[u8; 32]) -> Result { + schnorr::SigningKey::from(self.0).sign_prehash(msg) + } +} + +impl Debug for IssuanceAuthorizingKey { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("IssuanceAuthorizingKey") + .field(&self.0.to_bytes()) + .finish() } } /// A key used to validate issuance authorization signatures. /// /// Defined in [ZIP 227: Issuance of Zcash Shielded Assets § Issuance Key Generation][IssuanceZSA]. -/// Note that this is $\mathsf{ik}^\mathbb{P}$, which by construction is equivalent to -/// $\mathsf{ik}$ but stored here as a RedPallas verification key. /// /// [IssuanceZSA]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation -#[derive(Debug, Clone, PartialOrd, Ord)] -pub struct IssuanceValidatingKey(VerificationKey); +#[derive(Debug, Clone)] +pub struct IssuanceValidatingKey(schnorr::VerifyingKey); impl From<&IssuanceAuthorizingKey> for IssuanceValidatingKey { fn from(isk: &IssuanceAuthorizingKey) -> Self { - IssuanceValidatingKey((&(conditionally_negate(isk.derive_inner()))).into()) - } -} - -impl From<&IssuanceValidatingKey> for pallas::Point { - fn from(issuance_validating_key: &IssuanceValidatingKey) -> pallas::Point { - pallas::Point::from_bytes(&(&issuance_validating_key.0).into()).unwrap() + IssuanceValidatingKey(*schnorr::SigningKey::from(isk.0).verifying_key()) } } impl PartialEq for IssuanceValidatingKey { fn eq(&self, other: &Self) -> bool { - <[u8; 32]>::from(&self.0).eq(&<[u8; 32]>::from(&other.0)) + self.to_bytes().eq(&other.to_bytes()) } } impl Eq for IssuanceValidatingKey {} impl IssuanceValidatingKey { - /// Converts this spend validating key to its serialized form, - /// I2LEOSP_256(ik). + /// Converts this issuance validating key to its serialized form, + /// in big-endian order as defined in BIP 340. + /// Unwrap call never fails since the issuance validating key is exactly 32 bytes. pub fn to_bytes(&self) -> [u8; 32] { - // This is correct because the wrapped point must have ỹ = 0, and - // so the point repr is the same as I2LEOSP of its x-coordinate. - <[u8; 32]>::from(&self.0) + self.0.to_bytes().try_into().unwrap() } - /// Constructs an Orchard issuance validating key from uniformly-random bytes. + /// Constructs an Orchard issuance validating key from the provided bytes. + /// The bytes are assumed to be encoded in big-endian order. /// /// Returns `None` if the bytes do not correspond to a valid key. pub fn from_bytes(bytes: &[u8]) -> Option { - <[u8; 32]>::try_from(bytes) + VerifyingKey::from_bytes(bytes) .ok() - .and_then(check_structural_validity) .map(IssuanceValidatingKey) } /// Verifies a purported `signature` over `msg` made by this verification key. - pub fn verify( - &self, - msg: &[u8], - signature: &redpallas::Signature, - ) -> Result<(), reddsa::Error> { - self.0.verify(msg, signature) + pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), schnorr::Error> { + self.0.verify_prehash(msg, signature) } } @@ -1118,8 +1109,8 @@ pub mod testing { key in prop::array::uniform32(prop::num::u8::ANY) .prop_map(IssuanceAuthorizingKey::from_bytes) .prop_filter( - "Values must correspond to valid Orchard issuance keys.", - |opt| bool::from(opt.is_some()) + "Values must correspond to valid Orchard-ZSA issuance keys.", + |opt| opt.is_some() ) ) -> IssuanceAuthorizingKey { key.unwrap() @@ -1198,6 +1189,21 @@ mod tests { )); } + #[test] + fn issuance_authorizing_key_from_bytes_fail_on_zero() { + // isk must not be the zero scalar. + let isk = IssuanceAuthorizingKey::from_bytes([0; 32]); + assert!(isk.is_none()); + } + + #[test] + fn issuance_authorizing_key_from_bytes_to_bytes_roundtrip() { + let isk = IssuanceAuthorizingKey::random(); + let isk_bytes = isk.to_bytes(); + let isk_roundtrip = IssuanceAuthorizingKey::from_bytes(isk_bytes).unwrap(); + assert_eq!(isk_bytes, isk_roundtrip.to_bytes()); + } + proptest! { #[test] fn key_agreement( @@ -1235,13 +1241,13 @@ mod tests { let ask: SpendAuthorizingKey = (&sk).into(); assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask); - let isk = IssuanceAuthorizingKey::from_bytes(tv.sk).unwrap(); + let isk = IssuanceAuthorizingKey::from_bytes(tv.isk).unwrap(); let ak: SpendValidatingKey = (&ask).into(); assert_eq!(<[u8; 32]>::from(ak.0), tv.ak); let ik: IssuanceValidatingKey = (&isk).into(); - assert_eq!(<[u8; 32]>::from(ik.0), tv.ik); + assert_eq!(ik.to_bytes(), tv.ik); let nk: NullifierDerivingKey = (&sk).into(); assert_eq!(nk.0.to_repr(), tv.nk); @@ -1288,4 +1294,22 @@ mod tests { assert_eq!(internal_ovk.0, tv.internal_ovk); } } + + #[test] + fn issuance_auth_sig_test_vectors() { + for tv in crate::test_vectors::issuance_auth_sig::test_vectors() { + let isk = IssuanceAuthorizingKey::from_bytes(tv.isk).unwrap(); + + let ik = IssuanceValidatingKey::from(&isk); + assert_eq!(ik.to_bytes(), tv.ik); + + let message = tv.msg; + + let signature = isk.try_sign(&message).unwrap(); + let sig_bytes: [u8; 64] = signature.to_bytes(); + assert_eq!(sig_bytes, tv.sig); + + assert!(ik.verify(&message, &signature).is_ok()); + } + } } diff --git a/src/note.rs b/src/note.rs index 61a9f9a99..ca2e83e11 100644 --- a/src/note.rs +++ b/src/note.rs @@ -334,7 +334,7 @@ impl fmt::Debug for TransmittedNoteCiphertext { pub mod testing { use proptest::prelude::*; - use crate::note::asset_base::testing::arb_asset_id; + use crate::note::asset_base::testing::arb_asset_base; use crate::note::AssetBase; use crate::value::testing::arb_note_value; use crate::{ @@ -358,7 +358,7 @@ pub mod testing { recipient in arb_address(), rho in arb_nullifier(), rseed in arb_rseed(), - asset in arb_asset_id(), + asset in arb_asset_base(), ) -> Note { Note { recipient, diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index ba8c80825..6856bee74 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -2,7 +2,6 @@ use blake2b_simd::{Hash as Blake2bHash, Params}; use group::{Group, GroupEncoding}; use halo2_proofs::arithmetic::CurveExt; use pasta_curves::pallas; -use rand::RngCore; use std::hash::{Hash, Hasher}; use subtle::{Choice, ConstantTimeEq, CtOption}; @@ -101,8 +100,8 @@ impl AssetBase { /// Generates a ZSA random asset. /// /// This is only used in tests. - pub(crate) fn random(rng: &mut impl RngCore) -> Self { - let isk = IssuanceAuthorizingKey::random(rng); + pub(crate) fn random() -> Self { + let isk = IssuanceAuthorizingKey::random(); let ik = IssuanceValidatingKey::from(&isk); let asset_descr = "zsa_asset"; AssetBase::derive(&ik, asset_descr) @@ -139,7 +138,7 @@ pub mod testing { prop_compose! { /// Generate a uniformly distributed note type - pub fn arb_asset_id()( + pub fn arb_asset_base()( is_native in prop::bool::ANY, isk in arb_issuance_authorizing_key(), str in "[A-Za-z]{255}", @@ -154,7 +153,7 @@ pub mod testing { prop_compose! { /// Generate the native note type - pub fn native_asset_id()(_i in 0..10) -> AssetBase { + pub fn native_asset_base()(_i in 0..10) -> AssetBase { // TODO: remove _i AssetBase::native() } @@ -162,7 +161,7 @@ pub mod testing { prop_compose! { /// Generate an asset ID - pub fn arb_zsa_asset_id()( + pub fn arb_zsa_asset_base()( isk in arb_issuance_authorizing_key(), str in "[A-Za-z]{255}" ) -> AssetBase { @@ -172,7 +171,7 @@ pub mod testing { prop_compose! { /// Generate an asset ID using a specific description - pub fn zsa_asset_id(asset_desc: String)( + pub fn zsa_asset_base(asset_desc: String)( isk in arb_issuance_authorizing_key(), ) -> AssetBase { assert!(super::is_asset_desc_of_valid_size(&asset_desc)); @@ -182,7 +181,7 @@ pub mod testing { #[test] fn test_vectors() { - let test_vectors = crate::test_vectors::asset_id::test_vectors(); + let test_vectors = crate::test_vectors::asset_base::test_vectors(); for tv in test_vectors { let description = std::str::from_utf8(&tv.description).unwrap(); diff --git a/src/supply_info.rs b/src/supply_info.rs index 1752fbd64..1e3c8d28f 100644 --- a/src/supply_info.rs +++ b/src/supply_info.rs @@ -82,7 +82,7 @@ mod tests { fn create_test_asset(asset_desc: &str) -> AssetBase { use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; - let isk = IssuanceAuthorizingKey::from_bytes([0u8; 32]).unwrap(); + let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc) } diff --git a/src/test_vectors.rs b/src/test_vectors.rs index 945cfc2b7..3cea120cd 100644 --- a/src/test_vectors.rs +++ b/src/test_vectors.rs @@ -1,5 +1,6 @@ -pub(crate) mod asset_id; +pub(crate) mod asset_base; pub(crate) mod commitment_tree; +pub(crate) mod issuance_auth_sig; pub(crate) mod keys; pub(crate) mod merkle_path; pub(crate) mod note_encryption; diff --git a/src/test_vectors/asset_base.rs b/src/test_vectors/asset_base.rs new file mode 100644 index 000000000..041d80471 --- /dev/null +++ b/src/test_vectors/asset_base.rs @@ -0,0 +1,1032 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_asset_base) + +pub(crate) struct TestVector { + pub(crate) key: [u8; 32], + pub(crate) description: [u8; 512], + pub(crate) asset_base: [u8; 32], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + key: [ + 0x16, 0x88, 0x4f, 0x1d, 0xbc, 0x92, 0x90, 0x89, 0xa4, 0x17, 0x6e, 0x84, 0x0b, 0xb5, + 0x81, 0xc8, 0x0e, 0x16, 0xe9, 0xb1, 0xab, 0xd6, 0x54, 0xe6, 0x2c, 0x8b, 0x0b, 0x95, + 0x70, 0x20, 0xb7, 0x48, + ], + description: [ + 0x31, 0xc3, 0x85, 0xc7, 0xa7, 0x38, 0xc6, 0x88, 0x66, 0xc7, 0x8d, 0xc6, 0xa9, 0xc7, + 0xae, 0xc5, 0xb7, 0xc3, 0xaf, 0xc6, 0x85, 0xc7, 0x9f, 0xc6, 0x88, 0xe2, 0xb1, 0xbc, + 0xe1, 0x9a, 0xb7, 0xc3, 0x8c, 0xc7, 0x86, 0xc5, 0xbd, 0xc9, 0x80, 0xc3, 0x84, 0x4e, + 0x76, 0xc6, 0xa9, 0xc3, 0x91, 0x32, 0xc4, 0xab, 0xc9, 0x81, 0xce, 0x8c, 0xc4, 0xa7, + 0xc5, 0x97, 0xc6, 0xa6, 0xc4, 0xb3, 0xc5, 0xaa, 0xc7, 0x95, 0xc8, 0x99, 0xe1, 0x9b, + 0x91, 0xe1, 0x9a, 0xb5, 0xc7, 0x83, 0xc2, 0xa9, 0xc7, 0x80, 0xc7, 0xa5, 0xc8, 0x9d, + 0xce, 0x88, 0xc9, 0x8a, 0xc5, 0x92, 0xc7, 0x91, 0x5d, 0xc3, 0x93, 0x43, 0xc4, 0xa9, + 0xc8, 0x82, 0x25, 0xc3, 0xbb, 0xc3, 0x9d, 0xc8, 0xaf, 0xe1, 0x9a, 0xa5, 0xc8, 0xa0, + 0xc8, 0x8c, 0xc6, 0x86, 0xc3, 0xa4, 0xe1, 0x9b, 0x80, 0xc4, 0xbc, 0xc6, 0xb3, 0xc5, + 0x81, 0xe1, 0x9b, 0x97, 0xc5, 0x8e, 0xc8, 0x9d, 0xc6, 0xa1, 0xce, 0x8a, 0xc7, 0x88, + 0xc6, 0xb5, 0xc8, 0x83, 0xc3, 0xa2, 0xc4, 0x92, 0xc5, 0xb0, 0xc3, 0x8f, 0xc7, 0xab, + 0xe1, 0x9a, 0xac, 0xc2, 0xaf, 0xc7, 0x8a, 0x37, 0x72, 0x74, 0xe2, 0xb1, 0xbb, 0xc5, + 0x83, 0xe1, 0x9a, 0xa9, 0xe2, 0xb1, 0xa5, 0x5c, 0xc3, 0xbd, 0xc3, 0x88, 0xc9, 0x86, + 0x77, 0xc2, 0xb1, 0xc5, 0x9d, 0xc7, 0xa4, 0xc8, 0x9b, 0xcd, 0xb4, 0xc7, 0x81, 0xc4, + 0x9c, 0xc2, 0xbe, 0xe2, 0xb1, 0xa9, 0xc8, 0x82, 0xc6, 0xa0, 0xe1, 0x9a, 0xb5, 0xc2, + 0xa8, 0xc5, 0x82, 0xc3, 0x9a, 0xc6, 0xac, 0xc4, 0xa0, 0xc4, 0xb5, 0xc8, 0x93, 0xe2, + 0xb1, 0xa0, 0xc3, 0xbe, 0xc9, 0x84, 0x77, 0xc4, 0xb4, 0xc8, 0xbe, 0x5c, 0xc6, 0xbe, + 0xc3, 0xb0, 0xc9, 0x84, 0x28, 0xc6, 0x8d, 0xc3, 0xb2, 0xc8, 0xaa, 0xc8, 0x8f, 0xc8, + 0xb2, 0xc7, 0x8b, 0xcd, 0xba, 0xc3, 0xb5, 0xc9, 0x8e, 0xc4, 0xb4, 0xe2, 0xb1, 0xaa, + 0xe1, 0x9a, 0xab, 0xc2, 0xbd, 0xc8, 0xac, 0xc7, 0x8e, 0xc8, 0x95, 0xc2, 0xa9, 0xe1, + 0x9a, 0xa2, 0xe1, 0x9b, 0x8b, 0xc7, 0x98, 0xc6, 0x94, 0xe1, 0x9b, 0x9f, 0xc5, 0x98, + 0xc4, 0xbd, 0x39, 0x40, 0xc8, 0xa9, 0xc5, 0x94, 0x53, 0xe1, 0x9b, 0xac, 0xc8, 0xa0, + 0xc5, 0xb3, 0x76, 0x74, 0xc8, 0xa3, 0xc3, 0x81, 0x68, 0xcd, 0xbc, 0xc7, 0xba, 0x6e, + 0x73, 0xc5, 0x8f, 0xce, 0x8c, 0xc7, 0x9d, 0xc5, 0xaf, 0x45, 0xc3, 0xb0, 0xc3, 0x86, + 0xc4, 0x91, 0xc8, 0x94, 0xc5, 0x93, 0xc4, 0x81, 0xe2, 0xb1, 0xa1, 0xc7, 0x92, 0xc4, + 0xb0, 0xc8, 0x87, 0x4e, 0x51, 0xc6, 0xab, 0xc4, 0xb2, 0xe1, 0x9b, 0x8d, 0xc4, 0x8a, + 0xc4, 0xa9, 0xc3, 0xb3, 0xe1, 0x9b, 0x8f, 0xce, 0x8a, 0x3b, 0xc7, 0xa9, 0xc5, 0x9c, + 0x45, 0xe2, 0xb1, 0xab, 0xc6, 0xbc, 0xc2, 0xb5, 0xe1, 0x9b, 0x8d, 0xc4, 0x84, 0xe2, + 0xb1, 0xa8, 0xc7, 0xa9, 0xc6, 0x94, 0xc6, 0xa6, 0xc6, 0xba, 0xe1, 0x9b, 0xab, 0xc2, + 0xac, 0xc4, 0x8e, 0xe2, 0xb1, 0xb9, 0xc2, 0xb0, 0xce, 0x88, 0xc5, 0xb7, 0x70, 0xe2, + 0xb1, 0xac, 0xce, 0x86, 0x54, 0xc9, 0x8d, 0xc4, 0xa6, 0xcd, 0xb7, 0xc4, 0xaf, 0x75, + 0x3b, 0x3f, 0xc6, 0x81, 0xc8, 0xab, 0xc8, 0xa4, 0x78, 0xc8, 0xab, 0xc4, 0xbb, 0x2e, + 0xc8, 0x89, 0xc3, 0xb0, 0xc5, 0x90, 0x74, 0xc2, 0xa8, 0xc4, 0xa4, 0xc5, 0xbf, 0xe1, + 0x9a, 0xb2, 0xc2, 0xbc, 0x4b, 0xc6, 0xbf, 0xc7, 0xbc, 0xc7, 0xa5, 0xc3, 0xba, 0xc3, + 0x86, 0xc4, 0xb4, 0xc8, 0xa4, 0xc3, 0x9c, 0xe2, 0xb1, 0xb0, 0xc5, 0x92, 0xc4, 0x97, + 0xe1, 0x9b, 0xaa, 0xc6, 0xbf, 0xc5, 0x9e, 0xc7, 0x84, 0xc4, 0xaf, 0xc8, 0xaa, 0xc8, + 0x89, 0xc4, 0xb3, 0xc2, 0xbb, 0xc4, 0x97, 0x5a, + ], + asset_base: [ + 0x41, 0xb7, 0x75, 0x0a, 0x66, 0x59, 0xb2, 0xc8, 0x0f, 0x56, 0x7d, 0x67, 0x78, 0xd1, + 0x2d, 0x81, 0xc4, 0x7a, 0x46, 0xef, 0xdf, 0xfb, 0x63, 0x80, 0x6c, 0x01, 0x7c, 0xa5, + 0x61, 0x50, 0xa7, 0xa6, + ], + }, + TestVector { + key: [ + 0x72, 0x73, 0xb6, 0x57, 0xd9, 0x71, 0xa4, 0x5e, 0x72, 0x24, 0x0c, 0x7a, 0xaa, 0xa7, + 0xd0, 0x68, 0x5d, 0x06, 0xd7, 0x99, 0x9b, 0x0a, 0x19, 0xc4, 0xce, 0xa3, 0x27, 0x88, + 0xa6, 0xab, 0x51, 0x3d, + ], + description: [ + 0xc5, 0x96, 0xc6, 0xac, 0xc4, 0xb3, 0x28, 0x5f, 0xc2, 0xa5, 0x66, 0xe1, 0x9b, 0x8c, + 0xc8, 0xa5, 0xc3, 0x95, 0xc4, 0xaa, 0xc3, 0xa9, 0xc2, 0xbd, 0xe2, 0xb1, 0xbb, 0x52, + 0x48, 0xe1, 0x9b, 0x9f, 0xe2, 0xb1, 0xaf, 0xe1, 0x9b, 0x87, 0xc7, 0x9f, 0x2b, 0xe1, + 0x9a, 0xab, 0xc6, 0x97, 0x6b, 0xc8, 0x8e, 0xe1, 0x9a, 0xbb, 0xc6, 0xa0, 0xc7, 0x89, + 0xc2, 0xbd, 0xc8, 0xad, 0xc4, 0xbe, 0xe1, 0x9b, 0x82, 0xc8, 0x9c, 0xe1, 0x9a, 0xac, + 0x3f, 0xe1, 0x9a, 0xa2, 0xc9, 0x8c, 0xe1, 0x9a, 0xa2, 0xe1, 0x9b, 0x86, 0xc5, 0x9d, + 0xc4, 0xb4, 0xc7, 0x80, 0xc3, 0xb5, 0x71, 0x6b, 0x6c, 0xc8, 0x96, 0xc7, 0xbb, 0xc8, + 0x9a, 0xc7, 0x90, 0xc2, 0xb1, 0xc4, 0x89, 0xc3, 0x99, 0xc3, 0xbd, 0xc7, 0xae, 0xc2, + 0xa3, 0xc4, 0xa7, 0x58, 0xc4, 0x80, 0xc4, 0x9f, 0xc7, 0xbb, 0xc4, 0x8b, 0xc6, 0x8d, + 0xc5, 0x98, 0xc2, 0xb4, 0xc5, 0x93, 0xc4, 0x9c, 0xc8, 0x83, 0xc7, 0xbc, 0x30, 0xc4, + 0x87, 0xc3, 0x85, 0xe1, 0x9a, 0xb2, 0xc4, 0xa8, 0xc7, 0xb8, 0xc6, 0xab, 0x36, 0xc4, + 0xa6, 0x3b, 0xc7, 0xa3, 0xc7, 0x82, 0xcd, 0xb2, 0xc7, 0x80, 0xc3, 0xb0, 0xc2, 0xbd, + 0xe2, 0xb1, 0xb4, 0xc6, 0x93, 0xc4, 0x8f, 0x5d, 0xc6, 0x8f, 0x35, 0xc9, 0x85, 0xe1, + 0x9b, 0x95, 0xc7, 0xa4, 0xe2, 0xb1, 0xbf, 0xc4, 0x85, 0xc5, 0xa4, 0xc7, 0x83, 0xc8, + 0x81, 0xc8, 0x89, 0xc8, 0x98, 0xc5, 0xac, 0xe2, 0xb1, 0xb4, 0xc8, 0x8a, 0xc7, 0xa1, + 0xc7, 0x9d, 0xc6, 0xae, 0xc6, 0x9c, 0xc6, 0x98, 0xc3, 0xa3, 0xc4, 0x9b, 0x43, 0xe1, + 0x9b, 0x82, 0xc2, 0xa3, 0xc3, 0xa6, 0xc5, 0x85, 0xc8, 0x89, 0xe1, 0x9b, 0x99, 0x5f, + 0xc4, 0xa9, 0xe1, 0x9b, 0x95, 0xc2, 0xb7, 0xc3, 0x89, 0xe2, 0xb1, 0xb7, 0xc4, 0x96, + 0xe2, 0xb1, 0xa2, 0x5b, 0xc3, 0xac, 0x58, 0xc6, 0xa9, 0xcd, 0xbd, 0xc8, 0xa1, 0xe2, + 0xb1, 0xa6, 0xc8, 0x8e, 0xc5, 0xb3, 0xc7, 0x93, 0xc6, 0xa1, 0xc9, 0x8d, 0xc5, 0xa2, + 0x29, 0xce, 0x8c, 0xe1, 0x9b, 0x99, 0xc5, 0xaf, 0xc8, 0xbd, 0x2b, 0xc7, 0xb2, 0xc7, + 0xba, 0xcd, 0xb7, 0xc2, 0xbc, 0xe1, 0x9b, 0xa4, 0xc7, 0xb9, 0xc3, 0x8d, 0xe2, 0xb1, + 0xa0, 0xc2, 0xa4, 0xc8, 0x98, 0xc8, 0xa4, 0x49, 0xc5, 0xbb, 0xc3, 0x96, 0xc3, 0x94, + 0x5c, 0xc5, 0x8e, 0xe2, 0xb1, 0xae, 0x73, 0x74, 0xc6, 0xab, 0xc7, 0x86, 0xe2, 0xb1, + 0xb3, 0xe1, 0x9b, 0x8f, 0xc8, 0xb3, 0xc4, 0xa6, 0xc6, 0xb2, 0xc8, 0xa4, 0xc7, 0x86, + 0xc7, 0xa8, 0xe1, 0x9b, 0xa2, 0xc8, 0xaa, 0xc4, 0x92, 0xcd, 0xb2, 0x7e, 0xc9, 0x8d, + 0x4e, 0x45, 0xc6, 0x8a, 0xc6, 0xae, 0xc4, 0x8d, 0x3f, 0x59, 0xc5, 0x96, 0xe2, 0xb1, + 0xbd, 0xe1, 0x9a, 0xbc, 0xc3, 0x90, 0xc8, 0x8e, 0xc3, 0xa1, 0xc7, 0xad, 0xe1, 0x9a, + 0xb9, 0xc5, 0x8e, 0xe1, 0x9b, 0xa5, 0xe1, 0x9a, 0xb5, 0xc6, 0x83, 0xc7, 0x8e, 0xc8, + 0xbf, 0xc2, 0xbc, 0xc5, 0x8a, 0xc4, 0x8e, 0xcd, 0xb5, 0xc5, 0x97, 0xc4, 0x8f, 0xc2, + 0xaa, 0xc7, 0xaf, 0xc3, 0xbb, 0xc2, 0xa2, 0x49, 0x32, 0xc7, 0xa9, 0xc2, 0xb4, 0xe1, + 0x9b, 0xa1, 0xe1, 0x9b, 0xa3, 0xe2, 0xb1, 0xbf, 0x53, 0xc8, 0x96, 0xc8, 0xac, 0xc8, + 0xa3, 0xc3, 0xa0, 0x29, 0xe1, 0x9b, 0x89, 0xc5, 0xb3, 0xc6, 0xb2, 0xc3, 0xab, 0xc3, + 0x99, 0xc4, 0x9d, 0xc6, 0xb6, 0xc4, 0xa3, 0x3b, 0xe1, 0x9b, 0xa6, 0xc6, 0x95, 0xe1, + 0x9b, 0xa5, 0xc2, 0xbc, 0xc7, 0xa0, 0xc7, 0xa3, 0xe1, 0x9b, 0x8a, 0xc4, 0xb4, 0xc9, + 0x80, 0x64, 0x6f, 0xc6, 0x9e, 0xc4, 0x94, 0xc8, 0x8c, 0xc6, 0xa4, 0xc7, 0x96, 0xc3, + 0x9b, 0xc7, 0x91, 0xc5, 0x9d, 0x6d, 0xc7, 0x8a, + ], + asset_base: [ + 0xea, 0x1b, 0xf2, 0x91, 0x8d, 0xe2, 0xfb, 0x1a, 0x26, 0x10, 0x83, 0x25, 0x20, 0xbd, + 0x80, 0x71, 0x98, 0xe1, 0x26, 0x73, 0xab, 0xd2, 0x3b, 0x24, 0x1d, 0xba, 0x06, 0x08, + 0x20, 0x2e, 0x56, 0x17, + ], + }, + TestVector { + key: [ + 0xec, 0x05, 0xbb, 0x7f, 0x06, 0x5e, 0x25, 0x6f, 0xf4, 0x54, 0xf8, 0xa8, 0xdf, 0x6f, + 0x2f, 0x9b, 0x8a, 0x8c, 0x95, 0x08, 0xca, 0xac, 0xfe, 0xe9, 0x52, 0x1c, 0xbe, 0x68, + 0x9d, 0xd1, 0x12, 0x0f, + ], + description: [ + 0xc7, 0x82, 0x7e, 0xc5, 0xb9, 0xc6, 0xa6, 0xc5, 0xa3, 0xe1, 0x9a, 0xae, 0xe2, 0xb1, + 0xa6, 0xc8, 0xb2, 0xc8, 0xbc, 0xc5, 0x9f, 0xc8, 0x83, 0xc3, 0x82, 0xc4, 0x9a, 0xe2, + 0xb1, 0xa8, 0xc4, 0x88, 0xe2, 0xb1, 0xad, 0xc8, 0x98, 0xc3, 0xbb, 0xc3, 0x92, 0xc4, + 0xb7, 0xc7, 0xba, 0xc7, 0x8b, 0x72, 0xc6, 0x8d, 0x75, 0xc3, 0x82, 0xc3, 0xad, 0xc5, + 0x8a, 0xc7, 0xb1, 0xc8, 0xbb, 0xc5, 0x9e, 0xe2, 0xb1, 0xb3, 0xc3, 0xa5, 0xe1, 0x9a, + 0xb8, 0xc5, 0x81, 0x63, 0xc5, 0x98, 0xe1, 0x9b, 0x80, 0xc5, 0x86, 0xc4, 0xa9, 0xe1, + 0x9b, 0xa4, 0x60, 0xc8, 0xa0, 0xc3, 0x97, 0xc4, 0xa4, 0xc5, 0x81, 0xc3, 0x95, 0xc4, + 0xb0, 0xc2, 0xb2, 0xe1, 0x9b, 0x94, 0xc7, 0x8c, 0x46, 0x60, 0xe2, 0xb1, 0xa0, 0xc4, + 0xa5, 0xc7, 0xa9, 0xc6, 0xa8, 0xe1, 0x9b, 0x9c, 0xc5, 0xb4, 0xc5, 0x82, 0xc8, 0x80, + 0xc4, 0x9b, 0xe2, 0xb1, 0xa7, 0xc4, 0x95, 0xc5, 0x93, 0xc8, 0x83, 0xc4, 0x9f, 0xc4, + 0xa1, 0xc4, 0xb1, 0xc3, 0xb0, 0xc8, 0xa5, 0xc6, 0x87, 0xc5, 0xb5, 0xe1, 0x9b, 0xaf, + 0xc9, 0x8e, 0xc2, 0xac, 0xe2, 0xb1, 0xba, 0xc7, 0x9f, 0xc5, 0xa1, 0xc6, 0x94, 0xc3, + 0xa5, 0xc8, 0x8b, 0xc8, 0xa5, 0xe2, 0xb1, 0xb2, 0xc7, 0xab, 0xe1, 0x9b, 0x91, 0xc3, + 0xaa, 0xc6, 0xb5, 0xc4, 0xbf, 0xc5, 0x80, 0xc4, 0xb4, 0xc3, 0xb6, 0xe2, 0xb1, 0xb3, + 0x5e, 0xc8, 0xb6, 0xe1, 0x9a, 0xab, 0xe2, 0xb1, 0xa7, 0xc5, 0x98, 0xe1, 0x9b, 0x9e, + 0x69, 0xe1, 0x9b, 0x8b, 0xe2, 0xb1, 0xbf, 0xc9, 0x88, 0xe2, 0xb1, 0xb5, 0x71, 0x29, + 0xc6, 0x85, 0xc7, 0xab, 0xe1, 0x9b, 0xa9, 0x6d, 0xc7, 0x90, 0xc3, 0x9b, 0xc5, 0x8e, + 0xe1, 0x9b, 0x87, 0xc7, 0x9f, 0xc5, 0xa3, 0xc5, 0xb9, 0x74, 0x7d, 0xc4, 0x94, 0xe1, + 0x9b, 0x93, 0xc7, 0xbc, 0xc8, 0x96, 0x58, 0xe2, 0xb1, 0xaf, 0xe2, 0xb1, 0xbc, 0xc2, + 0xb4, 0xc8, 0xbd, 0xc8, 0xab, 0xc4, 0xb7, 0x42, 0xc2, 0xb5, 0xc7, 0xa5, 0xc5, 0x9c, + 0xcd, 0xb3, 0xc9, 0x87, 0xe2, 0xb1, 0xa0, 0xc4, 0xa3, 0xc8, 0xad, 0xc5, 0x90, 0xe1, + 0x9b, 0x81, 0xc5, 0x9a, 0xc4, 0xa8, 0xc4, 0xb0, 0x7e, 0xc5, 0xaf, 0x60, 0xe1, 0x9a, + 0xa1, 0xc3, 0xb3, 0xc6, 0xb2, 0xe1, 0x9b, 0x97, 0x3c, 0xc4, 0xba, 0xc5, 0xbb, 0x42, + 0xc4, 0x97, 0x66, 0xc8, 0x91, 0xc3, 0xb2, 0xc2, 0xa5, 0xe1, 0x9b, 0xa0, 0xc4, 0xaf, + 0xc8, 0xbf, 0xc8, 0x8a, 0xc5, 0xa1, 0xc3, 0x98, 0xc8, 0x8c, 0xc5, 0x82, 0xe1, 0x9b, + 0x89, 0xc5, 0x88, 0xc8, 0xa4, 0xc6, 0xbc, 0x7a, 0xc4, 0xa1, 0xc3, 0xb0, 0xc5, 0x88, + 0x7b, 0xe1, 0x9b, 0xa1, 0xc2, 0xae, 0xc7, 0x88, 0xc5, 0x9b, 0x71, 0xc7, 0xa7, 0xe1, + 0x9a, 0xa2, 0xc3, 0x8d, 0x50, 0xc6, 0x82, 0xc2, 0xb8, 0xc8, 0xab, 0xc6, 0xa5, 0xc7, + 0x9a, 0xe1, 0x9b, 0x81, 0xc6, 0xb8, 0xc8, 0xb8, 0x32, 0xe1, 0x9b, 0x9a, 0xc5, 0x92, + 0x21, 0xc2, 0xb1, 0xe1, 0x9b, 0xa4, 0xe2, 0xb1, 0xab, 0xe2, 0xb1, 0xbc, 0xc3, 0x9d, + 0xc4, 0xad, 0xc5, 0x83, 0xc7, 0x91, 0x7d, 0xc3, 0xb3, 0xc8, 0x9f, 0xc4, 0x94, 0x40, + 0xc4, 0xb2, 0xc8, 0x92, 0xc7, 0xa1, 0xc3, 0xbc, 0xe1, 0x9b, 0x97, 0xc2, 0xbb, 0xc5, + 0x9a, 0xc2, 0xb2, 0x52, 0xe1, 0x9a, 0xa9, 0x4c, 0xc2, 0xa2, 0xe2, 0xb1, 0xa9, 0xe1, + 0x9b, 0x87, 0xc5, 0x9c, 0xc4, 0x81, 0xc7, 0xb9, 0xe2, 0xb1, 0xad, 0xc4, 0xb3, 0xc5, + 0xa1, 0x64, 0xc5, 0x96, 0xc3, 0x9c, 0xc8, 0xaf, 0xc8, 0x91, 0xe2, 0xb1, 0xaf, 0xc4, + 0x9d, 0xc8, 0x98, 0xe1, 0x9b, 0x8c, 0xc6, 0x89, 0xc6, 0xbc, 0xc8, 0xbc, 0xc5, 0x81, + 0x37, 0x45, 0xc7, 0xa3, 0xc5, 0x81, 0x5a, 0x5a, + ], + asset_base: [ + 0x67, 0x0a, 0x16, 0x33, 0xc7, 0xae, 0x83, 0x6f, 0x14, 0x68, 0xb0, 0x6e, 0x24, 0xd0, + 0x8b, 0x84, 0x27, 0x6d, 0xf6, 0x78, 0xe7, 0xe5, 0x0d, 0x6c, 0x35, 0xce, 0x42, 0x98, + 0xbd, 0xc6, 0xb7, 0x92, + ], + }, + TestVector { + key: [ + 0x81, 0x8f, 0x50, 0xce, 0x47, 0x10, 0xf4, 0xeb, 0x11, 0xe7, 0x43, 0xe6, 0x40, 0x85, + 0x44, 0xaa, 0x3c, 0x12, 0x3c, 0x7f, 0x07, 0xe2, 0xaa, 0xbb, 0x91, 0xaf, 0xc4, 0xec, + 0x48, 0x78, 0x8d, 0xe9, + ], + description: [ + 0xc7, 0x98, 0xe1, 0x9a, 0xb2, 0x2a, 0xc2, 0xa5, 0xc7, 0xb7, 0xc8, 0xaa, 0xc4, 0x9b, + 0xc9, 0x84, 0xc5, 0xaf, 0x4d, 0xc3, 0x83, 0xc2, 0xa3, 0xc7, 0xaf, 0xc6, 0x92, 0xe2, + 0xb1, 0xbe, 0xc8, 0xbf, 0xe1, 0x9b, 0x83, 0xc7, 0x80, 0xc2, 0xb8, 0xc7, 0xa1, 0x6c, + 0xe1, 0x9b, 0xad, 0xc3, 0xa3, 0xc7, 0x97, 0x3b, 0xc9, 0x87, 0xce, 0x8a, 0x51, 0xc8, + 0xbc, 0xc7, 0xa4, 0xc2, 0xa4, 0x2d, 0xc3, 0xb6, 0x34, 0xc9, 0x8e, 0xc5, 0x8f, 0xc9, + 0x86, 0xc5, 0xba, 0xe1, 0x9b, 0x99, 0x76, 0xc6, 0x85, 0xc3, 0xa2, 0xc8, 0x99, 0xc3, + 0x91, 0xc4, 0xb3, 0xc5, 0xa1, 0xe2, 0xb1, 0xbb, 0xc7, 0xa0, 0xc6, 0x9d, 0xc3, 0x89, + 0xc9, 0x86, 0xc5, 0xa1, 0xe1, 0x9b, 0x98, 0xc5, 0xb7, 0xc5, 0xae, 0xc5, 0xb6, 0xe1, + 0x9b, 0x89, 0xc8, 0x98, 0x36, 0xc6, 0x95, 0xc4, 0xb5, 0xc8, 0x85, 0x5c, 0xe1, 0x9b, + 0x99, 0xe2, 0xb1, 0xaf, 0xc3, 0x92, 0xc7, 0x89, 0xc7, 0xb5, 0xc5, 0xbd, 0xc3, 0xa5, + 0xc6, 0x93, 0xc4, 0xac, 0xe1, 0x9b, 0x87, 0xc6, 0x9e, 0xc5, 0xa5, 0xcd, 0xbd, 0xe1, + 0x9b, 0x8a, 0xc6, 0x9d, 0xc9, 0x85, 0xc4, 0xa4, 0x5c, 0x6f, 0xc6, 0x93, 0x76, 0xc3, + 0xa6, 0xe1, 0x9a, 0xad, 0xcd, 0xbb, 0xc2, 0xab, 0xc2, 0xa3, 0xe2, 0xb1, 0xaf, 0xc3, + 0xb6, 0xc6, 0x9f, 0xc5, 0xa5, 0x37, 0x34, 0xe1, 0x9b, 0x8c, 0xc5, 0x8e, 0xc2, 0xb9, + 0xe2, 0xb1, 0xba, 0xc9, 0x88, 0xc8, 0xba, 0xc7, 0x95, 0xc3, 0xa2, 0xc5, 0x9a, 0xc7, + 0x83, 0xc6, 0xb5, 0xc9, 0x8a, 0xc7, 0xb0, 0xe2, 0xb1, 0xab, 0xc5, 0xab, 0xc7, 0x8f, + 0xc3, 0xb6, 0xc4, 0xa7, 0xe1, 0x9a, 0xbb, 0x4e, 0xe1, 0x9b, 0x85, 0x5a, 0xc8, 0xb7, + 0x21, 0xe1, 0x9b, 0x87, 0x25, 0xc6, 0xb4, 0xc5, 0x92, 0xc8, 0xba, 0xc2, 0xa3, 0xc2, + 0xae, 0xe1, 0x9b, 0x89, 0xc5, 0xac, 0x67, 0xc5, 0x98, 0xc7, 0x81, 0xce, 0x85, 0xe2, + 0xb1, 0xb5, 0xc3, 0xab, 0xe2, 0xb1, 0xbd, 0xe1, 0x9b, 0x93, 0xc7, 0x91, 0xc8, 0xa0, + 0xc5, 0x83, 0xc6, 0xb4, 0xc8, 0xb6, 0xc8, 0x9a, 0xe1, 0x9b, 0x93, 0xc7, 0xa3, 0xe1, + 0x9a, 0xba, 0xc9, 0x81, 0xc5, 0xa5, 0xc5, 0xb8, 0x33, 0xc5, 0x86, 0xc8, 0x97, 0x77, + 0xe1, 0x9a, 0xb7, 0xc7, 0xa2, 0xc2, 0xaf, 0xce, 0x88, 0xe1, 0x9a, 0xaa, 0x33, 0xc8, + 0x8f, 0xc4, 0xb9, 0xc8, 0xaf, 0xc3, 0x81, 0xc6, 0xbc, 0xc9, 0x80, 0xc7, 0xb6, 0x46, + 0xe1, 0x9a, 0xa3, 0x6a, 0xc4, 0x85, 0xe1, 0x9b, 0x85, 0xc5, 0x8f, 0xcd, 0xbe, 0x71, + 0x2a, 0xc7, 0x95, 0xc6, 0xa1, 0xc3, 0xaf, 0xe1, 0x9b, 0xa6, 0xc3, 0x93, 0xc3, 0xa5, + 0xc7, 0x9a, 0xc5, 0xb4, 0x50, 0xc7, 0x81, 0xc3, 0x88, 0xc7, 0x87, 0x5a, 0xc3, 0x87, + 0xc3, 0xa2, 0xc7, 0x8a, 0xc8, 0xb9, 0xc3, 0xbb, 0xe1, 0x9a, 0xab, 0xc3, 0xaa, 0xc7, + 0x99, 0xc7, 0x89, 0xc3, 0x98, 0x7c, 0xc6, 0x83, 0x2d, 0xe2, 0xb1, 0xa2, 0xc6, 0x96, + 0xe1, 0x9a, 0xb1, 0x46, 0xe2, 0xb1, 0xa9, 0xc6, 0xaf, 0xc3, 0xbe, 0xe1, 0x9b, 0xa2, + 0xe1, 0x9b, 0x91, 0xc2, 0xb1, 0xc8, 0x8c, 0xc4, 0xb2, 0x75, 0xc4, 0xb9, 0xc5, 0xa6, + 0x52, 0xc6, 0xbc, 0xc3, 0xab, 0xe1, 0x9a, 0xb9, 0xc4, 0xb6, 0xc6, 0xb4, 0xc7, 0xa7, + 0xc2, 0xa1, 0x2d, 0x73, 0x6c, 0xc3, 0xae, 0xc3, 0x98, 0xc8, 0x91, 0xe2, 0xb1, 0xa1, + 0xc4, 0x9c, 0xc5, 0xa9, 0xe1, 0x9b, 0x80, 0xc2, 0xba, 0x71, 0xc3, 0x8c, 0x3b, 0xc3, + 0xb6, 0xc7, 0x95, 0xc5, 0xab, 0xc3, 0x81, 0xc6, 0xbf, 0xc5, 0x9a, 0xe1, 0x9b, 0xab, + 0xc8, 0x9c, 0xc8, 0x83, 0xc5, 0x9f, 0xc5, 0x9a, 0xc5, 0xae, 0xe1, 0x9a, 0xb4, 0xc5, + 0x9a, 0xc3, 0xa4, 0xc8, 0xab, 0xc7, 0xba, 0x69, + ], + asset_base: [ + 0x7e, 0x26, 0x94, 0x4d, 0x61, 0xa6, 0xc8, 0xfe, 0x89, 0x5e, 0xda, 0x8d, 0x1c, 0x72, + 0x77, 0x13, 0xe9, 0x65, 0x61, 0xb7, 0x56, 0x56, 0xfd, 0xa2, 0x07, 0x0b, 0x2b, 0x0c, + 0x9d, 0xe1, 0x4d, 0x85, + ], + }, + TestVector { + key: [ + 0xae, 0x36, 0xb6, 0x1a, 0x3d, 0x10, 0xf1, 0xaa, 0x75, 0x2a, 0xb1, 0xdc, 0x16, 0xe3, + 0xe4, 0x9b, 0x6a, 0xc0, 0xd2, 0xae, 0x19, 0x07, 0xd2, 0xe6, 0x94, 0x25, 0xec, 0x12, + 0xc9, 0x3a, 0xae, 0xbc, + ], + description: [ + 0xc4, 0x9e, 0xe2, 0xb1, 0xa6, 0xe1, 0x9a, 0xb3, 0x2e, 0xe2, 0xb1, 0xb4, 0xc7, 0x8a, + 0xe1, 0x9b, 0xaf, 0xc4, 0xa9, 0xe2, 0xb1, 0xb5, 0x26, 0xc5, 0x8a, 0xc3, 0xa9, 0x7b, + 0xc7, 0xac, 0xc8, 0xb4, 0xe1, 0x9a, 0xb1, 0xe1, 0x9b, 0x85, 0xc6, 0x88, 0xc6, 0x80, + 0xe1, 0x9a, 0xb0, 0xc5, 0xa2, 0x23, 0xc4, 0x9f, 0xc2, 0xa1, 0xe1, 0x9b, 0xac, 0xc6, + 0x98, 0x70, 0x5c, 0xc9, 0x89, 0xc4, 0xa0, 0xc4, 0xaa, 0xc5, 0xa3, 0x79, 0xc3, 0xab, + 0xce, 0x89, 0xc9, 0x83, 0xc3, 0xab, 0xe2, 0xb1, 0xa0, 0x3d, 0x6a, 0xc4, 0x93, 0xe1, + 0x9b, 0xab, 0x7a, 0xe1, 0x9b, 0x87, 0xe1, 0x9b, 0x95, 0xc2, 0xa5, 0xc9, 0x86, 0xc7, + 0xb5, 0xc2, 0xaf, 0xe1, 0x9b, 0x9a, 0xc4, 0xa9, 0xc3, 0x8a, 0xc9, 0x80, 0xc3, 0xaf, + 0xc6, 0x8f, 0xc6, 0x89, 0xc4, 0xa9, 0xc4, 0xb4, 0xe1, 0x9b, 0x8d, 0x4b, 0xc8, 0x96, + 0xc6, 0x87, 0x40, 0xc4, 0x8e, 0xc6, 0x81, 0xc3, 0x9b, 0xc8, 0x9b, 0x49, 0xe2, 0xb1, + 0xa0, 0xc4, 0xb4, 0xc6, 0xa8, 0xc6, 0x8c, 0xc3, 0xb7, 0x34, 0xc8, 0x89, 0xc2, 0xb8, + 0xc2, 0xb2, 0xc4, 0xa8, 0xc4, 0xa0, 0xc7, 0xbb, 0xe2, 0xb1, 0xac, 0xe1, 0x9b, 0x97, + 0xc3, 0xa9, 0xc2, 0xbe, 0xc6, 0x85, 0xc2, 0xa9, 0xcd, 0xb5, 0xc3, 0x95, 0xc8, 0x8b, + 0xc5, 0x94, 0xe2, 0xb1, 0xa0, 0xc2, 0xb5, 0xc6, 0x94, 0xc4, 0xba, 0xe2, 0xb1, 0xbb, + 0xe1, 0x9b, 0x88, 0xc4, 0xa2, 0xc5, 0xa2, 0xcd, 0xbc, 0xc6, 0x88, 0xc3, 0x80, 0xc8, + 0x9d, 0xc5, 0x9b, 0xc7, 0xbe, 0xc5, 0x8c, 0xc5, 0xa8, 0xc5, 0xb0, 0xc9, 0x8c, 0xc2, + 0xa5, 0xc7, 0xbd, 0xc8, 0xaf, 0xc3, 0xb2, 0xc7, 0x8b, 0xc2, 0xb8, 0x25, 0xe1, 0x9b, + 0x80, 0xc9, 0x8f, 0xe1, 0x9b, 0xaa, 0xc5, 0xb1, 0xe1, 0x9b, 0x9d, 0xc5, 0xa5, 0xc2, + 0xa3, 0xc8, 0xaf, 0xc8, 0xb1, 0xc6, 0xb3, 0x3f, 0xc6, 0xb9, 0xc7, 0x91, 0xc7, 0x81, + 0xc7, 0xbc, 0x5d, 0x7c, 0x69, 0xc7, 0x96, 0xe1, 0x9b, 0x8c, 0xc7, 0xb7, 0xc6, 0xa3, + 0xe2, 0xb1, 0xb0, 0xc6, 0xb7, 0xce, 0x88, 0xc9, 0x81, 0xc3, 0x80, 0xe1, 0x9b, 0xaf, + 0xc7, 0xae, 0xc5, 0xbc, 0xc4, 0x8c, 0xc4, 0xa7, 0x71, 0x6e, 0xc6, 0x91, 0xc4, 0x96, + 0xc6, 0x88, 0xc6, 0x97, 0xc5, 0xa4, 0xc5, 0xbf, 0xc7, 0x8d, 0xc8, 0xb9, 0xc7, 0xb5, + 0xe1, 0x9a, 0xb0, 0xc4, 0xa8, 0xc7, 0xa3, 0xc6, 0xba, 0xe1, 0x9a, 0xb5, 0xc6, 0x86, + 0xe1, 0x9b, 0x80, 0xc9, 0x82, 0x4a, 0xc7, 0xa3, 0x7e, 0xc3, 0x9f, 0xc8, 0xb9, 0x7a, + 0x3b, 0xc6, 0xa7, 0xc8, 0x97, 0xc6, 0x92, 0xe1, 0x9b, 0xa1, 0xc7, 0x97, 0xc7, 0xa7, + 0xe1, 0x9a, 0xa3, 0xc9, 0x8d, 0xc6, 0xa0, 0xe1, 0x9b, 0xa0, 0xc4, 0x90, 0xc3, 0x9a, + 0xc4, 0x8f, 0xc7, 0xbc, 0xc4, 0x8b, 0xc2, 0xaa, 0x5d, 0xc3, 0xb0, 0xc3, 0x8b, 0xc4, + 0x90, 0xc3, 0xac, 0xc4, 0xad, 0xe1, 0x9a, 0xb8, 0xc5, 0x93, 0xc8, 0x92, 0xc3, 0x81, + 0xe1, 0x9a, 0xbc, 0xc4, 0xb3, 0xc6, 0x83, 0xc8, 0x9b, 0xc8, 0x81, 0x45, 0xe1, 0x9b, + 0x89, 0xc7, 0xbb, 0xc9, 0x87, 0xc6, 0xb6, 0x4c, 0xc6, 0x88, 0x60, 0xe1, 0x9b, 0x8c, + 0xc6, 0xa7, 0xcd, 0xbc, 0xc3, 0xbe, 0xc2, 0xb3, 0xc7, 0xab, 0xcd, 0xb6, 0xc8, 0xa2, + 0xc2, 0xbc, 0xe2, 0xb1, 0xa5, 0xc5, 0x8f, 0xc6, 0xa0, 0xc6, 0xa6, 0xc6, 0x9b, 0xc8, + 0x94, 0xe1, 0x9a, 0xa0, 0xe2, 0xb1, 0xb6, 0x3f, 0xcd, 0xb2, 0xc8, 0x81, 0xc3, 0x88, + 0xc3, 0xb9, 0xe1, 0x9b, 0x81, 0xe2, 0xb1, 0xa8, 0xc5, 0xb8, 0x48, 0x60, 0xc6, 0xb0, + 0xc5, 0xb1, 0xc3, 0x8e, 0x4a, 0xc5, 0x84, 0xc8, 0xaf, 0xc4, 0xb2, 0xc4, 0x97, 0xe2, + 0xb1, 0xbd, 0xc4, 0xb6, 0x3f, 0xc8, 0x89, 0x5a, + ], + asset_base: [ + 0xcc, 0x07, 0x9a, 0xf8, 0x84, 0x69, 0xe9, 0xbd, 0x7e, 0x67, 0x8e, 0xcf, 0x7f, 0x9f, + 0x79, 0xfa, 0x4d, 0x30, 0x89, 0x27, 0x28, 0xad, 0x87, 0x32, 0xe9, 0xcc, 0x99, 0x7d, + 0x3c, 0x7c, 0x64, 0x1f, + ], + }, + TestVector { + key: [ + 0x49, 0x26, 0x53, 0x80, 0xd2, 0xb0, 0x2e, 0x0a, 0x1d, 0x98, 0x8f, 0x3d, 0xe3, 0x45, + 0x8b, 0x6e, 0x00, 0x29, 0x1d, 0xb0, 0xe6, 0x2e, 0x17, 0x47, 0x91, 0xd0, 0x09, 0x29, + 0x9f, 0x61, 0xfe, 0xc4, + ], + description: [ + 0xc7, 0x88, 0xc2, 0xa3, 0xe2, 0xb1, 0xa7, 0xc5, 0x84, 0xc6, 0xac, 0xc8, 0xaa, 0x63, + 0xc6, 0xa7, 0xc5, 0xa7, 0x75, 0xc7, 0x97, 0xe1, 0x9b, 0xaf, 0x71, 0xc8, 0x95, 0xe1, + 0x9a, 0xba, 0x44, 0x45, 0xc3, 0xa1, 0xe1, 0x9b, 0xac, 0xc6, 0xbf, 0xc4, 0xbc, 0xc4, + 0x88, 0xe1, 0x9b, 0x82, 0xe2, 0xb1, 0xb1, 0x5d, 0xc3, 0xa7, 0xe1, 0x9b, 0xa0, 0xc7, + 0xb4, 0x5a, 0xc4, 0xad, 0xe1, 0x9b, 0x8f, 0xc5, 0x88, 0xc9, 0x8c, 0xc8, 0xab, 0xe1, + 0x9a, 0xaf, 0xc7, 0xb6, 0xc2, 0xb8, 0x59, 0xc5, 0xbb, 0xc5, 0xbd, 0x2e, 0xc5, 0x86, + 0xe2, 0xb1, 0xbb, 0xe2, 0xb1, 0xb1, 0xc3, 0xb4, 0xc5, 0xb2, 0xc4, 0x96, 0xc5, 0x99, + 0xc7, 0x8c, 0x71, 0xc6, 0xa2, 0xc3, 0x91, 0xc5, 0xb9, 0xcd, 0xbe, 0x26, 0xe1, 0x9a, + 0xa8, 0xe1, 0x9b, 0x86, 0xc3, 0x99, 0xc8, 0xa7, 0xc4, 0x8b, 0xe2, 0xb1, 0xb4, 0xc5, + 0x8c, 0xc5, 0x9e, 0xc5, 0xa5, 0xc4, 0xbd, 0x3c, 0xc5, 0x89, 0xc4, 0x88, 0x29, 0xc2, + 0xa6, 0x2c, 0xc7, 0xa9, 0xc5, 0xb6, 0xc8, 0x92, 0xc5, 0xb8, 0x3c, 0xc6, 0x8b, 0xc6, + 0x83, 0xe1, 0x9b, 0x9b, 0xc6, 0x88, 0xe2, 0xb1, 0xba, 0x32, 0x63, 0xc7, 0xbe, 0xc6, + 0x8a, 0xc7, 0x8d, 0xc6, 0xa5, 0xc6, 0x9f, 0xc8, 0x98, 0xc4, 0xb0, 0xc8, 0xac, 0xc8, + 0xb1, 0xc5, 0xa3, 0xc2, 0xb1, 0xc9, 0x8f, 0xc4, 0xbf, 0xe1, 0x9b, 0xa3, 0xe2, 0xb1, + 0xad, 0xc4, 0x88, 0xc5, 0x8d, 0xc7, 0x98, 0xc8, 0xb4, 0xc3, 0xab, 0xc3, 0x9b, 0xc6, + 0xa5, 0xe1, 0x9b, 0x89, 0xc2, 0xa8, 0xce, 0x88, 0xe2, 0xb1, 0xb9, 0xe1, 0x9b, 0x83, + 0xc6, 0x83, 0xce, 0x8c, 0xc3, 0xbc, 0x65, 0xe1, 0x9a, 0xaf, 0xc4, 0x88, 0xe1, 0x9a, + 0xa1, 0xc8, 0x87, 0xc8, 0x98, 0xc5, 0x8e, 0xc8, 0xbd, 0x30, 0xc4, 0xb8, 0xc7, 0xa4, + 0x48, 0xc8, 0xa1, 0xe1, 0x9b, 0x93, 0xc4, 0xa8, 0xc5, 0xba, 0x52, 0xc3, 0xbc, 0xc6, + 0xbe, 0xc6, 0x96, 0xc9, 0x8c, 0x3a, 0xc8, 0xa9, 0xc2, 0xac, 0xe1, 0x9b, 0x8c, 0xc3, + 0x9d, 0xe2, 0xb1, 0xb0, 0xc4, 0xaf, 0x34, 0xc5, 0xb2, 0xc7, 0xb3, 0xc6, 0xb2, 0xe1, + 0x9a, 0xb9, 0xc7, 0x98, 0xc8, 0xbe, 0x7a, 0xc2, 0xa7, 0xe1, 0x9b, 0x85, 0xc9, 0x8b, + 0xc5, 0x98, 0xc7, 0xa3, 0xe2, 0xb1, 0xab, 0xc3, 0xbf, 0xc3, 0xb1, 0xc8, 0x88, 0xc4, + 0x9d, 0xc4, 0x80, 0xc7, 0xac, 0xc7, 0xbe, 0xe1, 0x9a, 0xa3, 0xc6, 0x8c, 0xe1, 0x9b, + 0xa5, 0xc8, 0x8f, 0xc4, 0xbf, 0xc4, 0xbf, 0xc8, 0x84, 0xc3, 0x81, 0xc7, 0xa6, 0xe2, + 0xb1, 0xa3, 0xc3, 0xb2, 0x5a, 0xe1, 0x9b, 0xa2, 0xe1, 0x9a, 0xba, 0xc4, 0x92, 0xc8, + 0xaa, 0xe1, 0x9a, 0xaf, 0xc5, 0x8b, 0xc6, 0xa3, 0x73, 0xc6, 0x87, 0xc4, 0x82, 0xc8, + 0xa0, 0xc8, 0xaf, 0x6f, 0xe2, 0xb1, 0xbb, 0xc7, 0x9c, 0x55, 0xe1, 0x9a, 0xbf, 0xc2, + 0xa6, 0xc8, 0xab, 0xc6, 0xa5, 0xc8, 0x8b, 0xc5, 0x90, 0xc5, 0xbf, 0xc8, 0x94, 0xc6, + 0xa3, 0xc4, 0xbe, 0xc4, 0xab, 0xc7, 0xb8, 0xc4, 0x91, 0xc6, 0xa6, 0xc5, 0xb6, 0xc3, + 0x9b, 0xc8, 0xae, 0xc4, 0x8f, 0x62, 0xc2, 0xa4, 0xc8, 0x99, 0xcd, 0xba, 0xc4, 0x96, + 0xc2, 0xb2, 0xc6, 0x92, 0xc5, 0xb5, 0xc5, 0x83, 0xc6, 0x92, 0xc6, 0x8d, 0xe1, 0x9b, + 0xb0, 0xe1, 0x9b, 0x99, 0xc7, 0xae, 0xe1, 0x9a, 0xa7, 0x64, 0x33, 0x3c, 0xc6, 0xab, + 0xc4, 0x95, 0xc3, 0xbd, 0xc8, 0xad, 0xc5, 0xa5, 0x5e, 0xe2, 0xb1, 0xbe, 0xe1, 0x9a, + 0xb6, 0xc8, 0x83, 0x54, 0x25, 0xc8, 0x80, 0xc6, 0xa9, 0xe1, 0x9a, 0xb2, 0xc5, 0x98, + 0xc8, 0xb3, 0xc6, 0x96, 0xc7, 0x87, 0xe1, 0x9a, 0xaa, 0xe1, 0x9b, 0x92, 0xc6, 0xaa, + 0x72, 0x67, 0xe2, 0xb1, 0xb4, 0x4d, 0xc3, 0xb2, + ], + asset_base: [ + 0xaa, 0xb9, 0x9e, 0x01, 0x44, 0xfb, 0xf5, 0x9f, 0x87, 0xd2, 0xe5, 0xf6, 0x32, 0x63, + 0x82, 0xf6, 0x3a, 0x46, 0x83, 0x83, 0xb4, 0x74, 0x40, 0xd7, 0x84, 0xe9, 0x4e, 0x6b, + 0x3a, 0xb6, 0x45, 0x28, + ], + }, + TestVector { + key: [ + 0x9a, 0x0e, 0x46, 0x39, 0xb4, 0x69, 0x1f, 0x02, 0x7c, 0x0d, 0xb7, 0xfe, 0xf1, 0xbb, + 0x5e, 0xf9, 0x0a, 0xcd, 0xb7, 0x08, 0x62, 0x6d, 0x2e, 0x1f, 0x3e, 0x38, 0x3e, 0xe7, + 0x5b, 0x31, 0xcf, 0x57, + ], + description: [ + 0xc3, 0xaa, 0xc3, 0xa0, 0xe2, 0xb1, 0xba, 0xc6, 0x8d, 0x34, 0xc4, 0xb0, 0xc4, 0x8b, + 0xc2, 0xba, 0xc5, 0xa9, 0xe2, 0xb1, 0xa6, 0xc3, 0xa8, 0x6f, 0x2c, 0x45, 0xc5, 0xaf, + 0xc4, 0xbb, 0xc7, 0x8b, 0xc6, 0x8e, 0xc8, 0x94, 0xc3, 0xac, 0xc2, 0xab, 0xc8, 0x8b, + 0xe1, 0x9a, 0xb4, 0xc5, 0x9d, 0xc8, 0xb3, 0xc7, 0xb9, 0xe1, 0x9a, 0xac, 0xc6, 0x9b, + 0xc4, 0x9d, 0xc2, 0xa3, 0xe1, 0x9a, 0xb6, 0xc5, 0x92, 0xc7, 0x87, 0x46, 0xc4, 0x99, + 0xce, 0x88, 0xc5, 0x91, 0xc8, 0x92, 0xc4, 0xa9, 0xc3, 0xab, 0x78, 0xc9, 0x8e, 0xc7, + 0xac, 0xc5, 0xba, 0xc4, 0x88, 0xc5, 0x80, 0xc7, 0x91, 0xc5, 0xb7, 0xc5, 0xaa, 0xe1, + 0x9b, 0x97, 0x30, 0xc8, 0x8d, 0x5c, 0xc2, 0xb3, 0xc4, 0x9f, 0x2a, 0xc3, 0xb8, 0xc7, + 0xae, 0xc7, 0xbd, 0xc4, 0xa0, 0xe1, 0x9a, 0xa1, 0xe1, 0x9a, 0xbf, 0xc7, 0x9e, 0xe1, + 0x9b, 0x84, 0xc8, 0x9c, 0xc5, 0x86, 0x2b, 0xc4, 0x96, 0xcd, 0xb4, 0xc3, 0x82, 0x6a, + 0xc8, 0xa6, 0xc5, 0x8c, 0xc3, 0x8a, 0xc2, 0xbf, 0xc6, 0x9e, 0x32, 0xe2, 0xb1, 0xa0, + 0xc5, 0xa2, 0xc8, 0x8b, 0x3e, 0xc4, 0x91, 0xc6, 0xab, 0xc3, 0x92, 0xc7, 0xa7, 0xc8, + 0xa3, 0xc4, 0xa7, 0xe1, 0x9a, 0xb0, 0xc4, 0x9c, 0xcd, 0xb6, 0xe1, 0x9a, 0xa1, 0xc6, + 0x8b, 0xe1, 0x9b, 0x9e, 0xc2, 0xb5, 0xc6, 0x89, 0x33, 0x46, 0xc6, 0x8d, 0xc4, 0xb3, + 0xc8, 0xac, 0xc5, 0x97, 0xc3, 0xb7, 0xc7, 0xab, 0xe2, 0xb1, 0xa1, 0xe1, 0x9b, 0x9f, + 0xc4, 0x94, 0xe1, 0x9b, 0xb0, 0xc8, 0x8e, 0xc4, 0xa8, 0xc5, 0x8b, 0xc6, 0xbb, 0xc2, + 0xa6, 0xe1, 0x9b, 0xae, 0xc2, 0xac, 0xe1, 0x9b, 0x84, 0xc2, 0xb1, 0x4c, 0xc2, 0xb7, + 0xc5, 0x9c, 0x5d, 0xc9, 0x8c, 0xe1, 0x9b, 0x8b, 0x31, 0xc6, 0xb5, 0x62, 0xc7, 0x9e, + 0xc3, 0xa8, 0xc8, 0x82, 0xc7, 0xb7, 0x69, 0xe1, 0x9a, 0xbf, 0xe1, 0x9a, 0xa3, 0xe1, + 0x9b, 0xb0, 0x6e, 0xc6, 0xb9, 0xc9, 0x89, 0xc8, 0xb1, 0xc6, 0xaf, 0xe1, 0x9b, 0x90, + 0x55, 0xc4, 0xb1, 0xe1, 0x9b, 0xac, 0xe1, 0x9b, 0x8b, 0xc7, 0xaa, 0xe1, 0x9b, 0x88, + 0xc3, 0xbf, 0xe1, 0x9a, 0xa5, 0xc5, 0xa9, 0xc2, 0xb7, 0x62, 0xc3, 0x91, 0xc5, 0x93, + 0xc4, 0xbd, 0xc3, 0x90, 0xe1, 0x9b, 0x86, 0xe1, 0x9b, 0x8e, 0xcd, 0xbc, 0xc8, 0x86, + 0xe2, 0xb1, 0xb2, 0xc2, 0xbe, 0xc6, 0xbd, 0x64, 0xc2, 0xb2, 0xcd, 0xbb, 0xc3, 0x90, + 0xc7, 0x9c, 0xcd, 0xb5, 0xc8, 0x9f, 0xc7, 0xa0, 0x75, 0xc8, 0x9f, 0xe1, 0x9b, 0x99, + 0xc5, 0x9a, 0xe2, 0xb1, 0xae, 0xc6, 0x90, 0xc4, 0xad, 0xc3, 0x89, 0xc2, 0xba, 0xc4, + 0x91, 0xc6, 0x83, 0xe1, 0x9a, 0xa6, 0xc3, 0x93, 0xc3, 0x9b, 0xc7, 0x8f, 0xc4, 0xa3, + 0xc5, 0xae, 0x40, 0xc5, 0xb4, 0xe1, 0x9b, 0x97, 0xe2, 0xb1, 0xbf, 0xc6, 0xb3, 0xe2, + 0xb1, 0xb2, 0xe1, 0x9a, 0xae, 0xc3, 0x95, 0xc4, 0x80, 0xc5, 0x9b, 0xc5, 0xa9, 0xc5, + 0xa8, 0xe1, 0x9b, 0xa7, 0xc8, 0x98, 0x75, 0x53, 0xe2, 0xb1, 0xb4, 0xe1, 0x9a, 0xb4, + 0xc3, 0xa3, 0x4b, 0xc3, 0x86, 0xe1, 0x9a, 0xa9, 0xc3, 0x80, 0xe1, 0x9b, 0xb0, 0xc3, + 0x81, 0xc4, 0x86, 0xc9, 0x83, 0xc8, 0xbb, 0xc3, 0x88, 0xc8, 0x96, 0xc7, 0xac, 0xc4, + 0x9a, 0xc5, 0xb7, 0x7e, 0xc7, 0xbe, 0xc6, 0xba, 0xc2, 0xb6, 0xe1, 0x9a, 0xb5, 0xc7, + 0xbd, 0xc7, 0x80, 0x73, 0xc7, 0xab, 0xc8, 0xbd, 0xc7, 0xb7, 0xc3, 0x89, 0xe1, 0x9b, + 0x92, 0xe1, 0x9b, 0x85, 0xe2, 0xb1, 0xb7, 0xc8, 0x8c, 0xc4, 0xb8, 0xc8, 0xa2, 0xc3, + 0xa6, 0xc4, 0x9c, 0xc5, 0x9b, 0xc2, 0xa3, 0xc8, 0x8b, 0xc2, 0xbd, 0xe2, 0xb1, 0xb0, + 0xc5, 0xa6, 0xce, 0x87, 0xc2, 0xb3, 0xc5, 0xbc, + ], + asset_base: [ + 0x9c, 0x67, 0xc9, 0x2b, 0xeb, 0x8d, 0x82, 0xb5, 0x8a, 0x3d, 0x24, 0xba, 0xaa, 0x0a, + 0xa1, 0x5c, 0x30, 0x64, 0x16, 0xb2, 0x63, 0x72, 0x16, 0xe9, 0xb7, 0x83, 0x05, 0x43, + 0x4c, 0x57, 0x96, 0xb6, + ], + }, + TestVector { + key: [ + 0xbb, 0xf4, 0x49, 0x82, 0xf1, 0xba, 0x3a, 0x2b, 0x9d, 0xd3, 0xc1, 0x77, 0x4d, 0x71, + 0xce, 0x33, 0x60, 0x59, 0x9b, 0x07, 0xf2, 0x11, 0xc8, 0x16, 0xb8, 0xc4, 0x3b, 0x98, + 0x42, 0x23, 0x09, 0x24, + ], + description: [ + 0xc4, 0xa8, 0xc5, 0x96, 0xc2, 0xb6, 0xc6, 0xb1, 0x7c, 0xc7, 0xa0, 0x36, 0xc6, 0x9f, + 0x75, 0xc2, 0xa1, 0xc3, 0xbe, 0xc8, 0x90, 0xc2, 0xa6, 0xc3, 0x86, 0xc9, 0x86, 0xe2, + 0xb1, 0xa7, 0xe1, 0x9b, 0xa8, 0xc5, 0x9c, 0xc7, 0xa6, 0xc7, 0xbd, 0xe1, 0x9b, 0xa2, + 0x37, 0xc2, 0xbd, 0xc3, 0x97, 0xc4, 0x8f, 0xc3, 0x80, 0xc4, 0x8f, 0xc6, 0xa6, 0xc5, + 0x8e, 0xce, 0x89, 0xc4, 0xa6, 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0x8f, 0xe2, 0xb1, 0xb7, + 0xc9, 0x84, 0xe1, 0x9a, 0xa1, 0xc6, 0x97, 0xe1, 0x9b, 0x85, 0xc3, 0xaf, 0xc6, 0xbf, + 0x3e, 0xe2, 0xb1, 0xbf, 0xc7, 0xa9, 0x39, 0xc4, 0x80, 0xc3, 0x80, 0xc6, 0x87, 0xc3, + 0xa9, 0x4c, 0x66, 0xc8, 0xa5, 0x3b, 0xc5, 0x83, 0x48, 0xc6, 0xbd, 0xc5, 0xbd, 0xc7, + 0x8f, 0xc8, 0xaf, 0xc7, 0x9c, 0xe1, 0x9a, 0xb5, 0xcd, 0xbc, 0xc5, 0x9a, 0xc2, 0xa1, + 0xe2, 0xb1, 0xbf, 0xe1, 0x9b, 0x91, 0xc4, 0x8d, 0xc5, 0x9b, 0xc3, 0x9d, 0xc5, 0x90, + 0xe1, 0x9b, 0x82, 0x71, 0xc2, 0xb9, 0xc7, 0xa4, 0xcd, 0xbc, 0xc5, 0x80, 0xc8, 0x8e, + 0xc7, 0x83, 0x53, 0xc8, 0xb1, 0xc4, 0x83, 0xe2, 0xb1, 0xa0, 0xc5, 0x86, 0xc5, 0xa7, + 0xc4, 0xb0, 0xc6, 0x9b, 0xc8, 0xa6, 0xc8, 0xb2, 0xc5, 0x89, 0xc8, 0xb7, 0xc9, 0x83, + 0xc5, 0xaa, 0xc3, 0x9a, 0xc4, 0xae, 0xc4, 0xbb, 0xc6, 0x9f, 0xc6, 0xac, 0xc8, 0x8b, + 0xc9, 0x8e, 0x70, 0xc5, 0x88, 0x6e, 0xc6, 0x9e, 0xe1, 0x9a, 0xb7, 0xcd, 0xb5, 0xc3, + 0x9d, 0xe2, 0xb1, 0xb2, 0xc4, 0x90, 0xe1, 0x9b, 0x97, 0xc7, 0xb0, 0xc6, 0xa0, 0xe2, + 0xb1, 0xaa, 0xc7, 0x8e, 0xc5, 0xb4, 0x3c, 0xc7, 0xa8, 0xc9, 0x81, 0xc2, 0xb6, 0xc5, + 0xa8, 0x21, 0x78, 0xe2, 0xb1, 0xab, 0xce, 0x84, 0xc5, 0x85, 0xc6, 0x83, 0xc4, 0x82, + 0xc7, 0x90, 0xc6, 0xb5, 0xc6, 0xb9, 0xc8, 0xac, 0xc7, 0xb9, 0xc3, 0xb1, 0xc5, 0x85, + 0xe1, 0x9a, 0xa5, 0x50, 0x44, 0xc5, 0xb7, 0xe1, 0x9a, 0xac, 0xc4, 0x9c, 0xc7, 0x90, + 0xc5, 0x85, 0xc8, 0xbe, 0xc2, 0xb5, 0xc6, 0xb7, 0xc7, 0xba, 0xc6, 0x98, 0xe1, 0x9b, + 0xa8, 0xe2, 0xb1, 0xb9, 0xc5, 0xae, 0xc7, 0x83, 0xc5, 0xb4, 0xc4, 0x98, 0xc6, 0x9f, + 0xc5, 0x84, 0xc3, 0x92, 0xe1, 0x9b, 0x85, 0xc5, 0x95, 0x31, 0xc3, 0x8e, 0xe1, 0x9a, + 0xa0, 0x66, 0xc8, 0xbf, 0xc6, 0x96, 0xc7, 0xbb, 0xc2, 0xb2, 0xe2, 0xb1, 0xbf, 0xc4, + 0x96, 0xe1, 0x9a, 0xb6, 0xc8, 0xa5, 0xc5, 0xb6, 0xc6, 0xa7, 0xc8, 0x8d, 0xc3, 0xa0, + 0xc7, 0xae, 0xc7, 0xb8, 0xe1, 0x9b, 0x85, 0xc7, 0x8a, 0xc4, 0xa4, 0xc4, 0x9d, 0xc4, + 0xbe, 0xe1, 0x9a, 0xb5, 0xc4, 0x85, 0xc9, 0x83, 0xc3, 0xb5, 0xc3, 0xba, 0xc4, 0x9d, + 0xc6, 0xad, 0x68, 0xe1, 0x9b, 0xb0, 0xc4, 0x86, 0xc7, 0xb6, 0xc6, 0x92, 0xc9, 0x80, + 0xc5, 0x80, 0xcd, 0xb1, 0xc7, 0x85, 0xc4, 0xae, 0xc6, 0x95, 0xe2, 0xb1, 0xb2, 0xc5, + 0x9d, 0xc8, 0x99, 0xc4, 0x91, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, 0x91, 0xc4, 0xbc, 0xc4, + 0x85, 0xe1, 0x9b, 0xa1, 0xc5, 0x86, 0x26, 0xc3, 0xa8, 0xc3, 0x88, 0xc4, 0xb8, 0xe2, + 0xb1, 0xa7, 0xc2, 0xa5, 0xe1, 0x9b, 0x98, 0xc4, 0xb3, 0x7c, 0xc3, 0xb1, 0xe1, 0x9b, + 0x94, 0xc6, 0x9b, 0xcd, 0xbc, 0xcd, 0xb2, 0xc8, 0x8c, 0xc6, 0x8c, 0xe2, 0xb1, 0xb0, + 0x52, 0xc3, 0x9b, 0xc3, 0x8c, 0x5e, 0xc5, 0x90, 0xc3, 0xa4, 0xc3, 0x8a, 0x58, 0xc8, + 0x9e, 0xc5, 0xba, 0xc5, 0xb3, 0x6c, 0xc2, 0xab, 0xc4, 0xa1, 0x38, 0xc6, 0xb6, 0xe1, + 0x9b, 0x9f, 0x71, 0xc9, 0x84, 0xe2, 0xb1, 0xb9, 0xc3, 0x9a, 0xc6, 0x83, 0xe1, 0x9a, + 0xa4, 0xc6, 0x85, 0xc3, 0x8c, 0x25, 0x4e, 0x5a, + ], + asset_base: [ + 0x08, 0x32, 0x00, 0xcc, 0x9c, 0xa5, 0x39, 0xbe, 0xc9, 0x29, 0x51, 0x50, 0x4d, 0xca, + 0xf2, 0xc5, 0xe0, 0xe8, 0xe3, 0x57, 0xd7, 0xea, 0xed, 0x18, 0xb0, 0x15, 0x8b, 0x69, + 0x2c, 0xe4, 0xce, 0x9d, + ], + }, + TestVector { + key: [ + 0xff, 0x63, 0xc7, 0x89, 0x25, 0x1c, 0x10, 0x43, 0xc6, 0xf9, 0x6c, 0x66, 0xbf, 0x5b, + 0x0f, 0x61, 0xc9, 0xd6, 0x5f, 0xef, 0x5a, 0xaf, 0x42, 0x84, 0xa6, 0xa5, 0x69, 0x94, + 0x94, 0x1c, 0x05, 0xfa, + ], + description: [ + 0xc8, 0x8a, 0xc5, 0xb0, 0xe1, 0x9a, 0xb2, 0xc8, 0xbc, 0xc8, 0xbc, 0xc5, 0x9e, 0x63, + 0xcd, 0xb4, 0xc7, 0xbf, 0xc6, 0xbd, 0xc8, 0x99, 0xc3, 0x8c, 0xc8, 0x9c, 0x45, 0xc9, + 0x85, 0xcd, 0xb3, 0xc6, 0xb8, 0xc8, 0x91, 0x4e, 0xc9, 0x82, 0xc5, 0xab, 0xc5, 0x8a, + 0xce, 0x87, 0xe1, 0x9a, 0xbd, 0xc8, 0xa3, 0xc8, 0xa9, 0xc7, 0x90, 0xc6, 0x9c, 0xe1, + 0x9b, 0xa0, 0x41, 0x4c, 0xc2, 0xbb, 0xc7, 0x93, 0xe1, 0x9a, 0xa3, 0xc5, 0xba, 0xc6, + 0x86, 0xcd, 0xbd, 0xc5, 0x8d, 0xc4, 0xa4, 0xc8, 0xb5, 0xc3, 0x9d, 0xc3, 0xae, 0xc5, + 0x98, 0xe1, 0x9b, 0x91, 0x63, 0x66, 0xc3, 0xbc, 0xc8, 0xae, 0x7e, 0x40, 0xc2, 0xa8, + 0xc3, 0x8a, 0xc4, 0xac, 0x35, 0x3d, 0xcd, 0xbd, 0xc6, 0xad, 0xc3, 0x9b, 0xc6, 0x81, + 0xc5, 0xab, 0xc4, 0x8f, 0x28, 0xc4, 0x9d, 0xe1, 0x9b, 0x8e, 0xe1, 0x9b, 0xa4, 0xc5, + 0x86, 0xe1, 0x9a, 0xba, 0x50, 0xc6, 0xbc, 0xc6, 0x9b, 0xc7, 0xac, 0xc4, 0xb4, 0xe1, + 0x9a, 0xa9, 0xe1, 0x9b, 0xae, 0xc3, 0x91, 0xc6, 0x82, 0xc4, 0xa8, 0xc5, 0xa8, 0xc6, + 0xae, 0x2d, 0xe1, 0x9b, 0x9e, 0xc8, 0x8e, 0xe1, 0x9b, 0xa7, 0xc5, 0x8e, 0xc8, 0x8d, + 0xc3, 0x96, 0xc7, 0x9f, 0xc3, 0xb4, 0x3a, 0xcd, 0xb6, 0xc6, 0x8a, 0x6c, 0xc3, 0x9e, + 0xc9, 0x81, 0x65, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, 0xa2, 0xc7, 0x82, 0xe2, 0xb1, 0xad, + 0xe2, 0xb1, 0xa8, 0xc8, 0x96, 0xc8, 0xaa, 0xc6, 0xbc, 0x6b, 0xe1, 0x9a, 0xb4, 0xc5, + 0x9f, 0xc4, 0x92, 0xc6, 0x8e, 0xc3, 0x80, 0xc5, 0xb8, 0xc3, 0xa4, 0x2d, 0x38, 0xc5, + 0xb9, 0xc7, 0xb7, 0xc3, 0x8f, 0xc2, 0xb3, 0x62, 0xc5, 0x87, 0x21, 0xc6, 0x8f, 0xc7, + 0xb7, 0xe1, 0x9a, 0xb4, 0xc4, 0x84, 0x3e, 0xc7, 0x89, 0xc8, 0xaf, 0xc6, 0x98, 0xc6, + 0xb7, 0xc8, 0x9f, 0xc7, 0x9a, 0xc7, 0x96, 0xc3, 0xbb, 0x55, 0xe2, 0xb1, 0xb5, 0xc5, + 0xad, 0x2e, 0xc3, 0x86, 0xe1, 0x9b, 0x95, 0xc8, 0x81, 0xc3, 0x9b, 0xe1, 0x9b, 0xa4, + 0xcd, 0xb6, 0xc8, 0x8d, 0xc3, 0xa4, 0xc3, 0x89, 0xc8, 0x9d, 0xc8, 0xbe, 0x37, 0x25, + 0xc6, 0x99, 0x32, 0xc6, 0x92, 0xe1, 0x9b, 0x8b, 0x3a, 0x5f, 0x36, 0xc8, 0x9a, 0xc7, + 0xb3, 0x73, 0xc7, 0xaf, 0x7a, 0xc4, 0xac, 0xc7, 0x8b, 0xc8, 0x96, 0xc7, 0x82, 0xc8, + 0x8f, 0xc6, 0xb7, 0x37, 0xc3, 0xbc, 0xc5, 0x89, 0x2c, 0xc9, 0x84, 0xc5, 0xb7, 0xc6, + 0xb9, 0xc6, 0x90, 0xc7, 0x9f, 0xe2, 0xb1, 0xa5, 0xc5, 0x89, 0xc8, 0x8e, 0xc6, 0x8e, + 0xe1, 0x9b, 0x8e, 0xc8, 0xa6, 0xe1, 0x9a, 0xa4, 0xc5, 0xac, 0xc3, 0xa2, 0xc5, 0x9a, + 0x50, 0xc6, 0xa3, 0x44, 0xc6, 0x90, 0xc3, 0xae, 0x60, 0xc3, 0x8c, 0xc4, 0xb9, 0xc4, + 0x94, 0xc4, 0x9f, 0xc4, 0xa3, 0xc8, 0xb6, 0xc2, 0xa8, 0xc2, 0xa5, 0xc5, 0xb4, 0xe2, + 0xb1, 0xa2, 0x3a, 0xc7, 0xbd, 0x78, 0x78, 0xc3, 0xa9, 0xc2, 0xbc, 0xc4, 0xba, 0xc7, + 0x84, 0xc5, 0xb8, 0xe1, 0x9a, 0xaa, 0xe1, 0x9b, 0x83, 0xc3, 0x98, 0xc3, 0xb7, 0xc8, + 0x84, 0xcd, 0xbc, 0xcd, 0xba, 0xc4, 0xbe, 0xc2, 0xa9, 0xe1, 0x9a, 0xa0, 0xc5, 0xbd, + 0x5d, 0xc6, 0x92, 0xc8, 0xa0, 0x42, 0xc3, 0xb8, 0xe1, 0x9b, 0x8e, 0xc9, 0x89, 0xc2, + 0xb6, 0xc2, 0xb6, 0xc5, 0xbc, 0xc3, 0x88, 0xc5, 0x9b, 0xc8, 0xae, 0xc6, 0x98, 0xc7, + 0x9a, 0xc4, 0x82, 0xc6, 0x90, 0xc6, 0xa3, 0xc4, 0x98, 0xc9, 0x8f, 0xe1, 0x9a, 0xb1, + 0xe2, 0xb1, 0xbb, 0xc3, 0x97, 0xc8, 0xba, 0xc8, 0xab, 0xc7, 0xad, 0x4a, 0x3f, 0xe2, + 0xb1, 0xbb, 0xce, 0x8a, 0xc3, 0xa6, 0xc7, 0xbe, 0xc5, 0x8b, 0xe2, 0xb1, 0xbe, 0xc2, + 0xac, 0xc8, 0xbb, 0xc6, 0xb8, 0xc4, 0x8d, 0x5a, + ], + asset_base: [ + 0xf1, 0xfb, 0x77, 0xa6, 0xf4, 0x53, 0x77, 0x23, 0x9c, 0x47, 0x57, 0xff, 0xee, 0xe4, + 0xb2, 0x66, 0x42, 0x1b, 0xfc, 0x50, 0x00, 0xe3, 0x27, 0x68, 0x85, 0x5f, 0xa0, 0x6a, + 0x0f, 0x5d, 0xe2, 0x27, + ], + }, + TestVector { + key: [ + 0xbf, 0x39, 0x20, 0xce, 0x2e, 0x9e, 0x95, 0xb0, 0xee, 0xce, 0x13, 0x0a, 0x50, 0xba, + 0x7d, 0xcc, 0x6f, 0x26, 0x51, 0x2a, 0x9f, 0xc7, 0xb8, 0x04, 0xaf, 0xf0, 0x89, 0xf5, + 0x0c, 0xbc, 0xff, 0xf7, + ], + description: [ + 0x2d, 0xc4, 0x8b, 0xc5, 0xa1, 0xc2, 0xa3, 0xc6, 0x99, 0x41, 0xe2, 0xb1, 0xb6, 0x63, + 0x4a, 0xc5, 0xa5, 0xe2, 0xb1, 0xbe, 0xc2, 0xbe, 0xe1, 0x9b, 0x9a, 0xc7, 0xa1, 0xc3, + 0x85, 0xc7, 0xac, 0xc7, 0x99, 0xc3, 0x90, 0xc5, 0x98, 0xc7, 0x9d, 0xc6, 0x8d, 0xc8, + 0xad, 0xc8, 0xbe, 0x61, 0xc3, 0x9d, 0x55, 0x66, 0xc5, 0x89, 0xc6, 0x97, 0xc6, 0xb5, + 0xc3, 0xbe, 0xc4, 0x84, 0xc5, 0x96, 0xc3, 0x8c, 0xc7, 0xa5, 0xe1, 0x9b, 0x94, 0xc2, + 0xab, 0xc3, 0xbd, 0xc6, 0x95, 0x2b, 0xc8, 0x88, 0xc7, 0xa4, 0x68, 0xc8, 0xa5, 0xe1, + 0x9a, 0xbf, 0xc8, 0x84, 0xc4, 0x98, 0xc5, 0xa5, 0xe1, 0x9b, 0x8e, 0xe2, 0xb1, 0xba, + 0x28, 0xc6, 0xab, 0xc8, 0x93, 0xc7, 0xb5, 0xc2, 0xa1, 0xc5, 0x80, 0xc6, 0xb0, 0xc6, + 0x94, 0xc8, 0x84, 0xc2, 0xb7, 0xc5, 0x87, 0xe1, 0x9b, 0x9e, 0xc7, 0x93, 0x6c, 0xe1, + 0x9b, 0xa5, 0x41, 0x62, 0xcd, 0xb1, 0xc7, 0x94, 0xc8, 0xac, 0x3b, 0xc3, 0x95, 0xc4, + 0x83, 0xc6, 0xbb, 0xe2, 0xb1, 0xa2, 0xe1, 0x9a, 0xa6, 0xc9, 0x81, 0xe1, 0x9b, 0x85, + 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0x8c, 0xc3, 0xac, 0xc3, 0xa5, 0xc3, 0x80, 0xc3, 0x9d, + 0xc3, 0x9f, 0xc3, 0x96, 0xc3, 0xbb, 0xe2, 0xb1, 0xb4, 0xc8, 0xb1, 0x3b, 0xc5, 0x82, + 0x49, 0xc4, 0x90, 0xc4, 0xbd, 0xc9, 0x81, 0x4e, 0xc5, 0x8e, 0xc4, 0x94, 0xc3, 0xa7, + 0xc9, 0x89, 0xc6, 0x90, 0xc5, 0x8e, 0x3e, 0xe1, 0x9b, 0x99, 0x63, 0xc8, 0xb5, 0xc6, + 0xab, 0x38, 0xc8, 0xaf, 0xc5, 0xad, 0xc8, 0x8e, 0xc5, 0xab, 0xcd, 0xb0, 0xc5, 0xa3, + 0xc3, 0xb7, 0xc7, 0x85, 0xc2, 0xa7, 0x6d, 0xc2, 0xb7, 0x2f, 0xc3, 0xbd, 0xc7, 0x83, + 0xc5, 0xbb, 0xc2, 0xbf, 0xe2, 0xb1, 0xb8, 0xc4, 0xbc, 0xe1, 0x9b, 0xa5, 0xc7, 0x8c, + 0x71, 0x3d, 0xc7, 0xa0, 0xc9, 0x89, 0xc5, 0xb1, 0xc5, 0xa8, 0xc4, 0xa1, 0x5a, 0xe1, + 0x9a, 0xa4, 0xc7, 0xa6, 0xc6, 0x95, 0xc4, 0x90, 0xc7, 0x90, 0xe1, 0x9b, 0x90, 0xc3, + 0x92, 0xe1, 0x9a, 0xbd, 0xc7, 0xb2, 0xc7, 0xa9, 0xc6, 0xbb, 0xc6, 0x83, 0x21, 0xc9, + 0x87, 0xc3, 0x94, 0xc4, 0xac, 0xc2, 0xbf, 0xc4, 0x88, 0xc2, 0xa4, 0xc4, 0xbe, 0xc4, + 0xb2, 0xcd, 0xb6, 0xe2, 0xb1, 0xaa, 0xc9, 0x85, 0xc3, 0x97, 0xc8, 0x80, 0x78, 0xc8, + 0x95, 0xc6, 0x9f, 0xe1, 0x9b, 0xab, 0xc5, 0x8a, 0xc9, 0x82, 0xc8, 0x9a, 0x59, 0xe2, + 0xb1, 0xa7, 0xe1, 0x9b, 0xa2, 0x67, 0xc6, 0xb4, 0xc9, 0x8f, 0xc8, 0xbf, 0xc8, 0x85, + 0xc8, 0xb6, 0xc5, 0x94, 0x68, 0xe1, 0x9a, 0xaf, 0xe2, 0xb1, 0xa6, 0xc8, 0xae, 0xc4, + 0x89, 0xe1, 0x9a, 0xa2, 0xc7, 0xb9, 0xc8, 0xa0, 0xc2, 0xaf, 0xc7, 0x90, 0xc4, 0xb0, + 0xc4, 0xa7, 0xc5, 0xba, 0xc9, 0x82, 0xc3, 0x91, 0xe1, 0x9a, 0xa3, 0xc4, 0x92, 0x54, + 0xe1, 0x9a, 0xaa, 0xe1, 0x9b, 0xa7, 0xe1, 0x9a, 0xac, 0xc4, 0xb5, 0xe1, 0x9b, 0x9c, + 0xc5, 0x91, 0xce, 0x8c, 0xc5, 0xb1, 0x78, 0x66, 0xc5, 0x99, 0xcd, 0xbe, 0xc6, 0xa7, + 0xe1, 0x9b, 0x9e, 0xe2, 0xb1, 0xa4, 0xc3, 0x8e, 0x47, 0xc3, 0xae, 0xce, 0x86, 0x69, + 0xc6, 0x8a, 0xc3, 0x8e, 0xe1, 0x9b, 0xad, 0xc9, 0x88, 0xe1, 0x9b, 0x96, 0x7c, 0xe1, + 0x9b, 0x95, 0xc7, 0xba, 0xc8, 0xab, 0xe1, 0x9b, 0x85, 0xc7, 0x94, 0xc3, 0xa6, 0xe1, + 0x9b, 0xaa, 0x6d, 0xe1, 0x9a, 0xaf, 0xc4, 0x90, 0x79, 0xc3, 0xb5, 0xe2, 0xb1, 0xae, + 0x59, 0xc8, 0xab, 0xc8, 0xb2, 0xc8, 0xad, 0xe2, 0xb1, 0xb5, 0x50, 0xc5, 0xaf, 0x52, + 0xc6, 0xa6, 0xe1, 0x9b, 0x8b, 0xe1, 0x9a, 0xa5, 0x52, 0xcd, 0xbd, 0xc3, 0x86, 0x38, + 0xc4, 0xae, 0xc9, 0x81, 0xc5, 0x96, 0xc6, 0x94, + ], + asset_base: [ + 0x10, 0xc3, 0x37, 0x4c, 0xc5, 0xd2, 0x6d, 0x14, 0xda, 0x3d, 0x1d, 0x41, 0x7e, 0x60, + 0x2c, 0x75, 0x2e, 0xfe, 0x36, 0x4f, 0x6c, 0x2f, 0x9e, 0xf3, 0x93, 0x39, 0x1d, 0x1b, + 0x48, 0xd3, 0x35, 0x2c, + ], + }, + TestVector { + key: [ + 0x2a, 0x15, 0xb5, 0xe8, 0x6e, 0xe7, 0x0e, 0xe6, 0xab, 0xfb, 0xca, 0x6b, 0x2f, 0x15, + 0x6d, 0x43, 0xf1, 0x85, 0x7d, 0xb5, 0xcb, 0x5e, 0x6d, 0xd6, 0xb7, 0x23, 0x17, 0x20, + 0x05, 0xfc, 0x2f, 0x83, + ], + description: [ + 0x2c, 0xc3, 0x8b, 0x50, 0xe1, 0x9a, 0xb0, 0xc8, 0x96, 0xc7, 0xaf, 0x31, 0xc3, 0x9e, + 0xc3, 0x95, 0xc9, 0x87, 0xe1, 0x9b, 0x9f, 0x52, 0xe1, 0x9b, 0x8b, 0xc2, 0xb2, 0xc7, + 0x98, 0xe1, 0x9b, 0x84, 0xc2, 0xa6, 0xc2, 0xaa, 0xc7, 0xaa, 0xc3, 0x80, 0xc7, 0x95, + 0xc3, 0x8e, 0xe2, 0xb1, 0xba, 0x36, 0xc3, 0xa7, 0xc4, 0xa7, 0xe1, 0x9b, 0x8f, 0xe1, + 0x9b, 0x85, 0xc5, 0x87, 0xc7, 0xbb, 0xc5, 0x85, 0xc5, 0x93, 0xc5, 0x9c, 0xc8, 0x92, + 0x6b, 0xe1, 0x9b, 0x96, 0x78, 0xcd, 0xbe, 0xc4, 0x9a, 0xc7, 0x92, 0xc3, 0xb1, 0xc8, + 0xa8, 0xc3, 0x8b, 0x46, 0xc7, 0x94, 0xc5, 0x81, 0xc7, 0xa0, 0xc4, 0xb9, 0x78, 0x49, + 0xc5, 0xbb, 0xc5, 0xb5, 0xc5, 0x86, 0xc5, 0xb7, 0xc7, 0xb9, 0xc4, 0x86, 0xc5, 0xae, + 0xc7, 0xb4, 0x37, 0xc4, 0x89, 0x47, 0xe1, 0x9b, 0x88, 0xc6, 0x9d, 0xc4, 0xa8, 0xe2, + 0xb1, 0xa4, 0xc3, 0x9f, 0x3e, 0xc5, 0xa7, 0xc8, 0xbe, 0x41, 0xc9, 0x8a, 0xe1, 0x9a, + 0xad, 0xc2, 0xba, 0xc3, 0xba, 0xc4, 0x8b, 0xc5, 0x9b, 0xc5, 0xa7, 0x7a, 0xcd, 0xb6, + 0xc8, 0xb5, 0xc7, 0xa0, 0xc4, 0x81, 0xe1, 0x9b, 0x98, 0xc3, 0xb3, 0x72, 0xe1, 0x9a, + 0xad, 0xc6, 0x85, 0xcd, 0xb0, 0xce, 0x89, 0xc8, 0x86, 0xc3, 0x90, 0xc6, 0x83, 0x51, + 0xc7, 0x80, 0xc3, 0x8c, 0xe2, 0xb1, 0xa3, 0xc9, 0x8f, 0xc3, 0x8c, 0xc5, 0xad, 0xc3, + 0x86, 0xe1, 0x9b, 0xa7, 0x54, 0xc3, 0xb0, 0xce, 0x85, 0xc3, 0xbc, 0xe2, 0xb1, 0xa3, + 0xc4, 0x9f, 0x76, 0xc3, 0x91, 0xc5, 0xa0, 0xc4, 0x8f, 0xc5, 0x91, 0xc4, 0xa3, 0x33, + 0xc6, 0x9d, 0xe1, 0x9b, 0x8c, 0xc3, 0xa6, 0xc3, 0xb8, 0xe1, 0x9a, 0xa5, 0xe2, 0xb1, + 0xac, 0xc7, 0x9b, 0xc5, 0xaf, 0xc4, 0xb0, 0xe1, 0x9a, 0xb4, 0x4f, 0xe2, 0xb1, 0xa6, + 0x4e, 0x5f, 0xc8, 0xbf, 0xc3, 0xb3, 0xe1, 0x9b, 0x9a, 0xe1, 0x9a, 0xa4, 0xc7, 0x89, + 0xc6, 0x88, 0xcd, 0xbb, 0xc3, 0xa0, 0xc3, 0xb3, 0xcd, 0xb2, 0xc3, 0xbb, 0xc6, 0xa0, + 0xe1, 0x9b, 0xab, 0xc3, 0xa1, 0xc7, 0x97, 0x32, 0xe1, 0x9b, 0xa5, 0xc7, 0xac, 0xc5, + 0x9c, 0xc8, 0xbf, 0xc4, 0xbc, 0xc4, 0x8a, 0x3a, 0x60, 0xc6, 0x81, 0xe1, 0x9b, 0x80, + 0xc4, 0x82, 0xce, 0x89, 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0x9f, 0xc7, 0x92, 0xe2, 0xb1, + 0xa7, 0xe1, 0x9b, 0x82, 0xc7, 0x82, 0xe1, 0x9b, 0x91, 0xc6, 0xb5, 0x5e, 0xc7, 0xb0, + 0x3a, 0xc3, 0xa7, 0xce, 0x89, 0xe1, 0x9a, 0xbf, 0xc4, 0xbe, 0xc5, 0x9e, 0xc5, 0xb0, + 0xe2, 0xb1, 0xb6, 0xc9, 0x8f, 0xc8, 0x94, 0xc3, 0xbd, 0x6b, 0x4c, 0xc3, 0xad, 0xc8, + 0xb3, 0xc4, 0x99, 0xc3, 0xa5, 0xe2, 0xb1, 0xaf, 0xc4, 0x9d, 0x24, 0xc3, 0x91, 0xc5, + 0xa6, 0xc2, 0xaa, 0xe1, 0x9a, 0xb9, 0xc5, 0x9d, 0xc3, 0xab, 0xc5, 0xa3, 0xc6, 0xb6, + 0xe1, 0x9a, 0xac, 0x73, 0x7d, 0x4f, 0xe2, 0xb1, 0xb9, 0xc3, 0x8d, 0xc2, 0xa9, 0x57, + 0x2f, 0xc4, 0x99, 0xc7, 0xa6, 0xc6, 0xbb, 0xe2, 0xb1, 0xa5, 0xc3, 0xb7, 0x70, 0xc6, + 0x8c, 0xc6, 0xa9, 0xc7, 0xbf, 0xc2, 0xa7, 0xc3, 0xa2, 0xc2, 0xb0, 0xc8, 0x81, 0xc3, + 0x81, 0xe1, 0x9a, 0xba, 0xc5, 0x9c, 0xc4, 0x90, 0xc4, 0xa7, 0x71, 0xc8, 0xa9, 0xe1, + 0x9b, 0x9c, 0xe2, 0xb1, 0xab, 0x3e, 0x78, 0xc2, 0xb1, 0xc5, 0x88, 0xc4, 0xb1, 0xc7, + 0x9e, 0x38, 0xc8, 0xac, 0x71, 0xcd, 0xba, 0xc8, 0xba, 0x69, 0xc3, 0x8a, 0xcd, 0xbd, + 0xe1, 0x9b, 0xb0, 0xc8, 0x99, 0xc7, 0xbb, 0xc8, 0xb2, 0xc9, 0x8e, 0xc8, 0xac, 0xc2, + 0xa9, 0xc3, 0xb1, 0x3e, 0xc5, 0xbf, 0xc8, 0x8a, 0xe2, 0xb1, 0xaf, 0xc7, 0xaf, 0xc7, + 0x88, 0x5b, 0x4b, 0xe1, 0x9b, 0x87, 0x5a, 0x5a, + ], + asset_base: [ + 0x66, 0x9e, 0x20, 0x80, 0x8b, 0xa2, 0xa4, 0xd1, 0x31, 0xed, 0xeb, 0x7a, 0x39, 0x11, + 0xb1, 0xe1, 0x24, 0xd3, 0x77, 0x56, 0xd5, 0xb1, 0x3c, 0x61, 0xc6, 0x47, 0x73, 0x41, + 0xd2, 0x47, 0x57, 0xb6, + ], + }, + TestVector { + key: [ + 0x48, 0xbe, 0xf1, 0xc3, 0x4e, 0x8a, 0x86, 0x4c, 0x7e, 0xaa, 0x0c, 0x85, 0x31, 0x63, + 0x83, 0xc3, 0xf1, 0xc9, 0xb1, 0x87, 0xd5, 0x01, 0x74, 0xb4, 0x9a, 0xfe, 0xbd, 0x99, + 0xc3, 0xa1, 0xaf, 0xf9, + ], + description: [ + 0x5d, 0xc7, 0x88, 0xc2, 0xb9, 0x61, 0xc8, 0xb0, 0xc3, 0x98, 0xe2, 0xb1, 0xab, 0xc6, + 0xa9, 0xc8, 0xa7, 0xe2, 0xb1, 0xa9, 0xc5, 0xbb, 0x3a, 0x68, 0xc7, 0x83, 0xc8, 0xa1, + 0xc8, 0xbd, 0xc4, 0x9e, 0x6c, 0xc3, 0xab, 0xe1, 0x9b, 0xaf, 0xe1, 0x9b, 0x83, 0xc6, + 0xb7, 0xc2, 0xa4, 0xc4, 0x81, 0xc7, 0x9c, 0xc5, 0xb2, 0xe1, 0x9a, 0xaf, 0xe1, 0x9a, + 0xab, 0xc5, 0x88, 0xe1, 0x9a, 0xb0, 0xc6, 0xac, 0x63, 0xe1, 0x9b, 0xb0, 0xc7, 0xbe, + 0xc6, 0x8a, 0x3c, 0xc5, 0xb2, 0xc3, 0x89, 0xc2, 0xb0, 0x3d, 0xc2, 0xba, 0xe1, 0x9b, + 0x84, 0xc5, 0x8b, 0xe2, 0xb1, 0xb9, 0xc5, 0x91, 0x39, 0xc6, 0xb6, 0xc7, 0x9e, 0xc8, + 0x81, 0x74, 0xc7, 0xa8, 0xc8, 0xb0, 0xc2, 0xb6, 0xc4, 0x88, 0xc3, 0x9d, 0xc7, 0x89, + 0xc9, 0x8c, 0xc4, 0x85, 0xc3, 0x93, 0xc7, 0xaa, 0xc5, 0xb6, 0xc7, 0x9a, 0xc3, 0xae, + 0xe1, 0x9b, 0x81, 0xc3, 0x96, 0xc5, 0x80, 0xc5, 0x92, 0xc2, 0xa1, 0xc6, 0xa3, 0xe1, + 0x9a, 0xb7, 0xc2, 0xbf, 0xc5, 0xbb, 0xc7, 0xa9, 0xc7, 0x85, 0xc8, 0xbd, 0xc3, 0x8b, + 0xc7, 0xa6, 0xc3, 0xa0, 0xc6, 0x90, 0xe1, 0x9a, 0xb7, 0xc8, 0x88, 0xc4, 0x91, 0xc8, + 0x94, 0xc8, 0x9b, 0x6d, 0xc3, 0xa3, 0xc3, 0xb8, 0xc6, 0x88, 0xc5, 0xb1, 0x6e, 0xc7, + 0x87, 0x40, 0xc6, 0x8f, 0x7a, 0xc8, 0xa8, 0xc3, 0xb4, 0x46, 0xc3, 0xac, 0xc6, 0xa7, + 0xc6, 0x9c, 0xc8, 0x95, 0xc6, 0x87, 0xc6, 0x84, 0xc6, 0xb5, 0xc8, 0x97, 0xc3, 0xb8, + 0x69, 0x48, 0xe1, 0x9a, 0xaf, 0x53, 0xc4, 0xb8, 0xc3, 0x9c, 0xc4, 0xa8, 0xc5, 0xa6, + 0xc2, 0xbd, 0xc4, 0x92, 0xc2, 0xaf, 0xc2, 0xaf, 0xc4, 0xbb, 0xc7, 0x8c, 0xc3, 0xb9, + 0xc6, 0xb5, 0xc8, 0xa2, 0xc5, 0xb1, 0xc3, 0x81, 0xc6, 0x86, 0xc9, 0x8a, 0x4d, 0xc4, + 0xb8, 0xc4, 0xb4, 0xe1, 0x9a, 0xbf, 0xc2, 0xa2, 0xc4, 0x8d, 0xce, 0x87, 0xe2, 0xb1, + 0xbb, 0xe2, 0xb1, 0xa1, 0xc3, 0x87, 0xe1, 0x9a, 0xae, 0xc6, 0xb2, 0xc6, 0xa7, 0xc9, + 0x8d, 0xe1, 0x9b, 0xa8, 0xc4, 0x9a, 0xcd, 0xb1, 0xc5, 0x98, 0xc4, 0xbb, 0xc5, 0x95, + 0xc9, 0x8b, 0x61, 0xe2, 0xb1, 0xbf, 0xc3, 0xa6, 0xc5, 0xbd, 0xc4, 0x9c, 0xce, 0x85, + 0xe2, 0xb1, 0xa0, 0xc5, 0xbf, 0xc5, 0xbf, 0x34, 0xc7, 0x82, 0xcd, 0xb6, 0xe1, 0x9b, + 0x95, 0xc5, 0xaf, 0xc5, 0x98, 0xc8, 0x9f, 0xc2, 0xb8, 0xc4, 0xa5, 0xc5, 0xb8, 0xc4, + 0xad, 0xc8, 0xaf, 0xc6, 0x81, 0x6b, 0xc4, 0x8b, 0x55, 0xc7, 0xbe, 0xc3, 0xb4, 0xc6, + 0xa2, 0x62, 0xc8, 0xa0, 0xc3, 0x8d, 0xc3, 0xa8, 0x75, 0xc5, 0x90, 0xcd, 0xb1, 0x4d, + 0xc7, 0x9a, 0xc5, 0x87, 0xc5, 0xb5, 0xc6, 0x88, 0x25, 0xe2, 0xb1, 0xac, 0xc7, 0xa3, + 0xc9, 0x8d, 0xc8, 0x98, 0x6b, 0xc4, 0x9b, 0xc7, 0x90, 0xc8, 0x8e, 0xc8, 0x86, 0x36, + 0xe1, 0x9a, 0xaa, 0xc4, 0xa8, 0xe1, 0x9a, 0xa9, 0xc2, 0xb9, 0xe1, 0x9a, 0xb6, 0xc2, + 0xa8, 0xc2, 0xa4, 0xc3, 0x9a, 0xc3, 0x86, 0xc4, 0xb4, 0xc7, 0xa1, 0x53, 0xe2, 0xb1, + 0xa5, 0xc5, 0xa1, 0xe1, 0x9b, 0xa2, 0xc5, 0xaa, 0xc8, 0xa1, 0x2d, 0xc8, 0x96, 0x75, + 0xc2, 0xa6, 0xe1, 0x9b, 0x9b, 0xc6, 0xbb, 0xc9, 0x86, 0xc4, 0xa3, 0xc5, 0xb1, 0xe1, + 0x9b, 0x92, 0x39, 0x79, 0x5b, 0xc4, 0xbd, 0xe1, 0x9b, 0xa2, 0xe1, 0x9a, 0xa3, 0xc5, + 0xb6, 0xc8, 0x99, 0xc2, 0xb3, 0xe1, 0x9b, 0x8d, 0xc3, 0xbd, 0xc3, 0x86, 0xc4, 0x89, + 0xe2, 0xb1, 0xb2, 0xe1, 0x9b, 0xb0, 0x73, 0xe1, 0x9b, 0x9a, 0x34, 0xc4, 0x8a, 0x56, + 0xc2, 0xb5, 0xc4, 0xba, 0xe2, 0xb1, 0xa7, 0xc7, 0xa4, 0xcd, 0xbe, 0xe2, 0xb1, 0xb6, + 0xc8, 0xbc, 0xc8, 0x81, 0xc7, 0xac, 0xc8, 0x8e, + ], + asset_base: [ + 0x31, 0x1a, 0x81, 0xd9, 0x40, 0x52, 0x81, 0x50, 0xe5, 0xb4, 0x70, 0x97, 0x96, 0xb6, + 0x03, 0x22, 0x7a, 0xd1, 0xde, 0x1c, 0x15, 0x00, 0xef, 0x44, 0x5c, 0x40, 0xa4, 0xb2, + 0xaa, 0x21, 0xa1, 0x06, + ], + }, + TestVector { + key: [ + 0xff, 0x08, 0xec, 0x66, 0x3e, 0x18, 0x56, 0x51, 0x3f, 0xf6, 0x90, 0x80, 0x0c, 0x56, + 0x49, 0x91, 0xb2, 0x51, 0x67, 0xc2, 0xdd, 0x14, 0x07, 0x98, 0x13, 0x73, 0xc6, 0xd5, + 0x30, 0x65, 0xe3, 0x67, + ], + description: [ + 0xe1, 0x9b, 0x9e, 0xe1, 0x9a, 0xba, 0xc5, 0x9e, 0xe1, 0x9b, 0xa0, 0xc5, 0xbd, 0xe2, + 0xb1, 0xb8, 0xc8, 0x99, 0xc6, 0xb6, 0xc5, 0x9b, 0xc3, 0x83, 0xc2, 0xbd, 0xe1, 0x9a, + 0xbb, 0xe1, 0x9b, 0xa3, 0xc7, 0x8b, 0xc5, 0xb1, 0xc4, 0x9e, 0xe1, 0x9b, 0xa5, 0xe2, + 0xb1, 0xa5, 0xc8, 0xac, 0x58, 0xcd, 0xb2, 0xc6, 0x88, 0xc6, 0x85, 0xc7, 0x90, 0xc6, + 0x81, 0xe2, 0xb1, 0xb7, 0xc3, 0xb7, 0xc8, 0xb8, 0x7b, 0xe1, 0x9a, 0xb8, 0x64, 0xc4, + 0x85, 0x5f, 0xcd, 0xb3, 0xc8, 0xb1, 0xc9, 0x87, 0xc4, 0xbf, 0xc5, 0xbe, 0x2f, 0xe1, + 0x9b, 0x8c, 0xc7, 0xbc, 0xc5, 0xab, 0xe1, 0x9a, 0xb6, 0xe2, 0xb1, 0xa9, 0xc6, 0xb7, + 0xc4, 0x89, 0x63, 0xc3, 0xa5, 0xc2, 0xbf, 0xc6, 0x9b, 0x5c, 0xc5, 0x93, 0xc6, 0xb0, + 0xc4, 0xaa, 0xc8, 0xb3, 0xc8, 0x89, 0xc7, 0xbc, 0xc2, 0xa7, 0xc7, 0xa9, 0xc8, 0xb2, + 0xc7, 0xbd, 0xe1, 0x9b, 0xa5, 0xc5, 0xb5, 0xc4, 0x8e, 0xc9, 0x82, 0xc5, 0x84, 0xc6, + 0x86, 0xc3, 0x8f, 0xc4, 0x85, 0xc6, 0xa0, 0xc8, 0xa3, 0xc6, 0xa6, 0xe1, 0x9a, 0xa9, + 0xc5, 0x99, 0xc2, 0xa8, 0xc7, 0xbc, 0xe2, 0xb1, 0xbb, 0xc4, 0xa4, 0xc6, 0xb9, 0xc7, + 0x90, 0xc9, 0x8c, 0xc3, 0x80, 0xc7, 0x8f, 0xc5, 0x94, 0xc8, 0x88, 0xc9, 0x86, 0xc3, + 0xbd, 0xe2, 0xb1, 0xb1, 0xe2, 0xb1, 0xbe, 0x3c, 0xc6, 0x87, 0x7c, 0x6f, 0xc3, 0xbd, + 0xc6, 0x94, 0xc2, 0xa1, 0x7d, 0xc3, 0x87, 0xc2, 0xac, 0xcd, 0xb3, 0xc8, 0xa3, 0xc2, + 0xbb, 0x61, 0xc4, 0x97, 0xc9, 0x8d, 0x6c, 0xe2, 0xb1, 0xad, 0xc5, 0x8c, 0xc5, 0xa3, + 0xc2, 0xb2, 0xe2, 0xb1, 0xbf, 0xc5, 0xa2, 0xe1, 0x9b, 0x85, 0xc6, 0xb0, 0x78, 0xe1, + 0x9b, 0x80, 0xcd, 0xb6, 0xc5, 0x80, 0xc8, 0x99, 0xc2, 0xba, 0xc3, 0x96, 0xc6, 0x8c, + 0xc7, 0xaf, 0xc4, 0x97, 0xc3, 0x8b, 0xc4, 0xa4, 0xc6, 0xb0, 0xc7, 0x98, 0xc4, 0x8d, + 0x62, 0xc8, 0x8b, 0xc6, 0xaf, 0x4d, 0xc8, 0xb7, 0xc8, 0x8c, 0x5e, 0xc2, 0xab, 0xc4, + 0x86, 0xc5, 0xb1, 0x2c, 0xe2, 0xb1, 0xad, 0xe1, 0x9b, 0xa7, 0xc9, 0x8a, 0xc3, 0xb1, + 0xc3, 0xae, 0xc4, 0x98, 0xc7, 0xbe, 0xc5, 0x94, 0xc3, 0x8a, 0xce, 0x89, 0xcd, 0xbb, + 0xc6, 0xbc, 0xcd, 0xb1, 0xc4, 0x8a, 0xc5, 0x90, 0xc6, 0xa9, 0xe1, 0x9b, 0x85, 0xc9, + 0x8c, 0x63, 0xe1, 0x9a, 0xab, 0x57, 0xc3, 0xb7, 0xc6, 0xb9, 0xce, 0x86, 0xc4, 0xa7, + 0xc3, 0x80, 0xc8, 0xb6, 0xe1, 0x9b, 0x9c, 0xcd, 0xb6, 0xc3, 0xa3, 0xc4, 0x9c, 0xe2, + 0xb1, 0xa7, 0xc7, 0x88, 0xc4, 0xb6, 0xc8, 0x80, 0xe1, 0x9b, 0x95, 0x33, 0xc2, 0xb6, + 0xc6, 0x86, 0xc6, 0xae, 0xc6, 0x97, 0xc7, 0x9b, 0xc7, 0xbf, 0xc6, 0x95, 0xe1, 0x9b, + 0xab, 0xc5, 0x8b, 0x58, 0xc7, 0x9a, 0xc8, 0x81, 0xc2, 0xb2, 0xc3, 0x8a, 0xc9, 0x81, + 0xc6, 0x84, 0xc6, 0xb5, 0xc5, 0xa6, 0xc5, 0xaf, 0xc9, 0x8e, 0xc2, 0xbc, 0xc7, 0xb5, + 0xe1, 0x9b, 0x8b, 0xc8, 0x8c, 0xc9, 0x89, 0xe1, 0x9b, 0x91, 0xe1, 0x9a, 0xb8, 0x3b, + 0xc5, 0x88, 0xc2, 0xa5, 0xc8, 0xa0, 0xc4, 0x97, 0xe1, 0x9b, 0x8d, 0xc2, 0xa4, 0xc3, + 0x83, 0xc3, 0x9a, 0x4c, 0xe1, 0x9b, 0x80, 0xc4, 0xa5, 0xc3, 0xa9, 0xc9, 0x80, 0xc7, + 0xb3, 0xc7, 0xb4, 0xe1, 0x9b, 0x80, 0xe1, 0x9b, 0x8e, 0xc5, 0xb9, 0xc2, 0xb9, 0xc6, + 0xb7, 0xc8, 0xbc, 0xc5, 0xa6, 0xc4, 0x83, 0xe1, 0x9b, 0x80, 0xc8, 0x92, 0xc4, 0x94, + 0xe1, 0x9b, 0x8c, 0xc8, 0xbc, 0xc4, 0x8e, 0xe2, 0xb1, 0xb3, 0x38, 0xc8, 0x8d, 0xc9, + 0x8c, 0xc6, 0xbd, 0xc3, 0x90, 0xc6, 0xa9, 0xc3, 0xb6, 0x66, 0x38, 0xc8, 0x97, 0xe1, + 0x9a, 0xa1, 0xc8, 0xb2, 0xc5, 0xab, 0xc7, 0x99, + ], + asset_base: [ + 0x4f, 0x95, 0x9d, 0x88, 0x63, 0xb8, 0x36, 0x0b, 0x43, 0x30, 0x2b, 0xef, 0x35, 0x13, + 0x1f, 0x69, 0xd4, 0xf4, 0x26, 0xb1, 0x38, 0x3e, 0x54, 0xae, 0x38, 0x96, 0x40, 0x31, + 0xa8, 0xe5, 0xf9, 0x21, + ], + }, + TestVector { + key: [ + 0x39, 0xc4, 0x51, 0xf4, 0xd8, 0xdd, 0xcf, 0x69, 0x05, 0xed, 0xd8, 0x82, 0x5a, 0xd9, + 0x81, 0xb9, 0xe7, 0x3c, 0xa6, 0x83, 0x1c, 0xa2, 0xb3, 0xd7, 0xe8, 0xce, 0xf3, 0xd0, + 0xba, 0xaa, 0x31, 0x1b, + ], + description: [ + 0xc7, 0x94, 0xc5, 0xac, 0xc4, 0x97, 0xc6, 0xba, 0xe1, 0x9b, 0x97, 0xc7, 0x84, 0xc8, + 0xb6, 0xe1, 0x9b, 0x9d, 0xc8, 0x9c, 0xcd, 0xb5, 0xc3, 0x93, 0x7d, 0xc8, 0xa7, 0xc4, + 0x86, 0xc6, 0xab, 0xc4, 0x88, 0xe2, 0xb1, 0xb1, 0x6b, 0xe1, 0x9a, 0xa6, 0x68, 0xc6, + 0x9c, 0xc2, 0xb0, 0xc6, 0xba, 0xc7, 0xa6, 0xc5, 0x8c, 0xc9, 0x89, 0xc8, 0xbe, 0xc3, + 0xbc, 0xc5, 0xb7, 0xc7, 0x95, 0x5c, 0xc3, 0x96, 0xc4, 0x89, 0xc6, 0x84, 0xc3, 0xb2, + 0xc9, 0x87, 0x38, 0x45, 0xc3, 0xa1, 0xe2, 0xb1, 0xb1, 0x41, 0xc5, 0xac, 0xc6, 0xa1, + 0xc2, 0xa4, 0x34, 0xc4, 0xb0, 0xc2, 0xb5, 0xc5, 0xa2, 0xe1, 0x9a, 0xa9, 0xc4, 0xb6, + 0xc5, 0xbd, 0xc2, 0xbd, 0xc4, 0xa2, 0xc6, 0x8c, 0xc2, 0xb4, 0xc8, 0xb1, 0xc3, 0x95, + 0xc2, 0xbf, 0xc7, 0x99, 0xe1, 0x9b, 0x99, 0xc6, 0x8a, 0xc8, 0xaf, 0xc6, 0x9f, 0xc4, + 0x93, 0x38, 0xc7, 0x94, 0xc8, 0xa2, 0xc8, 0x84, 0xc6, 0x8f, 0x3a, 0xc5, 0xbd, 0xe1, + 0x9b, 0x97, 0xc5, 0x88, 0xcd, 0xb6, 0xc5, 0xa1, 0xc6, 0x96, 0xc4, 0x9f, 0xc3, 0x94, + 0xc5, 0xa6, 0xc4, 0xa4, 0xcd, 0xb2, 0xc7, 0xbc, 0xc8, 0x8d, 0x78, 0xc9, 0x86, 0xe2, + 0xb1, 0xab, 0xce, 0x84, 0xcd, 0xbd, 0xc4, 0x95, 0x65, 0xc7, 0x88, 0xc4, 0x84, 0xce, + 0x8c, 0xc3, 0xb1, 0xc2, 0xaf, 0xc6, 0xbf, 0xc4, 0x92, 0x25, 0xc7, 0xbc, 0xe2, 0xb1, + 0xb0, 0xc5, 0x93, 0xc7, 0x8a, 0xc5, 0x92, 0x75, 0xc4, 0xb7, 0xc6, 0x86, 0xc3, 0xbf, + 0xc7, 0xb7, 0xc6, 0xae, 0x67, 0xc2, 0xa9, 0xc6, 0x9e, 0xc5, 0x97, 0xcd, 0xb0, 0xc3, + 0x92, 0xc3, 0xac, 0xc5, 0xbb, 0xc3, 0x9a, 0xc3, 0xa1, 0xc6, 0x87, 0xc3, 0x8e, 0xc3, + 0xb8, 0xc9, 0x80, 0xe1, 0x9a, 0xa7, 0xc7, 0xac, 0x65, 0x24, 0xc6, 0x9c, 0xc3, 0xb2, + 0xc4, 0x82, 0x64, 0xc7, 0x8e, 0xc5, 0x8b, 0xe1, 0x9b, 0x8a, 0xe1, 0x9b, 0x89, 0xc9, + 0x82, 0xc3, 0x97, 0xc2, 0xac, 0xc4, 0x80, 0xc6, 0x83, 0xc4, 0xa6, 0xc4, 0xb6, 0xce, + 0x89, 0x52, 0x59, 0xce, 0x85, 0xc9, 0x85, 0xc6, 0xa9, 0xc4, 0x80, 0xc9, 0x8b, 0xe1, + 0x9a, 0xbe, 0xc9, 0x8e, 0xc2, 0xae, 0xc8, 0x96, 0xc6, 0x95, 0xc8, 0xaa, 0xe1, 0x9b, + 0x9b, 0xe1, 0x9a, 0xac, 0xc2, 0xb1, 0xc2, 0xaf, 0xc8, 0x8e, 0xe1, 0x9a, 0xae, 0xe1, + 0x9a, 0xa7, 0xc4, 0xb7, 0xc8, 0x82, 0xc3, 0xb2, 0xc4, 0xab, 0xc4, 0xbf, 0xc7, 0x91, + 0xe1, 0x9b, 0x9b, 0xc8, 0x90, 0xc7, 0x93, 0xe1, 0x9b, 0xa3, 0xc7, 0xb5, 0xc5, 0xa0, + 0xc8, 0xa2, 0xc8, 0x86, 0xc9, 0x86, 0xc2, 0xaa, 0x3d, 0xc4, 0xbf, 0xc5, 0xbc, 0xc4, + 0x96, 0xc3, 0xa5, 0xc3, 0x90, 0xc5, 0xb9, 0xc3, 0xa8, 0xc7, 0x80, 0xc5, 0x84, 0xce, + 0x89, 0xcd, 0xb7, 0xc3, 0x9b, 0xc2, 0xa1, 0xc7, 0x87, 0xcd, 0xb3, 0xe2, 0xb1, 0xb0, + 0xc8, 0x8b, 0xe1, 0x9a, 0xb1, 0xe1, 0x9a, 0xaf, 0x35, 0xc3, 0xa9, 0xc7, 0x85, 0xc4, + 0x85, 0xcd, 0xb1, 0xc4, 0xa7, 0xc3, 0x83, 0xe1, 0x9b, 0x94, 0xe2, 0xb1, 0xbf, 0xc4, + 0x80, 0x29, 0x2a, 0xc3, 0xa2, 0xe1, 0x9b, 0x88, 0xc3, 0x87, 0xe1, 0x9a, 0xb0, 0xc2, + 0xb8, 0xc7, 0x85, 0xc8, 0xb3, 0xc5, 0x84, 0x63, 0xc5, 0x8d, 0x3b, 0xc8, 0x9f, 0x5e, + 0xe2, 0xb1, 0xa5, 0x5c, 0xc4, 0x9f, 0xc8, 0xb4, 0xe2, 0xb1, 0xa0, 0xc7, 0xa5, 0x37, + 0xc6, 0xa2, 0xc8, 0xad, 0xe1, 0x9b, 0xa3, 0xc8, 0x96, 0xc6, 0xb6, 0xe2, 0xb1, 0xa4, + 0xc2, 0xb7, 0xc3, 0x86, 0xc4, 0xb1, 0xc6, 0x9f, 0xc8, 0x8c, 0xc8, 0xb3, 0xe1, 0x9a, + 0xa6, 0xc7, 0xa2, 0xc3, 0xbd, 0xe1, 0x9b, 0x8e, 0xc3, 0x9d, 0x21, 0xe1, 0x9b, 0xa5, + 0xe1, 0x9b, 0x8a, 0xc8, 0xb2, 0x24, 0xc8, 0x91, + ], + asset_base: [ + 0x2c, 0x25, 0xd3, 0x35, 0xaf, 0xa2, 0xd5, 0x69, 0x72, 0x42, 0xf6, 0x18, 0x5c, 0x00, + 0x69, 0xd7, 0x9b, 0x33, 0xc8, 0x4a, 0x3f, 0x7f, 0x5c, 0x3c, 0x26, 0x5d, 0x3e, 0x88, + 0x45, 0xac, 0xcd, 0x0e, + ], + }, + TestVector { + key: [ + 0xa2, 0x8d, 0x36, 0xc0, 0xa0, 0xe1, 0xd6, 0x54, 0x57, 0x44, 0x64, 0xec, 0x5e, 0x0c, + 0x8d, 0x87, 0x85, 0x6e, 0xb9, 0xdf, 0xd2, 0x1d, 0x4d, 0xa2, 0xb9, 0xea, 0x34, 0xfd, + 0xe7, 0x3b, 0x19, 0x42, + ], + description: [ + 0xc8, 0x96, 0xcd, 0xba, 0xc7, 0x94, 0x32, 0xc5, 0xbf, 0xc7, 0x9c, 0xc3, 0x94, 0xc5, + 0x97, 0xc7, 0x84, 0xc2, 0xb1, 0xc3, 0xa9, 0x25, 0xc2, 0xb6, 0xc7, 0x84, 0xce, 0x84, + 0xc7, 0x8d, 0xc8, 0xb3, 0xe1, 0x9a, 0xa3, 0xc3, 0xb1, 0xe1, 0x9a, 0xa4, 0xc7, 0xa6, + 0xc2, 0xa6, 0xe1, 0x9a, 0xb5, 0xc8, 0x97, 0x3f, 0xc7, 0x90, 0x55, 0xc3, 0x97, 0xc5, + 0xb6, 0xc5, 0xa3, 0xc7, 0x98, 0xc7, 0xba, 0xc7, 0xa7, 0xc8, 0x89, 0xc3, 0x80, 0xe2, + 0xb1, 0xb8, 0xc7, 0x8c, 0xc6, 0xa2, 0xc5, 0xb2, 0xc6, 0x90, 0xc4, 0x8f, 0xc4, 0x84, + 0xc7, 0xa3, 0xc2, 0xbd, 0x48, 0xc3, 0x97, 0xc7, 0x8b, 0xc7, 0x85, 0xc5, 0x83, 0xc7, + 0xb9, 0xe1, 0x9b, 0x96, 0xc8, 0x90, 0xc3, 0xbd, 0xe1, 0x9b, 0x99, 0xc8, 0x9b, 0xcd, + 0xb5, 0x28, 0xe1, 0x9b, 0xaa, 0xc5, 0x9a, 0xc6, 0xb7, 0x39, 0x75, 0x25, 0xc7, 0xb8, + 0xc5, 0xaa, 0xc8, 0xa5, 0xc5, 0xb3, 0xc7, 0x96, 0xc3, 0x8c, 0xc5, 0x87, 0x72, 0xe1, + 0x9a, 0xab, 0x72, 0xc9, 0x8b, 0xc3, 0xb0, 0xc8, 0x96, 0xc3, 0xb2, 0xc3, 0x82, 0x52, + 0x78, 0x68, 0x4d, 0xc5, 0x9e, 0xc5, 0x80, 0xe1, 0x9b, 0x84, 0xe2, 0xb1, 0xa6, 0xc6, + 0x8d, 0x51, 0xc8, 0xbe, 0xe1, 0x9b, 0x8d, 0xc2, 0xbc, 0xc6, 0xa8, 0xc7, 0x93, 0xc8, + 0x90, 0xc5, 0x99, 0x28, 0x6e, 0xc8, 0x95, 0x78, 0xe1, 0x9b, 0x83, 0xc4, 0xbe, 0xc8, + 0xb5, 0xc5, 0x80, 0x67, 0xc3, 0x9b, 0xe1, 0x9b, 0x89, 0xc5, 0x8c, 0x75, 0xc4, 0xb7, + 0xe1, 0x9b, 0x87, 0x47, 0xc3, 0xa9, 0xc5, 0x95, 0xc4, 0x93, 0xc3, 0x9d, 0xe1, 0x9b, + 0x82, 0xc7, 0x95, 0xc5, 0x84, 0xc5, 0x91, 0xe1, 0x9a, 0xa2, 0xc3, 0x95, 0xcd, 0xb6, + 0xe2, 0xb1, 0xbd, 0xc5, 0x91, 0xc4, 0xbb, 0xc7, 0x8a, 0xc7, 0xaa, 0xc8, 0xb3, 0xe1, + 0x9b, 0xa6, 0x5d, 0xcd, 0xb2, 0xc5, 0xab, 0xc4, 0xa0, 0x5b, 0xc2, 0xbe, 0x37, 0x60, + 0xc5, 0x8a, 0xe1, 0x9a, 0xbb, 0xc9, 0x82, 0xc5, 0xbd, 0xe1, 0x9b, 0xa0, 0xc3, 0x80, + 0xc7, 0xb0, 0xc7, 0xa7, 0xe1, 0x9b, 0xaf, 0x70, 0xc5, 0x98, 0xc4, 0x80, 0x5b, 0xc2, + 0xb1, 0xe2, 0xb1, 0xab, 0xc3, 0x8b, 0xc4, 0xa3, 0x2f, 0xc6, 0x9a, 0xc5, 0x84, 0x63, + 0xc3, 0xaf, 0xc3, 0x87, 0xe1, 0x9b, 0xa0, 0xc3, 0x82, 0x73, 0xc4, 0x98, 0xe1, 0x9b, + 0x91, 0xe1, 0x9a, 0xac, 0x76, 0xc9, 0x87, 0xc7, 0xa8, 0xc4, 0x90, 0xc2, 0xb1, 0x2e, + 0x4b, 0xc8, 0x8b, 0x58, 0xc8, 0xb1, 0xe1, 0x9a, 0xbf, 0xc8, 0xa2, 0xc6, 0x9f, 0xc4, + 0xab, 0xc4, 0xbf, 0xe1, 0x9b, 0x86, 0xe1, 0x9b, 0xa8, 0xce, 0x8c, 0xc5, 0xab, 0xc3, + 0x85, 0x75, 0xc3, 0xa7, 0xc7, 0xbc, 0xc7, 0xa5, 0xe2, 0xb1, 0xba, 0xc5, 0xad, 0x6b, + 0xc8, 0xbc, 0xc6, 0xb0, 0xc5, 0xa0, 0xc4, 0x8f, 0xc7, 0xbd, 0xe1, 0x9a, 0xa2, 0xc5, + 0x90, 0xc6, 0xa2, 0xc9, 0x84, 0xc6, 0xab, 0xc7, 0xb2, 0x7c, 0xc5, 0x86, 0x40, 0x3b, + 0xc3, 0x8f, 0xe1, 0x9a, 0xb4, 0xe2, 0xb1, 0xae, 0xc2, 0xb0, 0xc5, 0x90, 0xe2, 0xb1, + 0xad, 0xc3, 0x85, 0xcd, 0xba, 0xc3, 0x9d, 0xe1, 0x9b, 0xab, 0xe1, 0x9a, 0xbd, 0xc6, + 0xb8, 0xc6, 0xab, 0xc3, 0xb0, 0xc9, 0x87, 0xc5, 0xb0, 0xc2, 0xaa, 0xc8, 0x99, 0xc6, + 0x80, 0xc9, 0x84, 0xc4, 0xb6, 0xe1, 0x9b, 0x82, 0xc6, 0xa9, 0xc5, 0xac, 0x76, 0xce, + 0x85, 0xc6, 0xa9, 0xe1, 0x9b, 0xa5, 0xc3, 0xac, 0xc4, 0xa0, 0xe1, 0x9a, 0xa7, 0xc2, + 0xae, 0xc3, 0xb2, 0xc3, 0x83, 0xc6, 0xaa, 0xc5, 0x88, 0xe1, 0x9a, 0xab, 0xc4, 0x81, + 0xc4, 0x98, 0xc4, 0xa3, 0x62, 0x7d, 0xc6, 0x84, 0xc8, 0x85, 0xc5, 0x96, 0xc4, 0xad, + 0xe2, 0xb1, 0xbd, 0x34, 0xc6, 0x9c, 0x5a, 0x5a, + ], + asset_base: [ + 0x19, 0x8f, 0x36, 0xf8, 0x2b, 0xca, 0x02, 0x8c, 0x9f, 0x8d, 0x8d, 0x20, 0x9f, 0x4c, + 0x4a, 0xf6, 0xd1, 0x44, 0x90, 0x5e, 0xbb, 0x17, 0xda, 0xf4, 0x15, 0xd3, 0x1d, 0x4a, + 0xf3, 0x7c, 0x46, 0x2e, + ], + }, + TestVector { + key: [ + 0x28, 0x37, 0xcd, 0x45, 0x6e, 0x33, 0x19, 0x9f, 0x05, 0xb5, 0xd9, 0x0a, 0x42, 0xa7, + 0xb3, 0xd7, 0x13, 0xac, 0xd4, 0xec, 0xe6, 0xfe, 0x32, 0xdf, 0x77, 0xcb, 0x17, 0x00, + 0x43, 0xa2, 0xfa, 0xc6, + ], + description: [ + 0xc2, 0xb0, 0x5d, 0x32, 0xc3, 0x9a, 0xc3, 0x98, 0xc4, 0x88, 0xc5, 0x8f, 0xc4, 0xa4, + 0xc3, 0x81, 0xc7, 0x91, 0xe1, 0x9b, 0x9e, 0xc8, 0x9e, 0xc4, 0x86, 0xe1, 0x9b, 0xa6, + 0xc8, 0x89, 0xc8, 0x84, 0xce, 0x8c, 0xc9, 0x83, 0xe2, 0xb1, 0xac, 0xcd, 0xb2, 0xc3, + 0xb8, 0xc8, 0x81, 0x65, 0xc3, 0x82, 0xc3, 0x93, 0xc4, 0x81, 0x7e, 0xe1, 0x9a, 0xb0, + 0xc5, 0x82, 0xc9, 0x8f, 0xc4, 0xb9, 0xc3, 0xbe, 0xc8, 0x8d, 0xc7, 0xab, 0xce, 0x8c, + 0xe1, 0x9a, 0xb5, 0xc7, 0x8d, 0xc7, 0x87, 0xc7, 0xba, 0xc6, 0xa2, 0xc4, 0xa3, 0xc7, + 0x93, 0xc8, 0xa8, 0xc3, 0x90, 0xc2, 0xaa, 0x5f, 0xc7, 0xbb, 0xc3, 0xad, 0xe1, 0x9a, + 0xa1, 0xc8, 0xa7, 0xc3, 0xaa, 0x7e, 0xc3, 0xaa, 0xe2, 0xb1, 0xa0, 0xcd, 0xb1, 0xc4, + 0xa9, 0xc5, 0x98, 0x75, 0xc8, 0xa3, 0x5b, 0x2c, 0x44, 0xe2, 0xb1, 0xb4, 0xc6, 0x92, + 0xc3, 0x95, 0xc5, 0x8e, 0xc8, 0xa6, 0xc8, 0xb8, 0xc9, 0x82, 0xc7, 0x87, 0xc5, 0xa7, + 0xc8, 0x9f, 0x50, 0xc5, 0x9b, 0xc4, 0x9e, 0x56, 0x7c, 0xc5, 0xba, 0xc3, 0x85, 0xe1, + 0x9b, 0x8d, 0xe1, 0x9a, 0xbf, 0xc7, 0xaf, 0xc4, 0x89, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, + 0x95, 0xc8, 0xa8, 0xc6, 0xad, 0xe1, 0x9b, 0x80, 0xc7, 0x8d, 0x31, 0xc5, 0x83, 0xcd, + 0xb7, 0xc4, 0x9f, 0xc3, 0xa8, 0xc6, 0xa0, 0xe1, 0x9a, 0xa9, 0xc6, 0x8a, 0xc4, 0x9f, + 0x57, 0xc8, 0xaf, 0xc7, 0xa7, 0xe1, 0x9b, 0x9f, 0xc6, 0x88, 0xc8, 0xa4, 0xe2, 0xb1, + 0xbd, 0x3d, 0xc4, 0x83, 0xe1, 0x9b, 0xa1, 0x59, 0xe1, 0x9b, 0x94, 0x7c, 0x2b, 0xe1, + 0x9b, 0x86, 0xe1, 0x9a, 0xbb, 0xc7, 0xb7, 0xc9, 0x86, 0xc7, 0x9e, 0xc5, 0x82, 0xe2, + 0xb1, 0xb7, 0xc3, 0x98, 0xc5, 0xb9, 0xc3, 0xbe, 0xe1, 0x9b, 0x93, 0xc9, 0x87, 0xc7, + 0x92, 0xc9, 0x83, 0xc8, 0x8e, 0x30, 0xe1, 0x9b, 0x98, 0xc5, 0xba, 0xc6, 0x8a, 0x39, + 0x59, 0xc5, 0x96, 0xc4, 0x9f, 0xc7, 0x82, 0xe1, 0x9a, 0xb4, 0xc9, 0x8b, 0xc5, 0xbc, + 0xc3, 0xa6, 0xc8, 0x95, 0xc6, 0xa1, 0xc4, 0xba, 0xc6, 0xb0, 0xc5, 0xba, 0x7b, 0xc4, + 0x85, 0xc5, 0xb7, 0xc4, 0x85, 0xc7, 0x93, 0xc3, 0x8d, 0xc5, 0x85, 0xc7, 0xad, 0xc5, + 0x9e, 0xc4, 0xbc, 0xc2, 0xa4, 0xe1, 0x9b, 0x87, 0xc2, 0xab, 0xc8, 0xb1, 0xc6, 0x87, + 0x77, 0xc6, 0xb8, 0xc5, 0x85, 0xc4, 0x8c, 0xc7, 0xa3, 0xc3, 0x85, 0xc2, 0xb8, 0x42, + 0xc7, 0xa7, 0xce, 0x88, 0xe1, 0x9a, 0xaa, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0x9d, 0xe1, + 0x9b, 0xa6, 0xc6, 0xa4, 0xc7, 0x87, 0xc6, 0x81, 0xc4, 0x84, 0xc4, 0xae, 0xc9, 0x86, + 0xe2, 0xb1, 0xa8, 0xc2, 0xbc, 0xc4, 0x93, 0xe1, 0x9b, 0x88, 0xc7, 0x81, 0xc2, 0xa3, + 0xc4, 0xbf, 0xc7, 0x9d, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, 0xa1, 0xe1, 0x9a, 0xb1, 0xc8, + 0xb3, 0xc2, 0xb9, 0xe1, 0x9b, 0x9c, 0x37, 0x64, 0xc3, 0xbf, 0xe2, 0xb1, 0xb0, 0x42, + 0xc8, 0xae, 0x7e, 0xc7, 0x92, 0xc4, 0xbd, 0xc6, 0x98, 0xc3, 0xab, 0xc3, 0x9d, 0xc4, + 0xa4, 0xc5, 0x99, 0xc5, 0x84, 0xc3, 0xba, 0xc7, 0xa0, 0xc6, 0x92, 0xc8, 0xad, 0xc5, + 0xb8, 0xc4, 0xb6, 0xc7, 0x90, 0xc6, 0xa3, 0xc3, 0xab, 0xc3, 0x95, 0xc4, 0x91, 0xce, + 0x84, 0x30, 0xc4, 0xb5, 0xc7, 0x9a, 0xc6, 0x92, 0xc2, 0xba, 0xc3, 0x9e, 0xc7, 0x99, + 0xc4, 0x8d, 0xc3, 0x85, 0xc6, 0x87, 0xc7, 0x86, 0xc6, 0x82, 0xc6, 0x8a, 0x26, 0xc4, + 0x8b, 0xc4, 0xbe, 0x7c, 0x58, 0xc8, 0xa6, 0xc4, 0xab, 0xc4, 0xbe, 0xce, 0x8a, 0xc4, + 0xb7, 0xc3, 0xb9, 0xc5, 0x94, 0xe1, 0x9b, 0x9a, 0xc8, 0xbf, 0xc7, 0xa6, 0xc5, 0xbd, + 0xc4, 0xa8, 0xc5, 0x8f, 0xc5, 0xa3, 0xcd, 0xb4, + ], + asset_base: [ + 0x9a, 0xcc, 0xb2, 0xc5, 0xad, 0xae, 0x30, 0xab, 0xdb, 0x76, 0x58, 0x9d, 0xec, 0xdd, + 0x71, 0xe4, 0x65, 0x75, 0x53, 0x8d, 0x80, 0x3c, 0x28, 0xd7, 0xe4, 0xb8, 0x89, 0x6a, + 0xd7, 0xfd, 0xc6, 0x87, + ], + }, + TestVector { + key: [ + 0x0a, 0xbb, 0x5f, 0xa5, 0xab, 0x94, 0x0d, 0x29, 0x57, 0x4b, 0x95, 0x15, 0x9c, 0x40, + 0xbd, 0x79, 0x43, 0x44, 0xea, 0x07, 0xa8, 0x7e, 0x0f, 0x0f, 0x5f, 0xac, 0xa5, 0xb4, + 0x31, 0x81, 0x6d, 0xe2, + ], + description: [ + 0xcd, 0xbd, 0xe1, 0x9a, 0xb4, 0xc8, 0x9c, 0xc8, 0x96, 0xc6, 0xaa, 0xce, 0x88, 0xe1, + 0x9a, 0xb4, 0x2d, 0xc6, 0x81, 0xc7, 0x86, 0xc7, 0x9d, 0xc5, 0x86, 0xc4, 0x84, 0xe1, + 0x9b, 0x9e, 0xc6, 0x91, 0xe1, 0x9b, 0x89, 0x2d, 0xc4, 0x81, 0xc6, 0x88, 0x4c, 0xc2, + 0xbf, 0xc2, 0xaa, 0xc3, 0xb4, 0xc8, 0xae, 0xc7, 0x91, 0xc2, 0xb0, 0xc5, 0xa5, 0xc6, + 0xa3, 0xc4, 0x94, 0x38, 0xe1, 0x9a, 0xa9, 0xc4, 0xbe, 0xc3, 0x81, 0xe2, 0xb1, 0xba, + 0xc5, 0xa7, 0x44, 0xc3, 0xbb, 0xc8, 0x97, 0x5b, 0xc6, 0xbd, 0xc5, 0x9b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9a, 0xbd, 0xc2, 0xbf, 0xc3, 0x94, 0xc2, 0xb0, 0xc4, 0x9c, 0xc6, 0xa1, + 0xc3, 0xb6, 0xc2, 0xac, 0xe1, 0x9a, 0xa9, 0xc6, 0x90, 0x5c, 0xe2, 0xb1, 0xb2, 0x7c, + 0xc3, 0x86, 0x57, 0xe1, 0x9a, 0xa4, 0x71, 0xc7, 0x91, 0xe2, 0xb1, 0xbc, 0xc7, 0xab, + 0xc4, 0x86, 0xc5, 0xa1, 0xc5, 0x92, 0xc6, 0xa9, 0x78, 0x7a, 0xcd, 0xbd, 0xc4, 0xb2, + 0x75, 0xc8, 0xa4, 0x29, 0xc6, 0x9e, 0xc7, 0xa0, 0xc7, 0xa8, 0xc3, 0xa5, 0xc4, 0xb6, + 0xe1, 0x9b, 0x9d, 0x45, 0xc3, 0xa1, 0xc9, 0x8b, 0xc3, 0xbb, 0xc8, 0x86, 0xc7, 0x83, + 0xe1, 0x9b, 0x93, 0xc8, 0x9c, 0xc5, 0xba, 0xc7, 0xa8, 0xc7, 0x8d, 0xe1, 0x9a, 0xbf, + 0xcd, 0xb7, 0xc5, 0x91, 0xc4, 0x8f, 0x65, 0xc3, 0xa4, 0xc2, 0xb4, 0xe2, 0xb1, 0xb0, + 0xc8, 0xa9, 0xc8, 0xb1, 0xe1, 0x9b, 0x86, 0xc8, 0x85, 0xc4, 0x8d, 0xe1, 0x9a, 0xaf, + 0xe1, 0x9b, 0x81, 0xc3, 0xae, 0xc4, 0x90, 0xc8, 0xbb, 0x2a, 0xe1, 0x9a, 0xae, 0xc6, + 0xa3, 0xc4, 0xae, 0xc4, 0x93, 0x7b, 0xc7, 0x8e, 0xc8, 0x9c, 0xc3, 0xa3, 0xc5, 0xac, + 0xcd, 0xb7, 0x41, 0xc5, 0xb5, 0xc4, 0x95, 0xc3, 0x92, 0xc6, 0xaa, 0xe1, 0x9b, 0x83, + 0xe2, 0xb1, 0xb2, 0xe1, 0x9a, 0xbc, 0xc7, 0x87, 0xc7, 0xb7, 0xc5, 0x97, 0xc2, 0xb9, + 0x55, 0xe1, 0x9b, 0x91, 0x45, 0xc8, 0x8b, 0xe1, 0x9a, 0xa9, 0xe1, 0x9a, 0xad, 0xc6, + 0xab, 0xcd, 0xbd, 0xc8, 0xa2, 0xc3, 0x8c, 0x23, 0xe2, 0xb1, 0xa9, 0xe1, 0x9b, 0x8c, + 0xe1, 0x9a, 0xb7, 0xc6, 0x84, 0xc3, 0xa6, 0xc8, 0xb2, 0xc5, 0xbe, 0xc7, 0xbe, 0xe1, + 0x9a, 0xaa, 0xc3, 0xb1, 0xc6, 0xb3, 0xe1, 0x9a, 0xbe, 0xc4, 0xa0, 0xc2, 0xb9, 0x37, + 0xc5, 0x82, 0xc5, 0xbf, 0xc8, 0xa9, 0x44, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x9c, 0xe1, + 0x9b, 0xa6, 0xe1, 0x9b, 0x87, 0xe2, 0xb1, 0xaa, 0xc7, 0xab, 0xc7, 0xaf, 0xc7, 0x91, + 0xe2, 0xb1, 0xbf, 0xe1, 0x9a, 0xb9, 0xe1, 0x9b, 0x87, 0xc6, 0xb6, 0xc5, 0xa3, 0xc7, + 0x98, 0xc5, 0x90, 0xc8, 0x9b, 0xcd, 0xb2, 0xc4, 0x97, 0x7b, 0xe1, 0x9b, 0x96, 0xc3, + 0xa2, 0x6e, 0xc8, 0x90, 0x6f, 0xc6, 0x9e, 0xc9, 0x87, 0x6e, 0xc8, 0x82, 0xc4, 0x97, + 0xc3, 0xb0, 0xc4, 0x8d, 0xe2, 0xb1, 0xb6, 0xc7, 0x9b, 0xc3, 0x9a, 0xc8, 0xb5, 0xc6, + 0x95, 0xc3, 0xb6, 0x44, 0xc3, 0xac, 0xc5, 0x90, 0xe1, 0x9b, 0xa0, 0xc8, 0x92, 0x5d, + 0xc5, 0xad, 0xe1, 0x9b, 0xab, 0x7b, 0xc4, 0x97, 0xc7, 0xac, 0xe1, 0x9a, 0xb2, 0x2e, + 0xc3, 0xa8, 0xc6, 0xbc, 0x40, 0x23, 0xc6, 0xbf, 0x55, 0xc6, 0x82, 0xc7, 0x8a, 0x65, + 0xe1, 0x9b, 0x9b, 0xc3, 0xbc, 0xe2, 0xb1, 0xbd, 0x4b, 0xe2, 0xb1, 0xa7, 0xc6, 0x8d, + 0xc7, 0xae, 0xc3, 0x83, 0xc7, 0xb9, 0x64, 0xc6, 0xa6, 0xc8, 0x82, 0xc8, 0x9d, 0xc8, + 0x9f, 0xc8, 0xb2, 0xc6, 0x8c, 0xe2, 0xb1, 0xb8, 0xe1, 0x9b, 0xab, 0xc7, 0x9d, 0xc8, + 0xb5, 0xc5, 0xab, 0xcd, 0xba, 0x45, 0xe1, 0x9a, 0xab, 0xc3, 0x93, 0x37, 0xc2, 0xb8, + 0xc9, 0x8d, 0xc9, 0x88, 0xe1, 0x9b, 0x93, 0x5a, + ], + asset_base: [ + 0x1a, 0x28, 0x12, 0x59, 0x8b, 0xa7, 0x5c, 0x9a, 0x69, 0x2e, 0x69, 0x19, 0x65, 0x7f, + 0x68, 0x3e, 0xa4, 0x52, 0xe1, 0xae, 0x66, 0x33, 0xba, 0xcf, 0xe1, 0xf4, 0x54, 0x55, + 0x04, 0xc2, 0x95, 0xb4, + ], + }, + TestVector { + key: [ + 0x07, 0x82, 0x6a, 0x86, 0xb1, 0x72, 0xc5, 0x5a, 0x66, 0x40, 0x1e, 0x37, 0xfc, 0x69, + 0xf9, 0x2e, 0x6d, 0x62, 0xa0, 0x14, 0x6c, 0x67, 0x06, 0x29, 0xa2, 0xd6, 0x51, 0x34, + 0xdf, 0x3b, 0x22, 0xf6, + ], + description: [ + 0xc6, 0xbe, 0xc3, 0x90, 0xc3, 0x92, 0xc4, 0x97, 0x7e, 0xc6, 0x81, 0x34, 0xe1, 0x9b, + 0x86, 0xc8, 0x8e, 0x7e, 0xcd, 0xb4, 0xc6, 0x90, 0x7b, 0xc4, 0xae, 0xc7, 0x8a, 0xcd, + 0xbd, 0xc5, 0x98, 0xc5, 0xa2, 0xc2, 0xb7, 0x6a, 0xc5, 0x82, 0xc5, 0xac, 0xc2, 0xbf, + 0xc7, 0x83, 0x33, 0xe1, 0x9b, 0x87, 0xc5, 0xb8, 0xc8, 0xb7, 0xc5, 0xaa, 0xc5, 0xb1, + 0xc8, 0xbd, 0x47, 0x58, 0xc5, 0x90, 0xc6, 0x91, 0xc5, 0x89, 0x24, 0xc4, 0xbf, 0xc4, + 0x80, 0xc3, 0xa7, 0xc8, 0xaa, 0x69, 0x6e, 0xe1, 0x9b, 0xa0, 0xc2, 0xa1, 0x42, 0xc6, + 0x96, 0xc3, 0x9b, 0x76, 0x24, 0xcd, 0xbb, 0xc6, 0xaf, 0x52, 0x24, 0xc4, 0xa0, 0xe1, + 0x9b, 0x82, 0xc5, 0x82, 0xe1, 0x9b, 0x90, 0xc8, 0x92, 0xc5, 0xb1, 0xe2, 0xb1, 0xbd, + 0xc2, 0xb7, 0xc4, 0xa6, 0xce, 0x88, 0xe1, 0x9b, 0x91, 0x3e, 0x3b, 0xc8, 0x88, 0xc6, + 0xae, 0xe2, 0xb1, 0xa4, 0xc3, 0xa1, 0xc4, 0x84, 0xe1, 0x9a, 0xbd, 0xc3, 0x9c, 0xc8, + 0xa4, 0xe1, 0x9a, 0xba, 0xc7, 0xb1, 0xc2, 0xac, 0x6f, 0xc4, 0x87, 0xc8, 0xb9, 0xe1, + 0x9a, 0xae, 0xc2, 0xab, 0xc3, 0xad, 0xc3, 0xae, 0xc5, 0x8b, 0xc8, 0x9f, 0xce, 0x8c, + 0x4f, 0xc7, 0xbe, 0xc7, 0x8a, 0xc5, 0xbe, 0xc7, 0x92, 0xe1, 0x9b, 0x9d, 0xc5, 0x95, + 0xe1, 0x9a, 0xab, 0x57, 0xe1, 0x9a, 0xb0, 0xc4, 0x9e, 0x55, 0xc6, 0x96, 0xc4, 0xb2, + 0x29, 0xc9, 0x81, 0xc4, 0xa6, 0xc7, 0xa3, 0xc4, 0x91, 0xc6, 0x96, 0xc7, 0x80, 0xc7, + 0xb6, 0xe1, 0x9b, 0x8c, 0xc3, 0x9f, 0xc5, 0x92, 0xc8, 0x90, 0x72, 0xc6, 0x99, 0xe1, + 0x9a, 0xa3, 0x7e, 0xc3, 0xa6, 0x58, 0xc8, 0xb6, 0x6c, 0xc8, 0xb0, 0xc3, 0xbb, 0xe1, + 0x9a, 0xa4, 0xc2, 0xa5, 0xc3, 0x94, 0xcd, 0xb4, 0xc3, 0xb7, 0xc6, 0xa7, 0xc2, 0xaf, + 0xc4, 0xae, 0xc3, 0xa5, 0xe2, 0xb1, 0xb7, 0xe1, 0x9b, 0x86, 0x5d, 0xc5, 0x80, 0x3f, + 0xc6, 0x92, 0xc8, 0x8e, 0xc6, 0xb4, 0xc7, 0xac, 0xc6, 0xb4, 0xc3, 0xab, 0xc9, 0x8b, + 0xc4, 0x90, 0xe2, 0xb1, 0xa7, 0xc4, 0x96, 0xc4, 0x9a, 0xc8, 0xbd, 0xce, 0x87, 0xc6, + 0xaf, 0xc7, 0x83, 0x3c, 0xe1, 0x9b, 0xa2, 0xc2, 0xb4, 0xc4, 0x9d, 0x4d, 0xc3, 0x8a, + 0xc3, 0xa8, 0xc6, 0x93, 0x28, 0xc7, 0xbc, 0xc6, 0x9f, 0xe1, 0x9a, 0xa4, 0xc7, 0x8a, + 0xc7, 0xbd, 0xc3, 0x87, 0xe2, 0xb1, 0xb7, 0xc6, 0xac, 0xe1, 0x9b, 0x92, 0xc4, 0xa6, + 0xc5, 0x84, 0x3a, 0xc9, 0x8c, 0xc9, 0x8a, 0xc2, 0xa2, 0xc4, 0xae, 0xe1, 0x9a, 0xa8, + 0xc8, 0xa6, 0xc2, 0xbb, 0xe2, 0xb1, 0xa0, 0xc8, 0xab, 0xc7, 0x8a, 0xc7, 0x8a, 0xe1, + 0x9b, 0x97, 0xc4, 0x89, 0xc8, 0x9a, 0xe1, 0x9b, 0x91, 0xe1, 0x9b, 0x8b, 0x5c, 0xe1, + 0x9b, 0xa6, 0xc8, 0xa9, 0xc9, 0x80, 0x71, 0xc5, 0x95, 0xc8, 0xbd, 0xc5, 0x8f, 0xc5, + 0xa4, 0xc3, 0xb7, 0xc6, 0x85, 0xe1, 0x9a, 0xa9, 0xc6, 0xa2, 0xc8, 0xaa, 0xc7, 0x8c, + 0xc6, 0x9a, 0xc7, 0x81, 0xc3, 0xa0, 0xc4, 0xab, 0xc8, 0xa2, 0xc5, 0x9b, 0xc5, 0xbb, + 0xc7, 0x8e, 0xc6, 0x95, 0xc8, 0x9c, 0x6c, 0xc8, 0xbc, 0xe2, 0xb1, 0xaa, 0xc5, 0x85, + 0xc6, 0x83, 0xc4, 0xa1, 0xc4, 0x81, 0x4d, 0xe1, 0x9a, 0xa3, 0x5d, 0xc3, 0xb7, 0xc5, + 0xa4, 0xc6, 0xae, 0xe1, 0x9a, 0xad, 0xc4, 0xa4, 0xc3, 0xb8, 0xc3, 0xa7, 0x44, 0xc6, + 0xaa, 0xc7, 0xa5, 0xc4, 0xa4, 0xc5, 0xba, 0xc9, 0x85, 0xc3, 0xa6, 0xc3, 0x9d, 0xc4, + 0xa3, 0xc5, 0x97, 0xe1, 0x9a, 0xa1, 0x2d, 0x77, 0xc2, 0xa2, 0x3e, 0xc8, 0x8d, 0xc5, + 0xb1, 0xe1, 0x9a, 0xa9, 0xc6, 0xa2, 0xc5, 0xbf, 0xc7, 0xa4, 0xe1, 0x9a, 0xa9, 0xc6, + 0x82, 0xc3, 0xbb, 0xc3, 0xb9, 0xc6, 0x8a, 0x5a, + ], + asset_base: [ + 0x9f, 0x0a, 0x47, 0x16, 0x90, 0xe2, 0x1a, 0x74, 0x79, 0x7a, 0x71, 0x12, 0x36, 0xfa, + 0x58, 0x85, 0x5e, 0x6e, 0xd1, 0xaa, 0xd5, 0x4c, 0x6c, 0xaf, 0xa8, 0xa3, 0x7f, 0xdb, + 0xd1, 0x9e, 0x75, 0x00, + ], + }, + TestVector { + key: [ + 0xe5, 0x21, 0x62, 0x0d, 0x68, 0x53, 0x7c, 0xa3, 0x0b, 0xf3, 0x2f, 0x4e, 0xd2, 0xc3, + 0x3c, 0x0c, 0xf8, 0x25, 0x2a, 0x79, 0xa8, 0xa7, 0x39, 0x7b, 0xf1, 0x1b, 0x67, 0x87, + 0x30, 0x52, 0x44, 0xee, + ], + description: [ + 0xcd, 0xb4, 0xc6, 0x92, 0xc4, 0xa7, 0xc3, 0xb9, 0xc6, 0xb8, 0xcd, 0xba, 0xc4, 0xa4, + 0xc8, 0x9a, 0xc8, 0xb7, 0xe1, 0x9b, 0x92, 0xc5, 0xb2, 0xc7, 0xba, 0xc6, 0x86, 0xc8, + 0x87, 0xc5, 0x88, 0xc5, 0x87, 0xc7, 0xa0, 0xc8, 0x97, 0xc6, 0xad, 0x4e, 0xc4, 0xa4, + 0xc5, 0x9c, 0xc8, 0x89, 0xc5, 0xba, 0xc3, 0xa1, 0xc8, 0xa2, 0xc3, 0x9c, 0xc8, 0x88, + 0xe1, 0x9a, 0xa1, 0xc8, 0x9d, 0xc7, 0x8b, 0xc6, 0xb5, 0xc3, 0x87, 0xc3, 0x93, 0xc4, + 0xa3, 0xe2, 0xb1, 0xa2, 0x7b, 0xc9, 0x85, 0xc3, 0xb9, 0x3a, 0xc6, 0x86, 0xc3, 0x99, + 0xc7, 0xa2, 0xc7, 0x83, 0xce, 0x8a, 0xc7, 0xbd, 0xe1, 0x9b, 0xa7, 0xc8, 0xa9, 0xe2, + 0xb1, 0xb1, 0xc6, 0x9d, 0xc5, 0xbb, 0xc7, 0x98, 0xc6, 0x8a, 0xc6, 0x8d, 0xc5, 0xa2, + 0xc9, 0x89, 0xc3, 0xa3, 0x57, 0xc8, 0xa8, 0x66, 0xc7, 0x95, 0xc6, 0x86, 0xc4, 0xa2, + 0x79, 0xc8, 0x98, 0xc7, 0xa8, 0xc7, 0x86, 0xc6, 0xb4, 0xcd, 0xb6, 0xe1, 0x9a, 0xb2, + 0xc3, 0x9e, 0xc2, 0xb1, 0xc7, 0xbb, 0xc6, 0xa2, 0xc7, 0xb2, 0xc5, 0xa6, 0x48, 0xc2, + 0xbf, 0xc3, 0xac, 0x53, 0xc4, 0x80, 0xc2, 0xba, 0xc2, 0xbc, 0xc7, 0xad, 0xc7, 0xa7, + 0xc6, 0xb3, 0xe1, 0x9a, 0xad, 0xc8, 0x90, 0xe2, 0xb1, 0xaa, 0x31, 0xc5, 0xb9, 0xc5, + 0xbe, 0xe1, 0x9a, 0xb9, 0xc2, 0xb7, 0xc6, 0x91, 0xc3, 0xad, 0x7c, 0xc3, 0xa6, 0xc3, + 0x95, 0xc5, 0x8c, 0xc3, 0xb9, 0xc6, 0xa7, 0xc4, 0x9e, 0x7d, 0xce, 0x8c, 0x2e, 0xc7, + 0x97, 0xc6, 0x9b, 0x26, 0xc6, 0xa8, 0x7c, 0xc7, 0xa2, 0x4d, 0xc8, 0x9d, 0xc5, 0x8c, + 0xe2, 0xb1, 0xa5, 0xc7, 0xae, 0xc4, 0xbe, 0xe1, 0x9b, 0xa6, 0xc2, 0xae, 0xe2, 0xb1, + 0xaf, 0xc5, 0xb9, 0xc7, 0x87, 0x66, 0x5c, 0x53, 0xe2, 0xb1, 0xb1, 0xc8, 0xbf, 0xc5, + 0x8a, 0xc3, 0xa8, 0x21, 0xc3, 0x8c, 0xc4, 0x99, 0xc3, 0xba, 0xcd, 0xbe, 0xc8, 0xa6, + 0xc3, 0xbe, 0xc8, 0x90, 0xc4, 0x9d, 0xc4, 0x94, 0xc3, 0xbf, 0xc3, 0x9a, 0xe1, 0x9b, + 0x83, 0xc4, 0xb9, 0xc2, 0xa6, 0xc8, 0x8d, 0xc6, 0x82, 0xe1, 0x9a, 0xb0, 0xc6, 0x9b, + 0x31, 0xe1, 0x9b, 0x97, 0xc6, 0x91, 0xc3, 0x83, 0xc6, 0x9c, 0x4d, 0xc3, 0xb7, 0xc7, + 0x99, 0xe1, 0x9a, 0xac, 0xc2, 0xa3, 0xc6, 0xad, 0xc4, 0xb4, 0xc3, 0xa6, 0xe2, 0xb1, + 0xb2, 0x26, 0xc4, 0x84, 0xc7, 0x92, 0xc8, 0x8d, 0xc5, 0x93, 0x30, 0xc4, 0x94, 0xc5, + 0x88, 0xc5, 0xa1, 0xc2, 0xa1, 0xc7, 0x9f, 0xc4, 0xbb, 0xc7, 0x99, 0xc6, 0xac, 0xc6, + 0xa7, 0xc9, 0x87, 0x2b, 0xc6, 0x99, 0xce, 0x85, 0xe1, 0x9b, 0x9d, 0xc3, 0x90, 0xe1, + 0x9a, 0xad, 0xe1, 0x9b, 0x94, 0xc3, 0x97, 0xc4, 0x84, 0xc4, 0x9c, 0xc7, 0x84, 0xc3, + 0x8f, 0x79, 0xc5, 0xa1, 0xc8, 0x98, 0xc5, 0xa9, 0x64, 0xc3, 0xa9, 0x4d, 0xc4, 0x9c, + 0xc6, 0xba, 0xe2, 0xb1, 0xb8, 0xc5, 0xbe, 0xe2, 0xb1, 0xbf, 0xc3, 0x88, 0xc5, 0x81, + 0xc3, 0xbc, 0xc9, 0x84, 0xc6, 0xbb, 0xc6, 0xa3, 0xe1, 0x9b, 0x8c, 0x34, 0xc3, 0x85, + 0x78, 0xc8, 0xb8, 0xc2, 0xa4, 0xc5, 0xb2, 0xc6, 0x82, 0x40, 0xc6, 0xa3, 0xc3, 0xb0, + 0xc6, 0xb3, 0x72, 0xc2, 0xa1, 0xc6, 0x92, 0xc7, 0xa2, 0xe2, 0xb1, 0xa5, 0xc9, 0x8a, + 0xe2, 0xb1, 0xbb, 0xc2, 0xb5, 0xe2, 0xb1, 0xb0, 0xc4, 0x88, 0xc3, 0x95, 0xc6, 0xb2, + 0xc7, 0x9d, 0xc7, 0x96, 0xe2, 0xb1, 0xaa, 0x67, 0xc3, 0xa3, 0xc4, 0xbf, 0xc9, 0x8b, + 0xc4, 0xb9, 0xc4, 0xa8, 0xe2, 0xb1, 0xad, 0x41, 0xc3, 0xb4, 0xce, 0x86, 0xc4, 0xbe, + 0xc6, 0xa8, 0xe2, 0xb1, 0xa4, 0xc5, 0xbc, 0xc8, 0x94, 0xe1, 0x9b, 0x8b, 0xc5, 0x81, + 0xe1, 0x9b, 0x94, 0xc4, 0xae, 0xc5, 0x91, 0x5a, + ], + asset_base: [ + 0x6e, 0xa8, 0x83, 0xd2, 0x4d, 0x3d, 0xbc, 0xf6, 0xc7, 0xad, 0x2b, 0xf7, 0xed, 0x87, + 0xc7, 0xb5, 0xaa, 0xd2, 0x13, 0xf0, 0xcf, 0x11, 0x2b, 0xff, 0xa0, 0xc8, 0x84, 0xb1, + 0xd0, 0xe0, 0x56, 0x9a, + ], + }, + TestVector { + key: [ + 0x5e, 0x09, 0x49, 0x46, 0x12, 0x04, 0x4d, 0x6e, 0xf5, 0xb0, 0xbd, 0x0d, 0xc9, 0xb4, + 0xa0, 0xdc, 0x09, 0x47, 0x76, 0x00, 0x9e, 0x1e, 0x94, 0xce, 0x39, 0x1c, 0x27, 0xb8, + 0xb7, 0x51, 0x8f, 0xe0, + ], + description: [ + 0xc7, 0x9b, 0xc7, 0xa3, 0xc3, 0xa4, 0xc4, 0xa7, 0xe1, 0x9a, 0xa4, 0x29, 0xc9, 0x88, + 0xc3, 0xa8, 0xe1, 0x9b, 0x9c, 0x71, 0xc5, 0xaa, 0xe2, 0xb1, 0xba, 0xc8, 0xac, 0xc7, + 0xa5, 0xc8, 0x8b, 0xcd, 0xbc, 0xe1, 0x9b, 0x83, 0xc9, 0x86, 0xe1, 0x9a, 0xad, 0xc6, + 0x87, 0xc8, 0xbc, 0xc8, 0xa0, 0xc3, 0x94, 0xe1, 0x9b, 0xa5, 0xc8, 0x94, 0xc3, 0xac, + 0xc3, 0x88, 0xe1, 0x9a, 0xa8, 0xc7, 0xb9, 0x5b, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0x9f, + 0x63, 0xc6, 0x95, 0xcd, 0xb3, 0xc3, 0x8d, 0xc6, 0x88, 0xc2, 0xaf, 0xc4, 0x93, 0x64, + 0xc6, 0x89, 0xc8, 0xa0, 0x5b, 0xc8, 0x8b, 0xc6, 0xb7, 0xe1, 0x9b, 0xa0, 0x4c, 0x31, + 0x31, 0xc3, 0x82, 0xc7, 0xa5, 0xc9, 0x8e, 0xc9, 0x8f, 0xe1, 0x9b, 0x93, 0xc7, 0x80, + 0xc4, 0x80, 0xc3, 0xb2, 0xc3, 0x88, 0xe2, 0xb1, 0xb9, 0xc8, 0xab, 0xcd, 0xbb, 0xc3, + 0x8c, 0xc9, 0x87, 0xe1, 0x9a, 0xaf, 0xc8, 0xa9, 0xc9, 0x84, 0xc4, 0x8b, 0xe1, 0x9b, + 0x90, 0xc7, 0xb2, 0xc5, 0xaa, 0xc6, 0x9d, 0xc8, 0xb3, 0xe1, 0x9b, 0x9f, 0xc2, 0xa6, + 0xc5, 0xba, 0xe1, 0x9b, 0xa4, 0xc4, 0x8a, 0x4f, 0xc3, 0x85, 0xc5, 0x9d, 0x5f, 0xc8, + 0xbf, 0x6d, 0x41, 0xc7, 0x8b, 0xe1, 0x9a, 0xb3, 0xc7, 0xb3, 0xc4, 0x89, 0xc6, 0xaf, + 0xc6, 0xb7, 0xc3, 0x8f, 0xc5, 0x9d, 0xc8, 0x82, 0xc8, 0x82, 0xc6, 0xb6, 0xc3, 0xbf, + 0xc8, 0xa4, 0xc6, 0xab, 0x5e, 0xc3, 0x9a, 0xc5, 0xa0, 0xe2, 0xb1, 0xb0, 0xc3, 0x90, + 0xc8, 0x99, 0xc5, 0xac, 0xe1, 0x9a, 0xa6, 0xc3, 0x95, 0xcd, 0xb4, 0xcd, 0xb3, 0xc6, + 0x9f, 0xc7, 0x80, 0xc8, 0xaa, 0xe1, 0x9a, 0xb7, 0xc7, 0xa6, 0x2c, 0xc5, 0x83, 0xc8, + 0xbe, 0xc8, 0x93, 0xc4, 0xa0, 0xc3, 0x9f, 0xc5, 0xa1, 0xc5, 0x8d, 0xe1, 0x9b, 0xa5, + 0xc6, 0x99, 0x4b, 0xc4, 0xbe, 0xc8, 0x87, 0xc8, 0x92, 0xe1, 0x9b, 0xae, 0xc8, 0x86, + 0xc7, 0x90, 0xc5, 0x85, 0xc2, 0xb6, 0xc5, 0x84, 0xe1, 0x9a, 0xa5, 0xc8, 0x86, 0xc4, + 0x8d, 0xc6, 0xb9, 0xc8, 0x90, 0x25, 0xc4, 0xa9, 0xc4, 0xbb, 0xc5, 0xb0, 0xe2, 0xb1, + 0xa9, 0xe1, 0x9b, 0xad, 0x60, 0xc4, 0x9b, 0xc8, 0xab, 0xc3, 0xad, 0xc6, 0xa2, 0xc7, + 0x9d, 0xe1, 0x9b, 0x89, 0xe1, 0x9b, 0x97, 0xe1, 0x9b, 0xa6, 0x32, 0xc6, 0x99, 0xc3, + 0x9e, 0xc9, 0x8e, 0x4c, 0xe1, 0x9b, 0x93, 0xc6, 0xa4, 0xc6, 0x8c, 0xe2, 0xb1, 0xb8, + 0xc7, 0x9f, 0x2a, 0xc5, 0xa1, 0xe1, 0x9b, 0x9f, 0xcd, 0xbb, 0xc3, 0x8f, 0xc7, 0x89, + 0xc7, 0xaf, 0x5e, 0xc7, 0x8b, 0xc8, 0xa4, 0xc6, 0x81, 0xcd, 0xb3, 0xc2, 0xa9, 0xc7, + 0xae, 0xc8, 0x83, 0xc6, 0xae, 0xe1, 0x9b, 0xa3, 0xc6, 0xa3, 0xc6, 0xa0, 0xe1, 0x9a, + 0xab, 0xc8, 0xab, 0xc5, 0x9c, 0xc8, 0x94, 0xc5, 0xa8, 0xe2, 0xb1, 0xb6, 0xc4, 0xae, + 0xc6, 0xbe, 0xc7, 0xa4, 0xc7, 0x87, 0xc8, 0x9d, 0xe1, 0x9a, 0xbf, 0xc4, 0xa7, 0xc3, + 0xb3, 0xc5, 0x9e, 0xe1, 0x9a, 0xa2, 0xe1, 0x9b, 0x9e, 0xc7, 0xad, 0x7e, 0xe1, 0x9b, + 0x93, 0xc6, 0xa8, 0xc4, 0xb5, 0xc6, 0xb1, 0xe1, 0x9b, 0xa0, 0xc4, 0xac, 0xc4, 0x91, + 0xc4, 0xbe, 0xc8, 0x89, 0x4f, 0xc6, 0xa2, 0xc5, 0xbb, 0xe1, 0x9b, 0x91, 0xc7, 0x9f, + 0xe1, 0x9b, 0xa4, 0xe1, 0x9b, 0x9a, 0xc7, 0xa9, 0xc4, 0xa6, 0xe1, 0x9b, 0x85, 0xc7, + 0xae, 0xc5, 0x91, 0xc6, 0x94, 0x42, 0x6c, 0xc4, 0xab, 0xc5, 0xa0, 0xc8, 0x89, 0xe1, + 0x9a, 0xb9, 0xc6, 0xac, 0xc6, 0xae, 0xc5, 0xa1, 0xcd, 0xb1, 0xc8, 0xb0, 0xc3, 0x84, + 0xc8, 0xbc, 0xc3, 0x9b, 0xc7, 0xbc, 0xc6, 0xbc, 0xc8, 0x82, 0xc4, 0xbf, 0xe1, 0x9b, + 0xaa, 0xc8, 0xae, 0xce, 0x85, 0xc6, 0x86, 0x4c, + ], + asset_base: [ + 0x86, 0x78, 0x20, 0x68, 0xdc, 0x11, 0xd4, 0x4f, 0xff, 0xfe, 0x8d, 0x44, 0x03, 0xad, + 0x6e, 0xf1, 0xe7, 0x7d, 0x20, 0xd2, 0x10, 0x83, 0x2e, 0x2d, 0xbf, 0x84, 0xdf, 0x09, + 0x7c, 0x87, 0x21, 0x24, + ], + }, + ] +} diff --git a/src/test_vectors/asset_id.rs b/src/test_vectors/asset_id.rs deleted file mode 100644 index 2f4f08385..000000000 --- a/src/test_vectors/asset_id.rs +++ /dev/null @@ -1,1032 +0,0 @@ -// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_asset_id) - -pub(crate) struct TestVector { - pub(crate) key: [u8; 32], - pub(crate) description: [u8; 512], - pub(crate) asset_base: [u8; 32], -} - -pub(crate) fn test_vectors() -> Vec { - vec![ - TestVector { - key: [ - 0x85, 0xc8, 0xb5, 0xcd, 0x1a, 0xc3, 0xec, 0x3a, 0xd7, 0x09, 0x21, 0x32, 0xf9, 0x7f, - 0x01, 0x78, 0xb0, 0x75, 0xc8, 0x1a, 0x13, 0x9f, 0xd4, 0x60, 0xbb, 0xe0, 0xdf, 0xcd, - 0x75, 0x51, 0x47, 0x24, - ], - description: [ - 0xe1, 0x9b, 0x91, 0xc8, 0xa3, 0xe1, 0x9b, 0x8b, 0xc7, 0xac, 0xc8, 0xa0, 0xe1, 0x9b, - 0x89, 0xc3, 0x9b, 0xe1, 0x9b, 0xaa, 0xc6, 0xa7, 0xc9, 0x8e, 0xc2, 0xa2, 0xc2, 0xb2, - 0xe1, 0x9a, 0xbb, 0xc5, 0x9f, 0xc6, 0xaa, 0xc6, 0xbf, 0x69, 0xe1, 0x9b, 0xa9, 0xe1, - 0x9a, 0xae, 0xc4, 0xab, 0xe1, 0x9b, 0xa1, 0xc9, 0x8b, 0x23, 0xe1, 0x9b, 0x8a, 0xc7, - 0xa0, 0xe1, 0x9b, 0x88, 0xc4, 0xa6, 0xe1, 0x9b, 0xad, 0xc4, 0x9a, 0xe2, 0xb1, 0xb5, - 0xc7, 0xa7, 0x51, 0x78, 0x3f, 0xc3, 0xb0, 0xc8, 0x8a, 0x45, 0xc4, 0xa5, 0xc7, 0xb4, - 0xe1, 0x9a, 0xba, 0xe2, 0xb1, 0xbe, 0x38, 0xc2, 0xaa, 0xc8, 0xbb, 0xc8, 0xb2, 0xc6, - 0x86, 0xc6, 0xaa, 0xe1, 0x9b, 0xa2, 0xc8, 0xa7, 0xc5, 0x94, 0xc4, 0xad, 0x78, 0xc5, - 0x96, 0xe1, 0x9b, 0x81, 0xc9, 0x80, 0xc3, 0x93, 0xc6, 0xbe, 0xe1, 0x9a, 0xb0, 0x6d, - 0xc5, 0x90, 0xc4, 0x8a, 0x75, 0xc7, 0xa8, 0xc4, 0xac, 0xc4, 0x92, 0xc7, 0xa4, 0xc5, - 0x99, 0x25, 0xc6, 0xa1, 0xc5, 0x87, 0xc7, 0xa3, 0xce, 0x88, 0xc7, 0x8e, 0xc5, 0x85, - 0xe1, 0x9a, 0xb5, 0xe2, 0xb1, 0xad, 0xc4, 0x82, 0xc2, 0xb7, 0xc6, 0xac, 0xe1, 0x9b, - 0x82, 0x57, 0x30, 0xc3, 0xb0, 0xc7, 0xab, 0x69, 0xe1, 0x9b, 0x82, 0xc8, 0xb6, 0xc3, - 0xae, 0xe2, 0xb1, 0xab, 0x4f, 0xe1, 0x9a, 0xb5, 0xcd, 0xb5, 0xce, 0x88, 0xc4, 0x9f, - 0xc3, 0xb7, 0xc5, 0xb9, 0xc8, 0x88, 0x2f, 0xcd, 0xb7, 0xc8, 0x8f, 0xc8, 0xa4, 0xc5, - 0x95, 0xc3, 0xbc, 0x37, 0xe2, 0xb1, 0xb3, 0xc7, 0xa1, 0xc7, 0x89, 0xc4, 0x8d, 0xc5, - 0x87, 0x5f, 0xe1, 0x9a, 0xa2, 0xe1, 0x9b, 0x80, 0x76, 0xc7, 0xa6, 0xe2, 0xb1, 0xa2, - 0xe2, 0xb1, 0xb3, 0xc9, 0x83, 0xc3, 0xbd, 0x55, 0xe1, 0x9b, 0x84, 0xc7, 0xb6, 0xc9, - 0x8f, 0xc4, 0xa2, 0xc3, 0xbd, 0xe1, 0x9b, 0xa2, 0xc5, 0xb3, 0xc3, 0x90, 0x3d, 0xc6, - 0x8f, 0xc8, 0xbe, 0xc7, 0x99, 0xc5, 0xb4, 0xe2, 0xb1, 0xbd, 0xe2, 0xb1, 0xb4, 0xc8, - 0x9b, 0xc3, 0x81, 0xc6, 0xb0, 0x7d, 0xe2, 0xb1, 0xae, 0xc6, 0x85, 0xc5, 0x98, 0xc5, - 0x96, 0xc7, 0xb7, 0xc5, 0xa0, 0xcd, 0xbc, 0xc5, 0xa6, 0xe1, 0x9a, 0xb4, 0xc2, 0xa5, - 0xe1, 0x9b, 0xae, 0xc7, 0xbd, 0xc6, 0x9f, 0xc7, 0x81, 0xc6, 0x8e, 0x53, 0xc5, 0xb7, - 0xc2, 0xb0, 0xc7, 0xb6, 0xe1, 0x9b, 0xa6, 0xc7, 0x94, 0xe1, 0x9a, 0xa8, 0xc5, 0xa5, - 0xc8, 0xa6, 0x56, 0xc7, 0xae, 0xc6, 0x88, 0xe1, 0x9b, 0x8b, 0xc2, 0xb5, 0xe1, 0x9a, - 0xb5, 0xe1, 0x9a, 0xba, 0xe1, 0x9a, 0xa8, 0x32, 0xc2, 0xaf, 0xc6, 0xae, 0xce, 0x8a, - 0xc7, 0x92, 0xc2, 0xbf, 0xe1, 0x9b, 0x91, 0xc7, 0xb9, 0xc5, 0xa5, 0xc8, 0x95, 0xe2, - 0xb1, 0xb2, 0xc2, 0xa4, 0xc4, 0x9e, 0xc6, 0xa5, 0xc7, 0xb3, 0xc2, 0xa3, 0xe2, 0xb1, - 0xac, 0xe1, 0x9a, 0xa0, 0xc7, 0xa3, 0xcd, 0xb5, 0xc3, 0x9a, 0xc7, 0xaf, 0xc5, 0x87, - 0xe1, 0x9b, 0xa8, 0xc5, 0xaf, 0xc2, 0xbb, 0xc3, 0xae, 0xc6, 0xb9, 0xc6, 0x99, 0xc4, - 0xa7, 0xc3, 0x89, 0xe1, 0x9a, 0xbc, 0xc8, 0x95, 0xc5, 0x9e, 0xe1, 0x9a, 0xa6, 0xc4, - 0xab, 0xc8, 0x9b, 0xc5, 0xaf, 0xc3, 0x99, 0xc6, 0xaf, 0xe1, 0x9b, 0x90, 0xc8, 0xa7, - 0xc3, 0x97, 0x51, 0xc8, 0xab, 0xe2, 0xb1, 0xa2, 0x7d, 0x2c, 0x72, 0x36, 0x2b, 0xc3, - 0xb0, 0xc8, 0x8d, 0x46, 0xc5, 0x9d, 0xc4, 0xba, 0xc4, 0xa9, 0xc2, 0xa2, 0xc6, 0x9b, - 0xc3, 0xaf, 0x2f, 0xc8, 0x99, 0xe1, 0x9a, 0xb4, 0xc3, 0xba, 0xe1, 0x9b, 0x9b, 0xc2, - 0xa7, 0xc8, 0xb1, 0xe1, 0x9b, 0xae, 0xc7, 0xad, 0xe1, 0x9a, 0xaf, 0xc4, 0xbd, 0xc3, - 0x82, 0xc4, 0xaf, 0xc4, 0xb1, 0xe1, 0x9a, 0xaa, - ], - asset_base: [ - 0x64, 0x0c, 0x81, 0x73, 0x79, 0x71, 0x4a, 0xe4, 0x8a, 0xf0, 0xbb, 0x83, 0x32, 0xf2, - 0x0d, 0x57, 0x7c, 0xb2, 0x42, 0x7e, 0x8f, 0x04, 0x49, 0x18, 0xee, 0xe5, 0x76, 0x45, - 0x05, 0x09, 0x6c, 0x97, - ], - }, - TestVector { - key: [ - 0x43, 0x10, 0x6d, 0xe9, 0xa7, 0xec, 0x54, 0xdd, 0x36, 0xdf, 0xa7, 0x0b, 0xdb, 0xd9, - 0x07, 0x2d, 0xbd, 0xda, 0xb5, 0xe0, 0x66, 0xaa, 0xef, 0xfc, 0xf9, 0xbb, 0xa3, 0x20, - 0xd4, 0xff, 0xf7, 0x12, - ], - description: [ - 0xc6, 0x89, 0xc8, 0x9f, 0xc4, 0xa2, 0xe1, 0x9a, 0xb6, 0xc7, 0xa7, 0xe2, 0xb1, 0xa8, - 0xc2, 0xbc, 0xe2, 0xb1, 0xa2, 0xc3, 0x8d, 0x73, 0xc3, 0xa1, 0xc7, 0xbf, 0xc7, 0xa5, - 0xc7, 0xb3, 0xc6, 0x83, 0x7d, 0xc5, 0x85, 0x3c, 0xc8, 0x9d, 0x6a, 0x51, 0xc8, 0xac, - 0xe1, 0x9a, 0xb6, 0xce, 0x85, 0xc5, 0xbf, 0xc7, 0xb5, 0xe1, 0x9a, 0xb3, 0xc4, 0xa4, - 0xc2, 0xb9, 0x50, 0xe2, 0xb1, 0xa7, 0xc2, 0xb7, 0xc7, 0x91, 0xe1, 0x9b, 0xb0, 0xc4, - 0x8b, 0xe2, 0xb1, 0xae, 0xc3, 0x8a, 0xc4, 0x93, 0xc5, 0xac, 0xc2, 0xa2, 0xe2, 0xb1, - 0xad, 0xc3, 0x8e, 0xe1, 0x9b, 0x84, 0xc9, 0x88, 0xc5, 0xb1, 0xc4, 0xbb, 0xc4, 0x80, - 0xcd, 0xb5, 0xc5, 0xba, 0x45, 0xe1, 0x9a, 0xbe, 0xe2, 0xb1, 0xbd, 0xc9, 0x82, 0xc4, - 0xa2, 0x62, 0xc7, 0x91, 0x2e, 0xc7, 0x82, 0xc8, 0x92, 0xc8, 0x9e, 0xc7, 0x8f, 0xe1, - 0x9b, 0x9a, 0xc8, 0xa9, 0xc4, 0x9b, 0xc3, 0x9a, 0xc4, 0x9a, 0xc3, 0x8d, 0xc8, 0x88, - 0xc4, 0x8d, 0xc2, 0xa9, 0xcd, 0xbc, 0x5e, 0xc8, 0xb7, 0xcd, 0xbe, 0xc2, 0xb0, 0xe2, - 0xb1, 0xb0, 0xc3, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x84, 0xc7, 0x82, 0xc7, 0xb9, 0xc8, - 0xb6, 0xc9, 0x87, 0xc5, 0xbb, 0xc2, 0xb1, 0xc4, 0xaf, 0x73, 0xcd, 0xb4, 0x54, 0xc5, - 0xb6, 0xc7, 0x97, 0xc3, 0x87, 0xce, 0x87, 0xc6, 0xb3, 0x69, 0xc4, 0x84, 0xe1, 0x9b, - 0x9a, 0xc5, 0x91, 0xc7, 0x89, 0xc2, 0xa2, 0x2e, 0xc6, 0x85, 0xc5, 0x94, 0xc4, 0xbf, - 0xc3, 0xa8, 0xc6, 0xbc, 0xc7, 0x9c, 0xe2, 0xb1, 0xa5, 0x6e, 0xc6, 0xb4, 0xc8, 0xa1, - 0xc6, 0x91, 0xc6, 0x91, 0xc6, 0xa9, 0xe1, 0x9b, 0x88, 0xc7, 0x90, 0xc4, 0xb3, 0xe1, - 0x9a, 0xb9, 0xc4, 0x87, 0xc5, 0xbc, 0xe2, 0xb1, 0xae, 0xc3, 0x83, 0xe1, 0x9b, 0x9e, - 0xc5, 0x89, 0xc8, 0x9d, 0x66, 0xe2, 0xb1, 0xae, 0xc5, 0x98, 0xc4, 0xb5, 0xc8, 0x9f, - 0xc8, 0xaa, 0xc9, 0x86, 0xe1, 0x9a, 0xa3, 0xc5, 0x94, 0xc7, 0x8d, 0xc6, 0x90, 0xc7, - 0xb2, 0xc7, 0x9b, 0xc7, 0xb2, 0xc4, 0xa4, 0xc7, 0x88, 0xc8, 0xa5, 0xc6, 0x9a, 0xc4, - 0x8b, 0x39, 0xc7, 0xb8, 0x3c, 0xc8, 0xa8, 0xc6, 0x89, 0xc7, 0xb2, 0xc7, 0x98, 0xc3, - 0xb0, 0xc3, 0xb2, 0xc6, 0xa0, 0xc5, 0xa5, 0xc8, 0x90, 0x47, 0xc5, 0x9f, 0xc8, 0x8f, - 0xc7, 0x98, 0xc3, 0xb6, 0xe1, 0x9a, 0xa5, 0x2f, 0xc9, 0x89, 0xc8, 0xb0, 0xc7, 0x9f, - 0xc4, 0x80, 0xe2, 0xb1, 0xa2, 0x74, 0xe1, 0x9b, 0x82, 0xc3, 0x90, 0xc7, 0xb6, 0xc8, - 0xa4, 0xe2, 0xb1, 0xa7, 0xc6, 0xb4, 0xc7, 0xbe, 0x71, 0xc5, 0x8d, 0xe2, 0xb1, 0xbd, - 0xc6, 0x97, 0xc6, 0x95, 0x72, 0xc4, 0xa9, 0xe1, 0x9b, 0xaf, 0xc5, 0xa8, 0xc6, 0x89, - 0xc6, 0xad, 0xe2, 0xb1, 0xae, 0xc7, 0xb1, 0x6c, 0xc5, 0xab, 0xe2, 0xb1, 0xbe, 0xe1, - 0x9b, 0x8e, 0xc3, 0x96, 0xe1, 0x9b, 0xa7, 0x65, 0xc6, 0xab, 0xe1, 0x9b, 0x97, 0xc6, - 0x90, 0xe1, 0x9b, 0xa9, 0xe1, 0x9a, 0xa4, 0xc7, 0x8a, 0x5b, 0xe2, 0xb1, 0xa6, 0xc5, - 0xbf, 0xc9, 0x86, 0xc8, 0x8b, 0xc6, 0xbd, 0xc5, 0xab, 0xc3, 0x90, 0xc2, 0xbb, 0xc8, - 0xb4, 0xc5, 0x84, 0xc3, 0xa0, 0xc6, 0x91, 0xc9, 0x8e, 0xc4, 0x87, 0xe2, 0xb1, 0xa5, - 0x71, 0xe1, 0x9a, 0xbb, 0xc7, 0x90, 0xc8, 0x85, 0xc6, 0x84, 0xce, 0x8a, 0xe2, 0xb1, - 0xbf, 0xc3, 0x9d, 0xc4, 0xbe, 0xc5, 0xac, 0x53, 0xc4, 0x8b, 0xc7, 0x97, 0xc6, 0x8d, - 0xe2, 0xb1, 0xb0, 0xc6, 0x87, 0xe1, 0x9b, 0x9a, 0xc7, 0x8c, 0xe1, 0x9b, 0x90, 0xc3, - 0xa4, 0xc4, 0xa7, 0xc7, 0xb9, 0x7a, 0xe1, 0x9b, 0x98, 0x2a, 0x46, 0x65, 0xc8, 0x88, - 0x78, 0xc7, 0x83, 0xe1, 0x9b, 0xa7, 0xc3, 0xbf, - ], - asset_base: [ - 0xd6, 0x9d, 0x7b, 0xa8, 0xcd, 0x66, 0x3c, 0xf9, 0x52, 0x8f, 0x01, 0x0a, 0x2d, 0xee, - 0x7b, 0x42, 0x9f, 0xe5, 0x62, 0x65, 0x50, 0x09, 0x30, 0x52, 0x90, 0x5a, 0xa9, 0x09, - 0x88, 0x38, 0x8d, 0x06, - ], - }, - TestVector { - key: [ - 0x6b, 0xfb, 0xe5, 0xc2, 0x42, 0x23, 0x94, 0xdc, 0x23, 0x76, 0xad, 0x10, 0x69, 0x3a, - 0xbc, 0x1b, 0xf4, 0xa1, 0x6e, 0x18, 0x56, 0x5e, 0xbe, 0x79, 0x84, 0x1b, 0x95, 0x13, - 0x45, 0x02, 0x53, 0x01, - ], - description: [ - 0xe1, 0x9a, 0xa0, 0xc7, 0xbb, 0xe1, 0x9b, 0xa1, 0xce, 0x8a, 0xc8, 0xb3, 0x31, 0xc8, - 0xba, 0xc8, 0x95, 0xc7, 0xae, 0xcd, 0xb5, 0xc4, 0xac, 0xc3, 0x87, 0x6b, 0xc3, 0xbd, - 0xc3, 0x9a, 0xc8, 0x83, 0xc7, 0x92, 0x48, 0xe1, 0x9b, 0x90, 0xe2, 0xb1, 0xb2, 0xc6, - 0x89, 0xe1, 0x9a, 0xa7, 0xc6, 0x81, 0xc2, 0xa9, 0xe1, 0x9b, 0x9c, 0xe1, 0x9b, 0xac, - 0xc3, 0xa8, 0xc5, 0xae, 0xc8, 0x8f, 0xc4, 0x96, 0xc3, 0x8e, 0xcd, 0xbb, 0xe1, 0x9b, - 0xaf, 0xc3, 0xa2, 0xc4, 0x92, 0xc5, 0xb2, 0xc6, 0x9f, 0xc3, 0xbb, 0xc5, 0xb5, 0xe2, - 0xb1, 0xb4, 0xc4, 0x95, 0xc7, 0x9f, 0xe1, 0x9a, 0xaf, 0xc9, 0x82, 0xc7, 0x8d, 0xc5, - 0x8c, 0xc3, 0x90, 0xe1, 0x9b, 0xa5, 0xe1, 0x9b, 0x94, 0xc9, 0x89, 0xe2, 0xb1, 0xa9, - 0xc4, 0x90, 0xc7, 0xa2, 0xc4, 0x8c, 0xc7, 0xbf, 0xc3, 0x80, 0xc6, 0x83, 0xc6, 0x95, - 0x24, 0x23, 0xe1, 0x9b, 0x90, 0xe1, 0x9a, 0xa3, 0xc3, 0x96, 0xc9, 0x8a, 0xc5, 0xb6, - 0x48, 0xc7, 0x9b, 0xc2, 0xaf, 0xc8, 0x86, 0xc5, 0xb9, 0xc8, 0x9b, 0x52, 0xc5, 0xa4, - 0x56, 0xe1, 0x9b, 0x9d, 0xe1, 0x9b, 0x95, 0xe1, 0x9a, 0xba, 0xc4, 0xa7, 0xc5, 0xaa, - 0xe2, 0xb1, 0xa6, 0xc8, 0xb5, 0x62, 0x4c, 0xe1, 0x9b, 0xaf, 0xc7, 0xab, 0xc5, 0x86, - 0xc5, 0x9d, 0x39, 0xc6, 0x9d, 0x3d, 0xc6, 0x82, 0xc8, 0x91, 0xe2, 0xb1, 0xaa, 0xc6, - 0xb8, 0xc5, 0x96, 0xc3, 0x90, 0xc3, 0xa5, 0x31, 0xc8, 0x94, 0x7d, 0xc7, 0xae, 0x56, - 0xc8, 0xaa, 0x66, 0xc7, 0x8d, 0x79, 0xc4, 0x9b, 0xc7, 0xb9, 0xc2, 0xbb, 0xc4, 0x84, - 0xce, 0x85, 0xc3, 0x9c, 0xc9, 0x83, 0xc8, 0xbc, 0xc8, 0x83, 0xc7, 0x96, 0xc6, 0xbf, - 0x28, 0xe1, 0x9a, 0xa1, 0xc6, 0xb3, 0xe2, 0xb1, 0xb5, 0xc4, 0x92, 0xc4, 0x92, 0xc2, - 0xa9, 0xc2, 0xb2, 0xc3, 0xad, 0xe2, 0xb1, 0xbe, 0xc6, 0xb3, 0xc8, 0x89, 0xc9, 0x8b, - 0xc4, 0x94, 0xc6, 0xa5, 0x2a, 0xc6, 0x8b, 0xe1, 0x9b, 0xa3, 0xe1, 0x9a, 0xa4, 0xc7, - 0x85, 0xc7, 0x8f, 0xc6, 0x90, 0xc7, 0xa3, 0xc7, 0xbe, 0xc3, 0x9e, 0xc2, 0xbd, 0x25, - 0xc8, 0xaf, 0xc6, 0x92, 0xe1, 0x9b, 0xab, 0xc8, 0xb9, 0x59, 0xc5, 0x93, 0xc7, 0xbf, - 0xc3, 0x96, 0xc6, 0xbf, 0xc3, 0xb0, 0xc6, 0x9e, 0xc9, 0x83, 0x35, 0xe2, 0xb1, 0xa1, - 0xc5, 0xaf, 0xc8, 0x9b, 0xc4, 0x9f, 0xc2, 0xa2, 0xcd, 0xb7, 0xc5, 0x83, 0xc6, 0x9b, - 0xc8, 0x92, 0xcd, 0xb7, 0xc8, 0xba, 0xc2, 0xa8, 0x44, 0xc4, 0xa6, 0xe1, 0x9a, 0xb8, - 0xc7, 0xa1, 0xc8, 0xa4, 0xc4, 0xbe, 0x6b, 0xc6, 0xa1, 0xc7, 0xa5, 0x4f, 0xc2, 0xa1, - 0xc8, 0x9b, 0xc4, 0xb8, 0x6e, 0xc3, 0x8f, 0xc6, 0xb5, 0xc4, 0x9c, 0xe1, 0x9b, 0x87, - 0xc5, 0x8a, 0xe2, 0xb1, 0xa7, 0xc3, 0x8d, 0xc4, 0x9b, 0xc7, 0xb0, 0x7a, 0xc7, 0x88, - 0xc5, 0xa7, 0x2e, 0xc2, 0xbb, 0xc3, 0x95, 0x6c, 0xe2, 0xb1, 0xa6, 0xe1, 0x9a, 0xad, - 0xc7, 0x85, 0xc9, 0x80, 0xc8, 0xa2, 0xc8, 0xaa, 0xe1, 0x9b, 0x9e, 0xc7, 0x9e, 0xc3, - 0x8b, 0xc6, 0xb4, 0xc8, 0x8c, 0xc9, 0x85, 0xc5, 0xab, 0xc5, 0x8a, 0x26, 0xc5, 0xa5, - 0xc3, 0x98, 0x30, 0xe1, 0x9b, 0x8b, 0xc5, 0xb3, 0xe2, 0xb1, 0xa9, 0x51, 0x33, 0xc6, - 0x85, 0x75, 0xc9, 0x82, 0xe1, 0x9a, 0xaa, 0xc6, 0x89, 0xe1, 0x9a, 0xb7, 0xc7, 0x81, - 0xc4, 0xa4, 0xc8, 0x86, 0xc3, 0xaf, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xab, 0xc7, 0x96, - 0x68, 0xc4, 0x93, 0x3f, 0xc3, 0x99, 0xc2, 0xb7, 0xc8, 0x8b, 0xc7, 0xb3, 0xc5, 0xa5, - 0xe1, 0x9b, 0xa9, 0xc5, 0x84, 0xc4, 0xa7, 0xc5, 0x99, 0xc4, 0xae, 0xc9, 0x87, 0xe1, - 0x9a, 0xba, 0xc4, 0x8a, 0xc4, 0xb2, 0x6d, 0x5a, - ], - asset_base: [ - 0x8e, 0x9c, 0x21, 0x17, 0xed, 0x4f, 0x4e, 0xe8, 0x9a, 0xb8, 0xb3, 0x53, 0xf5, 0xfd, - 0xd0, 0xcb, 0xde, 0xb7, 0xf2, 0xc9, 0x55, 0xfa, 0xdc, 0x7b, 0x1a, 0xda, 0x09, 0x97, - 0x56, 0x11, 0x72, 0x85, - ], - }, - TestVector { - key: [ - 0xab, 0x90, 0x15, 0x62, 0x52, 0x72, 0xe1, 0xe7, 0xba, 0x69, 0x0a, 0xe0, 0x09, 0xa9, - 0x92, 0xe4, 0x9d, 0xe1, 0x9f, 0x33, 0xfc, 0xde, 0xb9, 0xf1, 0x71, 0xab, 0x1a, 0xaf, - 0x28, 0x88, 0xc6, 0x0e, - ], - description: [ - 0xc6, 0xb9, 0xe2, 0xb1, 0xae, 0xe2, 0xb1, 0xbc, 0xc7, 0x97, 0xe1, 0x9b, 0x9f, 0xc6, - 0x98, 0xc8, 0x82, 0xc3, 0xa2, 0xc4, 0xba, 0xc7, 0xbc, 0xc4, 0xbc, 0xc4, 0xa6, 0xc6, - 0xad, 0xc8, 0xb7, 0x70, 0xc3, 0x94, 0xe1, 0x9b, 0x81, 0xc5, 0x86, 0xe2, 0xb1, 0xa9, - 0xc8, 0x99, 0xce, 0x8c, 0xc3, 0x99, 0xc7, 0x91, 0xc3, 0xbd, 0x30, 0xc7, 0xb9, 0xc4, - 0xb0, 0xc8, 0xae, 0xe1, 0x9b, 0xa5, 0xc6, 0xbe, 0xc5, 0xad, 0xc5, 0xb6, 0xc2, 0xaf, - 0xc4, 0xbf, 0xce, 0x8c, 0xc8, 0xb8, 0x4a, 0xe2, 0xb1, 0xaa, 0xc3, 0xb1, 0xc5, 0x9a, - 0xe1, 0x9a, 0xb8, 0xc5, 0x9a, 0x33, 0xc4, 0x91, 0xc3, 0x9f, 0xc4, 0x86, 0x39, 0xc8, - 0x89, 0xc7, 0xa9, 0xc3, 0x9b, 0xc7, 0x92, 0xce, 0x89, 0x63, 0xc6, 0x93, 0xc6, 0x90, - 0xc2, 0xb6, 0xc5, 0x8f, 0xc8, 0x91, 0xc2, 0xab, 0xe1, 0x9a, 0xbc, 0xe2, 0xb1, 0xa4, - 0xc3, 0xb1, 0xc5, 0xaf, 0xe1, 0x9b, 0x84, 0xc5, 0xb5, 0xc5, 0x80, 0xe2, 0xb1, 0xa0, - 0x68, 0xc5, 0xa2, 0x26, 0xe1, 0x9a, 0xa1, 0xc4, 0x87, 0xc4, 0x9d, 0xc4, 0x9f, 0xc5, - 0x8b, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0x8d, 0xe1, 0x9a, 0xbd, 0xce, 0x88, 0xc9, 0x81, - 0xc7, 0x92, 0xe1, 0x9b, 0x9b, 0xc3, 0xb8, 0xc2, 0xab, 0x39, 0xe1, 0x9b, 0x9f, 0xc5, - 0xb4, 0xc5, 0xb3, 0xce, 0x86, 0xc8, 0x8d, 0xe1, 0x9b, 0x9b, 0xc5, 0xba, 0x38, 0xc6, - 0x84, 0xc8, 0xbf, 0xc6, 0xa2, 0xc8, 0x96, 0xc7, 0x8b, 0xc7, 0xbe, 0xc4, 0x97, 0xc8, - 0xb9, 0xc6, 0xb3, 0xc3, 0xbb, 0xc4, 0x8f, 0xc9, 0x86, 0xc5, 0x85, 0xc7, 0x9b, 0x7c, - 0xe2, 0xb1, 0xa0, 0xc7, 0xb2, 0xc8, 0x9c, 0xc5, 0xa8, 0xc2, 0xa8, 0xe1, 0x9a, 0xb6, - 0xc4, 0xaf, 0xc3, 0x8e, 0xc8, 0xbf, 0xc4, 0xa9, 0xc3, 0x95, 0xe1, 0x9b, 0x80, 0xc4, - 0xb7, 0xc8, 0x88, 0xc8, 0x80, 0xc5, 0xaf, 0xe1, 0x9a, 0xa4, 0xc7, 0x96, 0xc3, 0xb0, - 0xc4, 0xa2, 0x7c, 0xcd, 0xb6, 0xc7, 0x95, 0x4e, 0xc9, 0x86, 0xc2, 0xb0, 0xc3, 0xbb, - 0xc7, 0x8b, 0xc4, 0xb3, 0xe2, 0xb1, 0xaa, 0xe1, 0x9b, 0x8f, 0xc7, 0x84, 0xe1, 0x9a, - 0xaf, 0xc4, 0x92, 0xc7, 0x97, 0x34, 0xc2, 0xbe, 0xe1, 0x9b, 0x96, 0xc4, 0x9d, 0xc6, - 0xab, 0xe1, 0x9b, 0xa8, 0x4b, 0xc3, 0x86, 0xc7, 0x97, 0xc4, 0xa7, 0xc3, 0xbb, 0xc8, - 0x90, 0x48, 0xe1, 0x9b, 0x9a, 0xc6, 0x9d, 0xe1, 0x9b, 0x9b, 0xc4, 0xbb, 0xc3, 0x8f, - 0xc7, 0xb8, 0xc8, 0x9d, 0xc6, 0xac, 0xc6, 0xa5, 0xc6, 0x9e, 0xc7, 0x83, 0xc3, 0x97, - 0xc8, 0xae, 0xc3, 0xaf, 0xc3, 0xb4, 0xc5, 0xab, 0xc4, 0x81, 0xe1, 0x9b, 0xa0, 0xc3, - 0x85, 0xc4, 0x84, 0x7c, 0x21, 0xc2, 0xb4, 0xc9, 0x8b, 0xc9, 0x8b, 0xc8, 0x9c, 0xc7, - 0x8f, 0xe2, 0xb1, 0xab, 0xe1, 0x9a, 0xbc, 0xc7, 0x8b, 0xc6, 0xa0, 0xc6, 0xb2, 0xc9, - 0x82, 0xc5, 0x8c, 0xe2, 0xb1, 0xb7, 0xc7, 0x8d, 0xc5, 0xa9, 0xc4, 0xbd, 0xc6, 0x8f, - 0xc4, 0x83, 0xc6, 0x80, 0xe1, 0x9b, 0xa7, 0xc8, 0x94, 0xc5, 0x8e, 0xc6, 0x9e, 0x4a, - 0x62, 0x70, 0xe1, 0x9a, 0xa5, 0xe2, 0xb1, 0xba, 0xc3, 0x8f, 0xc3, 0x85, 0xc4, 0x82, - 0xc7, 0xbc, 0xce, 0x85, 0x77, 0xc2, 0xb2, 0xc8, 0x89, 0xe1, 0x9a, 0xa2, 0xc5, 0xac, - 0xc5, 0x9e, 0xcd, 0xb5, 0xc6, 0x83, 0xc6, 0x93, 0xc8, 0x9d, 0xe1, 0x9a, 0xa2, 0xe1, - 0x9b, 0xa8, 0xc2, 0xa2, 0xe1, 0x9a, 0xa5, 0xcd, 0xb3, 0xc4, 0xb8, 0x3c, 0xc6, 0xb5, - 0xc3, 0x8c, 0xc3, 0x90, 0xc3, 0xa4, 0xc7, 0x83, 0xc4, 0xb4, 0xc7, 0x93, 0xc5, 0xa3, - 0xc6, 0xa6, 0x25, 0xc5, 0xbf, 0x7d, 0xc6, 0xa3, 0x46, 0xc3, 0xa6, 0xc6, 0x9b, 0xc7, - 0xbc, 0xc6, 0x81, 0xc2, 0xba, 0xc7, 0xa7, 0x60, - ], - asset_base: [ - 0xd4, 0x7d, 0x06, 0xf8, 0x2f, 0x2d, 0x15, 0x8a, 0xee, 0xf7, 0x02, 0x8a, 0x1d, 0xb5, - 0xf3, 0xa1, 0xd1, 0x25, 0x0e, 0x2c, 0xfa, 0x28, 0x94, 0x44, 0x1d, 0x86, 0xee, 0xc4, - 0x7a, 0xbf, 0xbd, 0xb5, - ], - }, - TestVector { - key: [ - 0x06, 0xd4, 0x75, 0x14, 0x97, 0x0d, 0x02, 0xd3, 0xf8, 0x43, 0xfb, 0x9b, 0x96, 0x51, - 0x08, 0x75, 0xa7, 0xa6, 0xc0, 0x15, 0x68, 0x1d, 0x06, 0xe0, 0xb1, 0x5b, 0x8a, 0x92, - 0x1f, 0xbd, 0x81, 0x30, - ], - description: [ - 0xc5, 0x99, 0xc2, 0xa5, 0xc6, 0xb8, 0x6d, 0xc5, 0xa7, 0xc7, 0xbd, 0xc4, 0xa0, 0xe1, - 0x9b, 0xa7, 0xc8, 0xba, 0xc9, 0x81, 0x7d, 0x36, 0xc5, 0x80, 0x52, 0xcd, 0xb5, 0xc5, - 0xba, 0xc2, 0xbb, 0x6d, 0xe2, 0xb1, 0xb1, 0xc5, 0xa8, 0xc5, 0x8c, 0x38, 0x47, 0xc9, - 0x87, 0x7c, 0x43, 0xc3, 0x96, 0xc6, 0x87, 0xc7, 0xbf, 0xc4, 0x9b, 0xe1, 0x9b, 0x98, - 0xc7, 0x94, 0xe1, 0x9b, 0x9b, 0xe1, 0x9b, 0x9d, 0xe1, 0x9a, 0xbf, 0x35, 0xc7, 0xba, - 0xc8, 0x82, 0xc4, 0x80, 0xc6, 0xbf, 0xc7, 0xba, 0xc4, 0xbd, 0xc4, 0x81, 0xe2, 0xb1, - 0xbc, 0xe1, 0x9a, 0xad, 0xe1, 0x9a, 0xab, 0xc5, 0xab, 0xc5, 0xba, 0xc6, 0xa8, 0x3b, - 0xc6, 0x98, 0xc7, 0x8c, 0xc8, 0x9e, 0xc2, 0xbe, 0xc6, 0x8b, 0xc7, 0x9c, 0xc8, 0xb4, - 0x3f, 0xc5, 0xb8, 0xc4, 0xb7, 0xc8, 0xb2, 0xc6, 0x86, 0xc3, 0xa1, 0xc7, 0x9b, 0x5c, - 0xe1, 0x9a, 0xa6, 0xe1, 0x9b, 0xac, 0xc7, 0x8c, 0xc6, 0xa7, 0x53, 0xc6, 0xa5, 0xc7, - 0x90, 0xe1, 0x9b, 0x85, 0xc8, 0x94, 0xcd, 0xb1, 0xc6, 0x99, 0xc4, 0xa8, 0xc7, 0xb3, - 0xe1, 0x9a, 0xb1, 0x7b, 0xc2, 0xb1, 0xe1, 0x9b, 0x94, 0x36, 0xc9, 0x8d, 0xc2, 0xa2, - 0x73, 0xc5, 0x80, 0xc5, 0x8d, 0xc8, 0x84, 0xc7, 0xa6, 0xc9, 0x85, 0xc4, 0xbd, 0xc7, - 0xb8, 0xc8, 0xb0, 0xc4, 0x83, 0xc3, 0xb8, 0xcd, 0xb1, 0x77, 0xc3, 0xa6, 0xc6, 0x80, - 0xc4, 0x83, 0xc8, 0x8e, 0xc9, 0x87, 0xc7, 0xb4, 0xc5, 0xb8, 0xc5, 0x99, 0xe2, 0xb1, - 0xaa, 0xc6, 0xb6, 0xc4, 0xa3, 0xc6, 0xb4, 0xc6, 0x8d, 0xe2, 0xb1, 0xa3, 0xe1, 0x9a, - 0xaa, 0xe1, 0x9a, 0xb8, 0xc3, 0x92, 0x63, 0xcd, 0xb4, 0xc7, 0x91, 0xc8, 0x83, 0xc3, - 0xaf, 0xcd, 0xb2, 0xc7, 0x9b, 0x5a, 0xe1, 0x9b, 0x82, 0xc6, 0x87, 0xc8, 0x91, 0xc5, - 0x83, 0xc5, 0xa8, 0xc4, 0x85, 0xe1, 0x9b, 0xab, 0xe1, 0x9b, 0x9f, 0x39, 0xc6, 0xbc, - 0x64, 0xc5, 0x98, 0xe1, 0x9b, 0x9f, 0xc8, 0xab, 0xe1, 0x9a, 0xb4, 0xc4, 0x83, 0xe2, - 0xb1, 0xb2, 0xe2, 0xb1, 0xa8, 0x5e, 0xc8, 0x93, 0xc4, 0xb3, 0xe1, 0x9b, 0xa6, 0xc5, - 0x93, 0xe1, 0x9b, 0x86, 0xc3, 0x98, 0xc2, 0xbd, 0xc7, 0x9a, 0xe1, 0x9a, 0xb2, 0xc7, - 0x8a, 0x73, 0xc7, 0x96, 0xe2, 0xb1, 0xb0, 0xcd, 0xbc, 0xc7, 0xb8, 0xc7, 0x95, 0xc4, - 0xa7, 0xe2, 0xb1, 0xb4, 0xc5, 0xa6, 0xc4, 0xa6, 0xe1, 0x9a, 0xa1, 0xc4, 0xbd, 0xc2, - 0xa2, 0xc5, 0x96, 0xe1, 0x9b, 0x89, 0xe1, 0x9b, 0x8e, 0xe2, 0xb1, 0xab, 0xc8, 0x8e, - 0x24, 0xcd, 0xb7, 0xc5, 0xab, 0xc8, 0x97, 0xce, 0x86, 0xc3, 0xac, 0x63, 0xc7, 0x97, - 0xc5, 0x81, 0xc6, 0x8b, 0xc4, 0xb7, 0xe2, 0xb1, 0xad, 0xc4, 0x8e, 0xc8, 0x98, 0xcd, - 0xbc, 0xe1, 0x9a, 0xbb, 0xc5, 0xb8, 0xc4, 0x9d, 0x28, 0xc6, 0x87, 0xe1, 0x9b, 0x9d, - 0xe1, 0x9b, 0x93, 0xc3, 0xbb, 0xc7, 0x8f, 0x74, 0xc8, 0x9e, 0xce, 0x88, 0xc7, 0x9c, - 0xc8, 0x9d, 0xc9, 0x80, 0xc4, 0xbf, 0xc7, 0xad, 0xc3, 0x97, 0xe2, 0xb1, 0xad, 0x2e, - 0xc6, 0xb7, 0x40, 0xc3, 0xb7, 0xc3, 0xaf, 0xe1, 0x9a, 0xbe, 0xc7, 0x88, 0xc4, 0x8a, - 0xc3, 0x81, 0xc5, 0x97, 0xc8, 0x93, 0xc8, 0xb8, 0xe1, 0x9a, 0xa8, 0xc3, 0x9e, 0xc8, - 0xb1, 0xc8, 0xaa, 0x5c, 0xc6, 0xa4, 0xe1, 0x9b, 0x9d, 0xc2, 0xb6, 0xc8, 0x85, 0xc7, - 0x98, 0xc4, 0xb8, 0xc4, 0xa1, 0xc9, 0x81, 0xc5, 0x94, 0xc4, 0xa4, 0xc2, 0xa8, 0xc7, - 0xa7, 0xc5, 0xba, 0x5a, 0xcd, 0xb3, 0xe1, 0x9b, 0xa0, 0xc4, 0x83, 0xc6, 0x83, 0xc9, - 0x85, 0x45, 0xc3, 0xb5, 0xc7, 0x9f, 0xc5, 0x93, 0xc3, 0x90, 0xc7, 0x95, 0xc8, 0xb1, - 0xc7, 0x87, 0xc3, 0xb2, 0xc7, 0xb9, 0xc3, 0xa8, - ], - asset_base: [ - 0xa9, 0xa8, 0xef, 0x9a, 0x58, 0xbd, 0xab, 0xa1, 0x51, 0xcf, 0xc2, 0x58, 0x66, 0xca, - 0x40, 0x54, 0xd7, 0xac, 0xae, 0xbd, 0xde, 0x1a, 0xf7, 0xe9, 0xe4, 0x89, 0x6b, 0x43, - 0xc7, 0x18, 0xef, 0x9d, - ], - }, - TestVector { - key: [ - 0x3d, 0x8b, 0xb6, 0x41, 0x5a, 0x53, 0x0b, 0xb2, 0x0f, 0x0d, 0x70, 0x2e, 0x8c, 0xb8, - 0x0b, 0xc1, 0xd5, 0xae, 0x41, 0x66, 0x5c, 0x53, 0x14, 0x4c, 0xfb, 0x60, 0x6e, 0x58, - 0x6a, 0xbc, 0x03, 0x33, - ], - description: [ - 0x62, 0xc8, 0xbb, 0xc6, 0xb1, 0xc5, 0xa9, 0xc9, 0x8c, 0xc9, 0x8e, 0xc6, 0xb6, 0xc3, - 0x85, 0xc4, 0xb0, 0x70, 0xc2, 0xb9, 0x49, 0xc8, 0x9b, 0xe1, 0x9b, 0x91, 0x69, 0xc8, - 0xaf, 0xc6, 0x94, 0xc5, 0xa2, 0x24, 0xe1, 0x9a, 0xb3, 0xcd, 0xb3, 0xe1, 0x9a, 0xa1, - 0x62, 0x67, 0xc3, 0x9a, 0xc7, 0x84, 0xe1, 0x9b, 0xa2, 0xc9, 0x86, 0xc6, 0xab, 0xc5, - 0xad, 0xc8, 0xad, 0xc6, 0xbe, 0xc3, 0x84, 0xc4, 0xad, 0xc3, 0xbf, 0xe2, 0xb1, 0xb9, - 0xc8, 0x8c, 0xc5, 0xb7, 0xe1, 0x9b, 0xad, 0xc6, 0x87, 0xc3, 0xa8, 0xce, 0x88, 0xc2, - 0xa5, 0xc3, 0xa7, 0xc5, 0xb6, 0xc4, 0x82, 0xe1, 0x9a, 0xbf, 0xc5, 0xad, 0xc8, 0xb9, - 0xc8, 0xab, 0xc3, 0xb8, 0xc5, 0x85, 0xc3, 0xb4, 0xc3, 0xa4, 0xc4, 0xb0, 0xc9, 0x8b, - 0xc6, 0x9c, 0xc8, 0x94, 0xe1, 0x9b, 0xab, 0xc8, 0xaa, 0xe1, 0x9a, 0xab, 0xc4, 0xa2, - 0xc3, 0xbc, 0x68, 0xc5, 0x84, 0xc9, 0x8c, 0xc8, 0xa8, 0x39, 0xc7, 0xab, 0xe1, 0x9b, - 0x8d, 0x47, 0xe1, 0x9a, 0xa1, 0x26, 0xc4, 0x82, 0xe1, 0x9a, 0xb0, 0xc8, 0xb4, 0x50, - 0xc8, 0xab, 0xc7, 0x81, 0xe1, 0x9a, 0xb3, 0xc5, 0x81, 0xe1, 0x9b, 0x94, 0x3e, 0xc3, - 0xa1, 0x4e, 0xc4, 0xb7, 0xc5, 0xbf, 0xc4, 0xa2, 0x26, 0xc2, 0xb1, 0xc6, 0xb3, 0xc5, - 0xa6, 0xc4, 0xb2, 0xc5, 0x90, 0xc8, 0x92, 0xc5, 0xbe, 0xc5, 0xbb, 0xc8, 0xac, 0x3c, - 0xc4, 0x91, 0xc4, 0xac, 0xc6, 0x87, 0xc4, 0x94, 0xe1, 0x9a, 0xa7, 0xc9, 0x85, 0xe2, - 0xb1, 0xa3, 0xe1, 0x9b, 0xb0, 0xc6, 0xaf, 0x79, 0xe1, 0x9a, 0xad, 0xc9, 0x8e, 0xe1, - 0x9a, 0xa2, 0x23, 0xe2, 0xb1, 0xb7, 0xc4, 0xba, 0x45, 0xe1, 0x9a, 0xbe, 0xc7, 0xb7, - 0xc3, 0xa6, 0x5a, 0xce, 0x88, 0xc5, 0xa9, 0x46, 0x6a, 0xc3, 0xb5, 0xe1, 0x9b, 0xab, - 0xc2, 0xbe, 0xe2, 0xb1, 0xbf, 0xc6, 0x82, 0x66, 0x42, 0xc5, 0xb4, 0xc8, 0x85, 0xc4, - 0x97, 0xc2, 0xab, 0xc2, 0xa9, 0xc7, 0x8f, 0xc7, 0xb9, 0xe1, 0x9b, 0x8f, 0xc8, 0xb1, - 0xc7, 0xaf, 0xc9, 0x82, 0xc7, 0x8a, 0x38, 0xc2, 0xa3, 0xc4, 0xaf, 0xc4, 0xac, 0xc3, - 0x9b, 0xc7, 0xb9, 0x6d, 0xc7, 0xbf, 0xe1, 0x9a, 0xa1, 0xe1, 0x9b, 0xa4, 0xc6, 0xbe, - 0xc6, 0xa7, 0xc3, 0x8f, 0xe1, 0x9b, 0xa9, 0xc6, 0xb1, 0xce, 0x89, 0xc2, 0xb3, 0xc5, - 0x8f, 0xc6, 0x95, 0x52, 0xc8, 0x83, 0xc2, 0xb1, 0xc6, 0xb3, 0xc3, 0x87, 0xe1, 0x9b, - 0x84, 0xc6, 0xae, 0x32, 0xe1, 0x9b, 0x99, 0xcd, 0xb6, 0xc5, 0xbb, 0xc6, 0xa7, 0xc5, - 0xbd, 0xc6, 0x9f, 0xc8, 0x87, 0xc2, 0xbb, 0xc2, 0xbe, 0x5c, 0xc5, 0xb8, 0xc8, 0x8c, - 0xc8, 0x9c, 0xc2, 0xab, 0xe2, 0xb1, 0xac, 0x3e, 0xc6, 0xbc, 0x6b, 0xc2, 0xb2, 0xc7, - 0x95, 0xc6, 0xa0, 0xc3, 0xa6, 0xe2, 0xb1, 0xaf, 0xe1, 0x9b, 0xa8, 0xc6, 0xb1, 0xc5, - 0x81, 0xc5, 0x96, 0xc3, 0x99, 0xc8, 0x9b, 0x2c, 0xc4, 0x93, 0xe2, 0xb1, 0xbb, 0xc2, - 0xab, 0xc8, 0x92, 0xc2, 0xb9, 0xc4, 0xb5, 0xc7, 0x94, 0xc3, 0x94, 0xe1, 0x9a, 0xb0, - 0xc4, 0xae, 0xe1, 0x9b, 0x84, 0x30, 0xc7, 0x91, 0xc2, 0xa4, 0xc5, 0x9a, 0xc5, 0x92, - 0xc9, 0x8f, 0xe1, 0x9a, 0xb6, 0xe1, 0x9a, 0xaa, 0xc8, 0xb2, 0xc6, 0x9e, 0x30, 0xc4, - 0xae, 0x6f, 0x73, 0xc2, 0xa3, 0xc7, 0x8c, 0xe2, 0xb1, 0xb8, 0x57, 0xc9, 0x89, 0xe1, - 0x9b, 0x8c, 0x60, 0xc4, 0x88, 0xce, 0x87, 0x4c, 0xc4, 0xaa, 0xc4, 0xab, 0xc2, 0xae, - 0xc7, 0x8a, 0xc7, 0xad, 0xc4, 0x87, 0xc5, 0xb3, 0x5b, 0x68, 0xc4, 0x9a, 0xc4, 0x9c, - 0x3a, 0xc4, 0x8b, 0xe1, 0x9a, 0xb2, 0x2e, 0xc5, 0x9a, 0xc2, 0xb9, 0xe1, 0x9a, 0xa3, - 0xe1, 0x9b, 0x8b, 0xc8, 0xa9, 0xc6, 0x9d, 0x34, - ], - asset_base: [ - 0x3e, 0x9f, 0x51, 0x16, 0x2c, 0xbf, 0x73, 0x86, 0x1a, 0xe5, 0xd7, 0xc5, 0x82, 0x4e, - 0x0e, 0x54, 0xac, 0x96, 0xe9, 0xd7, 0xa2, 0xcf, 0x5a, 0x76, 0x0b, 0xf2, 0x61, 0x21, - 0x93, 0xe5, 0x7a, 0x15, - ], - }, - TestVector { - key: [ - 0x95, 0xa6, 0xa5, 0x7f, 0x8e, 0x85, 0x43, 0x72, 0xf9, 0xce, 0x7d, 0xb1, 0x34, 0xfd, - 0x9e, 0x87, 0x43, 0xbd, 0x39, 0x17, 0xe6, 0x50, 0x52, 0x93, 0x4c, 0xbd, 0xef, 0xa7, - 0x67, 0xb7, 0xc7, 0x18, - ], - description: [ - 0xc5, 0x94, 0xc5, 0xb4, 0xc2, 0xbd, 0xc6, 0xa4, 0xc6, 0x8e, 0xe1, 0x9b, 0x80, 0xc5, - 0x9c, 0xc4, 0xb5, 0xc3, 0x9f, 0xc7, 0x9b, 0xc6, 0xb2, 0xc2, 0xa8, 0xc8, 0xa2, 0xc3, - 0xad, 0x52, 0xc5, 0xa9, 0xc4, 0x87, 0xc3, 0xbf, 0x2e, 0xc4, 0x8c, 0xc5, 0x8c, 0xc4, - 0x88, 0xc2, 0xbf, 0xc7, 0xb0, 0xc9, 0x85, 0xc4, 0xa6, 0xc7, 0x99, 0xe1, 0x9b, 0x81, - 0x42, 0xc3, 0x8f, 0xc7, 0x8c, 0xe1, 0x9a, 0xa8, 0x2b, 0xc3, 0x9d, 0xc9, 0x87, 0xc4, - 0x89, 0xc6, 0x87, 0xc8, 0x8c, 0xc4, 0xbe, 0x51, 0xc5, 0xac, 0xc9, 0x81, 0xc3, 0xb7, - 0xc5, 0xb2, 0xe1, 0x9b, 0x87, 0xc6, 0xad, 0xc8, 0xa6, 0xc6, 0xad, 0xc6, 0x93, 0xc9, - 0x84, 0xc8, 0x85, 0x6f, 0x41, 0xc7, 0xb5, 0xe1, 0x9b, 0xa8, 0xc5, 0x89, 0xe2, 0xb1, - 0xa7, 0xc3, 0x9f, 0x64, 0xc7, 0x9e, 0x62, 0xc3, 0x95, 0xc7, 0xa1, 0xc6, 0x80, 0xc4, - 0xbb, 0xc2, 0xb1, 0x53, 0xc7, 0xb4, 0x63, 0xe1, 0x9b, 0x95, 0x21, 0xc5, 0xa2, 0xc4, - 0xa3, 0xc3, 0x9a, 0xc6, 0xbe, 0xc4, 0x93, 0xc5, 0xa5, 0xe1, 0x9b, 0x88, 0xc3, 0x85, - 0xc7, 0x9e, 0xc3, 0xbf, 0x48, 0xc5, 0x8a, 0xc3, 0xaf, 0x51, 0xc5, 0x9b, 0xe1, 0x9b, - 0xa3, 0xc4, 0xbf, 0xc5, 0x96, 0xe1, 0x9b, 0x97, 0xc7, 0x8c, 0xc7, 0xb0, 0x7b, 0xc6, - 0x94, 0x23, 0xe1, 0x9b, 0x86, 0xce, 0x86, 0xc4, 0x85, 0xc5, 0x94, 0xc5, 0x9f, 0xc7, - 0x84, 0xc3, 0xb1, 0xc6, 0x8a, 0xc8, 0x97, 0xc3, 0x81, 0xe2, 0xb1, 0xaf, 0xc7, 0xbf, - 0xc2, 0xa6, 0xc6, 0xbf, 0xc4, 0xbe, 0xcd, 0xb6, 0xc3, 0xb6, 0xc9, 0x8c, 0xc7, 0x86, - 0xc5, 0x9a, 0xc3, 0x9d, 0xc3, 0x91, 0xc8, 0xb9, 0xc4, 0x9c, 0xc4, 0x89, 0xc3, 0x99, - 0x70, 0xe1, 0x9b, 0x83, 0xc8, 0x97, 0xc8, 0xaf, 0xc3, 0xa3, 0xe2, 0xb1, 0xbd, 0xe2, - 0xb1, 0xb8, 0xc7, 0x8c, 0xc7, 0xa5, 0x5c, 0xc6, 0xb2, 0xc2, 0xa9, 0xc7, 0xb9, 0xe1, - 0x9b, 0x88, 0xc5, 0xbc, 0xc5, 0x83, 0xc7, 0x90, 0xc6, 0x91, 0xc7, 0xa3, 0x30, 0xe1, - 0x9a, 0xb9, 0xe2, 0xb1, 0xbe, 0xe1, 0x9b, 0xa0, 0x4c, 0xe1, 0x9b, 0x93, 0xc5, 0x93, - 0xc8, 0xb8, 0xc6, 0x98, 0xc3, 0xb2, 0xc6, 0xbf, 0xe1, 0x9b, 0xa6, 0xc5, 0x84, 0xe1, - 0x9b, 0x91, 0xc6, 0xb2, 0xc5, 0x94, 0xc4, 0x93, 0xe1, 0x9b, 0x98, 0xcd, 0xb6, 0xc6, - 0xae, 0x60, 0xc5, 0xa4, 0xc6, 0x81, 0x46, 0xc6, 0x86, 0xc4, 0xa1, 0x33, 0xc6, 0xb2, - 0x71, 0xc6, 0xae, 0xe2, 0xb1, 0xb9, 0x3d, 0x35, 0xe1, 0x9b, 0x9e, 0x62, 0xc8, 0x93, - 0x61, 0xc4, 0x90, 0xe1, 0x9b, 0x8c, 0xe1, 0x9b, 0x9d, 0x35, 0xe1, 0x9b, 0xae, 0xc9, - 0x83, 0xc7, 0x8d, 0xe1, 0x9a, 0xa6, 0xe1, 0x9a, 0xb9, 0xc3, 0x86, 0xc8, 0x9e, 0xc8, - 0xa8, 0xc9, 0x8f, 0xcd, 0xbe, 0xc8, 0xbe, 0xc5, 0x94, 0x63, 0x67, 0xc2, 0xa7, 0xc8, - 0xbf, 0xe2, 0xb1, 0xb2, 0xc3, 0x80, 0x32, 0xc6, 0xac, 0xe1, 0x9a, 0xbc, 0xc3, 0xa6, - 0xc3, 0x96, 0xe1, 0x9b, 0xa5, 0xe1, 0x9a, 0xb2, 0x4c, 0xe1, 0x9b, 0xac, 0xc8, 0xac, - 0xc3, 0xb7, 0xc3, 0x8d, 0x79, 0xc3, 0x9b, 0xc9, 0x8c, 0xcd, 0xbc, 0xc5, 0x9c, 0xe1, - 0x9b, 0xb0, 0xe1, 0x9b, 0x9a, 0x7c, 0xc7, 0xb6, 0xc6, 0xbc, 0xc4, 0x88, 0xe1, 0x9a, - 0xb0, 0xc7, 0x83, 0xc4, 0x9c, 0xe1, 0x9b, 0x82, 0xc5, 0xad, 0xc8, 0xac, 0xe1, 0x9b, - 0xa7, 0x7c, 0xc8, 0x8e, 0xc2, 0xbc, 0xc6, 0x91, 0xc7, 0xbb, 0xc6, 0x83, 0xc5, 0x92, - 0xc5, 0x8e, 0x73, 0xcd, 0xb3, 0xe1, 0x9a, 0xbc, 0x40, 0x61, 0xc6, 0x98, 0xe2, 0xb1, - 0xa9, 0xce, 0x8a, 0xc7, 0xb2, 0x60, 0xc4, 0xb7, 0xc8, 0x83, 0xc6, 0xaa, 0xc7, 0xb5, - 0xc6, 0xbf, 0x41, 0xc7, 0xaf, 0xc6, 0x89, 0x5a, - ], - asset_base: [ - 0xf1, 0x2e, 0x1e, 0x6c, 0xdd, 0x2a, 0xdb, 0x59, 0x2a, 0x2b, 0xe1, 0x2c, 0x09, 0x18, - 0x31, 0x10, 0xc7, 0x39, 0x0b, 0x80, 0xf3, 0x7b, 0xba, 0x6c, 0x6f, 0x6f, 0xe2, 0x06, - 0xf6, 0xf6, 0x67, 0xac, - ], - }, - TestVector { - key: [ - 0xa3, 0x6d, 0xf3, 0x6a, 0xc7, 0xa2, 0xe2, 0xba, 0xab, 0xfd, 0x1e, 0x8d, 0xbf, 0x39, - 0x3b, 0xd8, 0x25, 0x32, 0xec, 0x3d, 0x52, 0x3b, 0xbe, 0x85, 0x7f, 0x71, 0x58, 0x0c, - 0xcd, 0x22, 0xdf, 0x08, - ], - description: [ - 0xc4, 0x81, 0xc7, 0x88, 0xc8, 0xa0, 0xc8, 0xa8, 0xc7, 0xa1, 0xc7, 0x86, 0x29, 0xc6, - 0x99, 0xe2, 0xb1, 0xbe, 0xc4, 0xb0, 0xe1, 0x9a, 0xaf, 0xc5, 0xa7, 0xc8, 0xbd, 0xe1, - 0x9b, 0x93, 0xe2, 0xb1, 0xa7, 0xe1, 0x9a, 0xb6, 0xc6, 0xb3, 0xe1, 0x9b, 0x89, 0xce, - 0x86, 0xc5, 0xa4, 0xc2, 0xa8, 0xc8, 0xa1, 0xe2, 0xb1, 0xa7, 0xc4, 0x98, 0xe1, 0x9b, - 0xa0, 0xc2, 0xb3, 0xe1, 0x9b, 0xa3, 0xe1, 0x9b, 0x9e, 0x3c, 0xe2, 0xb1, 0xa8, 0xc8, - 0xba, 0xc2, 0xb9, 0xc5, 0x9d, 0xc5, 0xa0, 0xe1, 0x9a, 0xb8, 0xc8, 0x85, 0xc6, 0x88, - 0xe2, 0xb1, 0xbd, 0xe1, 0x9b, 0x8b, 0xc6, 0xbb, 0xc2, 0xa5, 0xc5, 0x8e, 0xcd, 0xb7, - 0x74, 0xc4, 0xba, 0xc4, 0x9a, 0xc6, 0xb9, 0xc5, 0xbc, 0xc5, 0x86, 0xc8, 0x9d, 0xe2, - 0xb1, 0xb9, 0xe2, 0xb1, 0xa2, 0xe2, 0xb1, 0xa6, 0xc3, 0xba, 0xc4, 0xb8, 0xcd, 0xb4, - 0xc8, 0xa8, 0x3f, 0xc4, 0xa1, 0xc7, 0x9c, 0x41, 0xc7, 0x81, 0xc8, 0xb8, 0xc6, 0xb8, - 0xc7, 0xaa, 0xcd, 0xb1, 0xc4, 0xb1, 0xce, 0x8c, 0xe1, 0x9b, 0x86, 0x2d, 0xc8, 0x88, - 0xc5, 0xaa, 0xc8, 0xab, 0xc3, 0xb6, 0xc9, 0x8a, 0x75, 0xc8, 0xa1, 0xc4, 0xa7, 0xc4, - 0x85, 0x48, 0xc6, 0x88, 0x3c, 0xe2, 0xb1, 0xb6, 0xc4, 0x8b, 0xe1, 0x9b, 0xa3, 0xc6, - 0x9b, 0xc8, 0x9d, 0xe1, 0x9b, 0xac, 0xe2, 0xb1, 0xaf, 0x2d, 0xc8, 0x93, 0xc4, 0x88, - 0xc3, 0x83, 0xc7, 0x95, 0xe1, 0x9a, 0xb5, 0xc4, 0xa2, 0x68, 0xc3, 0xbf, 0xc4, 0x96, - 0xc8, 0x9d, 0x43, 0xcd, 0xb4, 0x3d, 0xc6, 0xb1, 0xc4, 0x9c, 0xe1, 0x9b, 0xad, 0xc6, - 0xa3, 0xc3, 0xbe, 0xc4, 0xbf, 0xc7, 0xb8, 0xc2, 0xaa, 0xc8, 0xac, 0xc4, 0x91, 0x6f, - 0xc7, 0xbf, 0xc5, 0x84, 0xc8, 0x94, 0xc7, 0x8b, 0x69, 0xc7, 0xb5, 0x3f, 0xc4, 0xb9, - 0xc3, 0xa7, 0xc2, 0xa7, 0xcd, 0xb3, 0xc3, 0xa2, 0xc2, 0xb9, 0xc5, 0xbb, 0xc4, 0x8b, - 0xce, 0x88, 0x74, 0xc4, 0x94, 0xc2, 0xa2, 0xc6, 0x81, 0xc8, 0xb9, 0xc3, 0xb8, 0xc4, - 0xae, 0xc7, 0xb1, 0xc6, 0xb1, 0xc8, 0xa5, 0xc6, 0x9b, 0xc2, 0xaa, 0xe1, 0x9b, 0xa6, - 0xe2, 0xb1, 0xb4, 0xc3, 0xb5, 0xc3, 0xaf, 0xc4, 0xb7, 0xc2, 0xa3, 0xc8, 0xb7, 0x55, - 0xc4, 0xb0, 0xe1, 0x9a, 0xad, 0xc5, 0x8f, 0xc8, 0x9e, 0xc6, 0xa0, 0xc8, 0x9c, 0xc7, - 0xad, 0xe1, 0x9b, 0x8b, 0xc7, 0xbb, 0x62, 0xe2, 0xb1, 0xba, 0xc6, 0xb1, 0xc6, 0x94, - 0xc8, 0x84, 0xe1, 0x9b, 0x9b, 0xc7, 0xa8, 0xc3, 0x8d, 0xc7, 0x8c, 0xce, 0x87, 0xc7, - 0xa1, 0xc4, 0x89, 0xc7, 0xb8, 0x4e, 0xc2, 0xb0, 0xc6, 0x8a, 0xe2, 0xb1, 0xb0, 0xc9, - 0x8e, 0x2e, 0xe2, 0xb1, 0xb3, 0xc8, 0x9d, 0xc5, 0x90, 0xe1, 0x9b, 0xa8, 0xc5, 0xac, - 0xc3, 0x98, 0x72, 0xc4, 0xb1, 0xc4, 0x9f, 0x69, 0xe1, 0x9b, 0x8f, 0x7e, 0xc3, 0xaf, - 0xc7, 0x97, 0xc8, 0x96, 0xc3, 0x8a, 0xe1, 0x9b, 0xa2, 0xc6, 0xb8, 0xc7, 0x80, 0xc8, - 0xbc, 0x7d, 0xce, 0x87, 0x47, 0xc4, 0xad, 0xc4, 0xb8, 0xc8, 0xa4, 0xe1, 0x9b, 0xad, - 0xc7, 0x8a, 0xc3, 0x9c, 0xc2, 0xba, 0xe1, 0x9b, 0x9f, 0xe1, 0x9b, 0x86, 0xc2, 0xaa, - 0xc4, 0xaf, 0xc8, 0x84, 0x28, 0x6c, 0xc2, 0xb9, 0xe1, 0x9b, 0xa6, 0xe1, 0x9b, 0xac, - 0xc3, 0xa5, 0x53, 0xc2, 0xa6, 0xc2, 0xa2, 0xe1, 0x9b, 0xa3, 0x57, 0xc9, 0x84, 0xc4, - 0xa5, 0xc5, 0x8a, 0x7d, 0xc2, 0xb1, 0x66, 0xc8, 0x86, 0xc8, 0xb3, 0xc8, 0x8d, 0xe1, - 0x9b, 0xae, 0xe2, 0xb1, 0xad, 0xc5, 0xb1, 0x55, 0xc8, 0x89, 0xc8, 0x8f, 0xc6, 0xa7, - 0xc4, 0xbd, 0xe2, 0xb1, 0xb4, 0xc4, 0xb6, 0x34, 0xc7, 0xb8, 0xc3, 0x86, 0xc7, 0xad, - 0xc4, 0x88, 0xc8, 0xa9, 0xc8, 0x8f, 0xc8, 0x80, - ], - asset_base: [ - 0xd6, 0x96, 0x5d, 0xaf, 0xad, 0x0f, 0xc5, 0xb1, 0x1a, 0x16, 0xc3, 0xc4, 0x0b, 0x27, - 0xc2, 0x10, 0x4c, 0xf9, 0x99, 0x7a, 0x43, 0x56, 0xa3, 0x82, 0xbb, 0xd7, 0xd4, 0xd2, - 0xcc, 0x84, 0x84, 0x9c, - ], - }, - TestVector { - key: [ - 0x68, 0x89, 0x11, 0x8f, 0xa9, 0xe7, 0xda, 0xf2, 0x76, 0xfd, 0x62, 0xcb, 0x66, 0x5a, - 0xbf, 0x50, 0x72, 0x20, 0x15, 0xc2, 0xa0, 0x8b, 0x13, 0xf7, 0x7d, 0x20, 0x24, 0x75, - 0x96, 0x26, 0xc5, 0x03, - ], - description: [ - 0x2b, 0xc2, 0xbe, 0xe1, 0x9b, 0x94, 0xe2, 0xb1, 0xad, 0xc2, 0xa8, 0xc4, 0x9a, 0xc3, - 0x8c, 0xe2, 0xb1, 0xaa, 0xc7, 0x83, 0x6a, 0xc8, 0xbf, 0xc6, 0xbd, 0xc4, 0xa6, 0xc2, - 0xa2, 0xc5, 0x8e, 0xc8, 0x9e, 0xce, 0x89, 0xc5, 0xa1, 0xc6, 0xb8, 0xc8, 0x89, 0xe1, - 0x9a, 0xaf, 0xc8, 0xa1, 0xc9, 0x8e, 0xc3, 0xbf, 0xc7, 0xbc, 0x64, 0x72, 0xc4, 0xbb, - 0xc6, 0x9a, 0xc6, 0x97, 0x2a, 0xc3, 0xb4, 0x4f, 0x4b, 0xc4, 0xa2, 0xc3, 0x93, 0xe2, - 0xb1, 0xba, 0xe2, 0xb1, 0xb5, 0x37, 0xe1, 0x9b, 0x9a, 0xc2, 0xbb, 0xc5, 0x94, 0xc7, - 0xb8, 0xc5, 0x93, 0xc6, 0xa2, 0xc8, 0xa9, 0xc6, 0xa2, 0x5f, 0xc5, 0xb7, 0xc3, 0xae, - 0xc3, 0x98, 0xc6, 0x89, 0xc8, 0xa1, 0xc8, 0x87, 0xc4, 0x9c, 0xe2, 0xb1, 0xb5, 0xc7, - 0xb3, 0xc3, 0x9e, 0xc7, 0x8c, 0xc8, 0xa4, 0xe1, 0x9a, 0xa4, 0xe1, 0x9b, 0x9f, 0xe1, - 0x9b, 0x9a, 0xc8, 0x9c, 0xc7, 0xa4, 0xc3, 0xac, 0x47, 0x56, 0xe1, 0x9a, 0xae, 0x7e, - 0xc7, 0x8b, 0xc8, 0x9e, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, 0x84, 0x73, 0xc7, 0x93, 0xc5, - 0xba, 0x6f, 0xe2, 0xb1, 0xb0, 0xc4, 0xa0, 0xe1, 0x9b, 0x89, 0xe1, 0x9a, 0xb6, 0xc3, - 0x82, 0xe1, 0x9a, 0xbd, 0xc9, 0x8b, 0xc7, 0xb8, 0xe2, 0xb1, 0xaf, 0xc5, 0xba, 0x21, - 0xc3, 0x9c, 0x3c, 0xe1, 0x9b, 0x96, 0xc8, 0xac, 0x6e, 0xc5, 0x8d, 0xe1, 0x9b, 0x80, - 0xc3, 0xab, 0xc5, 0x85, 0xc4, 0xab, 0x6b, 0xc5, 0x90, 0xc8, 0x99, 0xe1, 0x9b, 0x99, - 0xc8, 0x84, 0xc3, 0xbb, 0xc8, 0x82, 0xc8, 0xa1, 0xc3, 0x92, 0xc7, 0x9d, 0xc4, 0xaf, - 0xc6, 0xaa, 0x61, 0xc5, 0x82, 0xc7, 0xb9, 0xc7, 0xa1, 0xce, 0x89, 0xc8, 0xb2, 0xe1, - 0x9b, 0xa8, 0xc7, 0x8d, 0xcd, 0xbe, 0x67, 0xc9, 0x87, 0xc4, 0xba, 0x43, 0xc7, 0xa2, - 0xc6, 0xb1, 0xe1, 0x9a, 0xad, 0xc5, 0x83, 0xc3, 0xb0, 0xc5, 0xb2, 0xc6, 0x9a, 0x3e, - 0xc4, 0xb8, 0xc2, 0xb9, 0xc8, 0xa1, 0xc6, 0x93, 0xc7, 0xa5, 0x6a, 0xc5, 0xa9, 0xc4, - 0xa7, 0xc8, 0xb6, 0xc3, 0xa6, 0xc4, 0xb2, 0xc8, 0x8d, 0xcd, 0xb1, 0x41, 0xc6, 0x85, - 0xc7, 0x84, 0xc4, 0x83, 0xe1, 0x9b, 0xa9, 0xc2, 0xb5, 0x52, 0xc5, 0x80, 0xe1, 0x9b, - 0x83, 0xc6, 0xbb, 0xc5, 0x8e, 0xe1, 0x9a, 0xa4, 0xc2, 0xa6, 0xe1, 0x9b, 0xa3, 0xe1, - 0x9a, 0xbd, 0xe1, 0x9b, 0xaf, 0xc4, 0xba, 0xe2, 0xb1, 0xa6, 0xc3, 0x89, 0x5a, 0xc4, - 0xa9, 0xe1, 0x9a, 0xba, 0x5d, 0xc6, 0x9f, 0xc4, 0xa8, 0xc4, 0xa3, 0xc5, 0x9f, 0xc6, - 0x8e, 0xe2, 0xb1, 0xb8, 0xc8, 0x9b, 0xe2, 0xb1, 0xa5, 0xc6, 0x9d, 0xe1, 0x9a, 0xaa, - 0xe1, 0x9b, 0x98, 0xc2, 0xa1, 0xc2, 0xb4, 0xc6, 0x87, 0xc7, 0x93, 0xc6, 0x88, 0xe1, - 0x9a, 0xb3, 0xc4, 0x98, 0xc2, 0xb1, 0xc8, 0x91, 0xc3, 0xb5, 0x62, 0xc7, 0xb8, 0xe1, - 0x9b, 0x94, 0xc3, 0x87, 0xc4, 0xa7, 0xc8, 0x8a, 0xc5, 0x95, 0xe1, 0x9b, 0xb0, 0xc4, - 0x98, 0xe2, 0xb1, 0xb3, 0xc5, 0xac, 0xcd, 0xb3, 0xc6, 0xbb, 0xc7, 0xbf, 0xc4, 0xbe, - 0xc3, 0x98, 0xcd, 0xba, 0x5d, 0xc3, 0x9e, 0x5a, 0xc4, 0x8c, 0x3e, 0x3f, 0x76, 0xc7, - 0x8a, 0xe1, 0x9a, 0xbf, 0xc6, 0xa6, 0xe1, 0x9b, 0x95, 0x77, 0xc7, 0xb2, 0xe1, 0x9b, - 0x91, 0xc8, 0x84, 0xe2, 0xb1, 0xa3, 0xc7, 0x82, 0xc4, 0x87, 0x70, 0xe1, 0x9a, 0xb1, - 0xc6, 0x91, 0xe1, 0x9a, 0xba, 0xc5, 0xa4, 0xc8, 0x8c, 0x59, 0xc4, 0xaa, 0xc6, 0x9a, - 0xc7, 0xb0, 0xc3, 0x87, 0xc7, 0xb6, 0xc6, 0x80, 0x3c, 0xcd, 0xb4, 0xc4, 0x8d, 0x71, - 0xe1, 0x9b, 0x9b, 0xe2, 0xb1, 0xb6, 0xc6, 0xb9, 0xe1, 0x9b, 0x85, 0xe2, 0xb1, 0xba, - 0xc7, 0xb2, 0xc8, 0xa4, 0xe1, 0x9a, 0xa2, 0x5a, - ], - asset_base: [ - 0x98, 0x06, 0x94, 0xc0, 0xcc, 0x2c, 0x02, 0x1c, 0xa3, 0x57, 0xa6, 0x06, 0x25, 0x2e, - 0x7e, 0x66, 0x90, 0xed, 0xa5, 0xea, 0x56, 0xc4, 0xfb, 0x57, 0x32, 0xdd, 0x0b, 0x8b, - 0xbf, 0xf0, 0x3b, 0x9d, - ], - }, - TestVector { - key: [ - 0x7a, 0xb9, 0xe5, 0xa6, 0x04, 0x28, 0x8a, 0x55, 0x0b, 0x9e, 0x08, 0x7a, 0x00, 0x4b, - 0xb8, 0x8b, 0xe4, 0xb2, 0xb4, 0x8d, 0xb3, 0x3f, 0xb0, 0x80, 0x97, 0xf8, 0xbc, 0x64, - 0x60, 0x3e, 0xf8, 0x1f, - ], - description: [ - 0xc2, 0xb3, 0xe2, 0xb1, 0xb3, 0xc4, 0xab, 0xe1, 0x9b, 0x81, 0xe1, 0x9a, 0xbc, 0xc7, - 0x82, 0xc3, 0xa6, 0xc7, 0x94, 0xc4, 0x8a, 0xc7, 0x8f, 0xc6, 0xaf, 0xc7, 0xaf, 0xc3, - 0xbe, 0xe1, 0x9a, 0xa7, 0xc6, 0x88, 0xc6, 0xb2, 0xc6, 0xab, 0xc4, 0x98, 0xc6, 0xb4, - 0xc7, 0x9b, 0xc7, 0xbb, 0xe1, 0x9b, 0xa1, 0xc5, 0xba, 0xc4, 0xb3, 0xc8, 0xb5, 0xe1, - 0x9b, 0x97, 0xc5, 0xb7, 0xc8, 0x89, 0x35, 0x66, 0xcd, 0xba, 0xc6, 0xb2, 0xc6, 0xac, - 0x29, 0xe2, 0xb1, 0xa9, 0xc8, 0xb4, 0xc3, 0xa5, 0x7d, 0xc8, 0xa0, 0xc3, 0x9a, 0xc8, - 0xaf, 0xc8, 0x82, 0xc3, 0xa4, 0xc4, 0xb5, 0x37, 0xe1, 0x9b, 0xa0, 0xc4, 0x8e, 0x32, - 0xc5, 0xb2, 0xc4, 0x90, 0xc5, 0xbb, 0xe1, 0x9b, 0x8d, 0xc7, 0x8a, 0xe1, 0x9a, 0xb2, - 0xc6, 0xbb, 0xc7, 0xa5, 0xc2, 0xbe, 0xe1, 0x9b, 0x96, 0xc3, 0x91, 0xc6, 0x86, 0xe1, - 0x9b, 0xa7, 0xc5, 0x93, 0xc3, 0xb5, 0x59, 0xc6, 0x9a, 0xc7, 0x9c, 0xe1, 0x9a, 0xb8, - 0xc6, 0x83, 0xe2, 0xb1, 0xb9, 0x59, 0xc9, 0x8b, 0xc4, 0x90, 0xc6, 0x92, 0xc2, 0xbf, - 0xc7, 0xbf, 0xc6, 0x97, 0x61, 0x37, 0xc8, 0xbc, 0xc2, 0xbd, 0xc5, 0xb7, 0xc5, 0xa3, - 0xc4, 0xa4, 0xc7, 0x96, 0xc6, 0x84, 0xc6, 0xb6, 0xc4, 0x83, 0x42, 0xc8, 0xba, 0xc7, - 0x94, 0xe1, 0x9b, 0xa2, 0xc3, 0xbf, 0xc6, 0xb5, 0xc6, 0x94, 0x7c, 0xc2, 0xbc, 0x5e, - 0xc3, 0xa6, 0xe1, 0x9a, 0xb6, 0xc9, 0x8b, 0xc4, 0x83, 0xc8, 0x9b, 0xc8, 0x9d, 0xc3, - 0xb3, 0xc8, 0xb6, 0xe1, 0x9b, 0xa8, 0xc2, 0xbd, 0xe1, 0x9b, 0xa3, 0xc8, 0x8f, 0x26, - 0xe1, 0x9b, 0x8d, 0xc8, 0x88, 0xc6, 0xbd, 0x6a, 0xc3, 0x8b, 0xc5, 0x91, 0xc4, 0xb1, - 0xce, 0x89, 0x4b, 0xc5, 0xb1, 0xe1, 0x9b, 0x8c, 0xc3, 0x9f, 0xc4, 0xb8, 0xc3, 0x98, - 0xe1, 0x9b, 0x91, 0xc7, 0xa9, 0xc8, 0x9c, 0xc5, 0x93, 0xc6, 0xb0, 0xe1, 0x9b, 0x89, - 0x6c, 0xe1, 0x9b, 0xa4, 0x4a, 0xc6, 0xad, 0xc7, 0x92, 0xc3, 0x88, 0x71, 0xc6, 0xa0, - 0xc6, 0x9f, 0xe1, 0x9b, 0x94, 0xc4, 0xbe, 0xc5, 0x84, 0xc4, 0x9e, 0xc2, 0xb6, 0xcd, - 0xb7, 0xc4, 0xa6, 0xc7, 0xbb, 0xc3, 0x97, 0xc7, 0x87, 0xc4, 0x94, 0x75, 0x43, 0xc6, - 0xbd, 0xc3, 0xb1, 0xc8, 0x92, 0xc3, 0x93, 0xc7, 0x8d, 0x65, 0xc8, 0x8a, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb5, 0xe2, 0xb1, 0xb0, 0xc7, 0x8d, 0x2f, 0x3f, 0xc3, 0xa9, 0xc8, 0xa1, - 0xc5, 0xa0, 0xc4, 0xa1, 0xc7, 0x87, 0xc2, 0xa6, 0x52, 0xc5, 0x89, 0xe1, 0x9b, 0xaf, - 0xc8, 0x84, 0xc5, 0xa3, 0xc7, 0x95, 0xc8, 0xa5, 0xc5, 0xb5, 0xc4, 0xa1, 0x79, 0xe1, - 0x9a, 0xba, 0xc8, 0x97, 0xc3, 0x94, 0xc5, 0x80, 0xe1, 0x9b, 0x88, 0x4b, 0x68, 0xc7, - 0x89, 0xc5, 0x98, 0x4e, 0xc4, 0xb9, 0xe1, 0x9b, 0xab, 0xc4, 0x95, 0xc6, 0xa0, 0xe1, - 0x9b, 0xa5, 0x24, 0xc6, 0x85, 0xc3, 0x93, 0xc6, 0x98, 0x6c, 0xc8, 0x94, 0xc5, 0xaa, - 0xc4, 0x94, 0xc3, 0xaf, 0xc4, 0xb6, 0x46, 0xc5, 0x90, 0xc4, 0x91, 0xc6, 0x97, 0xce, - 0x8a, 0xc7, 0xb9, 0xc6, 0xa7, 0xc3, 0x81, 0xc6, 0xa1, 0xc7, 0x82, 0xcd, 0xbc, 0xc6, - 0x82, 0xc2, 0xb9, 0xc5, 0xa7, 0xc5, 0xa3, 0xc9, 0x84, 0xc4, 0x8e, 0xc8, 0x9b, 0xe2, - 0xb1, 0xae, 0xe1, 0x9a, 0xbe, 0xc7, 0xb8, 0xe2, 0xb1, 0xb4, 0xe2, 0xb1, 0xba, 0xc4, - 0xb6, 0xc7, 0x8d, 0xe2, 0xb1, 0xb1, 0xc7, 0xbf, 0x50, 0xc5, 0x9f, 0xc6, 0x9d, 0xc5, - 0xa4, 0xc6, 0xb2, 0xc7, 0x83, 0x76, 0x68, 0xc8, 0x90, 0xc3, 0xaa, 0xc8, 0x8b, 0xc8, - 0x86, 0xc5, 0xba, 0x76, 0xcd, 0xb1, 0xc6, 0xa7, 0xc6, 0xa7, 0xc6, 0x84, 0xe1, 0x9b, - 0xa7, 0xc9, 0x8c, 0xc9, 0x89, 0x53, 0xc4, 0xb5, - ], - asset_base: [ - 0xc1, 0x69, 0x63, 0x4b, 0xf8, 0x47, 0x9d, 0x3d, 0x09, 0x47, 0x76, 0x4f, 0xbd, 0x30, - 0x3c, 0x31, 0xdc, 0x10, 0xb0, 0xa2, 0x81, 0x39, 0x1f, 0x5a, 0xde, 0xac, 0xf8, 0x2a, - 0xae, 0xce, 0xf3, 0xbe, - ], - }, - TestVector { - key: [ - 0xa2, 0x4a, 0x5b, 0x4b, 0x0c, 0x62, 0xe0, 0xfb, 0x6f, 0x01, 0xdb, 0x56, 0x7c, 0x33, - 0x3e, 0x12, 0x82, 0xe3, 0x70, 0xa6, 0x6f, 0x16, 0x8a, 0xe7, 0xf7, 0x7a, 0x3f, 0x16, - 0xaf, 0x40, 0x8d, 0x12, - ], - description: [ - 0xc8, 0xa5, 0xc4, 0xb5, 0xc8, 0xb7, 0xc6, 0xa8, 0x2e, 0xc7, 0xa8, 0xc7, 0xb0, 0x52, - 0xc7, 0xac, 0xc8, 0xbf, 0x79, 0xe1, 0x9a, 0xba, 0xe1, 0x9b, 0x83, 0xc3, 0xa9, 0xc4, - 0x90, 0xc7, 0x90, 0xc3, 0x80, 0xe1, 0x9b, 0x93, 0xe1, 0x9a, 0xad, 0x58, 0xc7, 0x9b, - 0xc5, 0x85, 0x69, 0xc5, 0x90, 0xc2, 0xb8, 0xc5, 0x92, 0xc4, 0xaa, 0xc2, 0xa5, 0xc4, - 0xaa, 0xc3, 0xa9, 0xc6, 0xaa, 0xc8, 0xa1, 0xc5, 0x8b, 0xc2, 0xbf, 0xe1, 0x9b, 0xa3, - 0xcd, 0xb4, 0xc5, 0xb9, 0xc7, 0x95, 0x32, 0xc7, 0xba, 0xc5, 0x8f, 0xc2, 0xbb, 0xc3, - 0xb4, 0xe2, 0xb1, 0xb0, 0xc8, 0xb6, 0xe1, 0x9a, 0xbd, 0xc4, 0xa7, 0xc5, 0xad, 0xc4, - 0x9e, 0xe1, 0x9a, 0xb5, 0xc6, 0xae, 0xc3, 0xb9, 0xc3, 0x89, 0xc7, 0xba, 0xc3, 0x90, - 0xc7, 0xb4, 0xc3, 0xbe, 0xe2, 0xb1, 0xb7, 0xc6, 0x90, 0xc5, 0x83, 0xc8, 0xba, 0xc5, - 0x89, 0xc5, 0xa9, 0xc9, 0x86, 0x4d, 0x53, 0xcd, 0xb5, 0xc2, 0xb0, 0xc2, 0xb5, 0xc6, - 0x9b, 0x7a, 0xc4, 0x8f, 0xc3, 0x96, 0x45, 0xc3, 0xab, 0xc5, 0x8d, 0x4c, 0xc4, 0x81, - 0xe1, 0x9b, 0xad, 0xc8, 0x93, 0xe2, 0xb1, 0xbb, 0x5a, 0xc5, 0xaf, 0xc7, 0xa3, 0x71, - 0xc6, 0xa1, 0xe1, 0x9b, 0xaf, 0xc5, 0x84, 0xc6, 0x86, 0xc7, 0xa0, 0xc2, 0xae, 0xc4, - 0xac, 0xcd, 0xbb, 0xc4, 0x8e, 0xc6, 0x9c, 0xc8, 0x85, 0xc2, 0xa4, 0xc5, 0x85, 0xc8, - 0x9b, 0xc6, 0x87, 0xe1, 0x9b, 0xad, 0xc3, 0x80, 0xc4, 0xb5, 0xe2, 0xb1, 0xbb, 0xc5, - 0x9b, 0xc7, 0xb6, 0xc2, 0xb5, 0xc7, 0x8c, 0xc5, 0x86, 0xc6, 0xa8, 0xc5, 0xb7, 0xe1, - 0x9b, 0xa2, 0xc7, 0x90, 0xc2, 0xb0, 0x2e, 0xc5, 0x95, 0xe1, 0x9b, 0x82, 0xc5, 0x89, - 0xc4, 0xa3, 0xe1, 0x9b, 0x87, 0x3c, 0xc9, 0x84, 0x46, 0x2c, 0xe2, 0xb1, 0xbb, 0xe1, - 0x9b, 0x8c, 0xc3, 0xb2, 0xc6, 0xa1, 0xc6, 0x85, 0x31, 0x45, 0xe2, 0xb1, 0xa9, 0xc5, - 0x8c, 0xc6, 0x88, 0xce, 0x84, 0xc5, 0x93, 0xc5, 0xa9, 0xe1, 0x9a, 0xa7, 0xcd, 0xb6, - 0xe1, 0x9b, 0xae, 0xc8, 0xa3, 0x5f, 0xe1, 0x9b, 0x94, 0xe1, 0x9b, 0xac, 0xc5, 0xbb, - 0xc7, 0xa2, 0xc6, 0x99, 0xc7, 0xbb, 0xc5, 0xbf, 0xc4, 0x95, 0xc7, 0x94, 0xe1, 0x9a, - 0xb8, 0xe2, 0xb1, 0xaf, 0xc9, 0x8a, 0xc7, 0x9d, 0xc8, 0x88, 0x7e, 0xc9, 0x88, 0x3e, - 0x21, 0x3e, 0xc5, 0xba, 0xc4, 0x9a, 0x30, 0xc9, 0x87, 0xc5, 0x9c, 0x44, 0xc4, 0xa6, - 0xc3, 0xad, 0xc5, 0x90, 0xc4, 0xa7, 0xc7, 0x9b, 0x3c, 0x58, 0xc4, 0x89, 0xc5, 0x9e, - 0xc5, 0x93, 0xe1, 0x9a, 0xbf, 0xc8, 0xb3, 0xe1, 0x9a, 0xb3, 0xc2, 0xa2, 0xc8, 0xbc, - 0xc6, 0xa6, 0x24, 0xe1, 0x9a, 0xba, 0xc6, 0xae, 0xe1, 0x9a, 0xa0, 0x57, 0xc6, 0x9a, - 0xc2, 0xbc, 0xc8, 0xbc, 0xc2, 0xb0, 0xc3, 0xa5, 0xc5, 0x81, 0xc3, 0xba, 0xe2, 0xb1, - 0xa5, 0xc7, 0xbf, 0xc4, 0xae, 0xc8, 0xae, 0xc2, 0xa6, 0xc6, 0xad, 0xc7, 0x82, 0xc3, - 0xba, 0xc5, 0x9d, 0xc3, 0x96, 0xc7, 0x93, 0xc7, 0xb9, 0xc4, 0xa7, 0xc7, 0xba, 0xc2, - 0xb1, 0xcd, 0xb7, 0xc4, 0xa8, 0xe2, 0xb1, 0xac, 0xe1, 0x9b, 0x89, 0xe2, 0xb1, 0xbc, - 0xc6, 0xb3, 0xc8, 0x9b, 0xc8, 0xbb, 0xe1, 0x9a, 0xa1, 0xc2, 0xa1, 0xc7, 0x81, 0xc8, - 0x98, 0xc4, 0x9b, 0xe1, 0x9a, 0xb8, 0xc6, 0x9f, 0xc2, 0xa7, 0xc5, 0x85, 0xc3, 0xb8, - 0xc7, 0x97, 0xc9, 0x83, 0xc9, 0x89, 0xc7, 0x90, 0xc8, 0xbf, 0xc8, 0xaa, 0xc8, 0x8a, - 0xc6, 0x9a, 0xc5, 0x81, 0xc7, 0x9e, 0x4b, 0xc3, 0x90, 0xc6, 0xa8, 0xe1, 0x9b, 0x9c, - 0xc8, 0x94, 0xc7, 0x9c, 0xc5, 0x90, 0xc4, 0x9b, 0xe1, 0x9b, 0x9d, 0xe1, 0x9b, 0xb0, - 0xe1, 0x9a, 0xa2, 0xc6, 0xb8, 0x61, 0x5a, 0x5a, - ], - asset_base: [ - 0xed, 0x3b, 0xad, 0xc9, 0x6d, 0xc0, 0x5f, 0x5f, 0x70, 0x48, 0xcc, 0x86, 0xd9, 0xea, - 0xe7, 0x59, 0x9b, 0x57, 0xd8, 0x61, 0xbe, 0x33, 0x15, 0x4e, 0x3b, 0x88, 0xc3, 0xc6, - 0x86, 0xb2, 0x82, 0xbb, - ], - }, - TestVector { - key: [ - 0xbe, 0xb4, 0x9a, 0x61, 0x01, 0x0b, 0x35, 0x51, 0xbc, 0x5c, 0xb2, 0xdb, 0xbc, 0xa6, - 0x0b, 0x20, 0xb5, 0x31, 0x6e, 0x42, 0x21, 0xdc, 0x9c, 0xed, 0xb8, 0xc3, 0xc4, 0x62, - 0xc1, 0xca, 0xcd, 0x02, - ], - description: [ - 0x79, 0x60, 0xc6, 0xb7, 0xc3, 0x8a, 0xc7, 0xb3, 0xe2, 0xb1, 0xbd, 0xc6, 0x85, 0xc6, - 0xb3, 0xc7, 0x9d, 0xe1, 0x9a, 0xa6, 0xc7, 0xba, 0xc4, 0xb8, 0xe1, 0x9b, 0xa1, 0xc3, - 0xbe, 0xe2, 0xb1, 0xb4, 0x7c, 0xe2, 0xb1, 0xae, 0xc8, 0x90, 0xc5, 0xab, 0xc5, 0xbc, - 0x4f, 0xc5, 0xb8, 0x6c, 0x5f, 0xe1, 0x9a, 0xbf, 0xc5, 0x8a, 0xe1, 0x9b, 0xa7, 0xc8, - 0xbc, 0xc8, 0x9b, 0xc3, 0xa7, 0xc5, 0xa6, 0xc4, 0xac, 0xe2, 0xb1, 0xab, 0x38, 0xc7, - 0x99, 0x54, 0xe2, 0xb1, 0xb6, 0x50, 0xc5, 0x8c, 0xe2, 0xb1, 0xb0, 0xc5, 0xb7, 0xc5, - 0x86, 0xc5, 0xa8, 0x3e, 0xc8, 0x88, 0xc4, 0xb5, 0xc5, 0x9c, 0xc7, 0x9b, 0xe1, 0x9b, - 0x8a, 0xc3, 0x97, 0xc8, 0xba, 0xe1, 0x9a, 0xa8, 0xc6, 0xb8, 0xc2, 0xa3, 0xe1, 0x9b, - 0x82, 0xe1, 0x9b, 0xa5, 0xc2, 0xae, 0xc8, 0x94, 0xe1, 0x9b, 0xa8, 0xc6, 0xb4, 0xc8, - 0xb9, 0xc3, 0xaf, 0xc6, 0xab, 0xc3, 0x91, 0xe2, 0xb1, 0xb3, 0xc4, 0xb6, 0xc5, 0xbf, - 0xc4, 0x8d, 0x43, 0xc6, 0xa0, 0xc4, 0xb3, 0xc6, 0x98, 0xc5, 0xbc, 0xc6, 0x9a, 0xc6, - 0xb3, 0xc3, 0x91, 0xc3, 0xa2, 0xc8, 0xa7, 0xc8, 0x9c, 0xc7, 0xb4, 0x43, 0xc7, 0x82, - 0xc2, 0xbe, 0xc7, 0xbf, 0xe1, 0x9a, 0xa9, 0xc3, 0xb2, 0xc4, 0xb2, 0xc8, 0xb0, 0xc7, - 0x80, 0xc6, 0xac, 0xc3, 0xb7, 0xc5, 0x91, 0xe1, 0x9b, 0x8f, 0xc8, 0xbb, 0xc3, 0x9f, - 0xc6, 0xa5, 0x7b, 0xc3, 0xb9, 0xcd, 0xb0, 0xe1, 0x9b, 0xa2, 0xc8, 0x8f, 0xc5, 0xa9, - 0xcd, 0xbd, 0xc8, 0x90, 0xcd, 0xb3, 0xe1, 0x9b, 0xa9, 0xc8, 0x82, 0xc3, 0xb6, 0xe1, - 0x9b, 0xa9, 0xc2, 0xb4, 0xc4, 0x9f, 0xc9, 0x8e, 0xc6, 0x8a, 0x37, 0xc7, 0x93, 0xc6, - 0x96, 0xc3, 0xa8, 0xc2, 0xae, 0xce, 0x84, 0xe2, 0xb1, 0xb2, 0xc2, 0xb6, 0xc5, 0x95, - 0xe2, 0xb1, 0xba, 0xc4, 0xa2, 0xc6, 0xbb, 0xc8, 0x93, 0xc3, 0x9f, 0xc5, 0xb0, 0xc5, - 0xb8, 0xe1, 0x9b, 0x8f, 0xc7, 0xb4, 0xc7, 0xaa, 0xc2, 0xb0, 0xe1, 0x9a, 0xb3, 0x5f, - 0xc6, 0xb1, 0xc8, 0x93, 0xc4, 0xb8, 0xe1, 0x9a, 0xa0, 0xc7, 0x9f, 0xc2, 0xb6, 0xe1, - 0x9b, 0xa2, 0xc8, 0x86, 0xe1, 0x9a, 0xa6, 0xc5, 0x8d, 0xc8, 0x89, 0xe1, 0x9a, 0xa4, - 0x44, 0xc5, 0xb3, 0xc8, 0x89, 0x5d, 0xc4, 0xa8, 0xc2, 0xa1, 0xcd, 0xbc, 0xc3, 0x88, - 0xc6, 0xb2, 0xe1, 0x9b, 0xa9, 0x26, 0xc8, 0xbb, 0xc3, 0xb9, 0xe1, 0x9b, 0x99, 0xc5, - 0xb2, 0x40, 0xc3, 0x8d, 0xc9, 0x8c, 0x5e, 0xe2, 0xb1, 0xa9, 0xc7, 0x9a, 0xe1, 0x9b, - 0xa1, 0xc4, 0x9a, 0xe1, 0x9b, 0x85, 0xc9, 0x80, 0xe1, 0x9a, 0xbf, 0xc3, 0x81, 0xe1, - 0x9b, 0x8e, 0xc8, 0x92, 0xe1, 0x9a, 0xaa, 0xc6, 0xac, 0xc9, 0x8f, 0xc7, 0x88, 0x3e, - 0xc3, 0xa8, 0xc3, 0xba, 0xc8, 0x96, 0xc6, 0xa2, 0xc7, 0x9e, 0xc8, 0x81, 0xc6, 0xac, - 0xc6, 0x85, 0xc8, 0xb6, 0xc8, 0x91, 0xc7, 0x99, 0xc6, 0x89, 0xc4, 0xae, 0xe1, 0x9b, - 0x8c, 0xe1, 0x9b, 0xad, 0xe1, 0x9b, 0xae, 0xc2, 0xb3, 0xc5, 0xa3, 0xc2, 0xa8, 0xc5, - 0xbc, 0xc3, 0xa7, 0xc8, 0xb6, 0xc6, 0xb1, 0xc8, 0x9e, 0xc6, 0x87, 0xc6, 0x80, 0x61, - 0xc6, 0xb3, 0x5c, 0xe1, 0x9a, 0xb0, 0xe1, 0x9b, 0x97, 0xe2, 0xb1, 0xaa, 0x25, 0xcd, - 0xb4, 0xc7, 0x89, 0x28, 0xc6, 0x8d, 0x6e, 0x40, 0xc7, 0xb6, 0xc7, 0x9e, 0xc6, 0x93, - 0x2d, 0xc7, 0xaf, 0xc6, 0x86, 0xc6, 0xbf, 0xc6, 0x9a, 0xc7, 0x82, 0xc6, 0x8c, 0xc7, - 0xaa, 0xe2, 0xb1, 0xa4, 0xc7, 0xa9, 0x32, 0x75, 0xc8, 0x98, 0xc8, 0xb7, 0xe2, 0xb1, - 0xb5, 0xc5, 0x89, 0xc2, 0xb4, 0xc8, 0xb8, 0xc6, 0xad, 0xc4, 0x9a, 0xe2, 0xb1, 0xb3, - 0xc3, 0x84, 0xc2, 0xb0, 0xc8, 0xa4, 0xc6, 0xb3, - ], - asset_base: [ - 0xb2, 0xd8, 0x44, 0xfe, 0xe4, 0x40, 0xbd, 0x64, 0x96, 0xd3, 0x1d, 0x5e, 0xdb, 0xee, - 0x95, 0x62, 0x3d, 0x19, 0x0e, 0xb3, 0x48, 0x4c, 0x48, 0x71, 0x0c, 0x76, 0x2f, 0x21, - 0x5b, 0x68, 0x4d, 0xbf, - ], - }, - TestVector { - key: [ - 0xb7, 0x0b, 0xb2, 0x77, 0xc0, 0x83, 0xf2, 0x95, 0x37, 0x6a, 0x02, 0xb3, 0x98, 0x76, - 0xae, 0x35, 0xfb, 0x26, 0x62, 0x3d, 0x9d, 0x6a, 0x55, 0xa5, 0x63, 0xf7, 0x85, 0xa6, - 0x5b, 0xc5, 0xa8, 0x27, - ], - description: [ - 0xc7, 0x96, 0xc8, 0xad, 0xc4, 0xbd, 0xe1, 0x9b, 0x9b, 0xe1, 0x9b, 0x96, 0xe2, 0xb1, - 0xb2, 0xc3, 0x8f, 0xe1, 0x9b, 0x91, 0xc5, 0x85, 0xe1, 0x9a, 0xa2, 0xc4, 0xba, 0xc3, - 0xa8, 0xc3, 0xaa, 0xc3, 0xa9, 0xc8, 0x93, 0xc8, 0x9b, 0xc8, 0x80, 0xc4, 0xa5, 0xc5, - 0xa9, 0xc4, 0x90, 0x6f, 0xc2, 0xaf, 0xc3, 0x95, 0xc6, 0xa6, 0xc8, 0x86, 0xe1, 0x9a, - 0xbd, 0xc8, 0x87, 0xc7, 0x97, 0xc6, 0xaa, 0x79, 0x52, 0xc7, 0x89, 0xc2, 0xa1, 0xc4, - 0xa7, 0xc9, 0x8d, 0x53, 0xc8, 0x89, 0xc7, 0xa4, 0xe1, 0x9b, 0x84, 0xc5, 0xac, 0x79, - 0xc8, 0xbc, 0xc4, 0xb0, 0xc6, 0xa9, 0xe1, 0x9a, 0xa4, 0xe2, 0xb1, 0xb6, 0xc7, 0x86, - 0xc4, 0x9b, 0x72, 0xc7, 0x88, 0xc2, 0xbc, 0xe1, 0x9a, 0xa4, 0xcd, 0xb0, 0xc6, 0xb7, - 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xb8, 0xc5, 0x89, 0xc9, 0x84, 0x35, 0xc3, 0xa3, 0xe1, - 0x9b, 0x90, 0xc7, 0x9c, 0x31, 0xc5, 0x9a, 0xc5, 0xa9, 0xc8, 0x88, 0xce, 0x8c, 0xc4, - 0x88, 0xc4, 0x95, 0xc8, 0xaa, 0x69, 0x46, 0xc8, 0x8d, 0xc5, 0xb9, 0xcd, 0xb0, 0xe1, - 0x9a, 0xb7, 0xc8, 0x83, 0xc4, 0x99, 0xe1, 0x9b, 0x81, 0xc4, 0x90, 0xc2, 0xb3, 0xc3, - 0x9b, 0x37, 0xc7, 0x95, 0xc3, 0x86, 0xe1, 0x9a, 0xbc, 0xc3, 0xba, 0xe2, 0xb1, 0xa5, - 0xc8, 0xac, 0x51, 0xc6, 0xa4, 0xc4, 0xb4, 0x21, 0xc5, 0x94, 0xc5, 0x92, 0xc4, 0xa3, - 0xc6, 0x8c, 0xc8, 0x84, 0xc8, 0xa9, 0xc3, 0x81, 0xc5, 0xb2, 0x53, 0xc7, 0x8a, 0xe1, - 0x9a, 0xba, 0xc4, 0xb7, 0xc8, 0x9e, 0xc3, 0xb6, 0xc7, 0xb1, 0xe2, 0xb1, 0xad, 0xc7, - 0x80, 0xc7, 0xb7, 0x51, 0xce, 0x85, 0xc4, 0xab, 0xc7, 0xaa, 0xc3, 0xad, 0xc5, 0x97, - 0xc8, 0xbe, 0x2e, 0x36, 0x71, 0xe1, 0x9b, 0x8a, 0xc5, 0xb1, 0xc4, 0x9b, 0xe1, 0x9b, - 0x8a, 0xc5, 0xb7, 0xc5, 0xb9, 0xc3, 0xbe, 0xc7, 0x80, 0xc3, 0xad, 0xc8, 0x80, 0xe1, - 0x9b, 0x9d, 0xc5, 0xb2, 0xc6, 0xaa, 0xc8, 0xa6, 0xc5, 0x93, 0xc6, 0xb2, 0xe1, 0x9a, - 0xb0, 0xc5, 0x86, 0xc5, 0xa2, 0xe1, 0x9a, 0xaf, 0x77, 0xc4, 0xb1, 0xe1, 0x9a, 0xa0, - 0xc4, 0x91, 0xc8, 0xb9, 0x21, 0xc3, 0x9a, 0xc6, 0x88, 0xc3, 0x80, 0xc4, 0x80, 0xc4, - 0x83, 0xc7, 0x81, 0x24, 0xc3, 0xa5, 0xc6, 0xbf, 0xc7, 0xb1, 0xe1, 0x9b, 0x98, 0xc8, - 0xaf, 0xc5, 0x9a, 0xc7, 0xa1, 0xc4, 0x89, 0x4f, 0xc2, 0xaf, 0xc9, 0x8c, 0x2f, 0xc4, - 0x94, 0x74, 0xc5, 0xb8, 0x26, 0xe1, 0x9b, 0x85, 0xc6, 0x97, 0xc2, 0xa3, 0xc5, 0xb4, - 0xc7, 0xbe, 0xc6, 0xa3, 0xc4, 0x9b, 0xe1, 0x9b, 0xa2, 0xc8, 0xb9, 0x7d, 0xc8, 0xa2, - 0xc7, 0x8a, 0xe2, 0xb1, 0xaa, 0xc3, 0x92, 0x5b, 0xc3, 0xaa, 0xc8, 0xa4, 0xc7, 0xad, - 0xc4, 0x91, 0xc8, 0xad, 0xc8, 0x8a, 0xc4, 0x89, 0x3e, 0xc5, 0xba, 0x58, 0xc4, 0xb7, - 0xc5, 0x82, 0xe1, 0x9b, 0x82, 0x51, 0xc5, 0xa5, 0xc3, 0x96, 0xc2, 0xb1, 0xc2, 0xa4, - 0xc8, 0x8f, 0xc3, 0xac, 0xc6, 0x91, 0xe1, 0x9b, 0xa3, 0xc8, 0xba, 0xc4, 0x82, 0x21, - 0xc6, 0xb3, 0xc7, 0xb1, 0xc3, 0x92, 0x2f, 0xc4, 0x9a, 0xc7, 0x86, 0xc4, 0x82, 0x7c, - 0x2e, 0xc8, 0xb6, 0xe1, 0x9b, 0x8a, 0x2f, 0x34, 0xc4, 0xaf, 0xc7, 0xb8, 0xc9, 0x8b, - 0xc6, 0xb6, 0xe1, 0x9b, 0x91, 0xc7, 0xb2, 0xc5, 0x87, 0xce, 0x85, 0xc4, 0x8b, 0xc7, - 0x88, 0xc5, 0xb7, 0xc8, 0x9c, 0xc6, 0xbb, 0xc4, 0x9e, 0xc4, 0xb2, 0xc4, 0xa8, 0xe1, - 0x9b, 0x83, 0xc7, 0x91, 0xc8, 0x82, 0xc8, 0xb6, 0xc5, 0x8e, 0xe1, 0x9b, 0xaf, 0xc7, - 0x89, 0xc4, 0x98, 0xc7, 0x90, 0xc2, 0xb8, 0xc8, 0xa2, 0xc8, 0xbf, 0xc5, 0xb8, 0x6e, - 0xc2, 0xbc, 0xc3, 0xb0, 0xc3, 0xa0, 0xc6, 0xb6, - ], - asset_base: [ - 0xee, 0xb5, 0xc9, 0x51, 0xcd, 0x1c, 0x9b, 0x20, 0x4f, 0x65, 0xe6, 0xf2, 0xb9, 0xeb, - 0xa1, 0xd2, 0x16, 0x1e, 0x21, 0x2b, 0x6f, 0x8e, 0x1c, 0x37, 0x96, 0x22, 0xbb, 0x7c, - 0x44, 0xb8, 0x8e, 0xa7, - ], - }, - TestVector { - key: [ - 0x70, 0x0d, 0xc0, 0x7a, 0xea, 0x5b, 0x17, 0xb5, 0xc0, 0x2b, 0xe3, 0x8c, 0x71, 0x1c, - 0x5d, 0x6d, 0x38, 0x13, 0xa4, 0x5e, 0xc2, 0x30, 0xda, 0x29, 0xfb, 0x37, 0x3c, 0x56, - 0x8c, 0x10, 0x44, 0x20, - ], - description: [ - 0xc3, 0x82, 0xc9, 0x85, 0xc3, 0xa9, 0xc7, 0xac, 0xc3, 0x93, 0xe1, 0x9b, 0xa7, 0xe1, - 0x9b, 0x81, 0xc8, 0xb5, 0x26, 0xe2, 0xb1, 0xbf, 0xc3, 0x96, 0xc4, 0xa2, 0xc5, 0x8c, - 0x4c, 0xc7, 0xbe, 0xce, 0x89, 0xc8, 0xa0, 0xc5, 0xb7, 0xc5, 0x92, 0xc7, 0xa6, 0xc4, - 0x8f, 0xc8, 0x84, 0x2f, 0xe2, 0xb1, 0xad, 0xc3, 0xab, 0xc6, 0xbc, 0xe1, 0x9a, 0xa8, - 0xc2, 0xb9, 0x72, 0x6b, 0xc3, 0xa9, 0xc3, 0xa3, 0xc9, 0x87, 0xc4, 0xb8, 0xc6, 0xbc, - 0xc8, 0xb8, 0xc6, 0x80, 0xe1, 0x9a, 0xbc, 0xc6, 0xb7, 0xc3, 0x9c, 0x3e, 0xc8, 0x8f, - 0xe1, 0x9b, 0x92, 0xc7, 0x88, 0x33, 0xc6, 0xab, 0xc8, 0x80, 0xc8, 0x9e, 0xe2, 0xb1, - 0xa2, 0x29, 0xc3, 0x9d, 0xc6, 0x82, 0xc3, 0xad, 0xc8, 0xa1, 0xe1, 0x9b, 0x99, 0xc4, - 0xad, 0xc9, 0x8c, 0xc7, 0xa8, 0xc8, 0x89, 0xc4, 0x90, 0xe1, 0x9b, 0xa0, 0xc4, 0xae, - 0xc6, 0xb5, 0xc7, 0x92, 0xc6, 0xbc, 0xc8, 0xa1, 0xc3, 0xac, 0xc3, 0x83, 0xe1, 0x9b, - 0x83, 0xc3, 0xb9, 0xc3, 0x9d, 0xc5, 0xa8, 0xe2, 0xb1, 0xbb, 0xc8, 0x9f, 0xc4, 0xb0, - 0xe2, 0xb1, 0xa3, 0xc7, 0xa8, 0xc4, 0x82, 0xc7, 0x87, 0xe1, 0x9b, 0x9e, 0xc8, 0x81, - 0xc3, 0xb7, 0xc5, 0x95, 0x34, 0xc6, 0xb8, 0xc5, 0xbd, 0xc4, 0x82, 0xc6, 0x92, 0xc4, - 0x9f, 0xc5, 0x9d, 0xc8, 0x9a, 0xc4, 0x89, 0xc3, 0x81, 0xc5, 0x8d, 0xe1, 0x9b, 0x85, - 0xc8, 0x84, 0xcd, 0xbe, 0xc6, 0xb5, 0xc7, 0xb5, 0xc4, 0xbe, 0x4d, 0xc6, 0x8c, 0xc6, - 0x83, 0xc6, 0x99, 0xc7, 0xa3, 0xc4, 0xae, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x86, 0xe1, - 0x9a, 0xa1, 0xc6, 0x84, 0xc3, 0xb0, 0xc9, 0x8b, 0xcd, 0xb0, 0xc7, 0x8c, 0xc6, 0xb4, - 0xc5, 0x82, 0xe2, 0xb1, 0xba, 0xc2, 0xbb, 0xc4, 0xbd, 0xc2, 0xaf, 0xc6, 0xba, 0x7b, - 0xc4, 0x89, 0x25, 0xe1, 0x9b, 0xae, 0xc7, 0x9d, 0xe1, 0x9b, 0x8b, 0xe2, 0xb1, 0xb8, - 0xe2, 0xb1, 0xa5, 0xc3, 0xb4, 0xc8, 0xb2, 0xc5, 0x9f, 0xc8, 0x9c, 0xc3, 0xa7, 0x38, - 0xc7, 0x8e, 0xc7, 0x92, 0xc6, 0xa8, 0xc6, 0x88, 0xe2, 0xb1, 0xa2, 0xc5, 0xb1, 0x39, - 0x6b, 0x4c, 0xe1, 0x9b, 0x86, 0xe1, 0x9a, 0xa8, 0xc2, 0xa6, 0xc5, 0xbf, 0xc5, 0xb5, - 0xc4, 0xaa, 0xe2, 0xb1, 0xa2, 0x3b, 0xc8, 0x98, 0xc9, 0x8f, 0xc4, 0x83, 0xc8, 0x91, - 0xc7, 0x8e, 0xe2, 0xb1, 0xab, 0xc8, 0x94, 0xc6, 0xb3, 0xc3, 0x93, 0xc3, 0x92, 0x3d, - 0xc4, 0x86, 0xc6, 0x88, 0xc4, 0xa3, 0xc5, 0x98, 0xc8, 0xb9, 0xc8, 0xb5, 0x26, 0xc4, - 0xb9, 0xc3, 0x90, 0xc5, 0xa7, 0xc6, 0xa6, 0xe2, 0xb1, 0xba, 0xc2, 0xb8, 0xc5, 0x93, - 0xce, 0x89, 0xc3, 0xa0, 0xc3, 0x8e, 0xe1, 0x9b, 0x81, 0xc2, 0xbb, 0xc7, 0xba, 0xc4, - 0x83, 0xc9, 0x83, 0xc5, 0xa8, 0xc4, 0x84, 0xc3, 0xb5, 0xc3, 0xad, 0x5d, 0xc4, 0x9b, - 0xc7, 0xbb, 0xe2, 0xb1, 0xb4, 0xc4, 0xb5, 0xc4, 0x8c, 0xc3, 0x8a, 0xc6, 0xb2, 0xe2, - 0xb1, 0xa5, 0xc6, 0xb1, 0xc4, 0xa7, 0xc3, 0xb3, 0xe1, 0x9b, 0xa6, 0xc7, 0x9d, 0xc4, - 0xb3, 0xc3, 0xbd, 0x3b, 0xe1, 0x9b, 0xa5, 0x3e, 0xc3, 0xbe, 0xc7, 0x87, 0xc3, 0xa4, - 0xc6, 0xbb, 0xe1, 0x9b, 0xad, 0xe2, 0xb1, 0xa4, 0xce, 0x89, 0xc8, 0xa2, 0xc8, 0x84, - 0x7a, 0xc8, 0x84, 0xc4, 0xb5, 0xc4, 0xbb, 0xc5, 0xa2, 0xc7, 0xaf, 0x49, 0xe1, 0x9b, - 0xb0, 0xc8, 0xab, 0xc6, 0xa7, 0xc7, 0xa4, 0xe2, 0xb1, 0xbd, 0xc4, 0x8f, 0xc6, 0x96, - 0xe1, 0x9b, 0x86, 0xc6, 0x9f, 0xc3, 0x83, 0xc4, 0x8b, 0x2b, 0xe1, 0x9a, 0xa9, 0x38, - 0xe2, 0xb1, 0xbc, 0xc3, 0x8c, 0xc8, 0x94, 0xcd, 0xb0, 0xc3, 0xb5, 0xc7, 0x82, 0x36, - 0x23, 0x41, 0xe2, 0xb1, 0xa8, 0x67, 0x5a, 0x5a, - ], - asset_base: [ - 0x65, 0x3e, 0x99, 0x25, 0x68, 0x30, 0x69, 0xc9, 0x88, 0x32, 0xaf, 0x7d, 0x3a, 0xa9, - 0xd3, 0x14, 0x41, 0xcc, 0x0f, 0x76, 0x34, 0x07, 0x91, 0x49, 0xf3, 0xef, 0xcb, 0x64, - 0xc7, 0x36, 0x97, 0x3d, - ], - }, - TestVector { - key: [ - 0xf3, 0x2c, 0x7a, 0x80, 0xb6, 0x83, 0x45, 0xb2, 0x38, 0xc7, 0x73, 0x34, 0x67, 0xba, - 0x6c, 0xd9, 0x7c, 0xcd, 0xf4, 0xfd, 0x21, 0x29, 0x48, 0x13, 0x1b, 0xfb, 0xc4, 0x06, - 0x19, 0x68, 0x73, 0x26, - ], - description: [ - 0xc8, 0x9b, 0x56, 0xe1, 0x9b, 0x9d, 0xc6, 0xaf, 0xe2, 0xb1, 0xbd, 0xc3, 0x80, 0xc5, - 0x8f, 0xe1, 0x9b, 0xaa, 0xc7, 0xbd, 0x45, 0x30, 0xe1, 0x9a, 0xbd, 0x62, 0xc5, 0x8a, - 0xc5, 0xba, 0xc7, 0x83, 0xc4, 0xa7, 0xe1, 0x9a, 0xa5, 0xc6, 0xab, 0xc6, 0x94, 0xe2, - 0xb1, 0xa0, 0xc3, 0x81, 0x6f, 0xc3, 0x84, 0x31, 0xc5, 0xbe, 0xc3, 0x87, 0xc7, 0xa8, - 0xe1, 0x9a, 0xa0, 0xc2, 0xa7, 0xc5, 0xb1, 0xc8, 0x85, 0xc8, 0xa1, 0x48, 0x2c, 0x41, - 0x53, 0xe2, 0xb1, 0xb4, 0xc7, 0xad, 0xc7, 0xb9, 0xc8, 0x9e, 0xc6, 0xa5, 0x4d, 0xe2, - 0xb1, 0xa4, 0xc3, 0x96, 0xc8, 0xbf, 0xc4, 0x95, 0xc6, 0x94, 0xc4, 0xa5, 0x64, 0xc4, - 0xbe, 0x69, 0xc8, 0xb9, 0x7d, 0xe1, 0x9b, 0x86, 0xe1, 0x9b, 0x9b, 0xce, 0x86, 0xe1, - 0x9a, 0xa9, 0xc4, 0x9f, 0x30, 0xc8, 0x8b, 0xe1, 0x9b, 0xa7, 0xc6, 0xbf, 0xc7, 0xbb, - 0xc7, 0x9a, 0xc8, 0x94, 0xc8, 0x9d, 0xc8, 0x8c, 0xc3, 0xb2, 0xc7, 0x95, 0x34, 0x71, - 0x38, 0xc6, 0xb5, 0xc4, 0xa6, 0xc8, 0x96, 0xce, 0x89, 0xc4, 0x93, 0x26, 0xc8, 0xa4, - 0xc6, 0xa7, 0xe1, 0x9b, 0xa7, 0x3b, 0xc4, 0x80, 0xc5, 0xb8, 0xc7, 0x86, 0xc8, 0xa0, - 0xc4, 0xbb, 0xc4, 0xa1, 0xc8, 0x88, 0x70, 0x5d, 0xe2, 0xb1, 0xa5, 0xc9, 0x89, 0xc7, - 0xbc, 0xc6, 0xb3, 0xc9, 0x8a, 0xc3, 0xbe, 0xe2, 0xb1, 0xa9, 0xc2, 0xbd, 0xc5, 0x88, - 0xc5, 0x88, 0xc4, 0xbc, 0xc6, 0x88, 0x5c, 0xc8, 0x86, 0xc3, 0xa8, 0x23, 0x58, 0xe1, - 0x9a, 0xa2, 0xc4, 0xb2, 0xc7, 0xbc, 0x5e, 0xe2, 0xb1, 0xb2, 0x45, 0xc7, 0xb7, 0xc9, - 0x81, 0xc2, 0xba, 0xe1, 0x9b, 0x91, 0xc3, 0x87, 0xc9, 0x8c, 0xce, 0x84, 0xe1, 0x9a, - 0xa8, 0xc8, 0x8c, 0xc7, 0x8b, 0xce, 0x86, 0xe2, 0xb1, 0xaf, 0x32, 0xc8, 0x88, 0xc4, - 0x9c, 0xe1, 0x9a, 0xac, 0xe1, 0x9b, 0x9e, 0xc6, 0xb1, 0xc7, 0x90, 0xe2, 0xb1, 0xa6, - 0xc8, 0x91, 0xc5, 0x9a, 0xc6, 0x8e, 0xc6, 0x84, 0xe1, 0x9a, 0xbd, 0xc4, 0xa6, 0xc5, - 0x84, 0xc3, 0x91, 0xc6, 0xbf, 0xc4, 0xb9, 0xce, 0x85, 0xc2, 0xa1, 0xc7, 0x93, 0xc9, - 0x8e, 0xc5, 0xb4, 0xc8, 0x91, 0xc5, 0xa1, 0xe1, 0x9b, 0x95, 0xc8, 0xa9, 0xe1, 0x9b, - 0x92, 0x5f, 0xc6, 0xba, 0x56, 0xc4, 0x95, 0x32, 0xe2, 0xb1, 0xa5, 0x53, 0xc3, 0xba, - 0x23, 0xc7, 0x99, 0xc7, 0xa8, 0xc3, 0x81, 0xc6, 0xa1, 0x34, 0xc5, 0xb1, 0xc3, 0x85, - 0xe1, 0x9b, 0xac, 0xc7, 0xad, 0xc4, 0x90, 0xc5, 0x9f, 0xc5, 0xaf, 0xc8, 0x9e, 0xc7, - 0xb5, 0xc5, 0x82, 0xc9, 0x81, 0xc5, 0x8d, 0xc5, 0x92, 0xc6, 0x9d, 0xc5, 0xba, 0xe1, - 0x9a, 0xa7, 0xc4, 0x81, 0xe2, 0xb1, 0xa1, 0xc6, 0xa5, 0xe2, 0xb1, 0xb9, 0xc4, 0x9f, - 0xce, 0x88, 0xc6, 0x97, 0xc6, 0xaf, 0xe1, 0x9b, 0xac, 0xc5, 0xa1, 0xe2, 0xb1, 0xb3, - 0xc9, 0x83, 0xc5, 0x86, 0xc6, 0xaa, 0xe2, 0xb1, 0xb0, 0xc7, 0x8b, 0xc5, 0xae, 0xc2, - 0xb5, 0x42, 0xc6, 0xab, 0x58, 0xc8, 0x93, 0xc6, 0x82, 0xe2, 0xb1, 0xb6, 0xc7, 0x92, - 0xe1, 0x9b, 0x95, 0xc4, 0x81, 0xc3, 0x9f, 0xc2, 0xb7, 0xc5, 0x8f, 0xc8, 0xb7, 0xc3, - 0xac, 0xc4, 0xbf, 0x48, 0xc5, 0xba, 0xe1, 0x9a, 0xb9, 0xc4, 0x8c, 0xe1, 0x9b, 0x87, - 0xc6, 0x93, 0xc4, 0x8a, 0xc7, 0x99, 0xc6, 0x98, 0xc6, 0xb7, 0xc5, 0xb9, 0xc4, 0x8b, - 0xc3, 0xbb, 0xc8, 0x8b, 0xc3, 0xbb, 0xc5, 0x93, 0xe1, 0x9b, 0xad, 0xe1, 0x9a, 0xb1, - 0xc3, 0x82, 0xc6, 0x99, 0xc5, 0x93, 0xc6, 0x8e, 0xcd, 0xb4, 0xe2, 0xb1, 0xa8, 0xc6, - 0x97, 0xc6, 0x99, 0xc5, 0x80, 0xc4, 0x9c, 0x78, 0xcd, 0xb2, 0xc4, 0xb3, 0xc5, 0x80, - 0xe1, 0x9b, 0x99, 0xc7, 0xa8, 0xc5, 0x8e, 0x5a, - ], - asset_base: [ - 0x76, 0xb6, 0xcc, 0x39, 0x90, 0xd8, 0xf1, 0x14, 0x96, 0x01, 0xe6, 0x8f, 0x2e, 0xca, - 0xcd, 0x97, 0x0f, 0xa0, 0xb7, 0xc0, 0xbe, 0xab, 0x7c, 0x88, 0x28, 0x21, 0x4a, 0x37, - 0xce, 0x87, 0x10, 0xa3, - ], - }, - TestVector { - key: [ - 0x98, 0xee, 0xc6, 0xfb, 0xdc, 0xa2, 0x77, 0x2a, 0x2a, 0x6b, 0xf9, 0x2f, 0x17, 0x18, - 0xdf, 0x59, 0xba, 0xb2, 0x5f, 0xd1, 0x05, 0x4c, 0x57, 0xad, 0xae, 0x0d, 0x72, 0x20, - 0xbf, 0xcd, 0x06, 0x38, - ], - description: [ - 0xc5, 0x87, 0xe2, 0xb1, 0xbb, 0xc8, 0xa4, 0xc5, 0x85, 0xc4, 0x84, 0xe1, 0x9b, 0x99, - 0xc9, 0x85, 0xe1, 0x9a, 0xbe, 0xc4, 0x85, 0xc7, 0x8b, 0xe1, 0x9b, 0xa2, 0xc6, 0xa4, - 0x5a, 0xc6, 0xad, 0xc7, 0x80, 0x23, 0xc5, 0x9f, 0xc4, 0xb2, 0xe1, 0x9b, 0x94, 0xc3, - 0xb1, 0xc6, 0xae, 0xe1, 0x9a, 0xaa, 0x71, 0xc6, 0xa1, 0xc8, 0x9e, 0xc8, 0x97, 0xc6, - 0xac, 0xc3, 0x83, 0xc8, 0x9a, 0xc6, 0xa7, 0x41, 0xe1, 0x9a, 0xbf, 0xc2, 0xaa, 0xc8, - 0x9b, 0xc4, 0xa4, 0xc3, 0x97, 0xc8, 0x9d, 0x55, 0xc4, 0x92, 0xc5, 0xa2, 0xc5, 0x8b, - 0xc8, 0xaa, 0xc6, 0xa3, 0xc3, 0x81, 0xc6, 0x81, 0x7a, 0xcd, 0xb0, 0x6e, 0xc3, 0xb4, - 0xc4, 0x90, 0xc4, 0xaa, 0xe2, 0xb1, 0xa6, 0xc4, 0xa0, 0xc2, 0xbf, 0xc7, 0xa7, 0xc3, - 0xad, 0x5b, 0xc7, 0xa3, 0xc5, 0xb3, 0xc7, 0xbe, 0xc6, 0x9a, 0xc7, 0x80, 0xc2, 0xab, - 0xc5, 0x99, 0xe1, 0x9b, 0x91, 0xc6, 0x90, 0x68, 0xc4, 0xb9, 0xc6, 0x87, 0x66, 0xc3, - 0xb6, 0xc5, 0xb8, 0xc6, 0x9a, 0x7b, 0xc7, 0x81, 0xc5, 0x8b, 0xc5, 0x87, 0xc3, 0x9b, - 0xc6, 0x94, 0xc4, 0x8d, 0xc2, 0xb9, 0xe2, 0xb1, 0xbd, 0xc6, 0x9e, 0xc7, 0xbc, 0x68, - 0xc3, 0xaa, 0x5b, 0xc5, 0x85, 0xc9, 0x87, 0xe1, 0x9b, 0x85, 0x5d, 0xc9, 0x8c, 0xe1, - 0x9b, 0xa6, 0x5d, 0xcd, 0xb7, 0xc7, 0x9f, 0x30, 0xc4, 0x9d, 0xc2, 0xb7, 0xe1, 0x9b, - 0xa0, 0xc4, 0xab, 0xc2, 0xaf, 0xc5, 0xb2, 0xe1, 0x9b, 0xa6, 0xc3, 0x81, 0xc5, 0xab, - 0xc8, 0xa0, 0xe1, 0x9b, 0x9c, 0xc5, 0xa5, 0xc4, 0x9e, 0xc3, 0x94, 0xc6, 0xa0, 0x7e, - 0xc6, 0x8c, 0xc5, 0x80, 0xc8, 0x9a, 0xcd, 0xb6, 0xc6, 0xa4, 0xc5, 0x9b, 0xe1, 0x9b, - 0x87, 0xe1, 0x9a, 0xa4, 0x62, 0xe2, 0xb1, 0xa4, 0x35, 0x3f, 0xc2, 0xaa, 0xc7, 0xb0, - 0xc5, 0xb4, 0xc9, 0x82, 0xe1, 0x9a, 0xab, 0xc8, 0xb1, 0xc8, 0xae, 0xc6, 0xbc, 0xc8, - 0x98, 0x33, 0xc5, 0xa4, 0x31, 0xe1, 0x9a, 0xbd, 0xc8, 0xb7, 0xc4, 0xa2, 0x45, 0xc5, - 0x8a, 0xe1, 0x9a, 0xb0, 0xc2, 0xb2, 0xc6, 0x8f, 0xc8, 0x96, 0xc6, 0x93, 0xc6, 0x89, - 0xe2, 0xb1, 0xb4, 0xc7, 0xb9, 0xc3, 0x88, 0xc7, 0x9f, 0xc7, 0x85, 0xe2, 0xb1, 0xa8, - 0xc7, 0xa9, 0xc8, 0x99, 0xc4, 0x8c, 0xc4, 0xaf, 0xc4, 0x99, 0x3b, 0xc5, 0xa8, 0xe1, - 0x9a, 0xaa, 0xc6, 0x9e, 0xc6, 0x86, 0xc2, 0xb5, 0x43, 0xc2, 0xaa, 0xe1, 0x9b, 0x95, - 0xc8, 0xba, 0xc2, 0xac, 0xc7, 0x9e, 0xe2, 0xb1, 0xb5, 0xc8, 0xb3, 0xe1, 0x9b, 0xa4, - 0xc8, 0xa6, 0xc6, 0x8c, 0xc6, 0x99, 0xc6, 0x89, 0xc5, 0x82, 0xc7, 0xa4, 0x7c, 0xce, - 0x89, 0xc6, 0xbf, 0xc8, 0x9d, 0xc3, 0x92, 0xc6, 0xab, 0xe1, 0x9a, 0xab, 0xe1, 0x9b, - 0x84, 0xc6, 0x9e, 0x21, 0x79, 0xcd, 0xb1, 0xc4, 0xb1, 0xce, 0x8c, 0xe1, 0x9b, 0x98, - 0xe1, 0x9b, 0x8d, 0xc6, 0xb0, 0xe1, 0x9a, 0xa5, 0xc7, 0xb9, 0xe1, 0x9b, 0x9d, 0x48, - 0xc4, 0xbe, 0xc8, 0xaf, 0xc8, 0x89, 0xe1, 0x9b, 0xb0, 0xc2, 0xb8, 0xe2, 0xb1, 0xb1, - 0xc3, 0x96, 0xc5, 0xb1, 0x44, 0xc3, 0x9e, 0x6c, 0xe1, 0x9a, 0xbb, 0xc4, 0xaf, 0xc4, - 0x8c, 0xc2, 0xa1, 0xc3, 0xa1, 0xc3, 0x98, 0xc8, 0xac, 0xc3, 0xa3, 0xc8, 0xa2, 0xcd, - 0xbb, 0xc6, 0xb3, 0xe1, 0x9b, 0x9c, 0x51, 0xc5, 0xa3, 0xc5, 0xb3, 0x77, 0xc3, 0x87, - 0xc3, 0xbb, 0x3b, 0xc8, 0x98, 0xc5, 0xb9, 0x2a, 0x4a, 0xc5, 0xb7, 0xc9, 0x8c, 0x6e, - 0xe1, 0x9b, 0xa9, 0xc3, 0x94, 0xc3, 0x9f, 0xc3, 0xaa, 0xe1, 0x9b, 0xb0, 0xc3, 0x85, - 0x59, 0xc8, 0xbb, 0xc4, 0x87, 0xc7, 0xb2, 0xcd, 0xbe, 0xc5, 0xb4, 0x6c, 0xe2, 0xb1, - 0xad, 0x6d, 0xc2, 0xa9, 0xc4, 0x8b, 0xc6, 0xb6, - ], - asset_base: [ - 0xba, 0xb2, 0xba, 0xb5, 0x2d, 0x54, 0x67, 0xd4, 0xa6, 0x36, 0x0c, 0xb2, 0x74, 0xc9, - 0x2a, 0x7b, 0x8e, 0x0b, 0xc5, 0x02, 0x28, 0xa9, 0x68, 0x0f, 0xcd, 0xa0, 0x38, 0x17, - 0x62, 0x3f, 0x48, 0x91, - ], - }, - TestVector { - key: [ - 0x3a, 0x86, 0x32, 0x5c, 0x89, 0x70, 0xca, 0x21, 0xb8, 0x3a, 0xb7, 0x59, 0x76, 0xa8, - 0xd8, 0x54, 0xff, 0xa0, 0xc7, 0x63, 0x1b, 0xd0, 0xf8, 0xa8, 0x8c, 0x0a, 0x09, 0x89, - 0xbd, 0xb7, 0x75, 0x19, - ], - description: [ - 0xc7, 0x93, 0xc6, 0xb5, 0xc4, 0x82, 0xc6, 0x85, 0xe1, 0x9a, 0xac, 0xc7, 0x91, 0xc4, - 0xad, 0xe1, 0x9b, 0x84, 0xe2, 0xb1, 0xbc, 0xc2, 0xbb, 0xc8, 0xa9, 0xc7, 0xaf, 0xc4, - 0xa6, 0x79, 0xc6, 0x8a, 0xc5, 0xac, 0xc6, 0x98, 0xe1, 0x9b, 0x8f, 0xc5, 0x8b, 0xc3, - 0x81, 0xe1, 0x9b, 0x84, 0xe1, 0x9a, 0xa9, 0xe2, 0xb1, 0xa2, 0xe1, 0x9b, 0x92, 0x40, - 0xe2, 0xb1, 0xa0, 0xc4, 0xa6, 0xc8, 0xac, 0xc7, 0xb9, 0xc9, 0x8d, 0xc7, 0xab, 0xc3, - 0x8a, 0xc6, 0xb8, 0x7c, 0xc5, 0xa1, 0xc8, 0xaf, 0xc4, 0x80, 0xc3, 0xb4, 0xc5, 0x82, - 0xc7, 0xb7, 0xc6, 0x8a, 0xc6, 0xb2, 0x2b, 0x6b, 0xc6, 0x9d, 0xe2, 0xb1, 0xb6, 0xc7, - 0x94, 0xcd, 0xb5, 0xc5, 0x96, 0xc7, 0xae, 0xc4, 0xb1, 0xc4, 0xb0, 0xe1, 0x9b, 0x8e, - 0xcd, 0xb2, 0xe1, 0x9b, 0x83, 0xc5, 0xb5, 0xc8, 0x84, 0xc6, 0x88, 0xcd, 0xb7, 0xe2, - 0xb1, 0xa5, 0xc8, 0xa6, 0xc5, 0x8c, 0xc5, 0x8f, 0x60, 0xc8, 0x83, 0xc6, 0x9f, 0xc4, - 0xa2, 0xc5, 0x9f, 0x5b, 0xc8, 0x97, 0xcd, 0xbc, 0xc4, 0xbb, 0xc5, 0x93, 0xc6, 0xa9, - 0xc3, 0x8e, 0x31, 0xe2, 0xb1, 0xae, 0x49, 0xc7, 0x93, 0xc2, 0xba, 0xc5, 0x9c, 0xc2, - 0xb4, 0xe1, 0x9a, 0xa6, 0xc9, 0x8b, 0x75, 0x36, 0xe1, 0x9b, 0x89, 0x6c, 0xc3, 0x95, - 0xc4, 0xba, 0x7e, 0x21, 0xc8, 0xac, 0xc4, 0xa0, 0x4f, 0xc5, 0xbc, 0x5b, 0xce, 0x88, - 0x37, 0x38, 0xc6, 0x8b, 0xc2, 0xb9, 0x58, 0xc3, 0x86, 0xc4, 0x96, 0x23, 0xc6, 0xbb, - 0xc8, 0xa3, 0x5a, 0xc6, 0xbc, 0xe1, 0x9b, 0x89, 0xc3, 0x82, 0xc3, 0x9d, 0x69, 0xe1, - 0x9a, 0xbe, 0xe1, 0x9b, 0x8d, 0xc3, 0xb6, 0x73, 0xc4, 0xb9, 0xe1, 0x9b, 0xaa, 0x6a, - 0xc2, 0xa8, 0xc6, 0xbb, 0xce, 0x85, 0xc7, 0x94, 0xc5, 0xaa, 0xc2, 0xb5, 0x5e, 0xc2, - 0xb5, 0xc3, 0xa1, 0xc6, 0x93, 0xc3, 0xb6, 0xc5, 0x95, 0xc6, 0x91, 0xc7, 0xb1, 0xc8, - 0xb3, 0x66, 0x21, 0xc4, 0x8a, 0xc7, 0xb9, 0xc5, 0x8d, 0x33, 0xc9, 0x8c, 0x5e, 0xc4, - 0xb6, 0xc7, 0x88, 0xc3, 0xae, 0xc5, 0x8e, 0xc7, 0xaf, 0x4e, 0xc4, 0xa6, 0xe1, 0x9b, - 0xad, 0xc7, 0x8c, 0xe1, 0x9a, 0xbf, 0xc7, 0x89, 0xc9, 0x88, 0xc6, 0xab, 0xe2, 0xb1, - 0xbf, 0xc7, 0x85, 0xc6, 0xa1, 0xc3, 0x86, 0xe1, 0x9b, 0x9c, 0x3b, 0xc2, 0xa6, 0x7c, - 0xc3, 0x94, 0x5c, 0xc8, 0x82, 0xc3, 0xad, 0xc7, 0x98, 0xc5, 0xab, 0xc7, 0xa1, 0xe1, - 0x9a, 0xa3, 0xc8, 0xa3, 0xc6, 0x96, 0xc5, 0x82, 0xe1, 0x9b, 0x84, 0xc8, 0xb0, 0xc2, - 0xaa, 0xc4, 0x94, 0x68, 0xc6, 0x8f, 0xe2, 0xb1, 0xb8, 0xc6, 0xae, 0x54, 0xe1, 0x9b, - 0x88, 0xc7, 0x82, 0xc3, 0x81, 0xc8, 0xaf, 0xc7, 0xa0, 0x3d, 0xc4, 0x98, 0xc4, 0x97, - 0xc7, 0xba, 0xe1, 0x9b, 0xa8, 0xc6, 0xba, 0xc3, 0x93, 0xc2, 0xa7, 0xc7, 0xa1, 0xc5, - 0x8d, 0xc7, 0x87, 0xc3, 0xa1, 0xc5, 0xa4, 0xc6, 0x9b, 0x21, 0xc5, 0xa8, 0xc8, 0xb2, - 0xc4, 0xb9, 0xc6, 0x81, 0xc7, 0xb6, 0xc8, 0xaa, 0xc3, 0x89, 0xe1, 0x9b, 0xac, 0x45, - 0xc3, 0xa0, 0xc4, 0xae, 0xe1, 0x9b, 0xa5, 0xc8, 0xad, 0xe1, 0x9a, 0xb6, 0x55, 0xe1, - 0x9b, 0x9d, 0xc4, 0x97, 0xc8, 0x89, 0xc8, 0xa8, 0xc5, 0xbe, 0xc7, 0x90, 0xc2, 0xab, - 0xc8, 0xbd, 0xc3, 0x96, 0xc7, 0x99, 0xc8, 0xa8, 0xc2, 0xa1, 0xe1, 0x9b, 0x80, 0xc7, - 0x9a, 0xc7, 0xba, 0xc5, 0xac, 0x26, 0xc5, 0x96, 0xe1, 0x9a, 0xa4, 0xc8, 0x9d, 0xc6, - 0xa6, 0xe1, 0x9a, 0xb9, 0xc4, 0x86, 0xe1, 0x9a, 0xbf, 0xc8, 0xab, 0xce, 0x87, 0xe1, - 0x9b, 0x94, 0xc4, 0x81, 0xc3, 0xaf, 0xc5, 0xb6, 0xc8, 0x8c, 0xe1, 0x9a, 0xbd, 0xc3, - 0xbc, 0xc3, 0x9b, 0xc4, 0xb5, 0x7b, 0xc8, 0xaf, - ], - asset_base: [ - 0x86, 0x7f, 0xd2, 0x6b, 0xe6, 0xf1, 0x84, 0x89, 0x32, 0x91, 0xf8, 0x22, 0x44, 0xee, - 0x64, 0xa0, 0x63, 0xac, 0x28, 0xd1, 0xb2, 0x32, 0x0e, 0x4b, 0x40, 0xca, 0x6a, 0xf2, - 0x0a, 0xa8, 0x11, 0xbe, - ], - }, - TestVector { - key: [ - 0x4f, 0x50, 0xd9, 0x58, 0xf6, 0xb6, 0x79, 0x91, 0x33, 0x48, 0x49, 0xd1, 0x85, 0xf1, - 0xa3, 0x92, 0x0e, 0xfb, 0x46, 0x35, 0x1c, 0x70, 0x7d, 0xc3, 0x7d, 0x3e, 0xa9, 0xa1, - 0x79, 0xc0, 0x76, 0x27, - ], - description: [ - 0xc7, 0x95, 0xc7, 0xa0, 0xe2, 0xb1, 0xb9, 0xc4, 0xb2, 0x36, 0x48, 0x2b, 0xc5, 0x93, - 0xc7, 0xb1, 0xc3, 0xbc, 0xc6, 0x9c, 0xc8, 0x98, 0xc5, 0xba, 0xe2, 0xb1, 0xa4, 0xc5, - 0x89, 0xc5, 0x9d, 0x2a, 0xc7, 0xa9, 0xe1, 0x9a, 0xb1, 0x7e, 0xc6, 0x98, 0xc7, 0xa2, - 0xc4, 0x85, 0xc8, 0xa3, 0xc8, 0xbb, 0xc6, 0x81, 0xc6, 0x9c, 0xc3, 0xb7, 0xc6, 0x98, - 0xc6, 0x8e, 0xce, 0x86, 0xc8, 0xa0, 0xce, 0x85, 0xe2, 0xb1, 0xb4, 0xc4, 0xaa, 0xc6, - 0xbb, 0xc5, 0xb1, 0xc8, 0x9f, 0x69, 0x21, 0xe1, 0x9a, 0xa8, 0xc4, 0xa3, 0x6f, 0xc3, - 0x93, 0xe1, 0x9b, 0x99, 0xc4, 0xa2, 0xcd, 0xb5, 0xe1, 0x9a, 0xa7, 0xc5, 0x82, 0x32, - 0xc5, 0x80, 0xc2, 0xb0, 0xc7, 0x82, 0x41, 0xc7, 0x90, 0xc8, 0xb8, 0xc6, 0xbe, 0xc5, - 0xa0, 0xc6, 0x8c, 0xe1, 0x9a, 0xb8, 0xc3, 0xb6, 0xc4, 0xb2, 0xc4, 0xa4, 0xc9, 0x84, - 0xc5, 0x8d, 0xc4, 0xb1, 0x54, 0xc7, 0x8f, 0xc8, 0x8b, 0x54, 0xe1, 0x9b, 0x9e, 0xc9, - 0x84, 0xe1, 0x9b, 0x82, 0xc8, 0xb5, 0x73, 0xc6, 0xa4, 0xc4, 0xa8, 0xc4, 0xba, 0xc7, - 0xa7, 0x26, 0x3d, 0xe2, 0xb1, 0xae, 0xc4, 0xbc, 0xc8, 0x91, 0xe1, 0x9a, 0xbe, 0xc6, - 0xb7, 0xc5, 0xb3, 0xc8, 0xad, 0xc6, 0xb4, 0xe1, 0x9a, 0xab, 0x44, 0x77, 0xc5, 0x93, - 0xc5, 0xab, 0xc3, 0xbb, 0xe1, 0x9a, 0xbe, 0xc4, 0x81, 0xc2, 0xbe, 0xc7, 0xbd, 0xcd, - 0xbc, 0x70, 0x45, 0xc5, 0x9a, 0xc9, 0x8d, 0x32, 0x76, 0xe1, 0x9b, 0x97, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0x8a, 0xc3, 0x81, 0xc8, 0xad, 0x4c, 0xc3, 0x89, 0xc6, 0xbd, 0xc4, - 0x93, 0xc7, 0x9c, 0x62, 0x4c, 0xe2, 0xb1, 0xa1, 0xcd, 0xbc, 0xc8, 0xb7, 0xe1, 0x9a, - 0xaf, 0xe1, 0x9a, 0xb9, 0xc3, 0xb2, 0xc5, 0xaa, 0xe1, 0x9b, 0xad, 0xc5, 0x8d, 0xce, - 0x8a, 0x6a, 0xc4, 0xbf, 0xc7, 0x8b, 0xc7, 0xa2, 0x7e, 0x6e, 0xe1, 0x9a, 0xb1, 0x47, - 0x2b, 0xc9, 0x82, 0xc7, 0x8b, 0xcd, 0xba, 0xc6, 0xaf, 0xc4, 0x91, 0xc6, 0x86, 0x52, - 0xe1, 0x9b, 0x9b, 0xc9, 0x8e, 0xe2, 0xb1, 0xbd, 0xc2, 0xbd, 0xc4, 0xb2, 0xc7, 0xb5, - 0xc5, 0xb0, 0xc8, 0xb6, 0xe2, 0xb1, 0xa6, 0xc6, 0x92, 0xc4, 0xbf, 0x4a, 0xc4, 0xa9, - 0xc6, 0xb2, 0xe1, 0x9b, 0x96, 0xc3, 0xa4, 0x70, 0x3d, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, - 0x93, 0xc6, 0xa3, 0x4d, 0xc7, 0xa6, 0xc3, 0x8c, 0xc6, 0x8e, 0xc7, 0xbd, 0xc3, 0x90, - 0x54, 0xc5, 0x9b, 0xe1, 0x9b, 0x94, 0x37, 0xc3, 0x89, 0x79, 0x49, 0xe1, 0x9b, 0x86, - 0xe1, 0x9b, 0xa2, 0xc6, 0x8b, 0xc8, 0xb6, 0xc3, 0x8b, 0xc7, 0x83, 0xc8, 0xa2, 0xc8, - 0x92, 0xc4, 0x9e, 0xc8, 0xa4, 0xc5, 0x80, 0xc7, 0xa6, 0xc6, 0x99, 0x24, 0xe1, 0x9b, - 0xa2, 0xc6, 0x8c, 0xe1, 0x9a, 0xac, 0x39, 0x21, 0xc2, 0xa9, 0xc7, 0x89, 0xe1, 0x9a, - 0xbe, 0xce, 0x8a, 0xc3, 0x86, 0xe1, 0x9b, 0xa4, 0xc7, 0xb6, 0xc3, 0x90, 0xc3, 0x97, - 0xc5, 0x99, 0xc7, 0x80, 0xc8, 0x93, 0xc2, 0xa5, 0xe1, 0x9b, 0x86, 0xc7, 0xb7, 0xc3, - 0x81, 0xc7, 0x8a, 0xe1, 0x9b, 0x9c, 0xe1, 0x9a, 0xaf, 0xc4, 0x84, 0xc2, 0xb7, 0xc6, - 0x8b, 0xc6, 0xab, 0xc8, 0xb0, 0xc3, 0xa7, 0xcd, 0xb1, 0xe1, 0x9a, 0xa2, 0xc8, 0x83, - 0xc6, 0xa8, 0xc6, 0xaf, 0xe2, 0xb1, 0xa1, 0xc3, 0xa2, 0xc7, 0xb5, 0xc9, 0x87, 0xc7, - 0x9c, 0xe1, 0x9a, 0xb1, 0xc5, 0x93, 0xe1, 0x9b, 0x95, 0xe2, 0xb1, 0xaa, 0xe1, 0x9b, - 0x8c, 0xc7, 0x99, 0xc6, 0xbe, 0x47, 0xc9, 0x83, 0xc5, 0xa5, 0xc5, 0x83, 0xe1, 0x9b, - 0x8b, 0xc8, 0xba, 0xc5, 0xb4, 0xc2, 0xb6, 0xe2, 0xb1, 0xa1, 0xce, 0x88, 0x36, 0x21, - 0xe2, 0xb1, 0xa6, 0xe1, 0x9b, 0x91, 0xc3, 0xa7, - ], - asset_base: [ - 0x3d, 0x73, 0x41, 0xcb, 0xb2, 0xd0, 0x56, 0xd3, 0xfa, 0x50, 0x77, 0x09, 0xd2, 0x62, - 0x75, 0xff, 0xee, 0xff, 0xa1, 0x64, 0xa4, 0xcd, 0xc9, 0x0d, 0x52, 0xf3, 0x56, 0xaa, - 0x67, 0x8e, 0xc6, 0xb6, - ], - }, - TestVector { - key: [ - 0x42, 0x67, 0x81, 0x37, 0x2b, 0x07, 0xac, 0x22, 0x91, 0x58, 0x7f, 0x9f, 0x81, 0xb5, - 0x4f, 0x8b, 0x96, 0xb4, 0xc8, 0xdd, 0xf8, 0xcd, 0x5b, 0x0d, 0x7d, 0x21, 0xe7, 0xa7, - 0x46, 0xbb, 0x13, 0x3e, - ], - description: [ - 0xc5, 0x9b, 0xc3, 0xb8, 0xc4, 0x89, 0xc3, 0xbd, 0xc8, 0xa6, 0xc6, 0x8e, 0xc4, 0xb9, - 0xe1, 0x9a, 0xb9, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0xb0, 0xc3, 0x99, 0x31, 0xe1, 0x9b, - 0x90, 0xc2, 0xb2, 0xc7, 0xa5, 0x7a, 0xe1, 0x9b, 0x88, 0xc8, 0x94, 0x35, 0x5d, 0xc5, - 0x9a, 0xc3, 0x9c, 0x55, 0xc6, 0x82, 0xc3, 0xb8, 0xc6, 0xaf, 0xc3, 0xb8, 0xc4, 0xab, - 0x25, 0xc4, 0x91, 0xc4, 0xb6, 0xce, 0x86, 0xc3, 0x80, 0xc2, 0xba, 0x40, 0xc9, 0x8a, - 0xc4, 0xa2, 0xc7, 0xb4, 0xc4, 0x8f, 0xe1, 0x9b, 0x90, 0xe1, 0x9b, 0xab, 0xc8, 0x83, - 0xc7, 0x97, 0x28, 0xc3, 0x9c, 0xc6, 0x9b, 0xc8, 0xbb, 0xc2, 0xa6, 0xc4, 0x81, 0xc5, - 0xac, 0xe1, 0x9a, 0xa0, 0xc2, 0xaf, 0xc9, 0x8e, 0xc2, 0xa9, 0xc6, 0xa7, 0xc8, 0xaf, - 0xc8, 0x86, 0xc8, 0xae, 0xc4, 0x8d, 0xe1, 0x9b, 0xb0, 0xc6, 0xa7, 0xc4, 0x81, 0xc2, - 0xa8, 0xc9, 0x87, 0xe1, 0x9a, 0xbf, 0xc5, 0xb5, 0xc8, 0xa1, 0xc4, 0x88, 0xc8, 0xb2, - 0xc7, 0x89, 0xc8, 0xb9, 0xc8, 0xa3, 0xe2, 0xb1, 0xb1, 0xc3, 0xb5, 0xc5, 0xaa, 0xc7, - 0x9f, 0xcd, 0xba, 0xc3, 0x8f, 0xc7, 0x9f, 0xcd, 0xb4, 0x42, 0xc7, 0xb2, 0xe1, 0x9a, - 0xa3, 0xc7, 0xbc, 0xe1, 0x9b, 0x93, 0xc8, 0xb9, 0xc7, 0xbd, 0xc2, 0xbb, 0xc5, 0x81, - 0xc5, 0xa7, 0xc6, 0x89, 0x69, 0xe1, 0x9b, 0x87, 0x32, 0xc9, 0x80, 0xcd, 0xba, 0xc5, - 0x9c, 0xe1, 0x9a, 0xbc, 0x2a, 0x57, 0xc7, 0x84, 0xc8, 0x95, 0xc8, 0xa6, 0xe2, 0xb1, - 0xa4, 0xc2, 0xab, 0xc4, 0xad, 0xe2, 0xb1, 0xb6, 0xc2, 0xb3, 0xe1, 0x9b, 0x92, 0xcd, - 0xbe, 0xc4, 0xa5, 0xc7, 0xbc, 0xc5, 0x87, 0xc8, 0xbe, 0xc3, 0xbc, 0xc3, 0xb8, 0xc6, - 0x8e, 0xc6, 0xba, 0x48, 0xe1, 0x9b, 0xa4, 0x57, 0xc4, 0x8f, 0xe2, 0xb1, 0xab, 0xc4, - 0x9d, 0xc7, 0xa0, 0xe1, 0x9a, 0xb2, 0x48, 0xc5, 0xba, 0xce, 0x87, 0xc7, 0x86, 0xc5, - 0xa6, 0xc2, 0xa7, 0xc7, 0x9d, 0xc6, 0x8c, 0xe1, 0x9a, 0xb0, 0x65, 0xc4, 0xb5, 0xc6, - 0xbb, 0xc7, 0x82, 0xc4, 0xb3, 0xc4, 0x98, 0xc3, 0x85, 0x24, 0xe1, 0x9a, 0xa9, 0xc4, - 0x83, 0xc6, 0xba, 0xc3, 0xaa, 0xc5, 0xa0, 0xc4, 0x9e, 0x5f, 0x59, 0xc3, 0x90, 0x59, - 0xc2, 0xb2, 0xc6, 0xa9, 0xcd, 0xb5, 0xe1, 0x9a, 0xa0, 0xc4, 0x83, 0xc6, 0x92, 0xe2, - 0xb1, 0xb4, 0xc3, 0x98, 0xc6, 0xa8, 0xc6, 0x90, 0xe1, 0x9b, 0x8d, 0xc8, 0x93, 0xc4, - 0xac, 0xc8, 0x93, 0xc7, 0xae, 0xe1, 0x9a, 0xa9, 0xc3, 0xa9, 0xc6, 0x8f, 0xc5, 0x93, - 0xc8, 0x84, 0xe1, 0x9b, 0xad, 0xe2, 0xb1, 0xb7, 0xe1, 0x9b, 0x97, 0xc3, 0x87, 0xe1, - 0x9b, 0x89, 0xc3, 0x91, 0x46, 0x4f, 0xc5, 0x9d, 0xc9, 0x8e, 0xc5, 0x99, 0xc6, 0x9b, - 0xe1, 0x9a, 0xbb, 0xe1, 0x9b, 0xa8, 0x51, 0xc6, 0x8d, 0xc3, 0x8b, 0xc2, 0xa7, 0xc3, - 0xb6, 0xc8, 0x82, 0xc7, 0x8b, 0xc8, 0xb2, 0x6b, 0xc5, 0x9e, 0xc9, 0x8b, 0xc6, 0x84, - 0xc6, 0xac, 0xc4, 0xa7, 0xe1, 0x9b, 0xa7, 0xc3, 0xb6, 0xc7, 0xb2, 0xc3, 0x9a, 0xc6, - 0xab, 0xc3, 0x86, 0xc6, 0xa8, 0x52, 0xe1, 0x9a, 0xba, 0x2a, 0xe1, 0x9b, 0x90, 0xc4, - 0xb7, 0xc3, 0x9f, 0xc4, 0x8d, 0xc8, 0xba, 0xc7, 0x86, 0xc8, 0x95, 0xe1, 0x9b, 0x9a, - 0x40, 0xc3, 0xa9, 0xe1, 0x9a, 0xbe, 0xc8, 0xa6, 0xc8, 0xab, 0xc5, 0x90, 0xce, 0x86, - 0xe2, 0xb1, 0xad, 0xc3, 0xa5, 0xe1, 0x9b, 0xa9, 0xc5, 0x84, 0xc4, 0xbf, 0xc3, 0x88, - 0xc7, 0x8b, 0xe1, 0x9a, 0xad, 0xc8, 0x90, 0xc7, 0xbb, 0xe2, 0xb1, 0xa2, 0xc6, 0xaf, - 0xc2, 0xa7, 0xc3, 0xb4, 0xc6, 0x8e, 0x56, 0xc8, 0x80, 0xc6, 0x86, 0xe1, 0x9a, 0xa7, - 0xc6, 0xbc, 0xc2, 0xba, 0xc6, 0xb7, 0xc5, 0x99, - ], - asset_base: [ - 0x39, 0xa7, 0x8f, 0x76, 0x63, 0x81, 0xec, 0x69, 0xd9, 0x2e, 0x8c, 0xa6, 0xb6, 0x4e, - 0x92, 0x10, 0xe9, 0x94, 0x28, 0x32, 0x9f, 0xde, 0x85, 0xb2, 0xe1, 0xfb, 0xb7, 0x35, - 0x70, 0x86, 0x7a, 0xb2, - ], - }, - TestVector { - key: [ - 0x76, 0xf4, 0x9c, 0xf8, 0xa3, 0x19, 0x21, 0x85, 0x61, 0x6a, 0x9a, 0x0d, 0xa0, 0xc7, - 0x6e, 0xc2, 0xc2, 0x75, 0x61, 0x59, 0xbc, 0xe1, 0x86, 0xa1, 0x86, 0x2b, 0x6e, 0x6e, - 0x59, 0x44, 0x2d, 0x11, - ], - description: [ - 0xc6, 0xbd, 0xc2, 0xa5, 0x6f, 0xe2, 0xb1, 0xb0, 0x64, 0xc5, 0xb2, 0x39, 0xc8, 0x9d, - 0xcd, 0xb0, 0xc3, 0x8d, 0xc5, 0xa5, 0xc7, 0xb7, 0xe1, 0x9b, 0xa5, 0xcd, 0xb4, 0xcd, - 0xb6, 0xc6, 0x96, 0xc5, 0xa2, 0xe1, 0x9b, 0x87, 0x68, 0xe1, 0x9a, 0xb2, 0xe1, 0x9b, - 0xa0, 0xc4, 0x99, 0xe1, 0x9a, 0xa5, 0xc9, 0x8f, 0x61, 0xe2, 0xb1, 0xa7, 0xc5, 0x8b, - 0xc4, 0xbb, 0xe1, 0x9a, 0xb9, 0xc8, 0xab, 0xc6, 0x99, 0xc7, 0xaa, 0x21, 0xcd, 0xbc, - 0xc4, 0xa6, 0xc2, 0xb4, 0xe1, 0x9b, 0x9b, 0x52, 0x7a, 0xc2, 0xb1, 0xc7, 0x97, 0x5a, - 0xc6, 0xba, 0xc6, 0xb5, 0xc5, 0xbd, 0xc6, 0xb3, 0xc2, 0xb9, 0xc3, 0xac, 0xc8, 0x93, - 0xe1, 0x9a, 0xa7, 0xc6, 0x80, 0xc6, 0x86, 0xce, 0x86, 0xc7, 0x86, 0xc4, 0xa9, 0xc5, - 0x9b, 0x4d, 0x21, 0xc8, 0xa8, 0x2b, 0xc6, 0x9b, 0xc3, 0x9f, 0xe1, 0x9a, 0xbf, 0x60, - 0xe1, 0x9b, 0x86, 0xe2, 0xb1, 0xbc, 0xcd, 0xb1, 0xc5, 0xb1, 0xc4, 0xa3, 0x21, 0xc6, - 0xb2, 0xc4, 0x95, 0xc2, 0xbe, 0xe1, 0x9b, 0x93, 0xc6, 0x88, 0xe1, 0x9a, 0xa9, 0xc7, - 0xbb, 0xc7, 0xb4, 0xc3, 0x84, 0xc9, 0x8e, 0xc7, 0xb3, 0x43, 0xc8, 0x87, 0xce, 0x85, - 0x55, 0xc3, 0xbd, 0xc3, 0x9c, 0xc7, 0x81, 0xc6, 0x9b, 0xc6, 0xa1, 0x6b, 0xc5, 0x9e, - 0xc6, 0xa1, 0xc5, 0xaa, 0x6e, 0xc5, 0xbc, 0xc4, 0xb0, 0xc8, 0x84, 0xc9, 0x80, 0xc7, - 0xb3, 0xc5, 0xb3, 0xc9, 0x88, 0x33, 0xc4, 0x83, 0xe1, 0x9b, 0x8c, 0xc9, 0x86, 0x6d, - 0xc8, 0xa5, 0xc3, 0xaf, 0xe1, 0x9b, 0xa0, 0xc2, 0xb1, 0xe2, 0xb1, 0xba, 0xc5, 0xae, - 0x3e, 0x79, 0xc4, 0xa4, 0xe1, 0x9b, 0xad, 0x33, 0xc7, 0xaa, 0xc4, 0x8c, 0xc8, 0xb6, - 0xe2, 0xb1, 0xa8, 0xe2, 0xb1, 0xb2, 0xe1, 0x9b, 0x94, 0xc8, 0x8e, 0xc5, 0xb2, 0xc4, - 0xb5, 0xc4, 0xad, 0xc8, 0xb5, 0xc7, 0xa5, 0xe2, 0xb1, 0xbd, 0x3b, 0xe1, 0x9b, 0x9f, - 0xc6, 0x8d, 0xc5, 0x84, 0xe1, 0x9b, 0xae, 0xc5, 0x8d, 0x23, 0x6f, 0x6f, 0xc5, 0x83, - 0xc5, 0xa7, 0xc4, 0x84, 0xc8, 0xa4, 0xc4, 0xb2, 0xc5, 0xba, 0xe2, 0xb1, 0xa5, 0xc8, - 0xa2, 0x3f, 0xc8, 0x86, 0xc8, 0x8b, 0xe1, 0x9b, 0x9e, 0xc5, 0x91, 0xe1, 0x9a, 0xaf, - 0xe1, 0x9b, 0x9b, 0xc4, 0xb7, 0xc6, 0x97, 0xc7, 0xbb, 0xe1, 0x9b, 0x9c, 0xc7, 0xa8, - 0xc7, 0x9a, 0xe1, 0x9b, 0xab, 0xc4, 0x93, 0x2f, 0xc6, 0xa3, 0xc6, 0x9d, 0xc6, 0xa6, - 0xc3, 0x86, 0xe1, 0x9b, 0x89, 0xc5, 0x84, 0xc6, 0x92, 0xc7, 0xa9, 0xc7, 0x91, 0xc5, - 0x99, 0xc6, 0x88, 0xc5, 0x98, 0x71, 0xe2, 0xb1, 0xa6, 0xcd, 0xbe, 0x5c, 0xc6, 0x8a, - 0xc3, 0xae, 0xc4, 0x80, 0xe1, 0x9a, 0xa6, 0x2d, 0xc6, 0x83, 0xc6, 0xa0, 0xc8, 0x8c, - 0xc7, 0xa9, 0xc6, 0xb1, 0xe1, 0x9b, 0x81, 0xe2, 0xb1, 0xb5, 0xc7, 0x8b, 0x43, 0xc8, - 0xad, 0xc4, 0xa4, 0xc7, 0x81, 0xc2, 0xbc, 0x4b, 0xc6, 0xb5, 0x67, 0xc2, 0xa2, 0xcd, - 0xba, 0xc6, 0xaa, 0xc2, 0xb8, 0xe1, 0x9b, 0xa5, 0x3c, 0xcd, 0xba, 0xc4, 0x94, 0xe2, - 0xb1, 0xaa, 0xe2, 0xb1, 0xbf, 0x48, 0x45, 0xc7, 0xba, 0xc5, 0xa0, 0xc2, 0xae, 0x2b, - 0xc2, 0xb7, 0xc6, 0xad, 0xc4, 0xa5, 0xc4, 0x93, 0xe1, 0x9a, 0xbd, 0xc3, 0xb2, 0xe1, - 0x9a, 0xa7, 0x66, 0xc7, 0x8b, 0xc2, 0xa7, 0x5c, 0xc7, 0x96, 0xc4, 0xb2, 0xe1, 0x9a, - 0xbc, 0xe2, 0xb1, 0xab, 0x43, 0xc9, 0x8f, 0xc5, 0x8e, 0x58, 0xe1, 0x9a, 0xa9, 0xe1, - 0x9b, 0x96, 0x59, 0xc5, 0x93, 0xe1, 0x9b, 0x89, 0xc7, 0xb1, 0xe1, 0x9a, 0xaf, 0xc9, - 0x82, 0xe2, 0xb1, 0xaf, 0xc7, 0xb4, 0xc4, 0xa5, 0x62, 0xc8, 0x93, 0xc5, 0xae, 0xc4, - 0xae, 0xce, 0x8c, 0xc8, 0xa8, 0xe1, 0x9a, 0xa0, - ], - asset_base: [ - 0xca, 0x81, 0x0e, 0x15, 0xe1, 0x48, 0x19, 0x50, 0xde, 0x77, 0xab, 0x5f, 0x02, 0xa1, - 0xa6, 0x37, 0xf0, 0x5c, 0x3f, 0x12, 0x64, 0xbb, 0x93, 0x65, 0xf5, 0x0a, 0x91, 0x10, - 0x4d, 0x52, 0x2b, 0x9e, - ], - }, - ] -} diff --git a/src/test_vectors/issuance_auth_sig.rs b/src/test_vectors/issuance_auth_sig.rs new file mode 100644 index 000000000..fe71486e2 --- /dev/null +++ b/src/test_vectors/issuance_auth_sig.rs @@ -0,0 +1,277 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (issuance_auth_sig) + +pub(crate) struct TestVector { + pub(crate) isk: [u8; 32], + pub(crate) ik: [u8; 32], + pub(crate) msg: [u8; 32], + pub(crate) sig: [u8; 64], +} + +pub(crate) fn test_vectors() -> Vec { + vec![ + TestVector { + isk: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, + ], + ik: [ + 0xf9, 0x30, 0x8a, 0x01, 0x92, 0x58, 0xc3, 0x10, 0x49, 0x34, 0x4f, 0x85, 0xf8, 0x9d, + 0x52, 0x29, 0xb5, 0x31, 0xc8, 0x45, 0x83, 0x6f, 0x99, 0xb0, 0x86, 0x01, 0xf1, 0x13, + 0xbc, 0xe0, 0x36, 0xf9, + ], + msg: [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ], + sig: [ + 0xe9, 0x07, 0x83, 0x1f, 0x80, 0x84, 0x8d, 0x10, 0x69, 0xa5, 0x37, 0x1b, 0x40, 0x24, + 0x10, 0x36, 0x4b, 0xdf, 0x1c, 0x5f, 0x83, 0x07, 0xb0, 0x08, 0x4c, 0x55, 0xf1, 0xce, + 0x2d, 0xca, 0x82, 0x15, 0x25, 0xf6, 0x6a, 0x4a, 0x85, 0xea, 0x8b, 0x71, 0xe4, 0x82, + 0xa7, 0x4f, 0x38, 0x2d, 0x2c, 0xe5, 0xeb, 0xee, 0xe8, 0xfd, 0xb2, 0x17, 0x2f, 0x47, + 0x7d, 0xf4, 0x90, 0x0d, 0x31, 0x05, 0x36, 0xc0, + ], + }, + TestVector { + isk: [ + 0x5d, 0x7a, 0x8f, 0x73, 0x9a, 0x2d, 0x9e, 0x94, 0x5b, 0x0c, 0xe1, 0x52, 0xa8, 0x04, + 0x9e, 0x29, 0x4c, 0x4d, 0x6e, 0x66, 0xb1, 0x64, 0x93, 0x9d, 0xaf, 0xfa, 0x2e, 0xf6, + 0xee, 0x69, 0x21, 0x48, + ], + ik: [ + 0x4b, 0xec, 0xe1, 0xff, 0x00, 0xe2, 0xed, 0x77, 0x64, 0xae, 0x6b, 0xe2, 0x0d, 0x2f, + 0x67, 0x22, 0x04, 0xfc, 0x86, 0xcc, 0xed, 0xd6, 0xfc, 0x1f, 0x71, 0xdf, 0x02, 0xc7, + 0x51, 0x6d, 0x9f, 0x31, + ], + msg: [ + 0x1c, 0xdd, 0x86, 0xb3, 0xcc, 0x43, 0x18, 0xd9, 0x61, 0x4f, 0xc8, 0x20, 0x90, 0x5d, + 0x04, 0x2b, 0xb1, 0xef, 0x9c, 0xa3, 0xf2, 0x49, 0x88, 0xc7, 0xb3, 0x53, 0x42, 0x01, + 0xcf, 0xb1, 0xcd, 0x8d, + ], + sig: [ + 0xa5, 0xb5, 0x92, 0x78, 0x1b, 0xeb, 0x55, 0xee, 0xbf, 0x8b, 0xc2, 0xbf, 0xd7, 0x9d, + 0xa9, 0x45, 0x2d, 0xc9, 0x22, 0x39, 0x87, 0x7e, 0xb7, 0xe1, 0xf5, 0x64, 0x65, 0xff, + 0x11, 0x1e, 0x59, 0x08, 0xde, 0xac, 0x15, 0xd5, 0x69, 0x99, 0x9a, 0x2b, 0xd2, 0x2b, + 0x2e, 0xf6, 0x01, 0xc5, 0x81, 0x3b, 0xdb, 0xba, 0x99, 0x3c, 0x08, 0xd4, 0xe8, 0x56, + 0xc9, 0x26, 0xd9, 0xe2, 0xc0, 0x63, 0x93, 0x67, + ], + }, + TestVector { + isk: [ + 0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb, + 0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e, + 0x30, 0xa7, 0x35, 0x94, + ], + ik: [ + 0xd4, 0x22, 0x9e, 0x19, 0x5e, 0x25, 0xf6, 0x02, 0xa2, 0x18, 0x61, 0x22, 0xcb, 0x4e, + 0x78, 0x76, 0x7b, 0x3c, 0x66, 0xac, 0x39, 0x08, 0x08, 0xd2, 0xd1, 0xb4, 0x04, 0x42, + 0xda, 0x7f, 0x00, 0x66, + ], + msg: [ + 0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, 0x25, + 0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, 0x91, + 0x2a, 0x63, 0x81, 0xce, + ], + sig: [ + 0x18, 0x8b, 0x15, 0x57, 0x42, 0x87, 0x83, 0x55, 0x6b, 0x66, 0x80, 0x3b, 0xf9, 0x06, + 0x63, 0xb7, 0xa1, 0x6d, 0x43, 0x76, 0x92, 0x7c, 0x58, 0x35, 0xe0, 0xb7, 0x26, 0x52, + 0x0e, 0xb2, 0x6d, 0x53, 0x24, 0x99, 0x10, 0xc3, 0x9c, 0x5f, 0x05, 0x90, 0xb6, 0xd6, + 0xaa, 0xb3, 0x51, 0xff, 0x8c, 0xd8, 0xe0, 0x63, 0xfa, 0x74, 0x20, 0x42, 0x55, 0xda, + 0xdc, 0x00, 0xd9, 0xe0, 0xdf, 0xf7, 0x7b, 0x09, + ], + }, + TestVector { + isk: [ + 0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, 0xd7, 0x55, 0x1d, 0xb5, 0xfd, + 0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, 0xd4, 0x77, 0x08, 0x37, 0x56, + 0xd5, 0x9a, 0xf8, 0x0d, + ], + ik: [ + 0xce, 0xb7, 0x5a, 0x43, 0x9f, 0xf0, 0x16, 0x15, 0x80, 0xbf, 0x29, 0x57, 0x24, 0xc6, + 0xd9, 0x2d, 0x31, 0xb7, 0xaa, 0x02, 0x84, 0x03, 0x39, 0x44, 0x49, 0x64, 0x48, 0x6f, + 0xae, 0xa8, 0x90, 0xe5, + ], + msg: [ + 0x06, 0xa7, 0x45, 0xf4, 0x4a, 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, + 0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, + 0xcc, 0xb8, 0xf6, 0x76, + ], + sig: [ + 0x6e, 0x5e, 0xd6, 0x65, 0x6c, 0x32, 0x71, 0x32, 0xb1, 0x65, 0x81, 0x06, 0x2f, 0x1b, + 0x13, 0x8a, 0xcc, 0x6f, 0x1f, 0x83, 0x43, 0xed, 0x9d, 0x89, 0xab, 0x5f, 0xd9, 0x38, + 0xe4, 0xe6, 0xce, 0xf7, 0x99, 0xa2, 0x25, 0x1c, 0xa5, 0x2d, 0x60, 0x82, 0x0e, 0x51, + 0x00, 0x25, 0x06, 0x7d, 0xcd, 0x1b, 0xf7, 0x54, 0xc5, 0xbf, 0xf1, 0x39, 0xb4, 0xcc, + 0x44, 0xb3, 0x7d, 0x27, 0xd1, 0x7c, 0x4a, 0xee, + ], + }, + TestVector { + isk: [ + 0x49, 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef, + 0xc2, 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d, + 0x94, 0x90, 0x3d, 0x3c, + ], + ik: [ + 0xb0, 0xfa, 0x9d, 0x77, 0xfc, 0xbd, 0x96, 0x45, 0x91, 0x32, 0xe3, 0x05, 0xe3, 0x24, + 0xe7, 0x93, 0x6a, 0xe1, 0x3b, 0x15, 0x14, 0x7e, 0x20, 0x5d, 0x7b, 0xae, 0x42, 0xfa, + 0x7f, 0xaf, 0x5d, 0x1e, + ], + msg: [ + 0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31, + 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b, + 0xe3, 0x4a, 0x98, 0x51, + ], + sig: [ + 0x17, 0xc2, 0xe5, 0xdf, 0x2e, 0xa6, 0xa1, 0x2e, 0x8a, 0xb2, 0xb0, 0xd5, 0x04, 0x89, + 0x8f, 0x3f, 0x23, 0x43, 0xe0, 0x98, 0x90, 0x7f, 0x7a, 0xfe, 0x43, 0xac, 0x8a, 0x01, + 0x14, 0x42, 0x35, 0x80, 0x97, 0x53, 0x67, 0xba, 0x4b, 0x6d, 0x16, 0x6c, 0x44, 0x28, + 0x48, 0x57, 0xb7, 0xcd, 0x29, 0xa8, 0x38, 0xb4, 0x9c, 0xc3, 0x41, 0xd2, 0x89, 0x51, + 0xaa, 0x0b, 0x5d, 0x55, 0x6a, 0x20, 0x9e, 0xb6, + ], + }, + TestVector { + isk: [ + 0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, + 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, + 0x32, 0x0d, 0xad, 0xd6, + ], + ik: [ + 0x0b, 0xb4, 0x91, 0x3d, 0xba, 0xf1, 0x4e, 0xf6, 0xd0, 0xad, 0xeb, 0x8b, 0x70, 0x27, + 0xbf, 0x0b, 0x9a, 0x8f, 0x59, 0x0d, 0x3e, 0x2d, 0x95, 0xa1, 0x2d, 0xba, 0xaf, 0x0b, + 0x95, 0x33, 0xdc, 0xa4, + ], + msg: [ + 0x4f, 0x54, 0x31, 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d, + 0x13, 0x09, 0x13, 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, + 0x47, 0xf1, 0xe1, 0x91, + ], + sig: [ + 0x42, 0x1f, 0x5b, 0x07, 0x57, 0x2e, 0x6b, 0x05, 0xe8, 0x0b, 0xa5, 0x85, 0xff, 0x63, + 0x21, 0x42, 0x26, 0x75, 0xcd, 0x19, 0xea, 0x59, 0x15, 0xd6, 0x32, 0xeb, 0x47, 0x64, + 0x6c, 0xe2, 0x20, 0x27, 0x6b, 0xb7, 0x82, 0x42, 0xcc, 0x75, 0x48, 0xd9, 0xa0, 0x57, + 0x2b, 0x89, 0x69, 0x2e, 0x5b, 0x95, 0xdb, 0x14, 0x14, 0xe4, 0xeb, 0xd2, 0x20, 0xcc, + 0xf8, 0x3a, 0xf2, 0x98, 0x2f, 0xdd, 0x3a, 0xec, + ], + }, + TestVector { + isk: [ + 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, 0xa9, + 0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, 0xda, + 0xe6, 0x9c, 0xe8, 0xfc, + ], + ik: [ + 0x61, 0xbb, 0x33, 0x91, 0x59, 0xdf, 0x98, 0x20, 0xef, 0xae, 0xb6, 0x1d, 0x9a, 0x10, + 0xcd, 0xc1, 0x3b, 0x4c, 0x99, 0xfd, 0xc8, 0x6d, 0x94, 0x85, 0x11, 0x5d, 0xfd, 0x83, + 0x62, 0x36, 0xac, 0xf8, + ], + msg: [ + 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, 0x93, 0x1d, 0xe5, 0x18, 0x85, + 0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, 0xc9, 0x37, 0x83, 0x65, 0xc8, + 0xf7, 0x39, 0x3c, 0x94, + ], + sig: [ + 0x5a, 0x11, 0x48, 0xa8, 0x92, 0x8f, 0xbf, 0x43, 0xbb, 0x33, 0xa5, 0x70, 0xf0, 0xdf, + 0xa3, 0x53, 0x32, 0xb7, 0x01, 0x80, 0x21, 0xa0, 0xcb, 0x75, 0xe9, 0x55, 0x4e, 0x86, + 0xec, 0xb2, 0x1d, 0xa3, 0x2e, 0xb5, 0xa2, 0xd8, 0xc5, 0x9e, 0xa3, 0x90, 0x43, 0xb9, + 0x74, 0x78, 0x75, 0x0c, 0x6b, 0xf8, 0x66, 0xeb, 0x3b, 0x01, 0x5e, 0xbb, 0x31, 0x68, + 0xf7, 0x53, 0x76, 0x6a, 0xd1, 0x71, 0xd2, 0x1e, + ], + }, + TestVector { + isk: [ + 0xe2, 0x88, 0x53, 0x15, 0xeb, 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f, + 0xe5, 0x3e, 0x29, 0xfe, 0xf2, 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, + 0xf4, 0x68, 0xa0, 0x08, + ], + ik: [ + 0x19, 0x58, 0x53, 0x8b, 0x12, 0x17, 0xa0, 0x3d, 0x89, 0xcd, 0x83, 0xb8, 0x3d, 0x0b, + 0xdd, 0x40, 0xa6, 0x9a, 0xbe, 0x3a, 0xc2, 0x5d, 0x00, 0xc6, 0xd2, 0x69, 0x97, 0xf9, + 0xf2, 0x57, 0x4d, 0x4f, + ], + msg: [ + 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, + 0x3f, 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, + 0x03, 0x59, 0x65, 0x55, + ], + sig: [ + 0x16, 0x90, 0xf5, 0x43, 0xee, 0x67, 0xbb, 0x1c, 0xe0, 0xe4, 0x25, 0x4e, 0xa5, 0xdf, + 0xd0, 0x42, 0xfe, 0x86, 0x3a, 0xb4, 0x6c, 0xd9, 0xa8, 0x90, 0x55, 0x19, 0xff, 0xb1, + 0xb8, 0x40, 0x6b, 0xec, 0xbd, 0x90, 0xda, 0x66, 0xe5, 0xb5, 0x44, 0xbc, 0xd4, 0x3b, + 0xdb, 0x29, 0xbc, 0x5d, 0x2c, 0x02, 0x4d, 0xd2, 0x85, 0xab, 0xcd, 0x77, 0xe4, 0xac, + 0x1f, 0x9d, 0x60, 0x35, 0x22, 0xe4, 0xf1, 0x5b, + ], + }, + TestVector { + isk: [ + 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, 0x89, 0x26, + 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d, + 0x99, 0x58, 0x9c, 0x8b, + ], + ik: [ + 0x7d, 0xd6, 0xd7, 0x61, 0xe1, 0x02, 0x01, 0x37, 0xfa, 0x01, 0xb4, 0xdd, 0xd3, 0xb0, + 0xf3, 0x48, 0x04, 0xcc, 0x10, 0xcc, 0x4e, 0x9f, 0x6e, 0x9d, 0xf5, 0xb6, 0x04, 0x69, + 0xf5, 0x79, 0x36, 0x67, + ], + msg: [ + 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, + 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d, + 0xed, 0x42, 0x43, 0x5e, + ], + sig: [ + 0x59, 0x34, 0x5d, 0x6b, 0x89, 0x4e, 0xd6, 0xd0, 0x3a, 0x56, 0x73, 0xa0, 0x14, 0x63, + 0x07, 0x51, 0x04, 0x3d, 0x11, 0xfa, 0x63, 0x18, 0x7c, 0x92, 0x9c, 0xae, 0x3f, 0xa1, + 0xb0, 0x29, 0x22, 0xf2, 0x7d, 0xc0, 0x16, 0x40, 0x33, 0x95, 0x2c, 0x84, 0x16, 0xe6, + 0xd0, 0x43, 0x81, 0x77, 0xb3, 0xbc, 0xe8, 0x78, 0xfd, 0xec, 0x75, 0x0a, 0x16, 0x64, + 0xd4, 0x89, 0xdf, 0x0a, 0x4e, 0xae, 0xb1, 0x35, + ], + }, + TestVector { + isk: [ + 0x92, 0x47, 0x69, 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72, + 0x7b, 0x89, 0xe0, 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6, + 0xf2, 0x65, 0x72, 0x50, + ], + ik: [ + 0xb5, 0x9c, 0x5f, 0x32, 0x34, 0xd6, 0xca, 0x36, 0xcc, 0x48, 0x3d, 0x67, 0xa8, 0x4f, + 0x37, 0xd6, 0xb2, 0x4b, 0x24, 0x45, 0x48, 0x25, 0xd2, 0xb7, 0xbf, 0xdc, 0x80, 0x2b, + 0x2e, 0x32, 0x8c, 0x43, + ], + msg: [ + 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, 0xbc, + 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, 0xe7, + 0x1a, 0x02, 0xaf, 0x11, + ], + sig: [ + 0xa4, 0x58, 0x79, 0x33, 0x26, 0x98, 0x37, 0x74, 0x09, 0x6d, 0x36, 0x59, 0xeb, 0x9a, + 0x21, 0xd1, 0x2c, 0x8e, 0xb8, 0x77, 0x56, 0x6b, 0x66, 0xbf, 0x60, 0x33, 0xdb, 0x8f, + 0xde, 0x20, 0xc4, 0x66, 0xa2, 0xe9, 0x54, 0x30, 0xa0, 0x1e, 0xb9, 0xad, 0x28, 0xe0, + 0x76, 0x5b, 0xed, 0x21, 0xdc, 0xd3, 0x03, 0x86, 0xfc, 0xe7, 0xaa, 0xba, 0xde, 0xa6, + 0xda, 0x72, 0x8c, 0x16, 0xbb, 0x80, 0xf1, 0xc2, + ], + }, + TestVector { + isk: [ + 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, 0xb1, 0xfc, 0xe4, 0x67, 0x50, + 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, 0xc3, 0x82, 0x85, 0x7d, 0xee, + 0xcc, 0x40, 0xa9, 0x8d, + ], + ik: [ + 0x45, 0x61, 0x9f, 0x20, 0x6c, 0x3b, 0xfc, 0x84, 0xfd, 0x42, 0x4f, 0xfb, 0x5c, 0x81, + 0x6f, 0x65, 0x4b, 0x27, 0xaa, 0x7f, 0x7b, 0x4b, 0xd6, 0x7e, 0xc5, 0xf9, 0xac, 0x6d, + 0x0f, 0x38, 0xdb, 0xb1, + ], + msg: [ + 0x5f, 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0x2d, 0xd2, 0x1a, 0xfd, 0xbb, 0x5d, 0x47, + 0xfa, 0x9a, 0x6d, 0xd9, 0x84, 0xd5, 0x67, 0xdb, 0x28, 0x57, 0xb9, 0x27, 0xb7, 0xfa, + 0xe2, 0xdb, 0x58, 0x71, + ], + sig: [ + 0xe6, 0x92, 0x4d, 0x53, 0xec, 0x97, 0x80, 0x79, 0xd6, 0x6a, 0x28, 0x4c, 0x00, 0xa8, + 0x68, 0xf9, 0xeb, 0x75, 0x1a, 0xe3, 0xb1, 0x69, 0x0d, 0x15, 0xee, 0x1b, 0x39, 0x68, + 0x0b, 0x83, 0xc4, 0x38, 0xe4, 0x5f, 0x02, 0xa2, 0x3c, 0x65, 0x6e, 0x4e, 0x53, 0xd3, + 0xc7, 0x3e, 0xfa, 0x0d, 0xc5, 0xf7, 0xad, 0x63, 0x28, 0x21, 0x7f, 0xd5, 0x9b, 0x23, + 0xaa, 0xe4, 0xf9, 0x0c, 0x68, 0xbe, 0x76, 0xbc, + ], + }, + ] +} diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 8fa650a37..4417713eb 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -44,14 +44,14 @@ pub(crate) fn test_vectors() -> Vec { 0xd4, 0xe2, 0x0f, 0x15, ], isk: [ - 0x95, 0x4a, 0x86, 0xc7, 0xa7, 0x15, 0x53, 0xfa, 0x6c, 0x8b, 0x67, 0x58, 0x54, 0x26, - 0x8e, 0xa5, 0x4c, 0x51, 0xfb, 0x17, 0xd8, 0x3d, 0x80, 0xee, 0x71, 0xd4, 0xae, 0x42, - 0xa1, 0xf8, 0xc8, 0x16, + 0x1c, 0xdd, 0x86, 0xb3, 0xcc, 0x43, 0x18, 0xd9, 0x61, 0x4f, 0xc8, 0x20, 0x90, 0x5d, + 0x04, 0x2b, 0xb1, 0xef, 0x9c, 0xa3, 0xf2, 0x49, 0x88, 0xc7, 0xb3, 0x53, 0x42, 0x01, + 0xcf, 0xb1, 0xcd, 0x8d, ], ik: [ - 0x2e, 0x4f, 0xd4, 0xa6, 0xec, 0x39, 0x94, 0x87, 0xd3, 0x78, 0xb4, 0xc7, 0x25, 0xfb, - 0x9b, 0xaf, 0xbc, 0x01, 0xa5, 0xe2, 0xb7, 0xf3, 0x68, 0x2e, 0xf4, 0x53, 0x95, 0x91, - 0xbc, 0xf0, 0x59, 0x02, + 0x16, 0x88, 0x4f, 0x1d, 0xbc, 0x92, 0x90, 0x89, 0xa4, 0x17, 0x6e, 0x84, 0x0b, 0xb5, + 0x81, 0xc8, 0x0e, 0x16, 0xe9, 0xb1, 0xab, 0xd6, 0x54, 0xe6, 0x2c, 0x8b, 0x0b, 0x95, + 0x70, 0x20, 0xb7, 0x48, ], nk: [ 0x9f, 0x2f, 0x82, 0x67, 0x38, 0x94, 0x5a, 0xd0, 0x1f, 0x47, 0xf7, 0x0d, 0xb0, 0xc3, @@ -111,7 +111,7 @@ pub(crate) fn test_vectors() -> Vec { 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 15643327852135767324, + note_v: 4751042572350679487, note_rho: [ 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, 0xcc, 0xb8, 0xf6, 0x76, 0x49, 0x5c, 0x22, 0x2f, @@ -123,14 +123,14 @@ pub(crate) fn test_vectors() -> Vec { 0x0c, 0x1d, 0x37, 0x10, ], note_cmx: [ - 0x45, 0x02, 0xe3, 0x39, 0x90, 0x1e, 0x39, 0x77, 0x17, 0x83, 0x91, 0x67, 0xcb, 0xb4, - 0x03, 0x7e, 0x0e, 0xcf, 0x68, 0x13, 0xb5, 0x1c, 0x81, 0xfe, 0x08, 0x5a, 0x7b, 0x78, - 0x2f, 0x12, 0x42, 0x28, + 0x6a, 0xcb, 0x59, 0x4e, 0x29, 0x6f, 0xfe, 0x99, 0xa8, 0x5c, 0x17, 0x5a, 0xa4, 0x22, + 0xc8, 0x29, 0x3c, 0xe7, 0xe1, 0x9a, 0x92, 0xdf, 0x7f, 0x80, 0xae, 0x87, 0x66, 0x55, + 0x44, 0x25, 0x83, 0x38, ], note_nf: [ - 0x1b, 0x32, 0xed, 0xbb, 0xe4, 0xd1, 0x8f, 0x28, 0x87, 0x6d, 0xe2, 0x62, 0x51, 0x8a, - 0xd3, 0x11, 0x22, 0x70, 0x1f, 0x8c, 0x0a, 0x52, 0xe9, 0x80, 0x47, 0xa3, 0x37, 0x87, - 0x6e, 0x7e, 0xea, 0x19, + 0x1c, 0x64, 0xc6, 0x82, 0x9a, 0x41, 0x21, 0xe1, 0x38, 0xd9, 0x8a, 0xae, 0xb4, 0xe6, + 0xbd, 0x4f, 0xf4, 0x5a, 0x1d, 0xb8, 0x6d, 0xef, 0x9f, 0x08, 0xd6, 0xaa, 0x60, 0x5a, + 0x97, 0xf3, 0x79, 0x39, ], }, TestVector { @@ -150,14 +150,14 @@ pub(crate) fn test_vectors() -> Vec { 0x56, 0xe4, 0x00, 0x2a, ], isk: [ - 0xee, 0xf5, 0xe9, 0x1b, 0x36, 0xb8, 0x06, 0x86, 0x72, 0x3d, 0x14, 0xdc, 0xc7, 0x04, - 0xad, 0x59, 0x67, 0x08, 0x0b, 0x7d, 0x6e, 0x49, 0xaf, 0x97, 0x03, 0x0e, 0x4f, 0xa0, - 0xbf, 0x5a, 0xd9, 0x0b, + 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, + 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, 0xe6, + 0x1d, 0xdf, 0x65, 0x8d, ], ik: [ - 0x2e, 0xde, 0xfb, 0x15, 0x8e, 0xa4, 0x48, 0x82, 0x57, 0x2b, 0xcd, 0xb2, 0x35, 0xca, - 0x36, 0xab, 0x39, 0xc7, 0x47, 0xbb, 0x71, 0xfe, 0x0f, 0x10, 0xfa, 0xa3, 0x9b, 0xfd, - 0x62, 0x0a, 0xcc, 0x04, + 0x46, 0x2e, 0xe2, 0x38, 0x00, 0xc2, 0x1e, 0x2b, 0xbd, 0x90, 0x2b, 0xf7, 0x2f, 0x60, + 0xe1, 0xab, 0x08, 0x26, 0xd3, 0x68, 0x0c, 0x6f, 0xd0, 0xa2, 0x6f, 0x87, 0xdb, 0xac, + 0xd0, 0xd7, 0x6c, 0xa0, ], nk: [ 0xa8, 0xb7, 0x3d, 0x97, 0x9b, 0x6e, 0xaa, 0xda, 0x89, 0x24, 0xbc, 0xbd, 0xc6, 0x3a, @@ -217,874 +217,874 @@ pub(crate) fn test_vectors() -> Vec { 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 4481649511318637270, + note_v: 654021594278506020, note_rho: [ - 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, - 0xad, 0xd6, 0x4f, 0x54, 0x31, 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, - 0x2c, 0x8d, 0x13, 0x09, + 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, 0xc9, 0x37, 0x83, 0x65, 0xc8, 0xf7, 0x39, + 0x3c, 0x94, 0xe2, 0x88, 0x53, 0x15, 0xeb, 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, + 0x79, 0x0f, 0xe5, 0x3e, ], note_rseed: [ - 0x13, 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d, 0x47, 0xf1, - 0xe1, 0x91, 0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, - 0x33, 0xa9, 0x7f, 0xa6, + 0x29, 0xfe, 0xf2, 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, + 0xa0, 0x08, 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, + 0xaa, 0xbe, 0x3f, 0x1a, ], note_cmx: [ - 0xc7, 0xad, 0x79, 0x4c, 0x56, 0x3e, 0x32, 0xca, 0xd4, 0x7d, 0x47, 0xdc, 0xda, 0x78, - 0x84, 0x69, 0x28, 0x48, 0xdc, 0xe2, 0x9b, 0xa4, 0xfe, 0xbd, 0x93, 0x20, 0x2b, 0x73, - 0x05, 0xf9, 0x03, 0x00, + 0x3b, 0x7a, 0x77, 0x4e, 0x5a, 0xc0, 0x16, 0xfd, 0x2a, 0x8a, 0x2b, 0xa0, 0x21, 0x2e, + 0x67, 0xfe, 0x16, 0x92, 0x9b, 0xa7, 0x2e, 0x7b, 0x82, 0x70, 0x8b, 0xd5, 0x74, 0x96, + 0xfb, 0xb3, 0x0f, 0x22, ], note_nf: [ - 0x2c, 0xf0, 0x67, 0xbc, 0x21, 0xd6, 0x63, 0x20, 0xe5, 0x1b, 0x9f, 0xbd, 0xc8, 0xae, - 0x03, 0x1c, 0x2c, 0x96, 0x37, 0x3d, 0xb4, 0x3b, 0x7b, 0x1a, 0x45, 0x05, 0x6c, 0x00, - 0xc6, 0x5d, 0x43, 0x20, + 0x6c, 0xba, 0xbc, 0xfe, 0x07, 0x58, 0xc0, 0x61, 0x75, 0x59, 0x3f, 0xcc, 0x89, 0x37, + 0x55, 0x9a, 0xc1, 0xc7, 0xb7, 0x22, 0xd5, 0x65, 0xa1, 0xf3, 0xfc, 0xf0, 0xb8, 0xc5, + 0x90, 0x37, 0x8a, 0x1c, ], }, TestVector { sk: [ - 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, 0xda, 0xe6, 0x9c, - 0xe8, 0xfc, 0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, 0x93, 0x1d, 0xe5, - 0x18, 0x85, 0x68, 0x78, + 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, 0x59, + 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, + 0x89, 0x26, 0xc1, 0x03, ], ask: [ - 0xce, 0x8b, 0x65, 0xa7, 0x23, 0x65, 0x11, 0xb2, 0xea, 0xf1, 0x9f, 0x72, 0xa3, 0xd6, - 0xdb, 0x7d, 0x06, 0x2b, 0x66, 0xf5, 0x16, 0x30, 0x7d, 0x19, 0x87, 0x06, 0xe5, 0xf6, - 0x92, 0x8e, 0x16, 0x15, + 0xe0, 0x9b, 0x65, 0x10, 0x87, 0x7d, 0xd4, 0x0e, 0x85, 0x4e, 0xe4, 0xb9, 0xc4, 0xc3, + 0x89, 0x8e, 0xc1, 0xe7, 0x26, 0x60, 0xfe, 0xf5, 0xb0, 0xab, 0xda, 0xdb, 0xa8, 0x08, + 0x10, 0x50, 0xae, 0x38, ], ak: [ - 0xef, 0xa5, 0xf1, 0xde, 0xbe, 0xea, 0xd0, 0x94, 0x0a, 0x61, 0x9c, 0xe0, 0x01, 0x7b, - 0xed, 0xb4, 0x26, 0x65, 0x7b, 0x2d, 0x07, 0x40, 0x66, 0x64, 0xd8, 0x95, 0x31, 0x2e, - 0xa1, 0xc3, 0xb3, 0x34, + 0x53, 0xf7, 0x4b, 0x84, 0x33, 0xe9, 0x4a, 0xae, 0xb8, 0x5f, 0x5e, 0xb4, 0x1a, 0x89, + 0xc1, 0x0f, 0xe2, 0x0a, 0xe0, 0x03, 0xec, 0xf4, 0xbc, 0xe1, 0x63, 0x38, 0xd9, 0x75, + 0x88, 0x65, 0x6b, 0x38, ], isk: [ - 0x5b, 0x1f, 0xc4, 0x57, 0xae, 0x71, 0x38, 0x3c, 0x53, 0xf4, 0x69, 0x41, 0xb7, 0xcb, - 0x4c, 0xec, 0x3d, 0xea, 0xc0, 0xc6, 0x03, 0xe2, 0xcd, 0xd0, 0xd1, 0x8d, 0x94, 0x01, - 0x9e, 0x43, 0xe2, 0x07, + 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d, 0x99, 0x58, + 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, + 0x1c, 0xd0, 0x74, 0xa5, ], ik: [ - 0x4f, 0x43, 0xeb, 0x7d, 0x9e, 0x03, 0x6f, 0xa6, 0x15, 0xfd, 0x04, 0xa5, 0xef, 0x6a, - 0xeb, 0x21, 0x6e, 0x06, 0x9b, 0xe9, 0x2d, 0x30, 0xe8, 0xf7, 0x16, 0x3e, 0xe3, 0x15, - 0x11, 0x6f, 0x18, 0x32, + 0xcb, 0x48, 0x0d, 0x9b, 0x96, 0x27, 0x3e, 0x89, 0x91, 0x40, 0x89, 0xa1, 0x04, 0xc2, + 0xc9, 0x36, 0xd0, 0x75, 0x95, 0xd4, 0xf8, 0x46, 0xad, 0xa6, 0xca, 0xea, 0x68, 0x5c, + 0x88, 0x0b, 0x8a, 0xf8, ], nk: [ - 0x04, 0x51, 0x4e, 0xa0, 0x48, 0xb9, 0x43, 0x63, 0xde, 0xa7, 0xcb, 0x3b, 0xe8, 0xd6, - 0x25, 0x82, 0xac, 0x52, 0x92, 0x2e, 0x08, 0x65, 0xf6, 0x62, 0x74, 0x3b, 0x05, 0xea, - 0xe8, 0x71, 0x5f, 0x17, + 0x6e, 0x37, 0x10, 0xbc, 0xa6, 0x80, 0x46, 0xc8, 0x3e, 0x54, 0x80, 0xbf, 0xe7, 0x3f, + 0xd7, 0x54, 0x13, 0x5d, 0xc0, 0x7f, 0xa1, 0xd1, 0x1b, 0x86, 0x5f, 0xd1, 0x5e, 0x7c, + 0x4e, 0x63, 0xe2, 0x02, ], rivk: [ - 0x2a, 0x32, 0x8f, 0x99, 0x4f, 0x6e, 0x5a, 0xd2, 0x9c, 0xa8, 0x11, 0xed, 0x34, 0x49, - 0x68, 0xea, 0x2c, 0xfc, 0x3f, 0xd2, 0x31, 0x03, 0x0e, 0x37, 0xbb, 0xd5, 0x6d, 0xb4, - 0x26, 0x40, 0x23, 0x1c, + 0xaa, 0xcc, 0xc8, 0x41, 0xfe, 0x74, 0x89, 0x49, 0xcf, 0x90, 0x59, 0xb5, 0x41, 0x1c, + 0x2c, 0xe8, 0xf0, 0x07, 0x05, 0x00, 0x23, 0x85, 0x2d, 0xd5, 0x8d, 0xb0, 0xb6, 0x9b, + 0x44, 0xfe, 0xf5, 0x33, ], ivk: [ - 0x60, 0x9e, 0xcb, 0xc3, 0xd8, 0xce, 0xe3, 0xbe, 0x2b, 0x2a, 0x23, 0x62, 0x95, 0x1f, - 0x58, 0xb7, 0x44, 0x82, 0xad, 0xfa, 0xee, 0xe1, 0xc4, 0x0f, 0x94, 0x03, 0x04, 0x40, - 0xf5, 0x58, 0xaa, 0x30, + 0xa8, 0x1d, 0xfd, 0x18, 0xbf, 0x1e, 0x5e, 0xad, 0x3d, 0x10, 0x02, 0xf5, 0xfe, 0x4b, + 0xcb, 0x89, 0xde, 0xea, 0xf9, 0xd6, 0x4c, 0xf8, 0x0a, 0xef, 0xdc, 0xb6, 0xcd, 0x0c, + 0xb7, 0xd1, 0x79, 0x02, ], ovk: [ - 0xdf, 0xd3, 0x0f, 0x62, 0xaa, 0x31, 0x9c, 0x6f, 0x53, 0xe2, 0x4c, 0x1f, 0x48, 0xc1, - 0xde, 0x96, 0x1b, 0x90, 0x01, 0xcb, 0x98, 0x8b, 0x80, 0xb3, 0xed, 0xa2, 0x44, 0xfc, - 0xfe, 0xb2, 0x5f, 0x83, + 0x45, 0xcf, 0x1a, 0x1d, 0xf6, 0x62, 0xfe, 0xc0, 0xf7, 0x84, 0x7a, 0x63, 0xa0, 0xd7, + 0x95, 0x51, 0xe1, 0xb0, 0x49, 0xc3, 0xc3, 0x58, 0x7e, 0x68, 0x37, 0xa7, 0x54, 0x45, + 0xa0, 0x04, 0x12, 0xa7, ], dk: [ - 0x23, 0x6b, 0xc3, 0xf3, 0xd0, 0x2f, 0x96, 0x02, 0x80, 0xee, 0xde, 0xde, 0x10, 0x8d, - 0x36, 0x85, 0x04, 0x9f, 0x23, 0x9a, 0xa6, 0x7c, 0x48, 0x55, 0x8f, 0x7c, 0x01, 0xd3, - 0xfd, 0x46, 0x9e, 0xcd, + 0xa8, 0x61, 0xd9, 0xa4, 0x37, 0x61, 0x87, 0xb2, 0xb5, 0xc1, 0x9a, 0x5f, 0x89, 0x6f, + 0xa4, 0x75, 0xaa, 0x0e, 0xd3, 0x8b, 0x99, 0x54, 0xf3, 0x93, 0x8a, 0x04, 0xec, 0x41, + 0xe5, 0x4f, 0xaf, 0x1c, ], default_d: [ - 0x64, 0x24, 0xf7, 0x1a, 0x3a, 0xd1, 0x97, 0x42, 0x64, 0x98, 0xf4, + 0x59, 0x8d, 0x20, 0x0e, 0x50, 0x9e, 0xc2, 0x4b, 0xdc, 0x7f, 0x1c, ], default_pk_d: [ - 0xec, 0xcb, 0x6a, 0x57, 0x80, 0x20, 0x42, 0x37, 0x98, 0x72, 0x32, 0xbc, 0x09, 0x8f, - 0x89, 0xac, 0xc4, 0x75, 0xc3, 0xf7, 0x4b, 0xd6, 0x9e, 0x2f, 0x35, 0xd4, 0x47, 0x36, - 0xf4, 0x8f, 0x3c, 0x14, + 0x68, 0x10, 0x44, 0xee, 0x77, 0xd7, 0xf8, 0x6a, 0x0a, 0x5c, 0x0c, 0xbe, 0x89, 0xa7, + 0xef, 0x3b, 0x3f, 0x5a, 0x6e, 0x85, 0x99, 0x8f, 0x48, 0x48, 0x51, 0xc9, 0x8a, 0x22, + 0x80, 0x18, 0xa0, 0x1e, ], internal_rivk: [ - 0x0a, 0xa9, 0xaa, 0xaa, 0x2c, 0xf1, 0x84, 0x90, 0xdd, 0xf9, 0xa7, 0xe5, 0x21, 0x07, - 0x14, 0x07, 0xea, 0x9b, 0xff, 0xfe, 0x84, 0x34, 0x29, 0xbc, 0x94, 0xa2, 0x88, 0xe8, - 0xa6, 0x06, 0xa7, 0x10, + 0xda, 0x3c, 0xdd, 0x9e, 0x0a, 0x3d, 0x1c, 0x41, 0x3e, 0x51, 0xb5, 0x34, 0x67, 0x7e, + 0x88, 0x3e, 0x85, 0x4b, 0x5f, 0x54, 0xbb, 0xdb, 0xba, 0x05, 0x04, 0xab, 0xb2, 0x2b, + 0x31, 0x5c, 0x4c, 0x1d, ], internal_ivk: [ - 0xa0, 0x6a, 0xbd, 0x29, 0xd5, 0xa1, 0x99, 0xe1, 0xc2, 0x10, 0x25, 0xb0, 0x33, 0x7e, - 0x94, 0x1f, 0x6d, 0x4d, 0x84, 0xeb, 0x7c, 0xc3, 0x5a, 0x39, 0x7f, 0x9e, 0x75, 0x3f, - 0xda, 0xed, 0x81, 0x0d, + 0x29, 0x3f, 0xf5, 0xf5, 0x2b, 0x40, 0xcf, 0x48, 0xeb, 0x4f, 0x21, 0x45, 0x24, 0xad, + 0xed, 0x6b, 0x53, 0x85, 0xf6, 0x09, 0x67, 0x56, 0xec, 0xa3, 0x0d, 0x46, 0xff, 0x47, + 0xa8, 0xc8, 0x6f, 0x0c, ], internal_ovk: [ - 0xf8, 0x2e, 0xb2, 0x49, 0x06, 0xe2, 0x94, 0xff, 0x65, 0x71, 0xac, 0x7d, 0x83, 0x68, - 0xea, 0x82, 0x80, 0xd4, 0x22, 0xf3, 0x47, 0x7c, 0xe7, 0x2a, 0xef, 0x5f, 0x9b, 0x9e, - 0xca, 0x48, 0x46, 0x8f, + 0x0c, 0xfc, 0xe5, 0xec, 0xc4, 0x1f, 0x12, 0x02, 0xcb, 0x61, 0xa4, 0x7f, 0x6d, 0x55, + 0x9a, 0x63, 0x92, 0x25, 0xc5, 0xb4, 0x7a, 0x99, 0x65, 0xc3, 0x02, 0x00, 0xd1, 0xb7, + 0xea, 0x58, 0xc1, 0x30, ], internal_dk: [ - 0x36, 0x56, 0xb5, 0x45, 0xa5, 0x0a, 0x6b, 0x26, 0x28, 0x74, 0x76, 0x64, 0x1b, 0x2b, - 0x68, 0xc6, 0x3c, 0x36, 0xf3, 0x32, 0xe7, 0x45, 0x57, 0xe9, 0x16, 0x05, 0x0f, 0x0b, - 0x91, 0x11, 0x17, 0x9b, + 0x43, 0x81, 0x82, 0x5b, 0x76, 0xeb, 0x8d, 0x47, 0x0a, 0x8b, 0x98, 0xed, 0x53, 0xff, + 0xb4, 0xd1, 0xf2, 0x1e, 0x96, 0x45, 0x0b, 0xe9, 0x4b, 0x15, 0xa8, 0x52, 0x1e, 0xe8, + 0x6f, 0xb6, 0xea, 0xe8, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 14496603531126387959, + note_v: 15839468553911279642, note_rho: [ - 0x32, 0xb4, 0xf4, 0x73, 0xf4, 0x68, 0xa0, 0x08, 0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, - 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe, 0x3f, 0x1a, 0x84, 0xb2, 0x7d, 0xb5, - 0x9a, 0x4a, 0x15, 0x3d, + 0xce, 0xcb, 0x8c, 0xb8, 0xa5, 0xda, 0x01, 0x30, 0x71, 0x52, 0xf1, 0x39, 0x36, 0xa2, + 0x70, 0x57, 0x26, 0x70, 0xdc, 0x82, 0xd3, 0x90, 0x26, 0xc6, 0xcb, 0x4c, 0xd4, 0xb0, + 0xf7, 0xf5, 0xaa, 0x2a, ], note_rseed: [ - 0x88, 0x2d, 0x2b, 0x21, 0x03, 0x59, 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, - 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, 0x89, 0x26, 0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, - 0xcf, 0x4a, 0x0d, 0x9c, + 0x4f, 0x5a, 0x53, 0x41, 0xec, 0x5d, 0xd7, 0x15, 0x40, 0x6f, 0x2f, 0xdd, 0x2a, 0xfa, + 0x73, 0x3f, 0x5f, 0x64, 0x1c, 0x8c, 0x21, 0x86, 0x2a, 0x1b, 0xaf, 0xce, 0x26, 0x09, + 0xd9, 0xee, 0xcf, 0xa1, ], note_cmx: [ - 0x03, 0xce, 0x20, 0xce, 0xa1, 0x94, 0xb7, 0x55, 0x9a, 0x8a, 0x90, 0x47, 0x1d, 0x28, - 0xa3, 0xc0, 0x53, 0xc3, 0x72, 0x0a, 0xd4, 0x9f, 0x40, 0xd2, 0x7c, 0x2d, 0xcc, 0xe3, - 0x35, 0x00, 0x56, 0x16, + 0x1b, 0x83, 0x10, 0x6d, 0xf8, 0x12, 0xf5, 0xb3, 0x24, 0xbc, 0x8d, 0xc9, 0x87, 0x02, + 0x52, 0xfd, 0x7a, 0x44, 0xf2, 0xd7, 0x5b, 0xf5, 0x54, 0x41, 0xac, 0x92, 0x5b, 0x45, + 0x82, 0xf9, 0x75, 0x17, ], note_nf: [ - 0x16, 0xfa, 0x2c, 0x34, 0x97, 0xfc, 0x09, 0xad, 0x90, 0xdd, 0x34, 0x92, 0x02, 0xa2, - 0x4b, 0x69, 0x89, 0x2d, 0xc8, 0x06, 0x29, 0xb2, 0xd1, 0xbf, 0xeb, 0xaf, 0x41, 0x70, - 0x8f, 0x0f, 0xb1, 0x0c, + 0x4b, 0xf3, 0xd9, 0x9e, 0x14, 0xdb, 0x5c, 0xa1, 0xb5, 0x81, 0x8d, 0x93, 0x37, 0xe9, + 0x26, 0xb1, 0x3c, 0x55, 0x94, 0x12, 0xd5, 0x61, 0xb6, 0xc7, 0x30, 0x53, 0xe2, 0xc7, + 0xb2, 0x08, 0x5a, 0x2d, ], }, TestVector { sk: [ - 0x73, 0x1e, 0x98, 0x5d, 0x99, 0x58, 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, - 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0, 0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, - 0xba, 0x18, 0xd1, 0xdb, + 0x58, 0xcf, 0xb5, 0xcd, 0x79, 0xf8, 0x80, 0x08, 0xe3, 0x15, 0xdc, 0x7d, 0x83, 0x88, + 0xe7, 0x6c, 0x17, 0x82, 0xfd, 0x27, 0x95, 0xd1, 0x8a, 0x76, 0x36, 0x24, 0xc2, 0x5f, + 0xa9, 0x59, 0xcc, 0x97, ], ask: [ - 0x42, 0x6a, 0x78, 0x44, 0xf3, 0x05, 0xb9, 0xd4, 0xe0, 0x7e, 0xa5, 0x2a, 0x39, 0x00, - 0x1c, 0x9b, 0x33, 0x6c, 0xfc, 0x0d, 0x6f, 0xa1, 0x5e, 0xf3, 0xd1, 0x1c, 0x3d, 0x7b, - 0x74, 0xf0, 0x8c, 0x2d, + 0x74, 0xef, 0xaa, 0xff, 0x27, 0x9c, 0xde, 0x93, 0x36, 0x11, 0x7a, 0xa4, 0x68, 0xb4, + 0xed, 0xdb, 0x70, 0x38, 0xa1, 0x22, 0xef, 0x86, 0x7d, 0xba, 0x05, 0x3e, 0x33, 0x55, + 0x68, 0x0a, 0x8c, 0x3c, ], ak: [ - 0xb1, 0xe0, 0xac, 0xbc, 0x69, 0xbf, 0x37, 0x7b, 0x85, 0xab, 0xf0, 0xf5, 0xa1, 0x0b, - 0xe7, 0x2c, 0x3b, 0x64, 0x00, 0x06, 0xff, 0x08, 0x50, 0x52, 0x80, 0xe4, 0xf0, 0x0f, - 0xad, 0xf7, 0x63, 0x28, + 0xc4, 0x51, 0x8d, 0x3c, 0xde, 0xa6, 0x55, 0xa3, 0x2d, 0xf8, 0xe3, 0xf5, 0xc1, 0x51, + 0xb5, 0x42, 0x32, 0x85, 0x31, 0xca, 0x01, 0xa6, 0x3f, 0x3c, 0x03, 0xa3, 0xc2, 0x4e, + 0xa7, 0x32, 0x82, 0x3a, ], isk: [ - 0x71, 0xd0, 0x64, 0xaa, 0xa0, 0x82, 0x63, 0xb8, 0xe4, 0xc3, 0xed, 0x70, 0x3c, 0x6f, - 0x54, 0x25, 0x4a, 0x88, 0x8c, 0x36, 0xec, 0x69, 0x86, 0x62, 0xf7, 0x1f, 0xbb, 0xf4, - 0x26, 0xd9, 0x09, 0x28, + 0x48, 0x9c, 0xe7, 0x57, 0x45, 0x82, 0x4b, 0x77, 0x86, 0x8c, 0x53, 0x23, 0x9c, 0xfb, + 0xdf, 0x73, 0xca, 0xec, 0x65, 0x60, 0x40, 0x37, 0x31, 0x4f, 0xaa, 0xce, 0xb5, 0x62, + 0x18, 0xc6, 0xbd, 0x30, ], ik: [ - 0x12, 0xb3, 0xab, 0xff, 0x96, 0x75, 0x20, 0x9e, 0x94, 0x54, 0x07, 0x0c, 0x14, 0xac, - 0x15, 0x54, 0x65, 0xae, 0x83, 0xbe, 0x2c, 0x39, 0x46, 0x63, 0x5e, 0x38, 0x77, 0xba, - 0x67, 0xdf, 0x49, 0x12, + 0xed, 0x56, 0xef, 0x8b, 0x55, 0x28, 0x00, 0x0f, 0xc2, 0xee, 0xf3, 0x33, 0x50, 0x8f, + 0x4c, 0x32, 0x71, 0x62, 0xd8, 0x96, 0x3b, 0xad, 0x50, 0xcc, 0x55, 0xdc, 0x03, 0x7d, + 0xb9, 0x60, 0x7f, 0x52, ], nk: [ - 0xcf, 0x36, 0xad, 0x6a, 0x06, 0x6c, 0xd2, 0x13, 0xe1, 0xd7, 0x67, 0xab, 0x07, 0x1d, - 0xc1, 0x16, 0x78, 0x85, 0xc4, 0x16, 0x8b, 0xc2, 0xe2, 0x17, 0x54, 0x48, 0x56, 0x3a, - 0xd1, 0x3f, 0x33, 0x3d, + 0x76, 0xff, 0xc1, 0xbb, 0x8d, 0xd7, 0xfb, 0x48, 0x7d, 0x48, 0xd0, 0x94, 0x29, 0x66, + 0x0b, 0xbc, 0x1d, 0xfc, 0xbf, 0x57, 0xc4, 0xa5, 0xa3, 0x21, 0x33, 0x24, 0x33, 0x44, + 0x70, 0xed, 0xdf, 0x33, ], rivk: [ - 0xc4, 0x1b, 0xba, 0xd3, 0x51, 0x05, 0xa8, 0x03, 0x14, 0xb7, 0x96, 0x24, 0xb6, 0x75, - 0x24, 0x12, 0x20, 0xb3, 0x31, 0xf1, 0x25, 0x92, 0x61, 0x7b, 0xdb, 0x70, 0x5b, 0xfc, - 0xce, 0x72, 0xae, 0x38, + 0x22, 0xe2, 0xf3, 0x90, 0x11, 0xe6, 0x70, 0xc8, 0x0f, 0xba, 0xc8, 0x91, 0x59, 0xac, + 0x63, 0x4d, 0x84, 0xd7, 0xc1, 0x3e, 0xbe, 0xfb, 0x97, 0x3b, 0xa4, 0x1f, 0x0c, 0x79, + 0xf0, 0x33, 0xfc, 0x3f, ], ivk: [ - 0xf7, 0x9f, 0xe8, 0x02, 0xe4, 0xd2, 0x43, 0x07, 0xa6, 0xaa, 0xf8, 0x5d, 0x19, 0xf5, - 0xe0, 0x83, 0x37, 0x40, 0xba, 0xe5, 0x98, 0xdc, 0x7c, 0x88, 0x0a, 0xc6, 0x09, 0x63, - 0x1d, 0xe1, 0x58, 0x19, + 0xe6, 0x80, 0xf5, 0xa7, 0x15, 0xb3, 0x2b, 0x9e, 0x1a, 0x14, 0x67, 0x9f, 0x11, 0x16, + 0xf1, 0x13, 0xaa, 0x04, 0x93, 0xf3, 0x82, 0x1b, 0x10, 0x8c, 0xa7, 0xe1, 0xc0, 0x71, + 0xad, 0x75, 0x2d, 0x22, ], ovk: [ - 0xf9, 0x63, 0x66, 0xbc, 0x6e, 0xab, 0xd2, 0x32, 0x54, 0x9e, 0xbb, 0x43, 0xb4, 0xed, - 0x6f, 0xd8, 0x1d, 0x33, 0x03, 0x73, 0xc5, 0xb5, 0x66, 0x90, 0x4e, 0x9a, 0xf1, 0x1a, - 0x6b, 0xab, 0x8d, 0x77, + 0x2a, 0x34, 0xab, 0x11, 0xc4, 0x0c, 0x6b, 0x3b, 0x28, 0x54, 0x56, 0xa6, 0x91, 0x54, + 0xcb, 0xe4, 0x4c, 0xba, 0x01, 0xda, 0x6d, 0xb0, 0xc2, 0xb2, 0x2b, 0x84, 0xca, 0x27, + 0x2b, 0xae, 0x01, 0xad, ], dk: [ - 0x80, 0x3e, 0x34, 0x85, 0x73, 0x02, 0x2b, 0xf8, 0x93, 0x2f, 0x23, 0xee, 0x7a, 0x32, - 0x5e, 0xa2, 0x83, 0x87, 0x9c, 0x65, 0x24, 0x12, 0xb8, 0x60, 0x6b, 0xe3, 0x19, 0x8c, - 0x4b, 0x78, 0x2c, 0x47, + 0xfa, 0xaa, 0xb4, 0xb9, 0x32, 0x46, 0x23, 0xc6, 0xc8, 0x6b, 0xd5, 0xdb, 0x70, 0xa7, + 0x18, 0xd9, 0x0b, 0xc0, 0xf1, 0x5b, 0x2b, 0x39, 0xeb, 0xfa, 0x82, 0xb5, 0xb1, 0xcc, + 0x14, 0x67, 0x0c, 0xbe, ], default_d: [ - 0xdb, 0x8c, 0x30, 0x55, 0x24, 0xbc, 0x0d, 0xea, 0xa8, 0x5d, 0x97, + 0x66, 0x4c, 0xab, 0xf8, 0xf7, 0x68, 0x93, 0xcb, 0x8d, 0xa7, 0x84, ], default_pk_d: [ - 0x04, 0xea, 0x8c, 0x13, 0x20, 0xff, 0xbb, 0xad, 0xfe, 0x96, 0xf0, 0xc6, 0xff, 0x16, - 0xb6, 0x07, 0x11, 0x1b, 0x55, 0x83, 0xbf, 0xb6, 0xf1, 0xea, 0x45, 0x27, 0x5e, 0xf2, - 0xaa, 0x2d, 0x87, 0x9b, + 0x07, 0x7c, 0x84, 0x57, 0x8b, 0x1d, 0xae, 0x2f, 0x80, 0x69, 0xef, 0x67, 0xd2, 0x87, + 0x71, 0x8d, 0xaf, 0xf5, 0xa1, 0x69, 0x4e, 0x1a, 0x8e, 0xa2, 0x36, 0xc9, 0xe6, 0x94, + 0x61, 0x5f, 0xb8, 0x16, ], internal_rivk: [ - 0x9e, 0x45, 0x2a, 0xb7, 0x2c, 0x6c, 0x8e, 0xcc, 0xf2, 0xe4, 0x39, 0xa0, 0xce, 0xc0, - 0xa0, 0xac, 0x39, 0x4a, 0x1a, 0xa1, 0x21, 0xac, 0x60, 0x32, 0xa7, 0xeb, 0xc2, 0x9d, - 0xb4, 0x85, 0x62, 0x26, + 0xc4, 0x01, 0xbc, 0x90, 0x7a, 0xaa, 0xed, 0xd1, 0x3b, 0x1f, 0xa7, 0x0d, 0x7a, 0xb2, + 0x8d, 0x71, 0x3b, 0x46, 0x38, 0xeb, 0xfb, 0xc8, 0xf9, 0xcc, 0x1d, 0xae, 0xd5, 0xac, + 0x2b, 0x76, 0x75, 0x33, ], internal_ivk: [ - 0x3b, 0xa9, 0x3b, 0x0f, 0xc3, 0xf2, 0x7a, 0xb2, 0x17, 0x63, 0x5d, 0x03, 0xf9, 0x0d, - 0x0b, 0x84, 0x2d, 0x99, 0xa1, 0x2c, 0xdc, 0x37, 0xa8, 0x1c, 0x18, 0x1e, 0xc0, 0x18, - 0xe5, 0xf4, 0x4c, 0x11, + 0xea, 0x9b, 0xeb, 0x2d, 0x19, 0x6a, 0xd4, 0x79, 0x69, 0xf2, 0x03, 0xdd, 0x28, 0xa0, + 0xfb, 0xe2, 0x4b, 0x98, 0x12, 0xb1, 0x15, 0x5b, 0x17, 0x01, 0x96, 0x36, 0x6a, 0xcd, + 0x62, 0xf5, 0xeb, 0x0c, ], internal_ovk: [ - 0xe3, 0xc7, 0xf8, 0x6c, 0x1b, 0x23, 0x83, 0xb3, 0xbd, 0x41, 0xad, 0x1a, 0x8f, 0x11, - 0xef, 0xa2, 0x55, 0x4a, 0x41, 0x0a, 0x98, 0xc8, 0x92, 0x07, 0xae, 0xb4, 0x31, 0x9b, - 0x1a, 0xbd, 0x78, 0x79, + 0x2f, 0x6d, 0x74, 0x4f, 0x40, 0xd6, 0xdc, 0xe6, 0x5e, 0x33, 0x5d, 0x3c, 0xb3, 0x96, + 0xc5, 0xaf, 0x54, 0xf0, 0xf7, 0xd5, 0x4f, 0xb4, 0x37, 0xec, 0x8e, 0x20, 0x29, 0x28, + 0x05, 0x8e, 0xfa, 0xdf, ], internal_dk: [ - 0xd7, 0x1a, 0x68, 0xcf, 0xd6, 0xc7, 0x68, 0xf4, 0x30, 0x73, 0xf6, 0x98, 0x18, 0x9a, - 0xc7, 0x5e, 0xe4, 0x21, 0xb4, 0x20, 0x4b, 0xb6, 0xf3, 0xc5, 0xd0, 0xfc, 0x43, 0x28, - 0x49, 0xaa, 0x71, 0x61, + 0x9f, 0xec, 0x61, 0xd0, 0x20, 0xb9, 0x29, 0x37, 0xbd, 0xf3, 0xc3, 0xce, 0x09, 0x43, + 0x3d, 0xdf, 0x01, 0xd4, 0xab, 0xe7, 0x43, 0x93, 0x94, 0x6e, 0x49, 0xcd, 0x79, 0xd1, + 0x19, 0x86, 0xb9, 0xfe, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 6792346249443327211, + note_v: 4573834453415770104, note_rho: [ - 0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, 0xbc, - 0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, 0xe7, - 0x1a, 0x02, 0xaf, 0x11, + 0x21, 0xa9, 0xfb, 0x80, 0xad, 0x03, 0xbc, 0x0c, 0xda, 0x4a, 0x44, 0x94, 0x6c, 0x00, + 0xe1, 0xb1, 0xa1, 0xdf, 0x0e, 0x5b, 0x87, 0xb5, 0xbe, 0xce, 0x47, 0x7a, 0x70, 0x96, + 0x49, 0xe9, 0x50, 0x06, ], note_rseed: [ - 0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, 0xb1, 0xfc, 0xe4, 0x67, 0x50, - 0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, 0xc3, 0x82, 0x85, 0x7d, 0xee, - 0xcc, 0x40, 0xa9, 0x8d, + 0x05, 0x91, 0x39, 0x48, 0x12, 0x95, 0x1e, 0x1f, 0xe3, 0x89, 0x5b, 0x8c, 0xc3, 0xd1, + 0x4d, 0x2c, 0xf6, 0x55, 0x6d, 0xf6, 0xed, 0x4b, 0x4d, 0xdd, 0x3d, 0x9a, 0x69, 0xf5, + 0x33, 0x57, 0xd7, 0x76, ], note_cmx: [ - 0xa9, 0xb1, 0x1b, 0xaf, 0x30, 0x34, 0xb6, 0x5c, 0x64, 0x24, 0x84, 0x1b, 0xfe, 0x02, - 0x3f, 0x8e, 0xda, 0x13, 0x13, 0xc3, 0x0a, 0xa2, 0x7d, 0xe9, 0x2e, 0x21, 0xa1, 0x08, - 0x31, 0x6e, 0x82, 0x19, + 0xbb, 0x2d, 0xd3, 0x29, 0xdf, 0xca, 0x48, 0xdc, 0x11, 0x56, 0x36, 0x58, 0xd0, 0x7e, + 0x20, 0x4a, 0x1d, 0x21, 0x2d, 0x20, 0x27, 0xe1, 0x45, 0x7c, 0xe6, 0x96, 0x8c, 0xdf, + 0xb0, 0x07, 0x7e, 0x04, ], note_nf: [ - 0x72, 0xd6, 0x30, 0x89, 0x60, 0x35, 0x1f, 0x7b, 0x26, 0xfa, 0x64, 0x60, 0x3f, 0xe4, - 0xdf, 0xd8, 0x67, 0xbd, 0x5e, 0xb3, 0x67, 0xba, 0x2b, 0x7c, 0xa4, 0x91, 0xc9, 0x23, - 0xc0, 0xea, 0xd2, 0x22, + 0xd4, 0x0c, 0xe3, 0x47, 0xb2, 0x3e, 0x26, 0x36, 0xc2, 0xb4, 0xc5, 0x43, 0x39, 0x50, + 0x26, 0xab, 0xb4, 0xa1, 0x5f, 0x28, 0xf9, 0x0a, 0x67, 0xb7, 0x08, 0xd6, 0x4b, 0x22, + 0x6f, 0x3a, 0x39, 0x31, ], }, TestVector { sk: [ - 0x5f, 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0x2d, 0xd2, 0x1a, 0xfd, 0xbb, 0x5d, 0x47, - 0xfa, 0x9a, 0x6d, 0xd9, 0x84, 0xd5, 0x67, 0xdb, 0x28, 0x57, 0xb9, 0x27, 0xb7, 0xfa, - 0xe2, 0xdb, 0x58, 0x71, + 0x7f, 0x4f, 0x5c, 0xcb, 0xdb, 0xc5, 0x96, 0x63, 0x12, 0x77, 0xf8, 0xfe, 0xcd, 0x08, + 0xcb, 0x05, 0x6b, 0x95, 0xe3, 0x02, 0x5b, 0x97, 0x92, 0xff, 0xf7, 0xf2, 0x44, 0xfc, + 0x71, 0x62, 0x69, 0xb9, ], ask: [ - 0x11, 0x80, 0x73, 0x28, 0x51, 0x64, 0xe6, 0x55, 0x73, 0x58, 0xfb, 0xc4, 0x1a, 0x81, - 0x35, 0xcb, 0x06, 0x2f, 0x86, 0x76, 0xcb, 0x61, 0xf9, 0xaa, 0x52, 0xd1, 0x9a, 0x09, - 0xfa, 0xc5, 0x58, 0x02, + 0x0a, 0xfd, 0x61, 0xd4, 0x12, 0x57, 0xb5, 0xe9, 0x36, 0xb9, 0x29, 0x29, 0xa3, 0xe1, + 0xb8, 0x7d, 0x60, 0x89, 0x7c, 0xb3, 0xdc, 0x8e, 0x77, 0x3f, 0x4f, 0xa1, 0xef, 0x40, + 0xef, 0xb5, 0x4b, 0x04, ], ak: [ - 0x0d, 0x26, 0x2d, 0xe3, 0x60, 0x94, 0x33, 0xfe, 0x5b, 0x7c, 0x86, 0x2b, 0xc4, 0x8e, - 0xf5, 0x6d, 0x83, 0x20, 0x09, 0xf7, 0x24, 0x2e, 0x1f, 0x7c, 0x77, 0x0a, 0x12, 0x24, - 0x1d, 0xfa, 0x28, 0x07, + 0x84, 0x7e, 0xc5, 0xb1, 0xe3, 0xdd, 0xfd, 0x93, 0xca, 0x0c, 0x67, 0xea, 0x48, 0x1b, + 0x40, 0x5b, 0xae, 0xef, 0x48, 0xb0, 0xf2, 0x7f, 0x87, 0xb8, 0x1f, 0xed, 0x32, 0xae, + 0x56, 0x31, 0x6f, 0x04, ], isk: [ - 0x44, 0x36, 0x1a, 0x7b, 0xa6, 0xa1, 0xaa, 0x17, 0x8e, 0x72, 0xaf, 0x47, 0xbd, 0xc1, - 0x60, 0x40, 0xce, 0x1c, 0x54, 0xdd, 0x4b, 0x56, 0x33, 0x21, 0x55, 0xba, 0x9d, 0x04, - 0x09, 0x71, 0xd0, 0x07, + 0x26, 0xd6, 0x2e, 0x95, 0x96, 0xfa, 0x82, 0x5c, 0x6b, 0xf2, 0x1a, 0xff, 0x9e, 0x68, + 0x62, 0x5a, 0x19, 0x24, 0x40, 0xea, 0x06, 0x82, 0x81, 0x23, 0xd9, 0x78, 0x84, 0x80, + 0x6f, 0x15, 0xfa, 0x08, ], ik: [ - 0x1f, 0x17, 0x2d, 0x79, 0xae, 0xdc, 0xc2, 0x06, 0x8c, 0x3a, 0x09, 0x08, 0x93, 0xe1, - 0xa1, 0x75, 0xd9, 0xb5, 0x78, 0xf8, 0x91, 0xaf, 0x9a, 0xb6, 0x8d, 0x4f, 0xe1, 0xe9, - 0x05, 0xa3, 0xb2, 0x11, + 0x95, 0x9c, 0x44, 0x8d, 0xaf, 0xb6, 0xb7, 0xc2, 0x54, 0x90, 0x42, 0xdd, 0x75, 0x7a, + 0x81, 0xfa, 0x16, 0xca, 0xd4, 0xd2, 0x7f, 0xc1, 0x5f, 0x45, 0x33, 0xcd, 0xe2, 0x0c, + 0xc5, 0xb5, 0xcd, 0xc9, ], nk: [ - 0x51, 0xba, 0xf3, 0x33, 0xcf, 0xf1, 0xf2, 0xd0, 0xc7, 0xe3, 0xcf, 0xf4, 0xd3, 0x01, - 0x29, 0x9d, 0xc1, 0xef, 0xe9, 0x83, 0x00, 0x31, 0x4a, 0x54, 0x19, 0x38, 0x02, 0x9b, - 0x45, 0xcc, 0x15, 0x21, + 0xd7, 0xd8, 0xf3, 0xd5, 0x18, 0x22, 0xd3, 0x4a, 0xdf, 0x86, 0xeb, 0xd3, 0x53, 0x36, + 0x47, 0x73, 0x2c, 0x03, 0xf6, 0x42, 0xd6, 0xed, 0x06, 0xff, 0x61, 0xd2, 0x50, 0xd6, + 0xba, 0xfd, 0x59, 0x37, ], rivk: [ - 0x22, 0x8f, 0xeb, 0x79, 0x21, 0x98, 0x73, 0xc7, 0xa7, 0x60, 0x6e, 0x52, 0x97, 0x3c, - 0x85, 0xf4, 0x60, 0x46, 0x5a, 0x60, 0x59, 0x08, 0x39, 0x19, 0xed, 0x73, 0xeb, 0x80, - 0x5c, 0x11, 0x83, 0x01, + 0xae, 0xea, 0xd1, 0x3e, 0x25, 0x36, 0xe8, 0xcb, 0xa6, 0x24, 0x46, 0xd8, 0xff, 0x10, + 0x99, 0x88, 0xce, 0xa9, 0xb2, 0x57, 0xce, 0xaf, 0xc8, 0xd2, 0x0b, 0x85, 0x07, 0xcc, + 0xc9, 0x81, 0x58, 0x2a, ], ivk: [ - 0x76, 0xf4, 0x9c, 0xf8, 0xa3, 0x19, 0x21, 0x85, 0x61, 0x6a, 0x9a, 0x0d, 0xa0, 0xc7, - 0x6e, 0xc2, 0xc2, 0x75, 0x61, 0x59, 0xbc, 0xe1, 0x86, 0xa1, 0x86, 0x2b, 0x6e, 0x6e, - 0x59, 0x44, 0x2d, 0x11, + 0x83, 0xbb, 0x91, 0x72, 0x72, 0xb0, 0xa0, 0x4b, 0x78, 0x21, 0xfb, 0x8e, 0xef, 0xd5, + 0x7b, 0xdb, 0x15, 0xa0, 0x28, 0x28, 0x73, 0x95, 0x46, 0x28, 0x5e, 0x7f, 0x19, 0x78, + 0x17, 0x43, 0xaa, 0x10, ], ovk: [ - 0xeb, 0x72, 0xb6, 0xc3, 0x1e, 0x83, 0x7f, 0xd8, 0x37, 0xaa, 0xcb, 0x61, 0xfa, 0xba, - 0xce, 0x75, 0xa1, 0x9d, 0xd9, 0xdd, 0x5b, 0x4b, 0x3a, 0x3e, 0xe7, 0x23, 0xc1, 0x4d, - 0xa7, 0x7b, 0x4b, 0xe8, + 0x48, 0x25, 0xc8, 0x9b, 0xc8, 0xef, 0x4d, 0x75, 0x50, 0xa8, 0xdc, 0x1b, 0xda, 0x47, + 0xc4, 0xe4, 0x1a, 0x30, 0xca, 0x56, 0x72, 0x26, 0xd0, 0xb3, 0x78, 0xb0, 0xb9, 0xcc, + 0xb2, 0xfb, 0x36, 0xe5, ], dk: [ - 0xee, 0x19, 0xf8, 0xdd, 0xd9, 0xda, 0x06, 0x34, 0x24, 0x51, 0x43, 0xc4, 0xb4, 0x3a, - 0xfc, 0x7d, 0x78, 0xc5, 0x49, 0xc8, 0x20, 0x54, 0xa9, 0xd8, 0x40, 0x07, 0xb5, 0x62, - 0x17, 0xdb, 0xfd, 0xd6, + 0x17, 0x84, 0x93, 0x0e, 0xf3, 0xd2, 0x6a, 0xce, 0x1e, 0xad, 0xb7, 0x0b, 0x38, 0x81, + 0x0b, 0x98, 0xf1, 0x82, 0x33, 0x8d, 0x54, 0xff, 0xe8, 0x37, 0x78, 0xf2, 0x7b, 0xe2, + 0xd1, 0x20, 0x67, 0xc0, ], default_d: [ - 0xaa, 0xe3, 0x6e, 0x09, 0x4d, 0xe0, 0x7b, 0xc1, 0x6f, 0x89, 0x8e, + 0x46, 0x3b, 0x71, 0x6d, 0x24, 0xdd, 0x01, 0x02, 0x03, 0xa7, 0x29, ], default_pk_d: [ - 0xb6, 0x53, 0x3d, 0xcb, 0xff, 0xf0, 0xf6, 0xc1, 0xce, 0xef, 0xa8, 0x47, 0x99, 0xbd, - 0xa3, 0xde, 0x73, 0x34, 0x32, 0x6c, 0xcd, 0x65, 0xf7, 0xce, 0x92, 0xff, 0x3d, 0x9e, - 0x6e, 0x1f, 0x14, 0x0b, + 0x9e, 0x22, 0xd0, 0x82, 0xbf, 0xbe, 0x2f, 0x05, 0x20, 0x69, 0x13, 0xa8, 0x63, 0x15, + 0xf0, 0x80, 0xbb, 0x87, 0xe7, 0x87, 0xff, 0x51, 0x84, 0x53, 0xb0, 0x85, 0x0b, 0xc3, + 0x57, 0xd9, 0x18, 0x06, ], internal_rivk: [ - 0x25, 0x44, 0x06, 0x72, 0x3b, 0x06, 0x67, 0xaf, 0x27, 0xe5, 0x1c, 0xb3, 0xce, 0x8f, - 0xa1, 0x38, 0x81, 0x64, 0xd9, 0x43, 0x76, 0xc8, 0x50, 0xbd, 0xdb, 0x39, 0xe9, 0xbe, - 0xa5, 0xfa, 0x96, 0x05, + 0xdf, 0x5f, 0x4f, 0x62, 0x55, 0x28, 0xd5, 0x6b, 0x2e, 0x64, 0xaf, 0x93, 0xb4, 0x79, + 0xbf, 0x1c, 0x3b, 0x37, 0xab, 0x8a, 0xcb, 0x9b, 0x9d, 0x4a, 0x75, 0x75, 0xcc, 0x75, + 0x2a, 0x9c, 0x08, 0x1b, ], internal_ivk: [ - 0xba, 0xd4, 0x83, 0x7b, 0xa7, 0x88, 0x22, 0xb8, 0xb1, 0x65, 0xb0, 0xa1, 0x6e, 0x11, - 0x04, 0xc7, 0x05, 0xc3, 0xc0, 0xe3, 0x82, 0xd3, 0xf1, 0x3c, 0x19, 0x5c, 0x0e, 0xf3, - 0x11, 0xbb, 0x80, 0x04, + 0xe3, 0x3c, 0xea, 0x19, 0xf7, 0x6a, 0x3b, 0xdc, 0x49, 0xc3, 0x2e, 0x32, 0x2f, 0xeb, + 0x87, 0x0e, 0xd2, 0xae, 0x18, 0x57, 0xca, 0x47, 0x03, 0x4a, 0x01, 0x60, 0x40, 0x0e, + 0x9c, 0xeb, 0x4c, 0x2b, ], internal_ovk: [ - 0xb9, 0x11, 0x3a, 0x95, 0x2d, 0xcc, 0x1e, 0x15, 0xc3, 0x4d, 0x13, 0x66, 0x03, 0xa2, - 0xef, 0x25, 0x4a, 0x38, 0x75, 0x5a, 0x55, 0x7f, 0xa9, 0xf8, 0x8c, 0x14, 0x3b, 0xd3, - 0x07, 0x64, 0x41, 0xb0, + 0xc9, 0x3d, 0x92, 0x4f, 0x45, 0x96, 0x08, 0xef, 0x68, 0xa6, 0x36, 0xe2, 0xe2, 0xfe, + 0xd5, 0xeb, 0x9b, 0xe3, 0x8c, 0xeb, 0xae, 0x57, 0x1d, 0x0e, 0xeb, 0xf3, 0xe8, 0xa5, + 0x37, 0x4f, 0x99, 0x71, ], internal_dk: [ - 0x02, 0xb5, 0x2c, 0x6e, 0xd9, 0xad, 0x49, 0xfb, 0x38, 0xe4, 0x44, 0x7c, 0x69, 0xb5, - 0x70, 0xeb, 0xd0, 0x55, 0xe4, 0xc7, 0xfd, 0x91, 0xc0, 0x20, 0xff, 0x43, 0x46, 0x1d, - 0x14, 0xe0, 0x2f, 0x29, + 0xec, 0xe1, 0xd3, 0x58, 0x8f, 0xc5, 0x0a, 0xa1, 0xf1, 0x06, 0x5d, 0x93, 0xf5, 0xd8, + 0xcf, 0xca, 0xf1, 0x35, 0x3a, 0xe1, 0xab, 0x39, 0x58, 0x9a, 0xb9, 0x28, 0xdf, 0xda, + 0xfe, 0x36, 0x84, 0x43, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 4079549063511228677, + note_v: 18438745196586160858, note_rho: [ - 0x26, 0x70, 0xdc, 0x82, 0xd3, 0x90, 0x26, 0xc6, 0xcb, 0x4c, 0xd4, 0xb0, 0xf7, 0xf5, - 0xaa, 0x2a, 0x4f, 0x5a, 0x53, 0x41, 0xec, 0x5d, 0xd7, 0x15, 0x40, 0x6f, 0x2f, 0xdd, - 0x2a, 0xfa, 0x73, 0x3f, + 0x1a, 0xbd, 0x5c, 0xe4, 0xfd, 0xdf, 0xcc, 0xfc, 0x3a, 0x61, 0x28, 0xae, 0xf7, 0x84, + 0xa6, 0x46, 0x10, 0xa8, 0x9d, 0x1a, 0x70, 0x99, 0x21, 0x6d, 0x08, 0x14, 0xd3, 0xa2, + 0xd4, 0x52, 0x43, 0x1c, ], note_rseed: [ - 0x5f, 0x64, 0x1c, 0x8c, 0x21, 0x86, 0x2a, 0x1b, 0xaf, 0xce, 0x26, 0x09, 0xd9, 0xee, - 0xcf, 0xa1, 0x58, 0xcf, 0xb5, 0xcd, 0x79, 0xf8, 0x80, 0x08, 0xe3, 0x15, 0xdc, 0x7d, - 0x83, 0x88, 0xe7, 0x6c, + 0x32, 0xd4, 0x11, 0xac, 0x1c, 0xce, 0x82, 0xad, 0x02, 0x29, 0x40, 0x7b, 0xbc, 0x48, + 0x98, 0x56, 0x75, 0xe3, 0xf8, 0x74, 0xa4, 0x53, 0x3f, 0x1d, 0x63, 0xa8, 0x4d, 0xfa, + 0x3e, 0x0f, 0x46, 0x0f, ], note_cmx: [ - 0x0f, 0xfb, 0xca, 0x1d, 0x59, 0x21, 0xfa, 0x0a, 0x8c, 0x51, 0x16, 0xae, 0x13, 0x7e, - 0x37, 0xf2, 0xc1, 0x18, 0xd5, 0x21, 0x25, 0x62, 0x8d, 0x8a, 0x3f, 0x41, 0x2c, 0xe0, - 0xe6, 0x53, 0x0e, 0x04, + 0xd6, 0x3a, 0x49, 0x61, 0x70, 0x68, 0x72, 0xdd, 0xf4, 0x0b, 0x6d, 0xd2, 0xa9, 0xc9, + 0xc1, 0xdb, 0xec, 0xb9, 0x7e, 0x72, 0xf0, 0x3f, 0x2f, 0x5a, 0xdd, 0x8b, 0x63, 0x53, + 0xe3, 0x9e, 0x59, 0x10, ], note_nf: [ - 0xe6, 0x2b, 0x8e, 0xd8, 0x35, 0x40, 0x14, 0x6c, 0xd2, 0x3c, 0xac, 0x74, 0xee, 0xd7, - 0xd7, 0x73, 0xd8, 0x02, 0x24, 0xa5, 0xaa, 0x30, 0xd6, 0x8e, 0x35, 0x57, 0x2e, 0xe8, - 0x83, 0xd1, 0xb7, 0x04, + 0x7e, 0xbe, 0xaa, 0x1a, 0x59, 0xed, 0x46, 0x01, 0x45, 0x8b, 0xa4, 0x6d, 0xcc, 0x96, + 0x2e, 0xd8, 0x1c, 0x15, 0xc7, 0x7f, 0x7e, 0x44, 0x52, 0x48, 0xe4, 0xfb, 0x52, 0x1e, + 0x59, 0xaa, 0x23, 0x1c, ], }, TestVector { sk: [ - 0x17, 0x82, 0xfd, 0x27, 0x95, 0xd1, 0x8a, 0x76, 0x36, 0x24, 0xc2, 0x5f, 0xa9, 0x59, - 0xcc, 0x97, 0x48, 0x9c, 0xe7, 0x57, 0x45, 0x82, 0x4b, 0x77, 0x86, 0x8c, 0x53, 0x23, - 0x9c, 0xfb, 0xdf, 0x73, + 0xe2, 0xf5, 0x7e, 0x34, 0xfb, 0xc7, 0x54, 0x23, 0xc3, 0x73, 0x7f, 0x5b, 0x2a, 0x06, + 0x15, 0xf5, 0x72, 0x2d, 0xb0, 0x41, 0xa3, 0xef, 0x66, 0xfa, 0x48, 0x3a, 0xfd, 0x3c, + 0x2e, 0x19, 0xe5, 0x94, ], ask: [ - 0xf6, 0xef, 0x32, 0x8d, 0x24, 0x76, 0x1d, 0x6d, 0x3c, 0xcd, 0x25, 0xd4, 0x71, 0x96, - 0xe8, 0x10, 0x9c, 0x03, 0x8f, 0xe1, 0x7c, 0x59, 0xa7, 0xf0, 0x5b, 0x98, 0xd6, 0x6b, - 0xeb, 0xc6, 0x41, 0x24, + 0x12, 0x4b, 0x26, 0x4c, 0x66, 0x07, 0xd3, 0x43, 0x5b, 0x4b, 0xbb, 0x10, 0x39, 0x31, + 0x4b, 0x39, 0x60, 0x4f, 0x06, 0x54, 0x10, 0x0e, 0xa9, 0x0a, 0x3f, 0x9b, 0xfa, 0xe5, + 0x4a, 0x45, 0xa8, 0x36, ], ak: [ - 0xd1, 0x17, 0x87, 0xca, 0x58, 0x2f, 0x94, 0x8e, 0x45, 0x07, 0x18, 0xb3, 0x69, 0x98, - 0xdf, 0x28, 0xbb, 0x0f, 0x10, 0x21, 0xea, 0x84, 0x3f, 0x86, 0x7f, 0x8a, 0x17, 0x0f, - 0x5c, 0x33, 0x90, 0x1f, + 0xbe, 0xbc, 0xa2, 0xb4, 0x46, 0x40, 0x91, 0x6a, 0xbf, 0x7e, 0xab, 0xb3, 0x44, 0x48, + 0xef, 0x19, 0xec, 0x7c, 0x02, 0x32, 0x8b, 0x12, 0x5e, 0xb5, 0xa1, 0x04, 0xcc, 0xf3, + 0x08, 0xfb, 0xd0, 0x3c, ], isk: [ - 0xdc, 0x93, 0x72, 0x9f, 0x3f, 0x28, 0x30, 0xed, 0x79, 0x1c, 0x21, 0xbe, 0xbe, 0x45, - 0x0f, 0xcf, 0x1f, 0x8f, 0xef, 0x49, 0x81, 0x39, 0xc7, 0x99, 0xd1, 0x63, 0x66, 0x5a, - 0x8c, 0x51, 0xe5, 0x2d, + 0x44, 0xa6, 0x4a, 0xdd, 0x6d, 0xf1, 0xd9, 0x63, 0xf5, 0xdd, 0x5b, 0x50, 0x10, 0xd3, + 0xd0, 0x25, 0xf0, 0x28, 0x7c, 0x4c, 0xf1, 0x9c, 0x75, 0xf3, 0x3d, 0x51, 0xdd, 0xdd, + 0xba, 0x5d, 0x65, 0x7b, ], ik: [ - 0x1d, 0xb6, 0x1c, 0x29, 0x3e, 0x3a, 0x93, 0x34, 0x5d, 0x06, 0xb9, 0x0b, 0xd7, 0x1f, - 0xd3, 0x21, 0x5c, 0x2c, 0x1c, 0x29, 0x53, 0x5a, 0x10, 0xde, 0x9d, 0x31, 0x40, 0xb7, - 0x4d, 0xb6, 0x1d, 0x07, + 0x0b, 0x93, 0xf6, 0x34, 0x6e, 0x57, 0x23, 0x27, 0x1b, 0x60, 0x7b, 0xc8, 0x08, 0x68, + 0x08, 0xf1, 0xbb, 0x03, 0x5d, 0x0d, 0xe5, 0x52, 0x4d, 0x06, 0x48, 0x08, 0x31, 0xe7, + 0x16, 0x31, 0x52, 0xd7, ], nk: [ - 0x9e, 0x99, 0x7d, 0x9d, 0x26, 0x97, 0x87, 0x26, 0x8e, 0x09, 0x2a, 0x7c, 0x85, 0x41, - 0x7d, 0xa5, 0x30, 0xea, 0x42, 0xfa, 0xc6, 0x68, 0xa7, 0x49, 0xaf, 0x55, 0xdf, 0xb7, - 0x1c, 0xdb, 0xbe, 0x09, + 0x49, 0xaf, 0xb9, 0xd3, 0x17, 0x63, 0x82, 0x90, 0x2b, 0x98, 0x5d, 0x7b, 0x04, 0xb3, + 0x77, 0x7b, 0x3e, 0x93, 0xf9, 0x25, 0xc0, 0xcf, 0x09, 0x40, 0x22, 0x91, 0xd6, 0x90, + 0x9d, 0x8b, 0x64, 0x0b, ], rivk: [ - 0x13, 0x6c, 0x6f, 0xe2, 0xe2, 0xb7, 0x9c, 0x51, 0x56, 0xdb, 0x50, 0x47, 0xd8, 0xd5, - 0xe7, 0x95, 0xdf, 0xc0, 0xbd, 0xc0, 0x88, 0x08, 0x53, 0xa4, 0x4a, 0xdb, 0x73, 0x92, - 0xc0, 0x2f, 0x94, 0x1b, + 0x29, 0x1c, 0xe2, 0x3e, 0x99, 0x33, 0x8b, 0x88, 0x3c, 0x3e, 0xcc, 0x93, 0xed, 0x61, + 0x59, 0x74, 0x83, 0xea, 0x1f, 0xbc, 0x78, 0x3f, 0xa4, 0x5b, 0xa7, 0xba, 0xf8, 0xfb, + 0x14, 0x78, 0xfe, 0x1a, ], ivk: [ - 0x02, 0x8b, 0x64, 0x05, 0x64, 0xb2, 0x49, 0x05, 0xde, 0x92, 0x92, 0xba, 0x5b, 0x98, - 0x10, 0xad, 0xdd, 0x86, 0xbe, 0xd0, 0xfb, 0x3b, 0x2d, 0x6b, 0x37, 0xf2, 0x6d, 0xd2, - 0x38, 0xa7, 0xdb, 0x13, + 0x61, 0x58, 0x87, 0xc8, 0x04, 0xac, 0x73, 0x06, 0x24, 0x51, 0x93, 0x54, 0x3f, 0x8a, + 0x8b, 0x20, 0xde, 0x76, 0x67, 0xba, 0xdd, 0xd3, 0x52, 0x64, 0x78, 0x07, 0x63, 0x37, + 0x49, 0x20, 0xd1, 0x1f, ], ovk: [ - 0x98, 0xd6, 0xa4, 0xbf, 0x68, 0x01, 0xd8, 0xba, 0x0d, 0x0b, 0x67, 0xea, 0x7b, 0x80, - 0x52, 0x07, 0xab, 0xc0, 0x34, 0x8f, 0xc5, 0x62, 0x00, 0x5a, 0x59, 0xa2, 0x7a, 0x8a, - 0x46, 0xfa, 0x6a, 0xdd, + 0x69, 0x96, 0x86, 0xa4, 0x13, 0xbc, 0x95, 0x43, 0xe8, 0xb3, 0x90, 0xc1, 0x51, 0x4a, + 0x41, 0xff, 0xa2, 0x80, 0xf1, 0xea, 0x8a, 0x52, 0xc6, 0x1a, 0x56, 0xea, 0x94, 0x98, + 0x6d, 0xd8, 0x66, 0x2c, ], dk: [ - 0xd0, 0xba, 0xef, 0x60, 0x12, 0xd3, 0x08, 0xef, 0xbb, 0x76, 0x9a, 0x99, 0xcc, 0xa2, - 0x92, 0x8c, 0xed, 0xe8, 0xdb, 0x27, 0x76, 0x45, 0xa7, 0x77, 0xea, 0xf1, 0x72, 0x2c, - 0xd0, 0x84, 0x50, 0xb3, + 0x2b, 0xc7, 0xd4, 0x9f, 0xed, 0x53, 0xc1, 0x59, 0x21, 0x9d, 0x29, 0xb3, 0xe5, 0x51, + 0x08, 0xd6, 0x5d, 0x2a, 0x82, 0x3f, 0xce, 0x17, 0x51, 0x08, 0xdb, 0xc9, 0xc5, 0xb5, + 0x00, 0x4a, 0x7f, 0xd4, ], default_d: [ - 0xcc, 0x7c, 0xe7, 0x34, 0xb0, 0x75, 0xa0, 0x1b, 0x92, 0xaa, 0xca, + 0x80, 0x1a, 0x91, 0xc1, 0x78, 0x47, 0x23, 0x30, 0x82, 0x67, 0x9a, ], default_pk_d: [ - 0x3d, 0xa5, 0x27, 0x3a, 0x56, 0x67, 0xc7, 0x66, 0xb8, 0x23, 0x12, 0x06, 0x18, 0x0f, - 0x15, 0x8a, 0xc0, 0x2a, 0xf3, 0xf0, 0x6e, 0xcc, 0xa6, 0xec, 0x7c, 0x38, 0xc7, 0x5d, - 0x33, 0x60, 0x03, 0x20, + 0x8e, 0xa1, 0xac, 0x5f, 0x65, 0xc1, 0x79, 0x9b, 0x6c, 0x7a, 0x68, 0x4f, 0xf3, 0x5e, + 0x63, 0xbd, 0xdf, 0x75, 0xff, 0xf6, 0x9f, 0xc2, 0xd2, 0x83, 0x59, 0xf2, 0xd4, 0x96, + 0xff, 0x9e, 0xb7, 0x20, ], internal_rivk: [ - 0x88, 0xd7, 0xb1, 0x96, 0x99, 0xf3, 0x94, 0xa5, 0x50, 0xbc, 0x9c, 0xdc, 0x6b, 0xf3, - 0xfc, 0x71, 0xf6, 0x10, 0xc3, 0x06, 0x56, 0x37, 0x61, 0x53, 0xa6, 0x96, 0x1f, 0xcd, - 0x5b, 0x97, 0xfa, 0x19, + 0x29, 0x8e, 0xf3, 0x46, 0x9e, 0x43, 0x01, 0x93, 0x44, 0xfa, 0x27, 0x4b, 0x67, 0xcc, + 0xd3, 0xef, 0xda, 0x04, 0x02, 0x18, 0x07, 0x17, 0xea, 0x6c, 0x7e, 0x6f, 0x11, 0xdf, + 0x1c, 0x8e, 0xbe, 0x20, ], internal_ivk: [ - 0x0a, 0x2d, 0xc9, 0x66, 0x61, 0xb9, 0x27, 0x25, 0x0d, 0x7e, 0x3c, 0xd2, 0xc7, 0xe0, - 0x6d, 0x51, 0x74, 0xc6, 0x2c, 0xb1, 0x2e, 0x07, 0x16, 0x7f, 0x19, 0x4f, 0x4c, 0xe6, - 0x4e, 0x68, 0x95, 0x02, + 0xa2, 0xea, 0xb2, 0x74, 0xa9, 0x69, 0xc4, 0x46, 0x8f, 0x66, 0x83, 0x9c, 0x72, 0xaa, + 0x6e, 0x65, 0xe6, 0x59, 0xb1, 0x2c, 0xd2, 0x17, 0xba, 0x91, 0x04, 0x21, 0xb8, 0x89, + 0x9f, 0xab, 0x59, 0x32, ], internal_ovk: [ - 0xcc, 0x79, 0x65, 0xf3, 0x3a, 0xc0, 0x1c, 0x60, 0x68, 0x51, 0xb1, 0x29, 0xbd, 0xc9, - 0xb6, 0xab, 0xd5, 0xca, 0x5b, 0x9d, 0x24, 0x1d, 0xbd, 0x5c, 0x18, 0xb2, 0x46, 0x9b, - 0x7c, 0x8c, 0xc8, 0x9f, + 0x81, 0xc1, 0xe2, 0xde, 0x44, 0xcb, 0xd6, 0xd5, 0xdd, 0x87, 0x6c, 0x87, 0xb5, 0xf8, + 0x28, 0x0b, 0xec, 0xa7, 0xfa, 0x77, 0x97, 0x76, 0x54, 0x73, 0xf5, 0x92, 0xd5, 0xfa, + 0xe3, 0xf7, 0xda, 0x9f, ], internal_dk: [ - 0xda, 0xa2, 0x42, 0xd2, 0x0d, 0xfd, 0xce, 0x8f, 0xc1, 0x0f, 0x4d, 0x99, 0x39, 0x7d, - 0xa2, 0x2c, 0x49, 0x1d, 0xc0, 0x9e, 0x1b, 0x12, 0x0f, 0x66, 0x93, 0xd6, 0x86, 0xec, - 0xd4, 0x03, 0x0a, 0x00, + 0x2b, 0x04, 0xdc, 0x9d, 0xed, 0xc2, 0xd0, 0x5e, 0x16, 0x37, 0x1b, 0xcb, 0x8a, 0x17, + 0x85, 0x44, 0x98, 0x53, 0xf0, 0xed, 0xaf, 0xeb, 0x09, 0xfd, 0xd4, 0x48, 0x3f, 0x42, + 0xec, 0x7a, 0xc1, 0xb6, ], asset: [ - 0xaa, 0xce, 0xb5, 0x62, 0x18, 0xc6, 0xbd, 0x30, 0xf8, 0x37, 0x4a, 0xc1, 0x33, 0x86, - 0x79, 0x3f, 0x21, 0xa9, 0xfb, 0x80, 0xad, 0x03, 0xbc, 0x0c, 0xda, 0x4a, 0x44, 0x94, - 0x6c, 0x00, 0xe1, 0xb1, + 0xcc, 0x73, 0x29, 0xf3, 0xe9, 0xb4, 0xe5, 0x4c, 0x23, 0x6c, 0x29, 0xaf, 0x39, 0x23, + 0x10, 0x17, 0x56, 0xd9, 0xfa, 0x4b, 0xd0, 0xf7, 0xd2, 0xdd, 0xaa, 0xcb, 0x6b, 0x0f, + 0x86, 0xa2, 0x65, 0x8e, ], - note_v: 5706402952489856202, + note_v: 1456989545392107075, note_rho: [ - 0xa1, 0xdf, 0x0e, 0x5b, 0x87, 0xb5, 0xbe, 0xce, 0x47, 0x7a, 0x70, 0x96, 0x49, 0xe9, - 0x50, 0x06, 0x05, 0x91, 0x39, 0x48, 0x12, 0x95, 0x1e, 0x1f, 0xe3, 0x89, 0x5b, 0x8c, - 0xc3, 0xd1, 0x4d, 0x2c, + 0x90, 0x70, 0x46, 0x07, 0xf3, 0x87, 0xa0, 0x3e, 0x49, 0xbf, 0x98, 0x36, 0x57, 0x44, + 0x31, 0x34, 0x5a, 0x78, 0x77, 0xef, 0xaa, 0x8a, 0x08, 0xe7, 0x30, 0x81, 0xef, 0x8d, + 0x62, 0xcb, 0x78, 0x0a, ], note_rseed: [ - 0xf6, 0x55, 0x6d, 0xf6, 0xed, 0x4b, 0x4d, 0xdd, 0x3d, 0x9a, 0x69, 0xf5, 0x33, 0x57, - 0xd7, 0x76, 0x7f, 0x4f, 0x5c, 0xcb, 0xdb, 0xc5, 0x96, 0x63, 0x12, 0x77, 0xf8, 0xfe, - 0xcd, 0x08, 0xcb, 0x05, + 0xb6, 0x88, 0x3a, 0x50, 0xa0, 0xd4, 0x70, 0x19, 0x0d, 0xfb, 0xa1, 0x0a, 0x85, 0x7f, + 0x82, 0x84, 0x2d, 0x38, 0x25, 0xb3, 0xd6, 0xda, 0x05, 0x73, 0xd3, 0x16, 0xeb, 0x16, + 0x0d, 0xc0, 0xb7, 0x16, ], note_cmx: [ - 0xf1, 0x34, 0x33, 0x5c, 0x60, 0xf3, 0x17, 0xec, 0x48, 0xd6, 0x7b, 0x49, 0x34, 0x58, - 0xde, 0x26, 0xb4, 0x06, 0xfd, 0xd2, 0x10, 0xf8, 0x60, 0xb1, 0x81, 0xaf, 0x7b, 0x82, - 0xcd, 0xe9, 0x4e, 0x37, + 0x26, 0xc0, 0xb4, 0x92, 0xe5, 0x6c, 0xf6, 0xc5, 0xdd, 0x67, 0x9c, 0x84, 0x66, 0x7b, + 0x74, 0x41, 0x83, 0x63, 0xc7, 0xd9, 0x15, 0xed, 0x6b, 0x72, 0x50, 0xde, 0xa9, 0xd9, + 0xe7, 0xeb, 0x51, 0x39, ], note_nf: [ - 0x75, 0x6c, 0x1f, 0x4b, 0xfa, 0xae, 0xc5, 0x5b, 0x42, 0x0a, 0x4f, 0x88, 0x12, 0xdb, - 0x6c, 0x43, 0x2e, 0x48, 0x61, 0x6f, 0xb8, 0xd1, 0xbb, 0x2b, 0x1d, 0xd1, 0xe7, 0x2c, - 0x0a, 0xa3, 0xdb, 0x3a, + 0x7e, 0xec, 0xa6, 0x5c, 0xbd, 0xc5, 0x01, 0x18, 0x2f, 0x6e, 0x1b, 0x11, 0xa2, 0x3b, + 0x0f, 0xaa, 0x80, 0xfc, 0x26, 0xca, 0x16, 0xbc, 0x4c, 0xd0, 0x97, 0x33, 0xab, 0x0e, + 0x1d, 0x10, 0x8d, 0x16, ], }, TestVector { sk: [ - 0x6b, 0x95, 0xe3, 0x02, 0x5b, 0x97, 0x92, 0xff, 0xf7, 0xf2, 0x44, 0xfc, 0x71, 0x62, - 0x69, 0xb9, 0x26, 0xd6, 0x2e, 0x95, 0x96, 0xfa, 0x82, 0x5c, 0x6b, 0xf2, 0x1a, 0xff, - 0x9e, 0x68, 0x62, 0x5a, + 0xc4, 0x8f, 0xbd, 0x46, 0x7f, 0x75, 0xb7, 0x80, 0x14, 0x9a, 0xe8, 0x80, 0x8f, 0x4e, + 0x68, 0xf5, 0x0c, 0x05, 0x36, 0xac, 0xdd, 0xf6, 0xf1, 0xae, 0xab, 0x01, 0x6b, 0x6b, + 0xc1, 0xec, 0x14, 0x4b, ], ask: [ - 0x75, 0x7d, 0x15, 0x8d, 0x07, 0x35, 0x6b, 0x3b, 0xc2, 0xc9, 0xe5, 0x1c, 0x55, 0x8a, - 0x9b, 0x31, 0x6b, 0xdd, 0xbc, 0x36, 0x0b, 0x8b, 0xeb, 0x6e, 0x2a, 0xe3, 0xb0, 0x61, - 0x8f, 0x06, 0x2d, 0x2e, + 0xb1, 0xc5, 0x78, 0x06, 0x79, 0xa6, 0x48, 0x9f, 0x79, 0x78, 0xd0, 0x2d, 0x12, 0xb9, + 0xcf, 0x78, 0xe9, 0x18, 0x25, 0x6d, 0xfa, 0xae, 0xbe, 0xe5, 0xd8, 0x9d, 0x71, 0xe5, + 0xc1, 0xdc, 0x0e, 0x3b, ], ak: [ - 0x44, 0x9a, 0x90, 0xd2, 0xe8, 0xd1, 0xa0, 0x37, 0x64, 0x2a, 0x97, 0x09, 0x6c, 0x91, - 0x65, 0x43, 0x46, 0x2a, 0x13, 0x7f, 0xfe, 0xa3, 0x7b, 0xaf, 0x41, 0xef, 0x28, 0x6b, - 0xb7, 0x32, 0xbe, 0x2c, + 0x95, 0x99, 0x81, 0xe9, 0x29, 0xa7, 0x15, 0xa3, 0x4e, 0x5b, 0x05, 0xc0, 0xc1, 0x23, + 0x1e, 0x52, 0x25, 0x96, 0xb9, 0x44, 0xd5, 0x24, 0xf6, 0x2c, 0x2a, 0x4b, 0xd6, 0x95, + 0x3e, 0x5a, 0x84, 0x13, ], isk: [ - 0xf2, 0x34, 0x52, 0x32, 0xc9, 0x19, 0xc1, 0x29, 0xe0, 0x4b, 0x0c, 0x46, 0xac, 0x2c, - 0xa8, 0x50, 0x65, 0xd9, 0x54, 0x85, 0xb9, 0x02, 0xab, 0x0f, 0x98, 0xf9, 0x3a, 0xee, - 0x59, 0x4b, 0x5f, 0x02, + 0x4e, 0x55, 0x3a, 0xcf, 0xd6, 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, 0x06, 0x77, + 0xe3, 0x1b, 0xa4, 0x59, 0xb4, 0x4e, 0x30, 0x77, 0x68, 0x95, 0x8f, 0xe3, 0x78, 0x9d, + 0x41, 0xc2, 0xb1, 0xff, ], ik: [ - 0x2c, 0x83, 0xd9, 0x20, 0xe9, 0xf6, 0x6d, 0xa5, 0x04, 0x86, 0x37, 0xad, 0x9a, 0xa2, - 0xcc, 0xe6, 0xe1, 0x6e, 0xf4, 0x8f, 0x86, 0x50, 0xea, 0x00, 0xd8, 0xc2, 0xd7, 0x68, - 0x61, 0x8a, 0xe3, 0x36, + 0xbf, 0xfe, 0xa0, 0x0a, 0xf9, 0x2b, 0x81, 0xbc, 0x57, 0x2b, 0xea, 0x4a, 0x26, 0x73, + 0x5a, 0x34, 0x9f, 0x4d, 0x76, 0xd1, 0x69, 0x68, 0xe5, 0x6c, 0x56, 0x5f, 0xd9, 0x2b, + 0xeb, 0x46, 0x08, 0x48, ], nk: [ - 0xfd, 0x31, 0x64, 0xc6, 0x32, 0xbe, 0xc9, 0x4c, 0xe9, 0xfb, 0x2f, 0x30, 0x22, 0x63, - 0xb8, 0x84, 0xab, 0xb9, 0xc1, 0x0e, 0x55, 0xe4, 0x48, 0x64, 0x7f, 0x67, 0x98, 0x49, - 0x5c, 0x9d, 0x08, 0x3f, + 0x7c, 0xf5, 0xe1, 0x97, 0xb7, 0x7a, 0x3c, 0xe4, 0xb6, 0x69, 0x61, 0x5b, 0x78, 0xd3, + 0x19, 0x65, 0x9a, 0x90, 0x46, 0x3e, 0x45, 0x93, 0x32, 0x47, 0x44, 0xb9, 0xb4, 0x19, + 0x35, 0xa9, 0xfd, 0x3a, ], rivk: [ - 0xc0, 0xb3, 0x6b, 0x56, 0x07, 0x0f, 0xff, 0x2f, 0xdf, 0x38, 0xeb, 0xa1, 0x1a, 0x74, - 0x24, 0x95, 0x71, 0x95, 0x01, 0x4c, 0xba, 0x43, 0xa5, 0x6b, 0xd1, 0xb1, 0x65, 0x8e, - 0x66, 0xa3, 0x9d, 0x00, + 0x61, 0xf7, 0x39, 0x8a, 0x70, 0x07, 0x07, 0x95, 0x94, 0xad, 0xa8, 0xc8, 0x37, 0x0d, + 0xd8, 0xa9, 0xe4, 0x90, 0x66, 0xee, 0xf2, 0xd6, 0x05, 0x9b, 0x02, 0xa1, 0x67, 0x68, + 0x26, 0xaa, 0x4a, 0x2d, ], ivk: [ - 0x97, 0x6a, 0x87, 0x88, 0x19, 0x1b, 0x87, 0xe4, 0xc1, 0x3f, 0x2c, 0x6d, 0x23, 0xb4, - 0xf3, 0x59, 0x5e, 0x02, 0x28, 0xe2, 0x45, 0xe9, 0x6e, 0xef, 0x1d, 0x24, 0xb2, 0x93, - 0x29, 0x6a, 0x19, 0x1c, + 0xcc, 0xb2, 0x24, 0x66, 0xf1, 0xa3, 0xda, 0x33, 0xc2, 0xfd, 0xab, 0x63, 0x19, 0xde, + 0x82, 0x71, 0xff, 0xd9, 0xc7, 0xc7, 0xba, 0xfa, 0x24, 0x06, 0x8e, 0x72, 0x32, 0x1c, + 0x87, 0x67, 0x76, 0x2b, ], ovk: [ - 0x1e, 0xd0, 0xed, 0xa5, 0xa4, 0x08, 0x61, 0x31, 0x26, 0x1a, 0x2e, 0xd4, 0x42, 0x92, - 0x61, 0xe4, 0x27, 0x6a, 0x26, 0xd4, 0x28, 0x59, 0xfa, 0xbd, 0xa3, 0x1a, 0xa9, 0x67, - 0x09, 0x87, 0x43, 0x71, + 0x12, 0xac, 0xb4, 0xf9, 0xf0, 0xb2, 0xcc, 0x5d, 0xfa, 0x03, 0x15, 0x46, 0x73, 0xd7, + 0xf3, 0x0c, 0x7f, 0x1c, 0xb1, 0x84, 0xa7, 0xce, 0x4e, 0xd8, 0x4b, 0x9d, 0x0b, 0x3d, + 0x8e, 0x68, 0x63, 0xd3, ], dk: [ - 0x5e, 0x5b, 0x60, 0xc0, 0x5b, 0x53, 0xd0, 0xbc, 0xd2, 0xda, 0x46, 0xa1, 0x31, 0x29, - 0x12, 0x51, 0x5c, 0xc7, 0xcf, 0x2d, 0x97, 0x4c, 0x11, 0x7c, 0x8d, 0xde, 0xa9, 0xfa, - 0xb6, 0x20, 0xc6, 0x68, + 0x51, 0xba, 0x5e, 0x4e, 0x4b, 0x8f, 0xbe, 0xf0, 0xd0, 0x1e, 0xf3, 0x8c, 0x77, 0xb4, + 0xba, 0x7f, 0xfa, 0x26, 0x72, 0xfa, 0x7a, 0xde, 0x50, 0x4f, 0xdb, 0x85, 0x91, 0x05, + 0x46, 0x7d, 0x0a, 0x91, ], default_d: [ - 0x99, 0xaf, 0x6b, 0xf3, 0xf4, 0x75, 0xbd, 0xe8, 0x89, 0xaa, 0xca, + 0x7f, 0xd2, 0x1b, 0xf0, 0xf5, 0xf3, 0x2f, 0x7d, 0xf2, 0xec, 0x7f, ], default_pk_d: [ - 0xac, 0xdc, 0xd3, 0x48, 0xca, 0x45, 0xee, 0x58, 0x32, 0x78, 0x30, 0x38, 0x46, 0xca, - 0x07, 0x84, 0x59, 0xd5, 0xbe, 0x5c, 0x5d, 0xcf, 0x34, 0x7e, 0x3b, 0x9a, 0x34, 0xcb, - 0xa1, 0x24, 0xb4, 0xa3, + 0x54, 0x92, 0x6e, 0xd8, 0xd4, 0xbc, 0x4c, 0xcd, 0xed, 0xc9, 0x91, 0xaa, 0x62, 0x19, + 0xc3, 0xf6, 0xb4, 0x58, 0xd6, 0x78, 0xc6, 0xd6, 0xc3, 0xc9, 0x0d, 0x57, 0xfc, 0x08, + 0x71, 0xc3, 0x50, 0xbe, ], internal_rivk: [ - 0x94, 0x1a, 0x17, 0xe1, 0x20, 0x2a, 0x62, 0x71, 0xa4, 0x4a, 0x01, 0x66, 0x65, 0x53, - 0xb5, 0x81, 0xbf, 0x25, 0xef, 0x99, 0xe8, 0xe9, 0x5f, 0x13, 0x2a, 0xce, 0x38, 0x1d, - 0x96, 0x01, 0x84, 0x32, + 0xd6, 0x2f, 0x96, 0x87, 0x62, 0x35, 0x26, 0x2b, 0x7e, 0x75, 0x5a, 0x3f, 0x1d, 0x4e, + 0x79, 0x99, 0x7e, 0xec, 0x6d, 0x46, 0x60, 0x39, 0x8f, 0xe0, 0x7e, 0x29, 0x0a, 0x31, + 0xac, 0xf0, 0xdb, 0x2c, ], internal_ivk: [ - 0xa2, 0x76, 0x29, 0xac, 0x1c, 0x62, 0xc9, 0xf4, 0xda, 0xd5, 0x7c, 0x95, 0x30, 0xab, - 0x2a, 0x59, 0x80, 0x0d, 0x2e, 0xf4, 0x55, 0xcd, 0x17, 0x44, 0x6f, 0x3f, 0xc6, 0x08, - 0x1a, 0x58, 0x1e, 0x3b, + 0x6e, 0x03, 0xa4, 0xfd, 0xba, 0x1e, 0xc7, 0xcd, 0xcf, 0x05, 0x09, 0x97, 0x60, 0xbb, + 0xb9, 0xa7, 0x0f, 0x42, 0x4d, 0xcb, 0x20, 0x88, 0x01, 0xd1, 0xe2, 0x7f, 0x12, 0xbd, + 0x4f, 0x14, 0x91, 0x1f, ], internal_ovk: [ - 0xe9, 0x89, 0x8e, 0xd6, 0xb6, 0x69, 0xc8, 0xd9, 0xd5, 0x90, 0xb7, 0x59, 0xd0, 0x29, - 0x5f, 0xcf, 0xaf, 0x95, 0xe2, 0xda, 0xf7, 0xda, 0x99, 0x1c, 0x27, 0x57, 0xdc, 0xef, - 0xe1, 0x62, 0x6e, 0x0e, + 0xba, 0xe4, 0x5d, 0xdd, 0xa9, 0xfe, 0x68, 0x60, 0xe7, 0xc8, 0x70, 0x09, 0x38, 0xb1, + 0x32, 0x4e, 0x6f, 0xe0, 0xe9, 0x88, 0x6e, 0xd8, 0xb0, 0xe2, 0xf9, 0xeb, 0x46, 0xe0, + 0x53, 0x1d, 0x2a, 0x5f, ], internal_dk: [ - 0x61, 0x0c, 0xbd, 0x9a, 0x57, 0x79, 0x79, 0xe1, 0xf7, 0x1d, 0xa8, 0x10, 0x0f, 0x6f, - 0xe6, 0xb8, 0xf6, 0xd1, 0x0a, 0x74, 0x7f, 0xed, 0x2a, 0x1c, 0x91, 0xcb, 0xe1, 0x42, - 0x47, 0x5c, 0x30, 0x82, + 0xc1, 0xcf, 0x55, 0xea, 0xc9, 0xa8, 0x94, 0x18, 0x77, 0x6b, 0x9e, 0xfc, 0x67, 0xef, + 0xe9, 0x0b, 0xf3, 0x61, 0xee, 0xb0, 0x96, 0xed, 0x61, 0x86, 0xc4, 0x1a, 0x60, 0xc4, + 0x29, 0xa5, 0xb5, 0xa9, ], asset: [ - 0x23, 0x6c, 0x29, 0xaf, 0x39, 0x23, 0x10, 0x17, 0x56, 0xd9, 0xfa, 0x4b, 0xd0, 0xf7, - 0xd2, 0xdd, 0xaa, 0xcb, 0x6b, 0x0f, 0x86, 0xa2, 0x65, 0x8e, 0x0a, 0x07, 0xa0, 0x5a, - 0xc5, 0xb9, 0x50, 0x05, + 0xbc, 0x6b, 0xc2, 0x30, 0x7b, 0x48, 0x8d, 0x25, 0x56, 0xd7, 0xb7, 0x38, 0x0e, 0xa4, + 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, 0x69, 0xcd, 0x40, 0x59, + 0xf3, 0x96, 0xbf, 0x29, ], - note_v: 2558469029534639129, + note_v: 94453636825041987, note_rho: [ - 0x34, 0x10, 0x80, 0x6e, 0xa6, 0xf2, 0x88, 0xf8, 0x73, 0x6c, 0x23, 0x35, 0x7c, 0x85, - 0xf4, 0x57, 0x91, 0xe1, 0x70, 0x80, 0x29, 0xd9, 0x82, 0x4d, 0x90, 0x70, 0x46, 0x07, - 0xf3, 0x87, 0xa0, 0x3e, + 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, + 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, + 0x62, 0x47, 0x0d, 0x02, ], note_rseed: [ - 0x49, 0xbf, 0x98, 0x36, 0x57, 0x44, 0x31, 0x34, 0x5a, 0x78, 0x77, 0xef, 0xaa, 0x8a, - 0x08, 0xe7, 0x30, 0x81, 0xef, 0x8d, 0x62, 0xcb, 0x78, 0x0a, 0xb6, 0x88, 0x3a, 0x50, - 0xa0, 0xd4, 0x70, 0x19, + 0xe0, 0xf0, 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, 0x29, 0x6e, + 0xfa, 0xa7, 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, + 0x9a, 0xd4, 0xbb, 0xc6, ], note_cmx: [ - 0x07, 0x1c, 0x49, 0x8b, 0x02, 0x6b, 0x8b, 0x1a, 0x7a, 0x1e, 0x84, 0x00, 0x13, 0x87, - 0x20, 0x82, 0x3d, 0x80, 0xec, 0xa4, 0x99, 0xac, 0xd2, 0x91, 0xfc, 0x07, 0xfd, 0x2f, - 0x41, 0x6e, 0x83, 0x38, + 0x98, 0xfc, 0x4e, 0x7f, 0x1d, 0xb8, 0x5a, 0xe6, 0x42, 0x14, 0xd8, 0x30, 0x06, 0xd8, + 0xac, 0xa8, 0xc2, 0x48, 0x73, 0x53, 0x2c, 0x22, 0x1b, 0x06, 0xd1, 0x8d, 0xf2, 0xb7, + 0xeb, 0x5f, 0xe5, 0x00, ], note_nf: [ - 0x22, 0x55, 0x5e, 0xe7, 0x85, 0x46, 0x8c, 0xc7, 0x70, 0xca, 0xf9, 0x0f, 0x82, 0x61, - 0x1b, 0x80, 0x15, 0xb0, 0x3d, 0xd8, 0x85, 0x6c, 0xc9, 0xa2, 0x7c, 0xbf, 0x7f, 0x5c, - 0x31, 0x3d, 0x96, 0x0e, + 0x37, 0xd7, 0xe9, 0x3c, 0xec, 0xfc, 0x62, 0x08, 0x8c, 0xde, 0x33, 0x41, 0x47, 0x88, + 0xfe, 0xab, 0x15, 0x8a, 0x40, 0xb4, 0xe9, 0x4a, 0x51, 0x11, 0xa7, 0x07, 0xaf, 0x3a, + 0x44, 0x3b, 0xd1, 0x3a, ], }, TestVector { sk: [ - 0x0d, 0xfb, 0xa1, 0x0a, 0x85, 0x7f, 0x82, 0x84, 0x2d, 0x38, 0x25, 0xb3, 0xd6, 0xda, - 0x05, 0x73, 0xd3, 0x16, 0xeb, 0x16, 0x0d, 0xc0, 0xb7, 0x16, 0xc4, 0x8f, 0xbd, 0x46, - 0x7f, 0x75, 0xb7, 0x80, + 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, 0x84, 0x1e, + 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, 0x90, 0x5a, 0xae, 0x08, 0x03, 0xfd, 0x69, 0x44, + 0x2e, 0xb7, 0x68, 0x1e, ], ask: [ - 0x10, 0x10, 0x16, 0x60, 0x30, 0x07, 0x06, 0x52, 0x6a, 0x03, 0xb2, 0x63, 0x24, 0x13, - 0x5b, 0xbd, 0xd2, 0x33, 0xfc, 0xf6, 0x96, 0xca, 0x7f, 0xd2, 0x12, 0xf2, 0x82, 0x55, - 0x9e, 0x78, 0x12, 0x3b, + 0xfb, 0x9c, 0xa6, 0xa7, 0xf2, 0x49, 0x20, 0x67, 0xaa, 0x19, 0x42, 0x01, 0xaa, 0xbc, + 0xd5, 0xc0, 0xce, 0xe9, 0x9f, 0x6d, 0x65, 0x0f, 0x0f, 0x10, 0x44, 0x96, 0xac, 0xc5, + 0x88, 0x34, 0x89, 0x2b, ], ak: [ - 0xeb, 0x1e, 0xd7, 0xf9, 0x37, 0x17, 0xd5, 0xdf, 0x15, 0xdd, 0xb6, 0xb2, 0xb2, 0xb0, - 0x17, 0x76, 0xf9, 0xa1, 0x91, 0xfb, 0x08, 0xa6, 0x8a, 0xe1, 0x32, 0x4f, 0x29, 0x13, - 0xe0, 0x6f, 0xa7, 0x10, + 0xa0, 0xb2, 0x52, 0xde, 0x9e, 0x88, 0xee, 0xc0, 0x36, 0x2e, 0x43, 0x6f, 0x58, 0x52, + 0xf7, 0x4f, 0x7e, 0x3c, 0x74, 0x94, 0xe4, 0xa6, 0x65, 0x2f, 0xbf, 0xa7, 0x44, 0xdb, + 0xa3, 0xa9, 0x23, 0x14, ], isk: [ - 0x90, 0x16, 0x58, 0x59, 0x87, 0x32, 0xd6, 0x5b, 0xea, 0x90, 0x17, 0xdb, 0x74, 0x38, - 0x76, 0xc5, 0x86, 0xbc, 0xa7, 0x45, 0x54, 0xd7, 0x60, 0xf4, 0x9b, 0xa6, 0x59, 0xe4, - 0xe2, 0x1c, 0xbb, 0x14, + 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, 0x92, 0xee, 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, + 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, 0x64, 0x0a, 0x69, 0x30, 0x1a, 0x52, 0xa3, 0x8d, + 0x4d, 0x9f, 0x9f, 0x95, ], ik: [ - 0xa1, 0xe5, 0xf8, 0xab, 0x90, 0x24, 0x01, 0x9a, 0x67, 0x10, 0x53, 0x90, 0x86, 0x72, - 0x65, 0xb4, 0xc5, 0x16, 0x40, 0xe6, 0x5d, 0xb3, 0xcb, 0xcd, 0x7d, 0xf0, 0x04, 0x88, - 0xf8, 0x9e, 0x68, 0x35, + 0x3e, 0x34, 0xea, 0xa1, 0x93, 0x26, 0x04, 0x49, 0xf3, 0xe8, 0x83, 0xfd, 0x5f, 0xbd, + 0x84, 0xfd, 0x99, 0xbf, 0x10, 0xa1, 0xa4, 0xdf, 0x14, 0x60, 0x98, 0x78, 0x4a, 0xe2, + 0xc3, 0xc2, 0xdb, 0xf7, ], nk: [ - 0xf6, 0x42, 0x02, 0x4d, 0x49, 0xe8, 0x4b, 0x65, 0x33, 0xed, 0x2c, 0x37, 0x65, 0x06, - 0x06, 0x39, 0xfc, 0x27, 0x82, 0xd3, 0x9f, 0x87, 0x69, 0xdb, 0x80, 0x6b, 0x37, 0xde, - 0xb1, 0xf0, 0x9c, 0x2b, + 0xfe, 0x7d, 0xda, 0x8a, 0x42, 0xb1, 0x49, 0x04, 0xad, 0x4f, 0xf1, 0x14, 0xae, 0x3a, + 0x97, 0xd2, 0x01, 0xb6, 0x17, 0xf5, 0xd5, 0xd0, 0x2e, 0xe0, 0xde, 0x77, 0x4b, 0xb4, + 0x6e, 0xd0, 0x56, 0x37, ], rivk: [ - 0xe8, 0x2d, 0xad, 0xba, 0x81, 0x82, 0x3b, 0x52, 0xaf, 0x0b, 0xb5, 0xfc, 0x22, 0x79, - 0xaf, 0xfb, 0xff, 0xf8, 0x9c, 0x2d, 0xb2, 0x93, 0xbc, 0x5e, 0x30, 0x78, 0xa1, 0x31, - 0x91, 0x71, 0x66, 0x39, + 0xf8, 0xbf, 0x8f, 0x4f, 0x71, 0x88, 0x90, 0x67, 0xcb, 0x99, 0xf2, 0xec, 0xc5, 0x41, + 0x50, 0x6c, 0x23, 0x0a, 0xff, 0x88, 0x64, 0x26, 0x68, 0x59, 0xf0, 0x15, 0xdf, 0xf4, + 0xc4, 0x89, 0x5e, 0x32, ], ivk: [ - 0xbd, 0xa0, 0xc1, 0x5b, 0x01, 0x4c, 0x15, 0x59, 0xf3, 0x34, 0x14, 0x97, 0xeb, 0x67, - 0xe7, 0x49, 0x5b, 0x73, 0x87, 0xbb, 0x6c, 0x2c, 0xbe, 0xa5, 0x95, 0x46, 0x9e, 0xc1, - 0xd2, 0xa8, 0x23, 0x3a, + 0x4b, 0x22, 0xa9, 0x1d, 0xfe, 0xa9, 0x16, 0x81, 0x91, 0x48, 0xb8, 0x3d, 0x80, 0x5d, + 0xe3, 0xc7, 0xc6, 0x3f, 0xe3, 0x58, 0x11, 0x41, 0xec, 0xdc, 0x26, 0x43, 0x28, 0xe5, + 0x7c, 0x0b, 0x43, 0x2b, ], ovk: [ - 0xd3, 0x8e, 0x31, 0xbd, 0x8a, 0xbd, 0xc5, 0x05, 0xfb, 0x3b, 0x0f, 0x03, 0xa5, 0x8a, - 0x73, 0x4f, 0xce, 0x58, 0x3b, 0x51, 0x4f, 0x32, 0xb3, 0x03, 0xf4, 0x6c, 0x5a, 0x69, - 0x01, 0x85, 0xa9, 0xb0, + 0x12, 0xe5, 0xa1, 0x7f, 0x89, 0x12, 0xd9, 0x6b, 0xfd, 0xc7, 0xd3, 0x75, 0x3c, 0xe2, + 0xa8, 0x3a, 0xca, 0x2b, 0xc6, 0x45, 0x38, 0x3b, 0xc4, 0x54, 0x51, 0x11, 0x5e, 0xd5, + 0xb3, 0xf5, 0xbe, 0xaa, ], dk: [ - 0x9a, 0x5b, 0x8c, 0xdc, 0x9f, 0x7b, 0xe7, 0x47, 0x6f, 0x7b, 0x5b, 0x73, 0x70, 0x71, - 0x90, 0xb6, 0x17, 0x20, 0xf8, 0x4b, 0xb4, 0x84, 0x47, 0x5c, 0x84, 0xd1, 0xce, 0xf1, - 0x5c, 0xa8, 0x15, 0x92, + 0xc6, 0xa0, 0xdc, 0x04, 0x56, 0xbc, 0x4c, 0x39, 0x9e, 0x20, 0x2d, 0x00, 0xd3, 0x2e, + 0xaf, 0xc9, 0xa8, 0xc0, 0xe2, 0x65, 0xa4, 0xae, 0xb1, 0x07, 0xa9, 0xa6, 0x4d, 0x93, + 0x8b, 0x14, 0xc0, 0x0f, ], default_d: [ - 0x46, 0x48, 0x8d, 0x15, 0x40, 0x98, 0x39, 0x66, 0x05, 0xf3, 0xc8, + 0x07, 0xd3, 0x0c, 0x15, 0x5a, 0x71, 0x0a, 0x2d, 0x03, 0x28, 0x25, ], default_pk_d: [ - 0x28, 0xa3, 0x18, 0xf5, 0x04, 0x30, 0x43, 0x03, 0xee, 0xfd, 0x42, 0x87, 0x9c, 0x9f, - 0xc4, 0xf6, 0x27, 0x51, 0x90, 0xc6, 0x37, 0x63, 0x09, 0xb9, 0x13, 0xcc, 0xab, 0x3a, - 0x56, 0x95, 0x94, 0x28, + 0xd7, 0x8b, 0x08, 0x60, 0xbb, 0xf7, 0x82, 0x52, 0x83, 0x79, 0x8e, 0xa7, 0xa6, 0x62, + 0x98, 0x14, 0xed, 0xe8, 0x14, 0x8a, 0x53, 0x8d, 0xe6, 0x30, 0x0e, 0x0f, 0x88, 0x90, + 0x4f, 0x01, 0x4c, 0x19, ], internal_rivk: [ - 0xdd, 0xa7, 0x37, 0x26, 0xb1, 0x7b, 0xfb, 0x17, 0x82, 0xc5, 0x73, 0xa7, 0x5b, 0x54, - 0xfe, 0x6a, 0x37, 0xff, 0x66, 0x0c, 0x9b, 0x0f, 0x08, 0x64, 0xa5, 0x4f, 0x77, 0xe6, - 0x25, 0x8d, 0x69, 0x39, + 0xc4, 0x35, 0x16, 0x37, 0x67, 0x71, 0xad, 0xca, 0x2b, 0x7b, 0xeb, 0xe3, 0xe6, 0xa7, + 0x1c, 0xb6, 0x5c, 0xa8, 0xcf, 0x1f, 0xfb, 0x16, 0xc9, 0xc4, 0xf0, 0x48, 0x19, 0x86, + 0x87, 0x9e, 0xee, 0x28, ], internal_ivk: [ - 0x71, 0x67, 0x63, 0x93, 0xce, 0x07, 0x32, 0xfc, 0x42, 0x42, 0x83, 0x1d, 0x94, 0xe7, - 0xf8, 0xc3, 0xf8, 0xa0, 0x78, 0x4d, 0xee, 0xa2, 0xae, 0xcd, 0x79, 0xdd, 0x54, 0x10, - 0x2a, 0x72, 0x89, 0x13, + 0xaf, 0x6a, 0xbb, 0xb5, 0xde, 0x71, 0x0f, 0x0f, 0xb4, 0x0f, 0xa5, 0xa2, 0xe2, 0x7e, + 0x8c, 0x83, 0x2c, 0x69, 0x9c, 0x2b, 0x7f, 0x58, 0xbd, 0xa6, 0xbc, 0x9a, 0xd5, 0xb9, + 0x11, 0xc1, 0xf0, 0x20, ], internal_ovk: [ - 0x4e, 0x71, 0xe6, 0xc1, 0x84, 0x5a, 0x5a, 0x36, 0xcf, 0x46, 0x03, 0x0f, 0xe6, 0x81, - 0xfd, 0xb0, 0xce, 0x39, 0xf4, 0x61, 0x31, 0x47, 0xbb, 0xcd, 0x10, 0xae, 0x42, 0x9c, - 0x81, 0x94, 0xb2, 0x05, + 0x08, 0x6a, 0x61, 0x0d, 0x50, 0x7d, 0xb9, 0xaa, 0x4f, 0x34, 0x90, 0x40, 0xd4, 0xf4, + 0xbf, 0x35, 0x58, 0x05, 0x68, 0xcf, 0x36, 0xe9, 0x3f, 0x40, 0x57, 0x5f, 0x7f, 0x2a, + 0x50, 0xb6, 0xa1, 0xde, ], internal_dk: [ - 0x06, 0x31, 0xff, 0x9b, 0x81, 0xac, 0xf2, 0x1f, 0xb6, 0xe1, 0xf0, 0x81, 0xb5, 0x50, - 0xa5, 0x4e, 0xa1, 0x54, 0x49, 0x8e, 0x52, 0x98, 0x73, 0xe2, 0x58, 0x82, 0xf0, 0x66, - 0xb7, 0x3b, 0x6b, 0x8c, + 0xfa, 0xae, 0xd1, 0xb9, 0xd7, 0xee, 0x7b, 0x90, 0xb4, 0xa4, 0x70, 0xfd, 0x49, 0xdc, + 0xd2, 0x8c, 0x76, 0xe6, 0x0e, 0xfc, 0xb8, 0x0f, 0x4d, 0x9e, 0x40, 0xe6, 0x6f, 0xa7, + 0x76, 0xc7, 0x07, 0x1f, ], asset: [ - 0x0c, 0x05, 0x36, 0xac, 0xdd, 0xf6, 0xf1, 0xae, 0xab, 0x01, 0x6b, 0x6b, 0xc1, 0xec, - 0x14, 0x4b, 0x4e, 0x55, 0x3a, 0xcf, 0xd6, 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, - 0x06, 0x77, 0xe3, 0x1b, + 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, 0x15, 0x81, 0xa1, 0x55, + 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, 0x2e, 0x65, 0x0b, 0x38, 0x6a, 0xd3, 0xa0, 0x8c, + 0xb6, 0xb8, 0x31, 0x31, ], - note_v: 17683470315120269844, + note_v: 1448031623652762490, note_rho: [ - 0xa4, 0x59, 0xb4, 0x4e, 0x30, 0x77, 0x68, 0x95, 0x8f, 0xe3, 0x78, 0x9d, 0x41, 0xc2, - 0xb1, 0xff, 0x43, 0x4c, 0xb3, 0x0e, 0x15, 0x91, 0x4f, 0x01, 0xbc, 0x6b, 0xc2, 0x30, - 0x7b, 0x48, 0x8d, 0x25, + 0x76, 0x1f, 0xd3, 0xf4, 0x1e, 0x72, 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, + 0xec, 0xa3, 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, + 0x99, 0xc7, 0x1f, 0x18, ], note_rseed: [ - 0x56, 0xd7, 0xb7, 0x38, 0x0e, 0xa4, 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, - 0xb9, 0x45, 0x69, 0xcd, 0x40, 0x59, 0xf3, 0x96, 0xbf, 0x29, 0xb9, 0x9d, 0x0a, 0x40, - 0xe5, 0xe1, 0x71, 0x1c, + 0x93, 0x41, 0xac, 0x9b, 0x78, 0xa2, 0x69, 0x16, 0x42, 0x06, 0xa0, 0xea, 0x1c, 0xe7, + 0x3b, 0xfb, 0x2a, 0x94, 0x2e, 0x73, 0x70, 0xb2, 0x47, 0xc0, 0x46, 0xf8, 0xe7, 0x5e, + 0xf8, 0xe3, 0xf8, 0xbd, ], note_cmx: [ - 0x7b, 0xc1, 0xdd, 0xba, 0x52, 0x06, 0x14, 0xdd, 0x4e, 0x44, 0x3e, 0xaa, 0xf2, 0x5b, - 0xea, 0xa0, 0x14, 0xc2, 0x78, 0x6d, 0x15, 0x0a, 0x3b, 0x6f, 0xea, 0x97, 0x6a, 0x9b, - 0xdf, 0x27, 0x02, 0x04, + 0xdf, 0x72, 0x6a, 0x0e, 0x47, 0xd8, 0xb7, 0xd9, 0xcc, 0xa2, 0x6a, 0x1f, 0x74, 0x55, + 0x4a, 0x81, 0x52, 0x5b, 0x1b, 0x7a, 0xf1, 0x6e, 0xfb, 0x52, 0xb9, 0x27, 0x8b, 0x7c, + 0x8a, 0xbf, 0x8c, 0x22, ], note_nf: [ - 0x78, 0x31, 0xe9, 0xc5, 0x1c, 0xc1, 0xdc, 0xa6, 0xda, 0x89, 0x1a, 0xde, 0xad, 0x3a, - 0x79, 0x24, 0xff, 0x26, 0x4b, 0xe4, 0x25, 0x0b, 0xec, 0x05, 0xc5, 0x92, 0xd3, 0x14, - 0x52, 0x6b, 0x1a, 0x2f, + 0x6a, 0xfb, 0x25, 0xb0, 0x7d, 0x0d, 0x60, 0xa3, 0x28, 0xef, 0x22, 0xd9, 0x06, 0xf3, + 0x53, 0x1d, 0x8b, 0x50, 0xc4, 0x10, 0x7b, 0xd1, 0xc7, 0x66, 0x2c, 0xd6, 0x7b, 0x5d, + 0xb2, 0x0a, 0x05, 0x28, ], }, TestVector { sk: [ - 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, 0x3d, 0xa0, - 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, 0x62, 0x47, 0x0d, 0x02, 0xe0, 0xf0, 0x5d, 0x4b, - 0xec, 0x95, 0x12, 0xbf, + 0x82, 0x1c, 0xf5, 0x77, 0x49, 0x18, 0x64, 0xe2, 0x0e, 0x6d, 0x08, 0xfd, 0x2e, 0x32, + 0xb5, 0x55, 0xc9, 0x2c, 0x66, 0x1f, 0x19, 0x58, 0x8b, 0x72, 0xa8, 0x95, 0x99, 0x71, + 0x0a, 0x88, 0x06, 0x12, ], ask: [ - 0x6e, 0x61, 0x4e, 0x28, 0x21, 0x35, 0x2a, 0xce, 0xd4, 0x53, 0x3e, 0x86, 0x42, 0x75, - 0x18, 0xc7, 0x42, 0xbf, 0xda, 0x68, 0x79, 0x65, 0x07, 0xa7, 0x01, 0xdd, 0xa3, 0x7d, - 0xaf, 0x20, 0xb3, 0x17, + 0xf5, 0x90, 0xaa, 0x36, 0x24, 0x9c, 0x92, 0xdb, 0x3c, 0xb8, 0x45, 0x9e, 0x7c, 0x0a, + 0x19, 0xd9, 0x22, 0xa7, 0x5e, 0x78, 0x3f, 0xf3, 0x6e, 0x7d, 0x08, 0x10, 0x55, 0xcd, + 0x5f, 0xf2, 0x1c, 0x38, ], ak: [ - 0xed, 0x6e, 0x79, 0xae, 0xd5, 0x75, 0x2e, 0x64, 0xc6, 0xe4, 0xb7, 0x9c, 0x06, 0xa4, - 0x43, 0xb8, 0xef, 0x32, 0xf7, 0xef, 0xa1, 0xf8, 0xf3, 0x5b, 0x54, 0x12, 0x63, 0xaa, - 0x66, 0xaf, 0xd7, 0x0a, + 0x66, 0x38, 0xf1, 0x69, 0x63, 0x2d, 0xd9, 0x4d, 0x3b, 0x0c, 0x21, 0x4e, 0xac, 0xc8, + 0x52, 0xc1, 0xe4, 0xe0, 0x70, 0xcb, 0xdf, 0xb6, 0xe6, 0x2d, 0x08, 0x0f, 0x57, 0x68, + 0xa6, 0xaa, 0xd4, 0x23, ], isk: [ - 0x91, 0xfe, 0x60, 0x36, 0x9d, 0x03, 0x63, 0x66, 0xc2, 0x45, 0x79, 0xec, 0x10, 0xb5, - 0x38, 0x1e, 0x8f, 0x1e, 0xda, 0x89, 0x5f, 0xe0, 0xb6, 0x76, 0xa2, 0xc8, 0x0b, 0x25, - 0xaf, 0x98, 0x67, 0x11, + 0x53, 0xca, 0x28, 0x5b, 0x63, 0x04, 0xb3, 0x7d, 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, + 0x54, 0xa8, 0x94, 0x32, 0x28, 0x48, 0xcc, 0xbd, 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, + 0x68, 0xaf, 0xac, 0x87, ], ik: [ - 0xfe, 0x7e, 0xfc, 0x8b, 0x60, 0x72, 0x1b, 0x3c, 0x8e, 0x88, 0xdc, 0xc8, 0x86, 0xcb, - 0x04, 0x8f, 0xad, 0x5b, 0x48, 0x07, 0xf2, 0xae, 0xe4, 0xae, 0xc6, 0xe1, 0xc3, 0xfa, - 0x51, 0x44, 0x03, 0x1c, + 0x5e, 0x8e, 0x92, 0x06, 0x37, 0x1f, 0xe4, 0xa0, 0x1d, 0x1c, 0x8a, 0x2c, 0x36, 0xe2, + 0x1a, 0x22, 0x6b, 0x12, 0xb2, 0xf6, 0x56, 0xfc, 0xcc, 0x0e, 0x9c, 0x43, 0x22, 0x27, + 0x69, 0x31, 0x09, 0x91, ], nk: [ - 0xb1, 0xe9, 0x25, 0x85, 0x1e, 0x8c, 0xbf, 0x94, 0x28, 0xaf, 0x98, 0xfc, 0x71, 0x4c, - 0xc9, 0xf2, 0x41, 0x30, 0x1a, 0x3d, 0x0f, 0xea, 0x55, 0xe1, 0x29, 0x26, 0xbf, 0x4e, - 0x84, 0x0d, 0x49, 0x16, + 0x64, 0x02, 0x41, 0x63, 0x14, 0x5b, 0x68, 0x66, 0x8d, 0x1c, 0x3f, 0x9c, 0x0f, 0x76, + 0xd3, 0x92, 0xd3, 0x71, 0x8f, 0x01, 0x75, 0x18, 0x1b, 0xa1, 0x4a, 0x0f, 0xc9, 0x5b, + 0x7f, 0xec, 0x65, 0x35, ], rivk: [ - 0x85, 0x45, 0x0e, 0x25, 0xbf, 0x7d, 0x7a, 0xed, 0x86, 0xc7, 0xab, 0xd3, 0x5e, 0xfb, - 0x8c, 0x62, 0x86, 0x77, 0x96, 0xf3, 0x47, 0x67, 0xd3, 0xd3, 0xfe, 0xf6, 0x49, 0x42, - 0x1c, 0x13, 0x32, 0x2f, + 0x4a, 0x61, 0xd4, 0x32, 0x0d, 0x12, 0xdd, 0x47, 0xa6, 0xc2, 0x2d, 0x00, 0xd8, 0xb0, + 0x52, 0xb4, 0x83, 0xd0, 0x40, 0xda, 0xd3, 0x79, 0xbb, 0x29, 0x0b, 0x40, 0xd5, 0x0d, + 0x36, 0x71, 0xcd, 0x0c, ], ivk: [ - 0xe5, 0xe7, 0xaf, 0x47, 0xbe, 0x07, 0x6f, 0xf1, 0xc6, 0x5b, 0x2e, 0xd3, 0x2c, 0xcc, - 0xab, 0xad, 0x90, 0xd6, 0x7e, 0xff, 0x93, 0x5c, 0xcc, 0x29, 0xb1, 0x42, 0xe2, 0xd6, - 0x88, 0x01, 0x8e, 0x0c, + 0x2c, 0x2b, 0x90, 0xc8, 0x3c, 0x30, 0xc2, 0x71, 0x64, 0xce, 0x4d, 0xd9, 0x14, 0xe6, + 0xb8, 0x9e, 0x99, 0x50, 0xe4, 0xf9, 0xa7, 0xa2, 0x4a, 0xfb, 0xcf, 0x11, 0xfe, 0x0d, + 0x86, 0xb1, 0x36, 0x1d, ], ovk: [ - 0xb4, 0x08, 0x5e, 0xe4, 0xeb, 0xd2, 0xd2, 0x80, 0xd5, 0xbf, 0x29, 0x35, 0xfb, 0xb1, - 0x6c, 0x8c, 0xa1, 0x29, 0x25, 0x4b, 0x92, 0x87, 0x2a, 0x1d, 0x12, 0x4a, 0xbb, 0x85, - 0x34, 0x8b, 0x1a, 0x88, + 0x30, 0xe0, 0xa4, 0x48, 0xa6, 0x1e, 0x75, 0xa2, 0x5b, 0xd5, 0x89, 0x61, 0x12, 0x5a, + 0x8e, 0xae, 0x84, 0x45, 0x24, 0xde, 0x0d, 0x91, 0x22, 0xa1, 0x2a, 0x4d, 0x59, 0x6c, + 0xfe, 0xdf, 0xab, 0xc1, ], dk: [ - 0xb3, 0xa5, 0x2b, 0xdc, 0x62, 0xaa, 0xfa, 0xda, 0x4c, 0x40, 0xb4, 0xa6, 0xcd, 0x09, - 0x07, 0x09, 0x83, 0x35, 0xfc, 0xb7, 0x9a, 0x6f, 0xd6, 0xd3, 0x10, 0xc7, 0x26, 0xc0, - 0x1b, 0x39, 0xb3, 0x9d, + 0x33, 0xe4, 0x2c, 0x50, 0xa6, 0x37, 0xe9, 0xdb, 0x68, 0xbe, 0x33, 0x11, 0xbf, 0x5d, + 0x7f, 0xc4, 0x77, 0x4b, 0xe6, 0x19, 0x26, 0xc8, 0x7e, 0xe4, 0xc7, 0xef, 0x36, 0xf1, + 0x87, 0xbb, 0x8c, 0xea, ], default_d: [ - 0xd8, 0x4c, 0x41, 0xf7, 0xb6, 0xb4, 0x33, 0x93, 0x65, 0xe3, 0x41, + 0xc8, 0xa8, 0x3e, 0x75, 0xb1, 0x29, 0x1e, 0x29, 0x59, 0x00, 0xa5, ], default_pk_d: [ - 0x0b, 0x85, 0x8b, 0x0e, 0x24, 0x56, 0x8b, 0x98, 0x4d, 0xa8, 0x96, 0xb3, 0xfb, 0x46, - 0xbe, 0xe7, 0x32, 0xac, 0x8c, 0x3d, 0xde, 0x34, 0xe7, 0x6b, 0xe7, 0x59, 0x90, 0xc8, - 0xd7, 0xc9, 0xc5, 0x04, + 0xc5, 0xc1, 0x1c, 0x61, 0x37, 0xce, 0x83, 0x92, 0x69, 0xee, 0x46, 0xc7, 0x97, 0xeb, + 0xc4, 0x6c, 0x10, 0x53, 0x1c, 0x11, 0xc7, 0x51, 0xa7, 0xda, 0xab, 0xa6, 0x62, 0x2a, + 0x43, 0xe5, 0xaf, 0x35, ], internal_rivk: [ - 0xad, 0x13, 0x65, 0x45, 0x09, 0xf3, 0x0a, 0x80, 0xa3, 0x2f, 0xcd, 0xb9, 0x78, 0x93, - 0xaa, 0x32, 0x7c, 0x3e, 0x56, 0x7f, 0x67, 0xb4, 0x40, 0x45, 0x5f, 0x0d, 0xeb, 0x68, - 0xc3, 0x24, 0xb6, 0x39, + 0x69, 0xa9, 0x4e, 0x8c, 0x99, 0x82, 0x59, 0xfe, 0x6e, 0x54, 0x6c, 0x83, 0x32, 0x8b, + 0x72, 0xf6, 0xf8, 0x3e, 0x80, 0x11, 0x70, 0x6a, 0x5e, 0x31, 0xc2, 0x0c, 0xf8, 0x85, + 0x1e, 0x13, 0x94, 0x37, ], internal_ivk: [ - 0xfa, 0xb6, 0xa5, 0x05, 0xa6, 0xee, 0x92, 0x55, 0x0d, 0xf5, 0xd5, 0xce, 0xbc, 0x37, - 0x9c, 0xd6, 0x24, 0x6c, 0xd2, 0xcc, 0x17, 0x43, 0xa8, 0x1f, 0xb5, 0xf9, 0x8a, 0xa0, - 0xf5, 0xea, 0x8f, 0x0d, + 0x14, 0xb4, 0xf4, 0x27, 0xd3, 0x39, 0xd1, 0xba, 0x26, 0xae, 0xcd, 0x57, 0x6f, 0x65, + 0x60, 0x9f, 0x18, 0xd9, 0xfc, 0x35, 0xb5, 0xf6, 0xdb, 0x5a, 0xf4, 0xc2, 0xa4, 0x32, + 0x09, 0x5b, 0x88, 0x28, ], internal_ovk: [ - 0x8d, 0x08, 0x28, 0xa8, 0x3a, 0xc9, 0x94, 0x33, 0x8a, 0x87, 0xe9, 0x72, 0x68, 0xd4, - 0xaf, 0x0a, 0x87, 0x3b, 0x7c, 0x5b, 0x68, 0xec, 0x60, 0x13, 0x38, 0x51, 0x51, 0xf0, - 0x2d, 0xb1, 0x06, 0x1b, + 0x01, 0xdb, 0x0e, 0x1d, 0x57, 0x47, 0x62, 0xfd, 0xf3, 0x18, 0xa4, 0xf0, 0x48, 0x57, + 0xcf, 0x3b, 0x35, 0x7e, 0xeb, 0xd7, 0xad, 0x92, 0x9e, 0xb9, 0xf8, 0xf1, 0x37, 0x33, + 0xda, 0x8f, 0x2d, 0x69, ], internal_dk: [ - 0x31, 0xe2, 0x98, 0x37, 0xcc, 0x3d, 0xdd, 0x80, 0xdd, 0x80, 0x97, 0x19, 0x7b, 0xfa, - 0x66, 0x46, 0x67, 0x96, 0x2b, 0x09, 0x05, 0x5e, 0x50, 0x7f, 0x39, 0x7d, 0x94, 0xae, - 0xad, 0x84, 0xd8, 0x48, + 0xf7, 0x6c, 0xb8, 0x2a, 0x6f, 0xe2, 0x49, 0xaf, 0xda, 0x87, 0xa7, 0xb5, 0xd8, 0xf7, + 0x7c, 0x4f, 0xba, 0x4d, 0x62, 0x73, 0xd8, 0x0e, 0xe4, 0x5a, 0x3d, 0xd5, 0xb6, 0x37, + 0xa4, 0x30, 0x5f, 0xdb, ], asset: [ - 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, - 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, 0x99, 0xc7, 0x1f, 0x18, 0x93, 0x41, 0xac, 0x9b, - 0x78, 0xa2, 0x69, 0x16, + 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, + 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, + 0xcd, 0xdb, 0x41, 0x87, ], - note_v: 12104108071547302835, + note_v: 3250512694054592767, note_rho: [ - 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, 0x54, 0xa8, 0x94, 0x32, 0x28, 0x48, 0xcc, 0xbd, - 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, 0x68, 0xaf, 0xac, 0x87, 0xff, 0xa0, 0x05, 0xc3, - 0x12, 0x24, 0x1c, 0x2d, + 0xbd, 0xf9, 0x55, 0x59, 0x48, 0xcb, 0xd5, 0xa3, 0x32, 0xd0, 0x45, 0xde, 0x6b, 0xa6, + 0xbf, 0x44, 0x90, 0xad, 0xfe, 0x74, 0x44, 0xcd, 0x46, 0x7a, 0x09, 0x07, 0x54, 0x17, + 0xfc, 0xc0, 0x06, 0x2e, ], note_rseed: [ - 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, - 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, - 0xcd, 0xdb, 0x41, 0x87, + 0x49, 0xf0, 0x08, 0xc5, 0x1a, 0xd4, 0x22, 0x74, 0x39, 0xc1, 0xb4, 0x47, 0x6c, 0xcd, + 0x8e, 0x97, 0x86, 0x2d, 0xab, 0x7b, 0xe1, 0xe8, 0xd3, 0x99, 0xc0, 0x5e, 0xf2, 0x7c, + 0x6e, 0x22, 0xee, 0x27, ], note_cmx: [ - 0xea, 0xf9, 0x49, 0x1c, 0xab, 0xca, 0x20, 0x07, 0xba, 0x91, 0xea, 0xc9, 0xb3, 0xc0, - 0xa1, 0x1c, 0x58, 0xef, 0x5f, 0xe0, 0x71, 0x86, 0x8c, 0x66, 0xf1, 0xc5, 0xf5, 0x9c, - 0x7c, 0x99, 0x25, 0x14, + 0x83, 0xc0, 0x41, 0xba, 0x80, 0x64, 0x27, 0x9b, 0x24, 0x02, 0xae, 0x1e, 0x60, 0x30, + 0xcb, 0x89, 0xc5, 0x0d, 0x96, 0x6e, 0x03, 0x93, 0x73, 0x5c, 0x45, 0x81, 0xd4, 0x98, + 0x11, 0x38, 0x8d, 0x01, ], note_nf: [ - 0x3a, 0xbc, 0x17, 0xad, 0xee, 0x2a, 0xa8, 0x8d, 0xf8, 0x93, 0x99, 0x4f, 0x1a, 0xf2, - 0x71, 0x51, 0xc1, 0x8b, 0xa6, 0xa9, 0x89, 0xc4, 0xbf, 0xfb, 0xb9, 0xa9, 0x18, 0xd5, - 0x50, 0x71, 0x95, 0x02, + 0x1c, 0xe7, 0x2d, 0x48, 0x1c, 0xd5, 0x9e, 0x6c, 0x89, 0x5d, 0x2c, 0x65, 0x85, 0xe9, + 0x77, 0x27, 0x9d, 0x99, 0x27, 0x2e, 0x66, 0xa6, 0xda, 0xa4, 0x74, 0x20, 0xed, 0xbb, + 0xa7, 0xf8, 0x9f, 0x27, ], }, TestVector { sk: [ - 0x2c, 0xfc, 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, 0x3d, 0xbf, - 0xf9, 0x30, 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, - 0x33, 0x92, 0xde, 0xb8, + 0x3e, 0x15, 0x78, 0x6e, 0x39, 0x4c, 0x8f, 0x1b, 0xe3, 0x16, 0x82, 0xa3, 0x01, 0x47, + 0x96, 0x3a, 0xc8, 0xda, 0x8d, 0x41, 0xd8, 0x04, 0x25, 0x84, 0x26, 0xa3, 0xf7, 0x02, + 0x89, 0xb8, 0xad, 0x19, ], ask: [ - 0x33, 0x4c, 0x49, 0x70, 0x7d, 0x93, 0x52, 0x5e, 0x70, 0x45, 0x5d, 0xd2, 0xc0, 0xdd, - 0xb4, 0x2d, 0x49, 0xc9, 0x39, 0x9f, 0x96, 0x14, 0x7f, 0xc0, 0x5e, 0x79, 0xec, 0x49, - 0x1b, 0xd9, 0xad, 0x07, + 0xd4, 0x21, 0xad, 0x5b, 0x18, 0x0c, 0x34, 0x4b, 0x93, 0xb4, 0xcf, 0x3c, 0xe9, 0x55, + 0x49, 0x1e, 0x00, 0x58, 0x45, 0xd9, 0x2e, 0x6f, 0xd6, 0xe9, 0xeb, 0x27, 0x6d, 0xfd, + 0xe6, 0xea, 0x89, 0x0c, ], ak: [ - 0xd3, 0xc0, 0xa4, 0xdc, 0x7e, 0x33, 0x47, 0xa5, 0x0b, 0xf0, 0x58, 0x44, 0xe0, 0xcb, - 0xfc, 0xd4, 0x41, 0x4a, 0x80, 0x9c, 0x0c, 0x30, 0xb1, 0x43, 0xbc, 0xe4, 0xa7, 0xc6, - 0x5c, 0xf0, 0x7f, 0x36, + 0x91, 0x34, 0xed, 0x63, 0xae, 0xe1, 0x94, 0xb4, 0xb5, 0x58, 0xf5, 0xf6, 0x55, 0xba, + 0xb5, 0x39, 0x39, 0x6b, 0x99, 0x67, 0x8e, 0xf9, 0x1f, 0x44, 0x5b, 0x51, 0x7c, 0x79, + 0xc5, 0x82, 0x18, 0x0e, ], isk: [ - 0xb3, 0x72, 0x5b, 0x89, 0x31, 0xc4, 0x93, 0xdb, 0x21, 0x97, 0xe2, 0x87, 0x8e, 0xd3, - 0x62, 0x67, 0x0a, 0x18, 0xb9, 0x29, 0x31, 0x2e, 0xdd, 0x64, 0x4d, 0x74, 0xf9, 0xf3, - 0x23, 0xc6, 0x5e, 0x14, + 0xd8, 0xde, 0x13, 0xbe, 0x4e, 0xeb, 0xe3, 0xbd, 0x4c, 0x8a, 0x6f, 0x55, 0xd6, 0xe0, + 0xc3, 0x73, 0xd4, 0x56, 0x85, 0x18, 0x79, 0xf5, 0xfb, 0xc2, 0x82, 0xdb, 0x9e, 0x13, + 0x48, 0x06, 0xbf, 0xf7, ], ik: [ - 0xc5, 0x12, 0x36, 0x0c, 0x13, 0x59, 0xa6, 0x4f, 0x2a, 0xbb, 0x9e, 0xb3, 0xab, 0x43, - 0xe4, 0x99, 0x8e, 0xd6, 0xd5, 0x1d, 0x17, 0xbd, 0x9d, 0x70, 0x64, 0xa3, 0x91, 0x67, - 0x41, 0x98, 0xea, 0x1a, + 0xb7, 0x47, 0x4b, 0x65, 0x52, 0xdf, 0xc5, 0xe1, 0xe2, 0x57, 0xca, 0xbf, 0xee, 0x40, + 0xe6, 0x08, 0x85, 0x7a, 0x2f, 0xbd, 0x48, 0xfd, 0xa6, 0x6e, 0x9c, 0x71, 0x31, 0x17, + 0x11, 0x58, 0x24, 0xa8, ], nk: [ - 0xc6, 0xb5, 0xe9, 0x28, 0x83, 0x73, 0x52, 0x14, 0x90, 0x20, 0xcc, 0x1f, 0x68, 0xf0, - 0xfb, 0xf8, 0x6a, 0x79, 0x89, 0xcb, 0x4e, 0x09, 0xb3, 0xb5, 0x44, 0x87, 0xb5, 0xcf, - 0x59, 0x00, 0x7c, 0x38, + 0x1b, 0x7d, 0x9f, 0x63, 0x24, 0x9b, 0x96, 0xe7, 0xde, 0x1e, 0xe9, 0xfc, 0xf9, 0x3b, + 0xbd, 0xa4, 0xeb, 0xe7, 0xe8, 0xe4, 0xc2, 0x1a, 0x6f, 0xe4, 0x24, 0xe9, 0x0b, 0x1d, + 0x72, 0x4f, 0x58, 0x39, ], rivk: [ - 0xe9, 0x38, 0xcf, 0x40, 0xc9, 0x83, 0x1a, 0x1a, 0x28, 0x48, 0xbc, 0x80, 0x22, 0x03, - 0x10, 0x81, 0x0b, 0x8f, 0x6a, 0xfd, 0xe1, 0x6c, 0xdd, 0x1e, 0xa1, 0x29, 0x98, 0xd3, - 0x74, 0xd1, 0xbb, 0x08, + 0x60, 0x2b, 0x39, 0xb7, 0xca, 0xff, 0x4e, 0x65, 0x6d, 0x1e, 0x2e, 0x50, 0x87, 0xbf, + 0x19, 0xec, 0x40, 0x93, 0x92, 0x5b, 0x99, 0x36, 0xb2, 0x72, 0x70, 0x74, 0x8e, 0x1b, + 0x16, 0xe0, 0x2f, 0x05, ], ivk: [ - 0x80, 0x78, 0xd4, 0x95, 0x71, 0x1d, 0xc8, 0xc9, 0xba, 0xea, 0xdf, 0x84, 0xee, 0xfa, - 0x78, 0x26, 0xe5, 0x74, 0x3c, 0x5f, 0x92, 0x26, 0x99, 0xf3, 0xfa, 0x56, 0xeb, 0xa3, - 0xe0, 0xe0, 0x77, 0x3c, + 0x5c, 0xb0, 0x1e, 0x28, 0x3d, 0x8b, 0x9e, 0xb1, 0x39, 0xe7, 0x4d, 0x4a, 0x72, 0xca, + 0x45, 0x14, 0x6b, 0xa7, 0xdd, 0x5e, 0x33, 0xe2, 0x79, 0xd3, 0x59, 0xd0, 0xc2, 0x75, + 0x01, 0x5a, 0xc1, 0x18, ], ovk: [ - 0x6c, 0xc7, 0xf9, 0xdc, 0xb8, 0x16, 0x9c, 0x38, 0x90, 0x97, 0x2f, 0xd3, 0x51, 0x04, - 0x13, 0x60, 0x4d, 0x0d, 0xdf, 0x82, 0xff, 0xfa, 0x0d, 0xc4, 0x58, 0xef, 0x5c, 0xd6, - 0xbb, 0x2f, 0x0d, 0x89, + 0x92, 0x13, 0x53, 0x2c, 0x80, 0xac, 0x0c, 0x31, 0x00, 0x1c, 0x08, 0x29, 0x67, 0x89, + 0x8c, 0xe1, 0x5e, 0xc6, 0x7e, 0xd5, 0xe6, 0x89, 0x65, 0x34, 0xb3, 0x3f, 0xc3, 0x4a, + 0x80, 0xda, 0x82, 0x83, ], dk: [ - 0xf8, 0xa0, 0x79, 0x29, 0x1e, 0x32, 0xce, 0x94, 0x4f, 0x0f, 0xfe, 0x65, 0x8e, 0xd8, - 0xfb, 0xdb, 0xfd, 0xb9, 0xa2, 0xd6, 0x96, 0x86, 0xe7, 0x44, 0xa5, 0xf7, 0xb5, 0x96, - 0xf1, 0x22, 0x57, 0xee, + 0x54, 0x72, 0xf9, 0x27, 0x27, 0x9e, 0xd7, 0xce, 0xc0, 0x9e, 0x60, 0xe7, 0x13, 0xd9, + 0xaf, 0x82, 0xe6, 0x79, 0x6f, 0x60, 0x9b, 0x83, 0xe7, 0xff, 0xdf, 0x2e, 0xbf, 0x16, + 0x4a, 0xd8, 0xa2, 0xb6, ], default_d: [ - 0x5c, 0x1b, 0x2f, 0x77, 0x6e, 0x19, 0x81, 0x35, 0xd0, 0xfd, 0x1f, + 0xac, 0xfb, 0x8d, 0xbc, 0x78, 0x27, 0x95, 0xb0, 0x21, 0xa1, 0xaf, ], default_pk_d: [ - 0x2a, 0x91, 0x7a, 0xe2, 0x42, 0x40, 0xb1, 0xa6, 0xaa, 0x67, 0x5b, 0x83, 0xa3, 0x78, - 0x25, 0x03, 0xeb, 0x71, 0x26, 0xd9, 0x99, 0x04, 0x9f, 0xb5, 0x7c, 0x70, 0x5e, 0xbc, - 0x01, 0x4e, 0x6b, 0x8f, + 0x5c, 0x9e, 0xac, 0x4a, 0x26, 0x36, 0xef, 0x27, 0x0b, 0xd8, 0x98, 0x6b, 0x72, 0xb7, + 0x01, 0x45, 0x5d, 0x40, 0x14, 0xbb, 0x83, 0xe8, 0x31, 0xa7, 0x04, 0x01, 0x75, 0x3d, + 0xc7, 0xf5, 0x58, 0x3b, ], internal_rivk: [ - 0xcd, 0x1d, 0xd3, 0x5e, 0xb9, 0xfa, 0xd9, 0x42, 0xb8, 0x69, 0xc8, 0x6f, 0xa1, 0x31, - 0x09, 0x83, 0x04, 0x78, 0x59, 0xfa, 0xe9, 0x09, 0xae, 0x97, 0x69, 0x7d, 0xa7, 0x0f, - 0xd5, 0x72, 0xa3, 0x16, + 0x52, 0x22, 0xd7, 0x35, 0x07, 0x6e, 0x53, 0x15, 0x2a, 0x3d, 0x00, 0x33, 0x19, 0x6e, + 0xe7, 0x3c, 0x7f, 0x6b, 0xf6, 0x08, 0xce, 0x1a, 0x7d, 0x54, 0xac, 0xfc, 0x04, 0x54, + 0x91, 0x87, 0xe7, 0x02, ], internal_ivk: [ - 0xa3, 0x36, 0xaa, 0x7a, 0xe3, 0xf6, 0xb5, 0x98, 0x3d, 0xad, 0xf0, 0x54, 0x93, 0xd5, - 0x76, 0xbe, 0x17, 0x31, 0x89, 0x7d, 0x36, 0x44, 0x83, 0x2b, 0x91, 0x81, 0xdd, 0xa1, - 0xbf, 0x7e, 0x1d, 0x17, + 0x44, 0xff, 0x25, 0xf6, 0xbd, 0x3e, 0xfc, 0xc1, 0x4a, 0x12, 0xdb, 0x7e, 0x2d, 0x2a, + 0xdd, 0xce, 0xe4, 0x84, 0x86, 0x22, 0xa9, 0x98, 0xb7, 0x83, 0x60, 0x88, 0x78, 0x36, + 0x0a, 0xb8, 0xd7, 0x24, ], internal_ovk: [ - 0x9f, 0xa3, 0xc3, 0xb0, 0x3a, 0xf8, 0xc3, 0xf7, 0x87, 0x44, 0x1a, 0x8c, 0x34, 0x07, - 0x8f, 0x6f, 0x36, 0xbb, 0xdc, 0xfc, 0x9b, 0x11, 0x0d, 0x3e, 0x27, 0x59, 0x57, 0xc4, - 0x43, 0x9a, 0x25, 0x48, + 0x21, 0x1d, 0x5c, 0x4e, 0x72, 0x3f, 0x62, 0xfc, 0xdd, 0x7f, 0x90, 0xe9, 0x54, 0xd1, + 0xba, 0x14, 0xe5, 0x9f, 0xb6, 0x0c, 0xdd, 0x7e, 0x44, 0xb7, 0xb9, 0x4a, 0x58, 0xcc, + 0x48, 0xfa, 0x96, 0x67, ], internal_dk: [ - 0x0c, 0xac, 0x83, 0xbf, 0x12, 0xf9, 0xc0, 0x56, 0x68, 0xa8, 0x3d, 0x27, 0x3d, 0x44, - 0x13, 0x85, 0x30, 0xd7, 0xa7, 0xf8, 0x76, 0x60, 0x21, 0xc5, 0x5b, 0x65, 0x03, 0xb1, - 0xda, 0xcc, 0xe5, 0x92, + 0xa6, 0xc2, 0x25, 0xd5, 0xac, 0xd0, 0x8e, 0x27, 0xb9, 0x46, 0x80, 0x71, 0x19, 0xc5, + 0xb0, 0x46, 0xb6, 0x97, 0x5c, 0xb1, 0xa0, 0x3a, 0xac, 0xf0, 0x89, 0x76, 0x39, 0xb0, + 0x65, 0x4c, 0x7e, 0x20, ], asset: [ - 0xe6, 0x10, 0x62, 0x0f, 0x71, 0xcd, 0xa8, 0xfc, 0x87, 0x76, 0x25, 0xf2, 0xc5, 0xbb, - 0x04, 0xcb, 0xe1, 0x22, 0x8b, 0x1e, 0x88, 0x6f, 0x40, 0x50, 0xaf, 0xd8, 0xfe, 0x94, - 0xe9, 0x7d, 0x2e, 0x9e, + 0x0c, 0x15, 0x13, 0xad, 0x47, 0xca, 0x61, 0xc6, 0x59, 0xcc, 0x5d, 0x32, 0x5b, 0x44, + 0x0f, 0x6b, 0x9f, 0x59, 0xaf, 0xf6, 0x68, 0x79, 0xbb, 0x66, 0x88, 0xfd, 0x28, 0x59, + 0x36, 0x2b, 0x18, 0x2f, ], - note_v: 17139625070743016316, + note_v: 7844555504117092638, note_rho: [ - 0x6c, 0x0b, 0x38, 0x99, 0xd4, 0x12, 0x22, 0xba, 0xce, 0x76, 0x0e, 0xe9, 0xc8, 0x81, - 0x8d, 0xed, 0x59, 0x9e, 0x34, 0xc5, 0x6d, 0x73, 0x72, 0xaf, 0x1e, 0xb8, 0x68, 0x52, - 0xf2, 0xa7, 0x32, 0x10, + 0xf3, 0x7b, 0xf6, 0xf3, 0xac, 0x2d, 0x26, 0xb8, 0x46, 0x86, 0xe5, 0x69, 0xd5, 0x8d, + 0x99, 0xc1, 0x38, 0x35, 0x97, 0xfa, 0xd8, 0x11, 0x93, 0xc4, 0xc1, 0xb1, 0x6e, 0x6a, + 0x90, 0xe2, 0xd5, 0x07, ], note_rseed: [ - 0x4b, 0xdb, 0x75, 0x07, 0x39, 0xde, 0x6c, 0x2c, 0x6e, 0x0f, 0x9e, 0xb7, 0xcb, 0x17, - 0xf1, 0x94, 0x2b, 0xfc, 0x9f, 0x4f, 0xd6, 0xeb, 0xb6, 0xb4, 0xcd, 0xd4, 0xda, 0x2b, - 0xca, 0x26, 0xfa, 0xc4, + 0xcd, 0xfe, 0x6f, 0xbd, 0xaa, 0x86, 0x16, 0x3e, 0x9c, 0xf5, 0xde, 0x31, 0x00, 0xfb, + 0xca, 0x7e, 0x8d, 0xa0, 0x47, 0xb0, 0x90, 0xdb, 0x9f, 0x37, 0x95, 0x2f, 0xbf, 0xee, + 0x76, 0xaf, 0x61, 0x66, ], note_cmx: [ - 0x22, 0x0c, 0xf6, 0xb7, 0xbd, 0x7d, 0xf1, 0x1a, 0xeb, 0x46, 0xb8, 0xf6, 0x52, 0x19, - 0x71, 0xe4, 0xf5, 0xce, 0xc6, 0x0e, 0x2c, 0x3a, 0xd1, 0x9e, 0x3b, 0x3f, 0x40, 0x7e, - 0x69, 0x4b, 0xe8, 0x01, + 0x2e, 0xc3, 0xc2, 0x5f, 0xed, 0x4b, 0x55, 0xf2, 0x3a, 0xef, 0xd4, 0x2a, 0x69, 0x61, + 0x59, 0x72, 0x69, 0x87, 0x74, 0xe6, 0x6c, 0xe2, 0x7f, 0x1b, 0x25, 0x6a, 0xce, 0x16, + 0x51, 0x7f, 0xc0, 0x3c, ], note_nf: [ - 0x0d, 0x35, 0x9b, 0x02, 0xf6, 0x2d, 0x72, 0x18, 0xc8, 0x93, 0xd0, 0x4e, 0xc0, 0xed, - 0xd4, 0x89, 0xb2, 0x33, 0xa3, 0xc6, 0x60, 0x15, 0xaf, 0x93, 0x93, 0x0b, 0x23, 0x30, - 0x35, 0x82, 0x07, 0x3f, + 0xaf, 0x67, 0xf7, 0xdf, 0x55, 0x93, 0xc3, 0x90, 0x80, 0x60, 0xb0, 0x50, 0x35, 0x96, + 0xef, 0x32, 0x0b, 0xad, 0x21, 0x30, 0x20, 0xa8, 0x44, 0x7b, 0x69, 0x38, 0x81, 0xf2, + 0xfd, 0x35, 0x9f, 0x11, ], }, ] diff --git a/src/value.rs b/src/value.rs index f575e2d31..ae3862726 100644 --- a/src/value.rs +++ b/src/value.rs @@ -462,7 +462,7 @@ pub mod testing { #[cfg(test)] mod tests { - use crate::note::asset_base::testing::{arb_asset_id, native_asset_id}; + use crate::note::asset_base::testing::{arb_asset_base, native_asset_base}; use crate::note::AssetBase; use proptest::prelude::*; @@ -532,17 +532,17 @@ mod tests { fn bsk_consistent_with_bvk_native_with_zsa_transfer_and_burning( native_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_id()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_base()), n_values) ) ), (asset_values, neg_trapdoors) in (1usize..10).prop_flat_map(|n_values| (arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound| - prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values) + prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_base()), n_values) ), prop::collection::vec(arb_trapdoor(), n_values)) ), burn_values in (1usize..10).prop_flat_map(|n_values| arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64) - .prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values)) + .prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_base()), n_values)) ) ) { check_binding_signature(&native_values, &[], &[], &[]); diff --git a/tests/zsa.rs b/tests/zsa.rs index dec5dcc1f..40b75f80c 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -58,7 +58,7 @@ fn prepare_keys() -> Keychain { let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); - let isk = IssuanceAuthorizingKey::from_bytes([0; 32]).unwrap(); + let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); let ik = IssuanceValidatingKey::from(&isk); Keychain { pk, @@ -73,12 +73,11 @@ fn prepare_keys() -> Keychain { fn sign_issue_bundle( unauthorized: IssueBundle, - rng: OsRng, isk: &IssuanceAuthorizingKey, ) -> IssueBundle { let sighash = unauthorized.commitment().into(); let proven = unauthorized.prepare(sighash); - proven.sign(rng, isk).unwrap() + proven.sign(isk).unwrap() } fn build_and_sign_bundle( @@ -161,7 +160,7 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { ) .is_ok()); - let issue_bundle = sign_issue_bundle(unauthorized, rng, keys.isk()); + let issue_bundle = sign_issue_bundle(unauthorized, keys.isk()); // Take notes from first action let notes = issue_bundle.get_all_notes(); From d8e2bc63c1793da684a9b7194568f54c648cc9c0 Mon Sep 17 00:00:00 2001 From: Kris Nuttycombe Date: Sun, 24 Mar 2024 19:23:51 -0600 Subject: [PATCH 55/92] orchard release version 0.8.0 --- CHANGELOG.md | 5 +++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 995654890..edf7a5608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,16 @@ and this project adheres to Rust's notion of ## [Unreleased] +## [0.8.0] - 2024-03-25 + ### Added - `orchard::note::Rho` - `orchard::action::Action::rho` - `orchard::note_encryption::CompactAction::rho` - `orchard::note_encryption::OrchardDomain::for_compact_action` +- Additions under the `test-dependencies` feature flag: + - `orchard::tree::MerkleHashOrchard::random` + - `impl Distribution for Standard` ### Changed - The following methods have their `Nullifier`-typed argument or return value diff --git a/Cargo.lock b/Cargo.lock index b7c63ea24..b525d0ada 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1412,7 +1412,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" -version = "0.7.1" +version = "0.8.0" dependencies = [ "aes", "bitvec", diff --git a/Cargo.toml b/Cargo.toml index 48074dd81..0ea1d289d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orchard" -version = "0.7.1" +version = "0.8.0" authors = [ "Sean Bowe ", "Jack Grigg ", From f3d945997f13155bcf28257992079c85d8657583 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 24 Apr 2024 11:24:37 +0200 Subject: [PATCH 56/92] Fix compilation errors after the merge (there're still several complilation errors in tests) --- Cargo.lock | 807 ++++++++++++++++++-------------------- src/builder.rs | 166 ++++++-- src/circuit.rs | 19 +- src/issuance.rs | 22 +- src/keys.rs | 13 +- src/note.rs | 4 +- src/note/nullifier.rs | 2 +- src/note_encryption_v3.rs | 38 +- src/zip32.rs | 2 +- 9 files changed, 576 insertions(+), 497 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c13f09fe..e2e8971ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -40,21 +40,22 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "getrandom", "once_cell", "version_check", + "zerocopy", ] [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -82,9 +83,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "arrayref" @@ -111,15 +112,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -171,9 +172,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -229,21 +230,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cast" @@ -262,12 +263,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -301,23 +299,23 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.30" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -326,18 +324,18 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half 1.8.2", + "half", ] [[package]] @@ -359,7 +357,7 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "bitflags 1.3.2", "clap_lex", - "indexmap", + "indexmap 1.9.3", "textwrap", ] @@ -372,15 +370,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "color_quant" version = "1.1.0" @@ -407,9 +396,9 @@ checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -417,9 +406,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" @@ -436,9 +425,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -468,18 +457,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -522,46 +511,37 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -633,7 +613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.0", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core", @@ -753,9 +733,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "elliptic-curve" @@ -777,35 +757,30 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.3" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys", ] [[package]] name = "exr" -version = "1.7.0" +version = "1.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" dependencies = [ "bit_field", "flume", - "half 2.2.1", + "half", "lebe", "miniz_oxide", "rayon-core", @@ -815,15 +790,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -853,9 +828,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -869,14 +844,10 @@ checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" [[package]] name = "flume" -version = "0.10.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", "spin 0.9.8", ] @@ -942,9 +913,9 @@ dependencies = [ [[package]] name = "freetype" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +checksum = "efc8599a3078adf8edeb86c71e9f8fa7d88af5ca31e806a867756081f90f5d83" dependencies = [ "freetype-sys", "libc", @@ -952,11 +923,11 @@ dependencies = [ [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "66ee28c39a43d89fbed8b4798fb4ba56722cfd2b5af81f9326c27614ba88ecd5" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -967,18 +938,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - [[package]] name = "generic-array" version = "0.14.7" @@ -992,22 +951,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] name = "gif" -version = "0.11.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ "color_quant", "weezl", @@ -1015,9 +972,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" dependencies = [ "color_quant", "weezl", @@ -1025,9 +982,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "group" @@ -1041,12 +998,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - [[package]] name = "half" version = "2.2.1" @@ -1105,9 +1056,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" @@ -1120,9 +1071,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1141,16 +1092,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1170,31 +1121,32 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "image" -version = "0.24.4" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8e4fb07cf672b1642304e731ef8a6a4c7891d67bb4fd4f5ce58cd6ed86803c" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", "color_quant", "exr", - "gif 0.11.4", + "gif 0.13.1", "jpeg-decoder", - "num-rational", "num-traits", "png", - "scoped_threadpool", + "qoi", "tiff", ] [[package]] name = "incrementalmerkletree" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361c467824d4d9d4f284be4b2608800839419dccc4d4608f28345237fe354623" +checksum = "eb1872810fb725b06b8c153dde9e86f3ec26747b9b60096da7a869883b549cbe" dependencies = [ "either", "proptest", + "rand", + "rand_core", ] [[package]] @@ -1207,22 +1159,31 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "inferno" -version = "0.11.14" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6e66fa9bb3c52f40d05c11b78919ff2f18993c2305bd8a62556d20cb3e9606f" +checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash", - "atty", "crossbeam-channel", "crossbeam-utils", "dashmap", - "indexmap", + "indexmap 2.2.6", + "is-terminal", "itoa", "log", "num-format", - "num_cpus", "once_cell", "quick-xml", "rgb", @@ -1238,6 +1199,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1249,24 +1221,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jpeg-decoder" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" dependencies = [ "rayon", ] [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1316,37 +1288,47 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys", + "windows-targets 0.52.5", ] [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1354,9 +1336,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "maybe-rayon" @@ -1370,9 +1352,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.3" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memmap2" @@ -1383,15 +1365,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - [[package]] name = "memuse" version = "0.2.1" @@ -1403,23 +1376,14 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", -] - [[package]] name = "nix" version = "0.26.4" @@ -1460,50 +1424,28 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.2", - "libc", -] - [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -1522,9 +1464,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "orchard" @@ -1564,9 +1506,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "parking_lot" @@ -1580,15 +1522,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -1618,49 +1560,18 @@ dependencies = [ [[package]] name = "pathfinder_simd" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" +checksum = "ebf45976c56919841273f2a0fc684c28437e2f304e264557d9c72be5d5a718be" dependencies = [ "rustc_version", ] -[[package]] -name = "pest" -version = "2.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.31", -] - [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pkcs8" @@ -1674,9 +1585,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plotters" @@ -1726,9 +1637,9 @@ dependencies = [ [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1778,33 +1689,42 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax", "rusty-fork", "tempfile", "unarray", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1822,9 +1742,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1876,9 +1796,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1886,14 +1806,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1916,67 +1834,52 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.7.5", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.5" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rfc6979" @@ -1990,9 +1893,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" dependencies = [ "bytemuck", ] @@ -2005,20 +1908,20 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc_version" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.11" +version = "0.38.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2039,9 +1942,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -2052,12 +1955,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" version = "1.2.0" @@ -2080,47 +1977,35 @@ dependencies = [ [[package]] name = "semver" -version = "0.11.0" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.60", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2156,9 +2041,9 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" @@ -2251,9 +2136,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.31" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2279,48 +2164,47 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", "rustix", "windows-sys", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.60", ] [[package]] name = "tiff" -version = "0.7.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f71e422515e83e3ab8a03d4781d05ebf864fc61f4546e6ecffa58cbd34181a0" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ "flate2", "jpeg-decoder", @@ -2339,11 +2223,10 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2351,20 +2234,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.60", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -2377,15 +2260,9 @@ checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" [[package]] name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.6" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uint" @@ -2407,9 +2284,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "universal-hash" @@ -2423,9 +2300,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] name = "version_check" @@ -2444,9 +2321,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2460,9 +2337,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2470,24 +2347,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.60", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2495,28 +2372,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2524,9 +2401,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" @@ -2546,9 +2423,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -2560,21 +2437,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] [[package]] @@ -2583,13 +2460,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -2598,42 +2491,90 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "wio" version = "0.2.2" @@ -2667,7 +2608,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#e14dab6945177815f2b13fbee9c61e12caa96e5a" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#8b6b31dcea4a883a606425c4b644fca213e78b3b" dependencies = [ "chacha20", "chacha20poly1305", @@ -2685,6 +2626,26 @@ dependencies = [ "blake2b_simd", ] +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "zeroize" version = "1.7.0" @@ -2702,14 +2663,14 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.31", + "syn 2.0.60", ] [[package]] name = "zip32" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d724a63be4dfb50b7f3617e542984e22e4b4a5b8ca5de91f55613152885e6b22" +checksum = "4226d0aee9c9407c27064dfeec9d7b281c917de3374e1e5a2e2cfad9e09de19e" dependencies = [ "blake2b_simd", "memuse", diff --git a/src/builder.rs b/src/builder.rs index 44db4fec7..b5bf6031b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -10,7 +10,6 @@ use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; -use crate::note::AssetBase; use crate::{ action::Action, address::Address, @@ -20,7 +19,7 @@ use crate::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, }, - note::{Note, Rho, TransmittedNoteCiphertext}, + note::{AssetBase, Note, Rho, TransmittedNoteCiphertext}, note_encryption_v3::OrchardNoteEncryption, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, @@ -54,7 +53,7 @@ impl BundleType { bundle_required: false, }; - // FIXME: add doc + /// FIXME: add doc pub const DEFAULT_ZSA: BundleType = BundleType::Transactional { flags: Flags::ENABLED_ZSA, bundle_required: false, @@ -67,6 +66,12 @@ impl BundleType { bundle_required: false, }; + /// FIXME: add doc + pub const ZSA_DISABLED: BundleType = BundleType::Transactional { + flags: Flags::from_parts(true, true, false), + bundle_required: false, + }; + /// Returns the number of logical actions that builder will produce in constructing a bundle /// of this type, given the specified numbers of spends and outputs. /// @@ -299,7 +304,7 @@ impl SpendInfo { } /// Information about a specific output to receive funds in an [`Action`]. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct OutputInfo { ovk: Option, recipient: Address, @@ -532,7 +537,7 @@ impl Builder { return Err(SpendError::SpendsDisabled); } - let spend = SpendInfo::new(fvk, note, merkle_path).ok_or(SpendError::FvkMismatch)?; + let spend = SpendInfo::new(fvk, note, merkle_path, false).ok_or(SpendError::FvkMismatch)?; // Consistency check: all anchors must be equal. if !spend.has_matching_anchor(&self.anchor) { @@ -621,7 +626,7 @@ impl Builder { /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. - pub fn build>( + pub fn build + TryFrom>( self, rng: impl RngCore, ) -> Result, BundleMetadata)>, BuildError> { @@ -631,20 +636,85 @@ impl Builder { self.bundle_type, self.spends, self.outputs, + self.burn, ) } } +/// Partition a list of spends and recipients by note types. +/// Method creates single dummy ZEC note if spends and recipients are both empty. +fn partition_by_asset( + spends: &[SpendInfo], + outputs: &[OutputInfo], + rng: &mut impl RngCore, +) -> HashMap< + AssetBase, + ( + Vec<(Option, SpendInfo)>, + Vec<(Option, OutputInfo)>, + ), +> { + let mut hm: HashMap< + AssetBase, + ( + Vec<(Option, SpendInfo)>, + Vec<(Option, OutputInfo)>, + ), + > = HashMap::new(); + + for (i, s) in spends.into_iter().enumerate() { + hm.entry(s.note.asset()) + .or_insert((vec![], vec![])) + .0 + .push((Some(i), s.clone())); + } + + for (i, o) in outputs.into_iter().enumerate() { + hm.entry(o.asset) + .or_insert((vec![], vec![])) + .1 + .push((Some(i), o.clone())); + } + + if hm.is_empty() { + let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng); + hm.insert( + dummy_spend.note.asset(), + (vec![(None, dummy_spend)], vec![]), + ); + } + + hm +} + +/// Returns a dummy/split notes to extend the spends. +fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) -> SpendInfo { + if asset.is_native().into() { + // For native asset, extends with dummy notes + SpendInfo::dummy(asset, &mut rng) + } else { + // For ZSA asset, extends with + // - dummy notes if first spend is empty + // - split notes otherwise. + let dummy = SpendInfo::dummy(asset, &mut rng); + spend.map_or_else(|| dummy, |s| s.create_split_spend(&mut rng)) + } +} + +// FIXME: the order of the arguments doesn't correspond the order of the fields of the Builder +// struct - is that okay? + /// Builds a bundle containing the given spent notes and outputs. /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. -pub fn bundle>( +pub fn bundle + TryFrom>( mut rng: impl RngCore, anchor: Anchor, bundle_type: BundleType, spends: Vec, outputs: Vec, + burn: HashMap, ) -> Result, BundleMetadata)>, BuildError> { let flags = bundle_type.flags(); @@ -670,39 +740,51 @@ pub fn bundle>( // Pair up the spends and outputs, extending with dummy values as necessary. let (pre_actions, bundle_meta) = { - let mut indexed_spends = spends - .into_iter() - .chain(iter::repeat_with(|| SpendInfo::dummy(&mut rng))) - .enumerate() - .take(num_actions) - .collect::>(); + let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); - let mut indexed_outputs = outputs + let pre_actions = partition_by_asset(&spends, &outputs, &mut rng) .into_iter() - .chain(iter::repeat_with(|| OutputInfo::dummy(&mut rng))) - .enumerate() - .take(num_actions) - .collect::>(); - - // Shuffle the spends and outputs, so that learning the position of a - // specific spent note or output note doesn't reveal anything on its own about - // the meaning of that note in the transaction context. - indexed_spends.shuffle(&mut rng); - indexed_outputs.shuffle(&mut rng); - - let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); - let pre_actions = indexed_spends + .flat_map(|(asset, (spends, outputs))| { + let first_spend = spends.first().map(|(_, s)| s).cloned(); + + let mut indexed_spends = spends + .into_iter() + .chain(iter::repeat_with(|| { + (None, pad_spend(first_spend.as_ref(), asset, &mut rng)) + })) + .take(num_actions) + .collect::>(); + + let mut indexed_outputs = outputs + .into_iter() + .chain(iter::repeat_with(|| { + (None, OutputInfo::dummy(&mut rng, asset)) + })) + .take(num_actions) + .collect::>(); + + // Shuffle the spends and outputs, so that learning the position of a + // specific spent note or output note doesn't reveal anything on its own about + // the meaning of that note in the transaction context. + indexed_spends.shuffle(&mut rng); + indexed_outputs.shuffle(&mut rng); + + indexed_spends.into_iter().zip(indexed_outputs.into_iter()) + }) + // FIXME: this collect is used to release the borrow of rng + // - try to find another way to do that, as there's the second + // collect below - two collects don't look good + .collect::>() .into_iter() - .zip(indexed_outputs.into_iter()) .enumerate() .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { // Record the post-randomization spend location - if spend_idx < num_requested_spends { + if let Some(spend_idx) = spend_idx { bundle_meta.spend_indices[spend_idx] = action_idx; } // Record the post-randomization output location - if out_idx < num_requested_outputs { + if let Some(out_idx) = out_idx { bundle_meta.output_indices[out_idx] = action_idx; } @@ -736,18 +818,18 @@ pub fn bundle>( let (actions, circuits): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); - // Verify that bsk and bvk are consistent. - let bvk = (actions.iter().map(|a| a.cv_net()).sum::() - - ValueCommitment::derive(value_balance, ValueCommitTrapdoor::zero())) - .into_bvk(); - assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); + let burn = burn + .into_iter() + .map(|(asset, value)| Ok((asset, value.into()?))) + .collect::>()?; - Ok(NonEmpty::from_vec(actions).map(|actions| { + let bundle = NonEmpty::from_vec(actions).map(|actions| { ( Bundle::from_parts( actions, flags, result_value_balance, + burn, anchor, InProgress { proof: Unproven { circuits }, @@ -756,7 +838,17 @@ pub fn bundle>( ), bundle_meta, ) - })) + }); + + // Verify that bsk and bvk are consistent. + if let Some((bundle, _)) = &bundle { + assert_eq!( + redpallas::VerificationKey::from(&bundle.authorization().sigs.bsk), + bundle.binding_validating_key() + ) + } + + Ok(bundle) } /// Marker trait representing bundle signatures in the process of being created. diff --git a/src/circuit.rs b/src/circuit.rs index 5473fef41..0baf1bdc3 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1210,12 +1210,17 @@ mod tests { let nk = *fvk.nk(); let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); let nf_old = spent_note.nullifier(&fvk); - let rho = Rho::from_nf_old(nf_old); + // FIXME: why it became unused? + //let rho = Rho::from_nf_old(nf_old); let ak: SpendValidatingKey = fvk.into(); let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); - let (_, _, output_note) = Note::dummy(&mut rng, Some(nf_old), AssetBase::native()); + let (_, _, output_note) = Note::dummy( + &mut rng, + Some(Rho::from_nf_old(nf_old)), + AssetBase::native(), + ); let cmx = output_note.commitment().into(); let value = spent_note.value() - output_note.value(); @@ -1495,7 +1500,7 @@ mod tests { let sk = SpendingKey::random(&mut rng); let fvk: FullViewingKey = (&sk).into(); let sender_address = fvk.address_at(0u32, Scope::External); - let rho_old = Nullifier::dummy(&mut rng); + let rho_old = Rho::from_nf_old(Nullifier::dummy(&mut rng)); let note = Note::new( sender_address, NoteValue::from_raw(40), @@ -1539,7 +1544,13 @@ mod tests { let fvk: FullViewingKey = (&sk).into(); let sender_address = fvk.address_at(0u32, Scope::External); - Note::new(sender_address, output_value, asset_base, nf_old, &mut rng) + Note::new( + sender_address, + output_value, + asset_base, + Rho::from_nf_old(nf_old), + &mut rng, + ) }; let cmx = output_note.commitment().into(); diff --git a/src/issuance.rs b/src/issuance.rs index f2eec90c6..4fade4b74 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -15,7 +15,7 @@ use crate::issuance::Error::{ }; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use crate::note::asset_base::is_asset_desc_of_valid_size; -use crate::note::{AssetBase, Nullifier}; +use crate::note::{AssetBase, Nullifier, Rho}; use crate::value::{NoteValue, ValueSum}; use crate::{Address, Note}; @@ -287,7 +287,7 @@ impl IssueBundle { issue_info.recipient, issue_info.value, asset, - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -335,7 +335,7 @@ impl IssueBundle { recipient, value, asset, - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -597,7 +597,7 @@ mod tests { use crate::keys::{ FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; - use crate::note::{AssetBase, Nullifier}; + use crate::note::{AssetBase, Nullifier, Rho}; use crate::value::{NoteValue, ValueSum}; use crate::{Address, Note}; use group::{Group, GroupEncoding}; @@ -644,7 +644,7 @@ mod tests { recipient, NoteValue::from_raw(note1_value), asset, - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -652,7 +652,7 @@ mod tests { recipient, NoteValue::from_raw(note2_value), note2_asset, - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -679,7 +679,7 @@ mod tests { recipient, NoteValue::from_raw(note1_value), identity_point(), - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -687,7 +687,7 @@ mod tests { recipient, NoteValue::from_raw(note2_value), identity_point(), - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -963,7 +963,7 @@ mod tests { recipient, NoteValue::from_raw(5), AssetBase::derive(bundle.ik(), "zsa_asset"), - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); bundle.actions.first_mut().notes.push(note); @@ -1226,7 +1226,7 @@ mod tests { recipient, NoteValue::from_raw(5), AssetBase::derive(signed.ik(), "zsa_asset"), - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -1267,7 +1267,7 @@ mod tests { recipient, NoteValue::from_raw(55), AssetBase::derive(&incorrect_ik, asset_description), - Nullifier::dummy(&mut rng), + Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); diff --git a/src/keys.rs b/src/keys.rs index 3777e915d..eddd4dcc4 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,6 +1,5 @@ //! Key structures for Orchard. -use core::mem; use std::{ fmt::{Debug, Formatter}, io::{self, Read, Write}, @@ -26,7 +25,7 @@ use pasta_curves::{pallas, pallas::Scalar}; use rand::{rngs::OsRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_note_encryption_zsa::EphemeralKeyBytes; -use zip32::{AccountId, ChildIndex}; +//use zip32::{AccountId, ChildIndex}; use crate::{ address::Address, @@ -37,12 +36,12 @@ use crate::{ PreparedNonIdentityBase, PreparedNonZeroScalar, PrfExpand, }, zip32::{ - self, ChildIndex, ExtendedSpendingKey, ZIP32_ORCHARD_PERSONALIZATION, + self, ExtendedSpendingKey, ZIP32_ORCHARD_PERSONALIZATION, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE, }, }; -pub use zip32::{DiversifierIndex, Scope}; +pub use ::zip32::{AccountId, ChildIndex, DiversifierIndex, Scope}; const KDF_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_OrchardKDF"; const ZIP32_PURPOSE: u32 = 32; @@ -278,9 +277,9 @@ impl IssuanceAuthorizingKey { ) -> Result { // Call zip32 logic let path = &[ - ChildIndex::try_from(ZIP32_PURPOSE_FOR_ISSUANCE)?, - ChildIndex::try_from(coin_type)?, - ChildIndex::try_from(account)?, + ChildIndex::hardened(ZIP32_PURPOSE_FOR_ISSUANCE), + ChildIndex::hardened(coin_type), + ChildIndex::hardened(account), ]; // we are reusing zip32 logic for deriving the key, zip32 should be updated as discussed diff --git a/src/note.rs b/src/note.rs index f79015e7a..bc036dfa2 100644 --- a/src/note.rs +++ b/src/note.rs @@ -416,7 +416,7 @@ pub mod testing { pub fn arb_native_note()( recipient in arb_address(), value in arb_note_value(), - rho in arb_nullifier(), + rho in arb_nullifier().prop_map(Rho::from_nf_old), rseed in arb_rseed(), ) -> Note { Note { @@ -435,7 +435,7 @@ pub mod testing { pub fn arb_zsa_note(asset: AssetBase)( recipient in arb_address(), value in arb_note_value(), - rho in arb_nullifier(), + rho in arb_nullifier().prop_map(Rho::from_nf_old), rseed in arb_rseed(), ) -> Note { Note { diff --git a/src/note/nullifier.rs b/src/note/nullifier.rs index 0c81f7bea..6c41a87a2 100644 --- a/src/note/nullifier.rs +++ b/src/note/nullifier.rs @@ -3,7 +3,7 @@ use halo2_proofs::arithmetic::CurveExt; use memuse::DynamicUsage; use pasta_curves::pallas; use rand::RngCore; -use subtle::{Choice, ConstantTimeEq, CtOption}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use super::NoteCommitment; use crate::{ diff --git a/src/note_encryption_v3.rs b/src/note_encryption_v3.rs index ceff0cbe2..8fb68dbd0 100644 --- a/src/note_encryption_v3.rs +++ b/src/note_encryption_v3.rs @@ -15,7 +15,7 @@ use crate::{ DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, + note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho}, value::{NoteValue, ValueCommitment}, Address, Note, }; @@ -75,6 +75,18 @@ impl AsRef<[u8]> for NoteCiphertextBytes { } } +impl AsMut<[u8]> for NoteCiphertextBytes { + fn as_mut(&mut self) -> &mut [u8] { + self.0.as_mut() + } +} + +impl From<(&[u8], &[u8])> for NoteCiphertextBytes { + fn from(s: (&[u8], &[u8])) -> Self { + Self([s.0, s.1].concat().try_into().unwrap()) + } +} + impl From<&[u8]> for NoteCiphertextBytes { fn from(s: &[u8]) -> Self where @@ -177,20 +189,18 @@ where /// Orchard-specific note encryption logic. #[derive(Debug)] pub struct OrchardDomainV3 { - rho: Nullifier, + rho: Rho, } impl OrchardDomainV3 { /// Constructs a domain that can be used to trial-decrypt this action's output note. pub fn for_action(act: &Action) -> Self { - OrchardDomainV3 { - rho: *act.nullifier(), - } + Self { rho: act.rho() } } - /// Constructs a domain from a nullifier. - pub fn for_nullifier(nullifier: Nullifier) -> Self { - OrchardDomainV3 { rho: nullifier } + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_compact_action(act: &CompactAction) -> Self { + Self { rho: act.rho() } } } @@ -443,6 +453,11 @@ impl CompactAction { pub fn nullifier(&self) -> Nullifier { self.nullifier } + + /// Obtains the [`Rho`] value that was used to construct the new note being created. + pub fn rho(&self) -> Rho { + Rho::from_nf_old(self.nullifier) + } } #[cfg(test)] @@ -465,7 +480,7 @@ mod tests { OutgoingViewingKey, PreparedIncomingViewingKey, }, note::{ - testing::arb_note, AssetBase, ExtractedNoteCommitment, Nullifier, RandomSeed, + testing::arb_note, AssetBase, ExtractedNoteCommitment, Nullifier, RandomSeed, Rho, TransmittedNoteCiphertext, }, primitives::redpallas, @@ -522,7 +537,8 @@ mod tests { // Received Action let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); - let rho = Nullifier::from_bytes(&tv.rho).unwrap(); + let nf_old = Nullifier::from_bytes(&tv.rho).unwrap(); + let rho = Rho::from_nf_old(nf_old); let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); @@ -554,7 +570,7 @@ mod tests { let action = Action::from_parts( // rho is the nullifier in the receiving Action. - rho, + nf_old, // We don't need a valid rk for this test. redpallas::VerificationKey::dummy(), cmx, diff --git a/src/zip32.rs b/src/zip32.rs index 6636ca69d..2a036ec9b 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -280,7 +280,7 @@ mod tests { assert!(bool::from( ExtendedSpendingKey::from_path( &seed, - &[ChildIndex::hardened(5), ChildIndex::hardened(7)] + &[ChildIndex::hardened(5), ChildIndex::hardened(7)], ZIP32_ORCHARD_PERSONALIZATION ) .unwrap() From 0f56f526b7dde6d16a5861feb9af0b2fa0707ec3 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 25 Apr 2024 09:07:21 +0200 Subject: [PATCH 57/92] Fix compilation errors in tests --- src/builder.rs | 105 ++++++++++++++++++++++--------------------------- tests/zsa.rs | 15 ++++--- 2 files changed, 54 insertions(+), 66 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index b5bf6031b..9d1232708 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -643,45 +643,31 @@ impl Builder { /// Partition a list of spends and recipients by note types. /// Method creates single dummy ZEC note if spends and recipients are both empty. +#[allow(clippy::type_complexity)] fn partition_by_asset( spends: &[SpendInfo], outputs: &[OutputInfo], rng: &mut impl RngCore, -) -> HashMap< - AssetBase, - ( - Vec<(Option, SpendInfo)>, - Vec<(Option, OutputInfo)>, - ), -> { - let mut hm: HashMap< - AssetBase, - ( - Vec<(Option, SpendInfo)>, - Vec<(Option, OutputInfo)>, - ), - > = HashMap::new(); +) -> HashMap, Vec<(usize, OutputInfo)>)> { + let mut hm = HashMap::new(); - for (i, s) in spends.into_iter().enumerate() { + for (i, s) in spends.iter().enumerate() { hm.entry(s.note.asset()) .or_insert((vec![], vec![])) .0 - .push((Some(i), s.clone())); + .push((i, s.clone())); } - for (i, o) in outputs.into_iter().enumerate() { + for (i, o) in outputs.iter().enumerate() { hm.entry(o.asset) .or_insert((vec![], vec![])) .1 - .push((Some(i), o.clone())); + .push((i, o.clone())); } if hm.is_empty() { let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng); - hm.insert( - dummy_spend.note.asset(), - (vec![(None, dummy_spend)], vec![]), - ); + hm.insert(dummy_spend.note.asset(), (vec![(0, dummy_spend)], vec![])); } hm @@ -739,52 +725,55 @@ pub fn bundle + TryFrom>( .map_err(|_| BuildError::BundleTypeNotSatisfiable)?; // Pair up the spends and outputs, extending with dummy values as necessary. + // FIXME: cargo clippy suggests to avoid using collect for spends + // but the direct fix causes compilation error (bacause of rbg borrowing) + #[allow(clippy::needless_collect)] let (pre_actions, bundle_meta) = { - let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); + let (mut indexed_spends, mut indexed_outputs): (Vec<_>, Vec<_>) = + partition_by_asset(&spends, &outputs, &mut rng) + .into_iter() + .flat_map(|(asset, (spends, outputs))| { + let first_spend = spends.first().map(|(_, s)| s.clone()); + + let indexed_spends = spends + .into_iter() + .chain(iter::repeat_with(|| { + (0, pad_spend(first_spend.as_ref(), asset, &mut rng)) + })) + .take(num_actions) + .collect::>(); + + let indexed_outputs = outputs + .into_iter() + .chain(iter::repeat_with(|| { + (0, OutputInfo::dummy(&mut rng, asset)) + })) + .take(num_actions) + .collect::>(); + + indexed_spends.into_iter().zip(indexed_outputs) + }) + .unzip(); - let pre_actions = partition_by_asset(&spends, &outputs, &mut rng) - .into_iter() - .flat_map(|(asset, (spends, outputs))| { - let first_spend = spends.first().map(|(_, s)| s).cloned(); - - let mut indexed_spends = spends - .into_iter() - .chain(iter::repeat_with(|| { - (None, pad_spend(first_spend.as_ref(), asset, &mut rng)) - })) - .take(num_actions) - .collect::>(); - - let mut indexed_outputs = outputs - .into_iter() - .chain(iter::repeat_with(|| { - (None, OutputInfo::dummy(&mut rng, asset)) - })) - .take(num_actions) - .collect::>(); - - // Shuffle the spends and outputs, so that learning the position of a - // specific spent note or output note doesn't reveal anything on its own about - // the meaning of that note in the transaction context. - indexed_spends.shuffle(&mut rng); - indexed_outputs.shuffle(&mut rng); - - indexed_spends.into_iter().zip(indexed_outputs.into_iter()) - }) - // FIXME: this collect is used to release the borrow of rng - // - try to find another way to do that, as there's the second - // collect below - two collects don't look good - .collect::>() + // Shuffle the spends and outputs, so that learning the position of a + // specific spent note or output note doesn't reveal anything on its own about + // the meaning of that note in the transaction context. + indexed_spends.shuffle(&mut rng); + indexed_outputs.shuffle(&mut rng); + + let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); + let pre_actions = indexed_spends .into_iter() + .zip(indexed_outputs.into_iter()) .enumerate() .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { // Record the post-randomization spend location - if let Some(spend_idx) = spend_idx { + if spend_idx < num_requested_spends { bundle_meta.spend_indices[spend_idx] = action_idx; } // Record the post-randomization output location - if let Some(out_idx) = out_idx { + if out_idx < num_requested_outputs { bundle_meta.output_indices[out_idx] = action_idx; } diff --git a/tests/zsa.rs b/tests/zsa.rs index 40b75f80c..4d6826b08 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -10,8 +10,7 @@ use orchard::note::{AssetBase, ExtractedNoteCommitment}; use orchard::note_encryption_v3::OrchardDomainV3; use orchard::tree::{MerkleHashOrchard, MerklePath}; use orchard::{ - builder::Builder, - bundle::Flags, + builder::{Builder, BundleType}, circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, value::NoteValue, @@ -86,7 +85,7 @@ fn build_and_sign_bundle( pk: &ProvingKey, sk: &SpendingKey, ) -> Bundle { - let unauthorized = builder.build(&mut rng).unwrap(); + let unauthorized = builder.build(&mut rng).unwrap().unwrap().0; let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(pk, &mut rng).unwrap(); proven @@ -184,9 +183,9 @@ fn create_native_note(keys: &Keychain) -> Note { // Use the empty tree. let anchor = MerkleHashOrchard::empty_root(32.into()).into(); - let mut builder = Builder::new(Flags::from_parts(false, true, false), anchor); + let mut builder = Builder::new(BundleType::Coinbase, anchor); assert_eq!( - builder.add_recipient( + builder.add_output( None, keys.recipient, NoteValue::from_raw(100), @@ -195,7 +194,7 @@ fn create_native_note(keys: &Keychain) -> Note { ), Ok(()) ); - let unauthorized = builder.build(&mut rng).unwrap(); + let unauthorized = builder.build(&mut rng).unwrap().unwrap().0; let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(keys.pk(), &mut rng).unwrap(); proven.apply_signatures(rng, sighash, &[]).unwrap() @@ -239,7 +238,7 @@ fn build_and_verify_bundle( ) -> Result<(), String> { let rng = OsRng; let shielded_bundle: Bundle<_, i64> = { - let mut builder = Builder::new(Flags::from_parts(true, true, true), anchor); + let mut builder = Builder::new(BundleType::DEFAULT_ZSA, anchor); spends .iter() @@ -250,7 +249,7 @@ fn build_and_verify_bundle( outputs .iter() .try_for_each(|output| { - builder.add_recipient(None, keys.recipient, output.value, output.asset, None) + builder.add_output(None, keys.recipient, output.value, output.asset, None) }) .map_err(|err| err.to_string())?; assets_to_burn From 149827dd6ffa269e9813279600bd42cca026d7d5 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 25 Apr 2024 10:51:59 +0200 Subject: [PATCH 58/92] Fix cargo doc issues --- src/note.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/note.rs b/src/note.rs index bc036dfa2..f5b8d30a0 100644 --- a/src/note.rs +++ b/src/note.rs @@ -36,7 +36,7 @@ impl Rho { /// value otherwise. /// /// [`Action::rho`]: crate::action::Action::rho - /// [`CompactAction::rho`]: crate::note_encryption::CompactAction::rho + /// [`CompactAction::rho`]: crate::note_encryption_v3::CompactAction::rho pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { pallas::Base::from_repr(*bytes).map(Rho) } From c8c84aa02f123c7e86295c10f005f41a2ec13876 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 29 Apr 2024 10:40:27 +0200 Subject: [PATCH 59/92] Fix Builder::bundle function to pass unit tests from tests folder correctly --- src/builder.rs | 194 ++++++++++++++++++++++++------------------------- 1 file changed, 95 insertions(+), 99 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 9d1232708..3e2b8c972 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -667,7 +667,10 @@ fn partition_by_asset( if hm.is_empty() { let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng); - hm.insert(dummy_spend.note.asset(), (vec![(0, dummy_spend)], vec![])); + hm.insert( + dummy_spend.note.asset(), + (vec![(usize::MAX, dummy_spend)], vec![]), + ); } hm @@ -720,81 +723,86 @@ pub fn bundle + TryFrom>( return Err(BuildError::OutputsDisabled); } - let num_actions = bundle_type - .num_actions(num_requested_spends, num_requested_outputs) - .map_err(|_| BuildError::BundleTypeNotSatisfiable)?; + // The number of actions to add to this bundle in order to contain at least MIN_ACTION actions. + let num_missing_actions = MIN_ACTIONS.saturating_sub(spends.len().max(outputs.len())); // Pair up the spends and outputs, extending with dummy values as necessary. - // FIXME: cargo clippy suggests to avoid using collect for spends - // but the direct fix causes compilation error (bacause of rbg borrowing) - #[allow(clippy::needless_collect)] - let (pre_actions, bundle_meta) = { - let (mut indexed_spends, mut indexed_outputs): (Vec<_>, Vec<_>) = - partition_by_asset(&spends, &outputs, &mut rng) - .into_iter() - .flat_map(|(asset, (spends, outputs))| { - let first_spend = spends.first().map(|(_, s)| s.clone()); - - let indexed_spends = spends - .into_iter() - .chain(iter::repeat_with(|| { - (0, pad_spend(first_spend.as_ref(), asset, &mut rng)) - })) - .take(num_actions) - .collect::>(); - - let indexed_outputs = outputs - .into_iter() - .chain(iter::repeat_with(|| { - (0, OutputInfo::dummy(&mut rng, asset)) - })) - .take(num_actions) - .collect::>(); - - indexed_spends.into_iter().zip(indexed_outputs) - }) - .unzip(); - - // Shuffle the spends and outputs, so that learning the position of a - // specific spent note or output note doesn't reveal anything on its own about - // the meaning of that note in the transaction context. - indexed_spends.shuffle(&mut rng); - indexed_outputs.shuffle(&mut rng); - - let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); - let pre_actions = indexed_spends - .into_iter() - .zip(indexed_outputs.into_iter()) - .enumerate() - .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { - // Record the post-randomization spend location - if spend_idx < num_requested_spends { - bundle_meta.spend_indices[spend_idx] = action_idx; - } - - // Record the post-randomization output location - if out_idx < num_requested_outputs { - bundle_meta.output_indices[out_idx] = action_idx; - } - - ActionInfo::new(spend, output, &mut rng) - }) - .collect::>(); - - (pre_actions, bundle_meta) - }; + let (pre_actions, bundle_meta, _) = partition_by_asset(&spends, &outputs, &mut rng) + .into_iter() + .fold( + ( + Vec::new(), + BundleMetadata::new(num_requested_spends, num_requested_outputs), + // We might have to add dummy/split actions only for the first asset to reach MIN_ACTIONS. + num_missing_actions, + ), + |(mut pre_actions, mut bundle_meta, num_missing_actions), + (asset, (spends, outputs))| { + let num_actions = spends.len().max(outputs.len()) + num_missing_actions; + + let first_spend = spends.first().map(|(_, s)| s.clone()); + + let mut indexed_spends = spends + .into_iter() + .chain(iter::repeat_with(|| { + (usize::MAX, pad_spend(first_spend.as_ref(), asset, &mut rng)) + })) + .take(num_actions) + .collect::>(); + + let mut indexed_outputs = outputs + .into_iter() + .chain(iter::repeat_with(|| { + (usize::MAX, OutputInfo::dummy(&mut rng, asset)) + })) + .take(num_actions) + .collect::>(); + + // Shuffle the spends and outputs, so that learning the position of a + // specific spent note or output note doesn't reveal anything on its own about + // the meaning of that note in the transaction context. + indexed_spends.shuffle(&mut rng); + indexed_outputs.shuffle(&mut rng); + + assert_eq!(indexed_spends.len(), indexed_outputs.len()); + + let pre_actions_len = pre_actions.len(); + + let new_actions = indexed_spends + .into_iter() + .zip(indexed_outputs.into_iter()) + .enumerate() + .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { + let action_idx = action_idx + pre_actions_len; + + // Record the post-randomization spend location + if spend_idx < num_requested_spends { + bundle_meta.spend_indices[spend_idx] = action_idx; + } + + // Record the post-randomization output location + if out_idx < num_requested_outputs { + bundle_meta.output_indices[out_idx] = action_idx; + } + + ActionInfo::new(spend, output, &mut rng) + }); + + pre_actions.extend(new_actions); + + (pre_actions, bundle_meta, 0) + }, + ); // Determine the value balance for this bundle, ensuring it is valid. - let value_balance = pre_actions + let native_value_balance: V = pre_actions .iter() + .filter(|action| action.spend.note.asset().is_native().into()) .fold(Some(ValueSum::zero()), |acc, action| { acc? + action.value_sum() }) - .ok_or(OverflowError)?; - - let result_value_balance: V = i64::try_from(value_balance) - .map_err(BuildError::ValueSum) - .and_then(|i| V::try_from(i).map_err(|_| BuildError::ValueSum(value::OverflowError)))?; + .ok_or(OverflowError)? + .into()?; // Compute the transaction binding signing key. let bsk = pre_actions @@ -807,37 +815,25 @@ pub fn bundle + TryFrom>( let (actions, circuits): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); - let burn = burn - .into_iter() - .map(|(asset, value)| Ok((asset, value.into()?))) - .collect::>()?; - - let bundle = NonEmpty::from_vec(actions).map(|actions| { - ( - Bundle::from_parts( - actions, - flags, - result_value_balance, - burn, - anchor, - InProgress { - proof: Unproven { circuits }, - sigs: Unauthorized { bsk }, - }, - ), - bundle_meta, - ) - }); - - // Verify that bsk and bvk are consistent. - if let Some((bundle, _)) = &bundle { - assert_eq!( - redpallas::VerificationKey::from(&bundle.authorization().sigs.bsk), - bundle.binding_validating_key() - ) - } - - Ok(bundle) + let bundle = Bundle::from_parts( + NonEmpty::from_vec(actions).unwrap(), + flags, + native_value_balance, + burn.into_iter() + .map(|(asset, value)| Ok((asset, value.into()?))) + .collect::>()?, + anchor, + InProgress { + proof: Unproven { circuits }, + sigs: Unauthorized { bsk }, + }, + ); + + assert_eq!( + redpallas::VerificationKey::from(&bundle.authorization().sigs.bsk), + bundle.binding_validating_key() + ); + Ok(Some((bundle, bundle_meta))) } /// Marker trait representing bundle signatures in the process of being created. From ac371f0ce29385c771e95b3a5c6f2847375dfd00 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 30 Apr 2024 09:19:26 +0200 Subject: [PATCH 60/92] Fix several comments, rename some flag constants --- src/builder.rs | 30 ++++++++++++----------------- src/bundle.rs | 10 ++++------ src/circuit.rs | 2 -- src/test_vectors/note_encryption.rs | 20 +++++++++---------- tests/builder.rs | 2 +- tests/zsa.rs | 2 +- 6 files changed, 28 insertions(+), 38 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 3e2b8c972..d2119f817 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -46,29 +46,23 @@ pub enum BundleType { } impl BundleType { - /// The default bundle type has all flags enabled, and does not require a bundle to be produced - /// if no spends or outputs have been added to the bundle. - pub const DEFAULT_VANILLA: BundleType = BundleType::Transactional { - flags: Flags::ENABLED_VANILLA, + /// The default bundle type has all flags enabled but ZSA disabled, and does not require a bundle + /// to be produced if no spends or outputs have been added to the bundle. + pub const DEFAULT_WITHOUT_ZSA: BundleType = BundleType::Transactional { + flags: Flags::ENABLED_WITHOUT_ZSA, bundle_required: false, }; - /// FIXME: add doc - pub const DEFAULT_ZSA: BundleType = BundleType::Transactional { - flags: Flags::ENABLED_ZSA, + /// The default bundle with all flags enabled, including ZSA. + pub const DEFAULT_WITH_ZSA: BundleType = BundleType::Transactional { + flags: Flags::ENABLED_WITH_ZSA, bundle_required: false, }; /// The DISABLED bundle type does not permit any bundle to be produced, and when used in the /// builder will prevent any spends or outputs from being added. pub const DISABLED: BundleType = BundleType::Transactional { - flags: Flags::from_parts(false, false, false), // FIXME: is this correct? - bundle_required: false, - }; - - /// FIXME: add doc - pub const ZSA_DISABLED: BundleType = BundleType::Transactional { - flags: Flags::from_parts(true, true, false), + flags: Flags::from_parts(false, false, false), // FIXME: is `false` value for ZSA flag correct here? bundle_required: false, }; @@ -690,8 +684,8 @@ fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) } } -// FIXME: the order of the arguments doesn't correspond the order of the fields of the Builder -// struct - is that okay? +// FIXME: the order of the arguments of the `bundle` function doesn't correspond the order +// of the fields of the `Builder` struct - is that okay? /// Builds a bundle containing the given spent notes and outputs. /// @@ -1171,7 +1165,7 @@ pub mod testing { /// Create a bundle from the set of arbitrary bundle inputs. fn into_bundle + Copy + Into>(mut self) -> Bundle { let fvk = FullViewingKey::from(&self.sk); - let mut builder = Builder::new(BundleType::DEFAULT_ZSA, self.anchor); + let mut builder = Builder::new(BundleType::DEFAULT_WITH_ZSA, self.anchor); for (note, path) in self.notes.into_iter() { builder.add_spend(fvk.clone(), note, path).unwrap(); @@ -1294,7 +1288,7 @@ mod tests { let recipient = fvk.address_at(0u32, Scope::External); let mut builder = Builder::new( - BundleType::ZSA_DISABLED, + BundleType::DEFAULT_WITHOUT_ZSA, EMPTY_ROOTS[MERKLE_DEPTH_ORCHARD].into(), ); diff --git a/src/bundle.rs b/src/bundle.rs index b53fd0416..1a119a786 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -85,17 +85,15 @@ impl Flags { } } - /// The flag set with both spends and outputs enabled. - // FIXME: mention id doc that zsa is disabled? - pub const ENABLED_VANILLA: Flags = Flags { + /// The flag set with both spends and outputs enabled and ZSA disabled. + pub const ENABLED_WITHOUT_ZSA: Flags = Flags { spends_enabled: true, outputs_enabled: true, zsa_enabled: false, }; - /// The flag set with both spends and outputs enabled. - // FIXME: mention id doc that zsa is enabled? - pub const ENABLED_ZSA: Flags = Flags { + /// The flag set with both spends and outputs enabled and ZSA enabled. + pub const ENABLED_WITH_ZSA: Flags = Flags { spends_enabled: true, outputs_enabled: true, zsa_enabled: true, diff --git a/src/circuit.rs b/src/circuit.rs index 0baf1bdc3..bfa78dce9 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1210,8 +1210,6 @@ mod tests { let nk = *fvk.nk(); let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); let nf_old = spent_note.nullifier(&fvk); - // FIXME: why it became unused? - //let rho = Rho::from_nf_old(nf_old); let ak: SpendValidatingKey = fvk.into(); let alpha = pallas::Scalar::random(&mut rng); let rk = ak.randomize(&alpha); diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption.rs index c3100b80c..b4a1f3137 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption.rs @@ -95,7 +95,7 @@ pub(crate) fn test_vectors() -> Vec { 0x42, 0xc2, 0x38, 0x51, 0x38, 0x15, 0x30, 0x2d, 0xf0, 0xf4, 0x83, 0x04, 0x21, 0xa6, 0xc1, 0x3e, 0x71, 0x01, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xc5, 0x96, 0xfb, 0xd3, 0x2e, 0xbb, 0xcb, 0xad, 0xae, 0x60, 0xd2, 0x85, 0xc7, 0xd7, 0x5f, 0xa8, 0x36, 0xf9, 0xd2, 0xfa, 0x86, 0x10, 0x0a, 0xb8, 0x58, 0xea, 0x2d, 0xe1, @@ -305,7 +305,7 @@ pub(crate) fn test_vectors() -> Vec { 0xa2, 0x17, 0x64, 0x10, 0x4a, 0x23, 0xea, 0xf6, 0xba, 0x49, 0x6c, 0xb9, 0xb8, 0xe8, 0x25, 0x7a, 0xd8, 0xb3, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x33, 0x88, 0xda, 0x05, 0x06, 0xda, 0x9e, 0xa2, 0xd5, 0x16, 0x73, 0x9b, 0x95, 0x1c, 0x7c, 0xc0, 0x58, 0x53, 0x36, 0xb4, 0x4d, 0xf9, 0xb3, 0xb5, 0x0e, 0x48, 0x93, 0xe4, @@ -515,7 +515,7 @@ pub(crate) fn test_vectors() -> Vec { 0x9d, 0x5e, 0x64, 0x07, 0x19, 0xbc, 0xa5, 0xc8, 0xed, 0x49, 0x99, 0x97, 0x34, 0xe6, 0xc5, 0xb3, 0x73, 0x3e, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xbe, 0xf8, 0xcf, 0x16, 0x98, 0xe4, 0x78, 0x47, 0xd3, 0x8e, 0x1a, 0xaa, 0x88, 0x86, 0x10, 0x77, 0xcd, 0xb5, 0xad, 0x4c, 0xf6, 0x6f, 0xe4, 0x2f, 0xd6, 0x52, 0x57, 0x81, @@ -725,7 +725,7 @@ pub(crate) fn test_vectors() -> Vec { 0xfa, 0xde, 0x94, 0xfa, 0x0b, 0x46, 0xe3, 0xb1, 0xa5, 0x73, 0x34, 0x99, 0x34, 0xe2, 0x32, 0xb5, 0x0e, 0x96, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x18, 0x89, 0x8e, 0x75, 0x21, 0x7b, 0x32, 0x9b, 0x3a, 0x56, 0x7b, 0x09, 0x37, 0x89, 0xa4, 0xd8, 0x19, 0xcd, 0xb0, 0x34, 0x88, 0xb8, 0x10, 0xda, 0x22, 0x0c, 0x3f, 0x59, @@ -935,7 +935,7 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x95, 0x89, 0xbe, 0x69, 0xd8, 0x28, 0xbe, 0x54, 0x30, 0x69, 0x16, 0x41, 0x3c, 0xd2, 0x50, 0x21, 0x17, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x23, 0x39, 0xa8, 0x95, 0x29, 0xcf, 0x35, 0x7b, 0x06, 0x7d, 0xd2, 0x8b, 0xe4, 0x06, 0x6e, 0x16, 0x23, 0x6d, 0xc5, 0xd7, 0x87, 0x06, 0x14, 0x9a, 0x72, 0x8c, 0x3e, 0x3d, @@ -1145,7 +1145,7 @@ pub(crate) fn test_vectors() -> Vec { 0x6e, 0x62, 0xe4, 0xed, 0xc7, 0x86, 0xd9, 0xe0, 0xb2, 0x7d, 0x26, 0x62, 0x8b, 0x79, 0xda, 0x6b, 0x15, 0x14, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xe5, 0xd0, 0x8c, 0x40, 0x26, 0x3e, 0x4a, 0x2a, 0x56, 0x96, 0xda, 0x21, 0x0d, 0x8e, 0x9a, 0x77, 0xf0, 0xaf, 0xc4, 0xc6, 0x8a, 0x6d, 0xda, 0x38, 0xe2, 0x85, 0xf4, 0xe3, @@ -1355,7 +1355,7 @@ pub(crate) fn test_vectors() -> Vec { 0x0a, 0x12, 0x01, 0x2d, 0x63, 0xc0, 0x09, 0xc6, 0x77, 0x44, 0xba, 0xe0, 0xd5, 0x83, 0x88, 0xff, 0xee, 0x2f, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xe9, 0x16, 0x93, 0xc3, 0x7d, 0x04, 0x37, 0x5e, 0x67, 0xc5, 0x71, 0x5a, 0x39, 0xc9, 0x79, 0x4a, 0x4e, 0xcd, 0x08, 0x38, 0xe2, 0x35, 0x1f, 0xd7, 0xcd, 0x93, 0xa1, 0x55, @@ -1565,7 +1565,7 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x51, 0x00, 0x89, 0x08, 0xa6, 0xcd, 0xd0, 0xaa, 0x02, 0x1b, 0x88, 0x8b, 0x98, 0xe2, 0x3c, 0x39, 0x11, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x35, 0x6f, 0xc7, 0x2e, 0x1b, 0xf1, 0xe3, 0xa2, 0xa5, 0x9a, 0xa9, 0xe4, 0x75, 0x15, 0x5c, 0xf7, 0x43, 0xf8, 0xfd, 0xf0, 0xd1, 0x5b, 0x4c, 0xc4, 0x02, 0x60, 0xd0, 0xd0, @@ -1775,7 +1775,7 @@ pub(crate) fn test_vectors() -> Vec { 0x7e, 0xed, 0xd2, 0xa7, 0x06, 0x44, 0x07, 0x34, 0x78, 0x41, 0x01, 0xae, 0x2d, 0x8e, 0x87, 0xe5, 0x05, 0xad, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x32, 0x91, 0x87, 0x35, 0x66, 0x3f, 0x34, 0xad, 0xa0, 0x22, 0x8a, 0xea, 0x4a, 0xcc, 0x19, 0x2a, 0x12, 0x3f, 0xcf, 0xa0, 0x60, 0x46, 0x89, 0xf9, 0x1a, 0xcb, 0xe9, 0x38, @@ -1985,7 +1985,7 @@ pub(crate) fn test_vectors() -> Vec { 0xbd, 0xb9, 0x6f, 0x1c, 0xe0, 0x57, 0xc3, 0x30, 0xd1, 0xcc, 0xba, 0x2f, 0x7d, 0xa8, 0x71, 0x55, 0x00, 0xb5, ], - // FIXME: used instead of rho, which was possiblu modified in zsa1 version + // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x3b, 0x37, 0x96, 0x78, 0x0c, 0x0a, 0xec, 0x14, 0xed, 0x28, 0x74, 0xb5, 0x23, 0x06, 0xe1, 0xc3, 0xd5, 0xde, 0x45, 0x93, 0xc6, 0x69, 0xaf, 0x1c, 0xaf, 0x11, 0xbc, 0xb4, diff --git a/tests/builder.rs b/tests/builder.rs index 845fa2367..07347b73d 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -110,7 +110,7 @@ fn bundle_chain() { let (merkle_path, anchor) = build_merkle_path(¬e); - let mut builder = Builder::new(BundleType::DEFAULT_VANILLA, anchor); + let mut builder = Builder::new(BundleType::DEFAULT_WITHOUT_ZSA, anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!( builder.add_output( diff --git a/tests/zsa.rs b/tests/zsa.rs index 4d6826b08..44850e23d 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -238,7 +238,7 @@ fn build_and_verify_bundle( ) -> Result<(), String> { let rng = OsRng; let shielded_bundle: Bundle<_, i64> = { - let mut builder = Builder::new(BundleType::DEFAULT_ZSA, anchor); + let mut builder = Builder::new(BundleType::DEFAULT_WITH_ZSA, anchor); spends .iter() From 7969b9ec78a92e9ba8ddea6b8cba4cb34211a628 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 30 Apr 2024 09:29:54 +0200 Subject: [PATCH 61/92] Fix flag names after renaming --- benches/circuit.rs | 2 +- benches/note_decryption.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benches/circuit.rs b/benches/circuit.rs index 080411607..bf2401af8 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -27,7 +27,7 @@ fn criterion_benchmark(c: &mut Criterion) { let create_bundle = |num_recipients| { let mut builder = Builder::new( - BundleType::DEFAULT_VANILLA, + BundleType::DEFAULT_WITHOUT_ZSA, Anchor::from_bytes([0; 32]).unwrap(), ); for _ in 0..num_recipients { diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 577cc20a0..fe3acb03c 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -46,7 +46,7 @@ fn bench_note_decryption(c: &mut Criterion) { let bundle = { let mut builder = Builder::new( - BundleType::DEFAULT_VANILLA, + BundleType::DEFAULT_WITHIOUT_ZSA, Anchor::from_bytes([0; 32]).unwrap(), ); // The builder pads to two actions, and shuffles their order. Add two recipients From 47f7aaeff839908b765e93fa5ec7e8804727e99c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 30 Apr 2024 10:00:56 +0200 Subject: [PATCH 62/92] Disable rustfmt for one line in keys.rs module to prevent removing double column in the use of external zip32 crate --- src/keys.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/keys.rs b/src/keys.rs index eddd4dcc4..123d9ef17 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -25,7 +25,6 @@ use pasta_curves::{pallas, pallas::Scalar}; use rand::{rngs::OsRng, RngCore}; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; use zcash_note_encryption_zsa::EphemeralKeyBytes; -//use zip32::{AccountId, ChildIndex}; use crate::{ address::Address, @@ -41,6 +40,9 @@ use crate::{ }, }; +// Disable rustfmt to preserve '::' which specifies the external 'zip32' crate, +// avoiding confusion with a local module of the same name. +#[rustfmt::skip] pub use ::zip32::{AccountId, ChildIndex, DiversifierIndex, Scope}; const KDF_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_OrchardKDF"; From bb9e03b4d814cc289c5f7d73ce42b9bdbb0e6d1b Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 30 Apr 2024 10:20:52 +0200 Subject: [PATCH 63/92] Fix typo in constant name --- benches/note_decryption.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index fe3acb03c..5f6d9bf50 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -46,7 +46,7 @@ fn bench_note_decryption(c: &mut Criterion) { let bundle = { let mut builder = Builder::new( - BundleType::DEFAULT_WITHIOUT_ZSA, + BundleType::DEFAULT_WITHOUT_ZSA, Anchor::from_bytes([0; 32]).unwrap(), ); // The builder pads to two actions, and shuffles their order. Add two recipients From dd956b8251e4c56c335a06b20b5c32ef64616ea7 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 1 May 2024 22:00:16 +0200 Subject: [PATCH 64/92] Fix comments, rename DEFAULT_WITH(OUT)_ZSA to DEVAULT_VANILLA(ZSA) --- benches/circuit.rs | 2 +- benches/note_decryption.rs | 2 +- src/builder.rs | 22 +++++++++------------- src/bundle.rs | 2 +- src/keys.rs | 3 +-- tests/builder.rs | 2 +- tests/zsa.rs | 2 +- 7 files changed, 15 insertions(+), 20 deletions(-) diff --git a/benches/circuit.rs b/benches/circuit.rs index bf2401af8..080411607 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -27,7 +27,7 @@ fn criterion_benchmark(c: &mut Criterion) { let create_bundle = |num_recipients| { let mut builder = Builder::new( - BundleType::DEFAULT_WITHOUT_ZSA, + BundleType::DEFAULT_VANILLA, Anchor::from_bytes([0; 32]).unwrap(), ); for _ in 0..num_recipients { diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 5f6d9bf50..577cc20a0 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -46,7 +46,7 @@ fn bench_note_decryption(c: &mut Criterion) { let bundle = { let mut builder = Builder::new( - BundleType::DEFAULT_WITHOUT_ZSA, + BundleType::DEFAULT_VANILLA, Anchor::from_bytes([0; 32]).unwrap(), ); // The builder pads to two actions, and shuffles their order. Add two recipients diff --git a/src/builder.rs b/src/builder.rs index d2119f817..f1cacb863 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -46,15 +46,15 @@ pub enum BundleType { } impl BundleType { - /// The default bundle type has all flags enabled but ZSA disabled, and does not require a bundle - /// to be produced if no spends or outputs have been added to the bundle. - pub const DEFAULT_WITHOUT_ZSA: BundleType = BundleType::Transactional { + /// The default bundle type has all flags enabled, ZSA disabled, and does not require a bundle + /// to be produced. + pub const DEFAULT_VANILLA: BundleType = BundleType::Transactional { flags: Flags::ENABLED_WITHOUT_ZSA, bundle_required: false, }; /// The default bundle with all flags enabled, including ZSA. - pub const DEFAULT_WITH_ZSA: BundleType = BundleType::Transactional { + pub const DEFAULT_ZSA: BundleType = BundleType::Transactional { flags: Flags::ENABLED_WITH_ZSA, bundle_required: false, }; @@ -62,7 +62,7 @@ impl BundleType { /// The DISABLED bundle type does not permit any bundle to be produced, and when used in the /// builder will prevent any spends or outputs from being added. pub const DISABLED: BundleType = BundleType::Transactional { - flags: Flags::from_parts(false, false, false), // FIXME: is `false` value for ZSA flag correct here? + flags: Flags::from_parts(false, false, false), bundle_required: false, }; @@ -670,23 +670,20 @@ fn partition_by_asset( hm } -/// Returns a dummy/split notes to extend the spends. +/// Returns the appropriate SpendInfo for padding. fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) -> SpendInfo { if asset.is_native().into() { // For native asset, extends with dummy notes SpendInfo::dummy(asset, &mut rng) } else { // For ZSA asset, extends with - // - dummy notes if first spend is empty + // - dummy note if SpendInfo is None // - split notes otherwise. let dummy = SpendInfo::dummy(asset, &mut rng); spend.map_or_else(|| dummy, |s| s.create_split_spend(&mut rng)) } } -// FIXME: the order of the arguments of the `bundle` function doesn't correspond the order -// of the fields of the `Builder` struct - is that okay? - /// Builds a bundle containing the given spent notes and outputs. /// /// The returned bundle will have no proof or signatures; these can be applied with @@ -717,7 +714,6 @@ pub fn bundle + TryFrom>( return Err(BuildError::OutputsDisabled); } - // The number of actions to add to this bundle in order to contain at least MIN_ACTION actions. let num_missing_actions = MIN_ACTIONS.saturating_sub(spends.len().max(outputs.len())); // Pair up the spends and outputs, extending with dummy values as necessary. @@ -1165,7 +1161,7 @@ pub mod testing { /// Create a bundle from the set of arbitrary bundle inputs. fn into_bundle + Copy + Into>(mut self) -> Bundle { let fvk = FullViewingKey::from(&self.sk); - let mut builder = Builder::new(BundleType::DEFAULT_WITH_ZSA, self.anchor); + let mut builder = Builder::new(BundleType::DEFAULT_ZSA, self.anchor); for (note, path) in self.notes.into_iter() { builder.add_spend(fvk.clone(), note, path).unwrap(); @@ -1288,7 +1284,7 @@ mod tests { let recipient = fvk.address_at(0u32, Scope::External); let mut builder = Builder::new( - BundleType::DEFAULT_WITHOUT_ZSA, + BundleType::DEFAULT_VANILLA, EMPTY_ROOTS[MERKLE_DEPTH_ORCHARD].into(), ); diff --git a/src/bundle.rs b/src/bundle.rs index 1a119a786..475dc2332 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -92,7 +92,7 @@ impl Flags { zsa_enabled: false, }; - /// The flag set with both spends and outputs enabled and ZSA enabled. + /// The flags set with spends, outputs and ZSA enabled. pub const ENABLED_WITH_ZSA: Flags = Flags { spends_enabled: true, outputs_enabled: true, diff --git a/src/keys.rs b/src/keys.rs index 123d9ef17..3c76a73f6 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -40,8 +40,7 @@ use crate::{ }, }; -// Disable rustfmt to preserve '::' which specifies the external 'zip32' crate, -// avoiding confusion with a local module of the same name. +// Preserve '::' which specifies the EXTERNAL 'zip32' crate #[rustfmt::skip] pub use ::zip32::{AccountId, ChildIndex, DiversifierIndex, Scope}; diff --git a/tests/builder.rs b/tests/builder.rs index 07347b73d..845fa2367 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -110,7 +110,7 @@ fn bundle_chain() { let (merkle_path, anchor) = build_merkle_path(¬e); - let mut builder = Builder::new(BundleType::DEFAULT_WITHOUT_ZSA, anchor); + let mut builder = Builder::new(BundleType::DEFAULT_VANILLA, anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!( builder.add_output( diff --git a/tests/zsa.rs b/tests/zsa.rs index 44850e23d..4d6826b08 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -238,7 +238,7 @@ fn build_and_verify_bundle( ) -> Result<(), String> { let rng = OsRng; let shielded_bundle: Bundle<_, i64> = { - let mut builder = Builder::new(BundleType::DEFAULT_WITH_ZSA, anchor); + let mut builder = Builder::new(BundleType::DEFAULT_ZSA, anchor); spends .iter() From 123b60988a5b0afa9029b8e22e04642edd170ad8 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 2 May 2024 15:38:05 +0200 Subject: [PATCH 65/92] 1) Use Option instead of usize::MAX in builder::partition_by_asset function. 2) Refactor builder::bundle function (pre-action genetation), to split 'fold' into three parts --- src/builder.rs | 159 +++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 72 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index f1cacb863..6e38201f6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -642,28 +642,34 @@ fn partition_by_asset( spends: &[SpendInfo], outputs: &[OutputInfo], rng: &mut impl RngCore, -) -> HashMap, Vec<(usize, OutputInfo)>)> { +) -> HashMap< + AssetBase, + ( + Vec<(Option, SpendInfo)>, + Vec<(Option, OutputInfo)>, + ), +> { let mut hm = HashMap::new(); for (i, s) in spends.iter().enumerate() { hm.entry(s.note.asset()) .or_insert((vec![], vec![])) .0 - .push((i, s.clone())); + .push((Some(i), s.clone())); } for (i, o) in outputs.iter().enumerate() { hm.entry(o.asset) .or_insert((vec![], vec![])) .1 - .push((i, o.clone())); + .push((Some(i), o.clone())); } if hm.is_empty() { - let dummy_spend = SpendInfo::dummy(AssetBase::native(), rng); + let dummy_spend = pad_spend(None, AssetBase::native(), rng); hm.insert( dummy_spend.note.asset(), - (vec![(usize::MAX, dummy_spend)], vec![]), + (vec![(None, dummy_spend)], vec![]), ); } @@ -714,76 +720,85 @@ pub fn bundle + TryFrom>( return Err(BuildError::OutputsDisabled); } - let num_missing_actions = MIN_ACTIONS.saturating_sub(spends.len().max(outputs.len())); - // Pair up the spends and outputs, extending with dummy values as necessary. - let (pre_actions, bundle_meta, _) = partition_by_asset(&spends, &outputs, &mut rng) - .into_iter() - .fold( - ( - Vec::new(), - BundleMetadata::new(num_requested_spends, num_requested_outputs), - // We might have to add dummy/split actions only for the first asset to reach MIN_ACTIONS. - num_missing_actions, - ), - |(mut pre_actions, mut bundle_meta, num_missing_actions), - (asset, (spends, outputs))| { - let num_actions = spends.len().max(outputs.len()) + num_missing_actions; - - let first_spend = spends.first().map(|(_, s)| s.clone()); - - let mut indexed_spends = spends - .into_iter() - .chain(iter::repeat_with(|| { - (usize::MAX, pad_spend(first_spend.as_ref(), asset, &mut rng)) - })) - .take(num_actions) - .collect::>(); - - let mut indexed_outputs = outputs - .into_iter() - .chain(iter::repeat_with(|| { - (usize::MAX, OutputInfo::dummy(&mut rng, asset)) - })) - .take(num_actions) - .collect::>(); - - // Shuffle the spends and outputs, so that learning the position of a - // specific spent note or output note doesn't reveal anything on its own about - // the meaning of that note in the transaction context. - indexed_spends.shuffle(&mut rng); - indexed_outputs.shuffle(&mut rng); - - assert_eq!(indexed_spends.len(), indexed_outputs.len()); - - let pre_actions_len = pre_actions.len(); - - let new_actions = indexed_spends - .into_iter() - .zip(indexed_outputs.into_iter()) - .enumerate() - .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { - let action_idx = action_idx + pre_actions_len; - - // Record the post-randomization spend location - if spend_idx < num_requested_spends { - bundle_meta.spend_indices[spend_idx] = action_idx; - } - - // Record the post-randomization output location - if out_idx < num_requested_outputs { - bundle_meta.output_indices[out_idx] = action_idx; - } - - ActionInfo::new(spend, output, &mut rng) - }); - - pre_actions.extend(new_actions); - - (pre_actions, bundle_meta, 0) - }, + let (pre_actions, bundle_meta) = { + // FIXME: use Vec::with_capacity().extend(...) instead of ...collect() as we can estimate + // the size of the resulting vector beforehand. Rust can't do that autimatically in this + // particular case, and possibly realloicates the vector during the collecting. + // Moreover, even if we use "colect" intstead of the first "extend", we still have to make + // the vector mutable and then potentially extend it with missing dummy elements to pad to + // MIN_ACTIONS elements. + let mut indexed_spends_outputs = + Vec::with_capacity(spends.len().max(outputs.len()).max(MIN_ACTIONS)); + + indexed_spends_outputs.extend( + partition_by_asset(&spends, &outputs, &mut rng) + .into_iter() + .flat_map(|(asset, (spends, outputs))| { + let num_asset_pre_actions = spends.len().max(outputs.len()); + + let first_spend = spends.first().map(|(_, s)| s.clone()); + + let mut indexed_spends = spends + .into_iter() + .chain(iter::repeat_with(|| { + (None, pad_spend(first_spend.as_ref(), asset, &mut rng)) + })) + .take(num_asset_pre_actions) + .collect::>(); + + let mut indexed_outputs = outputs + .into_iter() + .chain(iter::repeat_with(|| { + (None, OutputInfo::dummy(&mut rng, asset)) + })) + .take(num_asset_pre_actions) + .collect::>(); + + // Shuffle the spends and outputs, so that learning the position of a + // specific spent note or output note doesn't reveal anything on its own about + // the meaning of that note in the transaction context. + indexed_spends.shuffle(&mut rng); + indexed_outputs.shuffle(&mut rng); + + assert_eq!(indexed_spends.len(), indexed_outputs.len()); + + indexed_spends.into_iter().zip(indexed_outputs) + }), ); + indexed_spends_outputs.extend( + iter::repeat_with(|| { + ( + (None, pad_spend(None, AssetBase::native(), &mut rng)), + (None, OutputInfo::dummy(&mut rng, AssetBase::native())), + ) + }) + .take(MIN_ACTIONS.saturating_sub(indexed_spends_outputs.len())), + ); + + let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs); + let pre_actions = indexed_spends_outputs + .into_iter() + .enumerate() + .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { + // Record the post-randomization spend location + if let Some(spend_idx) = spend_idx { + bundle_meta.spend_indices[spend_idx] = action_idx; + } + + // Record the post-randomization output location + if let Some(out_idx) = out_idx { + bundle_meta.output_indices[out_idx] = action_idx; + } + + ActionInfo::new(spend, output, &mut rng) + }) + .collect::>(); + + (pre_actions, bundle_meta) + }; + // Determine the value balance for this bundle, ensuring it is valid. let native_value_balance: V = pre_actions .iter() From ee89541af6ad516ea708ad8d56b5e893ecbf5a06 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 7 May 2024 15:04:09 +0200 Subject: [PATCH 66/92] Refactor build function to remove `Copy + Into` constraints - Introduce `derive_bvk` function for streamlined calculation of `bvk` - Use `derive_bvk` in `bundle.binding_validating_key()` to avoid duplication - Adjust `native_value_balance` calculation to an `i64` and convert to `V` - Optimize calculations with iterators to reduce memory usage --- src/builder.rs | 54 +++++++++++++++++++++++++++++++------------------- src/bundle.rs | 52 ++++++++++++++++++++++++++---------------------- 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 6e38201f6..80cad82e2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -13,7 +13,7 @@ use rand::{prelude::SliceRandom, CryptoRng, RngCore}; use crate::{ action::Action, address::Address, - bundle::{Authorization, Authorized, Bundle, Flags}, + bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags}, circuit::{Circuit, Instance, Proof, ProvingKey}, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, @@ -620,7 +620,7 @@ impl Builder { /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. - pub fn build + TryFrom>( + pub fn build>( self, rng: impl RngCore, ) -> Result, BundleMetadata)>, BuildError> { @@ -694,7 +694,7 @@ fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. -pub fn bundle + TryFrom>( +pub fn bundle>( mut rng: impl RngCore, anchor: Anchor, bundle_type: BundleType, @@ -800,7 +800,7 @@ pub fn bundle + TryFrom>( }; // Determine the value balance for this bundle, ensuring it is valid. - let native_value_balance: V = pre_actions + let native_value_balance: i64 = pre_actions .iter() .filter(|action| action.spend.note.asset().is_native().into()) .fold(Some(ValueSum::zero()), |acc, action| { @@ -809,6 +809,9 @@ pub fn bundle + TryFrom>( .ok_or(OverflowError)? .into()?; + let result_value_balance = V::try_from(native_value_balance) + .map_err(|_| BuildError::ValueSum(value::OverflowError))?; + // Compute the transaction binding signing key. let bsk = pre_actions .iter() @@ -820,25 +823,36 @@ pub fn bundle + TryFrom>( let (actions, circuits): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); - let bundle = Bundle::from_parts( - NonEmpty::from_vec(actions).unwrap(), - flags, + // Verify that bsk and bvk are consistent. + let bvk = derive_bvk( + &actions, native_value_balance, - burn.into_iter() - .map(|(asset, value)| Ok((asset, value.into()?))) - .collect::>()?, - anchor, - InProgress { - proof: Unproven { circuits }, - sigs: Unauthorized { bsk }, - }, + burn.iter() + .flat_map(|(asset, value)| -> Result<_, BuildError> { Ok((*asset, (*value).into()?)) }), ); + assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); - assert_eq!( - redpallas::VerificationKey::from(&bundle.authorization().sigs.bsk), - bundle.binding_validating_key() - ); - Ok(Some((bundle, bundle_meta))) + let burn = burn + .into_iter() + .map(|(asset, value)| Ok((asset, value.into()?))) + .collect::, BuildError>>()?; + + Ok(NonEmpty::from_vec(actions).map(|actions| { + ( + Bundle::from_parts( + actions, + flags, + result_value_balance, + burn, + anchor, + InProgress { + proof: Unproven { circuits }, + sigs: Unauthorized { bsk }, + }, + ), + bundle_meta, + ) + })) } /// Marker trait representing bundle signatures in the process of being created. diff --git a/src/bundle.rs b/src/bundle.rs index 475dc2332..a4e87bac0 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -435,6 +435,33 @@ impl Bundle { } } +pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into>( + actions: impl IntoIterator>, //&NonEmpty>, + value_balance: V, + burn: impl Iterator, +) -> redpallas::VerificationKey { + // https://p.z.cash/TCR:bad-txns-orchard-binding-signature-invalid?partial + (actions + .into_iter() + .map(|a| a.cv_net()) + .sum::() + - ValueCommitment::derive( + ValueSum::from_raw(value_balance.into()), + ValueCommitTrapdoor::zero(), + AssetBase::native(), + ) + - burn + .map(|(asset, value)| { + ValueCommitment::derive( + ValueSum::from_raw(value.into()), + ValueCommitTrapdoor::zero(), + asset, + ) + }) + .sum::()) + .into_bvk() +} + impl> Bundle { /// Computes a commitment to the effects of this bundle, suitable for inclusion within /// a transaction ID. @@ -447,30 +474,7 @@ impl> Bundle { /// This can be used to validate the [`Authorized::binding_signature`] returned from /// [`Bundle::authorization`]. pub fn binding_validating_key(&self) -> redpallas::VerificationKey { - // https://p.z.cash/TCR:bad-txns-orchard-binding-signature-invalid?partial - (self - .actions - .iter() - .map(|a| a.cv_net()) - .sum::() - - ValueCommitment::derive( - ValueSum::from_raw(self.value_balance.into()), - ValueCommitTrapdoor::zero(), - AssetBase::native(), - ) - - self - .burn - .clone() - .into_iter() - .map(|(asset, value)| { - ValueCommitment::derive( - ValueSum::from_raw(value.into()), - ValueCommitTrapdoor::zero(), - asset, - ) - }) - .sum::()) - .into_bvk() + derive_bvk(&self.actions, self.value_balance, self.burn.iter().cloned()) } } From 73218b089b7121e226afa1ded4bf5eb3e236d5f6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 7 May 2024 18:38:15 +0200 Subject: [PATCH 67/92] Remove extra comment --- src/bundle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bundle.rs b/src/bundle.rs index a4e87bac0..8f9e8af79 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -436,7 +436,7 @@ impl Bundle { } pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into>( - actions: impl IntoIterator>, //&NonEmpty>, + actions: impl IntoIterator>, value_balance: V, burn: impl Iterator, ) -> redpallas::VerificationKey { From 50c6310f8ac3ba6aa087424ff16f08a3a79029c6 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Thu, 9 May 2024 11:10:56 +0200 Subject: [PATCH 68/92] Fix comments, indroduce and use MatadataIdx type in the builder --- src/builder.rs | 36 +++++++++++++++++++----------------- src/bundle.rs | 4 ++-- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 80cad82e2..ff3459012 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -635,6 +635,11 @@ impl Builder { } } +/// The index of the attached spend or output in the bundle. +/// None indicates a dummy note. +/// The index is used to track the position of the note in the bundle. +type MetadataIdx = Option; + /// Partition a list of spends and recipients by note types. /// Method creates single dummy ZEC note if spends and recipients are both empty. #[allow(clippy::type_complexity)] @@ -645,8 +650,8 @@ fn partition_by_asset( ) -> HashMap< AssetBase, ( - Vec<(Option, SpendInfo)>, - Vec<(Option, OutputInfo)>, + Vec<(SpendInfo, MetadataIdx)>, + Vec<(OutputInfo, MetadataIdx)>, ), > { let mut hm = HashMap::new(); @@ -655,21 +660,22 @@ fn partition_by_asset( hm.entry(s.note.asset()) .or_insert((vec![], vec![])) .0 - .push((Some(i), s.clone())); + .push((s.clone(), Some(i))); } for (i, o) in outputs.iter().enumerate() { hm.entry(o.asset) .or_insert((vec![], vec![])) .1 - .push((Some(i), o.clone())); + .push((o.clone(), Some(i))); } if hm.is_empty() { let dummy_spend = pad_spend(None, AssetBase::native(), rng); + // dummy_spend should not be included in the indexing and marked as None. hm.insert( dummy_spend.note.asset(), - (vec![(None, dummy_spend)], vec![]), + (vec![(dummy_spend, None)], vec![]), ); } @@ -722,12 +728,8 @@ pub fn bundle>( // Pair up the spends and outputs, extending with dummy values as necessary. let (pre_actions, bundle_meta) = { - // FIXME: use Vec::with_capacity().extend(...) instead of ...collect() as we can estimate - // the size of the resulting vector beforehand. Rust can't do that autimatically in this - // particular case, and possibly realloicates the vector during the collecting. - // Moreover, even if we use "colect" intstead of the first "extend", we still have to make - // the vector mutable and then potentially extend it with missing dummy elements to pad to - // MIN_ACTIONS elements. + // Use Vec::with_capacity().extend(...) instead of .collect() to avoid reallocations, + // as we can estimate the vector size beforehand. let mut indexed_spends_outputs = Vec::with_capacity(spends.len().max(outputs.len()).max(MIN_ACTIONS)); @@ -737,12 +739,12 @@ pub fn bundle>( .flat_map(|(asset, (spends, outputs))| { let num_asset_pre_actions = spends.len().max(outputs.len()); - let first_spend = spends.first().map(|(_, s)| s.clone()); + let first_spend = spends.first().map(|(s, _)| s.clone()); let mut indexed_spends = spends .into_iter() .chain(iter::repeat_with(|| { - (None, pad_spend(first_spend.as_ref(), asset, &mut rng)) + (pad_spend(first_spend.as_ref(), asset, &mut rng), None) })) .take(num_asset_pre_actions) .collect::>(); @@ -750,7 +752,7 @@ pub fn bundle>( let mut indexed_outputs = outputs .into_iter() .chain(iter::repeat_with(|| { - (None, OutputInfo::dummy(&mut rng, asset)) + (OutputInfo::dummy(&mut rng, asset), None) })) .take(num_asset_pre_actions) .collect::>(); @@ -770,8 +772,8 @@ pub fn bundle>( indexed_spends_outputs.extend( iter::repeat_with(|| { ( - (None, pad_spend(None, AssetBase::native(), &mut rng)), - (None, OutputInfo::dummy(&mut rng, AssetBase::native())), + (pad_spend(None, AssetBase::native(), &mut rng), None), + (OutputInfo::dummy(&mut rng, AssetBase::native()), None), ) }) .take(MIN_ACTIONS.saturating_sub(indexed_spends_outputs.len())), @@ -781,7 +783,7 @@ pub fn bundle>( let pre_actions = indexed_spends_outputs .into_iter() .enumerate() - .map(|(action_idx, ((spend_idx, spend), (out_idx, output)))| { + .map(|(action_idx, ((spend, spend_idx), (output, out_idx)))| { // Record the post-randomization spend location if let Some(spend_idx) = spend_idx { bundle_meta.spend_indices[spend_idx] = action_idx; diff --git a/src/bundle.rs b/src/bundle.rs index 8f9e8af79..385e5fec1 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -103,14 +103,14 @@ impl Flags { pub const SPENDS_DISABLED: Flags = Flags { spends_enabled: false, outputs_enabled: true, - zsa_enabled: false, // FIXME: is this correct? + zsa_enabled: false, }; /// The flag set with outputs disabled. pub const OUTPUTS_DISABLED: Flags = Flags { spends_enabled: true, outputs_enabled: false, - zsa_enabled: false, // FIXME: is this correct? + zsa_enabled: false, }; /// Flag denoting whether Orchard spends are enabled in the transaction. From 39b479ea81045e5c5ac719821fe2feb2bfce5f36 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 16 Jul 2024 15:45:46 +0200 Subject: [PATCH 69/92] OrchardZSA backward compatability 0.8.0 (#104) This pull request aims to generalize the implementation of the Orchard protocol, providing backward compatibility to support both the new (ZSA) and the original (non-ZSA - Vanilla) Orchard protocol variants. Key modifications and enhancements include: ### 1. Trait and Generic Structures for Note Encryption: - **OrchardDomain Trait:** A new `OrchardDomain` trait in `note_encryption.rs` differentiates between the original Orchard (Vanilla) and Orchard ZSA protocols, simplifying the implementation of the `Domain` trait through abstraction. - **OrchardDomainBase Generic Struct:** Introduced to contain data used for internal calculations in both Orchard variants. - **TransmittedNoteCiphertext Modifications:** This struct is now generic, supporting various lengths of encrypted note ciphertext to accommodate both Orchard variants. ### 2. Trait and Generic Structures for Circuit Generalization: - **OrchardCircuit Trait:** A new `OrchardCircuit` trait in `circuit.rs` provides an interface for different implementations of the PLONK circuit tailored to the specific requirements of the Orchard protocol's variants (Vanilla and ZSA). - **OrchardCircuitBase Generic Struct:** Contains data for internal calculations across both Orchard variants. ### 3. Module Organization: - Introduction of `note_encryption_vanilla.rs`, `note_encryption_zsa.rs` to support the different types of encrypted notes. - Introduction of `circuit_vanilla.rs`, and `circuit_zsa.rs` to support various circuit configurations. ### 4. Test Suite Updates: Updates to unit tests include separate versions for Vanilla and ZSA variants, ensuring thorough validation of the modifications. ### 5. Dependency Adaptation: The adoption of a modified version of the Halo2 Rust crate facilitates support for both Orchard protocol variants, guaranteeing that all tests, including those for non-ZSA functionality, pass successfully. --------- Co-authored-by: Paul Co-authored-by: Dmitry Demin Co-authored-by: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Co-authored-by: alexeykoren <2365507+alexeykoren@users.noreply.github.com> --- .gitignore | 2 + Cargo.lock | 436 +- Cargo.toml | 13 +- benches/circuit.rs | 45 +- benches/note_decryption.rs | 51 +- benches/utils.rs | 28 + src/action.rs | 173 +- src/builder.rs | 293 +- src/bundle.rs | 333 +- src/bundle/batch.rs | 6 +- src/bundle/commitments.rs | 69 +- src/circuit.rs | 1462 +- src/circuit/circuit_description_vanilla | 28140 ++++++++++++++++ .../circuit_description_zsa} | 0 .../circuit_proof_test_case_vanilla.bin | Bin 0 -> 5154 bytes .../circuit_proof_test_case_zsa.bin} | Bin src/circuit/circuit_vanilla.rs | 924 + src/circuit/circuit_vanilla/gadget.rs | 190 + src/circuit/circuit_vanilla/note_commit.rs | 2365 ++ src/circuit/circuit_zsa.rs | 1447 + src/circuit/circuit_zsa/gadget.rs | 245 + src/circuit/{ => circuit_zsa}/note_commit.rs | 138 +- .../{ => circuit_zsa}/value_commit_orchard.rs | 54 +- src/circuit/commit_ivk.rs | 407 +- src/circuit/gadget.rs | 223 +- src/circuit/gadget/add_chip.rs | 2 + src/circuit/orchard_sinsemilla_chip.rs | 88 + src/constants.rs | 2 +- src/issuance.rs | 20 + src/lib.rs | 7 +- src/note.rs | 9 +- src/note_encryption.rs | 692 +- src/note_encryption/compact_action.rs | 163 + src/note_encryption/domain.rs | 289 + src/note_encryption/orchard_domain.rs | 118 + src/note_encryption/orchard_domain_vanilla.rs | 217 + src/note_encryption/orchard_domain_zsa.rs | 224 + src/note_encryption_v2v3.rs | 716 - src/note_encryption_v3.rs | 632 - src/orchard_flavor.rs | 17 + src/test_vectors.rs | 4 +- src/test_vectors/asset_base.rs | 1722 +- src/test_vectors/issuance_auth_sig.rs | 2 +- src/test_vectors/keys.rs | 2 +- src/test_vectors/merkle_path.rs | 3 +- ...cryption.rs => note_encryption_vanilla.rs} | 1385 +- ...ncryption_v3.rs => note_encryption_zsa.rs} | 64 +- src/value.rs | 22 +- tests/builder.rs | 79 +- tests/zsa.rs | 22 +- 50 files changed, 37396 insertions(+), 6149 deletions(-) create mode 100644 benches/utils.rs create mode 100644 src/circuit/circuit_description_vanilla rename src/{circuit_description => circuit/circuit_description_zsa} (100%) create mode 100644 src/circuit/circuit_proof_test_case_vanilla.bin rename src/{circuit_proof_test_case.bin => circuit/circuit_proof_test_case_zsa.bin} (100%) create mode 100644 src/circuit/circuit_vanilla.rs create mode 100644 src/circuit/circuit_vanilla/gadget.rs create mode 100644 src/circuit/circuit_vanilla/note_commit.rs create mode 100644 src/circuit/circuit_zsa.rs create mode 100644 src/circuit/circuit_zsa/gadget.rs rename src/circuit/{ => circuit_zsa}/note_commit.rs (96%) rename src/circuit/{ => circuit_zsa}/value_commit_orchard.rs (88%) create mode 100644 src/circuit/orchard_sinsemilla_chip.rs create mode 100644 src/note_encryption/compact_action.rs create mode 100644 src/note_encryption/domain.rs create mode 100644 src/note_encryption/orchard_domain.rs create mode 100644 src/note_encryption/orchard_domain_vanilla.rs create mode 100644 src/note_encryption/orchard_domain_zsa.rs delete mode 100644 src/note_encryption_v2v3.rs delete mode 100644 src/note_encryption_v3.rs create mode 100644 src/orchard_flavor.rs rename src/test_vectors/{note_encryption.rs => note_encryption_vanilla.rs} (62%) rename src/test_vectors/{note_encryption_v3.rs => note_encryption_zsa.rs} (99%) diff --git a/.gitignore b/.gitignore index 874a5ed83..cd4022bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .vscode .idea action-circuit-layout.png +*.[0-9] +*.[0-9][0-9] diff --git a/Cargo.lock b/Cargo.lock index e2e8971ed..ff6675ce4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -83,9 +83,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arrayref" @@ -112,15 +112,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -172,9 +172,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -236,9 +236,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -263,9 +263,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.95" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" [[package]] name = "cfg-if" @@ -308,7 +308,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets", ] [[package]] @@ -376,12 +376,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "const-cstr" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" - [[package]] name = "const-oid" version = "0.9.6" @@ -412,9 +406,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" -version = "0.22.3" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -436,9 +430,9 @@ dependencies = [ [[package]] name = "core-text" -version = "19.2.0" +version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" +checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ "core-foundation", "core-graphics", @@ -466,9 +460,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -511,9 +505,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -539,9 +533,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -571,6 +565,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "cstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "darling" version = "0.10.2" @@ -613,7 +617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.3", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -733,9 +737,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elliptic-curve" @@ -764,9 +768,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys", @@ -790,9 +794,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fdeflate" @@ -828,9 +832,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -838,9 +842,9 @@ dependencies = [ [[package]] name = "float-ord" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" [[package]] name = "flume" @@ -848,7 +852,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -859,11 +863,11 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "font-kit" -version = "0.11.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21fe28504d371085fae9ac7a3450f0b289ab71e07c8e57baa3fb68b9e57d6ce5" +checksum = "2845a73bbd781e691ab7c2a028c579727cd254942e8ced57ff73e0eafd60de87" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "byteorder", "core-foundation", "core-graphics", @@ -871,7 +875,7 @@ dependencies = [ "dirs-next", "dwrote", "float-ord", - "freetype", + "freetype-sys", "lazy_static", "libc", "log", @@ -884,18 +888,30 @@ dependencies = [ [[package]] name = "foreign-types" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ + "foreign-types-macros", "foreign-types-shared", ] +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + [[package]] name = "foreign-types-shared" -version = "0.1.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "fpe" @@ -911,21 +927,11 @@ dependencies = [ "num-traits", ] -[[package]] -name = "freetype" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc8599a3078adf8edeb86c71e9f8fa7d88af5ca31e806a867756081f90f5d83" -dependencies = [ - "freetype-sys", - "libc", -] - [[package]] name = "freetype-sys" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ee28c39a43d89fbed8b4798fb4ba56722cfd2b5af81f9326c27614ba88ecd5" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" dependencies = [ "cc", "libc", @@ -951,9 +957,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -982,9 +988,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "group" @@ -1010,7 +1016,7 @@ dependencies = [ [[package]] name = "halo2_gadgets" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?branch=zsa1#5f436dc3387665fe3201d381791a62a8233b2171" +source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" dependencies = [ "arrayvec", "bitvec", @@ -1034,7 +1040,7 @@ checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" [[package]] name = "halo2_proofs" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?branch=zsa1#5f436dc3387665fe3201d381791a62a8233b2171" +source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" dependencies = [ "blake2b_simd", "ff", @@ -1056,9 +1062,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -1166,7 +1172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -1273,11 +1279,11 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -1288,18 +1294,18 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets", ] [[package]] @@ -1314,21 +1320,21 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1336,9 +1342,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "maybe-rayon" @@ -1352,9 +1358,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -1376,9 +1382,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", @@ -1403,11 +1409,10 @@ checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -1433,9 +1438,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -1443,9 +1448,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -1473,6 +1478,7 @@ name = "orchard" version = "0.8.0" dependencies = [ "aes", + "ahash", "bitvec", "blake2b_simd", "bridgetree", @@ -1480,6 +1486,7 @@ dependencies = [ "ff", "fpe", "group", + "half", "halo2_gadgets", "halo2_proofs", "hex", @@ -1512,9 +1519,9 @@ checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1522,15 +1529,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -1591,9 +1598,9 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "chrono", "font-kit", @@ -1611,15 +1618,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-bitmap" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cebbe1f70205299abc69e8b295035bb52a6a70ee35474ad10011f0a4efb8543" +checksum = "f7e7f6fb8302456d7c264a94dada86f76d76e1a03e2294ee86ca7da92983b0a6" dependencies = [ "gif 0.12.0", "image", @@ -1628,9 +1635,9 @@ dependencies = [ [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -1689,22 +1696,22 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.5.0", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand", @@ -1834,11 +1841,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] @@ -1854,9 +1861,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -1866,9 +1873,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1877,9 +1884,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rfc6979" @@ -1893,18 +1900,18 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "a7439be6844e40133eda024efd85bf07f59d0dd2f59b10c00dd6cfb92cc5c741" dependencies = [ "bytemuck", ] [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -1917,11 +1924,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.33" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1942,9 +1949,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1977,35 +1984,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "e8eddb61f0697cc3989c5d64b452f5488e2b8a60fd7d5076a3045076ffef8cb0" dependencies = [ "itoa", "ryu", @@ -2045,12 +2052,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -2096,9 +2097,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" @@ -2136,9 +2137,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -2182,22 +2183,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", ] [[package]] @@ -2240,7 +2241,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", ] [[package]] @@ -2254,9 +2255,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.17.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375812fa44dab6df41c195cd2f7fecb488f6c09fbaafb62807488cefab642bff" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] name = "typenum" @@ -2300,9 +2301,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" [[package]] name = "version_check" @@ -2356,7 +2357,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -2378,7 +2379,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2423,11 +2424,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys", ] [[package]] @@ -2442,7 +2443,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets", ] [[package]] @@ -2451,22 +2452,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -2475,46 +2461,28 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.5" @@ -2527,48 +2495,24 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.5" @@ -2595,11 +2539,11 @@ dependencies = [ [[package]] name = "yeslogic-fontconfig-sys" -version = "3.2.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2bbd69036d397ebbff671b1b8e4d918610c181c5a16073b96f984a38d08c386" +checksum = "ffb6b23999a8b1a997bf47c7bb4d19ad4029c3327bb3386ebe0a5ff584b33c7a" dependencies = [ - "const-cstr", + "cstr", "dlib", "once_cell", "pkg-config", @@ -2608,7 +2552,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#8b6b31dcea4a883a606425c4b644fca213e78b3b" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#b8bd2a186fc04ec4f55b2db44df7374f03ab5725" dependencies = [ "chacha20", "chacha20poly1305", @@ -2628,29 +2572,29 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -2663,7 +2607,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.68", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 378fb872d..53da31cb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,11 +26,12 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] aes = "0.8" bitvec = "1" blake2b_simd = "=1.0.1" # Last version required rust 1.66 +half = "=2.2.1" # Last version requires Rust 1.70 ff = "0.13" fpe = "0.6" group = { version = "0.13", features = ["wnaf-memuse"] } -halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } -halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } +halo2_gadgets = { git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" } +halo2_proofs = { git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } hex = "0.4" k256 = { version = "0.13.0", features = ["arithmetic", "schnorr"] } lazy_static = "1" @@ -56,14 +57,12 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] bridgetree = "0.4" -criterion = "0.4" #Pinned: 0.5 depends on clap 4 which has MSRV 1.70 -halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } -hex = "0.4" +criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 +halo2_gadgets = { git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11", features = ["test-dependencies"] } proptest = "1.0.0" zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } -#ahash = "=0.8.6" #Pinned: 0.8.7 depends on Rust 1.72 -#half = "=2.2.1" #Pinned: 2.3.1 requires Rust 1.70 +ahash = "=0.8.6" #Pinned: 0.8.7 depends on Rust 1.72 [target.'cfg(unix)'.dev-dependencies] inferno = { version = "0.11", default-features = false, features = ["multithreaded", "nameattr"] } diff --git a/benches/circuit.rs b/benches/circuit.rs index 080411607..668965c4d 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -6,24 +6,29 @@ use criterion::{BenchmarkId, Criterion}; #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; -use orchard::note::AssetBase; use orchard::{ builder::{Builder, BundleType}, circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, }; use rand::rngs::OsRng; -fn criterion_benchmark(c: &mut Criterion) { +mod utils; + +use utils::OrchardFlavorBench; + +fn criterion_benchmark(c: &mut Criterion) { let rng = OsRng; let sk = SpendingKey::from_bytes([7; 32]).unwrap(); let recipient = FullViewingKey::from(&sk).address_at(0u32, Scope::External); - let vk = VerifyingKey::build(); - let pk = ProvingKey::build(); + let vk = VerifyingKey::build::(); + let pk = ProvingKey::build::(); let create_bundle = |num_recipients| { let mut builder = Builder::new( @@ -41,7 +46,7 @@ fn criterion_benchmark(c: &mut Criterion) { ) .unwrap(); } - let bundle: Bundle<_, i64> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().unwrap().0; let instances: Vec<_> = bundle .actions() @@ -55,7 +60,7 @@ fn criterion_benchmark(c: &mut Criterion) { let recipients_range = 1..=4; { - let mut group = c.benchmark_group("proving"); + let mut group = FL::benchmark_group(c, "proving"); group.sample_size(10); for num_recipients in recipients_range.clone() { let (bundle, instances) = create_bundle(num_recipients); @@ -71,7 +76,7 @@ fn criterion_benchmark(c: &mut Criterion) { } { - let mut group = c.benchmark_group("verifying"); + let mut group = FL::benchmark_group(c, "verifying"); for num_recipients in recipients_range { let (bundle, instances) = create_bundle(num_recipients); let bundle = bundle @@ -88,15 +93,25 @@ fn criterion_benchmark(c: &mut Criterion) { } #[cfg(unix)] -criterion_group! { - name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = criterion_benchmark +fn create_config() -> Criterion { + Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))) } + #[cfg(windows)] +fn create_config() -> Criterion { + Criterion::default() +} + criterion_group! { - name = benches; - config = Criterion::default(); - targets = criterion_benchmark + name = benches_vanilla; + config = create_config(); + targets = criterion_benchmark:: } -criterion_main!(benches); + +criterion_group! { + name = benches_zsa; + config = create_config(); + targets = criterion_benchmark:: +} + +criterion_main!(benches_vanilla, benches_zsa); diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 577cc20a0..d17b01e41 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -4,7 +4,8 @@ use orchard::{ circuit::ProvingKey, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note::AssetBase, - note_encryption_v3::{CompactAction, OrchardDomainV3}, + note_encryption::{CompactAction, OrchardDomain}, + orchard_flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, }; @@ -14,9 +15,13 @@ use zcash_note_encryption_zsa::{batch, try_compact_note_decryption, try_note_dec #[cfg(unix)] use pprof::criterion::{Output, PProfProfiler}; -fn bench_note_decryption(c: &mut Criterion) { +mod utils; + +use utils::OrchardFlavorBench; + +fn bench_note_decryption(c: &mut Criterion) { let rng = OsRng; - let pk = ProvingKey::build(); + let pk = ProvingKey::build::(); let fvk = FullViewingKey::from(&SpendingKey::from_bytes([7; 32]).unwrap()); let valid_ivk = fvk.to_ivk(Scope::External); @@ -69,7 +74,7 @@ fn bench_note_decryption(c: &mut Criterion) { None, ) .unwrap(); - let bundle: Bundle<_, i64> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().unwrap().0; bundle .create_proof(&pk, rng) .unwrap() @@ -78,10 +83,10 @@ fn bench_note_decryption(c: &mut Criterion) { }; let action = bundle.actions().first(); - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); let compact = { - let mut group = c.benchmark_group("note-decryption"); + let mut group = FL::benchmark_group(c, "note-decryption"); group.throughput(Throughput::Elements(1)); group.bench_function("valid", |b| { @@ -103,7 +108,7 @@ fn bench_note_decryption(c: &mut Criterion) { }; { - let mut group = c.benchmark_group("compact-note-decryption"); + let mut group = FL::benchmark_group(c, "compact-note-decryption"); group.throughput(Throughput::Elements(invalid_ivks.len() as u64)); group.bench_function("invalid", |b| { b.iter(|| { @@ -119,18 +124,18 @@ fn bench_note_decryption(c: &mut Criterion) { let ivks = 2; let valid_ivks = vec![valid_ivk; ivks]; let actions: Vec<_> = (0..100) - .map(|_| (OrchardDomainV3::for_action(action), action.clone())) + .map(|_| (OrchardDomain::for_action(action), action.clone())) .collect(); let compact: Vec<_> = (0..100) .map(|_| { ( - OrchardDomainV3::for_action(action), + OrchardDomain::for_action(action), CompactAction::from(action), ) }) .collect(); - let mut group = c.benchmark_group("batch-note-decryption"); + let mut group = FL::benchmark_group(c, "batch-note-decryption"); for size in [10, 50, 100] { group.throughput(Throughput::Elements((ivks * size) as u64)); @@ -157,11 +162,25 @@ fn bench_note_decryption(c: &mut Criterion) { } #[cfg(unix)] +fn create_config() -> Criterion { + Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))) +} + +#[cfg(windows)] +fn create_config() -> Criterion { + Criterion::default() +} + criterion_group! { - name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = bench_note_decryption + name = benches_vanilla; + config = create_config(); + targets = bench_note_decryption:: } -#[cfg(not(unix))] -criterion_group!(benches, bench_note_decryption); -criterion_main!(benches); + +criterion_group! { + name = benches_zsa; + config = create_config(); + targets = bench_note_decryption:: +} + +criterion_main!(benches_vanilla, benches_zsa); diff --git a/benches/utils.rs b/benches/utils.rs new file mode 100644 index 000000000..d5f639278 --- /dev/null +++ b/benches/utils.rs @@ -0,0 +1,28 @@ +use criterion::{measurement::Measurement, BenchmarkGroup, Criterion}; + +use orchard::orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}; + +pub(crate) trait OrchardFlavorBench: OrchardFlavor { + fn benchmark_group<'a, M: Measurement>( + c: &'a mut Criterion, + group_name: &str, + ) -> BenchmarkGroup<'a, M>; +} + +impl OrchardFlavorBench for OrchardVanilla { + fn benchmark_group<'a, M: Measurement>( + c: &'a mut Criterion, + group_name: &str, + ) -> BenchmarkGroup<'a, M> { + c.benchmark_group(format!("[OrchardVanilla] {}", group_name)) + } +} + +impl OrchardFlavorBench for OrchardZSA { + fn benchmark_group<'a, M: Measurement>( + c: &'a mut Criterion, + group_name: &str, + ) -> BenchmarkGroup<'a, M> { + c.benchmark_group(format!("[OrchardZSA] {}", group_name)) + } +} diff --git a/src/action.rs b/src/action.rs index 5f3c9f9ac..cb51e32e7 100644 --- a/src/action.rs +++ b/src/action.rs @@ -2,6 +2,7 @@ use memuse::DynamicUsage; use crate::{ note::{ExtractedNoteCommitment, Nullifier, Rho, TransmittedNoteCiphertext}, + note_encryption::OrchardDomainCommon, primitives::redpallas::{self, SpendAuth}, value::ValueCommitment, }; @@ -11,7 +12,7 @@ use crate::{ /// This both creates a note (adding a commitment to the global ledger), and consumes /// some note created prior to this action (adding a nullifier to the global ledger). #[derive(Debug, Clone)] -pub struct Action { +pub struct Action { /// The nullifier of the note being spent. nf: Nullifier, /// The randomized verification key for the note being spent. @@ -19,22 +20,22 @@ pub struct Action { /// A commitment to the new note being created. cmx: ExtractedNoteCommitment, /// The transmitted note ciphertext. - encrypted_note: TransmittedNoteCiphertext, + encrypted_note: TransmittedNoteCiphertext, /// A commitment to the net value created or consumed by this action. cv_net: ValueCommitment, /// The authorization for this action. authorization: A, } -impl Action { +impl Action { /// Constructs an `Action` from its constituent parts. pub fn from_parts( nf: Nullifier, rk: redpallas::VerificationKey, cmx: ExtractedNoteCommitment, - encrypted_note: TransmittedNoteCiphertext, + encrypted_note: TransmittedNoteCiphertext, cv_net: ValueCommitment, - authorization: T, + authorization: A, ) -> Self { Action { nf, @@ -62,7 +63,7 @@ impl Action { } /// Returns the encrypted note ciphertext. - pub fn encrypted_note(&self) -> &TransmittedNoteCiphertext { + pub fn encrypted_note(&self) -> &TransmittedNoteCiphertext { &self.encrypted_note } @@ -77,12 +78,12 @@ impl Action { } /// Returns the authorization for this action. - pub fn authorization(&self) -> &T { + pub fn authorization(&self) -> &A { &self.authorization } /// Transitions this action from one authorization state to another. - pub fn map(self, step: impl FnOnce(T) -> U) -> Action { + pub fn map(self, step: impl FnOnce(A) -> U) -> Action { Action { nf: self.nf, rk: self.rk, @@ -94,7 +95,7 @@ impl Action { } /// Transitions this action from one authorization state to another. - pub fn try_map(self, step: impl FnOnce(T) -> Result) -> Result, E> { + pub fn try_map(self, step: impl FnOnce(A) -> Result) -> Result, E> { Ok(Action { nf: self.nf, rk: self.rk, @@ -106,7 +107,7 @@ impl Action { } } -impl DynamicUsage for Action> { +impl DynamicUsage for Action, D> { #[inline(always)] fn dynamic_usage(&self) -> usize { 0 @@ -127,12 +128,14 @@ pub(crate) mod testing { use proptest::prelude::*; - use crate::note::asset_base::testing::arb_asset_base; + use zcash_note_encryption_zsa::NoteEncryption; + use crate::{ note::{ - commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, - testing::arb_note, TransmittedNoteCiphertext, + asset_base::testing::arb_asset_base, commitment::ExtractedNoteCommitment, + nullifier::testing::arb_nullifier, testing::arb_note, Note, TransmittedNoteCiphertext, }, + note_encryption::{OrchardDomain, OrchardDomainCommon}, primitives::redpallas::{ self, testing::{arb_spendauth_signing_key, arb_spendauth_verification_key}, @@ -142,70 +145,92 @@ pub(crate) mod testing { use super::Action; - prop_compose! { - /// Generate an action without authorization data. - pub fn arb_unauthorized_action(spend_value: NoteValue, output_value: NoteValue)( - nf in arb_nullifier(), - rk in arb_spendauth_verification_key(), - note in arb_note(output_value), - asset in arb_asset_base() - ) -> Action<()> { - let cmx = ExtractedNoteCommitment::from(note.commitment()); - let cv_net = ValueCommitment::derive( - spend_value - output_value, - ValueCommitTrapdoor::zero(), - asset - ); - // FIXME: make a real one from the note. - let encrypted_note = TransmittedNoteCiphertext { - epk_bytes: [0u8; 32], - enc_ciphertext: [0u8; 612], - out_ciphertext: [0u8; 80] - }; - Action { - nf, - rk, - cmx, - encrypted_note, - cv_net, - authorization: () + /// `ActionArb` adapts `arb_...` functions for both Vanilla and ZSA Orchard protocol flavors + /// in property-based testing, addressing proptest crate limitations. + #[derive(Debug)] + pub struct ActionArb { + phantom: std::marker::PhantomData, + } + + impl ActionArb { + fn encrypt_note( + note: Note, + memo: Vec, + cmx: &ExtractedNoteCommitment, + cv_net: &ValueCommitment, + rng: &mut R, + ) -> TransmittedNoteCiphertext { + let encryptor = + NoteEncryption::>::new(None, note, memo.try_into().unwrap()); + + TransmittedNoteCiphertext { + epk_bytes: encryptor.epk().to_bytes().0, + enc_ciphertext: encryptor.encrypt_note_plaintext(), + out_ciphertext: encryptor.encrypt_outgoing_plaintext(cv_net, cmx, rng), + } + } + + prop_compose! { + /// Generate an action without authorization data. + pub fn arb_unauthorized_action(spend_value: NoteValue, output_value: NoteValue)( + nf in arb_nullifier(), + rk in arb_spendauth_verification_key(), + note in arb_note(output_value), + asset in arb_asset_base(), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + memo in prop::collection::vec(prop::num::u8::ANY, 512), + ) -> Action<(), D> { + let cmx = ExtractedNoteCommitment::from(note.commitment()); + let cv_net = ValueCommitment::derive( + spend_value - output_value, + ValueCommitTrapdoor::zero(), + asset + ); + + let mut rng = StdRng::from_seed(rng_seed); + let encrypted_note = Self::encrypt_note(note, memo, &cmx, &cv_net, &mut rng); + + Action { + nf, + rk, + cmx, + encrypted_note, + cv_net, + authorization: () + } } } - } - prop_compose! { - /// Generate an action with invalid (random) authorization data. - pub fn arb_action(spend_value: NoteValue, output_value: NoteValue)( - nf in arb_nullifier(), - sk in arb_spendauth_signing_key(), - note in arb_note(output_value), - rng_seed in prop::array::uniform32(prop::num::u8::ANY), - fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - asset in arb_asset_base() - ) -> Action> { - let cmx = ExtractedNoteCommitment::from(note.commitment()); - let cv_net = ValueCommitment::derive( - spend_value - output_value, - ValueCommitTrapdoor::zero(), - asset - ); - - // FIXME: make a real one from the note. - let encrypted_note = TransmittedNoteCiphertext { - epk_bytes: [0u8; 32], - enc_ciphertext: [0u8; 612], - out_ciphertext: [0u8; 80] - }; - - let rng = StdRng::from_seed(rng_seed); - - Action { - nf, - rk: redpallas::VerificationKey::from(&sk), - cmx, - encrypted_note, - cv_net, - authorization: sk.sign(rng, &fake_sighash), + prop_compose! { + /// Generate an action with invalid (random) authorization data. + pub fn arb_action(spend_value: NoteValue, output_value: NoteValue)( + nf in arb_nullifier(), + sk in arb_spendauth_signing_key(), + note in arb_note(output_value), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY), + asset in arb_asset_base(), + memo in prop::collection::vec(prop::num::u8::ANY, 512), + ) -> Action, D> { + let cmx = ExtractedNoteCommitment::from(note.commitment()); + let cv_net = ValueCommitment::derive( + spend_value - output_value, + ValueCommitTrapdoor::zero(), + asset + ); + + let mut rng = StdRng::from_seed(rng_seed); + + let encrypted_note = Self::encrypt_note(note, memo, &cmx, &cv_net, &mut rng); + + Action { + nf, + rk: redpallas::VerificationKey::from(&sk), + cmx, + encrypted_note, + cv_net, + authorization: sk.sign(rng, &fake_sighash), + } } } } diff --git a/src/builder.rs b/src/builder.rs index ff3459012..fa532275a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -10,17 +10,21 @@ use nonempty::NonEmpty; use pasta_curves::pallas; use rand::{prelude::SliceRandom, CryptoRng, RngCore}; +use zcash_note_encryption_zsa::NoteEncryption; + +use crate::builder::BuildError::{BurnNative, BurnZero}; use crate::{ action::Action, address::Address, bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags}, - circuit::{Circuit, Instance, Proof, ProvingKey}, + circuit::{Circuit, Instance, OrchardCircuit, Proof, ProvingKey}, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, }, note::{AssetBase, Note, Rho, TransmittedNoteCiphertext}, - note_encryption_v3::OrchardNoteEncryption, + note_encryption::{OrchardDomain, OrchardDomainCommon}, + orchard_flavor::OrchardFlavor, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -109,7 +113,7 @@ impl BundleType { pub fn flags(&self) -> Flags { match self { BundleType::Transactional { flags, .. } => *flags, - BundleType::Coinbase => Flags::SPENDS_DISABLED, + BundleType::Coinbase => Flags::SPENDS_DISABLED_WITHOUT_ZSA, } } } @@ -137,6 +141,12 @@ pub enum BuildError { DuplicateSignature, /// The bundle being constructed violated the construction rules for the requested bundle type. BundleTypeNotSatisfiable, + /// Native asset cannot be burned + BurnNative, + /// The value to be burned cannot be zero + BurnZero, + /// The asset to be burned is duplicated. + BurnDuplicateAsset, } impl Display for BuildError { @@ -156,6 +166,9 @@ impl Display for BuildError { AnchorMismatch => { f.write_str("All spends must share the anchor requested for the transaction.") } + BurnNative => f.write_str("Burning is only possible for non-native assets"), + BurnZero => f.write_str("Burning is not possible for zero values"), + BurnDuplicateAsset => f.write_str("Duplicate assets are not allowed when burning"), } } } @@ -378,7 +391,10 @@ impl ActionInfo { /// # Panics /// /// Panics if the asset types of the spent and output notes do not match. - fn build(self, mut rng: impl RngCore) -> (Action, Circuit) { + fn build( + self, + mut rng: impl RngCore, + ) -> (Action, Circuit) { assert_eq!( self.spend.note.asset(), self.output.asset, @@ -405,11 +421,12 @@ impl ActionInfo { let cm_new = note.commitment(); let cmx = cm_new.into(); - let encryptor = OrchardNoteEncryption::new(self.output.ovk, note, self.output.memo); + let encryptor = + NoteEncryption::>::new(self.output.ovk, note, self.output.memo); let encrypted_note = TransmittedNoteCiphertext { epk_bytes: encryptor.epk().to_bytes().0, - enc_ciphertext: encryptor.encrypt_note_plaintext().0, + enc_ciphertext: encryptor.encrypt_note_plaintext(), out_ciphertext: encryptor.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut rng), }; @@ -425,7 +442,7 @@ impl ActionInfo { parts: SigningParts { ak, alpha }, }, ), - Circuit::from_action_context_unchecked(self.spend, note, alpha, self.rcv), + Circuit::::from_action_context_unchecked(self.spend, note, alpha, self.rcv), ) } } @@ -433,7 +450,7 @@ impl ActionInfo { /// Type alias for an in-progress bundle that has no proofs or signatures. /// /// This is returned by [`Builder::build`]. -pub type UnauthorizedBundle = Bundle, V>; +pub type UnauthorizedBundle = Bundle, Unauthorized>, V, D>; /// Metadata about a bundle created by [`bundle`] or [`Builder::build`] that is not /// necessarily recoverable from the bundle itself. @@ -485,13 +502,16 @@ impl BundleMetadata { } } +/// A tuple containing an in-progress bundle with no proofs or signatures, and its associated metadata. +pub type UnauthorizedBundleWithMetadata = (UnauthorizedBundle, BundleMetadata); + /// A builder that constructs a [`Bundle`] from a set of notes to be spent, and outputs /// to receive funds. #[derive(Debug)] pub struct Builder { spends: Vec, outputs: Vec, - burn: HashMap, + burn: HashMap, bundle_type: BundleType, anchor: Anchor, } @@ -518,7 +538,7 @@ impl Builder { /// Returns an error if the given Merkle path does not have the required anchor for /// the given note. /// - /// [`OrchardDomain`]: crate::note_encryption_v3::OrchardDomainV3 + /// [`OrchardDomain`]: crate::note_encryption::OrchardDomain /// [`MerkleHashOrchard`]: crate::tree::MerkleHashOrchard pub fn add_spend( &mut self, @@ -564,19 +584,24 @@ impl Builder { } /// Add an instruction to burn a given amount of a specific asset. - pub fn add_burn(&mut self, asset: AssetBase, value: NoteValue) -> Result<(), &'static str> { + pub fn add_burn(&mut self, asset: AssetBase, value: NoteValue) -> Result<(), BuildError> { + use std::collections::hash_map::Entry; + if asset.is_native().into() { - return Err("Burning is only possible for non-native assets"); + return Err(BurnNative); } if value.inner() == 0 { - return Err("Burning is not possible for zero values"); + return Err(BurnZero); } - let cur = *self.burn.get(&asset).unwrap_or(&ValueSum::zero()); - let sum = (cur + value).ok_or("Orchard ValueSum operation overflowed")?; - self.burn.insert(asset, sum); - Ok(()) + match self.burn.entry(asset) { + Entry::Occupied(_) => Err(BuildError::BurnDuplicateAsset), + Entry::Vacant(entry) => { + entry.insert(value); + Ok(()) + } + } } /// Returns the action spend components that will be produced by the @@ -611,7 +636,7 @@ impl Builder { .iter() .map(|output| NoteValue::zero() - output.value), ) - .fold(Some(ValueSum::zero()), |acc, note_value| acc? + note_value) + .try_fold(ValueSum::zero(), |acc, note_value| acc + note_value) .ok_or(OverflowError)?; i64::try_from(value_balance).and_then(|i| V::try_from(i).map_err(|_| value::OverflowError)) } @@ -620,10 +645,10 @@ impl Builder { /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. - pub fn build>( + pub fn build, FL: OrchardFlavor>( self, rng: impl RngCore, - ) -> Result, BundleMetadata)>, BuildError> { + ) -> Result>, BuildError> { bundle( rng, self.anchor, @@ -640,8 +665,8 @@ impl Builder { /// The index is used to track the position of the note in the bundle. type MetadataIdx = Option; -/// Partition a list of spends and recipients by note types. -/// Method creates single dummy ZEC note if spends and recipients are both empty. +/// Partition a list of spends and outputs by note types. +/// Method creates single dummy ZEC note if spends and outputs are both empty. #[allow(clippy::type_complexity)] fn partition_by_asset( spends: &[SpendInfo], @@ -700,14 +725,15 @@ fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) /// /// The returned bundle will have no proof or signatures; these can be applied with /// [`Bundle::create_proof`] and [`Bundle::apply_signatures`] respectively. -pub fn bundle>( +#[allow(clippy::type_complexity)] +pub fn bundle, FL: OrchardFlavor>( mut rng: impl RngCore, anchor: Anchor, bundle_type: BundleType, spends: Vec, outputs: Vec, - burn: HashMap, -) -> Result, BundleMetadata)>, BuildError> { + burn: HashMap, +) -> Result>, BuildError> { let flags = bundle_type.flags(); let num_requested_spends = spends.len(); @@ -825,19 +851,22 @@ pub fn bundle>( let (actions, circuits): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); - // Verify that bsk and bvk are consistent. - let bvk = derive_bvk( - &actions, - native_value_balance, - burn.iter() - .flat_map(|(asset, value)| -> Result<_, BuildError> { Ok((*asset, (*value).into()?)) }), - ); - assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); - let burn = burn .into_iter() - .map(|(asset, value)| Ok((asset, value.into()?))) - .collect::, BuildError>>()?; + .map(|(asset, value)| { + Ok(( + asset, + NoteValue::from_raw( + u64::try_from(i128::from(value)) + .map_err(|_| BuildError::ValueSum(OverflowError))?, + ), + )) + }) + .collect::, BuildError>>()?; + + // Verify that bsk and bvk are consistent. + let bvk = derive_bvk(&actions, native_value_balance, burn.iter().cloned()); + assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); Ok(NonEmpty::from_vec(actions).map(|actions| { ( @@ -870,6 +899,19 @@ pub struct InProgress { sigs: S, } +impl InProgress { + /// Mutate the proof using the provided function. + pub fn map_proof(self, f: F) -> InProgress + where + F: FnOnce(P) -> P2, + { + InProgress { + proof: f(self.proof), + sigs: self.sigs, + } + } +} + impl Authorization for InProgress { type SpendAuth = S::SpendAuth; } @@ -878,11 +920,11 @@ impl Authorization for InProgress /// /// This struct contains the private data needed to create a [`Proof`] for a [`Bundle`]. #[derive(Clone, Debug)] -pub struct Unproven { - circuits: Vec, +pub struct Unproven { + circuits: Vec>, } -impl InProgress { +impl InProgress, S> { /// Creates the proof for this bundle. pub fn create_proof( &self, @@ -894,13 +936,13 @@ impl InProgress { } } -impl Bundle, V> { +impl Bundle, S>, V, FL> { /// Creates the proof for this bundle. pub fn create_proof( self, pk: &ProvingKey, mut rng: impl RngCore, - ) -> Result, V>, BuildError> { + ) -> Result, V, FL>, BuildError> { let instances: Vec<_> = self .actions() .iter() @@ -983,7 +1025,7 @@ impl MaybeSigned { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Loads the sighash into this bundle, preparing it for signing. /// /// This API ensures that all signatures are created over the same sighash. @@ -991,7 +1033,7 @@ impl Bundle, V> { self, mut rng: R, sighash: [u8; 32], - ) -> Bundle, V> { + ) -> Bundle, V, D> { self.map_authorization( &mut rng, |rng, _, SigningMetadata { dummy_ask, parts }| { @@ -1012,7 +1054,7 @@ impl Bundle, V> { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Applies signatures to this bundle, in order to authorize it. /// /// This is a helper method that wraps [`Bundle::prepare`], [`Bundle::sign`], and @@ -1022,7 +1064,7 @@ impl Bundle, V> { mut rng: R, sighash: [u8; 32], signing_keys: &[SpendAuthorizingKey], - ) -> Result, BuildError> { + ) -> Result, BuildError> { signing_keys .iter() .fold(self.prepare(&mut rng, sighash), |partial, ask| { @@ -1032,7 +1074,7 @@ impl Bundle, V> { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Signs this bundle with the given [`SpendAuthorizingKey`]. /// /// This will apply signatures for all notes controlled by this spending key. @@ -1095,11 +1137,11 @@ impl Bundle, V> { } } -impl Bundle, V> { +impl Bundle, V, D> { /// Finalizes this bundle, enabling it to be included in a transaction. /// /// Returns an error if any signatures are missing. - pub fn finalize(self) -> Result, BuildError> { + pub fn finalize(self) -> Result, BuildError> { self.try_map_authorization( &mut (), |_, _, maybe| maybe.finalize(), @@ -1164,6 +1206,8 @@ pub mod testing { circuit::ProvingKey, keys::{testing::arb_spending_key, FullViewingKey, SpendAuthorizingKey, SpendingKey}, note::testing::arb_note, + note_encryption::OrchardDomainCommon, + orchard_flavor::OrchardFlavor, tree::{Anchor, MerkleHashOrchard, MerklePath}, value::{testing::arb_positive_note_value, NoteValue, MAX_NOTE_VALUE}, Address, Note, @@ -1190,7 +1234,9 @@ pub mod testing { impl ArbitraryBundleInputs { /// Create a bundle from the set of arbitrary bundle inputs. - fn into_bundle + Copy + Into>(mut self) -> Bundle { + fn into_bundle + Copy + Into, FL: OrchardFlavor>( + mut self, + ) -> Bundle { let fvk = FullViewingKey::from(&self.sk); let mut builder = Builder::new(BundleType::DEFAULT_ZSA, self.anchor); @@ -1207,7 +1253,7 @@ pub mod testing { .unwrap(); } - let pk = ProvingKey::build(); + let pk = ProvingKey::build::(); builder .build(&mut self.rng) .unwrap() @@ -1222,70 +1268,78 @@ pub mod testing { } } - prop_compose! { - /// Produce a random valid Orchard bundle. - fn arb_bundle_inputs(sk: SpendingKey) - ( - n_notes in 1usize..30, - n_outputs in 1..30, + /// `BuilderArb` adapts `arb_...` functions for both Vanilla and ZSA Orchard protocol variations + /// in property-based testing, addressing proptest crate limitations. + #[derive(Debug)] + pub struct BuilderArb { + phantom: std::marker::PhantomData, + } - ) - ( - // generate note values that we're certain won't exceed MAX_NOTE_VALUE in total - notes in vec( - arb_positive_note_value(MAX_NOTE_VALUE / n_notes as u64).prop_flat_map(arb_note), - n_notes - ), - output_amounts in vec( - arb_address().prop_flat_map(move |a| { - arb_positive_note_value(MAX_NOTE_VALUE / n_outputs as u64) - .prop_map(move |v| { - (a,v, AssetBase::native()) - }) - }), - n_outputs as usize, - ), - rng_seed in prop::array::uniform32(prop::num::u8::ANY) - ) -> ArbitraryBundleInputs { - use crate::constants::MERKLE_DEPTH_ORCHARD; - let mut frontier = Frontier::::empty(); - let mut notes_and_auth_paths: Vec<(Note, MerklePath)> = Vec::new(); - - for note in notes.iter() { - let leaf = MerkleHashOrchard::from_cmx(¬e.commitment().into()); - frontier.append(leaf); - - let path = frontier - .witness(|addr| Some(::empty_root(addr.level()))) - .ok() - .flatten() - .expect("we can always construct a correct Merkle path"); - notes_and_auth_paths.push((*note, path.into())); - } + impl BuilderArb { + prop_compose! { + /// Produce a random valid Orchard bundle. + fn arb_bundle_inputs(sk: SpendingKey) + ( + n_notes in 1usize..30, + n_outputs in 1..30, + ) + ( + // generate note values that we're certain won't exceed MAX_NOTE_VALUE in total + notes in vec( + arb_positive_note_value(MAX_NOTE_VALUE / n_notes as u64).prop_flat_map(arb_note), + n_notes + ), + output_amounts in vec( + arb_address().prop_flat_map(move |a| { + arb_positive_note_value(MAX_NOTE_VALUE / n_outputs as u64) + .prop_map(move |v| { + (a,v, AssetBase::native()) + }) + }), + n_outputs as usize, + ), + rng_seed in prop::array::uniform32(prop::num::u8::ANY) + ) -> ArbitraryBundleInputs { + use crate::constants::MERKLE_DEPTH_ORCHARD; + let mut frontier = Frontier::::empty(); + let mut notes_and_auth_paths: Vec<(Note, MerklePath)> = Vec::new(); + + for note in notes.iter() { + let leaf = MerkleHashOrchard::from_cmx(¬e.commitment().into()); + frontier.append(leaf); + + let path = frontier + .witness(|addr| Some(::empty_root(addr.level()))) + .ok() + .flatten() + .expect("we can always construct a correct Merkle path"); + notes_and_auth_paths.push((*note, path.into())); + } - ArbitraryBundleInputs { - rng: StdRng::from_seed(rng_seed), - sk, - anchor: frontier.root().into(), - notes: notes_and_auth_paths, - output_amounts + ArbitraryBundleInputs { + rng: StdRng::from_seed(rng_seed), + sk, + anchor: frontier.root().into(), + notes: notes_and_auth_paths, + output_amounts + } } } - } - /// Produce an arbitrary valid Orchard bundle using a random spending key. - pub fn arb_bundle + Debug + Copy + Into>( - ) -> impl Strategy> { - arb_spending_key() - .prop_flat_map(arb_bundle_inputs) - .prop_map(|inputs| inputs.into_bundle::()) - } + /// Produce an arbitrary valid Orchard bundle using a random spending key. + pub fn arb_bundle + Debug + Copy + Into>( + ) -> impl Strategy> { + arb_spending_key() + .prop_flat_map(BuilderArb::::arb_bundle_inputs) + .prop_map(|inputs| inputs.into_bundle::()) + } - /// Produce an arbitrary valid Orchard bundle using a specified spending key. - pub fn arb_bundle_with_key + Debug + Copy + Into>( - k: SpendingKey, - ) -> impl Strategy> { - arb_bundle_inputs(k).prop_map(|inputs| inputs.into_bundle::()) + /// Produce an arbitrary valid Orchard bundle using a specified spending key. + pub fn arb_bundle_with_key + Debug + Copy + Into>( + k: SpendingKey, + ) -> impl Strategy> { + BuilderArb::::arb_bundle_inputs(k).prop_map(|inputs| inputs.into_bundle::()) + } } } @@ -1293,21 +1347,22 @@ pub mod testing { mod tests { use rand::rngs::OsRng; - use super::Builder; - use crate::note::AssetBase; use crate::{ builder::BundleType, bundle::{Authorized, Bundle}, circuit::ProvingKey, constants::MERKLE_DEPTH_ORCHARD, keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, tree::EMPTY_ROOTS, value::NoteValue, }; - #[test] - fn shielding_bundle() { - let pk = ProvingKey::build(); + use super::Builder; + + fn shielding_bundle() { + let pk = ProvingKey::build::(); let mut rng = OsRng; let sk = SpendingKey::random(&mut rng); @@ -1331,7 +1386,7 @@ mod tests { let balance: i64 = builder.value_balance().unwrap(); assert_eq!(balance, -5000); - let bundle: Bundle = builder + let bundle: Bundle = builder .build(&mut rng) .unwrap() .unwrap() @@ -1343,4 +1398,14 @@ mod tests { .unwrap(); assert_eq!(bundle.value_balance(), &(-5000)) } + + #[test] + fn shielding_bundle_vanilla() { + shielding_bundle::() + } + + #[test] + fn shielding_bundle_zsa() { + shielding_bundle::() + } } diff --git a/src/bundle.rs b/src/bundle.rs index 385e5fec1..de69c3613 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -13,21 +13,23 @@ use memuse::DynamicUsage; use nonempty::NonEmpty; use zcash_note_encryption_zsa::{try_note_decryption, try_output_recovery_with_ovk}; -use crate::note::AssetBase; use crate::{ action::Action, address::Address, bundle::commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, circuit::{Instance, Proof, VerifyingKey}, keys::{IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey}, - note::Note, - note_encryption_v3::OrchardDomainV3, + note::{AssetBase, Note}, + note_encryption::{OrchardDomain, OrchardDomainCommon}, + orchard_flavor::OrchardFlavor, primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, - value::{ValueCommitTrapdoor, ValueCommitment, ValueSum}, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum}, }; -impl Action { +pub(crate) use commitments::OrchardHash; + +impl Action { /// Prepares the public instance for this action, for creating and verifying the /// bundle proof. pub fn to_instance(&self, flags: Flags, anchor: Anchor) -> Instance { @@ -99,13 +101,20 @@ impl Flags { zsa_enabled: true, }; - /// The flag set with spends disabled. - pub const SPENDS_DISABLED: Flags = Flags { + /// The flag set with spends and ZSA disabled. + pub const SPENDS_DISABLED_WITHOUT_ZSA: Flags = Flags { spends_enabled: false, outputs_enabled: true, zsa_enabled: false, }; + /// The flag set with spends disabled and ZSA enabled. + pub const SPENDS_DISABLED_WITH_ZSA: Flags = Flags { + spends_enabled: false, + outputs_enabled: true, + zsa_enabled: true, + }; + /// The flag set with outputs disabled. pub const OUTPUTS_DISABLED: Flags = Flags { spends_enabled: true, @@ -185,9 +194,9 @@ pub trait Authorization: fmt::Debug { /// A bundle of actions to be applied to the ledger. #[derive(Clone)] -pub struct Bundle { +pub struct Bundle { /// The list of actions that make up this bundle. - actions: NonEmpty>, + actions: NonEmpty>, /// Orchard-specific transaction-level flags for this bundle. flags: Flags, /// The net value moved out of the Orchard shielded pool. @@ -195,18 +204,18 @@ pub struct Bundle { /// This is the sum of Orchard spends minus the sum of Orchard outputs. value_balance: V, /// Assets intended for burning - burn: Vec<(AssetBase, V)>, + burn: Vec<(AssetBase, NoteValue)>, /// The root of the Orchard commitment tree that this bundle commits to. anchor: Anchor, /// The authorization for this bundle. - authorization: T, + authorization: A, } -impl fmt::Debug for Bundle { +impl fmt::Debug for Bundle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// Helper struct for debug-printing actions without exposing `NonEmpty`. - struct Actions<'a, T>(&'a NonEmpty>); - impl<'a, T: fmt::Debug> fmt::Debug for Actions<'a, T> { + struct Actions<'a, A, D: OrchardDomainCommon>(&'a NonEmpty>); + impl<'a, A: fmt::Debug, D: OrchardDomainCommon> fmt::Debug for Actions<'a, A, D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.0.iter()).finish() } @@ -222,15 +231,15 @@ impl fmt::Debug for Bundle { } } -impl Bundle { +impl Bundle { /// Constructs a `Bundle` from its constituent parts. pub fn from_parts( - actions: NonEmpty>, + actions: NonEmpty>, flags: Flags, value_balance: V, - burn: Vec<(AssetBase, V)>, + burn: Vec<(AssetBase, NoteValue)>, anchor: Anchor, - authorization: T, + authorization: A, ) -> Self { Bundle { actions, @@ -243,7 +252,7 @@ impl Bundle { } /// Returns the list of actions that make up this bundle. - pub fn actions(&self) -> &NonEmpty> { + pub fn actions(&self) -> &NonEmpty> { &self.actions } @@ -260,7 +269,7 @@ impl Bundle { } /// Returns assets intended for burning - pub fn burn(&self) -> &Vec<(AssetBase, V)> { + pub fn burn(&self) -> &Vec<(AssetBase, NoteValue)> { &self.burn } @@ -272,7 +281,7 @@ impl Bundle { /// Returns the authorization for this bundle. /// /// In the case of a `Bundle`, this is the proof and binding signature. - pub fn authorization(&self) -> &T { + pub fn authorization(&self) -> &A { &self.authorization } @@ -281,16 +290,12 @@ impl Bundle { pub fn try_map_value_balance Result>( self, f: F, - ) -> Result, E> { + ) -> Result, E> { Ok(Bundle { actions: self.actions, flags: self.flags, value_balance: f(self.value_balance)?, - burn: self - .burn - .into_iter() - .map(|(asset, value)| Ok((asset, f(value)?))) - .collect::, E>>()?, + burn: self.burn, anchor: self.anchor, authorization: self.authorization, }) @@ -300,9 +305,9 @@ impl Bundle { pub fn map_authorization( self, context: &mut R, - mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> U::SpendAuth, - step: impl FnOnce(&mut R, T) -> U, - ) -> Bundle { + mut spend_auth: impl FnMut(&mut R, &A, A::SpendAuth) -> U::SpendAuth, + step: impl FnOnce(&mut R, A) -> U, + ) -> Bundle { let authorization = self.authorization; Bundle { actions: self @@ -320,9 +325,9 @@ impl Bundle { pub fn try_map_authorization( self, context: &mut R, - mut spend_auth: impl FnMut(&mut R, &T, T::SpendAuth) -> Result, - step: impl FnOnce(&mut R, T) -> Result, - ) -> Result, E> { + mut spend_auth: impl FnMut(&mut R, &A, A::SpendAuth) -> Result, + step: impl FnOnce(&mut R, A) -> Result, + ) -> Result, E> { let authorization = self.authorization; let new_actions = self .actions @@ -363,7 +368,7 @@ impl Bundle { .iter() .enumerate() .filter_map(|(idx, action)| { - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); prepared_keys.iter().find_map(|(ivk, prepared_ivk)| { try_note_decryption(&domain, prepared_ivk, action) .map(|(n, a, m)| (idx, (*ivk).clone(), n, a, m)) @@ -382,7 +387,7 @@ impl Bundle { ) -> Option<(Note, Address, [u8; 512])> { let prepared_ivk = PreparedIncomingViewingKey::new(key); self.actions.get(action_idx).and_then(move |action| { - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); try_note_decryption(&domain, &prepared_ivk, action) }) } @@ -399,7 +404,7 @@ impl Bundle { .iter() .enumerate() .filter_map(|(idx, action)| { - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); keys.iter().find_map(move |key| { try_output_recovery_with_ovk( &domain, @@ -423,7 +428,7 @@ impl Bundle { key: &OutgoingViewingKey, ) -> Option<(Note, Address, [u8; 512])> { self.actions.get(action_idx).and_then(move |action| { - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); try_output_recovery_with_ovk( &domain, key, @@ -435,10 +440,10 @@ impl Bundle { } } -pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into>( - actions: impl IntoIterator>, +pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into, FL: 'a + OrchardFlavor>( + actions: impl IntoIterator>, value_balance: V, - burn: impl Iterator, + burn: impl Iterator, ) -> redpallas::VerificationKey { // https://p.z.cash/TCR:bad-txns-orchard-binding-signature-invalid?partial (actions @@ -452,17 +457,13 @@ pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into>( ) - burn .map(|(asset, value)| { - ValueCommitment::derive( - ValueSum::from_raw(value.into()), - ValueCommitTrapdoor::zero(), - asset, - ) + ValueCommitment::derive(ValueSum::from(value), ValueCommitTrapdoor::zero(), asset) }) .sum::()) .into_bvk() } -impl> Bundle { +impl, FL: OrchardFlavor> Bundle { /// Computes a commitment to the effects of this bundle, suitable for inclusion within /// a transaction ID. pub fn commitment(&self) -> BundleCommitment { @@ -509,7 +510,7 @@ impl Authorized { } } -impl Bundle { +impl Bundle { /// Computes a commitment to the authorizing data within for this bundle. /// /// This together with `Bundle::commitment` bind the entire bundle. @@ -525,7 +526,7 @@ impl Bundle { } } -impl DynamicUsage for Bundle { +impl DynamicUsage for Bundle { fn dynamic_usage(&self) -> usize { self.actions.dynamic_usage() + self.value_balance.dynamic_usage() @@ -590,10 +591,11 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; - pub use crate::action::testing::{arb_action, arb_unauthorized_action}; + pub use crate::action::testing::ActionArb; use crate::note::asset_base::testing::arb_zsa_asset_base; use crate::note::AssetBase; - use crate::value::testing::arb_value_sum; + use crate::note_encryption::OrchardDomainCommon; + use crate::value::testing::arb_note_value; /// Marker for an unauthorized bundle with no proofs or signatures. #[derive(Debug)] @@ -603,142 +605,151 @@ pub mod testing { type SpendAuth = (); } - /// Generate an unauthorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. - pub fn arb_unauthorized_action_n( - n_actions: usize, - flags: Flags, - ) -> impl Strategy)> { - let spend_value_gen = if flags.spends_enabled { - Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) - } else { - Strategy::boxed(Just(NoteValue::zero())) - }; + /// `BundleArb` adapts `arb_...` functions for both Vanilla and ZSA Orchard protocol variations + /// in property-based testing, addressing proptest crate limitations. + #[derive(Debug)] + pub struct BundleArb { + phantom: std::marker::PhantomData, + } - spend_value_gen.prop_flat_map(move |spend_value| { - let output_value_gen = if flags.outputs_enabled { + impl BundleArb { + /// Generate an unauthorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. + pub fn arb_unauthorized_action_n( + n_actions: usize, + flags: Flags, + ) -> impl Strategy)> { + let spend_value_gen = if flags.spends_enabled { Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) } else { Strategy::boxed(Just(NoteValue::zero())) }; - output_value_gen.prop_flat_map(move |output_value| { - arb_unauthorized_action(spend_value, output_value) - .prop_map(move |a| (spend_value - output_value, a)) - }) - }) - } + spend_value_gen.prop_flat_map(move |spend_value| { + let output_value_gen = if flags.outputs_enabled { + Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) + } else { + Strategy::boxed(Just(NoteValue::zero())) + }; - /// Generate an authorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. - pub fn arb_action_n( - n_actions: usize, - flags: Flags, - ) -> impl Strategy>)> { - let spend_value_gen = if flags.spends_enabled { - Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) - } else { - Strategy::boxed(Just(NoteValue::zero())) - }; + output_value_gen.prop_flat_map(move |output_value| { + ActionArb::arb_unauthorized_action(spend_value, output_value) + .prop_map(move |a| (spend_value - output_value, a)) + }) + }) + } - spend_value_gen.prop_flat_map(move |spend_value| { - let output_value_gen = if flags.outputs_enabled { + /// Generate an authorized action having spend and output values less than MAX_NOTE_VALUE / n_actions. + pub fn arb_action_n( + n_actions: usize, + flags: Flags, + ) -> impl Strategy, D>)> { + let spend_value_gen = if flags.spends_enabled { Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) } else { Strategy::boxed(Just(NoteValue::zero())) }; - output_value_gen.prop_flat_map(move |output_value| { - arb_action(spend_value, output_value) - .prop_map(move |a| (spend_value - output_value, a)) + spend_value_gen.prop_flat_map(move |spend_value| { + let output_value_gen = if flags.outputs_enabled { + Strategy::boxed(arb_note_value_bounded(MAX_NOTE_VALUE / n_actions as u64)) + } else { + Strategy::boxed(Just(NoteValue::zero())) + }; + + output_value_gen.prop_flat_map(move |output_value| { + ActionArb::arb_action(spend_value, output_value) + .prop_map(move |a| (spend_value - output_value, a)) + }) }) - }) - } + } - prop_compose! { - /// Create an arbitrary vector of assets to burn. - pub fn arb_asset_to_burn() - ( - asset_base in arb_zsa_asset_base(), - value in arb_value_sum() - ) -> (AssetBase, ValueSum) { - (asset_base, value) + prop_compose! { + /// Create an arbitrary vector of assets to burn. + pub fn arb_asset_to_burn() + ( + asset_base in arb_zsa_asset_base(), + value in arb_note_value() + ) -> (AssetBase, NoteValue) { + (asset_base, value) + } } - } - prop_compose! { - /// Create an arbitrary set of flags. - pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY, zsa_enabled in prop::bool::ANY) -> Flags { - Flags::from_parts(spends_enabled, outputs_enabled, zsa_enabled) + prop_compose! { + /// Create an arbitrary set of flags. + pub fn arb_flags()(spends_enabled in prop::bool::ANY, outputs_enabled in prop::bool::ANY, zsa_enabled in prop::bool::ANY) -> Flags { + Flags::from_parts(spends_enabled, outputs_enabled, zsa_enabled) + } } - } - prop_compose! { - fn arb_base()(bytes in prop::array::uniform32(0u8..)) -> pallas::Base { - // Instead of rejecting out-of-range bytes, let's reduce them. - let mut buf = [0; 64]; - buf[..32].copy_from_slice(&bytes); - pallas::Base::from_uniform_bytes(&buf) + prop_compose! { + fn arb_base()(bytes in prop::array::uniform32(0u8..)) -> pallas::Base { + // Instead of rejecting out-of-range bytes, let's reduce them. + let mut buf = [0; 64]; + buf[..32].copy_from_slice(&bytes); + pallas::Base::from_uniform_bytes(&buf) + } } - } - prop_compose! { - /// Generate an arbitrary unauthorized bundle. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_bundle`] - pub fn arb_unauthorized_bundle(n_actions: usize) - ( - flags in arb_flags(), - ) - ( - acts in vec(arb_unauthorized_action_n(n_actions, flags), n_actions), - anchor in arb_base().prop_map(Anchor::from), - flags in Just(flags), - burn in vec(arb_asset_to_burn(), 1usize..10) - ) -> Bundle { - let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); - - Bundle::from_parts( - NonEmpty::from_vec(actions).unwrap(), - flags, - balances.into_iter().sum::>().unwrap(), - burn, - anchor, - Unauthorized, + prop_compose! { + /// Generate an arbitrary unauthorized bundle. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_bundle`] + pub fn arb_unauthorized_bundle(n_actions: usize) + ( + flags in Self::arb_flags(), ) + ( + acts in vec(Self::arb_unauthorized_action_n(n_actions, flags), n_actions), + anchor in Self::arb_base().prop_map(Anchor::from), + flags in Just(flags), + burn in vec(Self::arb_asset_to_burn(), 1usize..10) + ) -> Bundle { + let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); + + Bundle::from_parts( + NonEmpty::from_vec(actions).unwrap(), + flags, + balances.into_iter().sum::>().unwrap(), + burn, + anchor, + Unauthorized, + ) + } } - } - prop_compose! { - /// Generate an arbitrary bundle with fake authorization data. This bundle does not - /// necessarily respect consensus rules; for that use - /// [`crate::builder::testing::arb_bundle`] - pub fn arb_bundle(n_actions: usize) - ( - flags in arb_flags(), - ) - ( - acts in vec(arb_action_n(n_actions, flags), n_actions), - anchor in arb_base().prop_map(Anchor::from), - sk in arb_binding_signing_key(), - rng_seed in prop::array::uniform32(prop::num::u8::ANY), - fake_proof in vec(prop::num::u8::ANY, 1973), - fake_sighash in prop::array::uniform32(prop::num::u8::ANY), - flags in Just(flags), - burn in vec(arb_asset_to_burn(), 1usize..10) - ) -> Bundle { - let (balances, actions): (Vec, Vec>) = acts.into_iter().unzip(); - let rng = StdRng::from_seed(rng_seed); - - Bundle::from_parts( - NonEmpty::from_vec(actions).unwrap(), - flags, - balances.into_iter().sum::>().unwrap(), - burn, - anchor, - Authorized { - proof: Proof::new(fake_proof), - binding_signature: sk.sign(rng, &fake_sighash), - }, + prop_compose! { + /// Generate an arbitrary bundle with fake authorization data. This bundle does not + /// necessarily respect consensus rules; for that use + /// [`crate::builder::testing::arb_bundle`] + pub fn arb_bundle(n_actions: usize) + ( + flags in Self::arb_flags(), ) + ( + acts in vec(Self::arb_action_n(n_actions, flags), n_actions), + anchor in Self::arb_base().prop_map(Anchor::from), + sk in arb_binding_signing_key(), + rng_seed in prop::array::uniform32(prop::num::u8::ANY), + fake_proof in vec(prop::num::u8::ANY, 1973), + fake_sighash in prop::array::uniform32(prop::num::u8::ANY), + flags in Just(flags), + burn in vec(Self::arb_asset_to_burn(), 1usize..10) + ) -> Bundle { + let (balances, actions): (Vec, Vec, >) = acts.into_iter().unzip(); + let rng = StdRng::from_seed(rng_seed); + + Bundle::from_parts( + NonEmpty::from_vec(actions).unwrap(), + flags, + balances.into_iter().sum::>().unwrap(), + burn, + anchor, + Authorized { + proof: Proof::new(fake_proof), + binding_signature: sk.sign(rng, &fake_sighash), + }, + ) + } } } } diff --git a/src/bundle/batch.rs b/src/bundle/batch.rs index 6626b9162..cc9811c18 100644 --- a/src/bundle/batch.rs +++ b/src/bundle/batch.rs @@ -4,8 +4,10 @@ use rand::{CryptoRng, RngCore}; use tracing::debug; use super::{Authorized, Bundle}; + use crate::{ circuit::VerifyingKey, + orchard_flavor::OrchardFlavor, primitives::redpallas::{self, Binding, SpendAuth}, }; @@ -35,9 +37,9 @@ impl BatchValidator { } /// Adds the proof and RedPallas signatures from the given bundle to the validator. - pub fn add_bundle>( + pub fn add_bundle, FL: OrchardFlavor>( &mut self, - bundle: &Bundle, + bundle: &Bundle, sighash: [u8; 32], ) { for action in bundle.actions().iter() { diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index f67b6b75a..953c9d474 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -2,14 +2,23 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; -use crate::bundle::{Authorization, Authorized, Bundle}; -use crate::issuance::{IssueAuth, IssueBundle, Signed}; +use zcash_note_encryption_zsa::MEMO_SIZE; + +use crate::{ + bundle::{Authorization, Authorized, Bundle}, + issuance::{IssueAuth, IssueBundle, Signed}, + note::AssetBase, + note_encryption::OrchardDomainCommon, + orchard_flavor::{OrchardVanilla, OrchardZSA}, + value::NoteValue, +}; const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActCHash"; const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; +const ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcBurnHash"; const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdSAIssueHash"; const ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION: &[u8; 16] = b"ZTxIdIssuActHash"; const ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION: &[u8; 16] = b"ZTxIdIAcNoteHash"; @@ -19,6 +28,27 @@ fn hasher(personal: &[u8; 16]) -> State { Params::new().hash_length(32).personal(personal).to_state() } +/// Manages the hashing of ZSA burn-related data in transactions. +pub trait OrchardHash { + /// Incorporates the hash of burn items into the main transaction hash. + fn update_hash_with_burn(main_hasher: &mut State, burn_items: &[(AssetBase, NoteValue)]); +} + +impl OrchardHash for OrchardVanilla { + fn update_hash_with_burn(_main_hasher: &mut State, _burn_items: &[(AssetBase, NoteValue)]) {} +} + +impl OrchardHash for OrchardZSA { + fn update_hash_with_burn(main_hasher: &mut State, burn_items: &[(AssetBase, NoteValue)]) { + let mut burn_hasher = hasher(ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION); + for burn_item in burn_items { + burn_hasher.update(&burn_item.0.to_bytes()); + burn_hasher.update(&burn_item.1.to_bytes()); + } + main_hasher.update(burn_hasher.finalize().as_bytes()); + } +} + /// Write disjoint parts of each Orchard shielded action as 3 separate hashes: /// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized /// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION @@ -29,11 +59,18 @@ fn hasher(personal: &[u8; 16]) -> State { /// as defined in [ZIP-244: Transaction Identifier Non-Malleability][zip244] /// /// Then, hash these together along with (flags, value_balance_orchard, anchor_orchard), -/// personalized with ZCASH_ORCHARD_ACTIONS_HASH_PERSONALIZATION +/// and potentially the burn fields, if it is an OrchardZSA action. +/// +/// The final hash is personalized with ZCASH_ORCHARD_HASH_PERSONALIZATION. /// /// [zip244]: https://zips.z.cash/zip-0244 -pub(crate) fn hash_bundle_txid_data>( - bundle: &Bundle, +/// [zip226]: https://zips.z.cash/zip-0226 (for ZSA burn field hashing) +pub(crate) fn hash_bundle_txid_data< + A: Authorization, + V: Copy + Into, + D: OrchardDomainCommon + OrchardHash, +>( + bundle: &Bundle, ) -> Blake2bHash { let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); let mut ch = hasher(ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION); @@ -44,19 +81,27 @@ pub(crate) fn hash_bundle_txid_data>( ch.update(&action.nullifier().to_bytes()); ch.update(&action.cmx().to_bytes()); ch.update(&action.encrypted_note().epk_bytes); - ch.update(&action.encrypted_note().enc_ciphertext[..84]); // TODO: make sure it is backward compatible with Orchard [..52] + ch.update(&action.encrypted_note().enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE]); - mh.update(&action.encrypted_note().enc_ciphertext[84..596]); + mh.update( + &action.encrypted_note().enc_ciphertext.as_ref() + [D::COMPACT_NOTE_SIZE..D::COMPACT_NOTE_SIZE + MEMO_SIZE], + ); nh.update(&action.cv_net().to_bytes()); nh.update(&<[u8; 32]>::from(action.rk())); - nh.update(&action.encrypted_note().enc_ciphertext[596..]); + nh.update( + &action.encrypted_note().enc_ciphertext.as_ref()[D::COMPACT_NOTE_SIZE + MEMO_SIZE..], + ); nh.update(&action.encrypted_note().out_ciphertext); } h.update(ch.finalize().as_bytes()); h.update(mh.finalize().as_bytes()); h.update(nh.finalize().as_bytes()); + + D::update_hash_with_burn(&mut h, &bundle.burn); + h.update(&[bundle.flags().to_byte()]); h.update(&(*bundle.value_balance()).into().to_le_bytes()); h.update(&bundle.anchor().to_bytes()); @@ -76,7 +121,9 @@ pub fn hash_bundle_txid_empty() -> Blake2bHash { /// Identifier Non-Malleability][zip244] /// /// [zip244]: https://zips.z.cash/zip-0244 -pub(crate) fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash { +pub(crate) fn hash_bundle_auth_data( + bundle: &Bundle, +) -> Blake2bHash { let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); h.update(bundle.authorization().proof().as_ref()); for action in bundle.actions().iter() { @@ -101,7 +148,7 @@ pub fn hash_bundle_auth_empty() -> Blake2bHash { /// /// [zip227]: https://qed-it.github.io/zips/zip-0227 pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { - hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() + hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION).finalize() } /// Construct the commitment for an absent issue bundle as defined in @@ -116,9 +163,9 @@ pub fn hash_issue_bundle_txid_empty() -> Blake2bHash { pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) -> Blake2bHash { let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION); let mut ia = hasher(ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION); - let mut ind = hasher(ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION); for action in bundle.actions().iter() { + let mut ind = hasher(ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION); for note in action.notes().iter() { ind.update(¬e.recipient().to_raw_address_bytes()); ind.update(¬e.value().to_bytes()); diff --git a/src/circuit.rs b/src/circuit.rs index bfa78dce9..e72d3e121 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -1,37 +1,24 @@ //! The Orchard Action circuit implementation. +//! +//! This module defines the common structures, traits and implementations for the +//! Orchard Action circuit, supporting both the standard ("Vanilla") and ZSA variations. use core::fmt; -use ff::Field; use group::{Curve, GroupEncoding}; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, - plonk::{ - self, Advice, BatchVerifier, Column, Constraints, Expression, Instance as InstanceColumn, - Selector, SingleVerifier, - }, - poly::Rotation, + plonk::{self, BatchVerifier, SingleVerifier}, transcript::{Blake2bRead, Blake2bWrite}, }; use memuse::DynamicUsage; use pasta_curves::{arithmetic::CurveAffine, pallas, vesta}; use rand::RngCore; -use self::{ - commit_ivk::{CommitIvkChip, CommitIvkConfig}, - gadget::{ - add_chip::{AddChip, AddConfig}, - assign_free_advice, assign_is_native_asset, assign_split_flag, - }, - note_commit::{NoteCommitChip, NoteCommitConfig}, -}; use crate::{ builder::SpendInfo, bundle::Flags, - constants::{ - OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - MERKLE_DEPTH_ORCHARD, - }, + constants::MERKLE_DEPTH_ORCHARD, keys::{ CommitIvkRandomness, DiversifiedTransmissionKey, NullifierDerivingKey, SpendValidatingKey, }, @@ -45,30 +32,13 @@ use crate::{ tree::{Anchor, MerkleHashOrchard}, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, }; -use halo2_gadgets::{ - ecc::{ - chip::{EccChip, EccConfig}, - FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar, - }, - poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, - sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - merkle::{ - chip::{MerkleChip, MerkleConfig}, - MerklePath, - }, - }, - utilities::{ - bool_check, - cond_swap::{CondSwapChip, CondSwapConfig}, - lookup_range_check::LookupRangeCheckConfig, - }, -}; -mod commit_ivk; -pub mod gadget; -mod note_commit; -mod value_commit_orchard; +mod circuit_vanilla; +mod circuit_zsa; + +pub(in crate::circuit) mod commit_ivk; +pub(in crate::circuit) mod gadget; +pub(in crate::circuit) mod orchard_sinsemilla_chip; /// Size of the Orchard circuit. const K: u32 = 11; @@ -85,30 +55,48 @@ const ENABLE_SPEND: usize = 7; const ENABLE_OUTPUT: usize = 8; const ENABLE_ZSA: usize = 9; -/// Configuration needed to use the Orchard Action circuit. -#[derive(Clone, Debug)] -pub struct Config { - primary: Column, - q_orchard: Selector, - advices: [Column; 10], - add_config: AddConfig, - ecc_config: EccConfig, - poseidon_config: PoseidonConfig, - merkle_config_1: MerkleConfig, - merkle_config_2: MerkleConfig, - sinsemilla_config_1: - SinsemillaConfig, - sinsemilla_config_2: - SinsemillaConfig, - commit_ivk_config: CommitIvkConfig, - old_note_commit_config: NoteCommitConfig, - new_note_commit_config: NoteCommitConfig, - cond_swap_config: CondSwapConfig, +/// The `OrchardCircuit` trait defines an interface for different implementations of the PLONK circuit +/// for the different Orchard protocol flavors (Vanilla and ZSA). It serves as a bridge between +/// plonk::Circuit interfaces and specific requirements of the Orchard protocol's variations. +pub trait OrchardCircuit: Sized + Default { + /// Substitution for Config type of plonk::Circuit trait + type Config: Clone; + + /// Wrapper for configure function of plonk::Circuit trait + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config; + + /// Wrapper for configure function of plonk::Circuit trait + fn synthesize( + circuit: &Circuit, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), plonk::Error>; +} + +impl plonk::Circuit for Circuit { + type Config = C::Config; + type FloorPlanner = floor_planner::V1; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { + C::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + layouter: impl Layouter, + ) -> Result<(), plonk::Error> { + C::synthesize(self, config, layouter) + } } /// The Orchard Action circuit. #[derive(Clone, Debug, Default)] -pub struct Circuit { +pub struct Circuit { pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, pub(crate) pos: Value, pub(crate) g_d_old: Value, @@ -131,9 +119,10 @@ pub struct Circuit { pub(crate) rcv: Value, pub(crate) asset: Value, pub(crate) split_flag: Value, + phantom: std::marker::PhantomData, } -impl Circuit { +impl Circuit { /// This constructor is public to enable creation of custom builders. /// If you are not creating a custom builder, use [`Builder`] to compose /// and authorize a transaction. @@ -154,7 +143,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Option { + ) -> Option> { (Rho::from_nf_old(spend.note.nullifier(&spend.fvk)) == output_note.rho()) .then(|| Self::from_action_context_unchecked(spend, output_note, alpha, rcv)) } @@ -164,7 +153,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Circuit { + ) -> Circuit { let sender_address = spend.note.recipient(); let rho_old = spend.note.rho(); let psi_old = spend.note.rseed().psi(&rho_old); @@ -200,779 +189,11 @@ impl Circuit { rcv: Value::known(rcv), asset: Value::known(spend.note.asset()), split_flag: Value::known(spend.split_flag), + phantom: std::marker::PhantomData, } } } -impl plonk::Circuit for Circuit { - type Config = Config; - type FloorPlanner = floor_planner::V1; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - // Advice columns used in the Orchard circuit. - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Constrain split_flag to be boolean - // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - // Constrain (v_old = 0 and is_native_asset = 1) or (calculated root = anchor) (https://p.z.cash/ZKS:action-merkle-path-validity?partial). - // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). - // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). - // Constrain is_native_asset to be boolean - // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset - // Constraint if split_flag = 0 then psi_old = psi_nf - // Constraint if split_flag = 1, then is_native_asset = 0 - // Constraint if enable_zsa = 0, then is_native_asset = 1 - let q_orchard = meta.selector(); - meta.create_gate("Orchard circuit checks", |meta| { - let q_orchard = meta.query_selector(q_orchard); - let v_old = meta.query_advice(advices[0], Rotation::cur()); - let v_new = meta.query_advice(advices[1], Rotation::cur()); - let magnitude = meta.query_advice(advices[2], Rotation::cur()); - let sign = meta.query_advice(advices[3], Rotation::cur()); - - let root = meta.query_advice(advices[4], Rotation::cur()); - let anchor = meta.query_advice(advices[5], Rotation::cur()); - - let enable_spends = meta.query_advice(advices[6], Rotation::cur()); - let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); - - let split_flag = meta.query_advice(advices[8], Rotation::cur()); - - let is_native_asset = meta.query_advice(advices[9], Rotation::cur()); - let asset_x = meta.query_advice(advices[0], Rotation::next()); - let asset_y = meta.query_advice(advices[1], Rotation::next()); - let diff_asset_x_inv = meta.query_advice(advices[2], Rotation::next()); - let diff_asset_y_inv = meta.query_advice(advices[3], Rotation::next()); - - let one = Expression::Constant(pallas::Base::one()); - - let native_asset = AssetBase::native() - .cv_base() - .to_affine() - .coordinates() - .unwrap(); - - let diff_asset_x = asset_x - Expression::Constant(*native_asset.x()); - let diff_asset_y = asset_y - Expression::Constant(*native_asset.y()); - - let psi_old = meta.query_advice(advices[4], Rotation::next()); - let psi_nf = meta.query_advice(advices[5], Rotation::next()); - - let enable_zsa = meta.query_advice(advices[6], Rotation::next()); - - Constraints::with_selector( - q_orchard, - [ - ("bool_check split_flag", bool_check(split_flag.clone())), - ( - "v_old * (1 - split_flag) - v_new = magnitude * sign", - v_old.clone() * (one.clone() - split_flag.clone()) - - v_new.clone() - - magnitude * sign, - ), - // We already checked that - // * is_native_asset is boolean (just below), and - // * v_old is a 64 bit unsigned integer (in the note commitment evaluation). - // So, 1 - is_native_asset + v_old = 0 only when (is_native_asset = 1 and v_old = 0), no overflow can occur. - ( - "(v_old = 0 and is_native_asset = 1) or (root = anchor)", - (v_old.clone() + one.clone() - is_native_asset.clone()) * (root - anchor), - ), - ( - "v_old = 0 or enable_spends = 1", - v_old * (one.clone() - enable_spends), - ), - ( - "v_new = 0 or enable_outputs = 1", - v_new * (one.clone() - enable_outputs), - ), - ( - "bool_check is_native_asset", - bool_check(is_native_asset.clone()), - ), - ( - "(is_native_asset = 1) => (asset_x = native_asset_x)", - is_native_asset.clone() * diff_asset_x.clone(), - ), - ( - "(is_native_asset = 1) => (asset_y = native_asset_y)", - is_native_asset.clone() * diff_asset_y.clone(), - ), - // To prove that `asset` is not equal to `native_asset`, we will prove that at - // least one of `x(asset) - x(native_asset)` or `y(asset) - y(native_asset)` is - // not equal to zero. - // To prove that `x(asset) - x(native_asset)` (resp `y(asset) - y(native_asset)`) - // is not equal to zero, we will prove that it is invertible. - ( - "(is_native_asset = 0) => (asset != native_asset)", - (one.clone() - is_native_asset.clone()) - * (diff_asset_x * diff_asset_x_inv - one.clone()) - * (diff_asset_y * diff_asset_y_inv - one.clone()), - ), - ( - "(split_flag = 0) => (psi_old = psi_nf)", - (one.clone() - split_flag.clone()) * (psi_old - psi_nf), - ), - ( - "(split_flag = 1) => (is_native_asset = 0)", - split_flag * is_native_asset.clone(), - ), - ( - "(enable_zsa = 0) => (is_native_asset = 1)", - (one.clone() - enable_zsa) * (one - is_native_asset), - ), - ], - ) - }); - - // Addition of two field elements. - let add_config = AddChip::configure(meta, advices[7], advices[8], advices[6]); - - // Fixed columns for the Sinsemilla generator lookup table - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - table_range_check_tag, - ); - - // Instance column used for public inputs - let primary = meta.instance_column(); - meta.enable_equality(primary); - - // Permutation over all advice columns. - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - // Poseidon requires four advice columns, while ECC incomplete addition requires - // six, so we could choose to configure them in parallel. However, we only use a - // single Poseidon invocation, and we have the rows to accommodate it serially. - // Instead, we reduce the proof size by sharing fixed columns between the ECC and - // Poseidon chips. - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); - let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); - - // Also use the first Lagrange coefficient column for loading global constants. - // It's free real estate :) - meta.enable_constant(lagrange_coeffs[0]); - - // We have a lot of free space in the right-most advice columns; use one of them - // for all of our range checks. - let range_check = - LookupRangeCheckConfig::configure(meta, advices[9], table_idx, table_range_check_tag); - - // Configuration for curve point operations. - // This uses 10 advice columns and spans the whole circuit. - let ecc_config = - EccChip::::configure(meta, advices, lagrange_coeffs, range_check); - - // Configuration for the Poseidon hash. - let poseidon_config = PoseidonChip::configure::( - meta, - // We place the state columns after the partial_sbox column so that the - // pad-and-add region can be laid out more efficiently. - advices[6..9].try_into().unwrap(), - advices[5], - rc_a, - rc_b, - ); - - // Configuration for a Sinsemilla hash instantiation and a - // Merkle hash instantiation using this Sinsemilla instance. - // Since the Sinsemilla config uses only 5 advice columns, - // we can fit two instances side-by-side. - let (sinsemilla_config_1, merkle_config_1) = { - let sinsemilla_config_1 = SinsemillaChip::configure( - meta, - advices[..5].try_into().unwrap(), - advices[6], - lagrange_coeffs[0], - lookup, - range_check, - ); - let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); - - (sinsemilla_config_1, merkle_config_1) - }; - - // Configuration for a Sinsemilla hash instantiation and a - // Merkle hash instantiation using this Sinsemilla instance. - // Since the Sinsemilla config uses only 5 advice columns, - // we can fit two instances side-by-side. - let (sinsemilla_config_2, merkle_config_2) = { - let sinsemilla_config_2 = SinsemillaChip::configure( - meta, - advices[5..].try_into().unwrap(), - advices[7], - lagrange_coeffs[1], - lookup, - range_check, - ); - let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); - - (sinsemilla_config_2, merkle_config_2) - }; - - // Configuration to handle decomposition and canonicity checking - // for CommitIvk. - let commit_ivk_config = CommitIvkChip::configure(meta, advices); - - // Configuration to handle decomposition and canonicity checking - // for NoteCommit_old. - let old_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone()); - - // Configuration to handle decomposition and canonicity checking - // for NoteCommit_new. - let new_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); - - let cond_swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - Config { - primary, - q_orchard, - advices, - add_config, - ecc_config, - poseidon_config, - merkle_config_1, - merkle_config_2, - sinsemilla_config_1, - sinsemilla_config_2, - commit_ivk_config, - old_note_commit_config, - new_note_commit_config, - cond_swap_config, - } - } - - #[allow(non_snake_case)] - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), plonk::Error> { - // Load the Sinsemilla generator lookup table used by the whole circuit. - SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?; - - // Construct the ECC chip. - let ecc_chip = config.ecc_chip(); - - // Witness private inputs that are used across multiple checks. - let (psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset) = { - // Witness psi_nf - let psi_nf = assign_free_advice( - layouter.namespace(|| "witness psi_nf"), - config.advices[0], - self.psi_nf, - )?; - - // Witness psi_old - let psi_old = assign_free_advice( - layouter.namespace(|| "witness psi_old"), - config.advices[0], - self.psi_old, - )?; - - // Witness rho_old - let rho_old = assign_free_advice( - layouter.namespace(|| "witness rho_old"), - config.advices[0], - self.rho_old.map(|rho| rho.into_inner()), - )?; - - // Witness cm_old - let cm_old = Point::new( - ecc_chip.clone(), - layouter.namespace(|| "cm_old"), - self.cm_old.as_ref().map(|cm| cm.inner().to_affine()), - )?; - - // Witness g_d_old - let g_d_old = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "gd_old"), - self.g_d_old.as_ref().map(|gd| gd.to_affine()), - )?; - - // Witness ak_P. - let ak_P: Value = self.ak.as_ref().map(|ak| ak.into()); - let ak_P = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness ak_P"), - ak_P.map(|ak_P| ak_P.to_affine()), - )?; - - // Witness nk. - let nk = assign_free_advice( - layouter.namespace(|| "witness nk"), - config.advices[0], - self.nk.map(|nk| nk.inner()), - )?; - - // Witness v_old. - let v_old = assign_free_advice( - layouter.namespace(|| "witness v_old"), - config.advices[0], - self.v_old, - )?; - - // Witness v_new. - let v_new = assign_free_advice( - layouter.namespace(|| "witness v_new"), - config.advices[0], - self.v_new, - )?; - - // Witness asset - let asset = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness asset"), - self.asset.map(|asset| asset.cv_base().to_affine()), - )?; - - ( - psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, - ) - }; - - // Witness split_flag - let split_flag = assign_split_flag( - layouter.namespace(|| "witness split_flag"), - config.advices[0], - self.split_flag, - )?; - - // Witness is_native_asset which is equal to - // 1 if asset is equal to native asset, and - // 0 if asset is not equal to native asset. - let is_native_asset = assign_is_native_asset( - layouter.namespace(|| "witness is_native_asset"), - config.advices[0], - self.asset, - )?; - - // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). - let root = { - let path = self - .path - .map(|typed_path| typed_path.map(|node| node.inner())); - let merkle_inputs = MerklePath::construct( - [config.merkle_chip_1(), config.merkle_chip_2()], - OrchardHashDomains::MerkleCrh, - self.pos, - path, - ); - let leaf = cm_old.extract_p().inner().clone(); - merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? - }; - - // Value commitment integrity (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - let v_net_magnitude_sign = { - // Witness the magnitude and sign of v_net = v_old - v_new - let v_net_magnitude_sign = { - // v_net is equal to - // (-v_new) if split_flag = true - // v_old - v_new if split_flag = false - let v_net = self.split_flag.and_then(|split_flag| { - if split_flag { - Value::known(crate::value::NoteValue::zero()) - self.v_new - } else { - self.v_old - self.v_new - } - }); - - let magnitude_sign = v_net.map(|v_net| { - let (magnitude, sign) = v_net.magnitude_sign(); - - ( - // magnitude is guaranteed to be an unsigned 64-bit value. - // Therefore, we can move it into the base field. - pallas::Base::from(magnitude), - match sign { - crate::value::Sign::Positive => pallas::Base::one(), - crate::value::Sign::Negative => -pallas::Base::one(), - }, - ) - }); - - let magnitude = assign_free_advice( - layouter.namespace(|| "v_net magnitude"), - config.advices[9], - magnitude_sign.map(|m_s| m_s.0), - )?; - let sign = assign_free_advice( - layouter.namespace(|| "v_net sign"), - config.advices[9], - magnitude_sign.map(|m_s| m_s.1), - )?; - (magnitude, sign) - }; - - let rcv = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rcv"), - self.rcv.as_ref().map(|rcv| rcv.inner()), - )?; - - let cv_net = gadget::value_commit_orchard( - layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"), - config.sinsemilla_chip_1(), - ecc_chip.clone(), - v_net_magnitude_sign.clone(), - rcv, - asset.clone(), - )?; - - // Constrain cv_net to equal public input - layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, CV_NET_X)?; - layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, CV_NET_Y)?; - - // Return the magnitude and sign so we can use them in the Orchard gate. - v_net_magnitude_sign - }; - - // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). - let nf_old = { - let nf_old = gadget::derive_nullifier( - layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), - config.poseidon_chip(), - config.add_chip(), - ecc_chip.clone(), - config.cond_swap_chip(), - rho_old.clone(), - &psi_nf, - &cm_old, - nk.clone(), - split_flag.clone(), - )?; - - // Constrain nf_old to equal public input - layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; - - nf_old - }; - - // Spend authority (https://p.z.cash/ZKS:action-spend-authority) - { - let alpha = - ScalarFixed::new(ecc_chip.clone(), layouter.namespace(|| "alpha"), self.alpha)?; - - // alpha_commitment = [alpha] SpendAuthG - let (alpha_commitment, _) = { - let spend_auth_g = OrchardFixedBasesFull::SpendAuthG; - let spend_auth_g = FixedPoint::from_inner(ecc_chip.clone(), spend_auth_g); - spend_auth_g.mul(layouter.namespace(|| "[alpha] SpendAuthG"), alpha)? - }; - - // [alpha] SpendAuthG + ak_P - let rk = alpha_commitment.add(layouter.namespace(|| "rk"), &ak_P)?; - - // Constrain rk to equal public input - layouter.constrain_instance(rk.inner().x().cell(), config.primary, RK_X)?; - layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; - } - - // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). - let pk_d_old = { - let ivk = { - let ak = ak_P.extract_p().inner().clone(); - let rivk = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rivk"), - self.rivk.map(|rivk| rivk.inner()), - )?; - - gadget::commit_ivk( - config.sinsemilla_chip_1(), - ecc_chip.clone(), - config.commit_ivk_chip(), - layouter.namespace(|| "CommitIvk"), - ak, - nk, - rivk, - )? - }; - let ivk = - ScalarVar::from_base(ecc_chip.clone(), layouter.namespace(|| "ivk"), ivk.inner())?; - - // [ivk] g_d_old - // The scalar value is passed through and discarded. - let (derived_pk_d_old, _ivk) = - g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; - - // Constrain derived pk_d_old to equal witnessed pk_d_old - // - // This equality constraint is technically superfluous, because the assigned - // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see - // an explicit connection between circuit-synthesized values, and explicit - // prover witnesses. We could get the best of both worlds with a write-on-copy - // abstraction (https://github.com/zcash/halo2/issues/334). - let pk_d_old = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness pk_d_old"), - self.pk_d_old.map(|pk_d_old| pk_d_old.inner().to_affine()), - )?; - derived_pk_d_old - .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; - - pk_d_old - }; - - // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). - { - let rcm_old = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rcm_old"), - self.rcm_old.as_ref().map(|rcm_old| rcm_old.inner()), - )?; - - // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let derived_cm_old = gadget::note_commit( - layouter.namespace(|| { - "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" - }), - config.sinsemilla_chip_1(), - config.ecc_chip(), - config.note_commit_chip_old(), - config.cond_swap_chip(), - g_d_old.inner(), - pk_d_old.inner(), - v_old.clone(), - rho_old, - psi_old.clone(), - asset.inner(), - rcm_old, - is_native_asset.clone(), - )?; - - // Constrain derived cm_old to equal witnessed cm_old - derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; - } - - // New note commitment integrity (https://p.z.cash/ZKS:action-cmx-new-integrity?partial). - { - // Witness g_d_new - let g_d_new = { - let g_d_new = self.g_d_new.map(|g_d_new| g_d_new.to_affine()); - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness g_d_new_star"), - g_d_new, - )? - }; - - // Witness pk_d_new - let pk_d_new = { - let pk_d_new = self.pk_d_new.map(|pk_d_new| pk_d_new.inner().to_affine()); - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness pk_d_new"), - pk_d_new, - )? - }; - - // ρ^new = nf^old - let rho_new = nf_old.inner().clone(); - - // Witness psi_new - let psi_new = assign_free_advice( - layouter.namespace(|| "witness psi_new"), - config.advices[0], - self.psi_new, - )?; - - let rcm_new = ScalarFixed::new( - ecc_chip, - layouter.namespace(|| "rcm_new"), - self.rcm_new.as_ref().map(|rcm_new| rcm_new.inner()), - )?; - - // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let cm_new = gadget::note_commit( - layouter.namespace(|| { - "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" - }), - config.sinsemilla_chip_2(), - config.ecc_chip(), - config.note_commit_chip_new(), - config.cond_swap_chip(), - g_d_new.inner(), - pk_d_new.inner(), - v_new.clone(), - rho_new, - psi_new, - asset.inner(), - rcm_new, - is_native_asset.clone(), - )?; - - let cmx = cm_new.extract_p(); - - // Constrain cmx to equal public input - layouter.constrain_instance(cmx.inner().cell(), config.primary, CMX)?; - } - - // Constrain the remaining Orchard circuit checks. - layouter.assign_region( - || "Orchard circuit checks", - |mut region| { - v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; - v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; - v_net_magnitude_sign.0.copy_advice( - || "v_net magnitude", - &mut region, - config.advices[2], - 0, - )?; - v_net_magnitude_sign.1.copy_advice( - || "v_net sign", - &mut region, - config.advices[3], - 0, - )?; - - root.copy_advice(|| "calculated root", &mut region, config.advices[4], 0)?; - region.assign_advice_from_instance( - || "pub input anchor", - config.primary, - ANCHOR, - config.advices[5], - 0, - )?; - - region.assign_advice_from_instance( - || "enable spends", - config.primary, - ENABLE_SPEND, - config.advices[6], - 0, - )?; - - region.assign_advice_from_instance( - || "enable outputs", - config.primary, - ENABLE_OUTPUT, - config.advices[7], - 0, - )?; - - split_flag.copy_advice(|| "split_flag", &mut region, config.advices[8], 0)?; - - is_native_asset.copy_advice( - || "is_native_asset", - &mut region, - config.advices[9], - 0, - )?; - asset - .inner() - .x() - .copy_advice(|| "asset_x", &mut region, config.advices[0], 1)?; - asset - .inner() - .y() - .copy_advice(|| "asset_y", &mut region, config.advices[1], 1)?; - - // `diff_asset_x_inv` and `diff_asset_y_inv` will be used to prove that - // if is_native_asset = 0, then asset != native_asset. - region.assign_advice( - || "diff_asset_x_inv", - config.advices[2], - 1, - || { - self.asset.map(|asset| { - let asset_x = *asset.cv_base().to_affine().coordinates().unwrap().x(); - let native_asset_x = *AssetBase::native() - .cv_base() - .to_affine() - .coordinates() - .unwrap() - .x(); - - let diff_asset_x = asset_x - native_asset_x; - - if diff_asset_x == pallas::Base::zero() { - pallas::Base::zero() - } else { - diff_asset_x.invert().unwrap() - } - }) - }, - )?; - region.assign_advice( - || "diff_asset_y_inv", - config.advices[3], - 1, - || { - self.asset.map(|asset| { - let asset_y = *asset.cv_base().to_affine().coordinates().unwrap().y(); - let native_asset_y = *AssetBase::native() - .cv_base() - .to_affine() - .coordinates() - .unwrap() - .y(); - - let diff_asset_y = asset_y - native_asset_y; - - if diff_asset_y == pallas::Base::zero() { - pallas::Base::zero() - } else { - diff_asset_y.invert().unwrap() - } - }) - }, - )?; - - psi_old.copy_advice(|| "psi_old", &mut region, config.advices[4], 1)?; - psi_nf.copy_advice(|| "psi_nf", &mut region, config.advices[5], 1)?; - - region.assign_advice_from_instance( - || "enable zsa", - config.primary, - ENABLE_ZSA, - config.advices[6], - 1, - )?; - - config.q_orchard.enable(&mut region, 0) - }, - )?; - - Ok(()) - } -} - /// The verifying key for the Orchard Action circuit. #[derive(Debug)] pub struct VerifyingKey { @@ -982,9 +203,9 @@ pub struct VerifyingKey { impl VerifyingKey { /// Builds the verifying key. - pub fn build() -> Self { + pub fn build() -> Self { let params = halo2_proofs::poly::commitment::Params::new(K); - let circuit: Circuit = Default::default(); + let circuit: Circuit = Default::default(); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); @@ -1001,9 +222,9 @@ pub struct ProvingKey { impl ProvingKey { /// Builds the proving key. - pub fn build() -> Self { + pub fn build() -> Self { let params = halo2_proofs::poly::commitment::Params::new(K); - let circuit: Circuit = Default::default(); + let circuit: Circuit = Default::default(); let vk = plonk::keygen_vk(¶ms, &circuit).unwrap(); let pk = plonk::keygen_pk(¶ms, vk, &circuit).unwrap(); @@ -1115,9 +336,9 @@ impl DynamicUsage for Proof { impl Proof { /// Creates a proof for the given circuits and instances. - pub fn create( + pub fn create( pk: &ProvingKey, - circuits: &[Circuit], + circuits: &[Circuit], instances: &[Instance], mut rng: impl RngCore, ) -> Result { @@ -1179,566 +400,3 @@ impl Proof { Proof(bytes) } } - -#[cfg(test)] -mod tests { - use core::iter; - - use ff::Field; - use group::{Curve, Group, GroupEncoding}; - use halo2_proofs::{circuit::Value, dev::MockProver}; - use pasta_curves::pallas; - use rand::{rngs::OsRng, RngCore}; - - use super::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}; - use crate::builder::SpendInfo; - use crate::bundle::Flags; - use crate::note::commitment::NoteCommitTrapdoor; - use crate::note::{AssetBase, Nullifier}; - use crate::primitives::redpallas::VerificationKey; - use crate::{ - keys::{FullViewingKey, Scope, SpendValidatingKey, SpendingKey}, - note::{Note, NoteCommitment, Rho}, - tree::MerklePath, - value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, - }; - - fn generate_dummy_circuit_instance(mut rng: R) -> (Circuit, Instance) { - let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); - - let sender_address = spent_note.recipient(); - let nk = *fvk.nk(); - let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); - let nf_old = spent_note.nullifier(&fvk); - let ak: SpendValidatingKey = fvk.into(); - let alpha = pallas::Scalar::random(&mut rng); - let rk = ak.randomize(&alpha); - - let (_, _, output_note) = Note::dummy( - &mut rng, - Some(Rho::from_nf_old(nf_old)), - AssetBase::native(), - ); - let cmx = output_note.commitment().into(); - - let value = spent_note.value() - output_note.value(); - let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); - - let path = MerklePath::dummy(&mut rng); - let anchor = path.root(spent_note.commitment().into()); - - let psi_old = spent_note.rseed().psi(&spent_note.rho()); - - ( - Circuit { - path: Value::known(path.auth_path()), - pos: Value::known(path.position()), - g_d_old: Value::known(sender_address.g_d()), - pk_d_old: Value::known(*sender_address.pk_d()), - v_old: Value::known(spent_note.value()), - rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(psi_old), - rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Value::known(spent_note.commitment()), - // For non split note, psi_nf is equal to psi_old - psi_nf: Value::known(psi_old), - alpha: Value::known(alpha), - ak: Value::known(ak), - nk: Value::known(nk), - rivk: Value::known(rivk), - g_d_new: Value::known(output_note.recipient().g_d()), - pk_d_new: Value::known(*output_note.recipient().pk_d()), - v_new: Value::known(output_note.value()), - psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), - rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - rcv: Value::known(rcv), - asset: Value::known(spent_note.asset()), - split_flag: Value::known(false), - }, - Instance { - anchor, - cv_net, - nf_old, - rk, - cmx, - enable_spend: true, - enable_output: true, - enable_zsa: false, - }, - ) - } - - // TODO: recast as a proptest - #[test] - fn round_trip() { - let mut rng = OsRng; - - let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) - .map(|()| generate_dummy_circuit_instance(&mut rng)) - .unzip(); - - let vk = VerifyingKey::build(); - - // Test that the pinned verification key (representing the circuit) - // is as expected. - { - // panic!("{:#?}", vk.vk.pinned()); - assert_eq!( - format!("{:#?}\n", vk.vk.pinned()), - include_str!("circuit_description").replace("\r\n", "\n") - ); - } - - // Test that the proof size is as expected. - let expected_proof_size = { - let circuit_cost = - halo2_proofs::dev::CircuitCost::::measure( - K, - &circuits[0], - ); - assert_eq!(usize::from(circuit_cost.proof_size(1)), 5120); - assert_eq!(usize::from(circuit_cost.proof_size(2)), 7392); - usize::from(circuit_cost.proof_size(instances.len())) - }; - - for (circuit, instance) in circuits.iter().zip(instances.iter()) { - assert_eq!( - MockProver::run( - K, - circuit, - instance - .to_halo2_instance() - .iter() - .map(|p| p.to_vec()) - .collect() - ) - .unwrap() - .verify(), - Ok(()) - ); - } - - let pk = ProvingKey::build(); - let proof = Proof::create(&pk, &circuits, &instances, &mut rng).unwrap(); - assert!(proof.verify(&vk, &instances).is_ok()); - assert_eq!(proof.0.len(), expected_proof_size); - } - - #[test] - fn serialized_proof_test_case() { - use std::fs; - use std::io::{Read, Write}; - - let vk = VerifyingKey::build(); - - fn write_test_case( - mut w: W, - instance: &Instance, - proof: &Proof, - ) -> std::io::Result<()> { - w.write_all(&instance.anchor.to_bytes())?; - w.write_all(&instance.cv_net.to_bytes())?; - w.write_all(&instance.nf_old.to_bytes())?; - w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; - w.write_all(&instance.cmx.to_bytes())?; - w.write_all(&[ - u8::from(instance.enable_spend), - u8::from(instance.enable_output), - u8::from(instance.enable_zsa), - ])?; - - w.write_all(proof.as_ref())?; - Ok(()) - } - - fn read_test_case(mut r: R) -> std::io::Result<(Instance, Proof)> { - let read_32_bytes = |r: &mut R| { - let mut ret = [0u8; 32]; - r.read_exact(&mut ret).unwrap(); - ret - }; - let read_bool = |r: &mut R| { - let mut byte = [0u8; 1]; - r.read_exact(&mut byte).unwrap(); - match byte { - [0] => false, - [1] => true, - _ => panic!("Unexpected non-boolean byte"), - } - }; - - let anchor = crate::Anchor::from_bytes(read_32_bytes(&mut r)).unwrap(); - let cv_net = ValueCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); - let nf_old = crate::note::Nullifier::from_bytes(&read_32_bytes(&mut r)).unwrap(); - let rk = read_32_bytes(&mut r).try_into().unwrap(); - let cmx = - crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); - let enable_spend = read_bool(&mut r); - let enable_output = read_bool(&mut r); - let enable_zsa = read_bool(&mut r); - let instance = Instance::from_parts( - anchor, - cv_net, - nf_old, - rk, - cmx, - Flags::from_parts(enable_spend, enable_output, enable_zsa), - ); - - let mut proof_bytes = vec![]; - r.read_to_end(&mut proof_bytes)?; - let proof = Proof::new(proof_bytes); - - Ok((instance, proof)) - } - - if std::env::var_os("ORCHARD_CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { - let create_proof = || -> std::io::Result<()> { - let mut rng = OsRng; - - let (circuit, instance) = generate_dummy_circuit_instance(OsRng); - let instances = &[instance.clone()]; - - let pk = ProvingKey::build(); - let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); - assert!(proof.verify(&vk, instances).is_ok()); - - let file = std::fs::File::create("src/circuit_proof_test_case.bin")?; - write_test_case(file, &instance, &proof) - }; - create_proof().expect("should be able to write new proof"); - } - - // Parse the hardcoded proof test case. - let (instance, proof) = { - let test_case_bytes = fs::read("src/circuit_proof_test_case.bin").unwrap(); - read_test_case(&test_case_bytes[..]).expect("proof must be valid") - }; - assert_eq!(proof.0.len(), 5120); - - assert!(proof.verify(&vk, &[instance]).is_ok()); - } - - #[cfg(feature = "dev-graph")] - #[test] - fn print_action_circuit() { - use plotters::prelude::*; - - let root = BitMapBackend::new("action-circuit-layout.png", (1024, 768)).into_drawing_area(); - root.fill(&WHITE).unwrap(); - let root = root - .titled("Orchard Action Circuit", ("sans-serif", 60)) - .unwrap(); - - let circuit = Circuit { - path: Value::unknown(), - pos: Value::unknown(), - g_d_old: Value::unknown(), - pk_d_old: Value::unknown(), - v_old: Value::unknown(), - rho_old: Value::unknown(), - psi_old: Value::unknown(), - rcm_old: Value::unknown(), - cm_old: Value::unknown(), - psi_nf: Value::unknown(), - alpha: Value::unknown(), - ak: Value::unknown(), - nk: Value::unknown(), - rivk: Value::unknown(), - g_d_new: Value::unknown(), - pk_d_new: Value::unknown(), - v_new: Value::unknown(), - psi_new: Value::unknown(), - rcm_new: Value::unknown(), - rcv: Value::unknown(), - asset: Value::unknown(), - split_flag: Value::unknown(), - }; - halo2_proofs::dev::CircuitLayout::default() - .show_labels(false) - .view_height(0..(1 << 11)) - .render(K, &circuit, &root) - .unwrap(); - } - - fn check_proof_of_orchard_circuit(circuit: &Circuit, instance: &Instance, should_pass: bool) { - let proof_verify = MockProver::run( - K, - circuit, - instance - .to_halo2_instance() - .iter() - .map(|p| p.to_vec()) - .collect(), - ) - .unwrap() - .verify(); - if should_pass { - assert!(proof_verify.is_ok()); - } else { - assert!(proof_verify.is_err()); - } - } - - fn generate_circuit_instance( - is_native_asset: bool, - split_flag: bool, - mut rng: R, - ) -> (Circuit, Instance) { - // Create asset - let asset_base = if is_native_asset { - AssetBase::native() - } else { - AssetBase::random() - }; - - // Create spent_note - let (spent_note_fvk, spent_note) = { - let sk = SpendingKey::random(&mut rng); - let fvk: FullViewingKey = (&sk).into(); - let sender_address = fvk.address_at(0u32, Scope::External); - let rho_old = Rho::from_nf_old(Nullifier::dummy(&mut rng)); - let note = Note::new( - sender_address, - NoteValue::from_raw(40), - asset_base, - rho_old, - &mut rng, - ); - let spent_note = if split_flag { - note.create_split_note(&mut rng) - } else { - note - }; - (fvk, spent_note) - }; - - let output_value = NoteValue::from_raw(10); - - let (scope, v_net) = if split_flag { - ( - Scope::External, - // Split notes do not contribute to v_net. - // Therefore, if split_flag is true, v_net = - output_value - NoteValue::zero() - output_value, - ) - } else { - ( - spent_note_fvk - .scope_for_address(&spent_note.recipient()) - .unwrap(), - spent_note.value() - output_value, - ) - }; - - let nf_old = spent_note.nullifier(&spent_note_fvk); - let ak: SpendValidatingKey = spent_note_fvk.clone().into(); - let alpha = pallas::Scalar::random(&mut rng); - let rk = ak.randomize(&alpha); - - let output_note = { - let sk = SpendingKey::random(&mut rng); - let fvk: FullViewingKey = (&sk).into(); - let sender_address = fvk.address_at(0u32, Scope::External); - - Note::new( - sender_address, - output_value, - asset_base, - Rho::from_nf_old(nf_old), - &mut rng, - ) - }; - - let cmx = output_note.commitment().into(); - - let rcv = ValueCommitTrapdoor::random(&mut rng); - let cv_net = ValueCommitment::derive(v_net, rcv, asset_base); - - let path = MerklePath::dummy(&mut rng); - let anchor = path.root(spent_note.commitment().into()); - - let spend_info = SpendInfo { - dummy_sk: None, - fvk: spent_note_fvk, - scope, - note: spent_note, - merkle_path: path, - split_flag, - }; - - ( - Circuit::from_action_context_unchecked(spend_info, output_note, alpha, rcv), - Instance { - anchor, - cv_net, - nf_old, - rk, - cmx, - enable_spend: true, - enable_output: true, - enable_zsa: true, - }, - ) - } - - fn random_note_commitment(mut rng: impl RngCore) -> NoteCommitment { - NoteCommitment::derive( - pallas::Point::random(&mut rng).to_affine().to_bytes(), - pallas::Point::random(&mut rng).to_affine().to_bytes(), - NoteValue::from_raw(rng.next_u64()), - AssetBase::random(), - pallas::Base::random(&mut rng), - pallas::Base::random(&mut rng), - NoteCommitTrapdoor(pallas::Scalar::random(&mut rng)), - ) - .unwrap() - } - - #[test] - fn orchard_circuit_negative_test() { - let mut rng = OsRng; - - for is_native_asset in [true, false] { - for split_flag in [true, false] { - let (circuit, instance) = - generate_circuit_instance(is_native_asset, split_flag, &mut rng); - - let should_pass = !(matches!((is_native_asset, split_flag), (true, true))); - - check_proof_of_orchard_circuit(&circuit, &instance, should_pass); - - // Set cv_net to be zero - // The proof should fail - let instance_wrong_cv_net = Instance { - anchor: instance.anchor, - cv_net: ValueCommitment::from_bytes(&[0u8; 32]).unwrap(), - nf_old: instance.nf_old, - rk: instance.rk.clone(), - cmx: instance.cmx, - enable_spend: instance.enable_spend, - enable_output: instance.enable_output, - enable_zsa: instance.enable_zsa, - }; - check_proof_of_orchard_circuit(&circuit, &instance_wrong_cv_net, false); - - // Set rk_pub to be a dummy VerificationKey - // The proof should fail - let instance_wrong_rk = Instance { - anchor: instance.anchor, - cv_net: instance.cv_net.clone(), - nf_old: instance.nf_old, - rk: VerificationKey::dummy(), - cmx: instance.cmx, - enable_spend: instance.enable_spend, - enable_output: instance.enable_output, - enable_zsa: instance.enable_zsa, - }; - check_proof_of_orchard_circuit(&circuit, &instance_wrong_rk, false); - - // Set cm_old to be a random NoteCommitment - // The proof should fail - let circuit_wrong_cm_old = Circuit { - path: circuit.path, - pos: circuit.pos, - g_d_old: circuit.g_d_old, - pk_d_old: circuit.pk_d_old, - v_old: circuit.v_old, - rho_old: circuit.rho_old, - psi_old: circuit.psi_old, - rcm_old: circuit.rcm_old.clone(), - cm_old: Value::known(random_note_commitment(&mut rng)), - psi_nf: circuit.psi_nf, - alpha: circuit.alpha, - ak: circuit.ak.clone(), - nk: circuit.nk, - rivk: circuit.rivk, - g_d_new: circuit.g_d_new, - pk_d_new: circuit.pk_d_new, - v_new: circuit.v_new, - psi_new: circuit.psi_new, - rcm_new: circuit.rcm_new.clone(), - rcv: circuit.rcv, - asset: circuit.asset, - split_flag: circuit.split_flag, - }; - check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); - - // Set cmx_pub to be a random NoteCommitment - // The proof should fail - let instance_wrong_cmx_pub = Instance { - anchor: instance.anchor, - cv_net: instance.cv_net.clone(), - nf_old: instance.nf_old, - rk: instance.rk.clone(), - cmx: random_note_commitment(&mut rng).into(), - enable_spend: instance.enable_spend, - enable_output: instance.enable_output, - enable_zsa: instance.enable_zsa, - }; - check_proof_of_orchard_circuit(&circuit, &instance_wrong_cmx_pub, false); - - // Set nf_old_pub to be a random Nullifier - // The proof should fail - let instance_wrong_nf_old_pub = Instance { - anchor: instance.anchor, - cv_net: instance.cv_net.clone(), - nf_old: Nullifier::dummy(&mut rng), - rk: instance.rk.clone(), - cmx: instance.cmx, - enable_spend: instance.enable_spend, - enable_output: instance.enable_output, - enable_zsa: instance.enable_zsa, - }; - check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); - - // If split_flag = 0 , set psi_nf to be a random Pallas base element - // The proof should fail - if !split_flag { - let circuit_wrong_psi_nf = Circuit { - path: circuit.path, - pos: circuit.pos, - g_d_old: circuit.g_d_old, - pk_d_old: circuit.pk_d_old, - v_old: circuit.v_old, - rho_old: circuit.rho_old, - psi_old: circuit.psi_old, - rcm_old: circuit.rcm_old.clone(), - cm_old: circuit.cm_old.clone(), - psi_nf: Value::known(pallas::Base::random(&mut rng)), - alpha: circuit.alpha, - ak: circuit.ak.clone(), - nk: circuit.nk, - rivk: circuit.rivk, - g_d_new: circuit.g_d_new, - pk_d_new: circuit.pk_d_new, - v_new: circuit.v_new, - psi_new: circuit.psi_new, - rcm_new: circuit.rcm_new.clone(), - rcv: circuit.rcv, - asset: circuit.asset, - split_flag: circuit.split_flag, - }; - check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false); - } - - // If asset is not equal to the native asset, set enable_zsa = 0 - // The proof should fail - if !is_native_asset { - let instance_wrong_enable_zsa = Instance { - anchor: instance.anchor, - cv_net: instance.cv_net.clone(), - nf_old: instance.nf_old, - rk: instance.rk.clone(), - cmx: instance.cmx, - enable_spend: instance.enable_spend, - enable_output: instance.enable_output, - enable_zsa: false, - }; - check_proof_of_orchard_circuit(&circuit, &instance_wrong_enable_zsa, false); - } - } - } - } -} diff --git a/src/circuit/circuit_description_vanilla b/src/circuit/circuit_description_vanilla new file mode 100644 index 000000000..8bb3759ed --- /dev/null +++ b/src/circuit/circuit_description_vanilla @@ -0,0 +1,28140 @@ +PinnedVerificationKey { + base_modulus: "0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001", + scalar_modulus: "0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001", + domain: PinnedEvaluationDomain { + k: 11, + extended_k: 14, + omega: 0x181b50ad5f32119e31cbd395426d600b7a9b88bcaaa1c24eef28545aada17813, + }, + cs: PinnedConstraintSystem { + num_fixed_columns: 29, + num_advice_columns: 10, + num_instance_columns: 1, + num_selectors: 56, + gates: [ + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Sum( + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 19, + column_index: 19, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 18, + column_index: 18, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Product( + Sum( + Scaled( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Product( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 11, + column_index: 9, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 21, + column_index: 1, + rotation: Rotation( + -1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Product( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc0994a8dd8c46eb2100000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000010000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 20, + column_index: 20, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Product( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + ), + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 0, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 3, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Sum( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + Fixed { + query_index: 9, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 22, + column_index: 22, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000000, + ), + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Fixed { + query_index: 0, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 3, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Fixed { + query_index: 9, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Fixed { + query_index: 2, + column_index: 11, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Product( + Product( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + ), + ), + ), + Product( + Fixed { + query_index: 23, + column_index: 23, + rotation: Rotation( + 0, + ), + }, + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Negated( + Product( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Constant( + 0x0000000000000000000000000000000001000000000000000000000000000000, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000008, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Negated( + Scaled( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + 0x1000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x233162630ebf9ed7f8e24f66822c2d9f3a0a464048bd770ad049cdc8d085167c, + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, + ), + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, + ), + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 21, + column_index: 21, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2e29dd59c64b1037f333aa91c383346421680eabc56bc15dfee7a9944f84dbe4, + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, + ), + ), + Scaled( + Product( + Product( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 4, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Product( + Product( + Product( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0ab5e5b874a68de7b3d59fbdc8c9ead497d7a0ab23850b56323f2486d7e11b63, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x31916628e58a5abb293f0f0d886c7954240d4a7cbf7357368eca5596e996ab5e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x07c045d5f5e9e5a6d803952bbb364fdfa0a3b71a5fb1573519d1cf25d8e8345d, + ), + ), + Fixed { + query_index: 7, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Sum( + Sum( + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x2cc057f3fa14687acc59ffd00de864434543705f35e98ab5c6de463cd1404e6b, + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x32e7c439f2f967e55fd72b55df208385fadbf8ae7ae24796171840417cab7576, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x2eae5df8c3115969f461778abf6c91fa1403db6f50302040942645bd7d4464e0, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x233162630ebf9ed7f8e24f66822c2d9f3a0a464048bd770ad049cdc8d085167c, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x25cae2599892a8b0b36664548d60957d78f8365c85bbab07402270113e047a2e, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x22f5b5e1e6081c9774938717989a19579aad3d8262efd83ff84d806f685f747a, + ), + ), + Fixed { + query_index: 8, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x07bf368481067199db18b4aefe68d26d13f074fde9a18b29a1ca1516a4a1a6a0, + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x2aec6906c63f3cf1018a918b9dac5dadbb1d65040c85c1bfe82425bc1b23a059, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0952e0243aec2af01215944a64a246b276b2a7139db71b36e0541adf238e0781, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x2e29dd59c64b1037f333aa91c383346421680eabc56bc15dfee7a9944f84dbe4, + ), + Scaled( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 5, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + 0x1d1aab4ec1cd678892d15e7dceef1665cbeaf48b3a0624c3c771effa43263664, + ), + ), + Scaled( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 6, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + 0x3bf763086a18936451e0cbead65516b975872c39b59a31f615639415f6e85ef1, + ), + ), + Fixed { + query_index: 9, + column_index: 10, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x2fcbba6f9159a219723a63a0c09dab26aef9112e952fdbb52a418d8d73a7c908, + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x1ec7372574f3851bb4ddd4b4d6452256c5e4960d7424cd3776efab42d4fba90b, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0d0c2efd6472f12a3c26fa4b7d25b1e487a7435d30f8be81adc8933c6f3c72ee, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 20, + column_index: 6, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 23, + column_index: 7, + rotation: Rotation( + -1, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 24, + column_index: 8, + rotation: Rotation( + -1, + ), + }, + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Fixed { + query_index: 0, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 24, + column_index: 24, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Scaled( + Fixed { + query_index: 3, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Negated( + Sum( + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Product( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + Negated( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + ), + ), + Negated( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + ), + ), + Product( + Scaled( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Negated( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + 0x0001000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + 0x0020000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 16, + column_index: 0, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 13, + column_index: 3, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 17, + column_index: 1, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 14, + column_index: 4, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 25, + column_index: 25, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 26, + column_index: 26, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000100, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000400000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0200000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + ), + Scaled( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000040, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 27, + column_index: 27, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000020, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000100, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000400000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000010, + ), + ), + Constant( + 0x0000000000000000000000000000100000000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0200000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000200, + ), + ), + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000007, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + Scaled( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + ), + Scaled( + Advice { + query_index: 22, + column_index: 6, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Scaled( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + 0x0400000000000000000000000000000000000000000000000000000000000000, + ), + ), + Scaled( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + 0x4000000000000000000000000000000000000000000000000000000000000000, + ), + ), + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Sum( + Sum( + Advice { + query_index: 15, + column_index: 5, + rotation: Rotation( + 1, + ), + }, + Constant( + 0x0000000000000000000000000000000400000000000000000000000000000000, + ), + ), + Negated( + Constant( + 0x00000000000000000000000000000000224698fc094cf91b992d30ed00000001, + ), + ), + ), + Negated( + Advice { + query_index: 19, + column_index: 8, + rotation: Rotation( + 1, + ), + }, + ), + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + ), + Product( + Product( + Product( + Product( + Product( + Product( + Product( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000002, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000003, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000004, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000005, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000006, + ), + Negated( + Fixed { + query_index: 28, + column_index: 28, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + Product( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + ), + ), + ], + advice_queries: [ + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 9, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 2, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 3, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 4, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 5, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 0, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 1, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 6, + column_type: Advice, + }, + Rotation( + 1, + ), + ), + ( + Column { + index: 7, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ( + Column { + index: 8, + column_type: Advice, + }, + Rotation( + -1, + ), + ), + ], + instance_queries: [ + ( + Column { + index: 0, + column_type: Instance, + }, + Rotation( + 0, + ), + ), + ], + fixed_queries: [ + ( + Column { + index: 3, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 0, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 11, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 4, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 5, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 6, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 7, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 8, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 9, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 10, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 12, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 1, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 2, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 13, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 14, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 15, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 16, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 17, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 18, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 19, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 20, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 21, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 22, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 23, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 24, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 25, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 26, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 27, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ( + Column { + index: 28, + column_type: Fixed, + }, + Rotation( + 0, + ), + ), + ], + permutation: Argument { + columns: [ + Column { + index: 0, + column_type: Instance, + }, + Column { + index: 0, + column_type: Advice, + }, + Column { + index: 1, + column_type: Advice, + }, + Column { + index: 2, + column_type: Advice, + }, + Column { + index: 3, + column_type: Advice, + }, + Column { + index: 4, + column_type: Advice, + }, + Column { + index: 5, + column_type: Advice, + }, + Column { + index: 6, + column_type: Advice, + }, + Column { + index: 7, + column_type: Advice, + }, + Column { + index: 8, + column_type: Advice, + }, + Column { + index: 9, + column_type: Advice, + }, + Column { + index: 3, + column_type: Fixed, + }, + Column { + index: 8, + column_type: Fixed, + }, + Column { + index: 9, + column_type: Fixed, + }, + Column { + index: 10, + column_type: Fixed, + }, + ], + }, + lookups: [ + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 14, + column_index: 14, + rotation: Rotation( + 0, + ), + }, + Sum( + Product( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Advice { + query_index: 10, + column_index: 9, + rotation: Rotation( + 1, + ), + }, + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Product( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 15, + column_index: 15, + rotation: Rotation( + 0, + ), + }, + ), + ), + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 2, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 10, + column_index: 12, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 12, + column_index: 2, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 4, + column_index: 4, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 3, + column_index: 3, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 0, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 1, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 16, + column_index: 16, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 11, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 12, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ], + }, + Argument { + input_expressions: [ + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 7, + column_index: 7, + rotation: Rotation( + 0, + ), + }, + Negated( + Scaled( + Product( + Sum( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Product( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Sum( + Fixed { + query_index: 13, + column_index: 13, + rotation: Rotation( + 0, + ), + }, + Negated( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + ), + ), + ), + ), + ), + Advice { + query_index: 18, + column_index: 7, + rotation: Rotation( + 1, + ), + }, + ), + 0x0000000000000000000000000000000000000000000000000000000000000400, + ), + ), + ), + ), + Sum( + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x0db5218be6881f0f1431d4ea7d4afc7b29a05bafbede62b55a91eb912044ea5f, + ), + ), + Sum( + Product( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + Sum( + Scaled( + Product( + Sum( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 9, + column_index: 9, + rotation: Rotation( + 0, + ), + }, + ), + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Sum( + Sum( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + ), + Negated( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + ), + ), + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + 0x2000000000000000000000000000000011234c7e04a67c8dcc96987680000001, + ), + Negated( + Product( + Advice { + query_index: 8, + column_index: 8, + rotation: Rotation( + 0, + ), + }, + Sum( + Advice { + query_index: 5, + column_index: 5, + rotation: Rotation( + 0, + ), + }, + Negated( + Advice { + query_index: 6, + column_index: 6, + rotation: Rotation( + 0, + ), + }, + ), + ), + ), + ), + ), + ), + Scaled( + Sum( + Constant( + 0x0000000000000000000000000000000000000000000000000000000000000001, + ), + Negated( + Fixed { + query_index: 17, + column_index: 17, + rotation: Rotation( + 0, + ), + }, + ), + ), + 0x2f0f40c2f152a01c9caf66298493d5d0944a041c2e65ba0117c24f76bf8e6483, + ), + ), + ], + table_expressions: [ + Fixed { + query_index: 1, + column_index: 0, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 11, + column_index: 1, + rotation: Rotation( + 0, + ), + }, + Fixed { + query_index: 12, + column_index: 2, + rotation: Rotation( + 0, + ), + }, + ], + }, + ], + constants: [ + Column { + index: 3, + column_type: Fixed, + }, + ], + minimum_degree: None, + }, + fixed_commitments: [ + (0x05f5862cad2888855bc3c1843a9eff57b11b592d9eb0e13354256661387f5231, 0x32236b14df85bf5f532a930232cb23a5c56ef7d67aaeed8bcb8fc10ea132cbd6), + (0x3e727e8554679f98120355d39d958dbd8755d5a7f8b42ea87f258064c4b3eb57, 0x0c0d5c23f3ee62ac1b2d986dd3033bbcab260d590e1393de3a14a4b31ae091bb), + (0x3748680dd6a91c5dec668b30fb6bf9a450aeb884b81cbc344914f265760e7131, 0x18530eaa5c58b61bd3fc38220ea484c0922524a815a8f752be955c229f9c4164), + (0x18cd12d5f4e12bd7247a8fd7cc93ded7a8a9b60935b319b2db578a8fceef9559, 0x16b15af4fcfb9ed75533e7a4c1966cae5621f10dc1dfbba39a491ec37c911b5e), + (0x37e70146801841d95832259e4d8f39aeee8a364ea5007f82aa84a0e387231315, 0x20ef65833381c985722a95e65125a1123cab3357741168a5ed7e92e972dbd30d), + (0x12e3af8e507a2ca30e544568cf319701ecbc29dc5919f0198d541938edecc8f3, 0x3fb1bb2804faaa4c215e93694d5d1e6f87874cb8c34cb9206ff958de14e44275), + (0x334d99f316343f01c8eb67e327c76f743f8de7f957c893c6f30ccd87e5d1af3a, 0x1da64caf127c8eb513653791147a85ed1edcca12935c95b7d615a9377c9406d8), + (0x1430dca15080286939046d3cb9fb7ace4ed1da2fbe7a362e8f3575489bc6e3e1, 0x1ef5f4aff2902f3bc8acb2cc884a2d44334f910a68b2701f1c37943652b46d8f), + (0x02ebdeac7e91b3d15e4b7c0533e42678672ec384d51e51e22342be7edeeb8074, 0x03638952e0489de03ff03236433f5d2617cb4ddd0a72637ed31095deca85a2a6), + (0x31179b7f5b01ad2a55cf9a66f57b696e9b9cb4919cca426d469b270827f3018b, 0x2b231a9a71b674cc546ba9b36916a13411648903cfdcb808926fc47ee745586c), + (0x0673497660cec8a8c391cfb16f5ffdcb710f9e9e194a1a85935cf4bc45b01359, 0x15ce8801c51811f0256a43f762e497fe38c88866c09bb256289d93e0393dc225), + (0x098d2a0cfedae91fe29e21a01b5e43045b9cc8d9a334f1aee3e075f36a16e323, 0x0be47cc41643c9e6d95012428d5b46ae5a44e765392e05152a0181e30689d8b6), + (0x02adb7cbc9ebbbd87d7d6a41fc40cb4cf57585c6243aa204f757c9026ef20fd3, 0x327fc06fee179c6a57ed95336f9fb7854420d80dd191251a40935664ff6c8067), + (0x2d00d4ec8aa5e4b3d035131f559e4a97f896e8dbc39badb92b58a8d46b5e91df, 0x37046fb32ed8eb4ba0b4da8e1c9b56cd3832fa2ed4788f7faf4fee1f76a94c32), + (0x212f5afd70e787e2fd951e0ddc5430d1fa78f988c30740384d18cf9ff276b43b, 0x20c5a150e200caddf9a35a993668fc4742be5d924d1086f05c74ef6a78b5feb2), + (0x02c283cbde85f2ad26daddeabe01b1574ce7de68f0e329ec95a4154dd4713f29, 0x208cf96aa5255b543933ee3e9bdd054d4f15265a7c8921aaee89c192af2fd284), + (0x1f777f0e4263ec4a19f30813739c640335ffa951cc3cc586b6c4095e737f95be, 0x061c07fb12cb19582eefd858a08e689acd970c8cb9ed8f7b928d88e691a2f586), + (0x13d0bd76da4ace22c0e90b098d6073551322b8c734bf37eeca67fbf19687f550, 0x3d996cc9da5a31cefb453390b906eabbcc75797bc6a6b9c9e3af2fe7b6b8beed), + (0x04cad7405b492a30db0a710c842cecc97d02059acf4c02aa79626dce68ac4837, 0x3d6d7b6698b258e61ebe0b25d9cbcd4a016cb0a2ae8d92752532d98cfb27720d), + (0x1b6f5383c5a0ae5bf457e1c8e17a933e892464d33fef9e9262411e01c117d87e, 0x0c552b960e8ce365b5f2302bcc0b7ce5cdf964e6036602cfc859c8769184f619), + (0x3fa4b5cc33e30de3ac7342c84f47f4fffe7ae77dda1689c2f08050d0ab743cb1, 0x327663e39b128ec28c94486b1e5d4429000626f65230ed572c66f80406a42176), + (0x2184a7d65b5000cc5c5f178c2f4ab5b11a67fdc626771c29ade508020c8da032, 0x34c98ee1f6dfa6c1e8cd915d1efeb484206e13e5e32e13118925913568e620b7), + (0x0974ad1a3c0eb4c8d2c59cd820a82b7f28ea2f7a245008d403815131ff30879e, 0x00bb593cdf920cef4965f788d65eba3c3aa07d9718dfb62e3e385849a0d692a8), + (0x1e355d783cffccafc120f462461fb312773442762383ac444009653f3d8d4be6, 0x3c60e17b18492aa2c41798b409d2bcc1857ca57ee9d2fb0001584cedc8e141d6), + (0x0a6fe1cc1ce659681079768ca8ff94d82c7d51ef39cd99b738b144de3a3027f6, 0x30cfc2f4e0ec95f623199970d8b762647ad2d7c3591a20781ee8187702babe5f), + (0x00d87a2c430f1db50a63f18f8cf8807f4f70d3acb940d4130ba6811f8ba2d479, 0x13d5742320e1b2cecda6073b7f2bf5816b9067453deeaa829f356a65ef5621b2), + (0x3118979ade023f3977d034f86eed6506d7e0586ead81f80bc5ca01a7660ee0c9, 0x30f6731193d5c786cf61b05523c05e2664a066c2d39a685588f02883057320ad), + (0x0df51bd411d5f95da66fcc57f5e4d8dbcca3d82b08ceb61e9ff1befa074e08d3, 0x11c9092b6d02c46f173b0108854499ca4922afaf58e0734e77a6088715e84b64), + (0x24289014ede2672df8e8e32eb4e0d71709846041319fb85b1328cdb3b8764565, 0x0833de9c0b76ae816df0e41ae33daece27c63a41f2ba9abbbc7c08724211b50c), + ], + permutation: VerifyingKey { + commitments: [ + (0x2ad778f0e75a3dcad7c0cc2215e554f3d6fe41eabd612c487ea2708d59fb2e7e, 0x0561e9268230b53ec9cac0fd7654b3edaa3851f624c62bdae39519ae17526c06), + (0x358a21858e7f0da213959badd192b12e7bd40f6b18f5617a7fbad1f142b53c41, 0x1cc665c7a95332ea3ecb79bc35c4d672837809470691ad6a96f2eca081ca9c98), + (0x28d6468db328f1d201b3b7ca36f3affddee9dd0043d8868e34f1839742ac3190, 0x2f38eba3a82748cc28e46c1e20b7d343fdac7ef726ed6de89f6484c6070204f1), + (0x21f27b52cd9a76e1dbbf572fbfc0262007015777b68bda954f3c9db60ebb27f9, 0x0dbbf8f04e8476544a853e54093689d59935de9194eef24a0ee04d6faef9423f), + (0x0253a69e81add6bc1c2fe14bd90dab3e3c2603747dd3760c9dd1e341d96a79ed, 0x15cbe812a45a46512cc8ed493250f75a9dcaaee4be0d3bdaee8b43d74c50481f), + (0x19eb8760e7d0e6ae6d28d65627d958661cdde4e58a0aeb55a6b7017bcf723002, 0x064575794bf9bfdbc50e94b8afbbd2851ae4e12ff2809777d28fe71c235727d9), + (0x0e5c408b5224841cb4f75aec5cdb7bc95c150bbe858dbde8dbac9f72e5392462, 0x01030c69ac5fc7dd63e4e0bb1718d26f51b79dccc81e0b172e98c26e59145414), + (0x12437cb05ecff24131b52b5a55f6f143d8437c28c9d7c31eb06cfa093972a64b, 0x06e1a5e39566b4ce097a6c7dace6dcb827e54dac7d64fa79d994fb1557717614), + (0x34636ff9de412da15f41a8a006abbe8f43a5cffc94e6c3deb02f98af4fb2b8c7, 0x0270f0c3fa8cc7338f20fbcd5ec4e62799e051e0c5938d9e8c41581de8da6165), + (0x218e047b1c0a3b92c59539b3f6d9c23d34ebeeb65ca0be98f5e0e9642bdf1085, 0x20c1117f40b375688a94ff5c5c0b70004e43c7c7cd492fe8055fea081ea5ca78), + (0x2478c8226d4ede1c203fa7455b5fe28f99d5a0cb8ccdb5be4b54d5edcce974c4, 0x1ce69b76f05daeae57cd3d452370439237da89f2ddc84f7b2e35703acbf99655), + (0x08383138ecc6f2fb5459043c7666ae3df7802f1f02392af44db6ba25cd7d2c56, 0x20957d7a3f00a8589f627c5f5e471f45a84fbcbdcde00dfc97b9a97f3f723202), + (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), + (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), + (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), + ], + }, +} diff --git a/src/circuit_description b/src/circuit/circuit_description_zsa similarity index 100% rename from src/circuit_description rename to src/circuit/circuit_description_zsa diff --git a/src/circuit/circuit_proof_test_case_vanilla.bin b/src/circuit/circuit_proof_test_case_vanilla.bin new file mode 100644 index 0000000000000000000000000000000000000000..9dcabe5b67196ea961707b01496939b1c75770c7 GIT binary patch literal 5154 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, + q_orchard: Selector, + advices: [Column; 10], + add_config: AddConfig, + ecc_config: EccConfig, + poseidon_config: PoseidonConfig, + merkle_config_1: MerkleConfig, + merkle_config_2: MerkleConfig, + sinsemilla_config_1: + SinsemillaConfig, + sinsemilla_config_2: + SinsemillaConfig, + commit_ivk_config: CommitIvkConfig, + old_note_commit_config: NoteCommitConfig, + new_note_commit_config: NoteCommitConfig, +} + +impl OrchardCircuit for OrchardVanilla { + type Config = Config; + + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { + // Advice columns used in the Orchard circuit. + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Constrain v_old - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + // Either v_old = 0, or calculated root = anchor (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). + // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). + let q_orchard = meta.selector(); + meta.create_gate("Orchard circuit checks", |meta| { + let q_orchard = meta.query_selector(q_orchard); + let v_old = meta.query_advice(advices[0], Rotation::cur()); + let v_new = meta.query_advice(advices[1], Rotation::cur()); + let magnitude = meta.query_advice(advices[2], Rotation::cur()); + let sign = meta.query_advice(advices[3], Rotation::cur()); + + let root = meta.query_advice(advices[4], Rotation::cur()); + let anchor = meta.query_advice(advices[5], Rotation::cur()); + + let enable_spends = meta.query_advice(advices[6], Rotation::cur()); + let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); + + let one = Expression::Constant(pallas::Base::one()); + + Constraints::with_selector( + q_orchard, + [ + ( + "v_old - v_new = magnitude * sign", + v_old.clone() - v_new.clone() - magnitude * sign, + ), + ( + "Either v_old = 0, or root = anchor", + v_old.clone() * (root - anchor), + ), + ( + "v_old = 0 or enable_spends = 1", + v_old * (one.clone() - enable_spends), + ), + ( + "v_new = 0 or enable_outputs = 1", + v_new * (one - enable_outputs), + ), + ], + ) + }); + + // Addition of two field elements. + let add_config = AddChip::configure(meta, advices[7], advices[8], advices[6]); + + // Fixed columns for the Sinsemilla generator lookup table + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + // Permutation over all advice columns. + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Poseidon requires four advice columns, while ECC incomplete addition requires + // six, so we could choose to configure them in parallel. However, we only use a + // single Poseidon invocation, and we have the rows to accommodate it serially. + // Instead, we reduce the proof size by sharing fixed columns between the ECC and + // Poseidon chips. + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); + let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); + + // Also use the first Lagrange coefficient column for loading global constants. + // It's free real estate :) + meta.enable_constant(lagrange_coeffs[0]); + + // We have a lot of free space in the right-most advice columns; use one of them + // for all of our range checks. + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + + // Configuration for curve point operations. + // This uses 10 advice columns and spans the whole circuit. + let ecc_config = + EccChip::::configure(meta, advices, lagrange_coeffs, range_check); + + // Configuration for the Poseidon hash. + let poseidon_config = PoseidonChip::configure::( + meta, + // We place the state columns after the partial_sbox column so that the + // pad-and-add region can be laid out more efficiently. + advices[6..9].try_into().unwrap(), + advices[5], + rc_a, + rc_b, + ); + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_1, merkle_config_1) = { + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[6], + lagrange_coeffs[0], + lookup, + range_check, + false, + ); + let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); + + (sinsemilla_config_1, merkle_config_1) + }; + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_2, merkle_config_2) = { + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + lookup, + range_check, + false, + ); + let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); + + (sinsemilla_config_2, merkle_config_2) + }; + + // Configuration to handle decomposition and canonicity checking + // for CommitIvk. + let commit_ivk_config = CommitIvkChip::configure(meta, advices); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_old. + let old_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone()); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_new. + let new_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); + + Config { + primary, + q_orchard, + advices, + add_config, + ecc_config, + poseidon_config, + merkle_config_1, + merkle_config_2, + sinsemilla_config_1, + sinsemilla_config_2, + commit_ivk_config, + old_note_commit_config, + new_note_commit_config, + } + } + + #[allow(non_snake_case)] + fn synthesize( + circuit: &Circuit, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), plonk::Error> { + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?; + + // Construct the ECC chip. + let ecc_chip = config.ecc_chip(); + + // Witness private inputs that are used across multiple checks. + let (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) = { + // Witness psi_old + let psi_old = assign_free_advice( + layouter.namespace(|| "witness psi_old"), + config.advices[0], + circuit.psi_old, + )?; + + // Witness rho_old + let rho_old = assign_free_advice( + layouter.namespace(|| "witness rho_old"), + config.advices[0], + circuit.rho_old.map(|rho| rho.into_inner()), + )?; + + // Witness cm_old + let cm_old = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "cm_old"), + circuit.cm_old.as_ref().map(|cm| cm.inner().to_affine()), + )?; + + // Witness g_d_old + let g_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "gd_old"), + circuit.g_d_old.as_ref().map(|gd| gd.to_affine()), + )?; + + // Witness ak_P. + let ak_P: Value = circuit.ak.as_ref().map(|ak| ak.into()); + let ak_P = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness ak_P"), + ak_P.map(|ak_P| ak_P.to_affine()), + )?; + + // Witness nk. + let nk = assign_free_advice( + layouter.namespace(|| "witness nk"), + config.advices[0], + circuit.nk.map(|nk| nk.inner()), + )?; + + // Witness v_old. + let v_old = assign_free_advice( + layouter.namespace(|| "witness v_old"), + config.advices[0], + circuit.v_old, + )?; + + // Witness v_new. + let v_new = assign_free_advice( + layouter.namespace(|| "witness v_new"), + config.advices[0], + circuit.v_new, + )?; + + (psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new) + }; + + // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + let root = { + let path = circuit + .path + .map(|typed_path| typed_path.map(|node| node.inner())); + let merkle_inputs = MerklePath::construct( + [config.merkle_chip_1(), config.merkle_chip_2()], + OrchardHashDomains::MerkleCrh, + circuit.pos, + path, + ); + let leaf = cm_old.extract_p().inner().clone(); + merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? + }; + + // Value commitment integrity (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + let v_net_magnitude_sign = { + // Witness the magnitude and sign of v_net = v_old - v_new + let v_net_magnitude_sign = { + let v_net = circuit.v_old - circuit.v_new; + let magnitude_sign = v_net.map(|v_net| { + let (magnitude, sign) = v_net.magnitude_sign(); + + ( + // magnitude is guaranteed to be an unsigned 64-bit value. + // Therefore, we can move it into the base field. + pallas::Base::from(magnitude), + match sign { + crate::value::Sign::Positive => pallas::Base::one(), + crate::value::Sign::Negative => -pallas::Base::one(), + }, + ) + }); + + let magnitude = assign_free_advice( + layouter.namespace(|| "v_net magnitude"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.0), + )?; + let sign = assign_free_advice( + layouter.namespace(|| "v_net sign"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.1), + )?; + (magnitude, sign) + }; + + let v_net = ScalarFixedShort::new( + ecc_chip.clone(), + layouter.namespace(|| "v_net"), + v_net_magnitude_sign.clone(), + )?; + let rcv = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcv"), + circuit.rcv.as_ref().map(|rcv| rcv.inner()), + )?; + + let cv_net = gadget::value_commit_orchard( + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), + ecc_chip.clone(), + v_net, + rcv, + )?; + + // Constrain cv_net to equal public input + layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, CV_NET_X)?; + layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, CV_NET_Y)?; + + // Return the magnitude and sign so we can use them in the Orchard gate. + v_net_magnitude_sign + }; + + // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). + let nf_old = { + let nf_old = gadget::derive_nullifier( + layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old)"), + config.poseidon_chip(), + config.add_chip(), + ecc_chip.clone(), + rho_old.clone(), + &psi_old, + &cm_old, + nk.clone(), + )?; + + // Constrain nf_old to equal public input + layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; + + nf_old + }; + + // Spend authority (https://p.z.cash/ZKS:action-spend-authority) + { + let alpha = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "alpha"), + circuit.alpha, + )?; + + // alpha_commitment = [alpha] SpendAuthG + let (alpha_commitment, _) = { + let spend_auth_g = OrchardFixedBasesFull::SpendAuthG; + let spend_auth_g = FixedPoint::from_inner(ecc_chip.clone(), spend_auth_g); + spend_auth_g.mul(layouter.namespace(|| "[alpha] SpendAuthG"), alpha)? + }; + + // [alpha] SpendAuthG + ak_P + let rk = alpha_commitment.add(layouter.namespace(|| "rk"), &ak_P)?; + + // Constrain rk to equal public input + layouter.constrain_instance(rk.inner().x().cell(), config.primary, RK_X)?; + layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; + } + + // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). + let pk_d_old = { + let ivk = { + let ak = ak_P.extract_p().inner().clone(); + let rivk = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + circuit.rivk.map(|rivk| rivk.inner()), + )?; + + gadget::commit_ivk( + config.sinsemilla_chip_1(), + ecc_chip.clone(), + config.commit_ivk_chip(), + layouter.namespace(|| "CommitIvk"), + ak, + nk, + rivk, + )? + }; + let ivk = + ScalarVar::from_base(ecc_chip.clone(), layouter.namespace(|| "ivk"), ivk.inner())?; + + // [ivk] g_d_old + // The scalar value is passed through and discarded. + let (derived_pk_d_old, _ivk) = + g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; + + // Constrain derived pk_d_old to equal witnessed pk_d_old + // + // This equality constraint is technically superfluous, because the assigned + // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see + // an explicit connection between circuit-synthesized values, and explicit + // prover witnesses. We could get the best of both worlds with a write-on-copy + // abstraction (https://github.com/zcash/halo2/issues/334). + let pk_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_old"), + circuit + .pk_d_old + .map(|pk_d_old| pk_d_old.inner().to_affine()), + )?; + derived_pk_d_old + .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; + + pk_d_old + }; + + // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). + { + let rcm_old = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm_old"), + circuit.rcm_old.as_ref().map(|rcm_old| rcm_old.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let derived_cm_old = gadget::note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_1(), + config.ecc_chip(), + config.note_commit_chip_old(), + g_d_old.inner(), + pk_d_old.inner(), + v_old.clone(), + rho_old, + psi_old, + rcm_old, + )?; + + // Constrain derived cm_old to equal witnessed cm_old + derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; + } + + // New note commitment integrity (https://p.z.cash/ZKS:action-cmx-new-integrity?partial). + { + // Witness g_d_new + let g_d_new = { + let g_d_new = circuit.g_d_new.map(|g_d_new| g_d_new.to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d_new_star"), + g_d_new, + )? + }; + + // Witness pk_d_new + let pk_d_new = { + let pk_d_new = circuit + .pk_d_new + .map(|pk_d_new| pk_d_new.inner().to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_new"), + pk_d_new, + )? + }; + + // ρ^new = nf^old + let rho_new = nf_old.inner().clone(); + + // Witness psi_new + let psi_new = assign_free_advice( + layouter.namespace(|| "witness psi_new"), + config.advices[0], + circuit.psi_new, + )?; + + let rcm_new = ScalarFixed::new( + ecc_chip, + layouter.namespace(|| "rcm_new"), + circuit.rcm_new.as_ref().map(|rcm_new| rcm_new.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let cm_new = gadget::note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_2(), + config.ecc_chip(), + config.note_commit_chip_new(), + g_d_new.inner(), + pk_d_new.inner(), + v_new.clone(), + rho_new, + psi_new, + rcm_new, + )?; + + let cmx = cm_new.extract_p(); + + // Constrain cmx to equal public input + layouter.constrain_instance(cmx.inner().cell(), config.primary, CMX)?; + } + + // Constrain the remaining Orchard circuit checks. + layouter.assign_region( + || "Orchard circuit checks", + |mut region| { + v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; + v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; + v_net_magnitude_sign.0.copy_advice( + || "v_net magnitude", + &mut region, + config.advices[2], + 0, + )?; + v_net_magnitude_sign.1.copy_advice( + || "v_net sign", + &mut region, + config.advices[3], + 0, + )?; + + root.copy_advice(|| "calculated root", &mut region, config.advices[4], 0)?; + region.assign_advice_from_instance( + || "pub input anchor", + config.primary, + ANCHOR, + config.advices[5], + 0, + )?; + + region.assign_advice_from_instance( + || "enable spends", + config.primary, + ENABLE_SPEND, + config.advices[6], + 0, + )?; + + region.assign_advice_from_instance( + || "enable outputs", + config.primary, + ENABLE_OUTPUT, + config.advices[7], + 0, + )?; + + config.q_orchard.enable(&mut region, 0) + }, + )?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use core::iter; + + use ff::Field; + use halo2_proofs::{circuit::Value, dev::MockProver}; + use pasta_curves::pallas; + use rand::{rngs::OsRng, RngCore}; + + use crate::{ + bundle::Flags, + circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}, + keys::SpendValidatingKey, + note::{AssetBase, Note, Rho}, + orchard_flavor::OrchardVanilla, + tree::MerklePath, + value::{ValueCommitTrapdoor, ValueCommitment}, + }; + + type OrchardCircuitVanilla = Circuit; + + fn generate_circuit_instance(mut rng: R) -> (OrchardCircuitVanilla, Instance) { + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); + + let sender_address = spent_note.recipient(); + let nk = *fvk.nk(); + let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); + let nf_old = spent_note.nullifier(&fvk); + let rho = Rho::from_nf_old(nf_old); + let ak: SpendValidatingKey = fvk.into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let (_, _, output_note) = Note::dummy(&mut rng, Some(rho), AssetBase::native()); + let cmx = output_note.commitment().into(); + + let value = spent_note.value() - output_note.value(); + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let psi_old = spent_note.rseed().psi(&spent_note.rho()); + + ( + OrchardCircuitVanilla { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + phantom: std::marker::PhantomData, + }, + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + enable_zsa: false, + }, + ) + } + + // TODO: recast as a proptest + #[test] + fn round_trip() { + let mut rng = OsRng; + + let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) + .map(|()| generate_circuit_instance(&mut rng)) + .unzip(); + + let vk = VerifyingKey::build::(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + // panic!("{:#?}", vk.vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.vk.pinned()), + include_str!("circuit_description_vanilla").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + let expected_proof_size = { + let circuit_cost = + halo2_proofs::dev::CircuitCost::::measure( + K, + &circuits[0], + ); + println!("{:#?}", circuit_cost); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 4992); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7264); + usize::from(circuit_cost.proof_size(instances.len())) + }; + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + assert_eq!( + MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect() + ) + .unwrap() + .verify(), + Ok(()) + ); + } + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &circuits, &instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, &instances).is_ok()); + assert_eq!(proof.0.len(), expected_proof_size); + } + + #[test] + fn serialized_proof_test_case() { + use std::io::{Read, Write}; + + let vk = VerifyingKey::build::(); + + fn write_test_case( + mut w: W, + instance: &Instance, + proof: &Proof, + ) -> std::io::Result<()> { + w.write_all(&instance.anchor.to_bytes())?; + w.write_all(&instance.cv_net.to_bytes())?; + w.write_all(&instance.nf_old.to_bytes())?; + w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; + w.write_all(&instance.cmx.to_bytes())?; + w.write_all(&[ + u8::from(instance.enable_spend), + u8::from(instance.enable_output), + ])?; + + w.write_all(proof.as_ref())?; + Ok(()) + } + + fn read_test_case(mut r: R) -> std::io::Result<(Instance, Proof)> { + let read_32_bytes = |r: &mut R| { + let mut ret = [0u8; 32]; + r.read_exact(&mut ret).unwrap(); + ret + }; + let read_bool = |r: &mut R| { + let mut byte = [0u8; 1]; + r.read_exact(&mut byte).unwrap(); + match byte { + [0] => false, + [1] => true, + _ => panic!("Unexpected non-boolean byte"), + } + }; + + let anchor = crate::Anchor::from_bytes(read_32_bytes(&mut r)).unwrap(); + let cv_net = ValueCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let nf_old = crate::note::Nullifier::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let rk = read_32_bytes(&mut r).try_into().unwrap(); + let cmx = + crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let enable_spend = read_bool(&mut r); + let enable_output = read_bool(&mut r); + let enable_zsa = false; + let instance = Instance::from_parts( + anchor, + cv_net, + nf_old, + rk, + cmx, + Flags::from_parts(enable_spend, enable_output, enable_zsa), + ); + + let mut proof_bytes = vec![]; + r.read_to_end(&mut proof_bytes)?; + let proof = Proof::new(proof_bytes); + + Ok((instance, proof)) + } + + if std::env::var_os("ORCHARD_CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let mut rng = OsRng; + + let (circuit, instance) = generate_circuit_instance(OsRng); + let instances = &[instance.clone()]; + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, instances).is_ok()); + + let file = std::fs::File::create("circuit_proof_test_case.bin")?; + write_test_case(file, &instance, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let (instance, proof) = { + let test_case_bytes = include_bytes!("circuit_proof_test_case_vanilla.bin"); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + assert_eq!(proof.0.len(), 4992); + + assert!(proof.verify(&vk, &[instance]).is_ok()); + } + + #[cfg(feature = "dev-graph")] + #[test] + fn print_action_circuit() { + use plotters::prelude::*; + + let root = BitMapBackend::new("action-circuit-layout.png", (1024, 768)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root + .titled("Orchard Action Circuit", ("sans-serif", 60)) + .unwrap(); + + let circuit = OrchardCircuitVanilla { + path: Value::unknown(), + pos: Value::unknown(), + g_d_old: Value::unknown(), + pk_d_old: Value::unknown(), + v_old: Value::unknown(), + rho_old: Value::unknown(), + psi_old: Value::unknown(), + rcm_old: Value::unknown(), + cm_old: Value::unknown(), + psi_nf: Value::unknown(), + alpha: Value::unknown(), + ak: Value::unknown(), + nk: Value::unknown(), + rivk: Value::unknown(), + g_d_new: Value::unknown(), + pk_d_new: Value::unknown(), + v_new: Value::unknown(), + psi_new: Value::unknown(), + rcm_new: Value::unknown(), + rcv: Value::unknown(), + asset: Value::unknown(), + split_flag: Value::unknown(), + phantom: std::marker::PhantomData, + }; + halo2_proofs::dev::CircuitLayout::default() + .show_labels(false) + .view_height(0..(1 << 11)) + .render(K, &circuit, &root) + .unwrap(); + } +} diff --git a/src/circuit/circuit_vanilla/gadget.rs b/src/circuit/circuit_vanilla/gadget.rs new file mode 100644 index 000000000..5006f8083 --- /dev/null +++ b/src/circuit/circuit_vanilla/gadget.rs @@ -0,0 +1,190 @@ +//! Gadgets used in the Orchard circuit (Vanilla variation). + +use ff::Field; +use pasta_curves::pallas; + +use super::{add_chip, commit_ivk::CommitIvkChip, note_commit::NoteCommitChip, AddInstruction}; +use crate::constants::{ + NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, + ValueCommitV, +}; +use halo2_gadgets::{ + ecc::{ + chip::EccChip, EccInstructions, FixedPoint, FixedPointBaseField, FixedPointShort, Point, + ScalarFixed, ScalarFixedShort, X, + }, + poseidon::{ + primitives::{self as poseidon, ConstantLength}, + Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, + }, + sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, +}; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, Value}, + plonk::{self, Advice, Assigned, Column}, +}; + +impl super::Config { + pub(super) fn add_chip(&self) -> add_chip::AddChip { + add_chip::AddChip::construct(self.add_config.clone()) + } + + pub(super) fn commit_ivk_chip(&self) -> CommitIvkChip { + CommitIvkChip::construct(self.commit_ivk_config.clone()) + } + + pub(super) fn ecc_chip(&self) -> EccChip { + EccChip::construct(self.ecc_config.clone()) + } + + pub(super) fn sinsemilla_chip_1( + &self, + ) -> SinsemillaChip { + SinsemillaChip::construct(self.sinsemilla_config_1.clone()) + } + + pub(super) fn sinsemilla_chip_2( + &self, + ) -> SinsemillaChip { + SinsemillaChip::construct(self.sinsemilla_config_2.clone()) + } + + pub(super) fn merkle_chip_1( + &self, + ) -> MerkleChip { + MerkleChip::construct(self.merkle_config_1.clone()) + } + + pub(super) fn merkle_chip_2( + &self, + ) -> MerkleChip { + MerkleChip::construct(self.merkle_config_2.clone()) + } + + pub(super) fn poseidon_chip(&self) -> PoseidonChip { + PoseidonChip::construct(self.poseidon_config.clone()) + } + + pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { + NoteCommitChip::construct(self.new_note_commit_config.clone()) + } + + pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { + NoteCommitChip::construct(self.old_note_commit_config.clone()) + } +} + +/// Witnesses the given value in a standalone region. +/// +/// Usages of this helper are technically superfluous, as the single-cell region is only +/// ever used in equality constraints. We could eliminate them with a +/// [write-on-copy abstraction](https://github.com/zcash/halo2/issues/334). +pub(in crate::circuit) fn assign_free_advice( + mut layouter: impl Layouter, + column: Column, + value: Value, +) -> Result, plonk::Error> +where + for<'v> Assigned: From<&'v V>, +{ + layouter.assign_region( + || "load private", + |mut region| region.assign_advice(|| "load private", column, 0, || value), + ) +} + +/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. +/// +/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit +pub(in crate::circuit) fn value_commit_orchard< + EccChip: EccInstructions< + pallas::Affine, + FixedPoints = OrchardFixedBases, + Var = AssignedCell, + >, +>( + mut layouter: impl Layouter, + ecc_chip: EccChip, + v: ScalarFixedShort, + rcv: ScalarFixed, +) -> Result, plonk::Error> { + // commitment = [v] ValueCommitV + let (commitment, _) = { + let value_commit_v = ValueCommitV; + let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); + value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v)? + }; + + // blind = [rcv] ValueCommitR + let (blind, _rcv) = { + let value_commit_r = OrchardFixedBasesFull::ValueCommitR; + let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r); + + // [rcv] ValueCommitR + value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)? + }; + + // [v] ValueCommitV + [rcv] ValueCommitR + commitment.add(layouter.namespace(|| "cv"), &blind) +} + +/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. +/// +/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers +#[allow(clippy::too_many_arguments)] +pub(in crate::circuit) fn derive_nullifier< + PoseidonChip: PoseidonSpongeInstructions, 3, 2>, + AddChip: AddInstruction, + EccChip: EccInstructions< + pallas::Affine, + FixedPoints = OrchardFixedBases, + Var = AssignedCell, + >, +>( + mut layouter: impl Layouter, + poseidon_chip: PoseidonChip, + add_chip: AddChip, + ecc_chip: EccChip, + rho: AssignedCell, + psi: &AssignedCell, + cm: &Point, + nk: AssignedCell, +) -> Result, plonk::Error> { + // hash = poseidon_hash(nk, rho) + let hash = { + let poseidon_message = [nk, rho]; + let poseidon_hasher = + PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; + poseidon_hasher.hash( + layouter.namespace(|| "Poseidon hash (nk, rho)"), + poseidon_message, + )? + }; + + // Add hash output to psi. + // `scalar` = poseidon_hash(nk, rho) + psi. + let scalar = add_chip.add( + layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), + &hash, + psi, + )?; + + // Multiply scalar by NullifierK + // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. + // + let product = { + let nullifier_k = FixedPointBaseField::from_inner(ecc_chip, NullifierK); + nullifier_k.mul( + layouter.namespace(|| "[poseidon_output + psi] NullifierK"), + scalar, + )? + }; + + // Add cm to multiplied fixed base to get nf + // cm + [poseidon_output + psi] NullifierK + cm.add(layouter.namespace(|| "nf"), &product) + .map(|res| res.extract_p()) +} + +pub(in crate::circuit) use super::commit_ivk::gadgets::commit_ivk; +pub(in crate::circuit) use super::note_commit::gadgets::note_commit; diff --git a/src/circuit/circuit_vanilla/note_commit.rs b/src/circuit/circuit_vanilla/note_commit.rs new file mode 100644 index 000000000..986149e0f --- /dev/null +++ b/src/circuit/circuit_vanilla/note_commit.rs @@ -0,0 +1,2365 @@ +//! Note commitment logic for the Orchard circuit (Vanilla variation). + +use core::iter; + +use group::ff::PrimeField; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, Value}, + plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, + poly::Rotation, +}; +use pasta_curves::pallas; + +use crate::{ + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}, + value::NoteValue, +}; +use halo2_gadgets::{ + ecc::{ + chip::{EccChip, NonIdentityEccPoint}, + Point, ScalarFixed, + }, + sinsemilla::{ + chip::{SinsemillaChip, SinsemillaConfig}, + CommitDomain, Message, MessagePiece, + }, + utilities::{ + bool_check, + lookup_range_check::{LookupRangeCheck, PallasLookupRangeCheckConfig}, + FieldValue, RangeConstrained, + }, +}; + +type NoteCommitPiece = MessagePiece< + pallas::Affine, + SinsemillaChip, + 10, + 253, +>; + +/// The values of the running sum at the start and end of the range being used for a +/// canonicity check. +type CanonicityBounds = ( + AssignedCell, + AssignedCell, +); + +/* + + We need to hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi, + where + - g★_d is the representation of the point g_d, with 255 bits used for the + x-coordinate and 1 bit used for the y-coordinate; + - pk★_d is the representation of the point pk_d, with 255 bits used for the + x-coordinate and 1 bit used for the y-coordinate; + - v is a 64-bit value; + - rho is a base field element (255 bits); and + - psi is a base field element (255 bits). +*/ + +/// b = b_0 || b_1 || b_2 || b_3 +/// = (bits 250..=253 of x(g_d)) || (bit 254 of x(g_d)) || (ỹ bit of g_d) || (bits 0..=3 of pk★_d) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_b | +/// ------------------------------------ +/// | b | b_0 | b_1 | 1 | +/// | | b_2 | b_3 | 0 | +/// +/// +#[derive(Clone, Debug)] +struct DecomposeB { + q_notecommit_b: Selector, + col_l: Column, + col_m: Column, + col_r: Column, +} + +impl DecomposeB { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two_pow_4: pallas::Base, + two_pow_5: pallas::Base, + two_pow_6: pallas::Base, + ) -> Self { + let q_notecommit_b = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece b", |meta| { + let q_notecommit_b = meta.query_selector(q_notecommit_b); + + // b has been constrained to 10 bits by the Sinsemilla hash. + let b = meta.query_advice(col_l, Rotation::cur()); + // b_0 has been constrained to be 4 bits outside this gate. + let b_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains b_1 to be boolean. + let b_1 = meta.query_advice(col_r, Rotation::cur()); + // This gate constrains b_2 to be boolean. + let b_2 = meta.query_advice(col_m, Rotation::next()); + // b_3 has been constrained to 4 bits outside this gate. + let b_3 = meta.query_advice(col_r, Rotation::next()); + + // b = b_0 + (2^4) b_1 + (2^5) b_2 + (2^6) b_3 + let decomposition_check = + b - (b_0 + b_1.clone() * two_pow_4 + b_2.clone() * two_pow_5 + b_3 * two_pow_6); + + Constraints::with_selector( + q_notecommit_b, + [ + ("bool_check b_1", bool_check(b_1)), + ("bool_check b_2", bool_check(b_2)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_b, + col_l, + col_m, + col_r, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &PallasLookupRangeCheckConfig, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + g_d: &NonIdentityEccPoint, + pk_d: &NonIdentityEccPoint, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + let (gd_x, gd_y) = (g_d.x(), g_d.y()); + + // Constrain b_0 to be 4 bits + let b_0 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "b_0"), + gd_x.value(), + 250..254, + )?; + + // b_1, b_2 will be boolean-constrained in the gate. + let b_1 = RangeConstrained::bitrange_of(gd_x.value(), 254..255); + let b_2 = RangeConstrained::bitrange_of(gd_y.value(), 0..1); + + // Constrain b_3 to be 4 bits + let b_3 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "b_3"), + pk_d.x().value(), + 0..4, + )?; + + let b = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "b"), + [b_0.value(), b_1, b_2, b_3.value()], + )?; + + Ok((b, b_0, b_1, b_2, b_3)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + b: NoteCommitPiece, + b_0: RangeConstrained>, + b_1: RangeConstrained>, + b_2: RangeConstrained>, + b_3: RangeConstrained>, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece b", + |mut region| { + self.q_notecommit_b.enable(&mut region, 0)?; + + b.inner() + .cell_value() + .copy_advice(|| "b", &mut region, self.col_l, 0)?; + b_0.inner() + .copy_advice(|| "b_0", &mut region, self.col_m, 0)?; + let b_1 = region.assign_advice(|| "b_1", self.col_r, 0, || *b_1.inner())?; + + b_2.inner() + .copy_advice(|| "b_2", &mut region, self.col_m, 1)?; + b_3.inner() + .copy_advice(|| "b_3", &mut region, self.col_r, 1)?; + + Ok(b_1) + }, + ) + } +} + +/// d = d_0 || d_1 || d_2 || d_3 +/// = (bit 254 of x(pk_d)) || (ỹ bit of pk_d) || (bits 0..=7 of v) || (bits 8..=57 of v) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_d | +/// ------------------------------------ +/// | d | d_0 | d_1 | 1 | +/// | | d_2 | d_3 | 0 | +/// +/// +#[derive(Clone, Debug)] +struct DecomposeD { + q_notecommit_d: Selector, + col_l: Column, + col_m: Column, + col_r: Column, +} + +impl DecomposeD { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two: pallas::Base, + two_pow_2: pallas::Base, + two_pow_10: pallas::Base, + ) -> Self { + let q_notecommit_d = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece d", |meta| { + let q_notecommit_d = meta.query_selector(q_notecommit_d); + + // d has been constrained to 60 bits by the Sinsemilla hash. + let d = meta.query_advice(col_l, Rotation::cur()); + // This gate constrains d_0 to be boolean. + let d_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains d_1 to be boolean. + let d_1 = meta.query_advice(col_r, Rotation::cur()); + // d_2 has been constrained to 8 bits outside this gate. + let d_2 = meta.query_advice(col_m, Rotation::next()); + // d_3 is set to z1_d. + let d_3 = meta.query_advice(col_r, Rotation::next()); + + // d = d_0 + (2) d_1 + (2^2) d_2 + (2^10) d_3 + let decomposition_check = + d - (d_0.clone() + d_1.clone() * two + d_2 * two_pow_2 + d_3 * two_pow_10); + + Constraints::with_selector( + q_notecommit_d, + [ + ("bool_check d_0", bool_check(d_0)), + ("bool_check d_1", bool_check(d_1)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_d, + col_l, + col_m, + col_r, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &PallasLookupRangeCheckConfig, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + pk_d: &NonIdentityEccPoint, + value: &AssignedCell, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + let value_val = value.value().map(|v| pallas::Base::from(v.inner())); + + // d_0, d_1 will be boolean-constrained in the gate. + let d_0 = RangeConstrained::bitrange_of(pk_d.x().value(), 254..255); + let d_1 = RangeConstrained::bitrange_of(pk_d.y().value(), 0..1); + + // Constrain d_2 to be 8 bits + let d_2 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "d_2"), + value_val.as_ref(), + 0..8, + )?; + + // d_3 = z1_d from the SinsemillaHash(d) running sum output. + let d_3 = RangeConstrained::bitrange_of(value_val.as_ref(), 8..58); + + let d = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "d"), + [d_0, d_1, d_2.value(), d_3], + )?; + + Ok((d, d_0, d_1, d_2)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + d: NoteCommitPiece, + d_0: RangeConstrained>, + d_1: RangeConstrained>, + d_2: RangeConstrained>, + z1_d: AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece d", + |mut region| { + self.q_notecommit_d.enable(&mut region, 0)?; + + d.inner() + .cell_value() + .copy_advice(|| "d", &mut region, self.col_l, 0)?; + let d_0 = region.assign_advice(|| "d_0", self.col_m, 0, || *d_0.inner())?; + d_1.inner() + .copy_advice(|| "d_1", &mut region, self.col_r, 0)?; + + d_2.inner() + .copy_advice(|| "d_2", &mut region, self.col_m, 1)?; + z1_d.copy_advice(|| "d_3 = z1_d", &mut region, self.col_r, 1)?; + + Ok(d_0) + }, + ) + } +} + +/// e = e_0 || e_1 = (bits 58..=63 of v) || (bits 0..=3 of rho) +/// +/// | A_6 | A_7 | A_8 | q_notecommit_e | +/// ------------------------------------ +/// | e | e_0 | e_1 | 1 | +/// +/// +#[derive(Clone, Debug)] +struct DecomposeE { + q_notecommit_e: Selector, + col_l: Column, + col_m: Column, + col_r: Column, +} + +impl DecomposeE { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two_pow_6: pallas::Base, + ) -> Self { + let q_notecommit_e = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece e", |meta| { + let q_notecommit_e = meta.query_selector(q_notecommit_e); + + // e has been constrained to 10 bits by the Sinsemilla hash. + let e = meta.query_advice(col_l, Rotation::cur()); + // e_0 has been constrained to 6 bits outside this gate. + let e_0 = meta.query_advice(col_m, Rotation::cur()); + // e_1 has been constrained to 4 bits outside this gate. + let e_1 = meta.query_advice(col_r, Rotation::cur()); + + // e = e_0 + (2^6) e_1 + let decomposition_check = e - (e_0 + e_1 * two_pow_6); + + Constraints::with_selector(q_notecommit_e, Some(("decomposition", decomposition_check))) + }); + + Self { + q_notecommit_e, + col_l, + col_m, + col_r, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &PallasLookupRangeCheckConfig, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + value: &AssignedCell, + rho: &AssignedCell, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + let value_val = value.value().map(|v| pallas::Base::from(v.inner())); + + // Constrain e_0 to be 6 bits. + let e_0 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "e_0"), + value_val.as_ref(), + 58..64, + )?; + + // Constrain e_1 to be 4 bits. + let e_1 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "e_1"), + rho.value(), + 0..4, + )?; + + let e = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "e"), + [e_0.value(), e_1.value()], + )?; + + Ok((e, e_0, e_1)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + e: NoteCommitPiece, + e_0: RangeConstrained>, + e_1: RangeConstrained>, + ) -> Result<(), Error> { + layouter.assign_region( + || "NoteCommit MessagePiece e", + |mut region| { + self.q_notecommit_e.enable(&mut region, 0)?; + + e.inner() + .cell_value() + .copy_advice(|| "e", &mut region, self.col_l, 0)?; + e_0.inner() + .copy_advice(|| "e_0", &mut region, self.col_m, 0)?; + e_1.inner() + .copy_advice(|| "e_1", &mut region, self.col_r, 0)?; + + Ok(()) + }, + ) + } +} + +/// g = g_0 || g_1 || g_2 +/// = (bit 254 of rho) || (bits 0..=8 of psi) || (bits 9..=248 of psi) +/// +/// | A_6 | A_7 | q_notecommit_g | +/// ------------------------------ +/// | g | g_0 | 1 | +/// | g_1 | g_2 | 0 | +/// +/// +#[derive(Clone, Debug)] +struct DecomposeG { + q_notecommit_g: Selector, + col_l: Column, + col_m: Column, +} + +impl DecomposeG { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + two: pallas::Base, + two_pow_10: pallas::Base, + ) -> Self { + let q_notecommit_g = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece g", |meta| { + let q_notecommit_g = meta.query_selector(q_notecommit_g); + + // g has been constrained to 250 bits by the Sinsemilla hash. + let g = meta.query_advice(col_l, Rotation::cur()); + // This gate constrains g_0 to be boolean. + let g_0 = meta.query_advice(col_m, Rotation::cur()); + // g_1 has been constrained to 9 bits outside this gate. + let g_1 = meta.query_advice(col_l, Rotation::next()); + // g_2 is set to z1_g. + let g_2 = meta.query_advice(col_m, Rotation::next()); + + // g = g_0 + (2) g_1 + (2^10) g_2 + let decomposition_check = g - (g_0.clone() + g_1 * two + g_2 * two_pow_10); + + Constraints::with_selector( + q_notecommit_g, + [ + ("bool_check g_0", bool_check(g_0)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_g, + col_l, + col_m, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &PallasLookupRangeCheckConfig, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + rho: &AssignedCell, + psi: &AssignedCell, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + // g_0 will be boolean-constrained in the gate. + let g_0 = RangeConstrained::bitrange_of(rho.value(), 254..255); + + // Constrain g_1 to be 9 bits. + let g_1 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "g_1"), + psi.value(), + 0..9, + )?; + + // g_2 = z1_g from the SinsemillaHash(g) running sum output. + let g_2 = RangeConstrained::bitrange_of(psi.value(), 9..249); + + let g = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "g"), + [g_0, g_1.value(), g_2], + )?; + + Ok((g, g_0, g_1)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + g: NoteCommitPiece, + g_0: RangeConstrained>, + g_1: RangeConstrained>, + z1_g: AssignedCell, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece g", + |mut region| { + self.q_notecommit_g.enable(&mut region, 0)?; + + g.inner() + .cell_value() + .copy_advice(|| "g", &mut region, self.col_l, 0)?; + let g_0 = region.assign_advice(|| "g_0", self.col_m, 0, || *g_0.inner())?; + + g_1.inner() + .copy_advice(|| "g_1", &mut region, self.col_l, 1)?; + z1_g.copy_advice(|| "g_2 = z1_g", &mut region, self.col_m, 1)?; + + Ok(g_0) + }, + ) + } +} + +/// h = h_0 || h_1 || h_2 +/// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits +/// +/// | A_6 | A_7 | A_8 | q_notecommit_h | +/// ------------------------------------ +/// | h | h_0 | h_1 | 1 | +/// +/// +#[derive(Clone, Debug)] +struct DecomposeH { + q_notecommit_h: Selector, + col_l: Column, + col_m: Column, + col_r: Column, +} + +impl DecomposeH { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two_pow_5: pallas::Base, + ) -> Self { + let q_notecommit_h = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece h", |meta| { + let q_notecommit_h = meta.query_selector(q_notecommit_h); + + // h has been constrained to 10 bits by the Sinsemilla hash. + let h = meta.query_advice(col_l, Rotation::cur()); + // h_0 has been constrained to be 5 bits outside this gate. + let h_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains h_1 to be boolean. + let h_1 = meta.query_advice(col_r, Rotation::cur()); + + // h = h_0 + (2^5) h_1 + let decomposition_check = h - (h_0 + h_1.clone() * two_pow_5); + + Constraints::with_selector( + q_notecommit_h, + [ + ("bool_check h_1", bool_check(h_1)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_h, + col_l, + col_m, + col_r, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &PallasLookupRangeCheckConfig, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + psi: &AssignedCell, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + // Constrain h_0 to be 5 bits. + let h_0 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "h_0"), + psi.value(), + 249..254, + )?; + + // h_1 will be boolean-constrained in the gate. + let h_1 = RangeConstrained::bitrange_of(psi.value(), 254..255); + + let h = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "h"), + [ + h_0.value(), + h_1, + RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..4), + ], + )?; + + Ok((h, h_0, h_1)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + h: NoteCommitPiece, + h_0: RangeConstrained>, + h_1: RangeConstrained>, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece h", + |mut region| { + self.q_notecommit_h.enable(&mut region, 0)?; + + h.inner() + .cell_value() + .copy_advice(|| "h", &mut region, self.col_l, 0)?; + h_0.inner() + .copy_advice(|| "h_0", &mut region, self.col_m, 0)?; + let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?; + + Ok(h_1) + }, + ) + } +} + +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_g_d | +/// ----------------------------------------------------------- +/// | x(g_d) | b_0 | a | z13_a | 1 | +/// | | b_1 | a_prime | z13_a_prime | 0 | +/// +/// +#[derive(Clone, Debug)] +struct GdCanonicity { + q_notecommit_g_d: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, +} + +impl GdCanonicity { + #[allow(clippy::too_many_arguments)] + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, + two_pow_130: Expression, + two_pow_250: pallas::Base, + two_pow_254: pallas::Base, + t_p: Expression, + ) -> Self { + let q_notecommit_g_d = meta.selector(); + + meta.create_gate("NoteCommit input g_d", |meta| { + let q_notecommit_g_d = meta.query_selector(q_notecommit_g_d); + + let gd_x = meta.query_advice(col_l, Rotation::cur()); + + // b_0 has been constrained to be 4 bits outside this gate. + let b_0 = meta.query_advice(col_m, Rotation::cur()); + // b_1 has been constrained to be boolean outside this gate. + let b_1 = meta.query_advice(col_m, Rotation::next()); + + // a has been constrained to 250 bits by the Sinsemilla hash. + let a = meta.query_advice(col_r, Rotation::cur()); + let a_prime = meta.query_advice(col_r, Rotation::next()); + + let z13_a = meta.query_advice(col_z, Rotation::cur()); + let z13_a_prime = meta.query_advice(col_z, Rotation::next()); + + // x(g_d) = a + (2^250)b_0 + (2^254)b_1 + let decomposition_check = { + let sum = a.clone() + b_0.clone() * two_pow_250 + b_1.clone() * two_pow_254; + sum - gd_x + }; + + // a_prime = a + 2^130 - t_P + let a_prime_check = a + two_pow_130 - t_p - a_prime; + + // The gd_x_canonicity_checks are enforced if and only if `b_1` = 1. + // x(g_d) = a (250 bits) || b_0 (4 bits) || b_1 (1 bit) + let canonicity_checks = iter::empty() + .chain(Some(("b_1 = 1 => b_0", b_0))) + .chain(Some(("b_1 = 1 => z13_a", z13_a))) + .chain(Some(("b_1 = 1 => z13_a_prime", z13_a_prime))) + .map(move |(name, poly)| (name, b_1.clone() * poly)); + + Constraints::with_selector( + q_notecommit_g_d, + iter::empty() + .chain(Some(("decomposition", decomposition_check))) + .chain(Some(("a_prime_check", a_prime_check))) + .chain(canonicity_checks), + ) + }); + + Self { + q_notecommit_g_d, + col_l, + col_m, + col_r, + col_z, + } + } + + #[allow(clippy::too_many_arguments)] + fn assign( + &self, + layouter: &mut impl Layouter, + g_d: &NonIdentityEccPoint, + a: NoteCommitPiece, + b_0: RangeConstrained>, + b_1: AssignedCell, + a_prime: AssignedCell, + z13_a: AssignedCell, + z13_a_prime: AssignedCell, + ) -> Result<(), Error> { + layouter.assign_region( + || "NoteCommit input g_d", + |mut region| { + g_d.x().copy_advice(|| "gd_x", &mut region, self.col_l, 0)?; + + b_0.inner() + .copy_advice(|| "b_0", &mut region, self.col_m, 0)?; + b_1.copy_advice(|| "b_1", &mut region, self.col_m, 1)?; + + a.inner() + .cell_value() + .copy_advice(|| "a", &mut region, self.col_r, 0)?; + a_prime.copy_advice(|| "a_prime", &mut region, self.col_r, 1)?; + + z13_a.copy_advice(|| "z13_a", &mut region, self.col_z, 0)?; + z13_a_prime.copy_advice(|| "z13_a_prime", &mut region, self.col_z, 1)?; + + self.q_notecommit_g_d.enable(&mut region, 0) + }, + ) + } +} + +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d | +/// ------------------------------------------------------------------- +/// | x(pk_d) | b_3 | c | z13_c | 1 | +/// | | d_0 | b3_c_prime | z14_b3_c_prime | 0 | +/// +/// +#[derive(Clone, Debug)] +struct PkdCanonicity { + q_notecommit_pk_d: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, +} + +impl PkdCanonicity { + #[allow(clippy::too_many_arguments)] + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, + two_pow_4: pallas::Base, + two_pow_140: Expression, + two_pow_254: pallas::Base, + t_p: Expression, + ) -> Self { + let q_notecommit_pk_d = meta.selector(); + + meta.create_gate("NoteCommit input pk_d", |meta| { + let q_notecommit_pk_d = meta.query_selector(q_notecommit_pk_d); + + let pkd_x = meta.query_advice(col_l, Rotation::cur()); + + // `b_3` has been constrained to 4 bits outside this gate. + let b_3 = meta.query_advice(col_m, Rotation::cur()); + // d_0 has been constrained to be boolean outside this gate. + let d_0 = meta.query_advice(col_m, Rotation::next()); + + // `c` has been constrained to 250 bits by the Sinsemilla hash. + let c = meta.query_advice(col_r, Rotation::cur()); + let b3_c_prime = meta.query_advice(col_r, Rotation::next()); + + let z13_c = meta.query_advice(col_z, Rotation::cur()); + let z14_b3_c_prime = meta.query_advice(col_z, Rotation::next()); + + // x(pk_d) = b_3 + (2^4)c + (2^254)d_0 + let decomposition_check = { + let sum = b_3.clone() + c.clone() * two_pow_4 + d_0.clone() * two_pow_254; + sum - pkd_x + }; + + // b3_c_prime = b_3 + (2^4)c + 2^140 - t_P + let b3_c_prime_check = b_3 + (c * two_pow_4) + two_pow_140 - t_p - b3_c_prime; + + // The pkd_x_canonicity_checks are enforced if and only if `d_0` = 1. + // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` + let canonicity_checks = iter::empty() + .chain(Some(("d_0 = 1 => z13_c", z13_c))) + .chain(Some(("d_0 = 1 => z14_b3_c_prime", z14_b3_c_prime))) + .map(move |(name, poly)| (name, d_0.clone() * poly)); + + Constraints::with_selector( + q_notecommit_pk_d, + iter::empty() + .chain(Some(("decomposition", decomposition_check))) + .chain(Some(("b3_c_prime_check", b3_c_prime_check))) + .chain(canonicity_checks), + ) + }); + + Self { + q_notecommit_pk_d, + col_l, + col_m, + col_r, + col_z, + } + } + + #[allow(clippy::too_many_arguments)] + fn assign( + &self, + layouter: &mut impl Layouter, + pk_d: &NonIdentityEccPoint, + b_3: RangeConstrained>, + c: NoteCommitPiece, + d_0: AssignedCell, + b3_c_prime: AssignedCell, + z13_c: AssignedCell, + z14_b3_c_prime: AssignedCell, + ) -> Result<(), Error> { + layouter.assign_region( + || "NoteCommit input pk_d", + |mut region| { + pk_d.x() + .copy_advice(|| "pkd_x", &mut region, self.col_l, 0)?; + + b_3.inner() + .copy_advice(|| "b_3", &mut region, self.col_m, 0)?; + d_0.copy_advice(|| "d_0", &mut region, self.col_m, 1)?; + + c.inner() + .cell_value() + .copy_advice(|| "c", &mut region, self.col_r, 0)?; + b3_c_prime.copy_advice(|| "b3_c_prime", &mut region, self.col_r, 1)?; + + z13_c.copy_advice(|| "z13_c", &mut region, self.col_z, 0)?; + z14_b3_c_prime.copy_advice(|| "z14_b3_c_prime", &mut region, self.col_z, 1)?; + + self.q_notecommit_pk_d.enable(&mut region, 0) + }, + ) + } +} + +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_value | +/// ------------------------------------------------ +/// | value | d_2 | d_3 | e_0 | 1 | +/// +/// +#[derive(Clone, Debug)] +struct ValueCanonicity { + q_notecommit_value: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, +} + +impl ValueCanonicity { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, + two_pow_8: pallas::Base, + two_pow_58: pallas::Base, + ) -> Self { + let q_notecommit_value = meta.selector(); + + meta.create_gate("NoteCommit input value", |meta| { + let q_notecommit_value = meta.query_selector(q_notecommit_value); + + let value = meta.query_advice(col_l, Rotation::cur()); + // d_2 has been constrained to 8 bits outside this gate. + let d_2 = meta.query_advice(col_m, Rotation::cur()); + // z1_d has been constrained to 50 bits by the Sinsemilla hash. + let z1_d = meta.query_advice(col_r, Rotation::cur()); + let d_3 = z1_d; + // `e_0` has been constrained to 6 bits outside this gate. + let e_0 = meta.query_advice(col_z, Rotation::cur()); + + // value = d_2 + (2^8)d_3 + (2^58)e_0 + let value_check = d_2 + d_3 * two_pow_8 + e_0 * two_pow_58 - value; + + Constraints::with_selector(q_notecommit_value, Some(("value_check", value_check))) + }); + + Self { + q_notecommit_value, + col_l, + col_m, + col_r, + col_z, + } + } + + fn assign( + &self, + layouter: &mut impl Layouter, + value: AssignedCell, + d_2: RangeConstrained>, + z1_d: AssignedCell, + e_0: RangeConstrained>, + ) -> Result<(), Error> { + layouter.assign_region( + || "NoteCommit input value", + |mut region| { + value.copy_advice(|| "value", &mut region, self.col_l, 0)?; + d_2.inner() + .copy_advice(|| "d_2", &mut region, self.col_m, 0)?; + z1_d.copy_advice(|| "d3 = z1_d", &mut region, self.col_r, 0)?; + e_0.inner() + .copy_advice(|| "e_0", &mut region, self.col_z, 0)?; + + self.q_notecommit_value.enable(&mut region, 0) + }, + ) + } +} + +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_rho | +/// -------------------------------------------------------------- +/// | rho | e_1 | f | z13_f | 1 | +/// | | g_0 | e1_f_prime | z14_e1_f_prime | 0 | +/// +/// +#[derive(Clone, Debug)] +struct RhoCanonicity { + q_notecommit_rho: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, +} + +impl RhoCanonicity { + #[allow(clippy::too_many_arguments)] + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, + two_pow_4: pallas::Base, + two_pow_140: Expression, + two_pow_254: pallas::Base, + t_p: Expression, + ) -> Self { + let q_notecommit_rho = meta.selector(); + + meta.create_gate("NoteCommit input rho", |meta| { + let q_notecommit_rho = meta.query_selector(q_notecommit_rho); + + let rho = meta.query_advice(col_l, Rotation::cur()); + + // `e_1` has been constrained to 4 bits outside this gate. + let e_1 = meta.query_advice(col_m, Rotation::cur()); + let g_0 = meta.query_advice(col_m, Rotation::next()); + + // `f` has been constrained to 250 bits by the Sinsemilla hash. + let f = meta.query_advice(col_r, Rotation::cur()); + let e1_f_prime = meta.query_advice(col_r, Rotation::next()); + + let z13_f = meta.query_advice(col_z, Rotation::cur()); + let z14_e1_f_prime = meta.query_advice(col_z, Rotation::next()); + + // rho = e_1 + (2^4) f + (2^254) g_0 + let decomposition_check = { + let sum = e_1.clone() + f.clone() * two_pow_4 + g_0.clone() * two_pow_254; + sum - rho + }; + + // e1_f_prime = e_1 + (2^4)f + 2^140 - t_P + let e1_f_prime_check = e_1 + (f * two_pow_4) + two_pow_140 - t_p - e1_f_prime; + + // The rho_canonicity_checks are enforced if and only if `g_0` = 1. + // rho = e_1 (4 bits) || f (250 bits) || g_0 (1 bit) + let canonicity_checks = iter::empty() + .chain(Some(("g_0 = 1 => z13_f", z13_f))) + .chain(Some(("g_0 = 1 => z14_e1_f_prime", z14_e1_f_prime))) + .map(move |(name, poly)| (name, g_0.clone() * poly)); + + Constraints::with_selector( + q_notecommit_rho, + iter::empty() + .chain(Some(("decomposition", decomposition_check))) + .chain(Some(("e1_f_prime_check", e1_f_prime_check))) + .chain(canonicity_checks), + ) + }); + + Self { + q_notecommit_rho, + col_l, + col_m, + col_r, + col_z, + } + } + + #[allow(clippy::too_many_arguments)] + fn assign( + &self, + layouter: &mut impl Layouter, + rho: AssignedCell, + e_1: RangeConstrained>, + f: NoteCommitPiece, + g_0: AssignedCell, + e1_f_prime: AssignedCell, + z13_f: AssignedCell, + z14_e1_f_prime: AssignedCell, + ) -> Result<(), Error> { + layouter.assign_region( + || "NoteCommit input rho", + |mut region| { + rho.copy_advice(|| "rho", &mut region, self.col_l, 0)?; + + e_1.inner() + .copy_advice(|| "e_1", &mut region, self.col_m, 0)?; + g_0.copy_advice(|| "g_0", &mut region, self.col_m, 1)?; + + f.inner() + .cell_value() + .copy_advice(|| "f", &mut region, self.col_r, 0)?; + e1_f_prime.copy_advice(|| "e1_f_prime", &mut region, self.col_r, 1)?; + + z13_f.copy_advice(|| "z13_f", &mut region, self.col_z, 0)?; + z14_e1_f_prime.copy_advice(|| "z14_e1_f_prime", &mut region, self.col_z, 1)?; + + self.q_notecommit_rho.enable(&mut region, 0) + }, + ) + } +} + +/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_psi | +/// ---------------------------------------------------------------- +/// | psi | g_1 | g_2 | z13_g | 1 | +/// | h_0 | h_1 | g1_g2_prime | z13_g1_g2_prime | 0 | +/// +/// +#[derive(Clone, Debug)] +struct PsiCanonicity { + q_notecommit_psi: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, +} + +impl PsiCanonicity { + #[allow(clippy::too_many_arguments)] + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + col_z: Column, + two_pow_9: pallas::Base, + two_pow_130: Expression, + two_pow_249: pallas::Base, + two_pow_254: pallas::Base, + t_p: Expression, + ) -> Self { + let q_notecommit_psi = meta.selector(); + + meta.create_gate("NoteCommit input psi", |meta| { + let q_notecommit_psi = meta.query_selector(q_notecommit_psi); + + let psi = meta.query_advice(col_l, Rotation::cur()); + let h_0 = meta.query_advice(col_l, Rotation::next()); + + let g_1 = meta.query_advice(col_m, Rotation::cur()); + let h_1 = meta.query_advice(col_m, Rotation::next()); + + let z1_g = meta.query_advice(col_r, Rotation::cur()); + let g_2 = z1_g; + let g1_g2_prime = meta.query_advice(col_r, Rotation::next()); + + let z13_g = meta.query_advice(col_z, Rotation::cur()); + let z13_g1_g2_prime = meta.query_advice(col_z, Rotation::next()); + + // psi = g_1 + (2^9) g_2 + (2^249) h_0 + (2^254) h_1 + let decomposition_check = { + let sum = g_1.clone() + + g_2.clone() * two_pow_9 + + h_0.clone() * two_pow_249 + + h_1.clone() * two_pow_254; + sum - psi + }; + + // g1_g2_prime = g_1 + (2^9)g_2 + 2^130 - t_P + let g1_g2_prime_check = g_1 + (g_2 * two_pow_9) + two_pow_130 - t_p - g1_g2_prime; + + // The psi_canonicity_checks are enforced if and only if `h_1` = 1. + // `psi` = `g_1 (9 bits) || g_2 (240 bits) || h_0 (5 bits) || h_1 (1 bit)` + let canonicity_checks = iter::empty() + .chain(Some(("h_1 = 1 => h_0", h_0))) + .chain(Some(("h_1 = 1 => z13_g", z13_g))) + .chain(Some(("h_1 = 1 => z13_g1_g2_prime", z13_g1_g2_prime))) + .map(move |(name, poly)| (name, h_1.clone() * poly)); + + Constraints::with_selector( + q_notecommit_psi, + iter::empty() + .chain(Some(("decomposition", decomposition_check))) + .chain(Some(("g1_g2_prime_check", g1_g2_prime_check))) + .chain(canonicity_checks), + ) + }); + + Self { + q_notecommit_psi, + col_l, + col_m, + col_r, + col_z, + } + } + + #[allow(clippy::too_many_arguments)] + fn assign( + &self, + layouter: &mut impl Layouter, + psi: AssignedCell, + g_1: RangeConstrained>, + z1_g: AssignedCell, + h_0: RangeConstrained>, + h_1: AssignedCell, + g1_g2_prime: AssignedCell, + z13_g: AssignedCell, + z13_g1_g2_prime: AssignedCell, + ) -> Result<(), Error> { + layouter.assign_region( + || "NoteCommit input psi", + |mut region| { + psi.copy_advice(|| "psi", &mut region, self.col_l, 0)?; + h_0.inner() + .copy_advice(|| "h_0", &mut region, self.col_l, 1)?; + + g_1.inner() + .copy_advice(|| "g_1", &mut region, self.col_m, 0)?; + h_1.copy_advice(|| "h_1", &mut region, self.col_m, 1)?; + + z1_g.copy_advice(|| "g_2 = z1_g", &mut region, self.col_r, 0)?; + g1_g2_prime.copy_advice(|| "g1_g2_prime", &mut region, self.col_r, 1)?; + + z13_g.copy_advice(|| "z13_g", &mut region, self.col_z, 0)?; + z13_g1_g2_prime.copy_advice(|| "z13_g1_g2_prime", &mut region, self.col_z, 1)?; + + self.q_notecommit_psi.enable(&mut region, 0) + }, + ) + } +} + +/// Check decomposition and canonicity of y-coordinates. +/// This is used for both y(g_d) and y(pk_d). +/// +/// y = LSB || k_0 || k_1 || k_2 || k_3 +/// = (bit 0) || (bits 1..=9) || (bits 10..=249) || (bits 250..=253) || (bit 254) +/// +/// These pieces are laid out in the following configuration: +/// | A_5 | A_6 | A_7 | A_8 | A_9 | q_y_canon | +/// --------------------------------------------------------- +/// | y | lsb | k_0 | k_2 | k_3 | 1 | +/// | j | z1_j| z13_j | j_prime | z13_j_prime | 0 | +/// where z1_j = k_1. +#[derive(Clone, Debug)] +struct YCanonicity { + q_y_canon: Selector, + advices: [Column; 10], +} + +impl YCanonicity { + #[allow(clippy::too_many_arguments)] + fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 10], + two: pallas::Base, + two_pow_10: pallas::Base, + two_pow_130: Expression, + two_pow_250: pallas::Base, + two_pow_254: pallas::Base, + t_p: Expression, + ) -> Self { + let q_y_canon = meta.selector(); + + meta.create_gate("y coordinate checks", |meta| { + let q_y_canon = meta.query_selector(q_y_canon); + let y = meta.query_advice(advices[5], Rotation::cur()); + // LSB has been boolean-constrained outside this gate. + let lsb = meta.query_advice(advices[6], Rotation::cur()); + // k_0 has been constrained to 9 bits outside this gate. + let k_0 = meta.query_advice(advices[7], Rotation::cur()); + // k_1 = z1_j (witnessed in the next rotation). + // k_2 has been constrained to 4 bits outside this gate. + let k_2 = meta.query_advice(advices[8], Rotation::cur()); + // This gate constrains k_3 to be boolean. + let k_3 = meta.query_advice(advices[9], Rotation::cur()); + + // j = LSB + (2)k_0 + (2^10)k_1 + let j = meta.query_advice(advices[5], Rotation::next()); + let z1_j = meta.query_advice(advices[6], Rotation::next()); + let z13_j = meta.query_advice(advices[7], Rotation::next()); + + // j_prime = j + 2^130 - t_P + let j_prime = meta.query_advice(advices[8], Rotation::next()); + let z13_j_prime = meta.query_advice(advices[9], Rotation::next()); + + // Decomposition checks + // https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial + let decomposition_checks = { + // Check that k_3 is boolean + let k3_check = bool_check(k_3.clone()); + // Check that j = LSB + (2)k_0 + (2^10)k_1 + let k_1 = z1_j; + let j_check = j.clone() - (lsb + k_0 * two + k_1 * two_pow_10); + // Check that y = j + (2^250)k_2 + (2^254)k_3 + let y_check = + y - (j.clone() + k_2.clone() * two_pow_250 + k_3.clone() * two_pow_254); + // Check that j_prime = j + 2^130 - t_P + let j_prime_check = j + two_pow_130 - t_p - j_prime; + + iter::empty() + .chain(Some(("k3_check", k3_check))) + .chain(Some(("j_check", j_check))) + .chain(Some(("y_check", y_check))) + .chain(Some(("j_prime_check", j_prime_check))) + }; + + // Canonicity checks. These are enforced if and only if k_3 = 1. + // https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial + let canonicity_checks = { + iter::empty() + .chain(Some(("k_3 = 1 => k_2 = 0", k_2))) + .chain(Some(("k_3 = 1 => z13_j = 0", z13_j))) + .chain(Some(("k_3 = 1 => z13_j_prime = 0", z13_j_prime))) + .map(move |(name, poly)| (name, k_3.clone() * poly)) + }; + + Constraints::with_selector(q_y_canon, decomposition_checks.chain(canonicity_checks)) + }); + + Self { q_y_canon, advices } + } + + #[allow(clippy::too_many_arguments)] + fn assign( + &self, + layouter: &mut impl Layouter, + y: AssignedCell, + lsb: RangeConstrained>, + k_0: RangeConstrained>, + k_2: RangeConstrained>, + k_3: RangeConstrained>, + j: AssignedCell, + z1_j: AssignedCell, + z13_j: AssignedCell, + j_prime: AssignedCell, + z13_j_prime: AssignedCell, + ) -> Result>, Error> + { + layouter.assign_region( + || "y canonicity", + |mut region| { + self.q_y_canon.enable(&mut region, 0)?; + + // Offset 0 + let lsb = { + let offset = 0; + + // Copy y. + y.copy_advice(|| "copy y", &mut region, self.advices[5], offset)?; + // Witness LSB. + let lsb = region + .assign_advice(|| "witness LSB", self.advices[6], offset, || *lsb.inner()) + // SAFETY: This is sound because we just assigned this cell from a + // range-constrained value. + .map(|cell| RangeConstrained::unsound_unchecked(cell, lsb.num_bits()))?; + // Witness k_0. + k_0.inner() + .copy_advice(|| "copy k_0", &mut region, self.advices[7], offset)?; + // Copy k_2. + k_2.inner() + .copy_advice(|| "copy k_2", &mut region, self.advices[8], offset)?; + // Witness k_3. + region.assign_advice( + || "witness k_3", + self.advices[9], + offset, + || *k_3.inner(), + )?; + + lsb + }; + + // Offset 1 + { + let offset = 1; + + // Copy j. + j.copy_advice(|| "copy j", &mut region, self.advices[5], offset)?; + // Copy z1_j. + z1_j.copy_advice(|| "copy z1_j", &mut region, self.advices[6], offset)?; + // Copy z13_j. + z13_j.copy_advice(|| "copy z13_j", &mut region, self.advices[7], offset)?; + // Copy j_prime. + j_prime.copy_advice(|| "copy j_prime", &mut region, self.advices[8], offset)?; + // Copy z13_j_prime. + z13_j_prime.copy_advice( + || "copy z13_j_prime", + &mut region, + self.advices[9], + offset, + )?; + } + + Ok(lsb) + }, + ) + } +} + +#[allow(non_snake_case)] +#[derive(Clone, Debug)] +pub struct NoteCommitConfig { + b: DecomposeB, + d: DecomposeD, + e: DecomposeE, + g: DecomposeG, + h: DecomposeH, + g_d: GdCanonicity, + pk_d: PkdCanonicity, + value: ValueCanonicity, + rho: RhoCanonicity, + psi: PsiCanonicity, + y_canon: YCanonicity, + advices: [Column; 10], + sinsemilla_config: + SinsemillaConfig, +} + +#[derive(Clone, Debug)] +pub struct NoteCommitChip { + config: NoteCommitConfig, +} + +impl NoteCommitChip { + #[allow(non_snake_case)] + #[allow(clippy::many_single_char_names)] + pub(in crate::circuit) fn configure( + meta: &mut ConstraintSystem, + advices: [Column; 10], + sinsemilla_config: SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >, + ) -> NoteCommitConfig { + // Useful constants + let two = pallas::Base::from(2); + let two_pow_2 = pallas::Base::from(1 << 2); + let two_pow_4 = two_pow_2.square(); + let two_pow_5 = two_pow_4 * two; + let two_pow_6 = two_pow_5 * two; + let two_pow_8 = two_pow_4.square(); + let two_pow_9 = two_pow_8 * two; + let two_pow_10 = two_pow_9 * two; + let two_pow_58 = pallas::Base::from(1 << 58); + let two_pow_130 = Expression::Constant(pallas::Base::from_u128(1 << 65).square()); + let two_pow_140 = Expression::Constant(pallas::Base::from_u128(1 << 70).square()); + let two_pow_249 = pallas::Base::from_u128(1 << 124).square() * two; + let two_pow_250 = two_pow_249 * two; + let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); + + let t_p = Expression::Constant(pallas::Base::from_u128(T_P)); + + // Columns used for MessagePiece and message input gates. + let col_l = advices[6]; + let col_m = advices[7]; + let col_r = advices[8]; + let col_z = advices[9]; + + let b = DecomposeB::configure(meta, col_l, col_m, col_r, two_pow_4, two_pow_5, two_pow_6); + let d = DecomposeD::configure(meta, col_l, col_m, col_r, two, two_pow_2, two_pow_10); + let e = DecomposeE::configure(meta, col_l, col_m, col_r, two_pow_6); + let g = DecomposeG::configure(meta, col_l, col_m, two, two_pow_10); + let h = DecomposeH::configure(meta, col_l, col_m, col_r, two_pow_5); + + let g_d = GdCanonicity::configure( + meta, + col_l, + col_m, + col_r, + col_z, + two_pow_130.clone(), + two_pow_250, + two_pow_254, + t_p.clone(), + ); + + let pk_d = PkdCanonicity::configure( + meta, + col_l, + col_m, + col_r, + col_z, + two_pow_4, + two_pow_140.clone(), + two_pow_254, + t_p.clone(), + ); + + let value = + ValueCanonicity::configure(meta, col_l, col_m, col_r, col_z, two_pow_8, two_pow_58); + + let rho = RhoCanonicity::configure( + meta, + col_l, + col_m, + col_r, + col_z, + two_pow_4, + two_pow_140, + two_pow_254, + t_p.clone(), + ); + + let psi = PsiCanonicity::configure( + meta, + col_l, + col_m, + col_r, + col_z, + two_pow_9, + two_pow_130.clone(), + two_pow_249, + two_pow_254, + t_p.clone(), + ); + + let y_canon = YCanonicity::configure( + meta, + advices, + two, + two_pow_10, + two_pow_130, + two_pow_250, + two_pow_254, + t_p, + ); + + NoteCommitConfig { + b, + d, + e, + g, + h, + g_d, + pk_d, + value, + rho, + psi, + y_canon, + advices, + sinsemilla_config, + } + } + + pub(in crate::circuit) fn construct(config: NoteCommitConfig) -> Self { + Self { config } + } +} + +pub(in crate::circuit) mod gadgets { + use halo2_proofs::circuit::{Chip, Value}; + + use super::*; + + #[allow(clippy::many_single_char_names)] + #[allow(clippy::type_complexity)] + #[allow(clippy::too_many_arguments)] + pub(in crate::circuit) fn note_commit( + mut layouter: impl Layouter, + chip: SinsemillaChip, + ecc_chip: EccChip, + note_commit_chip: NoteCommitChip, + g_d: &NonIdentityEccPoint, + pk_d: &NonIdentityEccPoint, + value: AssignedCell, + rho: AssignedCell, + psi: AssignedCell, + rcm: ScalarFixed>, + ) -> Result>, Error> { + let lookup_config = chip.config().lookup_config(); + + // `a` = bits 0..=249 of `x(g_d)` + let a = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "a"), + [RangeConstrained::bitrange_of(g_d.x().value(), 0..250)], + )?; + + // b = b_0 || b_1 || b_2 || b_3 + // = (bits 250..=253 of x(g_d)) || (bit 254 of x(g_d)) || (ỹ bit of g_d) || (bits 0..=3 of pk★_d) + let (b, b_0, b_1, b_2, b_3) = + DecomposeB::decompose(&lookup_config, chip.clone(), &mut layouter, g_d, pk_d)?; + + // c = bits 4..=253 of pk★_d + let c = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "c"), + [RangeConstrained::bitrange_of(pk_d.x().value(), 4..254)], + )?; + + // d = d_0 || d_1 || d_2 || d_3 + // = (bit 254 of x(pk_d)) || (ỹ bit of pk_d) || (bits 0..=7 of v) || (bits 8..=57 of v) + let (d, d_0, d_1, d_2) = + DecomposeD::decompose(&lookup_config, chip.clone(), &mut layouter, pk_d, &value)?; + + // e = e_0 || e_1 = (bits 58..=63 of v) || (bits 0..=3 of rho) + let (e, e_0, e_1) = + DecomposeE::decompose(&lookup_config, chip.clone(), &mut layouter, &value, &rho)?; + + // f = bits 4..=253 inclusive of rho + let f = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "f"), + [RangeConstrained::bitrange_of(rho.value(), 4..254)], + )?; + + // g = g_0 || g_1 || g_2 + // = (bit 254 of rho) || (bits 0..=8 of psi) || (bits 9..=248 of psi) + let (g, g_0, g_1) = + DecomposeG::decompose(&lookup_config, chip.clone(), &mut layouter, &rho, &psi)?; + + // h = h_0 || h_1 || h_2 + // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits + let (h, h_0, h_1) = + DecomposeH::decompose(&lookup_config, chip.clone(), &mut layouter, &psi)?; + + // Check decomposition of `y(g_d)`. + let b_2 = y_canonicity( + &lookup_config, + ¬e_commit_chip.config.y_canon, + layouter.namespace(|| "y(g_d) decomposition"), + g_d.y(), + b_2, + )?; + // Check decomposition of `y(pk_d)`. + let d_1 = y_canonicity( + &lookup_config, + ¬e_commit_chip.config.y_canon, + layouter.namespace(|| "y(pk_d) decomposition"), + pk_d.y(), + d_1, + )?; + + // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) + // + // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition + // constraints allows ⊥ to occur, and then during synthesis it detects these edge + // cases and raises an error (aborting proof creation). + // + // https://p.z.cash/ZKS:action-cm-old-integrity?partial + // https://p.z.cash/ZKS:action-cmx-new-integrity?partial + let (cm, zs) = { + let message = Message::from_pieces( + chip.clone(), + vec![ + a.clone(), + b.clone(), + c.clone(), + d.clone(), + e.clone(), + f.clone(), + g.clone(), + h.clone(), + ], + ); + let domain = CommitDomain::new(chip, ecc_chip, &OrchardCommitDomains::NoteCommit); + domain.commit( + layouter.namespace(|| "Process NoteCommit inputs"), + message, + rcm, + )? + }; + + // `CommitDomain::commit` returns the running sum for each `MessagePiece`. Grab + // the outputs that we will need for canonicity checks. + let z13_a = zs[0][13].clone(); + let z13_c = zs[2][13].clone(); + let z1_d = zs[3][1].clone(); + let z13_f = zs[5][13].clone(); + let z1_g = zs[6][1].clone(); + let g_2 = z1_g.clone(); + let z13_g = zs[6][13].clone(); + + // Witness and constrain the bounds we need to ensure canonicity. + let (a_prime, z13_a_prime) = canon_bitshift_130( + &lookup_config, + layouter.namespace(|| "x(g_d) canonicity"), + a.inner().cell_value(), + )?; + + let (b3_c_prime, z14_b3_c_prime) = pkd_x_canonicity( + &lookup_config, + layouter.namespace(|| "x(pk_d) canonicity"), + b_3.clone(), + c.inner().cell_value(), + )?; + + let (e1_f_prime, z14_e1_f_prime) = rho_canonicity( + &lookup_config, + layouter.namespace(|| "rho canonicity"), + e_1.clone(), + f.inner().cell_value(), + )?; + + let (g1_g2_prime, z13_g1_g2_prime) = psi_canonicity( + &lookup_config, + layouter.namespace(|| "psi canonicity"), + g_1.clone(), + g_2, + )?; + + // Finally, assign values to all of the NoteCommit regions. + let cfg = note_commit_chip.config; + + let b_1 = cfg + .b + .assign(&mut layouter, b, b_0.clone(), b_1, b_2, b_3.clone())?; + + let d_0 = cfg + .d + .assign(&mut layouter, d, d_0, d_1, d_2.clone(), z1_d.clone())?; + + cfg.e.assign(&mut layouter, e, e_0.clone(), e_1.clone())?; + + let g_0 = cfg + .g + .assign(&mut layouter, g, g_0, g_1.clone(), z1_g.clone())?; + + let h_1 = cfg.h.assign(&mut layouter, h, h_0.clone(), h_1)?; + + cfg.g_d + .assign(&mut layouter, g_d, a, b_0, b_1, a_prime, z13_a, z13_a_prime)?; + + cfg.pk_d.assign( + &mut layouter, + pk_d, + b_3, + c, + d_0, + b3_c_prime, + z13_c, + z14_b3_c_prime, + )?; + + cfg.value.assign(&mut layouter, value, d_2, z1_d, e_0)?; + + cfg.rho.assign( + &mut layouter, + rho, + e_1, + f, + g_0, + e1_f_prime, + z13_f, + z14_e1_f_prime, + )?; + + cfg.psi.assign( + &mut layouter, + psi, + g_1, + z1_g, + h_0, + h_1, + g1_g2_prime, + z13_g, + z13_g1_g2_prime, + )?; + + Ok(cm) + } + + /// A canonicity check helper used in checking x(g_d), y(g_d), and y(pk_d). + /// + /// Specifications: + /// - [`g_d` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-g_d?partial) + /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) + fn canon_bitshift_130( + lookup_config: &PallasLookupRangeCheckConfig, + mut layouter: impl Layouter, + a: AssignedCell, + ) -> Result { + // element = `a (250 bits) || b_0 (4 bits) || b_1 (1 bit)` + // - b_1 = 1 => b_0 = 0 + // - b_1 = 1 => a < t_P + // - 0 ≤ a < 2^130 (z_13 of SinsemillaHash(a)) + // - 0 ≤ a + 2^130 - t_P < 2^130 (thirteen 10-bit lookups) + + // Decompose the low 130 bits of a_prime = a + 2^130 - t_P, and output + // the running sum at the end of it. If a_prime < 2^130, the running sum + // will be 0. + let a_prime = { + let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + a.value() + two_pow_130 - t_p + }; + let zs = lookup_config.witness_check( + layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), + a_prime, + 13, + false, + )?; + let a_prime = zs[0].clone(); + assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z_13] + + Ok((a_prime, zs[13].clone())) + } + + /// Check canonicity of `x(pk_d)` encoding. + /// + /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-pk_d?partial). + fn pkd_x_canonicity( + lookup_config: &PallasLookupRangeCheckConfig, + mut layouter: impl Layouter, + b_3: RangeConstrained>, + c: AssignedCell, + ) -> Result { + // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` + // - d_0 = 1 => b_3 + 2^4 c < t_P + // - 0 ≤ b_3 + 2^4 c < 2^134 + // - b_3 is part of the Sinsemilla message piece + // b = b_0 (4 bits) || b_1 (1 bit) || b_2 (1 bit) || b_3 (4 bits) + // - b_3 is individually constrained to be 4 bits. + // - z_13 of SinsemillaHash(c) == 0 constrains bits 4..=253 of pkd_x + // to 130 bits. z13_c is directly checked in the gate. + // - 0 ≤ b_3 + 2^4 c + 2^140 - t_P < 2^140 (14 ten-bit lookups) + + // Decompose the low 140 bits of b3_c_prime = b_3 + 2^4 c + 2^140 - t_P, + // and output the running sum at the end of it. + // If b3_c_prime < 2^140, the running sum will be 0. + let b3_c_prime = { + let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4)); + let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + b_3.inner().value() + (two_pow_4 * c.value()) + two_pow_140 - t_p + }; + + let zs = lookup_config.witness_check( + layouter.namespace(|| "Decompose low 140 bits of (b_3 + 2^4 c + 2^140 - t_P)"), + b3_c_prime, + 14, + false, + )?; + let b3_c_prime = zs[0].clone(); + assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z_13, z_14] + + Ok((b3_c_prime, zs[14].clone())) + } + + /// Check canonicity of `rho` encoding. + /// + /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-rho?partial). + fn rho_canonicity( + lookup_config: &PallasLookupRangeCheckConfig, + mut layouter: impl Layouter, + e_1: RangeConstrained>, + f: AssignedCell, + ) -> Result { + // `rho` = `e_1 (4 bits) || f (250 bits) || g_0 (1 bit)` + // - g_0 = 1 => e_1 + 2^4 f < t_P + // - 0 ≤ e_1 + 2^4 f < 2^134 + // - e_1 is part of the Sinsemilla message piece + // e = e_0 (56 bits) || e_1 (4 bits) + // - e_1 is individually constrained to be 4 bits. + // - z_13 of SinsemillaHash(f) == 0 constrains bits 4..=253 of rho + // to 130 bits. z13_f == 0 is directly checked in the gate. + // - 0 ≤ e_1 + 2^4 f + 2^140 - t_P < 2^140 (14 ten-bit lookups) + + let e1_f_prime = { + let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4)); + let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + e_1.inner().value() + (two_pow_4 * f.value()) + two_pow_140 - t_p + }; + + // Decompose the low 140 bits of e1_f_prime = e_1 + 2^4 f + 2^140 - t_P, + // and output the running sum at the end of it. + // If e1_f_prime < 2^140, the running sum will be 0. + let zs = lookup_config.witness_check( + layouter.namespace(|| "Decompose low 140 bits of (e_1 + 2^4 f + 2^140 - t_P)"), + e1_f_prime, + 14, + false, + )?; + let e1_f_prime = zs[0].clone(); + assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z_13, z_14] + + Ok((e1_f_prime, zs[14].clone())) + } + + /// Check canonicity of `psi` encoding. + /// + /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-psi?partial). + fn psi_canonicity( + lookup_config: &PallasLookupRangeCheckConfig, + mut layouter: impl Layouter, + g_1: RangeConstrained>, + g_2: AssignedCell, + ) -> Result { + // `psi` = `g_1 (9 bits) || g_2 (240 bits) || h_0 (5 bits) || h_1 (1 bit)` + // - h_1 = 1 => (h_0 = 0) ∧ (g_1 + 2^9 g_2 < t_P) + // - 0 ≤ g_1 + 2^9 g_2 < 2^130 + // - g_1 is individually constrained to be 9 bits + // - z_13 of SinsemillaHash(g) == 0 constrains bits 0..=248 of psi + // to 130 bits. z13_g == 0 is directly checked in the gate. + // - 0 ≤ g_1 + (2^9)g_2 + 2^130 - t_P < 2^130 (13 ten-bit lookups) + + // Decompose the low 130 bits of g1_g2_prime = g_1 + (2^9)g_2 + 2^130 - t_P, + // and output the running sum at the end of it. + // If g1_g2_prime < 2^130, the running sum will be 0. + let g1_g2_prime = { + let two_pow_9 = Value::known(pallas::Base::from(1u64 << 9)); + let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); + let t_p = Value::known(pallas::Base::from_u128(T_P)); + g_1.inner().value() + (two_pow_9 * g_2.value()) + two_pow_130 - t_p + }; + + let zs = lookup_config.witness_check( + layouter.namespace(|| "Decompose low 130 bits of (g_1 + (2^9)g_2 + 2^130 - t_P)"), + g1_g2_prime, + 13, + false, + )?; + let g1_g2_prime = zs[0].clone(); + assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z_13] + + Ok((g1_g2_prime, zs[13].clone())) + } + + /// Check canonicity of y-coordinate given its LSB as a value. + /// Also, witness the LSB and return the witnessed cell. + /// + /// Specifications: + /// - [`y` decomposition](https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial) + /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) + fn y_canonicity( + lookup_config: &PallasLookupRangeCheckConfig, + y_canon: &YCanonicity, + mut layouter: impl Layouter, + y: AssignedCell, + lsb: RangeConstrained>, + ) -> Result>, Error> + { + // Decompose the field element + // y = LSB || k_0 || k_1 || k_2 || k_3 + // = (bit 0) || (bits 1..=9) || (bits 10..=249) || (bits 250..=253) || (bit 254) + + // Range-constrain k_0 to be 9 bits. + let k_0 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "k_0"), + y.value(), + 1..10, + )?; + + // k_1 will be constrained by the decomposition of j. + let k_1 = RangeConstrained::bitrange_of(y.value(), 10..250); + + // Range-constrain k_2 to be 4 bits. + let k_2 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "k_2"), + y.value(), + 250..254, + )?; + + // k_3 will be boolean-constrained in the gate. + let k_3 = RangeConstrained::bitrange_of(y.value(), 254..255); + + // Decompose j = LSB + (2)k_0 + (2^10)k_1 using 25 ten-bit lookups. + let (j, z1_j, z13_j) = { + let j = { + let two = Value::known(pallas::Base::from(2)); + let two_pow_10 = Value::known(pallas::Base::from(1 << 10)); + lsb.inner().value() + two * k_0.inner().value() + two_pow_10 * k_1.inner().value() + }; + let zs = lookup_config.witness_check( + layouter.namespace(|| "Decompose j = LSB + (2)k_0 + (2^10)k_1"), + j, + 25, + true, + )?; + (zs[0].clone(), zs[1].clone(), zs[13].clone()) + }; + + // Decompose j_prime = j + 2^130 - t_P using 13 ten-bit lookups. + // We can reuse the canon_bitshift_130 logic here. + let (j_prime, z13_j_prime) = canon_bitshift_130( + lookup_config, + layouter.namespace(|| "j_prime = j + 2^130 - t_P"), + j.clone(), + )?; + + y_canon.assign( + &mut layouter, + y, + lsb, + k_0, + k_2, + k_3, + j, + z1_j, + z13_j, + j_prime, + z13_j_prime, + ) + } +} + +#[cfg(test)] +mod tests { + use core::iter; + + use super::NoteCommitConfig; + use crate::{ + circuit::circuit_vanilla::{ + gadget::assign_free_advice, + note_commit::{gadgets, NoteCommitChip}, + }, + constants::{ + fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, + OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q, + }, + value::NoteValue, + }; + use halo2_gadgets::{ + ecc::{ + chip::{EccChip, EccConfig}, + NonIdentityPoint, ScalarFixed, + }, + sinsemilla::chip::SinsemillaChip, + sinsemilla::primitives::CommitDomain, + utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, + }; + + use ff::{Field, PrimeField, PrimeFieldBits}; + use group::Curve; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + dev::MockProver, + plonk::{Circuit, ConstraintSystem, Error}, + }; + use pasta_curves::{arithmetic::CurveAffine, pallas}; + + use rand::{rngs::OsRng, RngCore}; + + #[test] + fn note_commit() { + #[derive(Default)] + struct MyCircuit { + gd_x: Value, + gd_y_lsb: Value, + pkd_x: Value, + pkd_y_lsb: Value, + rho: Value, + psi: Value, + } + + impl Circuit for MyCircuit { + type Config = (NoteCommitConfig, EccConfig); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants. + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let sinsemilla_config = SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + false, + ); + let note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config); + + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + (note_commit_config, ecc_config) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let (note_commit_config, ecc_config) = config; + + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?; + + // Construct a Sinsemilla chip + let sinsemilla_chip = + SinsemillaChip::construct(note_commit_config.sinsemilla_config.clone()); + + // Construct an ECC chip + let ecc_chip = EccChip::construct(ecc_config); + + // Construct a NoteCommit chip + let note_commit_chip = NoteCommitChip::construct(note_commit_config.clone()); + + // Witness g_d + let g_d = { + let g_d = self.gd_x.zip(self.gd_y_lsb).map(|(x, y_lsb)| { + // Calculate y = (x^3 + 5).sqrt() + let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); + if bool::from(y.is_odd() ^ y_lsb.is_odd()) { + y = -y; + } + pallas::Affine::from_xy(x, y).unwrap() + }); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d"), + g_d, + )? + }; + + // Witness pk_d + let pk_d = { + let pk_d = self.pkd_x.zip(self.pkd_y_lsb).map(|(x, y_lsb)| { + // Calculate y = (x^3 + 5).sqrt() + let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); + if bool::from(y.is_odd() ^ y_lsb.is_odd()) { + y = -y; + } + pallas::Affine::from_xy(x, y).unwrap() + }); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d"), + pk_d, + )? + }; + + // Witness a random non-negative u64 note value + // A note value cannot be negative. + let value = { + let mut rng = OsRng; + NoteValue::from_raw(rng.next_u64()) + }; + let value_var = { + assign_free_advice( + layouter.namespace(|| "witness value"), + note_commit_config.advices[0], + Value::known(value), + )? + }; + + // Witness rho + let rho = assign_free_advice( + layouter.namespace(|| "witness rho"), + note_commit_config.advices[0], + self.rho, + )?; + + // Witness psi + let psi = assign_free_advice( + layouter.namespace(|| "witness psi"), + note_commit_config.advices[0], + self.psi, + )?; + + let rcm = pallas::Scalar::random(OsRng); + let rcm_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm"), + Value::known(rcm), + )?; + + let cm = gadgets::note_commit( + layouter.namespace(|| "Hash NoteCommit pieces"), + sinsemilla_chip, + ecc_chip.clone(), + note_commit_chip, + g_d.inner(), + pk_d.inner(), + value_var, + rho, + psi, + rcm_gadget, + )?; + let expected_cm = { + let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); + // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi + let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one(); + let point = self + .gd_x + .zip(self.gd_y_lsb) + .zip(self.pkd_x.zip(self.pkd_y_lsb)) + .zip(self.rho.zip(self.psi)) + .map(|(((gd_x, gd_y_lsb), (pkd_x, pkd_y_lsb)), (rho, psi))| { + domain + .commit( + iter::empty() + .chain( + gd_x.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ) + .chain(Some(lsb(gd_y_lsb))) + .chain( + pkd_x + .to_le_bits() + .iter() + .by_vals() + .take(L_ORCHARD_BASE), + ) + .chain(Some(lsb(pkd_y_lsb))) + .chain(value.to_le_bits().iter().by_vals().take(L_VALUE)) + .chain( + rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ) + .chain( + psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ), + &rcm, + ) + .unwrap() + .to_affine() + }); + NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)? + }; + cm.constrain_equal(layouter.namespace(|| "cm == expected cm"), &expected_cm) + } + } + + let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); + // Test different values of `ak`, `nk` + let circuits = [ + // `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points) + // `rho` = 0, `psi` = 0 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(pallas::Base::zero()), + psi: Value::known(pallas::Base::zero()), + }, + // `rho` = T_Q - 1, `psi` = T_Q - 1 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(T_Q - 1)), + psi: Value::known(pallas::Base::from_u128(T_Q - 1)), + }, + // `rho` = T_Q, `psi` = T_Q + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(T_Q)), + psi: Value::known(pallas::Base::from_u128(T_Q)), + }, + // `rho` = 2^127 - 1, `psi` = 2^127 - 1 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + }, + // `rho` = 2^127, `psi` = 2^127 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(1 << 127)), + psi: Value::known(pallas::Base::from_u128(1 << 127)), + }, + // `rho` = 2^254 - 1, `psi` = 2^254 - 1 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(two_pow_254 - pallas::Base::one()), + psi: Value::known(two_pow_254 - pallas::Base::one()), + }, + // `rho` = 2^254, `psi` = 2^254 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(two_pow_254), + psi: Value::known(two_pow_254), + }, + ]; + + for circuit in circuits.iter() { + let prover = MockProver::::run(11, circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } +} diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs new file mode 100644 index 000000000..0fc7cf6db --- /dev/null +++ b/src/circuit/circuit_zsa.rs @@ -0,0 +1,1447 @@ +//! The Orchard Action circuit implementation for the ZSA variation of the Orchard protocol. +//! +//! Includes the configuration, synthesis, and proof verification logic. + +use ff::Field; + +use group::Curve; + +use pasta_curves::{arithmetic::CurveAffine, pallas}; + +use halo2_gadgets::{ + ecc::{ + chip::{EccChip, EccConfig}, + FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar, + }, + poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, + sinsemilla::{ + chip::{SinsemillaChip, SinsemillaConfig}, + merkle::{ + chip::{MerkleChip, MerkleConfig}, + MerklePath, + }, + }, + utilities::{ + bool_check, + cond_swap::{CondSwapChip, CondSwapConfig}, + lookup_range_check::{LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig}, + }, +}; + +use halo2_proofs::{ + circuit::{Layouter, Value}, + plonk::{self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector}, + poly::Rotation, +}; + +use crate::{ + constants::OrchardFixedBasesFull, + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, + note::AssetBase, + orchard_flavor::OrchardZSA, +}; + +use super::{ + commit_ivk::{ + self, {CommitIvkChip, CommitIvkConfig}, + }, + gadget::{ + add_chip::{self, AddChip, AddConfig}, + AddInstruction, + }, + Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, + ENABLE_ZSA, NF_OLD, RK_X, RK_Y, +}; + +use self::{ + gadget::{assign_free_advice, assign_is_native_asset, assign_split_flag}, + note_commit::{NoteCommitChip, NoteCommitConfig}, +}; + +pub mod gadget; +mod note_commit; +mod value_commit_orchard; + +/// Configuration needed to use the Orchard Action circuit. +#[derive(Clone, Debug)] +pub struct Config { + primary: Column, + q_orchard: Selector, + advices: [Column; 10], + add_config: AddConfig, + ecc_config: EccConfig, + poseidon_config: PoseidonConfig, + merkle_config_1: MerkleConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, + merkle_config_2: MerkleConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, + sinsemilla_config_1: SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, + sinsemilla_config_2: SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, + commit_ivk_config: CommitIvkConfig, + old_note_commit_config: NoteCommitConfig, + new_note_commit_config: NoteCommitConfig, + cond_swap_config: CondSwapConfig, +} + +impl OrchardCircuit for OrchardZSA { + type Config = Config; + + fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { + // Advice columns used in the Orchard circuit. + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Constrain split_flag to be boolean + // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + // Constrain (v_old = 0 and is_native_asset = 1) or (calculated root = anchor) (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). + // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). + // Constrain is_native_asset to be boolean + // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset + // Constraint if split_flag = 0 then psi_old = psi_nf + // Constraint if split_flag = 1, then is_native_asset = 0 + // Constraint if enable_zsa = 0, then is_native_asset = 1 + let q_orchard = meta.selector(); + meta.create_gate("Orchard circuit checks", |meta| { + let q_orchard = meta.query_selector(q_orchard); + let v_old = meta.query_advice(advices[0], Rotation::cur()); + let v_new = meta.query_advice(advices[1], Rotation::cur()); + let magnitude = meta.query_advice(advices[2], Rotation::cur()); + let sign = meta.query_advice(advices[3], Rotation::cur()); + + let root = meta.query_advice(advices[4], Rotation::cur()); + let anchor = meta.query_advice(advices[5], Rotation::cur()); + + let enable_spends = meta.query_advice(advices[6], Rotation::cur()); + let enable_outputs = meta.query_advice(advices[7], Rotation::cur()); + + let split_flag = meta.query_advice(advices[8], Rotation::cur()); + + let is_native_asset = meta.query_advice(advices[9], Rotation::cur()); + let asset_x = meta.query_advice(advices[0], Rotation::next()); + let asset_y = meta.query_advice(advices[1], Rotation::next()); + let diff_asset_x_inv = meta.query_advice(advices[2], Rotation::next()); + let diff_asset_y_inv = meta.query_advice(advices[3], Rotation::next()); + + let one = Expression::Constant(pallas::Base::one()); + + let native_asset = AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap(); + + let diff_asset_x = asset_x - Expression::Constant(*native_asset.x()); + let diff_asset_y = asset_y - Expression::Constant(*native_asset.y()); + + let psi_old = meta.query_advice(advices[4], Rotation::next()); + let psi_nf = meta.query_advice(advices[5], Rotation::next()); + + let enable_zsa = meta.query_advice(advices[6], Rotation::next()); + + Constraints::with_selector( + q_orchard, + [ + ("bool_check split_flag", bool_check(split_flag.clone())), + ( + "v_old * (1 - split_flag) - v_new = magnitude * sign", + v_old.clone() * (one.clone() - split_flag.clone()) + - v_new.clone() + - magnitude * sign, + ), + // We already checked that + // * is_native_asset is boolean (just below), and + // * v_old is a 64 bit unsigned integer (in the note commitment evaluation). + // So, 1 - is_native_asset + v_old = 0 only when (is_native_asset = 1 and v_old = 0), no overflow can occur. + ( + "(v_old = 0 and is_native_asset = 1) or (root = anchor)", + (v_old.clone() + one.clone() - is_native_asset.clone()) * (root - anchor), + ), + ( + "v_old = 0 or enable_spends = 1", + v_old * (one.clone() - enable_spends), + ), + ( + "v_new = 0 or enable_outputs = 1", + v_new * (one.clone() - enable_outputs), + ), + ( + "bool_check is_native_asset", + bool_check(is_native_asset.clone()), + ), + ( + "(is_native_asset = 1) => (asset_x = native_asset_x)", + is_native_asset.clone() * diff_asset_x.clone(), + ), + ( + "(is_native_asset = 1) => (asset_y = native_asset_y)", + is_native_asset.clone() * diff_asset_y.clone(), + ), + // To prove that `asset` is not equal to `native_asset`, we will prove that at + // least one of `x(asset) - x(native_asset)` or `y(asset) - y(native_asset)` is + // not equal to zero. + // To prove that `x(asset) - x(native_asset)` (resp `y(asset) - y(native_asset)`) + // is not equal to zero, we will prove that it is invertible. + ( + "(is_native_asset = 0) => (asset != native_asset)", + (one.clone() - is_native_asset.clone()) + * (diff_asset_x * diff_asset_x_inv - one.clone()) + * (diff_asset_y * diff_asset_y_inv - one.clone()), + ), + ( + "(split_flag = 0) => (psi_old = psi_nf)", + (one.clone() - split_flag.clone()) * (psi_old - psi_nf), + ), + ( + "(split_flag = 1) => (is_native_asset = 0)", + split_flag * is_native_asset.clone(), + ), + ( + "(enable_zsa = 0) => (is_native_asset = 1)", + (one.clone() - enable_zsa) * (one - is_native_asset), + ), + ], + ) + }); + + // Addition of two field elements. + let add_config = AddChip::configure(meta, advices[7], advices[8], advices[6]); + + // Fixed columns for the Sinsemilla generator lookup table + let table_idx = meta.lookup_table_column(); + let table_range_check_tag = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + + // Instance column used for public inputs + let primary = meta.instance_column(); + meta.enable_equality(primary); + + // Permutation over all advice columns. + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + // Poseidon requires four advice columns, while ECC incomplete addition requires + // six, so we could choose to configure them in parallel. However, we only use a + // single Poseidon invocation, and we have the rows to accommodate it serially. + // Instead, we reduce the proof size by sharing fixed columns between the ECC and + // Poseidon chips. + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + let rc_a = lagrange_coeffs[2..5].try_into().unwrap(); + let rc_b = lagrange_coeffs[5..8].try_into().unwrap(); + + // Also use the first Lagrange coefficient column for loading global constants. + // It's free real estate :) + meta.enable_constant(lagrange_coeffs[0]); + + // We have a lot of free space in the right-most advice columns; use one of them + // for all of our range checks. + let range_check = LookupRangeCheck45BConfig::configure_with_tag( + meta, + advices[9], + table_idx, + table_range_check_tag, + ); + + // Configuration for curve point operations. + // This uses 10 advice columns and spans the whole circuit. + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + // Configuration for the Poseidon hash. + let poseidon_config = PoseidonChip::configure::( + meta, + // We place the state columns after the partial_sbox column so that the + // pad-and-add region can be laid out more efficiently. + advices[6..9].try_into().unwrap(), + advices[5], + rc_a, + rc_b, + ); + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_1, merkle_config_1) = { + let sinsemilla_config_1 = SinsemillaChip::configure( + meta, + advices[..5].try_into().unwrap(), + advices[6], + lagrange_coeffs[0], + lookup, + range_check, + true, + ); + let merkle_config_1 = MerkleChip::configure(meta, sinsemilla_config_1.clone()); + + (sinsemilla_config_1, merkle_config_1) + }; + + // Configuration for a Sinsemilla hash instantiation and a + // Merkle hash instantiation using this Sinsemilla instance. + // Since the Sinsemilla config uses only 5 advice columns, + // we can fit two instances side-by-side. + let (sinsemilla_config_2, merkle_config_2) = { + let sinsemilla_config_2 = SinsemillaChip::configure( + meta, + advices[5..].try_into().unwrap(), + advices[7], + lagrange_coeffs[1], + lookup, + range_check, + true, + ); + let merkle_config_2 = MerkleChip::configure(meta, sinsemilla_config_2.clone()); + + (sinsemilla_config_2, merkle_config_2) + }; + + // Configuration to handle decomposition and canonicity checking + // for CommitIvk. + let commit_ivk_config = CommitIvkChip::configure(meta, advices); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_old. + let old_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone()); + + // Configuration to handle decomposition and canonicity checking + // for NoteCommit_new. + let new_note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); + + let cond_swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); + + Config { + primary, + q_orchard, + advices, + add_config, + ecc_config, + poseidon_config, + merkle_config_1, + merkle_config_2, + sinsemilla_config_1, + sinsemilla_config_2, + commit_ivk_config, + old_note_commit_config, + new_note_commit_config, + cond_swap_config, + } + } + + #[allow(non_snake_case)] + fn synthesize( + circuit: &Circuit, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), plonk::Error> { + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::load(config.sinsemilla_config_1.clone(), &mut layouter)?; + + // Construct the ECC chip. + let ecc_chip = config.ecc_chip(); + + // Witness private inputs that are used across multiple checks. + let (psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset) = { + // Witness psi_nf + let psi_nf = assign_free_advice( + layouter.namespace(|| "witness psi_nf"), + config.advices[0], + circuit.psi_nf, + )?; + + // Witness psi_old + let psi_old = assign_free_advice( + layouter.namespace(|| "witness psi_old"), + config.advices[0], + circuit.psi_old, + )?; + + // Witness rho_old + let rho_old = assign_free_advice( + layouter.namespace(|| "witness rho_old"), + config.advices[0], + circuit.rho_old.map(|rho| rho.into_inner()), + )?; + + // Witness cm_old + let cm_old = Point::new( + ecc_chip.clone(), + layouter.namespace(|| "cm_old"), + circuit.cm_old.as_ref().map(|cm| cm.inner().to_affine()), + )?; + + // Witness g_d_old + let g_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "gd_old"), + circuit.g_d_old.as_ref().map(|gd| gd.to_affine()), + )?; + + // Witness ak_P. + let ak_P: Value = circuit.ak.as_ref().map(|ak| ak.into()); + let ak_P = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness ak_P"), + ak_P.map(|ak_P| ak_P.to_affine()), + )?; + + // Witness nk. + let nk = assign_free_advice( + layouter.namespace(|| "witness nk"), + config.advices[0], + circuit.nk.map(|nk| nk.inner()), + )?; + + // Witness v_old. + let v_old = assign_free_advice( + layouter.namespace(|| "witness v_old"), + config.advices[0], + circuit.v_old, + )?; + + // Witness v_new. + let v_new = assign_free_advice( + layouter.namespace(|| "witness v_new"), + config.advices[0], + circuit.v_new, + )?; + + // Witness asset + let asset = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness asset"), + circuit.asset.map(|asset| asset.cv_base().to_affine()), + )?; + + ( + psi_nf, psi_old, rho_old, cm_old, g_d_old, ak_P, nk, v_old, v_new, asset, + ) + }; + + // Witness split_flag + let split_flag = assign_split_flag( + layouter.namespace(|| "witness split_flag"), + config.advices[0], + circuit.split_flag, + )?; + + // Witness is_native_asset which is equal to + // 1 if asset is equal to native asset, and + // 0 if asset is not equal to native asset. + let is_native_asset = assign_is_native_asset( + layouter.namespace(|| "witness is_native_asset"), + config.advices[0], + circuit.asset, + )?; + + // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + let root = { + let path = circuit + .path + .map(|typed_path| typed_path.map(|node| node.inner())); + let merkle_inputs = MerklePath::construct( + [config.merkle_chip_1(), config.merkle_chip_2()], + OrchardHashDomains::MerkleCrh, + circuit.pos, + path, + ); + let leaf = cm_old.extract_p().inner().clone(); + merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? + }; + + // Value commitment integrity (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + let v_net_magnitude_sign = { + // Witness the magnitude and sign of v_net = v_old - v_new + let v_net_magnitude_sign = { + // v_net is equal to + // (-v_new) if split_flag = true + // v_old - v_new if split_flag = false + let v_net = circuit.split_flag.and_then(|split_flag| { + if split_flag { + Value::known(crate::value::NoteValue::zero()) - circuit.v_new + } else { + circuit.v_old - circuit.v_new + } + }); + + let magnitude_sign = v_net.map(|v_net| { + let (magnitude, sign) = v_net.magnitude_sign(); + + ( + // magnitude is guaranteed to be an unsigned 64-bit value. + // Therefore, we can move it into the base field. + pallas::Base::from(magnitude), + match sign { + crate::value::Sign::Positive => pallas::Base::one(), + crate::value::Sign::Negative => -pallas::Base::one(), + }, + ) + }); + + let magnitude = assign_free_advice( + layouter.namespace(|| "v_net magnitude"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.0), + )?; + let sign = assign_free_advice( + layouter.namespace(|| "v_net sign"), + config.advices[9], + magnitude_sign.map(|m_s| m_s.1), + )?; + (magnitude, sign) + }; + + let rcv = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcv"), + circuit.rcv.as_ref().map(|rcv| rcv.inner()), + )?; + + let cv_net = gadget::value_commit_orchard( + layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"), + config.sinsemilla_chip_1(), + ecc_chip.clone(), + v_net_magnitude_sign.clone(), + rcv, + asset.clone(), + )?; + + // Constrain cv_net to equal public input + layouter.constrain_instance(cv_net.inner().x().cell(), config.primary, CV_NET_X)?; + layouter.constrain_instance(cv_net.inner().y().cell(), config.primary, CV_NET_Y)?; + + // Return the magnitude and sign so we can use them in the Orchard gate. + v_net_magnitude_sign + }; + + // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). + let nf_old = { + let nf_old = gadget::derive_nullifier( + layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), + config.poseidon_chip(), + config.add_chip(), + ecc_chip.clone(), + config.cond_swap_chip(), + rho_old.clone(), + &psi_nf, + &cm_old, + nk.clone(), + split_flag.clone(), + )?; + + // Constrain nf_old to equal public input + layouter.constrain_instance(nf_old.inner().cell(), config.primary, NF_OLD)?; + + nf_old + }; + + // Spend authority (https://p.z.cash/ZKS:action-spend-authority) + { + let alpha = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "alpha"), + circuit.alpha, + )?; + + // alpha_commitment = [alpha] SpendAuthG + let (alpha_commitment, _) = { + let spend_auth_g = OrchardFixedBasesFull::SpendAuthG; + let spend_auth_g = FixedPoint::from_inner(ecc_chip.clone(), spend_auth_g); + spend_auth_g.mul(layouter.namespace(|| "[alpha] SpendAuthG"), alpha)? + }; + + // [alpha] SpendAuthG + ak_P + let rk = alpha_commitment.add(layouter.namespace(|| "rk"), &ak_P)?; + + // Constrain rk to equal public input + layouter.constrain_instance(rk.inner().x().cell(), config.primary, RK_X)?; + layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; + } + + // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). + let pk_d_old = { + let ivk = { + let ak = ak_P.extract_p().inner().clone(); + let rivk = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + circuit.rivk.map(|rivk| rivk.inner()), + )?; + + gadget::commit_ivk( + config.sinsemilla_chip_1(), + ecc_chip.clone(), + config.commit_ivk_chip(), + layouter.namespace(|| "CommitIvk"), + ak, + nk, + rivk, + )? + }; + let ivk = + ScalarVar::from_base(ecc_chip.clone(), layouter.namespace(|| "ivk"), ivk.inner())?; + + // [ivk] g_d_old + // The scalar value is passed through and discarded. + let (derived_pk_d_old, _ivk) = + g_d_old.mul(layouter.namespace(|| "[ivk] g_d_old"), ivk)?; + + // Constrain derived pk_d_old to equal witnessed pk_d_old + // + // This equality constraint is technically superfluous, because the assigned + // value of `derived_pk_d_old` is an equivalent witness. But it's nice to see + // an explicit connection between circuit-synthesized values, and explicit + // prover witnesses. We could get the best of both worlds with a write-on-copy + // abstraction (https://github.com/zcash/halo2/issues/334). + let pk_d_old = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_old"), + circuit + .pk_d_old + .map(|pk_d_old| pk_d_old.inner().to_affine()), + )?; + derived_pk_d_old + .constrain_equal(layouter.namespace(|| "pk_d_old equality"), &pk_d_old)?; + + pk_d_old + }; + + // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). + { + let rcm_old = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm_old"), + circuit.rcm_old.as_ref().map(|rcm_old| rcm_old.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let derived_cm_old = gadget::note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_1(), + config.ecc_chip(), + config.note_commit_chip_old(), + config.cond_swap_chip(), + g_d_old.inner(), + pk_d_old.inner(), + v_old.clone(), + rho_old, + psi_old.clone(), + asset.inner(), + rcm_old, + is_native_asset.clone(), + )?; + + // Constrain derived cm_old to equal witnessed cm_old + derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; + } + + // New note commitment integrity (https://p.z.cash/ZKS:action-cmx-new-integrity?partial). + { + // Witness g_d_new + let g_d_new = { + let g_d_new = circuit.g_d_new.map(|g_d_new| g_d_new.to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d_new_star"), + g_d_new, + )? + }; + + // Witness pk_d_new + let pk_d_new = { + let pk_d_new = circuit + .pk_d_new + .map(|pk_d_new| pk_d_new.inner().to_affine()); + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d_new"), + pk_d_new, + )? + }; + + // ρ^new = nf^old + let rho_new = nf_old.inner().clone(); + + // Witness psi_new + let psi_new = assign_free_advice( + layouter.namespace(|| "witness psi_new"), + config.advices[0], + circuit.psi_new, + )?; + + let rcm_new = ScalarFixed::new( + ecc_chip, + layouter.namespace(|| "rcm_new"), + circuit.rcm_new.as_ref().map(|rcm_new| rcm_new.inner()), + )?; + + // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) + let cm_new = gadget::note_commit( + layouter.namespace(|| { + "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" + }), + config.sinsemilla_chip_2(), + config.ecc_chip(), + config.note_commit_chip_new(), + config.cond_swap_chip(), + g_d_new.inner(), + pk_d_new.inner(), + v_new.clone(), + rho_new, + psi_new, + asset.inner(), + rcm_new, + is_native_asset.clone(), + )?; + + let cmx = cm_new.extract_p(); + + // Constrain cmx to equal public input + layouter.constrain_instance(cmx.inner().cell(), config.primary, CMX)?; + } + + // Constrain the remaining Orchard circuit checks. + layouter.assign_region( + || "Orchard circuit checks", + |mut region| { + v_old.copy_advice(|| "v_old", &mut region, config.advices[0], 0)?; + v_new.copy_advice(|| "v_new", &mut region, config.advices[1], 0)?; + v_net_magnitude_sign.0.copy_advice( + || "v_net magnitude", + &mut region, + config.advices[2], + 0, + )?; + v_net_magnitude_sign.1.copy_advice( + || "v_net sign", + &mut region, + config.advices[3], + 0, + )?; + + root.copy_advice(|| "calculated root", &mut region, config.advices[4], 0)?; + region.assign_advice_from_instance( + || "pub input anchor", + config.primary, + ANCHOR, + config.advices[5], + 0, + )?; + + region.assign_advice_from_instance( + || "enable spends", + config.primary, + ENABLE_SPEND, + config.advices[6], + 0, + )?; + + region.assign_advice_from_instance( + || "enable outputs", + config.primary, + ENABLE_OUTPUT, + config.advices[7], + 0, + )?; + + split_flag.copy_advice(|| "split_flag", &mut region, config.advices[8], 0)?; + + is_native_asset.copy_advice( + || "is_native_asset", + &mut region, + config.advices[9], + 0, + )?; + asset + .inner() + .x() + .copy_advice(|| "asset_x", &mut region, config.advices[0], 1)?; + asset + .inner() + .y() + .copy_advice(|| "asset_y", &mut region, config.advices[1], 1)?; + + // `diff_asset_x_inv` and `diff_asset_y_inv` will be used to prove that + // if is_native_asset = 0, then asset != native_asset. + region.assign_advice( + || "diff_asset_x_inv", + config.advices[2], + 1, + || { + circuit.asset.map(|asset| { + let asset_x = *asset.cv_base().to_affine().coordinates().unwrap().x(); + let native_asset_x = *AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap() + .x(); + + let diff_asset_x = asset_x - native_asset_x; + + if diff_asset_x == pallas::Base::zero() { + pallas::Base::zero() + } else { + diff_asset_x.invert().unwrap() + } + }) + }, + )?; + region.assign_advice( + || "diff_asset_y_inv", + config.advices[3], + 1, + || { + circuit.asset.map(|asset| { + let asset_y = *asset.cv_base().to_affine().coordinates().unwrap().y(); + let native_asset_y = *AssetBase::native() + .cv_base() + .to_affine() + .coordinates() + .unwrap() + .y(); + + let diff_asset_y = asset_y - native_asset_y; + + if diff_asset_y == pallas::Base::zero() { + pallas::Base::zero() + } else { + diff_asset_y.invert().unwrap() + } + }) + }, + )?; + + psi_old.copy_advice(|| "psi_old", &mut region, config.advices[4], 1)?; + psi_nf.copy_advice(|| "psi_nf", &mut region, config.advices[5], 1)?; + + region.assign_advice_from_instance( + || "enable zsa", + config.primary, + ENABLE_ZSA, + config.advices[6], + 1, + )?; + + config.q_orchard.enable(&mut region, 0) + }, + )?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use core::iter; + + use ff::Field; + use group::{Curve, Group, GroupEncoding}; + use halo2_proofs::{circuit::Value, dev::MockProver}; + use pasta_curves::pallas; + use rand::{rngs::OsRng, RngCore}; + + use crate::{ + builder::SpendInfo, + bundle::Flags, + circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}, + keys::{FullViewingKey, Scope, SpendValidatingKey, SpendingKey}, + note::{commitment::NoteCommitTrapdoor, AssetBase, Note, NoteCommitment, Nullifier, Rho}, + orchard_flavor::OrchardZSA, + primitives::redpallas::VerificationKey, + tree::MerklePath, + value::{NoteValue, ValueCommitTrapdoor, ValueCommitment}, + }; + + type OrchardCircuitZSA = Circuit; + + fn generate_dummy_circuit_instance(mut rng: R) -> (OrchardCircuitZSA, Instance) { + let (_, fvk, spent_note) = Note::dummy(&mut rng, None, AssetBase::native()); + + let sender_address = spent_note.recipient(); + let nk = *fvk.nk(); + let rivk = fvk.rivk(fvk.scope_for_address(&spent_note.recipient()).unwrap()); + let nf_old = spent_note.nullifier(&fvk); + let rho = Rho::from_nf_old(nf_old); + let ak: SpendValidatingKey = fvk.into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let (_, _, output_note) = Note::dummy(&mut rng, Some(rho), AssetBase::native()); + let cmx = output_note.commitment().into(); + + let value = spent_note.value() - output_note.value(); + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(value, rcv, AssetBase::native()); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let psi_old = spent_note.rseed().psi(&spent_note.rho()); + + ( + OrchardCircuitZSA { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(psi_old), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + phantom: std::marker::PhantomData, + }, + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + enable_zsa: false, + }, + ) + } + + // TODO: recast as a proptest + #[test] + fn round_trip() { + let mut rng = OsRng; + + let (circuits, instances): (Vec<_>, Vec<_>) = iter::once(()) + .map(|()| generate_dummy_circuit_instance(&mut rng)) + .unzip(); + + let vk = VerifyingKey::build::(); + + // Test that the pinned verification key (representing the circuit) + // is as expected. + { + // panic!("{:#?}", vk.vk.pinned()); + assert_eq!( + format!("{:#?}\n", vk.vk.pinned()), + include_str!("circuit_description_zsa").replace("\r\n", "\n") + ); + } + + // Test that the proof size is as expected. + let expected_proof_size = { + let circuit_cost = + halo2_proofs::dev::CircuitCost::::measure( + K, + &circuits[0], + ); + assert_eq!(usize::from(circuit_cost.proof_size(1)), 5120); + assert_eq!(usize::from(circuit_cost.proof_size(2)), 7392); + usize::from(circuit_cost.proof_size(instances.len())) + }; + + for (circuit, instance) in circuits.iter().zip(instances.iter()) { + assert_eq!( + MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect() + ) + .unwrap() + .verify(), + Ok(()) + ); + } + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &circuits, &instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, &instances).is_ok()); + assert_eq!(proof.0.len(), expected_proof_size); + } + + #[test] + fn serialized_proof_test_case() { + use std::fs; + use std::io::{Read, Write}; + + let vk = VerifyingKey::build::(); + + fn write_test_case( + mut w: W, + instance: &Instance, + proof: &Proof, + ) -> std::io::Result<()> { + w.write_all(&instance.anchor.to_bytes())?; + w.write_all(&instance.cv_net.to_bytes())?; + w.write_all(&instance.nf_old.to_bytes())?; + w.write_all(&<[u8; 32]>::from(instance.rk.clone()))?; + w.write_all(&instance.cmx.to_bytes())?; + w.write_all(&[ + u8::from(instance.enable_spend), + u8::from(instance.enable_output), + u8::from(instance.enable_zsa), + ])?; + + w.write_all(proof.as_ref())?; + Ok(()) + } + + fn read_test_case(mut r: R) -> std::io::Result<(Instance, Proof)> { + let read_32_bytes = |r: &mut R| { + let mut ret = [0u8; 32]; + r.read_exact(&mut ret).unwrap(); + ret + }; + let read_bool = |r: &mut R| { + let mut byte = [0u8; 1]; + r.read_exact(&mut byte).unwrap(); + match byte { + [0] => false, + [1] => true, + _ => panic!("Unexpected non-boolean byte"), + } + }; + + let anchor = crate::Anchor::from_bytes(read_32_bytes(&mut r)).unwrap(); + let cv_net = ValueCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let nf_old = crate::note::Nullifier::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let rk = read_32_bytes(&mut r).try_into().unwrap(); + let cmx = + crate::note::ExtractedNoteCommitment::from_bytes(&read_32_bytes(&mut r)).unwrap(); + let enable_spend = read_bool(&mut r); + let enable_output = read_bool(&mut r); + let enable_zsa = read_bool(&mut r); + let instance = Instance::from_parts( + anchor, + cv_net, + nf_old, + rk, + cmx, + Flags::from_parts(enable_spend, enable_output, enable_zsa), + ); + + let mut proof_bytes = vec![]; + r.read_to_end(&mut proof_bytes)?; + let proof = Proof::new(proof_bytes); + + Ok((instance, proof)) + } + + if std::env::var_os("ORCHARD_CIRCUIT_TEST_GENERATE_NEW_PROOF").is_some() { + let create_proof = || -> std::io::Result<()> { + let mut rng = OsRng; + + let (circuit, instance) = generate_dummy_circuit_instance(OsRng); + let instances = &[instance.clone()]; + + let pk = ProvingKey::build::(); + let proof = Proof::create(&pk, &[circuit], instances, &mut rng).unwrap(); + assert!(proof.verify(&vk, instances).is_ok()); + + let file = std::fs::File::create("src/circuit/circuit_proof_test_case_zsa.bin")?; + write_test_case(file, &instance, &proof) + }; + create_proof().expect("should be able to write new proof"); + } + + // Parse the hardcoded proof test case. + let (instance, proof) = { + let test_case_bytes = fs::read("src/circuit/circuit_proof_test_case_zsa.bin").unwrap(); + read_test_case(&test_case_bytes[..]).expect("proof must be valid") + }; + assert_eq!(proof.0.len(), 5120); + + assert!(proof.verify(&vk, &[instance]).is_ok()); + } + + #[cfg(feature = "dev-graph")] + #[test] + fn print_action_circuit() { + use plotters::prelude::*; + + let root = BitMapBackend::new("action-circuit-layout.png", (1024, 768)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root + .titled("Orchard Action Circuit", ("sans-serif", 60)) + .unwrap(); + + let circuit = OrchardCircuitZSA { + path: Value::unknown(), + pos: Value::unknown(), + g_d_old: Value::unknown(), + pk_d_old: Value::unknown(), + v_old: Value::unknown(), + rho_old: Value::unknown(), + psi_old: Value::unknown(), + rcm_old: Value::unknown(), + cm_old: Value::unknown(), + psi_nf: Value::unknown(), + alpha: Value::unknown(), + ak: Value::unknown(), + nk: Value::unknown(), + rivk: Value::unknown(), + g_d_new: Value::unknown(), + pk_d_new: Value::unknown(), + v_new: Value::unknown(), + psi_new: Value::unknown(), + rcm_new: Value::unknown(), + rcv: Value::unknown(), + asset: Value::unknown(), + split_flag: Value::unknown(), + phantom: std::marker::PhantomData, + }; + halo2_proofs::dev::CircuitLayout::default() + .show_labels(false) + .view_height(0..(1 << 11)) + .render(K, &circuit, &root) + .unwrap(); + } + + fn check_proof_of_orchard_circuit( + circuit: &OrchardCircuitZSA, + instance: &Instance, + should_pass: bool, + ) { + let proof_verify = MockProver::run( + K, + circuit, + instance + .to_halo2_instance() + .iter() + .map(|p| p.to_vec()) + .collect(), + ) + .unwrap() + .verify(); + if should_pass { + assert!(proof_verify.is_ok()); + } else { + assert!(proof_verify.is_err()); + } + } + + fn generate_circuit_instance( + is_native_asset: bool, + split_flag: bool, + mut rng: R, + ) -> (OrchardCircuitZSA, Instance) { + // Create asset + let asset_base = if is_native_asset { + AssetBase::native() + } else { + AssetBase::random() + }; + + // Create spent_note + let (spent_note_fvk, spent_note) = { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + let sender_address = fvk.address_at(0u32, Scope::External); + let nf_old = Nullifier::dummy(&mut rng); + let rho = Rho::from_nf_old(nf_old); + let note = Note::new( + sender_address, + NoteValue::from_raw(40), + asset_base, + rho, + &mut rng, + ); + let spent_note = if split_flag { + note.create_split_note(&mut rng) + } else { + note + }; + (fvk, spent_note) + }; + + let output_value = NoteValue::from_raw(10); + + let (scope, v_net) = if split_flag { + ( + Scope::External, + // Split notes do not contribute to v_net. + // Therefore, if split_flag is true, v_net = - output_value + NoteValue::zero() - output_value, + ) + } else { + ( + spent_note_fvk + .scope_for_address(&spent_note.recipient()) + .unwrap(), + spent_note.value() - output_value, + ) + }; + + let nf_old = spent_note.nullifier(&spent_note_fvk); + let rho = Rho::from_nf_old(nf_old); + let ak: SpendValidatingKey = spent_note_fvk.clone().into(); + let alpha = pallas::Scalar::random(&mut rng); + let rk = ak.randomize(&alpha); + + let output_note = { + let sk = SpendingKey::random(&mut rng); + let fvk: FullViewingKey = (&sk).into(); + let sender_address = fvk.address_at(0u32, Scope::External); + + Note::new(sender_address, output_value, asset_base, rho, &mut rng) + }; + + let cmx = output_note.commitment().into(); + + let rcv = ValueCommitTrapdoor::random(&mut rng); + let cv_net = ValueCommitment::derive(v_net, rcv, asset_base); + + let path = MerklePath::dummy(&mut rng); + let anchor = path.root(spent_note.commitment().into()); + + let spend_info = SpendInfo { + dummy_sk: None, + fvk: spent_note_fvk, + scope, + note: spent_note, + merkle_path: path, + split_flag, + }; + + ( + OrchardCircuitZSA::from_action_context_unchecked(spend_info, output_note, alpha, rcv), + Instance { + anchor, + cv_net, + nf_old, + rk, + cmx, + enable_spend: true, + enable_output: true, + enable_zsa: true, + }, + ) + } + + fn random_note_commitment(mut rng: impl RngCore) -> NoteCommitment { + NoteCommitment::derive( + pallas::Point::random(&mut rng).to_affine().to_bytes(), + pallas::Point::random(&mut rng).to_affine().to_bytes(), + NoteValue::from_raw(rng.next_u64()), + AssetBase::random(), + pallas::Base::random(&mut rng), + pallas::Base::random(&mut rng), + NoteCommitTrapdoor(pallas::Scalar::random(&mut rng)), + ) + .unwrap() + } + + #[test] + fn orchard_circuit_negative_test() { + let mut rng = OsRng; + + for is_native_asset in [true, false] { + for split_flag in [true, false] { + let (circuit, instance) = + generate_circuit_instance(is_native_asset, split_flag, &mut rng); + + let should_pass = !(matches!((is_native_asset, split_flag), (true, true))); + + check_proof_of_orchard_circuit(&circuit, &instance, should_pass); + + // Set cv_net to be zero + // The proof should fail + let instance_wrong_cv_net = Instance { + anchor: instance.anchor, + cv_net: ValueCommitment::from_bytes(&[0u8; 32]).unwrap(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_cv_net, false); + + // Set rk_pub to be a dummy VerificationKey + // The proof should fail + let instance_wrong_rk = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: VerificationKey::dummy(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_rk, false); + + // Set cm_old to be a random NoteCommitment + // The proof should fail + let circuit_wrong_cm_old = OrchardCircuitZSA { + path: circuit.path, + pos: circuit.pos, + g_d_old: circuit.g_d_old, + pk_d_old: circuit.pk_d_old, + v_old: circuit.v_old, + rho_old: circuit.rho_old, + psi_old: circuit.psi_old, + rcm_old: circuit.rcm_old.clone(), + cm_old: Value::known(random_note_commitment(&mut rng)), + psi_nf: circuit.psi_nf, + alpha: circuit.alpha, + ak: circuit.ak.clone(), + nk: circuit.nk, + rivk: circuit.rivk, + g_d_new: circuit.g_d_new, + pk_d_new: circuit.pk_d_new, + v_new: circuit.v_new, + psi_new: circuit.psi_new, + rcm_new: circuit.rcm_new.clone(), + rcv: circuit.rcv, + asset: circuit.asset, + split_flag: circuit.split_flag, + phantom: std::marker::PhantomData, + }; + check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); + + // Set cmx_pub to be a random NoteCommitment + // The proof should fail + let instance_wrong_cmx_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: random_note_commitment(&mut rng).into(), + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_cmx_pub, false); + + // Set nf_old_pub to be a random Nullifier + // The proof should fail + let instance_wrong_nf_old_pub = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: Nullifier::dummy(&mut rng), + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: instance.enable_zsa, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_nf_old_pub, false); + + // If split_flag = 0 , set psi_nf to be a random Pallas base element + // The proof should fail + if !split_flag { + let circuit_wrong_psi_nf = OrchardCircuitZSA { + path: circuit.path, + pos: circuit.pos, + g_d_old: circuit.g_d_old, + pk_d_old: circuit.pk_d_old, + v_old: circuit.v_old, + rho_old: circuit.rho_old, + psi_old: circuit.psi_old, + rcm_old: circuit.rcm_old.clone(), + cm_old: circuit.cm_old.clone(), + psi_nf: Value::known(pallas::Base::random(&mut rng)), + alpha: circuit.alpha, + ak: circuit.ak.clone(), + nk: circuit.nk, + rivk: circuit.rivk, + g_d_new: circuit.g_d_new, + pk_d_new: circuit.pk_d_new, + v_new: circuit.v_new, + psi_new: circuit.psi_new, + rcm_new: circuit.rcm_new.clone(), + rcv: circuit.rcv, + asset: circuit.asset, + split_flag: circuit.split_flag, + phantom: std::marker::PhantomData, + }; + check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false); + } + + // If asset is not equal to the native asset, set enable_zsa = 0 + // The proof should fail + if !is_native_asset { + let instance_wrong_enable_zsa = Instance { + anchor: instance.anchor, + cv_net: instance.cv_net.clone(), + nf_old: instance.nf_old, + rk: instance.rk.clone(), + cmx: instance.cmx, + enable_spend: instance.enable_spend, + enable_output: instance.enable_output, + enable_zsa: false, + }; + check_proof_of_orchard_circuit(&circuit, &instance_wrong_enable_zsa, false); + } + } + } + } +} diff --git a/src/circuit/circuit_zsa/gadget.rs b/src/circuit/circuit_zsa/gadget.rs new file mode 100644 index 000000000..9919dc682 --- /dev/null +++ b/src/circuit/circuit_zsa/gadget.rs @@ -0,0 +1,245 @@ +//! Gadgets used in the Orchard circuit (ZSA variation). + +use ff::Field; +use group::Curve; +use pasta_curves::arithmetic::CurveExt; +use pasta_curves::pallas; + +use super::{add_chip, commit_ivk::CommitIvkChip, note_commit::NoteCommitChip, AddInstruction}; +use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; +use crate::note::AssetBase; +use halo2_gadgets::{ + ecc::{chip::EccChip, chip::EccPoint, EccInstructions, FixedPointBaseField, Point, X}, + poseidon::{ + primitives::{self as poseidon, ConstantLength}, + Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, + }, + sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, + utilities::{cond_swap::CondSwapChip, lookup_range_check::PallasLookupRangeCheck45BConfig}, +}; +use halo2_proofs::{ + circuit::{AssignedCell, Layouter, Value}, + plonk::{self, Advice, Assigned, Column}, +}; + +impl super::Config { + pub(super) fn add_chip(&self) -> add_chip::AddChip { + add_chip::AddChip::construct(self.add_config.clone()) + } + + pub(super) fn commit_ivk_chip(&self) -> CommitIvkChip { + CommitIvkChip::construct(self.commit_ivk_config.clone()) + } + + pub(super) fn ecc_chip(&self) -> EccChip { + EccChip::construct(self.ecc_config.clone()) + } + + pub(super) fn sinsemilla_chip_1( + &self, + ) -> SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + > { + SinsemillaChip::construct(self.sinsemilla_config_1.clone()) + } + + pub(super) fn sinsemilla_chip_2( + &self, + ) -> SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + > { + SinsemillaChip::construct(self.sinsemilla_config_2.clone()) + } + + pub(super) fn merkle_chip_1( + &self, + ) -> MerkleChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + > { + MerkleChip::construct(self.merkle_config_1.clone()) + } + + pub(super) fn merkle_chip_2( + &self, + ) -> MerkleChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + > { + MerkleChip::construct(self.merkle_config_2.clone()) + } + + pub(super) fn poseidon_chip(&self) -> PoseidonChip { + PoseidonChip::construct(self.poseidon_config.clone()) + } + + pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { + NoteCommitChip::construct(self.new_note_commit_config.clone()) + } + + pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { + NoteCommitChip::construct(self.old_note_commit_config.clone()) + } + + pub(super) fn cond_swap_chip(&self) -> CondSwapChip { + CondSwapChip::construct(self.cond_swap_config.clone()) + } +} + +/// Witnesses the given value in a standalone region. +/// +/// Usages of this helper are technically superfluous, as the single-cell region is only +/// ever used in equality constraints. We could eliminate them with a +/// [write-on-copy abstraction](https://github.com/zcash/halo2/issues/334). +pub(in crate::circuit) fn assign_free_advice( + mut layouter: impl Layouter, + column: Column, + value: Value, +) -> Result, plonk::Error> +where + for<'v> Assigned: From<&'v V>, +{ + layouter.assign_region( + || "load private", + |mut region| region.assign_advice(|| "load private", column, 0, || value), + ) +} + +/// Witnesses is_native_asset. +pub(in crate::circuit) fn assign_is_native_asset( + layouter: impl Layouter, + column: Column, + asset: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + asset.map(|asset| { + if bool::from(asset.is_native()) { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) +} + +/// Witnesses split_flag. +pub(in crate::circuit) fn assign_split_flag( + layouter: impl Layouter, + column: Column, + split_flag: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + split_flag.map(|split_flag| { + if split_flag { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) +} + +/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. +/// +/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers +#[allow(clippy::too_many_arguments)] +pub(in crate::circuit) fn derive_nullifier< + PoseidonChip: PoseidonSpongeInstructions, 3, 2>, + AddChip: AddInstruction, + EccChip: EccInstructions< + pallas::Affine, + FixedPoints = OrchardFixedBases, + Point = EccPoint, + Var = AssignedCell, + >, +>( + mut layouter: impl Layouter, + poseidon_chip: PoseidonChip, + add_chip: AddChip, + ecc_chip: EccChip, + cond_swap_chip: CondSwapChip, + rho: AssignedCell, + psi: &AssignedCell, + cm: &Point, + nk: AssignedCell, + split_flag: AssignedCell, +) -> Result, plonk::Error> { + // hash = poseidon_hash(nk, rho) + let hash = { + let poseidon_message = [nk, rho]; + let poseidon_hasher = + PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; + poseidon_hasher.hash( + layouter.namespace(|| "Poseidon hash (nk, rho)"), + poseidon_message, + )? + }; + + // Add hash output to psi. + // `scalar` = poseidon_hash(nk, rho) + psi. + let scalar = add_chip.add( + layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), + &hash, + psi, + )?; + + // Multiply scalar by NullifierK + // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. + // + let product = { + let nullifier_k = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK); + nullifier_k.mul( + layouter.namespace(|| "[poseidon_output + psi] NullifierK"), + scalar, + )? + }; + + // Add cm to multiplied fixed base + // nf = cm + [poseidon_output + psi] NullifierK + let nf = cm.add(layouter.namespace(|| "nf"), &product)?; + + // Add NullifierL to nf + // split_note_nf = NullifierL + nf + let nullifier_l = Point::new_from_constant( + ecc_chip.clone(), + layouter.namespace(|| "witness NullifierL constant"), + pallas::Point::hash_to_curve("z.cash:Orchard")(b"L").to_affine(), + )?; + let split_note_nf = nullifier_l.add(layouter.namespace(|| "split_note_nf"), &nf)?; + + // Select the desired nullifier according to split_flag + Ok(Point::from_inner( + ecc_chip, + cond_swap_chip.mux_on_points( + layouter.namespace(|| "mux on nf"), + &split_flag, + nf.inner(), + split_note_nf.inner(), + )?, + ) + .extract_p()) +} + +pub(in crate::circuit) use super::commit_ivk::gadgets::commit_ivk; +pub(in crate::circuit) use super::note_commit::gadgets::note_commit; +pub(in crate::circuit) use super::value_commit_orchard::gadgets::value_commit_orchard; diff --git a/src/circuit/note_commit.rs b/src/circuit/circuit_zsa/note_commit.rs similarity index 96% rename from src/circuit/note_commit.rs rename to src/circuit/circuit_zsa/note_commit.rs index 47d928fc0..4f9a6a86a 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/circuit_zsa/note_commit.rs @@ -1,3 +1,5 @@ +//! Note commitment logic for the Orchard circuit (ZSA variation). + use core::iter; use group::ff::PrimeField; @@ -22,14 +24,21 @@ use halo2_gadgets::{ CommitDomain, Message, MessagePiece, }, utilities::{ - bool_check, cond_swap::CondSwapChip, lookup_range_check::LookupRangeCheckConfig, + bool_check, + cond_swap::CondSwapChip, + lookup_range_check::{LookupRangeCheck, PallasLookupRangeCheck45BConfig}, FieldValue, RangeConstrained, }, }; type NoteCommitPiece = MessagePiece< pallas::Affine, - SinsemillaChip, + SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, 10, 253, >; @@ -121,8 +130,13 @@ impl DecomposeB { #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &PallasLookupRangeCheck45BConfig, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, layouter: &mut impl Layouter, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, @@ -266,8 +280,13 @@ impl DecomposeD { #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &PallasLookupRangeCheck45BConfig, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, layouter: &mut impl Layouter, pk_d: &NonIdentityEccPoint, value: &AssignedCell, @@ -388,8 +407,13 @@ impl DecomposeE { #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &PallasLookupRangeCheck45BConfig, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, layouter: &mut impl Layouter, value: &AssignedCell, rho: &AssignedCell, @@ -513,8 +537,13 @@ impl DecomposeG { #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &PallasLookupRangeCheck45BConfig, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, layouter: &mut impl Layouter, rho: &AssignedCell, psi: &AssignedCell, @@ -649,8 +678,13 @@ impl DecomposeH { #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &LookupRangeCheckConfig, - chip: SinsemillaChip, + lookup_config: &PallasLookupRangeCheck45BConfig, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, layouter: &mut impl Layouter, psi: &AssignedCell, asset: &NonIdentityEccPoint, @@ -798,7 +832,12 @@ impl DecomposeJ { #[allow(clippy::type_complexity)] fn decompose( - chip: SinsemillaChip, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, layouter: &mut impl Layouter, asset: &NonIdentityEccPoint, ) -> Result< @@ -1594,8 +1633,12 @@ pub struct NoteCommitConfig { psi: PsiCanonicity, y_canon: YCanonicity, advices: [Column; 10], - sinsemilla_config: - SinsemillaConfig, + sinsemilla_config: SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, } #[derive(Clone, Debug)] @@ -1613,6 +1656,7 @@ impl NoteCommitChip { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, + PallasLookupRangeCheck45BConfig, >, ) -> NoteCommitConfig { // Useful constants @@ -1742,8 +1786,13 @@ pub(in crate::circuit) mod gadgets { #[allow(clippy::too_many_arguments)] pub(in crate::circuit) fn note_commit( mut layouter: impl Layouter, - chip: SinsemillaChip, - ecc_chip: EccChip, + chip: SinsemillaChip< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, + ecc_chip: EccChip, note_commit_chip: NoteCommitChip, cond_swap_chip: CondSwapChip, g_d: &NonIdentityEccPoint, @@ -1752,9 +1801,15 @@ pub(in crate::circuit) mod gadgets { rho: AssignedCell, psi: AssignedCell, asset: &NonIdentityEccPoint, - rcm: ScalarFixed>, + rcm: ScalarFixed< + pallas::Affine, + EccChip, + >, is_native_asset: AssignedCell, - ) -> Result>, Error> { + ) -> Result< + Point>, + Error, + > { let lookup_config = chip.config().lookup_config(); // `a` = bits 0..=249 of `x(g_d)` @@ -2088,7 +2143,7 @@ pub(in crate::circuit) mod gadgets { /// - [`g_d` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-g_d?partial) /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) fn canon_bitshift_130( - lookup_config: &LookupRangeCheckConfig, + lookup_config: &PallasLookupRangeCheck45BConfig, mut layouter: impl Layouter, a: AssignedCell, ) -> Result { @@ -2122,7 +2177,7 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-pk_d?partial). fn pkd_asset_x_canonicity( - lookup_config: &LookupRangeCheckConfig, + lookup_config: &PallasLookupRangeCheck45BConfig, mut layouter: impl Layouter, b_3: RangeConstrained>, c: AssignedCell, @@ -2165,7 +2220,7 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-rho?partial). fn rho_canonicity( - lookup_config: &LookupRangeCheckConfig, + lookup_config: &PallasLookupRangeCheck45BConfig, mut layouter: impl Layouter, e_1: RangeConstrained>, f: AssignedCell, @@ -2206,7 +2261,7 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-psi?partial). fn psi_canonicity( - lookup_config: &LookupRangeCheckConfig, + lookup_config: &PallasLookupRangeCheck45BConfig, mut layouter: impl Layouter, g_1: RangeConstrained>, g_2: AssignedCell, @@ -2248,7 +2303,7 @@ pub(in crate::circuit) mod gadgets { /// - [`y` decomposition](https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial) /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) fn y_canonicity( - lookup_config: &LookupRangeCheckConfig, + lookup_config: &PallasLookupRangeCheck45BConfig, y_canon: &YCanonicity, mut layouter: impl Layouter, y: AssignedCell, @@ -2325,7 +2380,7 @@ pub(in crate::circuit) mod gadgets { mod tests { use super::NoteCommitConfig; use crate::{ - circuit::{ + circuit::circuit_zsa::{ gadget::{assign_free_advice, assign_is_native_asset}, note_commit::{gadgets, NoteCommitChip}, }, @@ -2341,7 +2396,7 @@ mod tests { sinsemilla::chip::SinsemillaChip, utilities::{ cond_swap::{CondSwapChip, CondSwapConfig}, - lookup_range_check::LookupRangeCheckConfig, + lookup_range_check::PallasLookupRangeCheck45BConfig, }, }; @@ -2370,7 +2425,7 @@ mod tests { impl Circuit for MyCircuit { type Config = ( NoteCommitConfig, - EccConfig, + EccConfig, CondSwapConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -2407,7 +2462,6 @@ mod tests { table_idx, meta.lookup_table_column(), meta.lookup_table_column(), - table_range_check_tag, ); let lagrange_coeffs = [ meta.fixed_column(), @@ -2420,7 +2474,7 @@ mod tests { meta.fixed_column(), ]; - let range_check = LookupRangeCheckConfig::configure( + let range_check = PallasLookupRangeCheck45BConfig::configure_with_tag( meta, advices[9], table_idx, @@ -2430,6 +2484,7 @@ mod tests { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, + PallasLookupRangeCheck45BConfig, >::configure( meta, advices[..5].try_into().unwrap(), @@ -2437,16 +2492,18 @@ mod tests { lagrange_coeffs[0], lookup, range_check, + true, ); let note_commit_config = NoteCommitChip::configure(meta, advices, sinsemilla_config); - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); + let ecc_config = + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); let cond_swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); @@ -2463,10 +2520,13 @@ mod tests { // Load the Sinsemilla generator lookup table used by the whole circuit. SinsemillaChip::< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?; + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >::load( + note_commit_config.sinsemilla_config.clone(), &mut layouter + )?; // Construct a Sinsemilla chip let sinsemilla_chip = diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/circuit_zsa/value_commit_orchard.rs similarity index 88% rename from src/circuit/value_commit_orchard.rs rename to src/circuit/circuit_zsa/value_commit_orchard.rs index d9871a5bc..a30b62d48 100644 --- a/src/circuit/value_commit_orchard.rs +++ b/src/circuit/circuit_zsa/value_commit_orchard.rs @@ -1,3 +1,5 @@ +//! Value commitment logic for the Orchard circuit (ZSA variation). + pub(in crate::circuit) mod gadgets { use pasta_curves::pallas; @@ -7,6 +9,7 @@ pub(in crate::circuit) mod gadgets { use halo2_gadgets::{ ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, sinsemilla::{self, chip::SinsemillaChip}, + utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRangeCheck45BConfig}, }; use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, @@ -22,15 +25,25 @@ pub(in crate::circuit) mod gadgets { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, + PallasLookupRangeCheck45BConfig, >, - ecc_chip: EccChip, + ecc_chip: EccChip, v_net_magnitude_sign: ( AssignedCell, AssignedCell, ), - rcv: ScalarFixed>, - asset: NonIdentityPoint>, - ) -> Result>, plonk::Error> { + rcv: ScalarFixed< + pallas::Affine, + EccChip, + >, + asset: NonIdentityPoint< + pallas::Affine, + EccChip, + >, + ) -> Result< + Point>, + plonk::Error, + > { // Check that magnitude is 64 bits. { let lookup_config = sinsemilla_chip.config().lookup_config(); @@ -92,7 +105,7 @@ pub(in crate::circuit) mod gadgets { #[cfg(test)] mod tests { use crate::{ - circuit::gadget::{assign_free_advice, value_commit_orchard}, + circuit::circuit_zsa::gadget::{assign_free_advice, value_commit_orchard}, circuit::K, constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, note::AssetBase, @@ -104,7 +117,9 @@ mod tests { NonIdentityPoint, ScalarFixed, }, sinsemilla::chip::{SinsemillaChip, SinsemillaConfig}, - utilities::lookup_range_check::LookupRangeCheckConfig, + utilities::lookup_range_check::{ + LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig, + }, }; use group::Curve; @@ -123,11 +138,15 @@ mod tests { pub struct MyConfig { primary: Column, advices: [Column; 10], - ecc_config: EccConfig, + ecc_config: EccConfig, // Sinsemilla config is only used to initialize the table_idx lookup table in the same // way as in the Orchard circuit - sinsemilla_config: - SinsemillaConfig, + sinsemilla_config: SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + PallasLookupRangeCheck45BConfig, + >, } #[derive(Default)] struct MyCircuit { @@ -174,7 +193,6 @@ mod tests { table_idx, meta.lookup_table_column(), meta.lookup_table_column(), - table_range_check_tag, ); let lagrange_coeffs = [ @@ -189,7 +207,7 @@ mod tests { ]; meta.enable_constant(lagrange_coeffs[0]); - let range_check = LookupRangeCheckConfig::configure( + let range_check = LookupRangeCheck45BConfig::configure_with_tag( meta, advices[9], table_idx, @@ -203,17 +221,19 @@ mod tests { lagrange_coeffs[0], lookup, range_check, + true, ); MyConfig { primary, advices, - ecc_config: EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ), + ecc_config: + EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ), sinsemilla_config, } } diff --git a/src/circuit/commit_ivk.rs b/src/circuit/commit_ivk.rs index 73c24a91f..bfface3ff 100644 --- a/src/circuit/commit_ivk.rs +++ b/src/circuit/commit_ivk.rs @@ -1,3 +1,5 @@ +//! Commit IVK (Incoming Viewing Key) for the Orchard circuit. + use core::iter; use group::ff::{Field, PrimeField}; @@ -8,10 +10,10 @@ use halo2_proofs::{ }; use pasta_curves::pallas; -use crate::constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}; +use crate::constants::{OrchardCommitDomains, OrchardFixedBases, T_P}; use halo2_gadgets::{ ecc::{chip::EccChip, ScalarFixed, X}, - sinsemilla::{chip::SinsemillaChip, CommitDomain, Message, MessagePiece}, + sinsemilla::{CommitDomain, Message, MessagePiece}, utilities::{bool_check, RangeConstrained}, }; @@ -228,29 +230,29 @@ impl CommitIvkChip { } pub(in crate::circuit) mod gadgets { - use halo2_gadgets::utilities::{lookup_range_check::LookupRangeCheckConfig, RangeConstrained}; - use halo2_proofs::circuit::Chip; + use halo2_gadgets::utilities::{lookup_range_check::PallasLookupRangeCheck, RangeConstrained}; use super::*; + use super::super::orchard_sinsemilla_chip::OrchardSinsemillaChip; + /// `Commit^ivk` from [Section 5.4.8.4 Sinsemilla commitments]. /// /// [Section 5.4.8.4 Sinsemilla commitments]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillacommit #[allow(non_snake_case)] #[allow(clippy::type_complexity)] - pub(in crate::circuit) fn commit_ivk( - sinsemilla_chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >, - ecc_chip: EccChip, + pub(in crate::circuit) fn commit_ivk< + Lookup: PallasLookupRangeCheck, + Chip: OrchardSinsemillaChip, + >( + sinsemilla_chip: Chip, + ecc_chip: EccChip, commit_ivk_chip: CommitIvkChip, mut layouter: impl Layouter, ak: AssignedCell, nk: AssignedCell, - rivk: ScalarFixed>, - ) -> Result>, Error> { + rivk: ScalarFixed>, + ) -> Result>, Error> { let lookup_config = sinsemilla_chip.config().lookup_config(); // We need to hash `ak || nk` where each of `ak`, `nk` is a field element (255 bits). @@ -398,8 +400,8 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:commit-ivk-canonicity-ak?partial). #[allow(clippy::type_complexity)] - fn ak_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn ak_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, a: AssignedCell, ) -> Result< @@ -439,8 +441,8 @@ pub(in crate::circuit) mod gadgets { /// /// [Specification](https://p.z.cash/orchard-0.1:commit-ivk-canonicity-nk?partial). #[allow(clippy::type_complexity)] - fn nk_canonicity( - lookup_config: &LookupRangeCheckConfig, + fn nk_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, b_2: &RangeConstrained>, c: AssignedCell, @@ -664,6 +666,7 @@ mod tests { use core::iter; use super::{gadgets, CommitIvkChip, CommitIvkConfig}; + use crate::constants::{ fixed_bases::COMMIT_IVK_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, L_ORCHARD_BASE, T_Q, @@ -678,7 +681,13 @@ mod tests { chip::{SinsemillaChip, SinsemillaConfig}, primitives::CommitDomain, }, - utilities::{lookup_range_check::LookupRangeCheckConfig, UtilitiesInstructions}, + utilities::{ + lookup_range_check::{ + PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheckConfig, + }, + UtilitiesInstructions, + }, }; use halo2_proofs::{ circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}, @@ -688,216 +697,236 @@ mod tests { use pasta_curves::pallas; use rand::rngs::OsRng; - #[test] - fn commit_ivk() { - #[derive(Default)] - struct MyCircuit { - ak: Value, - nk: Value, - } + trait MyLookup: PallasLookupRangeCheck { + const ENABLE_HASH_FROM_PRIVATE_POINT: bool; + } + + impl MyLookup for PallasLookupRangeCheckConfig { + const ENABLE_HASH_FROM_PRIVATE_POINT: bool = false; + } + + impl MyLookup for PallasLookupRangeCheck45BConfig { + const ENABLE_HASH_FROM_PRIVATE_POINT: bool = true; + } - impl UtilitiesInstructions for MyCircuit { - type Var = AssignedCell; + #[derive(Default)] + struct MyCircuit { + ak: Value, + nk: Value, + phantom: std::marker::PhantomData, + } + + impl UtilitiesInstructions for MyCircuit { + type Var = AssignedCell; + } + + impl Circuit for MyCircuit { + type Config = ( + SinsemillaConfig, + CommitIvkConfig, + EccConfig, + ); + + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self { + ak: Default::default(), + nk: Default::default(), + phantom: std::marker::PhantomData, + } } - impl Circuit for MyCircuit { - type Config = ( - SinsemillaConfig, - CommitIvkConfig, - EccConfig, + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + let range_check = Lookup::configure(meta, advices[9], table_idx); + let sinsemilla_config = SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + Lookup, + >::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + Lookup::ENABLE_HASH_FROM_PRIVATE_POINT, ); - type FloorPlanner = SimpleFloorPlanner; - fn without_witnesses(&self) -> Self { - Self::default() - } + let commit_ivk_config = CommitIvkChip::configure(meta, advices); - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - for advice in advices.iter() { - meta.enable_equality(*advice); - } + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + (sinsemilla_config, commit_ivk_config, ecc_config) + } - let table_idx = meta.lookup_table_column(); - let table_range_check_tag = meta.lookup_table_column(); - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - table_range_check_tag, - ); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - let range_check = LookupRangeCheckConfig::configure( - meta, - advices[9], - table_idx, - table_range_check_tag, - ); - let sinsemilla_config = SinsemillaChip::< + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let (sinsemilla_config, commit_ivk_config, ecc_config) = config; + + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::< OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, - >::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - lagrange_coeffs[0], - lookup, - range_check, - ); - - let commit_ivk_config = CommitIvkChip::configure(meta, advices); - - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); - - (sinsemilla_config, commit_ivk_config, ecc_config) - } + Lookup, + >::load(sinsemilla_config.clone(), &mut layouter)?; - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let (sinsemilla_config, commit_ivk_config, ecc_config) = config; - - // Load the Sinsemilla generator lookup table used by the whole circuit. - SinsemillaChip::::load(sinsemilla_config.clone(), &mut layouter)?; - - // Construct a Sinsemilla chip - let sinsemilla_chip = SinsemillaChip::construct(sinsemilla_config); - - // Construct an ECC chip - let ecc_chip = EccChip::construct(ecc_config); - - let commit_ivk_chip = CommitIvkChip::construct(commit_ivk_config.clone()); - - // Witness ak - let ak = self.load_private( - layouter.namespace(|| "load ak"), - commit_ivk_config.advices[0], - self.ak, - )?; - - // Witness nk - let nk = self.load_private( - layouter.namespace(|| "load nk"), - commit_ivk_config.advices[0], - self.nk, - )?; - - // Use a random scalar for rivk - let rivk = pallas::Scalar::random(OsRng); - let rivk_gadget = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rivk"), - Value::known(rivk), - )?; - - let ivk = gadgets::commit_ivk( - sinsemilla_chip, - ecc_chip, - commit_ivk_chip, - layouter.namespace(|| "CommitIvk"), - ak, - nk, - rivk_gadget, - )?; - - self.ak - .zip(self.nk) - .zip(ivk.inner().value()) - .assert_if_known(|((ak, nk), ivk)| { - let expected_ivk = { - let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); - // Hash ak || nk - domain - .short_commit( - iter::empty() - .chain( - ak.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ) - .chain( - nk.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ), - &rivk, - ) - .unwrap() - }; - - &&expected_ivk == ivk - }); + // Construct a Sinsemilla chip + let sinsemilla_chip = SinsemillaChip::construct(sinsemilla_config); - Ok(()) - } + // Construct an ECC chip + let ecc_chip = EccChip::construct(ecc_config); + + let commit_ivk_chip = CommitIvkChip::construct(commit_ivk_config.clone()); + + // Witness ak + let ak = self.load_private( + layouter.namespace(|| "load ak"), + commit_ivk_config.advices[0], + self.ak, + )?; + + // Witness nk + let nk = self.load_private( + layouter.namespace(|| "load nk"), + commit_ivk_config.advices[0], + self.nk, + )?; + + // Use a random scalar for rivk + let rivk = pallas::Scalar::random(OsRng); + let rivk_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rivk"), + Value::known(rivk), + )?; + + let ivk = gadgets::commit_ivk( + sinsemilla_chip, + ecc_chip, + commit_ivk_chip, + layouter.namespace(|| "CommitIvk"), + ak, + nk, + rivk_gadget, + )?; + + self.ak + .zip(self.nk) + .zip(ivk.inner().value()) + .assert_if_known(|((ak, nk), ivk)| { + let expected_ivk = { + let domain = CommitDomain::new(COMMIT_IVK_PERSONALIZATION); + // Hash ak || nk + domain + .short_commit( + iter::empty() + .chain(ak.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)) + .chain(nk.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE)), + &rivk, + ) + .unwrap() + }; + + &&expected_ivk == ivk + }); + + Ok(()) } + } + fn commit_ivk() { let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); // Test different values of `ak`, `nk` let circuits = [ // `ak` = 0, `nk` = 0 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::zero()), nk: Value::known(pallas::Base::zero()), + phantom: std::marker::PhantomData, }, // `ak` = T_Q - 1, `nk` = T_Q - 1 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128(T_Q - 1)), nk: Value::known(pallas::Base::from_u128(T_Q - 1)), + phantom: std::marker::PhantomData, }, // `ak` = T_Q, `nk` = T_Q - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128(T_Q)), nk: Value::known(pallas::Base::from_u128(T_Q)), + phantom: std::marker::PhantomData, }, // `ak` = 2^127 - 1, `nk` = 2^127 - 1 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128((1 << 127) - 1)), nk: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + phantom: std::marker::PhantomData, }, // `ak` = 2^127, `nk` = 2^127 - MyCircuit { + MyCircuit:: { ak: Value::known(pallas::Base::from_u128(1 << 127)), nk: Value::known(pallas::Base::from_u128(1 << 127)), + phantom: std::marker::PhantomData, }, // `ak` = 2^254 - 1, `nk` = 2^254 - 1 - MyCircuit { + MyCircuit:: { ak: Value::known(two_pow_254 - pallas::Base::one()), nk: Value::known(two_pow_254 - pallas::Base::one()), + phantom: std::marker::PhantomData, }, // `ak` = 2^254, `nk` = 2^254 - MyCircuit { + MyCircuit:: { ak: Value::known(two_pow_254), nk: Value::known(two_pow_254), + phantom: std::marker::PhantomData, }, ]; @@ -906,4 +935,14 @@ mod tests { assert_eq!(prover.verify(), Ok(())); } } + + #[test] + fn commit_ivk_vanilla() { + commit_ivk::() + } + + #[test] + fn commit_ivk_zsa() { + commit_ivk::() + } } diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index dff412b72..c62f825f7 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -1,83 +1,14 @@ -//! Gadgets used in the Orchard circuit. +//! Common gadgets and functions used in the Orchard circuit. use ff::Field; -use group::Curve; -use pasta_curves::arithmetic::CurveExt; -use pasta_curves::pallas; -use super::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip}; -use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; -use crate::note::AssetBase; -use halo2_gadgets::{ - ecc::{chip::EccChip, chip::EccPoint, EccInstructions, FixedPointBaseField, Point, X}, - poseidon::{ - primitives::{self as poseidon, ConstantLength}, - Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, - }, - sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, - utilities::cond_swap::CondSwapChip, -}; use halo2_proofs::{ - circuit::{AssignedCell, Chip, Layouter, Value}, - plonk::{self, Advice, Assigned, Column}, + circuit::{AssignedCell, Chip, Layouter}, + plonk, }; pub(in crate::circuit) mod add_chip; -impl super::Config { - pub(super) fn add_chip(&self) -> add_chip::AddChip { - add_chip::AddChip::construct(self.add_config.clone()) - } - - pub(super) fn commit_ivk_chip(&self) -> CommitIvkChip { - CommitIvkChip::construct(self.commit_ivk_config.clone()) - } - - pub(super) fn ecc_chip(&self) -> EccChip { - EccChip::construct(self.ecc_config.clone()) - } - - pub(super) fn sinsemilla_chip_1( - &self, - ) -> SinsemillaChip { - SinsemillaChip::construct(self.sinsemilla_config_1.clone()) - } - - pub(super) fn sinsemilla_chip_2( - &self, - ) -> SinsemillaChip { - SinsemillaChip::construct(self.sinsemilla_config_2.clone()) - } - - pub(super) fn merkle_chip_1( - &self, - ) -> MerkleChip { - MerkleChip::construct(self.merkle_config_1.clone()) - } - - pub(super) fn merkle_chip_2( - &self, - ) -> MerkleChip { - MerkleChip::construct(self.merkle_config_2.clone()) - } - - pub(super) fn poseidon_chip(&self) -> PoseidonChip { - PoseidonChip::construct(self.poseidon_config.clone()) - } - - pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { - NoteCommitChip::construct(self.new_note_commit_config.clone()) - } - - pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { - NoteCommitChip::construct(self.old_note_commit_config.clone()) - } - - pub(super) fn cond_swap_chip(&self) -> CondSwapChip { - CondSwapChip::construct(self.cond_swap_config.clone()) - } -} - /// An instruction set for adding two circuit words (field elements). pub(in crate::circuit) trait AddInstruction: Chip { /// Constraints `a + b` and returns the sum. @@ -88,151 +19,3 @@ pub(in crate::circuit) trait AddInstruction: Chip { b: &AssignedCell, ) -> Result, plonk::Error>; } - -/// Witnesses the given value in a standalone region. -/// -/// Usages of this helper are technically superfluous, as the single-cell region is only -/// ever used in equality constraints. We could eliminate them with a -/// [write-on-copy abstraction](https://github.com/zcash/halo2/issues/334). -pub(in crate::circuit) fn assign_free_advice( - mut layouter: impl Layouter, - column: Column, - value: Value, -) -> Result, plonk::Error> -where - for<'v> Assigned: From<&'v V>, -{ - layouter.assign_region( - || "load private", - |mut region| region.assign_advice(|| "load private", column, 0, || value), - ) -} - -/// Witnesses is_native_asset. -pub(in crate::circuit) fn assign_is_native_asset( - layouter: impl Layouter, - column: Column, - asset: Value, -) -> Result, plonk::Error> -where - Assigned: for<'v> From<&'v pasta_curves::Fp>, -{ - assign_free_advice( - layouter, - column, - asset.map(|asset| { - if bool::from(asset.is_native()) { - pallas::Base::one() - } else { - pallas::Base::zero() - } - }), - ) -} - -/// Witnesses split_flag. -pub(in crate::circuit) fn assign_split_flag( - layouter: impl Layouter, - column: Column, - split_flag: Value, -) -> Result, plonk::Error> -where - Assigned: for<'v> From<&'v pasta_curves::Fp>, -{ - assign_free_advice( - layouter, - column, - split_flag.map(|split_flag| { - if split_flag { - pallas::Base::one() - } else { - pallas::Base::zero() - } - }), - ) -} - -/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. -/// -/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers -#[allow(clippy::too_many_arguments)] -pub(in crate::circuit) fn derive_nullifier< - PoseidonChip: PoseidonSpongeInstructions, 3, 2>, - AddChip: AddInstruction, - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Point = EccPoint, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - poseidon_chip: PoseidonChip, - add_chip: AddChip, - ecc_chip: EccChip, - cond_swap_chip: CondSwapChip, - rho: AssignedCell, - psi: &AssignedCell, - cm: &Point, - nk: AssignedCell, - split_flag: AssignedCell, -) -> Result, plonk::Error> { - // hash = poseidon_hash(nk, rho) - let hash = { - let poseidon_message = [nk, rho]; - let poseidon_hasher = - PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; - poseidon_hasher.hash( - layouter.namespace(|| "Poseidon hash (nk, rho)"), - poseidon_message, - )? - }; - - // Add hash output to psi. - // `scalar` = poseidon_hash(nk, rho) + psi. - let scalar = add_chip.add( - layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), - &hash, - psi, - )?; - - // Multiply scalar by NullifierK - // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. - // - let product = { - let nullifier_k = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK); - nullifier_k.mul( - layouter.namespace(|| "[poseidon_output + psi] NullifierK"), - scalar, - )? - }; - - // Add cm to multiplied fixed base - // nf = cm + [poseidon_output + psi] NullifierK - let nf = cm.add(layouter.namespace(|| "nf"), &product)?; - - // Add NullifierL to nf - // split_note_nf = NullifierL + nf - let nullifier_l = Point::new_from_constant( - ecc_chip.clone(), - layouter.namespace(|| "witness NullifierL constant"), - pallas::Point::hash_to_curve("z.cash:Orchard")(b"L").to_affine(), - )?; - let split_note_nf = nullifier_l.add(layouter.namespace(|| "split_note_nf"), &nf)?; - - // Select the desired nullifier according to split_flag - Ok(Point::from_inner( - ecc_chip, - cond_swap_chip.mux_on_points( - layouter.namespace(|| "mux on nf"), - &split_flag, - nf.inner(), - split_note_nf.inner(), - )?, - ) - .extract_p()) -} - -pub(in crate::circuit) use crate::circuit::commit_ivk::gadgets::commit_ivk; -pub(in crate::circuit) use crate::circuit::note_commit::gadgets::note_commit; -pub(in crate::circuit) use crate::circuit::value_commit_orchard::gadgets::value_commit_orchard; diff --git a/src/circuit/gadget/add_chip.rs b/src/circuit/gadget/add_chip.rs index 0973a3f3b..9c0fb5dad 100644 --- a/src/circuit/gadget/add_chip.rs +++ b/src/circuit/gadget/add_chip.rs @@ -1,3 +1,5 @@ +//! 'Add' chip implemetation. + use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, plonk::{self, Advice, Column, ConstraintSystem, Constraints, Selector}, diff --git a/src/circuit/orchard_sinsemilla_chip.rs b/src/circuit/orchard_sinsemilla_chip.rs new file mode 100644 index 000000000..c58399d8b --- /dev/null +++ b/src/circuit/orchard_sinsemilla_chip.rs @@ -0,0 +1,88 @@ +//! Defines the `OrchardSinsemillaChip` trait to abstract over `SinsemillaChip` and `SinsemillaChip` types. +//! Used to generalize the `commit_ivk` function. + +use pasta_curves::pallas; + +use halo2_proofs::circuit::Chip; + +use halo2_gadgets::{ + sinsemilla::{ + chip::{SinsemillaChip, SinsemillaConfig}, + primitives as sinsemilla, SinsemillaInstructions, + }, + utilities::lookup_range_check::PallasLookupRangeCheck, +}; + +use crate::constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; + +type BaseSinsemillaChip = + SinsemillaChip; + +pub(super) trait OrchardSinsemillaChip: + SinsemillaInstructions< + pallas::Affine, + { sinsemilla::K }, + { sinsemilla::C }, + CellValue = >::CellValue, + Message = >::Message, + MessagePiece = >::MessagePiece, + RunningSum = >::RunningSum, + X = >::X, + NonIdentityPoint = >::NonIdentityPoint, + FixedPoints = >::FixedPoints, + HashDomains = >::HashDomains, + CommitDomains = >::CommitDomains, + > + Chip< + pallas::Base, + Config = SinsemillaConfig< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + Lookup, + >, + > + Clone + + std::fmt::Debug + + Eq +{ +} + +impl OrchardSinsemillaChip + for SinsemillaChip +{ +} diff --git a/src/constants.rs b/src/constants.rs index 8a9b76f23..b64d114f5 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -3,7 +3,7 @@ pub mod fixed_bases; pub mod sinsemilla; pub mod util; -pub use fixed_bases::{NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV, H}; +pub use fixed_bases::{NullifierK, OrchardFixedBases, OrchardFixedBasesFull, ValueCommitV}; pub use sinsemilla::{OrchardCommitDomains, OrchardHashDomains}; /// $\mathsf{MerkleDepth^{Orchard}}$ diff --git a/src/issuance.rs b/src/issuance.rs index 4fade4b74..4ba3b8feb 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -188,6 +188,13 @@ impl Signed { pub fn signature(&self) -> &schnorr::Signature { &self.signature } + + /// Constructs a `Signed` from a byte array containing Schnorr signature bytes. + pub fn from_data(data: [u8; 64]) -> Self { + Signed { + signature: schnorr::Signature::try_from(data.as_ref()).unwrap(), + } + } } impl IssueAuth for Unauthorized {} @@ -248,6 +255,19 @@ impl IssueBundle { authorization, } } + + /// Transitions this bundle from one authorization state to another. + pub fn map_authorization( + self, + map_auth: impl FnOnce(T) -> T2, + ) -> IssueBundle { + let authorization = self.authorization; + IssueBundle { + ik: self.ik, + actions: self.actions, + authorization: map_auth(authorization), + } + } } impl IssueBundle { diff --git a/src/lib.rs b/src/lib.rs index 65e4a5835..96a3c3a2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,8 +26,11 @@ pub mod issuance; pub mod keys; pub mod note; pub mod supply_info; -// pub mod note_encryption; // disabled until backward compatability is implemented. -pub mod note_encryption_v3; + +pub mod note_encryption; + +pub mod orchard_flavor; + pub mod primitives; mod spec; pub mod tree; diff --git a/src/note.rs b/src/note.rs index f5b8d30a0..77cd1b2b8 100644 --- a/src/note.rs +++ b/src/note.rs @@ -10,6 +10,7 @@ use subtle::{Choice, ConditionallySelectable, CtOption}; use crate::{ keys::{EphemeralSecretKey, FullViewingKey, Scope, SpendingKey}, + note_encryption::OrchardDomainCommon, spec::{to_base, to_scalar, NonZeroPallasScalar, PrfExpand}, value::NoteValue, Address, @@ -36,7 +37,7 @@ impl Rho { /// value otherwise. /// /// [`Action::rho`]: crate::action::Action::rho - /// [`CompactAction::rho`]: crate::note_encryption_v3::CompactAction::rho + /// [`CompactAction::rho`]: crate::note_encryption::CompactAction::rho pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { pallas::Base::from_repr(*bytes).map(Rho) } @@ -348,17 +349,17 @@ impl Note { /// An encrypted note. #[derive(Clone)] -pub struct TransmittedNoteCiphertext { +pub struct TransmittedNoteCiphertext { /// The serialization of the ephemeral public key pub epk_bytes: [u8; 32], /// The encrypted note ciphertext - pub enc_ciphertext: [u8; 612], + pub enc_ciphertext: D::NoteCiphertextBytes, /// An encrypted value that allows the holder of the outgoing cipher /// key for the note to recover the note plaintext. pub out_ciphertext: [u8; 80], } -impl fmt::Debug for TransmittedNoteCiphertext { +impl fmt::Debug for TransmittedNoteCiphertext { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TransmittedNoteCiphertext") .field("epk_bytes", &self.epk_bytes) diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 2ac88014c..8f2607e89 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -1,679 +1,17 @@ //! In-band secret distribution for Orchard bundles. - -use blake2b_simd::{Hash, Params}; -use group::ff::PrimeField; -use std::fmt; -use zcash_note_encryption_zsa::{ - BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, - AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, -}; - -use crate::note::AssetBase; -use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, - OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, - }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho}, - value::{NoteValue, ValueCommitment}, - Address, Note, +//! +//! This module handles the encryption and decryption of notes within the Orchard protocol, +//! It includes functionality for handling both the standard "Vanilla" variantion and the ZSA +//! variantion, with different implementations for each. The different implementations are +//! organized into separate submodules. + +mod compact_action; +mod domain; +mod orchard_domain; +mod orchard_domain_vanilla; +mod orchard_domain_zsa; + +pub use { + compact_action::CompactAction, + orchard_domain::{OrchardDomain, OrchardDomainCommon}, }; - -const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; - -/// The size of a v2 compact note. -pub const COMPACT_NOTE_SIZE_V2: usize = 1 + // version - 11 + // diversifier - 8 + // value - 32; // rseed (or rcm prior to ZIP 212) -/// The size of [`NotePlaintextBytes`] for V2. -pub const NOTE_PLAINTEXT_SIZE_V2: usize = COMPACT_NOTE_SIZE_V2 + MEMO_SIZE; -/// The size of an encrypted note plaintext. -pub const ENC_CIPHERTEXT_SIZE_V2: usize = NOTE_PLAINTEXT_SIZE_V2 + AEAD_TAG_SIZE; - -/// a type to represent the raw bytes of a note plaintext. -#[derive(Clone, Debug)] -pub struct NotePlaintextBytes(pub [u8; NOTE_PLAINTEXT_SIZE_V2]); - -/// a type to represent the raw bytes of an encrypted note plaintext. -#[derive(Clone, Debug)] -pub struct NoteCiphertextBytes(pub [u8; ENC_CIPHERTEXT_SIZE_V2]); - -/// a type to represent the raw bytes of a compact note. -#[derive(Clone, Debug)] -pub struct CompactNotePlaintextBytes(pub [u8; COMPACT_NOTE_SIZE_V2]); - -/// a type to represent the raw bytes of an encrypted compact note. -#[derive(Clone, Debug)] -pub struct CompactNoteCiphertextBytes(pub [u8; COMPACT_NOTE_SIZE_V2]); - -impl AsMut<[u8]> for NotePlaintextBytes { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl From<&[u8]> for NotePlaintextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - NotePlaintextBytes(s.try_into().unwrap()) - } -} - -impl AsRef<[u8]> for NoteCiphertextBytes { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -impl From<&[u8]> for NoteCiphertextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - NoteCiphertextBytes(s.try_into().unwrap()) - } -} - -impl AsMut<[u8]> for CompactNotePlaintextBytes { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl From<&[u8]> for CompactNotePlaintextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - CompactNotePlaintextBytes(s.try_into().unwrap()) - } -} - -impl AsRef<[u8]> for CompactNoteCiphertextBytes { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. -/// -/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs -pub(crate) fn prf_ock_orchard( - ovk: &OutgoingViewingKey, - cv: &ValueCommitment, - cmx_bytes: &[u8; 32], - ephemeral_key: &EphemeralKeyBytes, -) -> OutgoingCipherKey { - OutgoingCipherKey( - Params::new() - .hash_length(32) - .personal(PRF_OCK_ORCHARD_PERSONALIZATION) - .to_state() - .update(ovk.as_ref()) - .update(&cv.to_bytes()) - .update(cmx_bytes) - .update(ephemeral_key.as_ref()) - .finalize() - .as_bytes() - .try_into() - .unwrap(), - ) -} - -/// note_version will return the version of the note plaintext. -pub fn note_version(plaintext: &[u8]) -> Option { - match plaintext[0] { - 0x02 => Some(0x02), - 0x03 => Some(0x03), - _ => None, - } -} - -fn orchard_parse_note_plaintext_without_memo( - domain: &OrchardDomainV2, - plaintext: &[u8], // TODO: replace with CompactNotePlaintextBytes - get_pk_d: F, -) -> Option<(Note, Address)> -where - F: FnOnce(&Diversifier) -> DiversifiedTransmissionKey, -{ - assert!(plaintext.len() >= COMPACT_NOTE_SIZE_V2); - - // Check note plaintext version - if note_version(plaintext).unwrap() != 0x02 { - return None; - } - - // The unwraps below are guaranteed to succeed by the assertion above - let diversifier = Diversifier::from_bytes(plaintext[1..12].try_into().unwrap()); - let value = NoteValue::from_bytes(plaintext[12..20].try_into().unwrap()); - let rseed = Option::from(RandomSeed::from_bytes( - plaintext[20..COMPACT_NOTE_SIZE_V2].try_into().unwrap(), - &domain.rho, - ))?; - - let pk_d = get_pk_d(&diversifier); - - let recipient = Address::from_parts(diversifier, pk_d); - let note = Option::from(Note::from_parts( - recipient, - value, - AssetBase::native(), //V2 notes are always native. - domain.rho, - rseed, - ))?; - Some((note, recipient)) -} - -/// Orchard-specific note encryption logic. -#[derive(Debug)] -pub struct OrchardDomainV2 { - rho: Rho, -} - -impl memuse::DynamicUsage for OrchardDomainV2 { - fn dynamic_usage(&self) -> usize { - self.rho.dynamic_usage() - } - - fn dynamic_usage_bounds(&self) -> (usize, Option) { - self.rho.dynamic_usage_bounds() - } -} - -impl OrchardDomainV2 { - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_action(act: &Action) -> Self { - Self { rho: act.rho() } - } - - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_compact_action(act: &CompactAction) -> Self { - Self { rho: act.rho() } - } -} - -impl Domain for OrchardDomainV2 { - type EphemeralSecretKey = EphemeralSecretKey; - type EphemeralPublicKey = EphemeralPublicKey; - type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; - type SharedSecret = SharedSecret; - type SymmetricKey = Hash; - type Note = Note; - type Recipient = Address; - type DiversifiedTransmissionKey = DiversifiedTransmissionKey; - type IncomingViewingKey = PreparedIncomingViewingKey; - type OutgoingViewingKey = OutgoingViewingKey; - type ValueCommitment = ValueCommitment; - type ExtractedCommitment = ExtractedNoteCommitment; - type ExtractedCommitmentBytes = [u8; 32]; - type Memo = [u8; MEMO_SIZE]; // TODO use a more interesting type - - type NotePlaintextBytes = NotePlaintextBytes; - type NoteCiphertextBytes = NoteCiphertextBytes; - type CompactNotePlaintextBytes = CompactNotePlaintextBytes; - type CompactNoteCiphertextBytes = CompactNoteCiphertextBytes; - - fn derive_esk(note: &Self::Note) -> Option { - Some(note.esk()) - } - - fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { - *note.recipient().pk_d() - } - - fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { - PreparedEphemeralPublicKey::new(epk) - } - - fn ka_derive_public( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> Self::EphemeralPublicKey { - esk.derive_public(note.recipient().g_d()) - } - - fn ka_agree_enc( - esk: &Self::EphemeralSecretKey, - pk_d: &Self::DiversifiedTransmissionKey, - ) -> Self::SharedSecret { - esk.agree(pk_d) - } - - fn ka_agree_dec( - ivk: &Self::IncomingViewingKey, - epk: &Self::PreparedEphemeralPublicKey, - ) -> Self::SharedSecret { - epk.agree(ivk) - } - - fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { - secret.kdf_orchard(ephemeral_key) - } - - fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> NotePlaintextBytes { - let mut np = [0; NOTE_PLAINTEXT_SIZE_V2]; - np[0] = 0x02; - np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); - np[12..20].copy_from_slice(¬e.value().to_bytes()); - np[20..52].copy_from_slice(note.rseed().as_bytes()); - np[52..].copy_from_slice(memo); - NotePlaintextBytes(np) - } - - fn derive_ock( - ovk: &Self::OutgoingViewingKey, - cv: &Self::ValueCommitment, - cmstar_bytes: &Self::ExtractedCommitmentBytes, - ephemeral_key: &EphemeralKeyBytes, - ) -> OutgoingCipherKey { - prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) - } - - fn outgoing_plaintext_bytes( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> OutPlaintextBytes { - let mut op = [0; OUT_PLAINTEXT_SIZE]; - op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); - op[32..].copy_from_slice(&esk.0.to_repr()); - OutPlaintextBytes(op) - } - - fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { - epk.to_bytes() - } - - fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { - EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() - } - - fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { - note.commitment().into() - } - - fn parse_note_plaintext_without_memo_ivk( - &self, - ivk: &Self::IncomingViewingKey, - plaintext: &CompactNotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { - DiversifiedTransmissionKey::derive(ivk, diversifier) - }) - } - - fn parse_note_plaintext_without_memo_ovk( - &self, - pk_d: &Self::DiversifiedTransmissionKey, - plaintext: &NotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, &plaintext.0, |_| *pk_d) - } - - fn extract_memo( - &self, - plaintext: &NotePlaintextBytes, - ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { - let (compact, memo) = plaintext.0.split_at(COMPACT_NOTE_SIZE_V2); - (compact.try_into().unwrap(), memo.try_into().unwrap()) - } - - fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { - DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() - } - - fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { - EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) - .into() - } -} - -impl BatchDomain for OrchardDomainV2 { - fn batch_kdf<'a>( - items: impl Iterator, &'a EphemeralKeyBytes)>, - ) -> Vec> { - let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); - - SharedSecret::batch_to_affine(shared_secrets) - .zip(ephemeral_keys.into_iter()) - .map(|(secret, ephemeral_key)| { - secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) - }) - .collect() - } -} - -/// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption_zsa::NoteEncryption; - -impl ShieldedOutput for Action { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.encrypted_note().epk_bytes) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx().to_bytes() - } - - fn enc_ciphertext(&self) -> Option { - Some(NoteCiphertextBytes(self.encrypted_note().enc_ciphertext)) - } - - fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { - CompactNoteCiphertextBytes( - self.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V2] - .try_into() - .unwrap(), - ) - } -} - -/// A compact Action for light clients. -#[derive(Clone)] -pub struct CompactAction { - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: CompactNoteCiphertextBytes, -} - -impl fmt::Debug for CompactAction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "CompactAction") - } -} - -impl From<&Action> for CompactAction -where - Action: ShieldedOutput, -{ - fn from(action: &Action) -> Self { - CompactAction { - nullifier: *action.nullifier(), - cmx: *action.cmx(), - ephemeral_key: action.ephemeral_key(), - enc_ciphertext: CompactNoteCiphertextBytes( - action.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V2] - .try_into() - .unwrap(), - ), - } - } -} - -impl ShieldedOutput for CompactAction { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.ephemeral_key.0) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx.to_bytes() - } - - fn enc_ciphertext(&self) -> Option { - None - } - - fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { - self.enc_ciphertext.clone() - } -} - -impl CompactAction { - /// Create a CompactAction from its constituent parts - pub fn from_parts( - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: CompactNoteCiphertextBytes, - ) -> Self { - Self { - nullifier, - cmx, - ephemeral_key, - enc_ciphertext, - } - } - - /// Returns the nullifier of the note being spent. - pub fn nullifier(&self) -> Nullifier { - self.nullifier - } - - /// Returns the commitment to the new note being created. - pub fn cmx(&self) -> ExtractedNoteCommitment { - self.cmx - } - - /// Obtains the [`Rho`] value that was used to construct the new note being created. - pub fn rho(&self) -> Rho { - Rho::from_nf_old(self.nullifier) - } -} - -/// Utilities for constructing test data. -#[cfg(feature = "test-dependencies")] -pub mod testing { - use rand::RngCore; - use zcash_note_encryption::Domain; - - use crate::{ - keys::OutgoingViewingKey, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho}, - value::NoteValue, - Address, Note, - }; - - use super::{CompactAction, OrchardDomain, OrchardNoteEncryption}; - - /// Creates a fake `CompactAction` paying the given recipient the specified value. - /// - /// Returns the `CompactAction` and the new note. - pub fn fake_compact_action( - rng: &mut R, - nf_old: Nullifier, - recipient: Address, - value: NoteValue, - ovk: Option, - ) -> (CompactAction, Note) { - let rho = Rho::from_nf_old(nf_old); - let rseed = { - loop { - let mut bytes = [0; 32]; - rng.fill_bytes(&mut bytes); - let rseed = RandomSeed::from_bytes(bytes, &rho); - if rseed.is_some().into() { - break rseed.unwrap(); - } - } - }; - let note = Note::from_parts(recipient, value, rho, rseed).unwrap(); - let encryptor = OrchardNoteEncryption::new(ovk, note, [0u8; 512]); - let cmx = ExtractedNoteCommitment::from(note.commitment()); - let ephemeral_key = OrchardDomain::epk_bytes(encryptor.epk()); - let enc_ciphertext = encryptor.encrypt_note_plaintext(); - - ( - CompactAction { - nullifier: nf_old, - cmx, - ephemeral_key, - enc_ciphertext: enc_ciphertext.as_ref()[..52].try_into().unwrap(), - }, - note, - ) - } -} - -#[cfg(test)] -mod tests { - use proptest::proptest; - use rand::rngs::OsRng; - use zcash_note_encryption_zsa::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, - EphemeralKeyBytes, - }; - - use super::{prf_ock_orchard, CompactAction, OrchardDomainV2, OrchardNoteEncryption}; - use crate::note::AssetBase; - use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, - OutgoingViewingKey, PreparedIncomingViewingKey, - }, - note::{ - testing::arb_native_note, ExtractedNoteCommitment, Nullifier, RandomSeed, Rho, - TransmittedNoteCiphertext, - }, - note_encryption::{ - note_version, orchard_parse_note_plaintext_without_memo, NoteCiphertextBytes, - }, - primitives::redpallas, - value::{NoteValue, ValueCommitment}, - Address, Note, - }; - - proptest! { - #[test] - fn test_encoding_roundtrip( - note in arb_native_note(), - ) { - let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; - - // Encode. - let mut plaintext = OrchardDomainV2::note_plaintext_bytes(¬e, ¬e.recipient(), memo); - - // Decode. - let domain = OrchardDomainV2 { rho: note.rho() }; - let parsed_version = note_version(plaintext.as_mut()).unwrap(); - let (compact,parsed_memo) = domain.extract_memo(&plaintext); - - let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &compact.0, - |diversifier| { - assert_eq!(diversifier, ¬e.recipient().diversifier()); - Some(*note.recipient().pk_d()) - } - ).expect("Plaintext parsing failed"); - - // Check. - assert_eq!(parsed_note, note); - assert_eq!(parsed_recipient, note.recipient()); - assert_eq!(&parsed_memo, memo); - assert_eq!(parsed_version, 0x02); - } - } - - #[test] - fn test_vectors() { - let test_vectors = crate::test_vectors::note_encryption::test_vectors(); - - for tv in test_vectors { - // - // Load the test vector components - // - - // Recipient key material - let ivk = PreparedIncomingViewingKey::new( - &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), - ); - let ovk = OutgoingViewingKey::from(tv.ovk); - let d = Diversifier::from_bytes(tv.default_d); - let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); - - // Received Action - let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); - let nf_old = Nullifier::from_bytes(&tv.nf_old).unwrap(); - let rho = Rho::from_nf_old(nf_old); - let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); - - let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); - let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); - - // Details about the expected note - let value = NoteValue::from_raw(tv.v); - let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); - - // - // Test the individual components - // - - let shared_secret = esk.agree(&pk_d); - assert_eq!(shared_secret.to_bytes(), tv.shared_secret); - - let k_enc = shared_secret.kdf_orchard(&ephemeral_key); - assert_eq!(k_enc.as_bytes(), tv.k_enc); - - let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); - assert_eq!(ock.as_ref(), tv.ock); - - let recipient = Address::from_parts(d, pk_d); - let note = Note::from_parts(recipient, value, AssetBase::native(), rho, rseed).unwrap(); - assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); - - let action = Action::from_parts( - // nf_old is the nullifier revealed by the receiving Action. - nf_old, - // We don't need a valid rk for this test. - redpallas::VerificationKey::dummy(), - cmx, - TransmittedNoteCiphertext { - epk_bytes: ephemeral_key.0, - enc_ciphertext: tv.c_enc, - out_ciphertext: tv.c_out, - }, - cv_net.clone(), - (), - ); - - // - // Test decryption - // (Tested first because it only requires immutable references.) - // - - let domain = OrchardDomainV2 { rho }; - - match try_note_decryption(&domain, &ivk, &action) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Note decryption failed"), - } - - match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { - Some((decrypted_note, decrypted_to)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - } - None => panic!("Compact note decryption failed"), - } - - match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Output recovery failed"), - } - - // - // Test encryption - // - - let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, tv.memo); - - assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); - assert_eq!( - &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], - &tv.c_out[..] - ); - } - } -} diff --git a/src/note_encryption/compact_action.rs b/src/note_encryption/compact_action.rs new file mode 100644 index 000000000..77fc768b8 --- /dev/null +++ b/src/note_encryption/compact_action.rs @@ -0,0 +1,163 @@ +//! Defines actions for Orchard shielded outputs and compact action for light clients. + +use std::fmt; + +use zcash_note_encryption_zsa::{EphemeralKeyBytes, ShieldedOutput}; + +use crate::{ + action::Action, + note::{ExtractedNoteCommitment, Nullifier, Rho}, +}; + +use super::orchard_domain::{OrchardDomain, OrchardDomainCommon}; + +impl ShieldedOutput> for Action { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.encrypted_note().epk_bytes) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx().to_bytes() + } + + fn enc_ciphertext(&self) -> Option { + Some(self.encrypted_note().enc_ciphertext) + } + + fn enc_ciphertext_compact(&self) -> D::CompactNoteCiphertextBytes { + self.encrypted_note().enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE].into() + } +} + +/// A compact Action for light clients. +pub struct CompactAction { + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: D::CompactNoteCiphertextBytes, +} + +impl fmt::Debug for CompactAction { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "CompactAction") + } +} + +impl From<&Action> for CompactAction +where + Action: ShieldedOutput>, +{ + fn from(action: &Action) -> Self { + CompactAction { + nullifier: *action.nullifier(), + cmx: *action.cmx(), + ephemeral_key: action.ephemeral_key(), + enc_ciphertext: action.enc_ciphertext_compact(), + } + } +} + +impl ShieldedOutput> for CompactAction { + fn ephemeral_key(&self) -> EphemeralKeyBytes { + EphemeralKeyBytes(self.ephemeral_key.0) + } + + fn cmstar_bytes(&self) -> [u8; 32] { + self.cmx.to_bytes() + } + + fn enc_ciphertext(&self) -> Option { + None + } + + fn enc_ciphertext_compact(&self) -> D::CompactNoteCiphertextBytes { + self.enc_ciphertext + } +} + +impl CompactAction { + /// Create a CompactAction from its constituent parts + pub fn from_parts( + nullifier: Nullifier, + cmx: ExtractedNoteCommitment, + ephemeral_key: EphemeralKeyBytes, + enc_ciphertext: D::CompactNoteCiphertextBytes, + ) -> Self { + Self { + nullifier, + cmx, + ephemeral_key, + enc_ciphertext, + } + } + + /// Returns the nullifier of the note being spent. + pub fn nullifier(&self) -> Nullifier { + self.nullifier + } + + /// Returns the commitment to the new note being created. + pub fn cmx(&self) -> ExtractedNoteCommitment { + self.cmx + } + + /// Obtains the [`Rho`] value that was used to construct the new note being created. + pub fn rho(&self) -> Rho { + Rho::from_nf_old(self.nullifier) + } +} + +/// Utilities for constructing test data. +#[cfg(feature = "test-dependencies")] +pub mod testing { + use rand::RngCore; + + use zcash_note_encryption_zsa::{Domain, NoteEncryption}; + + use crate::{ + address::Address, + keys::OutgoingViewingKey, + note::{AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, Rho}, + value::NoteValue, + }; + + use super::{CompactAction, OrchardDomain, OrchardDomainCommon}; + + /// Creates a fake `CompactAction` paying the given recipient the specified value. + /// + /// Returns the `CompactAction` and the new note. + pub fn fake_compact_action( + rng: &mut R, + nf_old: Nullifier, + recipient: Address, + value: NoteValue, + ovk: Option, + ) -> (CompactAction, Note) { + let rho = Rho::from_nf_old(nf_old); + let rseed = { + loop { + let mut bytes = [0; 32]; + rng.fill_bytes(&mut bytes); + let rseed = RandomSeed::from_bytes(bytes, &rho); + if rseed.is_some().into() { + break rseed.unwrap(); + } + } + }; + let note = Note::from_parts(recipient, value, AssetBase::native(), rho, rseed).unwrap(); + let encryptor = NoteEncryption::>::new(ovk, note, [0u8; 512]); + let cmx = ExtractedNoteCommitment::from(note.commitment()); + let ephemeral_key = OrchardDomain::::epk_bytes(encryptor.epk()); + let enc_ciphertext = encryptor.encrypt_note_plaintext(); + + ( + CompactAction { + nullifier: nf_old, + cmx, + ephemeral_key, + enc_ciphertext: enc_ciphertext.as_ref()[..52].try_into().unwrap(), + }, + note, + ) + } +} diff --git a/src/note_encryption/domain.rs b/src/note_encryption/domain.rs new file mode 100644 index 000000000..c91ad81b4 --- /dev/null +++ b/src/note_encryption/domain.rs @@ -0,0 +1,289 @@ +//! This module implements `Domain` and `BatchDomain` traits from the `zcash_note_encryption` +//! crate and contains the common logic for `OrchardVanilla` and `OrchardZSA` flavors. + +use blake2b_simd::Hash; +use group::ff::PrimeField; + +use blake2b_simd::Params; + +use zcash_note_encryption_zsa::{ + BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, MEMO_SIZE, + OUT_PLAINTEXT_SIZE, +}; + +use crate::{ + address::Address, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, + OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, + }, + note::{ExtractedNoteCommitment, Note, RandomSeed, Rho}, + value::{NoteValue, ValueCommitment}, +}; + +use super::orchard_domain::{OrchardDomain, OrchardDomainCommon}; + +const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; + +const NOTE_VERSION_SIZE: usize = 1; +const NOTE_DIVERSIFIER_SIZE: usize = 11; +const NOTE_VALUE_SIZE: usize = 8; +const NOTE_RSEED_SIZE: usize = 32; // rseed (or rcm prior to ZIP 212) + +const NOTE_VERSION_OFFSET: usize = 0; +const NOTE_DIVERSIFIER_OFFSET: usize = NOTE_VERSION_OFFSET + NOTE_VERSION_SIZE; +const NOTE_VALUE_OFFSET: usize = NOTE_DIVERSIFIER_OFFSET + NOTE_DIVERSIFIER_SIZE; +const NOTE_RSEED_OFFSET: usize = NOTE_VALUE_OFFSET + NOTE_VALUE_SIZE; + +/// The size of a Vanilla compact note. +pub(super) const COMPACT_NOTE_SIZE_VANILLA: usize = + NOTE_VERSION_SIZE + NOTE_DIVERSIFIER_SIZE + NOTE_VALUE_SIZE + NOTE_RSEED_SIZE; + +/// The size of the encoding of a ZSA asset id. +const ZSA_ASSET_SIZE: usize = 32; + +/// The size of a ZSA compact note. +pub(super) const COMPACT_NOTE_SIZE_ZSA: usize = COMPACT_NOTE_SIZE_VANILLA + ZSA_ASSET_SIZE; + +/// The version byte for Vanilla. +pub(super) const NOTE_VERSION_BYTE_V2: u8 = 0x02; + +/// The version byte for ZSA. +pub(super) const NOTE_VERSION_BYTE_V3: u8 = 0x03; + +pub(super) type Memo = [u8; MEMO_SIZE]; + +/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. +/// +/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs +pub(super) fn prf_ock_orchard( + ovk: &OutgoingViewingKey, + cv: &ValueCommitment, + cmx_bytes: &[u8; 32], + ephemeral_key: &EphemeralKeyBytes, +) -> OutgoingCipherKey { + OutgoingCipherKey( + Params::new() + .hash_length(32) + .personal(PRF_OCK_ORCHARD_PERSONALIZATION) + .to_state() + .update(ovk.as_ref()) + .update(&cv.to_bytes()) + .update(cmx_bytes) + .update(ephemeral_key.as_ref()) + .finalize() + .as_bytes() + .try_into() + .unwrap(), + ) +} + +/// Retrieves the version of the note plaintext. +/// Returns `Some(u8)` if the version is recognized, otherwise `None`. +pub(super) fn parse_note_version(plaintext: &[u8]) -> Option { + plaintext.first().and_then(|version| match *version { + NOTE_VERSION_BYTE_V2 | NOTE_VERSION_BYTE_V3 => Some(*version), + _ => None, + }) +} + +/// Parses the note plaintext (excluding the memo) and extracts the note and address if valid. +/// Domain-specific requirements: +/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. +pub(super) fn parse_note_plaintext_without_memo( + rho: Rho, + plaintext: &D::CompactNotePlaintextBytes, + get_validated_pk_d: F, +) -> Option<(Note, Address)> +where + F: FnOnce(&Diversifier) -> Option, +{ + parse_note_version(plaintext.as_ref())?; + + // The unwraps below are guaranteed to succeed + let diversifier = Diversifier::from_bytes( + plaintext.as_ref()[NOTE_DIVERSIFIER_OFFSET..NOTE_VALUE_OFFSET] + .try_into() + .unwrap(), + ); + + let value = NoteValue::from_bytes( + plaintext.as_ref()[NOTE_VALUE_OFFSET..NOTE_RSEED_OFFSET] + .try_into() + .unwrap(), + ); + + let rseed = Option::from(RandomSeed::from_bytes( + plaintext.as_ref()[NOTE_RSEED_OFFSET..COMPACT_NOTE_SIZE_VANILLA] + .try_into() + .unwrap(), + &rho, + ))?; + + let pk_d = get_validated_pk_d(&diversifier)?; + let recipient = Address::from_parts(diversifier, pk_d); + let asset = D::extract_asset(plaintext)?; + let note = Option::from(Note::from_parts(recipient, value, asset, rho, rseed))?; + + Some((note, recipient)) +} + +// Constructs a note plaintext bytes array given note information. +pub(super) fn build_base_note_plaintext_bytes( + version: u8, + note: &Note, +) -> [u8; NOTE_PLAINTEXT_SIZE] { + let mut np = [0; NOTE_PLAINTEXT_SIZE]; + + np[NOTE_VERSION_OFFSET] = version; + np[NOTE_DIVERSIFIER_OFFSET..NOTE_VALUE_OFFSET] + .copy_from_slice(note.recipient().diversifier().as_array()); + np[NOTE_VALUE_OFFSET..NOTE_RSEED_OFFSET].copy_from_slice(¬e.value().to_bytes()); + np[NOTE_RSEED_OFFSET..COMPACT_NOTE_SIZE_VANILLA].copy_from_slice(note.rseed().as_bytes()); + + np +} + +impl Domain for OrchardDomain { + type EphemeralSecretKey = EphemeralSecretKey; + type EphemeralPublicKey = EphemeralPublicKey; + type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; + type SharedSecret = SharedSecret; + type SymmetricKey = Hash; + type Note = Note; + type Recipient = Address; + type DiversifiedTransmissionKey = DiversifiedTransmissionKey; + type IncomingViewingKey = PreparedIncomingViewingKey; + type OutgoingViewingKey = OutgoingViewingKey; + type ValueCommitment = ValueCommitment; + type ExtractedCommitment = ExtractedNoteCommitment; + type ExtractedCommitmentBytes = [u8; 32]; + type Memo = Memo; + + type NotePlaintextBytes = D::NotePlaintextBytes; + type NoteCiphertextBytes = D::NoteCiphertextBytes; + type CompactNotePlaintextBytes = D::CompactNotePlaintextBytes; + type CompactNoteCiphertextBytes = D::CompactNoteCiphertextBytes; + + fn derive_esk(note: &Self::Note) -> Option { + Some(note.esk()) + } + + fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { + *note.recipient().pk_d() + } + + fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { + PreparedEphemeralPublicKey::new(epk) + } + + fn ka_derive_public( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> Self::EphemeralPublicKey { + esk.derive_public(note.recipient().g_d()) + } + + fn ka_agree_enc( + esk: &Self::EphemeralSecretKey, + pk_d: &Self::DiversifiedTransmissionKey, + ) -> Self::SharedSecret { + esk.agree(pk_d) + } + + fn ka_agree_dec( + ivk: &Self::IncomingViewingKey, + epk: &Self::PreparedEphemeralPublicKey, + ) -> Self::SharedSecret { + epk.agree(ivk) + } + + fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { + secret.kdf_orchard(ephemeral_key) + } + + fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> D::NotePlaintextBytes { + D::build_note_plaintext_bytes(note, memo) + } + + fn derive_ock( + ovk: &Self::OutgoingViewingKey, + cv: &Self::ValueCommitment, + cmstar_bytes: &Self::ExtractedCommitmentBytes, + ephemeral_key: &EphemeralKeyBytes, + ) -> OutgoingCipherKey { + prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) + } + + fn outgoing_plaintext_bytes( + note: &Self::Note, + esk: &Self::EphemeralSecretKey, + ) -> OutPlaintextBytes { + let mut op = [0; OUT_PLAINTEXT_SIZE]; + op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); + op[32..].copy_from_slice(&esk.0.to_repr()); + OutPlaintextBytes(op) + } + + fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { + epk.to_bytes() + } + + fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { + EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() + } + + fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { + note.commitment().into() + } + + fn parse_note_plaintext_without_memo_ivk( + &self, + ivk: &Self::IncomingViewingKey, + plaintext: &D::CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + parse_note_plaintext_without_memo::(self.rho, plaintext, |diversifier| { + Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) + }) + } + + fn parse_note_plaintext_without_memo_ovk( + &self, + pk_d: &Self::DiversifiedTransmissionKey, + plaintext: &D::CompactNotePlaintextBytes, + ) -> Option<(Self::Note, Self::Recipient)> { + parse_note_plaintext_without_memo::(self.rho, plaintext, |_| Some(*pk_d)) + } + + fn extract_memo( + &self, + plaintext: &D::NotePlaintextBytes, + ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { + let (compact, memo) = plaintext.as_ref().split_at(D::COMPACT_NOTE_SIZE); + (compact.into(), memo.try_into().unwrap()) + } + + fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { + DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() + } + + fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { + EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) + .into() + } +} + +impl BatchDomain for OrchardDomain { + fn batch_kdf<'a>( + items: impl Iterator, &'a EphemeralKeyBytes)>, + ) -> Vec> { + let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); + + SharedSecret::batch_to_affine(shared_secrets) + .zip(ephemeral_keys) + .map(|(secret, ephemeral_key)| { + secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) + }) + .collect() + } +} diff --git a/src/note_encryption/orchard_domain.rs b/src/note_encryption/orchard_domain.rs new file mode 100644 index 000000000..aa70fded6 --- /dev/null +++ b/src/note_encryption/orchard_domain.rs @@ -0,0 +1,118 @@ +//! The OrchardDomain trait represents the difference between the `OrchardVanilla` and the `OrchardZSA` +//! encryption and decryption procedures. + +use core::fmt; + +use zcash_note_encryption_zsa::{AEAD_TAG_SIZE, MEMO_SIZE}; + +use crate::{ + action::Action, + note::{AssetBase, Rho}, + Note, +}; + +use super::{compact_action::CompactAction, domain::Memo}; + +/// Represents a fixed-size array of bytes for note components. +#[derive(Clone, Copy, Debug)] +pub struct NoteBytesData(pub [u8; N]); + +impl AsRef<[u8]> for NoteBytesData { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl AsMut<[u8]> for NoteBytesData { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +impl From<&[u8]> for NoteBytesData { + fn from(s: &[u8]) -> Self { + Self(s.try_into().unwrap()) + } +} + +impl From<(&[u8], &[u8])> for NoteBytesData { + fn from(s: (&[u8], &[u8])) -> Self { + Self([s.0, s.1].concat().try_into().unwrap()) + } +} + +/// Provides a unified interface for handling fixed-size byte arrays used in Orchard note encryption. +pub trait NoteBytes: + AsRef<[u8]> + + AsMut<[u8]> + + for<'a> From<&'a [u8]> + + for<'a> From<(&'a [u8], &'a [u8])> + + Clone + + Copy + + Send +{ +} + +impl NoteBytes for NoteBytesData {} + +/// Represents the Orchard protocol domain specifics required for note encryption and decryption. +pub trait OrchardDomainCommon: fmt::Debug + Clone { + /// The size of a compact note, specific to the Orchard protocol. + const COMPACT_NOTE_SIZE: usize; + + /// The size of a note plaintext, including memo and other metadata. + const NOTE_PLAINTEXT_SIZE: usize = Self::COMPACT_NOTE_SIZE + MEMO_SIZE; + + /// The size of an encrypted note ciphertext, accounting for additional AEAD tag space. + const ENC_CIPHERTEXT_SIZE: usize = Self::NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE; + + /// The raw bytes of a note plaintext. + type NotePlaintextBytes: NoteBytes; + /// The raw bytes of an encrypted note plaintext. + type NoteCiphertextBytes: NoteBytes; + /// The raw bytes of a compact note. + type CompactNotePlaintextBytes: NoteBytes; + /// The raw bytes of an encrypted compact note. + type CompactNoteCiphertextBytes: NoteBytes; + + /// Builds NotePlaintextBytes from Note and Memo. + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes; + + /// Extracts the asset from the note plaintext. + fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option; +} + +/// Orchard-specific note encryption logic. +#[derive(Debug, Clone)] +pub struct OrchardDomain { + /// A parameter needed to generate the nullifier. + pub rho: Rho, + phantom: std::marker::PhantomData, +} + +impl OrchardDomain { + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_action(act: &Action) -> Self { + Self { + rho: act.rho(), + phantom: Default::default(), + } + } + + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_compact_action(act: &CompactAction) -> Self { + Self { + rho: act.rho(), + phantom: Default::default(), + } + } + + /// Constructs a domain from a rho. + #[cfg(test)] + pub fn for_rho(rho: Rho) -> Self { + Self { + rho, + phantom: Default::default(), + } + } +} diff --git a/src/note_encryption/orchard_domain_vanilla.rs b/src/note_encryption/orchard_domain_vanilla.rs new file mode 100644 index 000000000..d49c361da --- /dev/null +++ b/src/note_encryption/orchard_domain_vanilla.rs @@ -0,0 +1,217 @@ +//! This module implements the note encryption logic specific for the `OrchardVanilla` flavor. + +use crate::{ + note::{AssetBase, Note}, + orchard_flavor::OrchardVanilla, +}; + +use super::{ + domain::{ + build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, NOTE_VERSION_BYTE_V2, + }, + orchard_domain::{NoteBytesData, OrchardDomainCommon}, +}; + +impl OrchardDomainCommon for OrchardVanilla { + const COMPACT_NOTE_SIZE: usize = COMPACT_NOTE_SIZE_VANILLA; + + type NotePlaintextBytes = NoteBytesData<{ Self::NOTE_PLAINTEXT_SIZE }>; + type NoteCiphertextBytes = NoteBytesData<{ Self::ENC_CIPHERTEXT_SIZE }>; + type CompactNotePlaintextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + type CompactNoteCiphertextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes { + let mut np = build_base_note_plaintext_bytes(NOTE_VERSION_BYTE_V2, note); + + np[COMPACT_NOTE_SIZE_VANILLA..].copy_from_slice(memo); + + NoteBytesData(np) + } + + fn extract_asset(_plaintext: &Self::CompactNotePlaintextBytes) -> Option { + Some(AssetBase::native()) + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + + use rand::rngs::OsRng; + + use zcash_note_encryption_zsa::{ + try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, + EphemeralKeyBytes, + }; + + use crate::{ + action::Action, + address::Address, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, + OutgoingViewingKey, PreparedIncomingViewingKey, + }, + note::{ + testing::arb_native_note, AssetBase, ExtractedNoteCommitment, Note, Nullifier, + RandomSeed, Rho, TransmittedNoteCiphertext, + }, + orchard_flavor::OrchardVanilla, + primitives::redpallas, + value::{NoteValue, ValueCommitment}, + }; + + use super::super::{ + compact_action::CompactAction, + domain::{parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard}, + orchard_domain::{NoteBytesData, OrchardDomain}, + }; + + type OrchardDomainVanilla = OrchardDomain; + + /// Implementation of in-band secret distribution for Orchard bundles. + pub type OrchardDomainCommonryptionVanilla = + zcash_note_encryption_zsa::NoteEncryption; + + proptest! { + #[test] + fn encoding_roundtrip( + note in arb_native_note(), + ) { + let memo = &crate::test_vectors::note_encryption_vanilla::test_vectors()[0].memo; + let rho = note.rho(); + + // Encode. + let plaintext = OrchardDomainVanilla::note_plaintext_bytes(¬e, memo); + + // Decode. + let domain = OrchardDomainVanilla::for_rho(rho); + let (compact, parsed_memo) = domain.extract_memo(&plaintext); + + assert!(parse_note_version(compact.as_ref()).is_some()); + + let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo::(rho, &compact, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + assert_eq!(&parsed_memo, memo); + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::note_encryption_vanilla::test_vectors(); + + for tv in test_vectors { + // + // Load the test vector components + // + + // Recipient key material + let ivk = PreparedIncomingViewingKey::new( + &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), + ); + let ovk = OutgoingViewingKey::from(tv.ovk); + let d = Diversifier::from_bytes(tv.default_d); + let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); + + // Received Action + let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); + let nf_old = Nullifier::from_bytes(&tv.nf_old).unwrap(); + let rho = Rho::from_nf_old(nf_old); + let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); + + let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); + let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); + + // Details about the expected note + let value = NoteValue::from_raw(tv.v); + let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); + + // + // Test the individual components + // + + let shared_secret = esk.agree(&pk_d); + assert_eq!(shared_secret.to_bytes(), tv.shared_secret); + + let k_enc = shared_secret.kdf_orchard(&ephemeral_key); + assert_eq!(k_enc.as_bytes(), tv.k_enc); + + let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); + assert_eq!(ock.as_ref(), tv.ock); + + let recipient = Address::from_parts(d, pk_d); + + let asset = AssetBase::native(); + + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); + + let action = Action::from_parts( + // nf_old is the nullifier revealed by the receiving Action. + nf_old, + // We don't need a valid rk for this test. + redpallas::VerificationKey::dummy(), + cmx, + TransmittedNoteCiphertext:: { + epk_bytes: ephemeral_key.0, + enc_ciphertext: NoteBytesData(tv.c_enc), + out_ciphertext: tv.c_out, + }, + cv_net.clone(), + (), + ); + + // + // Test decryption + // (Tested first because it only requires immutable references.) + // + + let domain = OrchardDomain::for_rho(rho); + + match try_note_decryption(&domain, &ivk, &action) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Note decryption failed"), + } + + match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { + Some((decrypted_note, decrypted_to)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + } + None => panic!("Compact note decryption failed"), + } + + match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Output recovery failed"), + } + + // + // Test encryption + // + + let ne = OrchardDomainCommonryptionVanilla::new_with_esk(esk, Some(ovk), note, tv.memo); + + assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); + assert_eq!( + &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], + &tv.c_out[..] + ); + } + } +} diff --git a/src/note_encryption/orchard_domain_zsa.rs b/src/note_encryption/orchard_domain_zsa.rs new file mode 100644 index 000000000..4979e8c91 --- /dev/null +++ b/src/note_encryption/orchard_domain_zsa.rs @@ -0,0 +1,224 @@ +//! This module implements the note encryption logic specific for the `OrchardZSA` flavor. + +use crate::{ + note::{AssetBase, Note}, + orchard_flavor::OrchardZSA, +}; + +use super::{ + domain::{ + build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, COMPACT_NOTE_SIZE_ZSA, + NOTE_VERSION_BYTE_V3, + }, + orchard_domain::{NoteBytesData, OrchardDomainCommon}, +}; + +impl OrchardDomainCommon for OrchardZSA { + const COMPACT_NOTE_SIZE: usize = COMPACT_NOTE_SIZE_ZSA; + + type NotePlaintextBytes = NoteBytesData<{ Self::NOTE_PLAINTEXT_SIZE }>; + type NoteCiphertextBytes = NoteBytesData<{ Self::ENC_CIPHERTEXT_SIZE }>; + type CompactNotePlaintextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + type CompactNoteCiphertextBytes = NoteBytesData<{ Self::COMPACT_NOTE_SIZE }>; + + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes { + let mut np = build_base_note_plaintext_bytes(NOTE_VERSION_BYTE_V3, note); + + np[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA] + .copy_from_slice(¬e.asset().to_bytes()); + np[COMPACT_NOTE_SIZE_ZSA..].copy_from_slice(memo); + + NoteBytesData(np) + } + + fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option { + let bytes = plaintext.as_ref()[COMPACT_NOTE_SIZE_VANILLA..COMPACT_NOTE_SIZE_ZSA] + .try_into() + .unwrap(); + + AssetBase::from_bytes(bytes).into() + } +} + +#[cfg(test)] +mod tests { + use proptest::prelude::*; + + use rand::rngs::OsRng; + + use zcash_note_encryption_zsa::{ + try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, + EphemeralKeyBytes, + }; + + use crate::{ + action::Action, + address::Address, + keys::{ + DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, + OutgoingViewingKey, PreparedIncomingViewingKey, + }, + note::{ + testing::arb_note, AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, + Rho, TransmittedNoteCiphertext, + }, + orchard_flavor::OrchardZSA, + primitives::redpallas, + value::{NoteValue, ValueCommitment}, + }; + + use super::super::{ + compact_action::CompactAction, + domain::{parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard}, + orchard_domain::{NoteBytesData, OrchardDomain}, + }; + + type OrchardDomainZSA = OrchardDomain; + + /// Implementation of in-band secret distribution for Orchard bundles. + pub type OrchardDomainCommonryptionZSA = + zcash_note_encryption_zsa::NoteEncryption; + + proptest! { + #[test] + fn encoding_roundtrip( + note in arb_note(NoteValue::from_raw(100)), + ) { + let memo = &crate::test_vectors::note_encryption_zsa::test_vectors()[0].memo; + let rho = note.rho(); + + // Encode. + let plaintext = OrchardDomainZSA::note_plaintext_bytes(¬e, memo); + + // Decode. + let domain = OrchardDomainZSA::for_rho(rho); + let (compact, parsed_memo) = domain.extract_memo(&plaintext); + + assert!(parse_note_version(compact.as_ref()).is_some()); + + let (parsed_note, parsed_recipient) = parse_note_plaintext_without_memo::(rho, &compact, + |diversifier| { + assert_eq!(diversifier, ¬e.recipient().diversifier()); + Some(*note.recipient().pk_d()) + } + ).expect("Plaintext parsing failed"); + + // Check. + assert_eq!(parsed_note, note); + assert_eq!(parsed_recipient, note.recipient()); + assert_eq!(&parsed_memo, memo); + } + } + + #[test] + fn test_vectors() { + let test_vectors = crate::test_vectors::note_encryption_zsa::test_vectors(); + + for tv in test_vectors { + // + // Load the test vector components + // + + // Recipient key material + let ivk = PreparedIncomingViewingKey::new( + &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), + ); + let ovk = OutgoingViewingKey::from(tv.ovk); + let d = Diversifier::from_bytes(tv.default_d); + let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); + + // Received Action + let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); + let nf_old = Nullifier::from_bytes(&tv.nf_old).unwrap(); + let rho = Rho::from_nf_old(nf_old); + let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); + + let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); + let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); + + // Details about the expected note + let value = NoteValue::from_raw(tv.v); + let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); + + // + // Test the individual components + // + + let shared_secret = esk.agree(&pk_d); + assert_eq!(shared_secret.to_bytes(), tv.shared_secret); + + let k_enc = shared_secret.kdf_orchard(&ephemeral_key); + assert_eq!(k_enc.as_bytes(), tv.k_enc); + + let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); + assert_eq!(ock.as_ref(), tv.ock); + + let recipient = Address::from_parts(d, pk_d); + + let asset = AssetBase::from_bytes(&tv.asset).unwrap(); + + let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); + assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); + + let action = Action::from_parts( + // nf_old is the nullifier revealed by the receiving Action. + nf_old, + // We don't need a valid rk for this test. + redpallas::VerificationKey::dummy(), + cmx, + TransmittedNoteCiphertext:: { + epk_bytes: ephemeral_key.0, + enc_ciphertext: NoteBytesData(tv.c_enc), + out_ciphertext: tv.c_out, + }, + cv_net.clone(), + (), + ); + + // + // Test decryption + // (Tested first because it only requires immutable references.) + // + + let domain = OrchardDomain::for_rho(rho); + + match try_note_decryption(&domain, &ivk, &action) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Note decryption failed"), + } + + match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { + Some((decrypted_note, decrypted_to)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + } + None => panic!("Compact note decryption failed"), + } + + match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { + Some((decrypted_note, decrypted_to, decrypted_memo)) => { + assert_eq!(decrypted_note, note); + assert_eq!(decrypted_to, recipient); + assert_eq!(&decrypted_memo[..], &tv.memo[..]); + } + None => panic!("Output recovery failed"), + } + + // + // Test encryption + // + + let ne = OrchardDomainCommonryptionZSA::new_with_esk(esk, Some(ovk), note, tv.memo); + + assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); + assert_eq!( + &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], + &tv.c_out[..] + ); + } + } +} diff --git a/src/note_encryption_v2v3.rs b/src/note_encryption_v2v3.rs deleted file mode 100644 index 107184ab8..000000000 --- a/src/note_encryption_v2v3.rs +++ /dev/null @@ -1,716 +0,0 @@ -//! In-band secret distribution for Orchard bundles. - -use blake2b_simd::{Hash, Params}; -use core::fmt; -use group::ff::PrimeField; -use zcash_note_encryption_zsa::{ - BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, - AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, -}; - -use crate::note::AssetBase; -use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, - IncomingViewingKey, OutgoingViewingKey, SharedSecret, - }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed}, - spec::diversify_hash, - value::{NoteValue, ValueCommitment}, - Address, Note, -}; - -const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; - -/// The size of a v2 compact note. -pub const COMPACT_NOTE_SIZE_V2: usize = 1 + // version - 11 + // diversifier - 8 + // value - 32; // rseed (or rcm prior to ZIP 212) -/// The size of [`NotePlaintextBytes`] for V2. -pub const NOTE_PLAINTEXT_SIZE_V2: usize = COMPACT_NOTE_SIZE_V2 + MEMO_SIZE; -/// The size of an encrypted note plaintext. -pub const ENC_CIPHERTEXT_SIZE_V2: usize = NOTE_PLAINTEXT_SIZE_V2 + AEAD_TAG_SIZE; - -/// The size of the encoding of a ZSA asset id. -const ZSA_ASSET_SIZE: usize = 32; -/// The size of a v3 compact note. -const COMPACT_NOTE_SIZE_V3: usize = COMPACT_NOTE_SIZE_V2 + ZSA_ASSET_SIZE; -/// The size of [`NotePlaintextBytes`] for V3. -const NOTE_PLAINTEXT_SIZE_V3: usize = COMPACT_NOTE_SIZE_V3 + MEMO_SIZE; -/// The size of the encrypted ciphertext of the ZSA variant of a note. -const ENC_CIPHERTEXT_SIZE_V3: usize = NOTE_PLAINTEXT_SIZE_V3 + AEAD_TAG_SIZE; - -/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. -/// -/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs -pub(crate) fn prf_ock_orchard( - ovk: &OutgoingViewingKey, - cv: &ValueCommitment, - cmx_bytes: &[u8; 32], - ephemeral_key: &EphemeralKeyBytes, -) -> OutgoingCipherKey { - OutgoingCipherKey( - Params::new() - .hash_length(32) - .personal(PRF_OCK_ORCHARD_PERSONALIZATION) - .to_state() - .update(ovk.as_ref()) - .update(&cv.to_bytes()) - .update(cmx_bytes) - .update(ephemeral_key.as_ref()) - .finalize() - .as_bytes() - .try_into() - .unwrap(), - ) -} - -// TODO: VA: Needs updating -/// Domain-specific requirements: -/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. -fn orchard_parse_note_plaintext_without_memo( - domain: &OrchardDomain, - plaintext: &CompactNotePlaintextBytes, - get_validated_pk_d: F, -) -> Option<(Note, Address)> -where - F: FnOnce(&Diversifier) -> Option, -{ - // Check note plaintext version - // and parse the asset type accordingly. - let asset = parse_version_and_asset_type(plaintext)?; - - let mut plaintext_inner = [0u8; COMPACT_NOTE_SIZE_V2]; - match plaintext { - CompactNotePlaintextBytes::V2(x) => { - plaintext_inner.copy_from_slice(&x[..COMPACT_NOTE_SIZE_V2]) - } - CompactNotePlaintextBytes::V3(x) => { - plaintext_inner.copy_from_slice(&x[..COMPACT_NOTE_SIZE_V2]) - } - } - - // The unwraps below are guaranteed to succeed by the assertion above - let diversifier = Diversifier::from_bytes(plaintext_inner[1..12].try_into().unwrap()); - let value = NoteValue::from_bytes(plaintext_inner[12..20].try_into().unwrap()); - let rseed = Option::from(RandomSeed::from_bytes( - plaintext_inner[20..COMPACT_NOTE_SIZE_V2] - .try_into() - .unwrap(), - &domain.rho, - ))?; - - let pk_d = get_validated_pk_d(&diversifier)?; - - let recipient = Address::from_parts(diversifier, pk_d); - let note = Option::from(Note::from_parts(recipient, value, asset, domain.rho, rseed))?; - Some((note, recipient)) -} - -fn parse_version_and_asset_type(plaintext: &CompactNotePlaintextBytes) -> Option { - match plaintext { - CompactNotePlaintextBytes::V2(x) if x[0] == 0x02 => Some(AssetBase::native()), - CompactNotePlaintextBytes::V3(x) if x[0] == 0x03 => { - let bytes = x[COMPACT_NOTE_SIZE_V2..COMPACT_NOTE_SIZE_V3] - .try_into() - .unwrap(); - AssetBase::from_bytes(bytes).into() - } - _ => None, - } -} - -/// Orchard-specific note encryption logic. -#[derive(Debug)] -pub struct OrchardDomain { - rho: Nullifier, -} - -/// Newtype for encoding the note plaintext post ZSA. -// pub struct NotePlaintextZSA (pub [u8; ZSA_NOTE_PLAINTEXT_SIZE]); -#[derive(Clone, Debug)] -pub enum NotePlaintextBytes { - /// Variant for old note plaintexts. - V2([u8; NOTE_PLAINTEXT_SIZE_V2]), - /// Variant for the new note plaintexts post ZSA. - V3([u8; NOTE_PLAINTEXT_SIZE_V3]), -} - -impl AsMut<[u8]> for NotePlaintextBytes { - fn as_mut(&mut self) -> &mut [u8] { - match self { - NotePlaintextBytes::V2(x) => x.as_mut(), - NotePlaintextBytes::V3(x) => x.as_mut(), - } - } -} - -impl From<&[u8]> for NotePlaintextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - match s.len() { - NOTE_PLAINTEXT_SIZE_V2 => NotePlaintextBytes::V2(s.try_into().unwrap()), - NOTE_PLAINTEXT_SIZE_V3 => NotePlaintextBytes::V3(s.try_into().unwrap()), - _ => panic!("Invalid note plaintext size"), - } - } -} - -/// Newtype for encoding the encrypted note ciphertext post ZSA. -// pub struct EncNoteCiphertextZSA (pub [u8; ZSA_ENC_CIPHERTEXT_SIZE]); -#[derive(Clone, Debug)] -pub enum NoteCiphertextBytes { - /// Variant for old encrypted note ciphertexts. - V2([u8; ENC_CIPHERTEXT_SIZE_V2]), - /// Variant for new encrypted note ciphertexts post ZSA. - V3([u8; ENC_CIPHERTEXT_SIZE_V3]), -} - -impl AsRef<[u8]> for NoteCiphertextBytes { - fn as_ref(&self) -> &[u8] { - match self { - NoteCiphertextBytes::V2(x) => x, - NoteCiphertextBytes::V3(x) => x, - } - } -} - -/// Panics if the given slice is not `ENC_CIPHERTEXT_SIZE_V2` or `ENC_CIPHERTEXT_SIZE_V3` bytes long. -impl From<&[u8]> for NoteCiphertextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - match s.len() { - ENC_CIPHERTEXT_SIZE_V2 => NoteCiphertextBytes::V2(s.try_into().unwrap()), - ENC_CIPHERTEXT_SIZE_V3 => NoteCiphertextBytes::V3(s.try_into().unwrap()), - _ => panic!("Invalid length for compact note plaintext"), - } - } -} - -/// Newtype for encoding a compact note -#[derive(Clone, Debug)] -pub enum CompactNotePlaintextBytes { - /// Variant for old compact notes. - V2([u8; COMPACT_NOTE_SIZE_V2]), - /// Variant for new compact notes post ZSA. - V3([u8; COMPACT_NOTE_SIZE_V3]), -} - -impl AsMut<[u8]> for CompactNotePlaintextBytes { - fn as_mut(&mut self) -> &mut [u8] { - match self { - CompactNotePlaintextBytes::V2(x) => x, - CompactNotePlaintextBytes::V3(x) => x, - } - } -} - -/// Panics if the given slice is not `COMPACT_NOTE_SIZE_V2` or `COMPACT_NOTE_SIZE_V3` bytes long. -impl From<&[u8]> for CompactNotePlaintextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - match s.len() { - COMPACT_NOTE_SIZE_V2 => CompactNotePlaintextBytes::V2(s.try_into().unwrap()), - COMPACT_NOTE_SIZE_V3 => CompactNotePlaintextBytes::V3(s.try_into().unwrap()), - _ => panic!("Invalid length for compact note plaintext"), - } - } -} - -/// Newtype for encoding a compact note -#[derive(Clone, Debug)] -pub enum CompactNoteCiphertextBytes { - /// Variant for old compact notes. - V2([u8; COMPACT_NOTE_SIZE_V2]), - /// Variant for new compact notes post ZSA. - V3([u8; COMPACT_NOTE_SIZE_V3]), -} - -impl AsRef<[u8]> for CompactNoteCiphertextBytes { - fn as_ref(&self) -> &[u8] { - match self { - CompactNoteCiphertextBytes::V2(x) => x, - CompactNoteCiphertextBytes::V3(x) => x, - } - } -} - -impl OrchardDomain { - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_action(act: &Action) -> Self { - OrchardDomain { - rho: *act.nullifier(), - } - } - - /// Constructs a domain from a nullifier. - pub fn for_nullifier(nullifier: Nullifier) -> Self { - OrchardDomain { rho: nullifier } - } -} - -impl Domain for OrchardDomain { - type EphemeralSecretKey = EphemeralSecretKey; - type EphemeralPublicKey = EphemeralPublicKey; - type PreparedEphemeralPublicKey = EphemeralPublicKey; - type SharedSecret = SharedSecret; - type SymmetricKey = Hash; - type Note = Note; - type Recipient = Address; - type DiversifiedTransmissionKey = DiversifiedTransmissionKey; - type IncomingViewingKey = IncomingViewingKey; - type OutgoingViewingKey = OutgoingViewingKey; - type ValueCommitment = ValueCommitment; - type ExtractedCommitment = ExtractedNoteCommitment; - type ExtractedCommitmentBytes = [u8; 32]; - type Memo = [u8; MEMO_SIZE]; // TODO use a more interesting type - - type NotePlaintextBytes = NotePlaintextBytes; - type NoteCiphertextBytes = NoteCiphertextBytes; - type CompactNotePlaintextBytes = CompactNotePlaintextBytes; - type CompactNoteCiphertextBytes = CompactNoteCiphertextBytes; - - fn derive_esk(note: &Self::Note) -> Option { - Some(note.esk()) - } - - fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { - *note.recipient().pk_d() - } - - fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { - epk - } - - fn ka_derive_public( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> Self::EphemeralPublicKey { - esk.derive_public(note.recipient().g_d()) - } - - fn ka_agree_enc( - esk: &Self::EphemeralSecretKey, - pk_d: &Self::DiversifiedTransmissionKey, - ) -> Self::SharedSecret { - esk.agree(pk_d) - } - - fn ka_agree_dec( - ivk: &Self::IncomingViewingKey, - epk: &Self::PreparedEphemeralPublicKey, - ) -> Self::SharedSecret { - epk.agree(ivk) - } - - fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { - secret.kdf_orchard(ephemeral_key) - } - - fn note_plaintext_bytes( - note: &Self::Note, - _: &Self::Recipient, - memo: &Self::Memo, - ) -> NotePlaintextBytes { - let mut np = [0u8; NOTE_PLAINTEXT_SIZE_V3]; - np[0] = 0x03; - np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); - np[12..20].copy_from_slice(¬e.value().to_bytes()); - np[20..52].copy_from_slice(note.rseed().as_bytes()); - let zsa_type = note.asset().to_bytes(); - np[52..84].copy_from_slice(&zsa_type); - np[84..].copy_from_slice(memo); - NotePlaintextBytes::V3(np) - } - - fn derive_ock( - ovk: &Self::OutgoingViewingKey, - cv: &Self::ValueCommitment, - cmstar_bytes: &Self::ExtractedCommitmentBytes, - ephemeral_key: &EphemeralKeyBytes, - ) -> OutgoingCipherKey { - prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) - } - - fn outgoing_plaintext_bytes( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> OutPlaintextBytes { - let mut op = [0; OUT_PLAINTEXT_SIZE]; - op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); - op[32..].copy_from_slice(&esk.0.to_repr()); - OutPlaintextBytes(op) - } - - fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { - epk.to_bytes() - } - - fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { - EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() - } - - fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { - note.commitment().into() - } - - fn parse_note_plaintext_without_memo_ivk( - &self, - ivk: &Self::IncomingViewingKey, - plaintext: &CompactNotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { - Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) - }) - } - - fn parse_note_plaintext_without_memo_ovk( - &self, - pk_d: &Self::DiversifiedTransmissionKey, - esk: &Self::EphemeralSecretKey, - ephemeral_key: &EphemeralKeyBytes, - plaintext: &CompactNotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { - if esk - .derive_public(diversify_hash(diversifier.as_array())) - .to_bytes() - .0 - == ephemeral_key.0 - { - Some(*pk_d) - } else { - None - } - }) - } - - fn extract_memo( - &self, - plaintext: &NotePlaintextBytes, - ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { - match plaintext { - NotePlaintextBytes::V2(np) => { - let (compact, memo) = np.split_at(COMPACT_NOTE_SIZE_V2); - ( - CompactNotePlaintextBytes::V2(compact.try_into().unwrap()), - memo.try_into().unwrap(), - ) - } - NotePlaintextBytes::V3(np) => { - let (compact, memo) = np.split_at(COMPACT_NOTE_SIZE_V3); - ( - CompactNotePlaintextBytes::V3(compact.try_into().unwrap()), - memo.try_into().unwrap(), - ) - } - } - } - - fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { - DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() - } - - fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { - EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) - .into() - } -} - -impl BatchDomain for OrchardDomain { - fn batch_kdf<'a>( - items: impl Iterator, &'a EphemeralKeyBytes)>, - ) -> Vec> { - let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); - - SharedSecret::batch_to_affine(shared_secrets) - .zip(ephemeral_keys.into_iter()) - .map(|(secret, ephemeral_key)| { - secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) - }) - .collect() - } -} - -/// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption_zsa::NoteEncryption; - -impl ShieldedOutput for Action { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.encrypted_note().epk_bytes) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx().to_bytes() - } - - fn enc_ciphertext(&self) -> Option { - let result = self.encrypted_note().enc_ciphertext.clone(); - Some(result) - } - - fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { - match self.encrypted_note().enc_ciphertext { - NoteCiphertextBytes::V2(ncx) => { - CompactNoteCiphertextBytes::V2(ncx[..COMPACT_NOTE_SIZE_V2].try_into().unwrap()) - } - NoteCiphertextBytes::V3(ncx) => { - CompactNoteCiphertextBytes::V3(ncx[..COMPACT_NOTE_SIZE_V3].try_into().unwrap()) - } - } - } -} - -/// A compact Action for light clients. -pub struct CompactAction { - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: CompactNoteCiphertextBytes, -} - -impl fmt::Debug for CompactAction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "CompactAction") - } -} - -impl From<&Action> for CompactAction { - fn from(action: &Action) -> Self { - let comp_ciphertext: CompactNoteCiphertextBytes = - match action.encrypted_note().enc_ciphertext { - NoteCiphertextBytes::V2(ncx) => { - CompactNoteCiphertextBytes::V2(ncx[..COMPACT_NOTE_SIZE_V2].try_into().unwrap()) - } - NoteCiphertextBytes::V3(ncx) => { - CompactNoteCiphertextBytes::V3(ncx[..COMPACT_NOTE_SIZE_V3].try_into().unwrap()) - } - }; - CompactAction { - nullifier: *action.nullifier(), - cmx: *action.cmx(), - ephemeral_key: action.ephemeral_key(), - enc_ciphertext: comp_ciphertext, - } - } -} - -impl ShieldedOutput for CompactAction { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.ephemeral_key.0) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx.to_bytes() - } - - fn enc_ciphertext(&self) -> Option { - None - } - - fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { - &self.enc_ciphertext - } -} - -impl CompactAction { - /// Create a CompactAction from its constituent parts - pub fn from_parts( - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: CompactNoteCiphertextBytes, - ) -> Self { - Self { - nullifier, - cmx, - ephemeral_key, - enc_ciphertext, - } - } - - ///Returns the nullifier of the note being spent. - pub fn nullifier(&self) -> Nullifier { - self.nullifier - } -} - -#[cfg(test)] -mod tests { - use proptest::prelude::*; - use rand::rngs::OsRng; - use zcash_note_encryption_zsa::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, - EphemeralKeyBytes, - }; - - use super::{prf_ock_orchard, CompactAction, OrchardDomain, OrchardNoteEncryption}; - use crate::note::AssetBase; - use crate::note_encryption::NoteCiphertextBytes; - use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, - OutgoingViewingKey, - }, - note::{ - testing::arb_note, ExtractedNoteCommitment, Nullifier, RandomSeed, - TransmittedNoteCiphertext, - }, - primitives::redpallas, - value::{NoteValue, ValueCommitment}, - Address, Note, - }; - - use super::{orchard_parse_note_plaintext_without_memo, version}; - - proptest! { - #[test] - fn test_encoding_roundtrip( - note in arb_note(NoteValue::from_raw(100)), - ) { - let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; - - // Encode. - let mut plaintext = OrchardDomain::note_plaintext_bytes(¬e, ¬e.recipient(), memo); - - // Decode. - let domain = OrchardDomain { rho: note.rho() }; - let parsed_version = version(plaintext.as_mut()).unwrap(); - let (mut compact,parsed_memo) = domain.extract_memo(&plaintext); - - let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &compact.as_mut(), - |diversifier| { - assert_eq!(diversifier, ¬e.recipient().diversifier()); - Some(*note.recipient().pk_d()) - } - ).expect("Plaintext parsing failed"); - - // Check. - assert_eq!(parsed_note, note); - assert_eq!(parsed_recipient, note.recipient()); - assert_eq!(&parsed_memo, memo); - assert_eq!(parsed_version, 0x03); - } - } - - #[test] - fn test_vectors() { - let test_vectors = crate::test_vectors::note_encryption::test_vectors(); - - for tv in test_vectors { - // - // Load the test vector components - // - - // Recipient key material - let ivk = IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(); - let ovk = OutgoingViewingKey::from(tv.ovk); - let d = Diversifier::from_bytes(tv.default_d); - let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); - - // Received Action - let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); - let rho = Nullifier::from_bytes(&tv.rho).unwrap(); - let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); - - let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); - let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); - - // Details about the expected note - let value = NoteValue::from_raw(tv.v); - let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); - - // - // Test the individual components - // - - let shared_secret = esk.agree(&pk_d); - assert_eq!(shared_secret.to_bytes(), tv.shared_secret); - - let k_enc = shared_secret.kdf_orchard(&ephemeral_key); - assert_eq!(k_enc.as_bytes(), tv.k_enc); - - let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); - assert_eq!(ock.as_ref(), tv.ock); - - let recipient = Address::from_parts(d, pk_d); - - let asset = match tv.asset { - None => AssetBase::native(), - Some(type_bytes) => AssetBase::from_bytes(&type_bytes).unwrap(), - }; - - let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); - assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); - - let action = Action::from_parts( - // rho is the nullifier in the receiving Action. - rho, - // We don't need a valid rk for this test. - redpallas::VerificationKey::dummy(), - cmx, - TransmittedNoteCiphertext { - epk_bytes: ephemeral_key.0, - enc_ciphertext: NoteCiphertextBytes::V3(tv.c_enc), // TODO: VA: Would need a mix of V2 and V3 eventually - out_ciphertext: tv.c_out, - }, - cv_net.clone(), - (), - ); - - // - // Test decryption - // (Tested first because it only requires immutable references.) - // - - let domain = OrchardDomain { rho }; - - match try_note_decryption(&domain, &ivk, &action) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Note decryption failed"), - } - - match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { - Some((decrypted_note, decrypted_to)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - } - None => panic!("Compact note decryption failed"), - } - - match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Output recovery failed"), - } - - // - // Test encryption - // - - let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, recipient, tv.memo); - - // assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); - assert_eq!( - &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], - &tv.c_out[..] - ); - } - } -} diff --git a/src/note_encryption_v3.rs b/src/note_encryption_v3.rs deleted file mode 100644 index 8fb68dbd0..000000000 --- a/src/note_encryption_v3.rs +++ /dev/null @@ -1,632 +0,0 @@ -//! In-band secret distribution for Orchard bundles. - -use blake2b_simd::{Hash, Params}; -use core::fmt; -use group::ff::PrimeField; -use zcash_note_encryption_zsa::{ - BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, ShieldedOutput, - AEAD_TAG_SIZE, MEMO_SIZE, OUT_PLAINTEXT_SIZE, -}; - -use crate::note::AssetBase; -use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralPublicKey, EphemeralSecretKey, - OutgoingViewingKey, PreparedEphemeralPublicKey, PreparedIncomingViewingKey, SharedSecret, - }, - note::{ExtractedNoteCommitment, Nullifier, RandomSeed, Rho}, - value::{NoteValue, ValueCommitment}, - Address, Note, -}; - -const PRF_OCK_ORCHARD_PERSONALIZATION: &[u8; 16] = b"Zcash_Orchardock"; - -/// The size of a v2 compact note. -pub const COMPACT_NOTE_SIZE_V2: usize = 1 + // version - 11 + // diversifier - 8 + // value - 32; // rseed (or rcm prior to ZIP 212) -/// The size of [`NotePlaintextBytes`] for V2. - -/// The size of the encoding of a ZSA asset id. -const ZSA_ASSET_SIZE: usize = 32; -/// The size of a v3 compact note. -pub const COMPACT_NOTE_SIZE_V3: usize = COMPACT_NOTE_SIZE_V2 + ZSA_ASSET_SIZE; -/// The size of [`NotePlaintextBytes`] for V3. -pub const NOTE_PLAINTEXT_SIZE_V3: usize = COMPACT_NOTE_SIZE_V3 + MEMO_SIZE; -/// The size of the encrypted ciphertext of the ZSA variant of a note. -pub const ENC_CIPHERTEXT_SIZE_V3: usize = NOTE_PLAINTEXT_SIZE_V3 + AEAD_TAG_SIZE; - -/// a type to represent the raw bytes of a note plaintext. -#[derive(Clone, Debug)] -pub struct NotePlaintextBytes(pub [u8; NOTE_PLAINTEXT_SIZE_V3]); - -/// a type to represent the raw bytes of an encrypted note plaintext. -#[derive(Clone, Debug)] -pub struct NoteCiphertextBytes(pub [u8; ENC_CIPHERTEXT_SIZE_V3]); - -/// a type to represent the raw bytes of a compact note. -#[derive(Clone, Debug)] -pub struct CompactNotePlaintextBytes(pub [u8; COMPACT_NOTE_SIZE_V3]); - -/// a type to represent the raw bytes of an encrypted compact note. -#[derive(Clone, Debug)] -pub struct CompactNoteCiphertextBytes(pub [u8; COMPACT_NOTE_SIZE_V3]); - -impl AsMut<[u8]> for NotePlaintextBytes { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl From<&[u8]> for NotePlaintextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - NotePlaintextBytes(s.try_into().unwrap()) - } -} - -impl AsRef<[u8]> for NoteCiphertextBytes { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -impl AsMut<[u8]> for NoteCiphertextBytes { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl From<(&[u8], &[u8])> for NoteCiphertextBytes { - fn from(s: (&[u8], &[u8])) -> Self { - Self([s.0, s.1].concat().try_into().unwrap()) - } -} - -impl From<&[u8]> for NoteCiphertextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - NoteCiphertextBytes(s.try_into().unwrap()) - } -} - -impl AsMut<[u8]> for CompactNotePlaintextBytes { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl From<&[u8]> for CompactNotePlaintextBytes { - fn from(s: &[u8]) -> Self - where - Self: Sized, - { - CompactNotePlaintextBytes(s.try_into().unwrap()) - } -} - -impl AsRef<[u8]> for CompactNoteCiphertextBytes { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -/// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. -/// -/// [concreteprfs]: https://zips.z.cash/protocol/nu5.pdf#concreteprfs -pub(crate) fn prf_ock_orchard( - ovk: &OutgoingViewingKey, - cv: &ValueCommitment, - cmx_bytes: &[u8; 32], - ephemeral_key: &EphemeralKeyBytes, -) -> OutgoingCipherKey { - OutgoingCipherKey( - Params::new() - .hash_length(32) - .personal(PRF_OCK_ORCHARD_PERSONALIZATION) - .to_state() - .update(ovk.as_ref()) - .update(&cv.to_bytes()) - .update(cmx_bytes) - .update(ephemeral_key.as_ref()) - .finalize() - .as_bytes() - .try_into() - .unwrap(), - ) -} - -/// note_version will return the version of the note plaintext. -pub fn note_version(plaintext: &[u8]) -> Option { - match plaintext[0] { - 0x02 => Some(0x02), - 0x03 => Some(0x03), - _ => None, - } -} - -/// Domain-specific requirements: -/// - If the note version is 3, the `plaintext` must contain a valid encoding of a ZSA asset type. -fn orchard_parse_note_plaintext_without_memo( - domain: &OrchardDomainV3, - plaintext: &CompactNotePlaintextBytes, - get_validated_pk_d: F, -) -> Option<(Note, Address)> -where - F: FnOnce(&Diversifier) -> Option, -{ - // The unwraps below are guaranteed to succeed by the assertion above - let diversifier = Diversifier::from_bytes(plaintext.0[1..12].try_into().unwrap()); - let value = NoteValue::from_bytes(plaintext.0[12..20].try_into().unwrap()); - let rseed = Option::from(RandomSeed::from_bytes( - plaintext.0[20..COMPACT_NOTE_SIZE_V2].try_into().unwrap(), - &domain.rho, - ))?; - let pk_d = get_validated_pk_d(&diversifier)?; - let recipient = Address::from_parts(diversifier, pk_d); - - let asset = match note_version(plaintext.0.as_ref())? { - 0x02 => AssetBase::native(), - 0x03 => { - let bytes = plaintext.0[COMPACT_NOTE_SIZE_V2..COMPACT_NOTE_SIZE_V3] - .try_into() - .unwrap(); - AssetBase::from_bytes(bytes).unwrap() - } - _ => panic!("invalid note version"), - }; - - let note = Option::from(Note::from_parts(recipient, value, asset, domain.rho, rseed))?; - Some((note, recipient)) -} - -/// Orchard-specific note encryption logic. -#[derive(Debug)] -pub struct OrchardDomainV3 { - rho: Rho, -} - -impl OrchardDomainV3 { - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_action(act: &Action) -> Self { - Self { rho: act.rho() } - } - - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_compact_action(act: &CompactAction) -> Self { - Self { rho: act.rho() } - } -} - -impl Domain for OrchardDomainV3 { - type EphemeralSecretKey = EphemeralSecretKey; - type EphemeralPublicKey = EphemeralPublicKey; - type PreparedEphemeralPublicKey = PreparedEphemeralPublicKey; - type SharedSecret = SharedSecret; - type SymmetricKey = Hash; - type Note = Note; - type Recipient = Address; - type DiversifiedTransmissionKey = DiversifiedTransmissionKey; - type IncomingViewingKey = PreparedIncomingViewingKey; - type OutgoingViewingKey = OutgoingViewingKey; - type ValueCommitment = ValueCommitment; - type ExtractedCommitment = ExtractedNoteCommitment; - type ExtractedCommitmentBytes = [u8; 32]; - type Memo = [u8; MEMO_SIZE]; - - type NotePlaintextBytes = NotePlaintextBytes; - type NoteCiphertextBytes = NoteCiphertextBytes; - type CompactNotePlaintextBytes = CompactNotePlaintextBytes; - type CompactNoteCiphertextBytes = CompactNoteCiphertextBytes; - - fn derive_esk(note: &Self::Note) -> Option { - Some(note.esk()) - } - - fn get_pk_d(note: &Self::Note) -> Self::DiversifiedTransmissionKey { - *note.recipient().pk_d() - } - - fn prepare_epk(epk: Self::EphemeralPublicKey) -> Self::PreparedEphemeralPublicKey { - PreparedEphemeralPublicKey::new(epk) - } - - fn ka_derive_public( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> Self::EphemeralPublicKey { - esk.derive_public(note.recipient().g_d()) - } - - fn ka_agree_enc( - esk: &Self::EphemeralSecretKey, - pk_d: &Self::DiversifiedTransmissionKey, - ) -> Self::SharedSecret { - esk.agree(pk_d) - } - - fn ka_agree_dec( - ivk: &Self::IncomingViewingKey, - epk: &Self::PreparedEphemeralPublicKey, - ) -> Self::SharedSecret { - epk.agree(ivk) - } - - fn kdf(secret: Self::SharedSecret, ephemeral_key: &EphemeralKeyBytes) -> Self::SymmetricKey { - secret.kdf_orchard(ephemeral_key) - } - - fn note_plaintext_bytes(note: &Self::Note, memo: &Self::Memo) -> NotePlaintextBytes { - let mut np = [0u8; NOTE_PLAINTEXT_SIZE_V3]; - np[0] = 0x03; - np[1..12].copy_from_slice(note.recipient().diversifier().as_array()); - np[12..20].copy_from_slice(¬e.value().to_bytes()); - np[20..52].copy_from_slice(note.rseed().as_bytes()); - np[52..84].copy_from_slice(¬e.asset().to_bytes()); - np[84..].copy_from_slice(memo); - NotePlaintextBytes(np) - } - - fn derive_ock( - ovk: &Self::OutgoingViewingKey, - cv: &Self::ValueCommitment, - cmstar_bytes: &Self::ExtractedCommitmentBytes, - ephemeral_key: &EphemeralKeyBytes, - ) -> OutgoingCipherKey { - prf_ock_orchard(ovk, cv, cmstar_bytes, ephemeral_key) - } - - fn outgoing_plaintext_bytes( - note: &Self::Note, - esk: &Self::EphemeralSecretKey, - ) -> OutPlaintextBytes { - let mut op = [0; OUT_PLAINTEXT_SIZE]; - op[..32].copy_from_slice(¬e.recipient().pk_d().to_bytes()); - op[32..].copy_from_slice(&esk.0.to_repr()); - OutPlaintextBytes(op) - } - - fn epk_bytes(epk: &Self::EphemeralPublicKey) -> EphemeralKeyBytes { - epk.to_bytes() - } - - fn epk(ephemeral_key: &EphemeralKeyBytes) -> Option { - EphemeralPublicKey::from_bytes(&ephemeral_key.0).into() - } - - fn cmstar(note: &Self::Note) -> Self::ExtractedCommitment { - note.commitment().into() - } - - fn parse_note_plaintext_without_memo_ivk( - &self, - ivk: &Self::IncomingViewingKey, - plaintext: &CompactNotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |diversifier| { - Some(DiversifiedTransmissionKey::derive(ivk, diversifier)) - }) - } - - fn parse_note_plaintext_without_memo_ovk( - &self, - pk_d: &Self::DiversifiedTransmissionKey, - plaintext: &CompactNotePlaintextBytes, - ) -> Option<(Self::Note, Self::Recipient)> { - orchard_parse_note_plaintext_without_memo(self, plaintext, |_| Some(*pk_d)) - } - - fn extract_memo( - &self, - plaintext: &NotePlaintextBytes, - ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { - let (compact, memo) = plaintext.0.split_at(COMPACT_NOTE_SIZE_V3); - ( - CompactNotePlaintextBytes(compact.try_into().unwrap()), - memo.try_into().unwrap(), - ) - } - - fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { - DiversifiedTransmissionKey::from_bytes(out_plaintext.0[0..32].try_into().unwrap()).into() - } - - fn extract_esk(out_plaintext: &OutPlaintextBytes) -> Option { - EphemeralSecretKey::from_bytes(out_plaintext.0[32..OUT_PLAINTEXT_SIZE].try_into().unwrap()) - .into() - } -} - -impl BatchDomain for OrchardDomainV3 { - fn batch_kdf<'a>( - items: impl Iterator, &'a EphemeralKeyBytes)>, - ) -> Vec> { - let (shared_secrets, ephemeral_keys): (Vec<_>, Vec<_>) = items.unzip(); - - SharedSecret::batch_to_affine(shared_secrets) - .zip(ephemeral_keys.into_iter()) - .map(|(secret, ephemeral_key)| { - secret.map(|dhsecret| SharedSecret::kdf_orchard_inner(dhsecret, ephemeral_key)) - }) - .collect() - } -} - -/// Implementation of in-band secret distribution for Orchard bundles. -pub type OrchardNoteEncryption = zcash_note_encryption_zsa::NoteEncryption; - -impl ShieldedOutput for Action { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.encrypted_note().epk_bytes) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx().to_bytes() - } - - fn enc_ciphertext(&self) -> Option { - Some(NoteCiphertextBytes(self.encrypted_note().enc_ciphertext)) - } - - fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { - CompactNoteCiphertextBytes( - self.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V3] - .try_into() - .unwrap(), - ) - } -} - -/// A compact Action for light clients. -pub struct CompactAction { - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: CompactNoteCiphertextBytes, -} - -impl fmt::Debug for CompactAction { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "CompactAction") - } -} - -impl From<&Action> for CompactAction -where - Action: ShieldedOutput, -{ - fn from(action: &Action) -> Self { - CompactAction { - nullifier: *action.nullifier(), - cmx: *action.cmx(), - ephemeral_key: action.ephemeral_key(), - enc_ciphertext: CompactNoteCiphertextBytes( - action.encrypted_note().enc_ciphertext[..COMPACT_NOTE_SIZE_V3] - .try_into() - .unwrap(), - ), - } - } -} - -impl ShieldedOutput for CompactAction { - fn ephemeral_key(&self) -> EphemeralKeyBytes { - EphemeralKeyBytes(self.ephemeral_key.0) - } - - fn cmstar_bytes(&self) -> [u8; 32] { - self.cmx.to_bytes() - } - - fn enc_ciphertext(&self) -> Option { - None - } - - fn enc_ciphertext_compact(&self) -> CompactNoteCiphertextBytes { - self.enc_ciphertext.clone() - } -} - -impl CompactAction { - /// Create a CompactAction from its constituent parts - pub fn from_parts( - nullifier: Nullifier, - cmx: ExtractedNoteCommitment, - ephemeral_key: EphemeralKeyBytes, - enc_ciphertext: CompactNoteCiphertextBytes, - ) -> Self { - Self { - nullifier, - cmx, - ephemeral_key, - enc_ciphertext, - } - } - - ///Returns the nullifier of the note being spent. - pub fn nullifier(&self) -> Nullifier { - self.nullifier - } - - /// Obtains the [`Rho`] value that was used to construct the new note being created. - pub fn rho(&self) -> Rho { - Rho::from_nf_old(self.nullifier) - } -} - -#[cfg(test)] -mod tests { - use proptest::prelude::*; - use rand::rngs::OsRng; - use zcash_note_encryption_zsa::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, - EphemeralKeyBytes, - }; - - use super::{ - note_version, orchard_parse_note_plaintext_without_memo, prf_ock_orchard, CompactAction, - OrchardDomainV3, OrchardNoteEncryption, - }; - use crate::{ - action::Action, - keys::{ - DiversifiedTransmissionKey, Diversifier, EphemeralSecretKey, IncomingViewingKey, - OutgoingViewingKey, PreparedIncomingViewingKey, - }, - note::{ - testing::arb_note, AssetBase, ExtractedNoteCommitment, Nullifier, RandomSeed, Rho, - TransmittedNoteCiphertext, - }, - primitives::redpallas, - value::{NoteValue, ValueCommitment}, - Address, Note, - }; - - proptest! { - #[test] - fn test_encoding_roundtrip( - note in arb_note(NoteValue::from_raw(100)), - ) { - let memo = &crate::test_vectors::note_encryption::test_vectors()[0].memo; - - // Encode. - let mut plaintext = OrchardDomainV3::note_plaintext_bytes(¬e, memo); - - // Decode. - let domain = OrchardDomainV3 { rho: note.rho() }; - let parsed_version = note_version(plaintext.as_mut()).unwrap(); - let (compact,parsed_memo) = domain.extract_memo(&plaintext); - - let (parsed_note, parsed_recipient) = orchard_parse_note_plaintext_without_memo(&domain, &compact, - |diversifier| { - assert_eq!(diversifier, ¬e.recipient().diversifier()); - Some(*note.recipient().pk_d()) - } - ).expect("Plaintext parsing failed"); - - // Check. - assert_eq!(parsed_note, note); - assert_eq!(parsed_recipient, note.recipient()); - assert_eq!(&parsed_memo, memo); - assert_eq!(parsed_version, 0x03); - } - } - - #[test] - fn test_vectors() { - let test_vectors = crate::test_vectors::note_encryption_v3::test_vectors(); - - for tv in test_vectors { - // - // Load the test vector components - // - - // Recipient key material - let ivk = PreparedIncomingViewingKey::new( - &IncomingViewingKey::from_bytes(&tv.incoming_viewing_key).unwrap(), - ); - let ovk = OutgoingViewingKey::from(tv.ovk); - let d = Diversifier::from_bytes(tv.default_d); - let pk_d = DiversifiedTransmissionKey::from_bytes(&tv.default_pk_d).unwrap(); - - // Received Action - let cv_net = ValueCommitment::from_bytes(&tv.cv_net).unwrap(); - let nf_old = Nullifier::from_bytes(&tv.rho).unwrap(); - let rho = Rho::from_nf_old(nf_old); - let cmx = ExtractedNoteCommitment::from_bytes(&tv.cmx).unwrap(); - - let esk = EphemeralSecretKey::from_bytes(&tv.esk).unwrap(); - let ephemeral_key = EphemeralKeyBytes(tv.ephemeral_key); - - // Details about the expected note - let value = NoteValue::from_raw(tv.v); - let rseed = RandomSeed::from_bytes(tv.rseed, &rho).unwrap(); - - // - // Test the individual components - // - - let shared_secret = esk.agree(&pk_d); - assert_eq!(shared_secret.to_bytes(), tv.shared_secret); - - let k_enc = shared_secret.kdf_orchard(&ephemeral_key); - assert_eq!(k_enc.as_bytes(), tv.k_enc); - - let ock = prf_ock_orchard(&ovk, &cv_net, &cmx.to_bytes(), &ephemeral_key); - assert_eq!(ock.as_ref(), tv.ock); - - let recipient = Address::from_parts(d, pk_d); - - let asset = AssetBase::from_bytes(&tv.asset).unwrap(); - - let note = Note::from_parts(recipient, value, asset, rho, rseed).unwrap(); - assert_eq!(ExtractedNoteCommitment::from(note.commitment()), cmx); - - let action = Action::from_parts( - // rho is the nullifier in the receiving Action. - nf_old, - // We don't need a valid rk for this test. - redpallas::VerificationKey::dummy(), - cmx, - TransmittedNoteCiphertext { - epk_bytes: ephemeral_key.0, - enc_ciphertext: tv.c_enc, - out_ciphertext: tv.c_out, - }, - cv_net.clone(), - (), - ); - - // - // Test decryption - // (Tested first because it only requires immutable references.) - // - - let domain = OrchardDomainV3 { rho }; - - match try_note_decryption(&domain, &ivk, &action) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Note decryption failed"), - } - - match try_compact_note_decryption(&domain, &ivk, &CompactAction::from(&action)) { - Some((decrypted_note, decrypted_to)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - } - None => panic!("Compact note decryption failed"), - } - - match try_output_recovery_with_ovk(&domain, &ovk, &action, &cv_net, &tv.c_out) { - Some((decrypted_note, decrypted_to, decrypted_memo)) => { - assert_eq!(decrypted_note, note); - assert_eq!(decrypted_to, recipient); - assert_eq!(&decrypted_memo[..], &tv.memo[..]); - } - None => panic!("Output recovery failed"), - } - - // - // Test encryption - // - - let ne = OrchardNoteEncryption::new_with_esk(esk, Some(ovk), note, tv.memo); - - assert_eq!(ne.encrypt_note_plaintext().as_ref(), &tv.c_enc[..]); - assert_eq!( - &ne.encrypt_outgoing_plaintext(&cv_net, &cmx, &mut OsRng)[..], - &tv.c_out[..] - ); - } - } -} diff --git a/src/orchard_flavor.rs b/src/orchard_flavor.rs new file mode 100644 index 000000000..481aba5c1 --- /dev/null +++ b/src/orchard_flavor.rs @@ -0,0 +1,17 @@ +//! Defines types and traits for the variations ("flavors") of the Orchard protocol (Vanilla and ZSA). + +use crate::{bundle::OrchardHash, circuit::OrchardCircuit, note_encryption::OrchardDomainCommon}; + +/// Represents the "Vanilla" variation ("flavor") of the Orchard protocol. +#[derive(Debug, Clone, Default)] +pub struct OrchardVanilla; + +/// Represents the "ZSA" variation ("flavor") of the Orchard protocol. +#[derive(Debug, Clone, Default)] +pub struct OrchardZSA; + +/// A trait binding the common functionality between different Orchard protocol flavors. +pub trait OrchardFlavor: OrchardDomainCommon + OrchardCircuit + OrchardHash {} + +impl OrchardFlavor for OrchardVanilla {} +impl OrchardFlavor for OrchardZSA {} diff --git a/src/test_vectors.rs b/src/test_vectors.rs index 3cea120cd..b97f11b04 100644 --- a/src/test_vectors.rs +++ b/src/test_vectors.rs @@ -3,5 +3,5 @@ pub(crate) mod commitment_tree; pub(crate) mod issuance_auth_sig; pub(crate) mod keys; pub(crate) mod merkle_path; -pub(crate) mod note_encryption; -pub(crate) mod note_encryption_v3; +pub(crate) mod note_encryption_vanilla; +pub(crate) mod note_encryption_zsa; diff --git a/src/test_vectors/asset_base.rs b/src/test_vectors/asset_base.rs index 041d80471..4cfaa0207 100644 --- a/src/test_vectors/asset_base.rs +++ b/src/test_vectors/asset_base.rs @@ -1,4 +1,4 @@ -// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_asset_base) +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_asset_base) pub(crate) struct TestVector { pub(crate) key: [u8; 32], @@ -10,1022 +10,1022 @@ pub(crate) fn test_vectors() -> Vec { vec![ TestVector { key: [ - 0x16, 0x88, 0x4f, 0x1d, 0xbc, 0x92, 0x90, 0x89, 0xa4, 0x17, 0x6e, 0x84, 0x0b, 0xb5, - 0x81, 0xc8, 0x0e, 0x16, 0xe9, 0xb1, 0xab, 0xd6, 0x54, 0xe6, 0x2c, 0x8b, 0x0b, 0x95, - 0x70, 0x20, 0xb7, 0x48, + 0x4b, 0xec, 0xe1, 0xff, 0x00, 0xe2, 0xed, 0x77, 0x64, 0xae, 0x6b, 0xe2, 0x0d, 0x2f, + 0x67, 0x22, 0x04, 0xfc, 0x86, 0xcc, 0xed, 0xd6, 0xfc, 0x1f, 0x71, 0xdf, 0x02, 0xc7, + 0x51, 0x6d, 0x9f, 0x31, ], description: [ - 0x31, 0xc3, 0x85, 0xc7, 0xa7, 0x38, 0xc6, 0x88, 0x66, 0xc7, 0x8d, 0xc6, 0xa9, 0xc7, - 0xae, 0xc5, 0xb7, 0xc3, 0xaf, 0xc6, 0x85, 0xc7, 0x9f, 0xc6, 0x88, 0xe2, 0xb1, 0xbc, - 0xe1, 0x9a, 0xb7, 0xc3, 0x8c, 0xc7, 0x86, 0xc5, 0xbd, 0xc9, 0x80, 0xc3, 0x84, 0x4e, - 0x76, 0xc6, 0xa9, 0xc3, 0x91, 0x32, 0xc4, 0xab, 0xc9, 0x81, 0xce, 0x8c, 0xc4, 0xa7, - 0xc5, 0x97, 0xc6, 0xa6, 0xc4, 0xb3, 0xc5, 0xaa, 0xc7, 0x95, 0xc8, 0x99, 0xe1, 0x9b, - 0x91, 0xe1, 0x9a, 0xb5, 0xc7, 0x83, 0xc2, 0xa9, 0xc7, 0x80, 0xc7, 0xa5, 0xc8, 0x9d, - 0xce, 0x88, 0xc9, 0x8a, 0xc5, 0x92, 0xc7, 0x91, 0x5d, 0xc3, 0x93, 0x43, 0xc4, 0xa9, - 0xc8, 0x82, 0x25, 0xc3, 0xbb, 0xc3, 0x9d, 0xc8, 0xaf, 0xe1, 0x9a, 0xa5, 0xc8, 0xa0, - 0xc8, 0x8c, 0xc6, 0x86, 0xc3, 0xa4, 0xe1, 0x9b, 0x80, 0xc4, 0xbc, 0xc6, 0xb3, 0xc5, - 0x81, 0xe1, 0x9b, 0x97, 0xc5, 0x8e, 0xc8, 0x9d, 0xc6, 0xa1, 0xce, 0x8a, 0xc7, 0x88, - 0xc6, 0xb5, 0xc8, 0x83, 0xc3, 0xa2, 0xc4, 0x92, 0xc5, 0xb0, 0xc3, 0x8f, 0xc7, 0xab, - 0xe1, 0x9a, 0xac, 0xc2, 0xaf, 0xc7, 0x8a, 0x37, 0x72, 0x74, 0xe2, 0xb1, 0xbb, 0xc5, - 0x83, 0xe1, 0x9a, 0xa9, 0xe2, 0xb1, 0xa5, 0x5c, 0xc3, 0xbd, 0xc3, 0x88, 0xc9, 0x86, - 0x77, 0xc2, 0xb1, 0xc5, 0x9d, 0xc7, 0xa4, 0xc8, 0x9b, 0xcd, 0xb4, 0xc7, 0x81, 0xc4, - 0x9c, 0xc2, 0xbe, 0xe2, 0xb1, 0xa9, 0xc8, 0x82, 0xc6, 0xa0, 0xe1, 0x9a, 0xb5, 0xc2, - 0xa8, 0xc5, 0x82, 0xc3, 0x9a, 0xc6, 0xac, 0xc4, 0xa0, 0xc4, 0xb5, 0xc8, 0x93, 0xe2, - 0xb1, 0xa0, 0xc3, 0xbe, 0xc9, 0x84, 0x77, 0xc4, 0xb4, 0xc8, 0xbe, 0x5c, 0xc6, 0xbe, - 0xc3, 0xb0, 0xc9, 0x84, 0x28, 0xc6, 0x8d, 0xc3, 0xb2, 0xc8, 0xaa, 0xc8, 0x8f, 0xc8, - 0xb2, 0xc7, 0x8b, 0xcd, 0xba, 0xc3, 0xb5, 0xc9, 0x8e, 0xc4, 0xb4, 0xe2, 0xb1, 0xaa, - 0xe1, 0x9a, 0xab, 0xc2, 0xbd, 0xc8, 0xac, 0xc7, 0x8e, 0xc8, 0x95, 0xc2, 0xa9, 0xe1, - 0x9a, 0xa2, 0xe1, 0x9b, 0x8b, 0xc7, 0x98, 0xc6, 0x94, 0xe1, 0x9b, 0x9f, 0xc5, 0x98, - 0xc4, 0xbd, 0x39, 0x40, 0xc8, 0xa9, 0xc5, 0x94, 0x53, 0xe1, 0x9b, 0xac, 0xc8, 0xa0, - 0xc5, 0xb3, 0x76, 0x74, 0xc8, 0xa3, 0xc3, 0x81, 0x68, 0xcd, 0xbc, 0xc7, 0xba, 0x6e, - 0x73, 0xc5, 0x8f, 0xce, 0x8c, 0xc7, 0x9d, 0xc5, 0xaf, 0x45, 0xc3, 0xb0, 0xc3, 0x86, - 0xc4, 0x91, 0xc8, 0x94, 0xc5, 0x93, 0xc4, 0x81, 0xe2, 0xb1, 0xa1, 0xc7, 0x92, 0xc4, - 0xb0, 0xc8, 0x87, 0x4e, 0x51, 0xc6, 0xab, 0xc4, 0xb2, 0xe1, 0x9b, 0x8d, 0xc4, 0x8a, - 0xc4, 0xa9, 0xc3, 0xb3, 0xe1, 0x9b, 0x8f, 0xce, 0x8a, 0x3b, 0xc7, 0xa9, 0xc5, 0x9c, - 0x45, 0xe2, 0xb1, 0xab, 0xc6, 0xbc, 0xc2, 0xb5, 0xe1, 0x9b, 0x8d, 0xc4, 0x84, 0xe2, - 0xb1, 0xa8, 0xc7, 0xa9, 0xc6, 0x94, 0xc6, 0xa6, 0xc6, 0xba, 0xe1, 0x9b, 0xab, 0xc2, - 0xac, 0xc4, 0x8e, 0xe2, 0xb1, 0xb9, 0xc2, 0xb0, 0xce, 0x88, 0xc5, 0xb7, 0x70, 0xe2, - 0xb1, 0xac, 0xce, 0x86, 0x54, 0xc9, 0x8d, 0xc4, 0xa6, 0xcd, 0xb7, 0xc4, 0xaf, 0x75, - 0x3b, 0x3f, 0xc6, 0x81, 0xc8, 0xab, 0xc8, 0xa4, 0x78, 0xc8, 0xab, 0xc4, 0xbb, 0x2e, - 0xc8, 0x89, 0xc3, 0xb0, 0xc5, 0x90, 0x74, 0xc2, 0xa8, 0xc4, 0xa4, 0xc5, 0xbf, 0xe1, - 0x9a, 0xb2, 0xc2, 0xbc, 0x4b, 0xc6, 0xbf, 0xc7, 0xbc, 0xc7, 0xa5, 0xc3, 0xba, 0xc3, - 0x86, 0xc4, 0xb4, 0xc8, 0xa4, 0xc3, 0x9c, 0xe2, 0xb1, 0xb0, 0xc5, 0x92, 0xc4, 0x97, - 0xe1, 0x9b, 0xaa, 0xc6, 0xbf, 0xc5, 0x9e, 0xc7, 0x84, 0xc4, 0xaf, 0xc8, 0xaa, 0xc8, - 0x89, 0xc4, 0xb3, 0xc2, 0xbb, 0xc4, 0x97, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x41, 0xb7, 0x75, 0x0a, 0x66, 0x59, 0xb2, 0xc8, 0x0f, 0x56, 0x7d, 0x67, 0x78, 0xd1, - 0x2d, 0x81, 0xc4, 0x7a, 0x46, 0xef, 0xdf, 0xfb, 0x63, 0x80, 0x6c, 0x01, 0x7c, 0xa5, - 0x61, 0x50, 0xa7, 0xa6, + 0xa7, 0x62, 0x5a, 0x60, 0xff, 0x6a, 0xdc, 0x49, 0x8a, 0xc2, 0xf5, 0x7b, 0x4d, 0xbe, + 0xd3, 0x67, 0x26, 0xba, 0xe6, 0x40, 0x1f, 0x3e, 0x01, 0xc2, 0x61, 0x17, 0x0b, 0x02, + 0x81, 0x0f, 0x08, 0x19, ], }, TestVector { key: [ - 0x72, 0x73, 0xb6, 0x57, 0xd9, 0x71, 0xa4, 0x5e, 0x72, 0x24, 0x0c, 0x7a, 0xaa, 0xa7, - 0xd0, 0x68, 0x5d, 0x06, 0xd7, 0x99, 0x9b, 0x0a, 0x19, 0xc4, 0xce, 0xa3, 0x27, 0x88, - 0xa6, 0xab, 0x51, 0x3d, + 0x16, 0x88, 0x4f, 0x1d, 0xbc, 0x92, 0x90, 0x89, 0xa4, 0x17, 0x6e, 0x84, 0x0b, 0xb5, + 0x81, 0xc8, 0x0e, 0x16, 0xe9, 0xb1, 0xab, 0xd6, 0x54, 0xe6, 0x2c, 0x8b, 0x0b, 0x95, + 0x70, 0x20, 0xb7, 0x48, ], description: [ - 0xc5, 0x96, 0xc6, 0xac, 0xc4, 0xb3, 0x28, 0x5f, 0xc2, 0xa5, 0x66, 0xe1, 0x9b, 0x8c, - 0xc8, 0xa5, 0xc3, 0x95, 0xc4, 0xaa, 0xc3, 0xa9, 0xc2, 0xbd, 0xe2, 0xb1, 0xbb, 0x52, - 0x48, 0xe1, 0x9b, 0x9f, 0xe2, 0xb1, 0xaf, 0xe1, 0x9b, 0x87, 0xc7, 0x9f, 0x2b, 0xe1, - 0x9a, 0xab, 0xc6, 0x97, 0x6b, 0xc8, 0x8e, 0xe1, 0x9a, 0xbb, 0xc6, 0xa0, 0xc7, 0x89, - 0xc2, 0xbd, 0xc8, 0xad, 0xc4, 0xbe, 0xe1, 0x9b, 0x82, 0xc8, 0x9c, 0xe1, 0x9a, 0xac, - 0x3f, 0xe1, 0x9a, 0xa2, 0xc9, 0x8c, 0xe1, 0x9a, 0xa2, 0xe1, 0x9b, 0x86, 0xc5, 0x9d, - 0xc4, 0xb4, 0xc7, 0x80, 0xc3, 0xb5, 0x71, 0x6b, 0x6c, 0xc8, 0x96, 0xc7, 0xbb, 0xc8, - 0x9a, 0xc7, 0x90, 0xc2, 0xb1, 0xc4, 0x89, 0xc3, 0x99, 0xc3, 0xbd, 0xc7, 0xae, 0xc2, - 0xa3, 0xc4, 0xa7, 0x58, 0xc4, 0x80, 0xc4, 0x9f, 0xc7, 0xbb, 0xc4, 0x8b, 0xc6, 0x8d, - 0xc5, 0x98, 0xc2, 0xb4, 0xc5, 0x93, 0xc4, 0x9c, 0xc8, 0x83, 0xc7, 0xbc, 0x30, 0xc4, - 0x87, 0xc3, 0x85, 0xe1, 0x9a, 0xb2, 0xc4, 0xa8, 0xc7, 0xb8, 0xc6, 0xab, 0x36, 0xc4, - 0xa6, 0x3b, 0xc7, 0xa3, 0xc7, 0x82, 0xcd, 0xb2, 0xc7, 0x80, 0xc3, 0xb0, 0xc2, 0xbd, - 0xe2, 0xb1, 0xb4, 0xc6, 0x93, 0xc4, 0x8f, 0x5d, 0xc6, 0x8f, 0x35, 0xc9, 0x85, 0xe1, - 0x9b, 0x95, 0xc7, 0xa4, 0xe2, 0xb1, 0xbf, 0xc4, 0x85, 0xc5, 0xa4, 0xc7, 0x83, 0xc8, - 0x81, 0xc8, 0x89, 0xc8, 0x98, 0xc5, 0xac, 0xe2, 0xb1, 0xb4, 0xc8, 0x8a, 0xc7, 0xa1, - 0xc7, 0x9d, 0xc6, 0xae, 0xc6, 0x9c, 0xc6, 0x98, 0xc3, 0xa3, 0xc4, 0x9b, 0x43, 0xe1, - 0x9b, 0x82, 0xc2, 0xa3, 0xc3, 0xa6, 0xc5, 0x85, 0xc8, 0x89, 0xe1, 0x9b, 0x99, 0x5f, - 0xc4, 0xa9, 0xe1, 0x9b, 0x95, 0xc2, 0xb7, 0xc3, 0x89, 0xe2, 0xb1, 0xb7, 0xc4, 0x96, - 0xe2, 0xb1, 0xa2, 0x5b, 0xc3, 0xac, 0x58, 0xc6, 0xa9, 0xcd, 0xbd, 0xc8, 0xa1, 0xe2, - 0xb1, 0xa6, 0xc8, 0x8e, 0xc5, 0xb3, 0xc7, 0x93, 0xc6, 0xa1, 0xc9, 0x8d, 0xc5, 0xa2, - 0x29, 0xce, 0x8c, 0xe1, 0x9b, 0x99, 0xc5, 0xaf, 0xc8, 0xbd, 0x2b, 0xc7, 0xb2, 0xc7, - 0xba, 0xcd, 0xb7, 0xc2, 0xbc, 0xe1, 0x9b, 0xa4, 0xc7, 0xb9, 0xc3, 0x8d, 0xe2, 0xb1, - 0xa0, 0xc2, 0xa4, 0xc8, 0x98, 0xc8, 0xa4, 0x49, 0xc5, 0xbb, 0xc3, 0x96, 0xc3, 0x94, - 0x5c, 0xc5, 0x8e, 0xe2, 0xb1, 0xae, 0x73, 0x74, 0xc6, 0xab, 0xc7, 0x86, 0xe2, 0xb1, - 0xb3, 0xe1, 0x9b, 0x8f, 0xc8, 0xb3, 0xc4, 0xa6, 0xc6, 0xb2, 0xc8, 0xa4, 0xc7, 0x86, - 0xc7, 0xa8, 0xe1, 0x9b, 0xa2, 0xc8, 0xaa, 0xc4, 0x92, 0xcd, 0xb2, 0x7e, 0xc9, 0x8d, - 0x4e, 0x45, 0xc6, 0x8a, 0xc6, 0xae, 0xc4, 0x8d, 0x3f, 0x59, 0xc5, 0x96, 0xe2, 0xb1, - 0xbd, 0xe1, 0x9a, 0xbc, 0xc3, 0x90, 0xc8, 0x8e, 0xc3, 0xa1, 0xc7, 0xad, 0xe1, 0x9a, - 0xb9, 0xc5, 0x8e, 0xe1, 0x9b, 0xa5, 0xe1, 0x9a, 0xb5, 0xc6, 0x83, 0xc7, 0x8e, 0xc8, - 0xbf, 0xc2, 0xbc, 0xc5, 0x8a, 0xc4, 0x8e, 0xcd, 0xb5, 0xc5, 0x97, 0xc4, 0x8f, 0xc2, - 0xaa, 0xc7, 0xaf, 0xc3, 0xbb, 0xc2, 0xa2, 0x49, 0x32, 0xc7, 0xa9, 0xc2, 0xb4, 0xe1, - 0x9b, 0xa1, 0xe1, 0x9b, 0xa3, 0xe2, 0xb1, 0xbf, 0x53, 0xc8, 0x96, 0xc8, 0xac, 0xc8, - 0xa3, 0xc3, 0xa0, 0x29, 0xe1, 0x9b, 0x89, 0xc5, 0xb3, 0xc6, 0xb2, 0xc3, 0xab, 0xc3, - 0x99, 0xc4, 0x9d, 0xc6, 0xb6, 0xc4, 0xa3, 0x3b, 0xe1, 0x9b, 0xa6, 0xc6, 0x95, 0xe1, - 0x9b, 0xa5, 0xc2, 0xbc, 0xc7, 0xa0, 0xc7, 0xa3, 0xe1, 0x9b, 0x8a, 0xc4, 0xb4, 0xc9, - 0x80, 0x64, 0x6f, 0xc6, 0x9e, 0xc4, 0x94, 0xc8, 0x8c, 0xc6, 0xa4, 0xc7, 0x96, 0xc3, - 0x9b, 0xc7, 0x91, 0xc5, 0x9d, 0x6d, 0xc7, 0x8a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0xea, 0x1b, 0xf2, 0x91, 0x8d, 0xe2, 0xfb, 0x1a, 0x26, 0x10, 0x83, 0x25, 0x20, 0xbd, - 0x80, 0x71, 0x98, 0xe1, 0x26, 0x73, 0xab, 0xd2, 0x3b, 0x24, 0x1d, 0xba, 0x06, 0x08, - 0x20, 0x2e, 0x56, 0x17, + 0xb9, 0xfc, 0x57, 0x2c, 0x5a, 0xd8, 0x81, 0x26, 0xff, 0x6b, 0x7c, 0x65, 0x9f, 0x78, + 0x74, 0x91, 0xf7, 0xc2, 0x7c, 0x5f, 0xe4, 0xff, 0x24, 0x20, 0x8a, 0x02, 0xbc, 0x94, + 0x5e, 0x55, 0x4a, 0xbf, ], }, TestVector { key: [ - 0xec, 0x05, 0xbb, 0x7f, 0x06, 0x5e, 0x25, 0x6f, 0xf4, 0x54, 0xf8, 0xa8, 0xdf, 0x6f, - 0x2f, 0x9b, 0x8a, 0x8c, 0x95, 0x08, 0xca, 0xac, 0xfe, 0xe9, 0x52, 0x1c, 0xbe, 0x68, - 0x9d, 0xd1, 0x12, 0x0f, + 0xd4, 0x22, 0x9e, 0x19, 0x5e, 0x25, 0xf6, 0x02, 0xa2, 0x18, 0x61, 0x22, 0xcb, 0x4e, + 0x78, 0x76, 0x7b, 0x3c, 0x66, 0xac, 0x39, 0x08, 0x08, 0xd2, 0xd1, 0xb4, 0x04, 0x42, + 0xda, 0x7f, 0x00, 0x66, ], description: [ - 0xc7, 0x82, 0x7e, 0xc5, 0xb9, 0xc6, 0xa6, 0xc5, 0xa3, 0xe1, 0x9a, 0xae, 0xe2, 0xb1, - 0xa6, 0xc8, 0xb2, 0xc8, 0xbc, 0xc5, 0x9f, 0xc8, 0x83, 0xc3, 0x82, 0xc4, 0x9a, 0xe2, - 0xb1, 0xa8, 0xc4, 0x88, 0xe2, 0xb1, 0xad, 0xc8, 0x98, 0xc3, 0xbb, 0xc3, 0x92, 0xc4, - 0xb7, 0xc7, 0xba, 0xc7, 0x8b, 0x72, 0xc6, 0x8d, 0x75, 0xc3, 0x82, 0xc3, 0xad, 0xc5, - 0x8a, 0xc7, 0xb1, 0xc8, 0xbb, 0xc5, 0x9e, 0xe2, 0xb1, 0xb3, 0xc3, 0xa5, 0xe1, 0x9a, - 0xb8, 0xc5, 0x81, 0x63, 0xc5, 0x98, 0xe1, 0x9b, 0x80, 0xc5, 0x86, 0xc4, 0xa9, 0xe1, - 0x9b, 0xa4, 0x60, 0xc8, 0xa0, 0xc3, 0x97, 0xc4, 0xa4, 0xc5, 0x81, 0xc3, 0x95, 0xc4, - 0xb0, 0xc2, 0xb2, 0xe1, 0x9b, 0x94, 0xc7, 0x8c, 0x46, 0x60, 0xe2, 0xb1, 0xa0, 0xc4, - 0xa5, 0xc7, 0xa9, 0xc6, 0xa8, 0xe1, 0x9b, 0x9c, 0xc5, 0xb4, 0xc5, 0x82, 0xc8, 0x80, - 0xc4, 0x9b, 0xe2, 0xb1, 0xa7, 0xc4, 0x95, 0xc5, 0x93, 0xc8, 0x83, 0xc4, 0x9f, 0xc4, - 0xa1, 0xc4, 0xb1, 0xc3, 0xb0, 0xc8, 0xa5, 0xc6, 0x87, 0xc5, 0xb5, 0xe1, 0x9b, 0xaf, - 0xc9, 0x8e, 0xc2, 0xac, 0xe2, 0xb1, 0xba, 0xc7, 0x9f, 0xc5, 0xa1, 0xc6, 0x94, 0xc3, - 0xa5, 0xc8, 0x8b, 0xc8, 0xa5, 0xe2, 0xb1, 0xb2, 0xc7, 0xab, 0xe1, 0x9b, 0x91, 0xc3, - 0xaa, 0xc6, 0xb5, 0xc4, 0xbf, 0xc5, 0x80, 0xc4, 0xb4, 0xc3, 0xb6, 0xe2, 0xb1, 0xb3, - 0x5e, 0xc8, 0xb6, 0xe1, 0x9a, 0xab, 0xe2, 0xb1, 0xa7, 0xc5, 0x98, 0xe1, 0x9b, 0x9e, - 0x69, 0xe1, 0x9b, 0x8b, 0xe2, 0xb1, 0xbf, 0xc9, 0x88, 0xe2, 0xb1, 0xb5, 0x71, 0x29, - 0xc6, 0x85, 0xc7, 0xab, 0xe1, 0x9b, 0xa9, 0x6d, 0xc7, 0x90, 0xc3, 0x9b, 0xc5, 0x8e, - 0xe1, 0x9b, 0x87, 0xc7, 0x9f, 0xc5, 0xa3, 0xc5, 0xb9, 0x74, 0x7d, 0xc4, 0x94, 0xe1, - 0x9b, 0x93, 0xc7, 0xbc, 0xc8, 0x96, 0x58, 0xe2, 0xb1, 0xaf, 0xe2, 0xb1, 0xbc, 0xc2, - 0xb4, 0xc8, 0xbd, 0xc8, 0xab, 0xc4, 0xb7, 0x42, 0xc2, 0xb5, 0xc7, 0xa5, 0xc5, 0x9c, - 0xcd, 0xb3, 0xc9, 0x87, 0xe2, 0xb1, 0xa0, 0xc4, 0xa3, 0xc8, 0xad, 0xc5, 0x90, 0xe1, - 0x9b, 0x81, 0xc5, 0x9a, 0xc4, 0xa8, 0xc4, 0xb0, 0x7e, 0xc5, 0xaf, 0x60, 0xe1, 0x9a, - 0xa1, 0xc3, 0xb3, 0xc6, 0xb2, 0xe1, 0x9b, 0x97, 0x3c, 0xc4, 0xba, 0xc5, 0xbb, 0x42, - 0xc4, 0x97, 0x66, 0xc8, 0x91, 0xc3, 0xb2, 0xc2, 0xa5, 0xe1, 0x9b, 0xa0, 0xc4, 0xaf, - 0xc8, 0xbf, 0xc8, 0x8a, 0xc5, 0xa1, 0xc3, 0x98, 0xc8, 0x8c, 0xc5, 0x82, 0xe1, 0x9b, - 0x89, 0xc5, 0x88, 0xc8, 0xa4, 0xc6, 0xbc, 0x7a, 0xc4, 0xa1, 0xc3, 0xb0, 0xc5, 0x88, - 0x7b, 0xe1, 0x9b, 0xa1, 0xc2, 0xae, 0xc7, 0x88, 0xc5, 0x9b, 0x71, 0xc7, 0xa7, 0xe1, - 0x9a, 0xa2, 0xc3, 0x8d, 0x50, 0xc6, 0x82, 0xc2, 0xb8, 0xc8, 0xab, 0xc6, 0xa5, 0xc7, - 0x9a, 0xe1, 0x9b, 0x81, 0xc6, 0xb8, 0xc8, 0xb8, 0x32, 0xe1, 0x9b, 0x9a, 0xc5, 0x92, - 0x21, 0xc2, 0xb1, 0xe1, 0x9b, 0xa4, 0xe2, 0xb1, 0xab, 0xe2, 0xb1, 0xbc, 0xc3, 0x9d, - 0xc4, 0xad, 0xc5, 0x83, 0xc7, 0x91, 0x7d, 0xc3, 0xb3, 0xc8, 0x9f, 0xc4, 0x94, 0x40, - 0xc4, 0xb2, 0xc8, 0x92, 0xc7, 0xa1, 0xc3, 0xbc, 0xe1, 0x9b, 0x97, 0xc2, 0xbb, 0xc5, - 0x9a, 0xc2, 0xb2, 0x52, 0xe1, 0x9a, 0xa9, 0x4c, 0xc2, 0xa2, 0xe2, 0xb1, 0xa9, 0xe1, - 0x9b, 0x87, 0xc5, 0x9c, 0xc4, 0x81, 0xc7, 0xb9, 0xe2, 0xb1, 0xad, 0xc4, 0xb3, 0xc5, - 0xa1, 0x64, 0xc5, 0x96, 0xc3, 0x9c, 0xc8, 0xaf, 0xc8, 0x91, 0xe2, 0xb1, 0xaf, 0xc4, - 0x9d, 0xc8, 0x98, 0xe1, 0x9b, 0x8c, 0xc6, 0x89, 0xc6, 0xbc, 0xc8, 0xbc, 0xc5, 0x81, - 0x37, 0x45, 0xc7, 0xa3, 0xc5, 0x81, 0x5a, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x67, 0x0a, 0x16, 0x33, 0xc7, 0xae, 0x83, 0x6f, 0x14, 0x68, 0xb0, 0x6e, 0x24, 0xd0, - 0x8b, 0x84, 0x27, 0x6d, 0xf6, 0x78, 0xe7, 0xe5, 0x0d, 0x6c, 0x35, 0xce, 0x42, 0x98, - 0xbd, 0xc6, 0xb7, 0x92, + 0x69, 0x03, 0x15, 0xe6, 0xb7, 0xbb, 0xbc, 0x9d, 0x88, 0x60, 0x17, 0xfd, 0x0e, 0xb1, + 0x38, 0x67, 0x16, 0xc2, 0xb4, 0x3f, 0x43, 0xf9, 0xa1, 0xc5, 0x42, 0x74, 0xd7, 0x4a, + 0x50, 0xbc, 0x22, 0x8d, ], }, TestVector { key: [ - 0x81, 0x8f, 0x50, 0xce, 0x47, 0x10, 0xf4, 0xeb, 0x11, 0xe7, 0x43, 0xe6, 0x40, 0x85, - 0x44, 0xaa, 0x3c, 0x12, 0x3c, 0x7f, 0x07, 0xe2, 0xaa, 0xbb, 0x91, 0xaf, 0xc4, 0xec, - 0x48, 0x78, 0x8d, 0xe9, + 0x72, 0x73, 0xb6, 0x57, 0xd9, 0x71, 0xa4, 0x5e, 0x72, 0x24, 0x0c, 0x7a, 0xaa, 0xa7, + 0xd0, 0x68, 0x5d, 0x06, 0xd7, 0x99, 0x9b, 0x0a, 0x19, 0xc4, 0xce, 0xa3, 0x27, 0x88, + 0xa6, 0xab, 0x51, 0x3d, ], description: [ - 0xc7, 0x98, 0xe1, 0x9a, 0xb2, 0x2a, 0xc2, 0xa5, 0xc7, 0xb7, 0xc8, 0xaa, 0xc4, 0x9b, - 0xc9, 0x84, 0xc5, 0xaf, 0x4d, 0xc3, 0x83, 0xc2, 0xa3, 0xc7, 0xaf, 0xc6, 0x92, 0xe2, - 0xb1, 0xbe, 0xc8, 0xbf, 0xe1, 0x9b, 0x83, 0xc7, 0x80, 0xc2, 0xb8, 0xc7, 0xa1, 0x6c, - 0xe1, 0x9b, 0xad, 0xc3, 0xa3, 0xc7, 0x97, 0x3b, 0xc9, 0x87, 0xce, 0x8a, 0x51, 0xc8, - 0xbc, 0xc7, 0xa4, 0xc2, 0xa4, 0x2d, 0xc3, 0xb6, 0x34, 0xc9, 0x8e, 0xc5, 0x8f, 0xc9, - 0x86, 0xc5, 0xba, 0xe1, 0x9b, 0x99, 0x76, 0xc6, 0x85, 0xc3, 0xa2, 0xc8, 0x99, 0xc3, - 0x91, 0xc4, 0xb3, 0xc5, 0xa1, 0xe2, 0xb1, 0xbb, 0xc7, 0xa0, 0xc6, 0x9d, 0xc3, 0x89, - 0xc9, 0x86, 0xc5, 0xa1, 0xe1, 0x9b, 0x98, 0xc5, 0xb7, 0xc5, 0xae, 0xc5, 0xb6, 0xe1, - 0x9b, 0x89, 0xc8, 0x98, 0x36, 0xc6, 0x95, 0xc4, 0xb5, 0xc8, 0x85, 0x5c, 0xe1, 0x9b, - 0x99, 0xe2, 0xb1, 0xaf, 0xc3, 0x92, 0xc7, 0x89, 0xc7, 0xb5, 0xc5, 0xbd, 0xc3, 0xa5, - 0xc6, 0x93, 0xc4, 0xac, 0xe1, 0x9b, 0x87, 0xc6, 0x9e, 0xc5, 0xa5, 0xcd, 0xbd, 0xe1, - 0x9b, 0x8a, 0xc6, 0x9d, 0xc9, 0x85, 0xc4, 0xa4, 0x5c, 0x6f, 0xc6, 0x93, 0x76, 0xc3, - 0xa6, 0xe1, 0x9a, 0xad, 0xcd, 0xbb, 0xc2, 0xab, 0xc2, 0xa3, 0xe2, 0xb1, 0xaf, 0xc3, - 0xb6, 0xc6, 0x9f, 0xc5, 0xa5, 0x37, 0x34, 0xe1, 0x9b, 0x8c, 0xc5, 0x8e, 0xc2, 0xb9, - 0xe2, 0xb1, 0xba, 0xc9, 0x88, 0xc8, 0xba, 0xc7, 0x95, 0xc3, 0xa2, 0xc5, 0x9a, 0xc7, - 0x83, 0xc6, 0xb5, 0xc9, 0x8a, 0xc7, 0xb0, 0xe2, 0xb1, 0xab, 0xc5, 0xab, 0xc7, 0x8f, - 0xc3, 0xb6, 0xc4, 0xa7, 0xe1, 0x9a, 0xbb, 0x4e, 0xe1, 0x9b, 0x85, 0x5a, 0xc8, 0xb7, - 0x21, 0xe1, 0x9b, 0x87, 0x25, 0xc6, 0xb4, 0xc5, 0x92, 0xc8, 0xba, 0xc2, 0xa3, 0xc2, - 0xae, 0xe1, 0x9b, 0x89, 0xc5, 0xac, 0x67, 0xc5, 0x98, 0xc7, 0x81, 0xce, 0x85, 0xe2, - 0xb1, 0xb5, 0xc3, 0xab, 0xe2, 0xb1, 0xbd, 0xe1, 0x9b, 0x93, 0xc7, 0x91, 0xc8, 0xa0, - 0xc5, 0x83, 0xc6, 0xb4, 0xc8, 0xb6, 0xc8, 0x9a, 0xe1, 0x9b, 0x93, 0xc7, 0xa3, 0xe1, - 0x9a, 0xba, 0xc9, 0x81, 0xc5, 0xa5, 0xc5, 0xb8, 0x33, 0xc5, 0x86, 0xc8, 0x97, 0x77, - 0xe1, 0x9a, 0xb7, 0xc7, 0xa2, 0xc2, 0xaf, 0xce, 0x88, 0xe1, 0x9a, 0xaa, 0x33, 0xc8, - 0x8f, 0xc4, 0xb9, 0xc8, 0xaf, 0xc3, 0x81, 0xc6, 0xbc, 0xc9, 0x80, 0xc7, 0xb6, 0x46, - 0xe1, 0x9a, 0xa3, 0x6a, 0xc4, 0x85, 0xe1, 0x9b, 0x85, 0xc5, 0x8f, 0xcd, 0xbe, 0x71, - 0x2a, 0xc7, 0x95, 0xc6, 0xa1, 0xc3, 0xaf, 0xe1, 0x9b, 0xa6, 0xc3, 0x93, 0xc3, 0xa5, - 0xc7, 0x9a, 0xc5, 0xb4, 0x50, 0xc7, 0x81, 0xc3, 0x88, 0xc7, 0x87, 0x5a, 0xc3, 0x87, - 0xc3, 0xa2, 0xc7, 0x8a, 0xc8, 0xb9, 0xc3, 0xbb, 0xe1, 0x9a, 0xab, 0xc3, 0xaa, 0xc7, - 0x99, 0xc7, 0x89, 0xc3, 0x98, 0x7c, 0xc6, 0x83, 0x2d, 0xe2, 0xb1, 0xa2, 0xc6, 0x96, - 0xe1, 0x9a, 0xb1, 0x46, 0xe2, 0xb1, 0xa9, 0xc6, 0xaf, 0xc3, 0xbe, 0xe1, 0x9b, 0xa2, - 0xe1, 0x9b, 0x91, 0xc2, 0xb1, 0xc8, 0x8c, 0xc4, 0xb2, 0x75, 0xc4, 0xb9, 0xc5, 0xa6, - 0x52, 0xc6, 0xbc, 0xc3, 0xab, 0xe1, 0x9a, 0xb9, 0xc4, 0xb6, 0xc6, 0xb4, 0xc7, 0xa7, - 0xc2, 0xa1, 0x2d, 0x73, 0x6c, 0xc3, 0xae, 0xc3, 0x98, 0xc8, 0x91, 0xe2, 0xb1, 0xa1, - 0xc4, 0x9c, 0xc5, 0xa9, 0xe1, 0x9b, 0x80, 0xc2, 0xba, 0x71, 0xc3, 0x8c, 0x3b, 0xc3, - 0xb6, 0xc7, 0x95, 0xc5, 0xab, 0xc3, 0x81, 0xc6, 0xbf, 0xc5, 0x9a, 0xe1, 0x9b, 0xab, - 0xc8, 0x9c, 0xc8, 0x83, 0xc5, 0x9f, 0xc5, 0x9a, 0xc5, 0xae, 0xe1, 0x9a, 0xb4, 0xc5, - 0x9a, 0xc3, 0xa4, 0xc8, 0xab, 0xc7, 0xba, 0x69, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x7e, 0x26, 0x94, 0x4d, 0x61, 0xa6, 0xc8, 0xfe, 0x89, 0x5e, 0xda, 0x8d, 0x1c, 0x72, - 0x77, 0x13, 0xe9, 0x65, 0x61, 0xb7, 0x56, 0x56, 0xfd, 0xa2, 0x07, 0x0b, 0x2b, 0x0c, - 0x9d, 0xe1, 0x4d, 0x85, + 0x9b, 0xe1, 0x71, 0xf6, 0xf2, 0x77, 0x5f, 0x14, 0xa8, 0x8a, 0xf7, 0x42, 0x5f, 0xb8, + 0x37, 0xe8, 0x4e, 0x4f, 0xb0, 0x8b, 0x69, 0xdc, 0xa7, 0x0d, 0x96, 0x70, 0x94, 0xd6, + 0x78, 0xb9, 0x66, 0x92, ], }, TestVector { key: [ - 0xae, 0x36, 0xb6, 0x1a, 0x3d, 0x10, 0xf1, 0xaa, 0x75, 0x2a, 0xb1, 0xdc, 0x16, 0xe3, - 0xe4, 0x9b, 0x6a, 0xc0, 0xd2, 0xae, 0x19, 0x07, 0xd2, 0xe6, 0x94, 0x25, 0xec, 0x12, - 0xc9, 0x3a, 0xae, 0xbc, + 0xce, 0xb7, 0x5a, 0x43, 0x9f, 0xf0, 0x16, 0x15, 0x80, 0xbf, 0x29, 0x57, 0x24, 0xc6, + 0xd9, 0x2d, 0x31, 0xb7, 0xaa, 0x02, 0x84, 0x03, 0x39, 0x44, 0x49, 0x64, 0x48, 0x6f, + 0xae, 0xa8, 0x90, 0xe5, ], description: [ - 0xc4, 0x9e, 0xe2, 0xb1, 0xa6, 0xe1, 0x9a, 0xb3, 0x2e, 0xe2, 0xb1, 0xb4, 0xc7, 0x8a, - 0xe1, 0x9b, 0xaf, 0xc4, 0xa9, 0xe2, 0xb1, 0xb5, 0x26, 0xc5, 0x8a, 0xc3, 0xa9, 0x7b, - 0xc7, 0xac, 0xc8, 0xb4, 0xe1, 0x9a, 0xb1, 0xe1, 0x9b, 0x85, 0xc6, 0x88, 0xc6, 0x80, - 0xe1, 0x9a, 0xb0, 0xc5, 0xa2, 0x23, 0xc4, 0x9f, 0xc2, 0xa1, 0xe1, 0x9b, 0xac, 0xc6, - 0x98, 0x70, 0x5c, 0xc9, 0x89, 0xc4, 0xa0, 0xc4, 0xaa, 0xc5, 0xa3, 0x79, 0xc3, 0xab, - 0xce, 0x89, 0xc9, 0x83, 0xc3, 0xab, 0xe2, 0xb1, 0xa0, 0x3d, 0x6a, 0xc4, 0x93, 0xe1, - 0x9b, 0xab, 0x7a, 0xe1, 0x9b, 0x87, 0xe1, 0x9b, 0x95, 0xc2, 0xa5, 0xc9, 0x86, 0xc7, - 0xb5, 0xc2, 0xaf, 0xe1, 0x9b, 0x9a, 0xc4, 0xa9, 0xc3, 0x8a, 0xc9, 0x80, 0xc3, 0xaf, - 0xc6, 0x8f, 0xc6, 0x89, 0xc4, 0xa9, 0xc4, 0xb4, 0xe1, 0x9b, 0x8d, 0x4b, 0xc8, 0x96, - 0xc6, 0x87, 0x40, 0xc4, 0x8e, 0xc6, 0x81, 0xc3, 0x9b, 0xc8, 0x9b, 0x49, 0xe2, 0xb1, - 0xa0, 0xc4, 0xb4, 0xc6, 0xa8, 0xc6, 0x8c, 0xc3, 0xb7, 0x34, 0xc8, 0x89, 0xc2, 0xb8, - 0xc2, 0xb2, 0xc4, 0xa8, 0xc4, 0xa0, 0xc7, 0xbb, 0xe2, 0xb1, 0xac, 0xe1, 0x9b, 0x97, - 0xc3, 0xa9, 0xc2, 0xbe, 0xc6, 0x85, 0xc2, 0xa9, 0xcd, 0xb5, 0xc3, 0x95, 0xc8, 0x8b, - 0xc5, 0x94, 0xe2, 0xb1, 0xa0, 0xc2, 0xb5, 0xc6, 0x94, 0xc4, 0xba, 0xe2, 0xb1, 0xbb, - 0xe1, 0x9b, 0x88, 0xc4, 0xa2, 0xc5, 0xa2, 0xcd, 0xbc, 0xc6, 0x88, 0xc3, 0x80, 0xc8, - 0x9d, 0xc5, 0x9b, 0xc7, 0xbe, 0xc5, 0x8c, 0xc5, 0xa8, 0xc5, 0xb0, 0xc9, 0x8c, 0xc2, - 0xa5, 0xc7, 0xbd, 0xc8, 0xaf, 0xc3, 0xb2, 0xc7, 0x8b, 0xc2, 0xb8, 0x25, 0xe1, 0x9b, - 0x80, 0xc9, 0x8f, 0xe1, 0x9b, 0xaa, 0xc5, 0xb1, 0xe1, 0x9b, 0x9d, 0xc5, 0xa5, 0xc2, - 0xa3, 0xc8, 0xaf, 0xc8, 0xb1, 0xc6, 0xb3, 0x3f, 0xc6, 0xb9, 0xc7, 0x91, 0xc7, 0x81, - 0xc7, 0xbc, 0x5d, 0x7c, 0x69, 0xc7, 0x96, 0xe1, 0x9b, 0x8c, 0xc7, 0xb7, 0xc6, 0xa3, - 0xe2, 0xb1, 0xb0, 0xc6, 0xb7, 0xce, 0x88, 0xc9, 0x81, 0xc3, 0x80, 0xe1, 0x9b, 0xaf, - 0xc7, 0xae, 0xc5, 0xbc, 0xc4, 0x8c, 0xc4, 0xa7, 0x71, 0x6e, 0xc6, 0x91, 0xc4, 0x96, - 0xc6, 0x88, 0xc6, 0x97, 0xc5, 0xa4, 0xc5, 0xbf, 0xc7, 0x8d, 0xc8, 0xb9, 0xc7, 0xb5, - 0xe1, 0x9a, 0xb0, 0xc4, 0xa8, 0xc7, 0xa3, 0xc6, 0xba, 0xe1, 0x9a, 0xb5, 0xc6, 0x86, - 0xe1, 0x9b, 0x80, 0xc9, 0x82, 0x4a, 0xc7, 0xa3, 0x7e, 0xc3, 0x9f, 0xc8, 0xb9, 0x7a, - 0x3b, 0xc6, 0xa7, 0xc8, 0x97, 0xc6, 0x92, 0xe1, 0x9b, 0xa1, 0xc7, 0x97, 0xc7, 0xa7, - 0xe1, 0x9a, 0xa3, 0xc9, 0x8d, 0xc6, 0xa0, 0xe1, 0x9b, 0xa0, 0xc4, 0x90, 0xc3, 0x9a, - 0xc4, 0x8f, 0xc7, 0xbc, 0xc4, 0x8b, 0xc2, 0xaa, 0x5d, 0xc3, 0xb0, 0xc3, 0x8b, 0xc4, - 0x90, 0xc3, 0xac, 0xc4, 0xad, 0xe1, 0x9a, 0xb8, 0xc5, 0x93, 0xc8, 0x92, 0xc3, 0x81, - 0xe1, 0x9a, 0xbc, 0xc4, 0xb3, 0xc6, 0x83, 0xc8, 0x9b, 0xc8, 0x81, 0x45, 0xe1, 0x9b, - 0x89, 0xc7, 0xbb, 0xc9, 0x87, 0xc6, 0xb6, 0x4c, 0xc6, 0x88, 0x60, 0xe1, 0x9b, 0x8c, - 0xc6, 0xa7, 0xcd, 0xbc, 0xc3, 0xbe, 0xc2, 0xb3, 0xc7, 0xab, 0xcd, 0xb6, 0xc8, 0xa2, - 0xc2, 0xbc, 0xe2, 0xb1, 0xa5, 0xc5, 0x8f, 0xc6, 0xa0, 0xc6, 0xa6, 0xc6, 0x9b, 0xc8, - 0x94, 0xe1, 0x9a, 0xa0, 0xe2, 0xb1, 0xb6, 0x3f, 0xcd, 0xb2, 0xc8, 0x81, 0xc3, 0x88, - 0xc3, 0xb9, 0xe1, 0x9b, 0x81, 0xe2, 0xb1, 0xa8, 0xc5, 0xb8, 0x48, 0x60, 0xc6, 0xb0, - 0xc5, 0xb1, 0xc3, 0x8e, 0x4a, 0xc5, 0x84, 0xc8, 0xaf, 0xc4, 0xb2, 0xc4, 0x97, 0xe2, - 0xb1, 0xbd, 0xc4, 0xb6, 0x3f, 0xc8, 0x89, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0xcc, 0x07, 0x9a, 0xf8, 0x84, 0x69, 0xe9, 0xbd, 0x7e, 0x67, 0x8e, 0xcf, 0x7f, 0x9f, - 0x79, 0xfa, 0x4d, 0x30, 0x89, 0x27, 0x28, 0xad, 0x87, 0x32, 0xe9, 0xcc, 0x99, 0x7d, - 0x3c, 0x7c, 0x64, 0x1f, + 0x76, 0x3d, 0x56, 0xa8, 0x53, 0xf6, 0xac, 0x5e, 0xe8, 0xef, 0x29, 0x4e, 0xfd, 0x01, + 0x42, 0xbe, 0x6c, 0x23, 0xc5, 0x18, 0x96, 0xfc, 0xb8, 0x3c, 0x40, 0x09, 0x4d, 0x34, + 0x01, 0xc0, 0xc0, 0x94, ], }, TestVector { key: [ - 0x49, 0x26, 0x53, 0x80, 0xd2, 0xb0, 0x2e, 0x0a, 0x1d, 0x98, 0x8f, 0x3d, 0xe3, 0x45, - 0x8b, 0x6e, 0x00, 0x29, 0x1d, 0xb0, 0xe6, 0x2e, 0x17, 0x47, 0x91, 0xd0, 0x09, 0x29, - 0x9f, 0x61, 0xfe, 0xc4, + 0xec, 0x05, 0xbb, 0x7f, 0x06, 0x5e, 0x25, 0x6f, 0xf4, 0x54, 0xf8, 0xa8, 0xdf, 0x6f, + 0x2f, 0x9b, 0x8a, 0x8c, 0x95, 0x08, 0xca, 0xac, 0xfe, 0xe9, 0x52, 0x1c, 0xbe, 0x68, + 0x9d, 0xd1, 0x12, 0x0f, ], description: [ - 0xc7, 0x88, 0xc2, 0xa3, 0xe2, 0xb1, 0xa7, 0xc5, 0x84, 0xc6, 0xac, 0xc8, 0xaa, 0x63, - 0xc6, 0xa7, 0xc5, 0xa7, 0x75, 0xc7, 0x97, 0xe1, 0x9b, 0xaf, 0x71, 0xc8, 0x95, 0xe1, - 0x9a, 0xba, 0x44, 0x45, 0xc3, 0xa1, 0xe1, 0x9b, 0xac, 0xc6, 0xbf, 0xc4, 0xbc, 0xc4, - 0x88, 0xe1, 0x9b, 0x82, 0xe2, 0xb1, 0xb1, 0x5d, 0xc3, 0xa7, 0xe1, 0x9b, 0xa0, 0xc7, - 0xb4, 0x5a, 0xc4, 0xad, 0xe1, 0x9b, 0x8f, 0xc5, 0x88, 0xc9, 0x8c, 0xc8, 0xab, 0xe1, - 0x9a, 0xaf, 0xc7, 0xb6, 0xc2, 0xb8, 0x59, 0xc5, 0xbb, 0xc5, 0xbd, 0x2e, 0xc5, 0x86, - 0xe2, 0xb1, 0xbb, 0xe2, 0xb1, 0xb1, 0xc3, 0xb4, 0xc5, 0xb2, 0xc4, 0x96, 0xc5, 0x99, - 0xc7, 0x8c, 0x71, 0xc6, 0xa2, 0xc3, 0x91, 0xc5, 0xb9, 0xcd, 0xbe, 0x26, 0xe1, 0x9a, - 0xa8, 0xe1, 0x9b, 0x86, 0xc3, 0x99, 0xc8, 0xa7, 0xc4, 0x8b, 0xe2, 0xb1, 0xb4, 0xc5, - 0x8c, 0xc5, 0x9e, 0xc5, 0xa5, 0xc4, 0xbd, 0x3c, 0xc5, 0x89, 0xc4, 0x88, 0x29, 0xc2, - 0xa6, 0x2c, 0xc7, 0xa9, 0xc5, 0xb6, 0xc8, 0x92, 0xc5, 0xb8, 0x3c, 0xc6, 0x8b, 0xc6, - 0x83, 0xe1, 0x9b, 0x9b, 0xc6, 0x88, 0xe2, 0xb1, 0xba, 0x32, 0x63, 0xc7, 0xbe, 0xc6, - 0x8a, 0xc7, 0x8d, 0xc6, 0xa5, 0xc6, 0x9f, 0xc8, 0x98, 0xc4, 0xb0, 0xc8, 0xac, 0xc8, - 0xb1, 0xc5, 0xa3, 0xc2, 0xb1, 0xc9, 0x8f, 0xc4, 0xbf, 0xe1, 0x9b, 0xa3, 0xe2, 0xb1, - 0xad, 0xc4, 0x88, 0xc5, 0x8d, 0xc7, 0x98, 0xc8, 0xb4, 0xc3, 0xab, 0xc3, 0x9b, 0xc6, - 0xa5, 0xe1, 0x9b, 0x89, 0xc2, 0xa8, 0xce, 0x88, 0xe2, 0xb1, 0xb9, 0xe1, 0x9b, 0x83, - 0xc6, 0x83, 0xce, 0x8c, 0xc3, 0xbc, 0x65, 0xe1, 0x9a, 0xaf, 0xc4, 0x88, 0xe1, 0x9a, - 0xa1, 0xc8, 0x87, 0xc8, 0x98, 0xc5, 0x8e, 0xc8, 0xbd, 0x30, 0xc4, 0xb8, 0xc7, 0xa4, - 0x48, 0xc8, 0xa1, 0xe1, 0x9b, 0x93, 0xc4, 0xa8, 0xc5, 0xba, 0x52, 0xc3, 0xbc, 0xc6, - 0xbe, 0xc6, 0x96, 0xc9, 0x8c, 0x3a, 0xc8, 0xa9, 0xc2, 0xac, 0xe1, 0x9b, 0x8c, 0xc3, - 0x9d, 0xe2, 0xb1, 0xb0, 0xc4, 0xaf, 0x34, 0xc5, 0xb2, 0xc7, 0xb3, 0xc6, 0xb2, 0xe1, - 0x9a, 0xb9, 0xc7, 0x98, 0xc8, 0xbe, 0x7a, 0xc2, 0xa7, 0xe1, 0x9b, 0x85, 0xc9, 0x8b, - 0xc5, 0x98, 0xc7, 0xa3, 0xe2, 0xb1, 0xab, 0xc3, 0xbf, 0xc3, 0xb1, 0xc8, 0x88, 0xc4, - 0x9d, 0xc4, 0x80, 0xc7, 0xac, 0xc7, 0xbe, 0xe1, 0x9a, 0xa3, 0xc6, 0x8c, 0xe1, 0x9b, - 0xa5, 0xc8, 0x8f, 0xc4, 0xbf, 0xc4, 0xbf, 0xc8, 0x84, 0xc3, 0x81, 0xc7, 0xa6, 0xe2, - 0xb1, 0xa3, 0xc3, 0xb2, 0x5a, 0xe1, 0x9b, 0xa2, 0xe1, 0x9a, 0xba, 0xc4, 0x92, 0xc8, - 0xaa, 0xe1, 0x9a, 0xaf, 0xc5, 0x8b, 0xc6, 0xa3, 0x73, 0xc6, 0x87, 0xc4, 0x82, 0xc8, - 0xa0, 0xc8, 0xaf, 0x6f, 0xe2, 0xb1, 0xbb, 0xc7, 0x9c, 0x55, 0xe1, 0x9a, 0xbf, 0xc2, - 0xa6, 0xc8, 0xab, 0xc6, 0xa5, 0xc8, 0x8b, 0xc5, 0x90, 0xc5, 0xbf, 0xc8, 0x94, 0xc6, - 0xa3, 0xc4, 0xbe, 0xc4, 0xab, 0xc7, 0xb8, 0xc4, 0x91, 0xc6, 0xa6, 0xc5, 0xb6, 0xc3, - 0x9b, 0xc8, 0xae, 0xc4, 0x8f, 0x62, 0xc2, 0xa4, 0xc8, 0x99, 0xcd, 0xba, 0xc4, 0x96, - 0xc2, 0xb2, 0xc6, 0x92, 0xc5, 0xb5, 0xc5, 0x83, 0xc6, 0x92, 0xc6, 0x8d, 0xe1, 0x9b, - 0xb0, 0xe1, 0x9b, 0x99, 0xc7, 0xae, 0xe1, 0x9a, 0xa7, 0x64, 0x33, 0x3c, 0xc6, 0xab, - 0xc4, 0x95, 0xc3, 0xbd, 0xc8, 0xad, 0xc5, 0xa5, 0x5e, 0xe2, 0xb1, 0xbe, 0xe1, 0x9a, - 0xb6, 0xc8, 0x83, 0x54, 0x25, 0xc8, 0x80, 0xc6, 0xa9, 0xe1, 0x9a, 0xb2, 0xc5, 0x98, - 0xc8, 0xb3, 0xc6, 0x96, 0xc7, 0x87, 0xe1, 0x9a, 0xaa, 0xe1, 0x9b, 0x92, 0xc6, 0xaa, - 0x72, 0x67, 0xe2, 0xb1, 0xb4, 0x4d, 0xc3, 0xb2, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0xaa, 0xb9, 0x9e, 0x01, 0x44, 0xfb, 0xf5, 0x9f, 0x87, 0xd2, 0xe5, 0xf6, 0x32, 0x63, - 0x82, 0xf6, 0x3a, 0x46, 0x83, 0x83, 0xb4, 0x74, 0x40, 0xd7, 0x84, 0xe9, 0x4e, 0x6b, - 0x3a, 0xb6, 0x45, 0x28, + 0x90, 0x10, 0xb3, 0x4c, 0xdf, 0xfd, 0x95, 0x84, 0x96, 0x62, 0x44, 0xdd, 0x6c, 0x3a, + 0x23, 0x4f, 0xc6, 0xa0, 0x74, 0xf1, 0xa9, 0xc9, 0xb2, 0xd8, 0x3d, 0x1c, 0x2c, 0x04, + 0xf5, 0x30, 0x75, 0x0c, ], }, TestVector { key: [ - 0x9a, 0x0e, 0x46, 0x39, 0xb4, 0x69, 0x1f, 0x02, 0x7c, 0x0d, 0xb7, 0xfe, 0xf1, 0xbb, - 0x5e, 0xf9, 0x0a, 0xcd, 0xb7, 0x08, 0x62, 0x6d, 0x2e, 0x1f, 0x3e, 0x38, 0x3e, 0xe7, - 0x5b, 0x31, 0xcf, 0x57, + 0xb0, 0xfa, 0x9d, 0x77, 0xfc, 0xbd, 0x96, 0x45, 0x91, 0x32, 0xe3, 0x05, 0xe3, 0x24, + 0xe7, 0x93, 0x6a, 0xe1, 0x3b, 0x15, 0x14, 0x7e, 0x20, 0x5d, 0x7b, 0xae, 0x42, 0xfa, + 0x7f, 0xaf, 0x5d, 0x1e, ], description: [ - 0xc3, 0xaa, 0xc3, 0xa0, 0xe2, 0xb1, 0xba, 0xc6, 0x8d, 0x34, 0xc4, 0xb0, 0xc4, 0x8b, - 0xc2, 0xba, 0xc5, 0xa9, 0xe2, 0xb1, 0xa6, 0xc3, 0xa8, 0x6f, 0x2c, 0x45, 0xc5, 0xaf, - 0xc4, 0xbb, 0xc7, 0x8b, 0xc6, 0x8e, 0xc8, 0x94, 0xc3, 0xac, 0xc2, 0xab, 0xc8, 0x8b, - 0xe1, 0x9a, 0xb4, 0xc5, 0x9d, 0xc8, 0xb3, 0xc7, 0xb9, 0xe1, 0x9a, 0xac, 0xc6, 0x9b, - 0xc4, 0x9d, 0xc2, 0xa3, 0xe1, 0x9a, 0xb6, 0xc5, 0x92, 0xc7, 0x87, 0x46, 0xc4, 0x99, - 0xce, 0x88, 0xc5, 0x91, 0xc8, 0x92, 0xc4, 0xa9, 0xc3, 0xab, 0x78, 0xc9, 0x8e, 0xc7, - 0xac, 0xc5, 0xba, 0xc4, 0x88, 0xc5, 0x80, 0xc7, 0x91, 0xc5, 0xb7, 0xc5, 0xaa, 0xe1, - 0x9b, 0x97, 0x30, 0xc8, 0x8d, 0x5c, 0xc2, 0xb3, 0xc4, 0x9f, 0x2a, 0xc3, 0xb8, 0xc7, - 0xae, 0xc7, 0xbd, 0xc4, 0xa0, 0xe1, 0x9a, 0xa1, 0xe1, 0x9a, 0xbf, 0xc7, 0x9e, 0xe1, - 0x9b, 0x84, 0xc8, 0x9c, 0xc5, 0x86, 0x2b, 0xc4, 0x96, 0xcd, 0xb4, 0xc3, 0x82, 0x6a, - 0xc8, 0xa6, 0xc5, 0x8c, 0xc3, 0x8a, 0xc2, 0xbf, 0xc6, 0x9e, 0x32, 0xe2, 0xb1, 0xa0, - 0xc5, 0xa2, 0xc8, 0x8b, 0x3e, 0xc4, 0x91, 0xc6, 0xab, 0xc3, 0x92, 0xc7, 0xa7, 0xc8, - 0xa3, 0xc4, 0xa7, 0xe1, 0x9a, 0xb0, 0xc4, 0x9c, 0xcd, 0xb6, 0xe1, 0x9a, 0xa1, 0xc6, - 0x8b, 0xe1, 0x9b, 0x9e, 0xc2, 0xb5, 0xc6, 0x89, 0x33, 0x46, 0xc6, 0x8d, 0xc4, 0xb3, - 0xc8, 0xac, 0xc5, 0x97, 0xc3, 0xb7, 0xc7, 0xab, 0xe2, 0xb1, 0xa1, 0xe1, 0x9b, 0x9f, - 0xc4, 0x94, 0xe1, 0x9b, 0xb0, 0xc8, 0x8e, 0xc4, 0xa8, 0xc5, 0x8b, 0xc6, 0xbb, 0xc2, - 0xa6, 0xe1, 0x9b, 0xae, 0xc2, 0xac, 0xe1, 0x9b, 0x84, 0xc2, 0xb1, 0x4c, 0xc2, 0xb7, - 0xc5, 0x9c, 0x5d, 0xc9, 0x8c, 0xe1, 0x9b, 0x8b, 0x31, 0xc6, 0xb5, 0x62, 0xc7, 0x9e, - 0xc3, 0xa8, 0xc8, 0x82, 0xc7, 0xb7, 0x69, 0xe1, 0x9a, 0xbf, 0xe1, 0x9a, 0xa3, 0xe1, - 0x9b, 0xb0, 0x6e, 0xc6, 0xb9, 0xc9, 0x89, 0xc8, 0xb1, 0xc6, 0xaf, 0xe1, 0x9b, 0x90, - 0x55, 0xc4, 0xb1, 0xe1, 0x9b, 0xac, 0xe1, 0x9b, 0x8b, 0xc7, 0xaa, 0xe1, 0x9b, 0x88, - 0xc3, 0xbf, 0xe1, 0x9a, 0xa5, 0xc5, 0xa9, 0xc2, 0xb7, 0x62, 0xc3, 0x91, 0xc5, 0x93, - 0xc4, 0xbd, 0xc3, 0x90, 0xe1, 0x9b, 0x86, 0xe1, 0x9b, 0x8e, 0xcd, 0xbc, 0xc8, 0x86, - 0xe2, 0xb1, 0xb2, 0xc2, 0xbe, 0xc6, 0xbd, 0x64, 0xc2, 0xb2, 0xcd, 0xbb, 0xc3, 0x90, - 0xc7, 0x9c, 0xcd, 0xb5, 0xc8, 0x9f, 0xc7, 0xa0, 0x75, 0xc8, 0x9f, 0xe1, 0x9b, 0x99, - 0xc5, 0x9a, 0xe2, 0xb1, 0xae, 0xc6, 0x90, 0xc4, 0xad, 0xc3, 0x89, 0xc2, 0xba, 0xc4, - 0x91, 0xc6, 0x83, 0xe1, 0x9a, 0xa6, 0xc3, 0x93, 0xc3, 0x9b, 0xc7, 0x8f, 0xc4, 0xa3, - 0xc5, 0xae, 0x40, 0xc5, 0xb4, 0xe1, 0x9b, 0x97, 0xe2, 0xb1, 0xbf, 0xc6, 0xb3, 0xe2, - 0xb1, 0xb2, 0xe1, 0x9a, 0xae, 0xc3, 0x95, 0xc4, 0x80, 0xc5, 0x9b, 0xc5, 0xa9, 0xc5, - 0xa8, 0xe1, 0x9b, 0xa7, 0xc8, 0x98, 0x75, 0x53, 0xe2, 0xb1, 0xb4, 0xe1, 0x9a, 0xb4, - 0xc3, 0xa3, 0x4b, 0xc3, 0x86, 0xe1, 0x9a, 0xa9, 0xc3, 0x80, 0xe1, 0x9b, 0xb0, 0xc3, - 0x81, 0xc4, 0x86, 0xc9, 0x83, 0xc8, 0xbb, 0xc3, 0x88, 0xc8, 0x96, 0xc7, 0xac, 0xc4, - 0x9a, 0xc5, 0xb7, 0x7e, 0xc7, 0xbe, 0xc6, 0xba, 0xc2, 0xb6, 0xe1, 0x9a, 0xb5, 0xc7, - 0xbd, 0xc7, 0x80, 0x73, 0xc7, 0xab, 0xc8, 0xbd, 0xc7, 0xb7, 0xc3, 0x89, 0xe1, 0x9b, - 0x92, 0xe1, 0x9b, 0x85, 0xe2, 0xb1, 0xb7, 0xc8, 0x8c, 0xc4, 0xb8, 0xc8, 0xa2, 0xc3, - 0xa6, 0xc4, 0x9c, 0xc5, 0x9b, 0xc2, 0xa3, 0xc8, 0x8b, 0xc2, 0xbd, 0xe2, 0xb1, 0xb0, - 0xc5, 0xa6, 0xce, 0x87, 0xc2, 0xb3, 0xc5, 0xbc, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x9c, 0x67, 0xc9, 0x2b, 0xeb, 0x8d, 0x82, 0xb5, 0x8a, 0x3d, 0x24, 0xba, 0xaa, 0x0a, - 0xa1, 0x5c, 0x30, 0x64, 0x16, 0xb2, 0x63, 0x72, 0x16, 0xe9, 0xb7, 0x83, 0x05, 0x43, - 0x4c, 0x57, 0x96, 0xb6, + 0xbd, 0x61, 0xcd, 0xd1, 0x35, 0x54, 0x21, 0x00, 0x57, 0xaa, 0xef, 0xc0, 0xf0, 0xc7, + 0xc0, 0xbe, 0x9c, 0xdb, 0xef, 0x14, 0xe8, 0x79, 0xac, 0x10, 0xf3, 0xd2, 0x66, 0xad, + 0x18, 0x39, 0xc2, 0x1b, ], }, TestVector { key: [ - 0xbb, 0xf4, 0x49, 0x82, 0xf1, 0xba, 0x3a, 0x2b, 0x9d, 0xd3, 0xc1, 0x77, 0x4d, 0x71, - 0xce, 0x33, 0x60, 0x59, 0x9b, 0x07, 0xf2, 0x11, 0xc8, 0x16, 0xb8, 0xc4, 0x3b, 0x98, - 0x42, 0x23, 0x09, 0x24, + 0x81, 0x8f, 0x50, 0xce, 0x47, 0x10, 0xf4, 0xeb, 0x11, 0xe7, 0x43, 0xe6, 0x40, 0x85, + 0x44, 0xaa, 0x3c, 0x12, 0x3c, 0x7f, 0x07, 0xe2, 0xaa, 0xbb, 0x91, 0xaf, 0xc4, 0xec, + 0x48, 0x78, 0x8d, 0xe9, ], description: [ - 0xc4, 0xa8, 0xc5, 0x96, 0xc2, 0xb6, 0xc6, 0xb1, 0x7c, 0xc7, 0xa0, 0x36, 0xc6, 0x9f, - 0x75, 0xc2, 0xa1, 0xc3, 0xbe, 0xc8, 0x90, 0xc2, 0xa6, 0xc3, 0x86, 0xc9, 0x86, 0xe2, - 0xb1, 0xa7, 0xe1, 0x9b, 0xa8, 0xc5, 0x9c, 0xc7, 0xa6, 0xc7, 0xbd, 0xe1, 0x9b, 0xa2, - 0x37, 0xc2, 0xbd, 0xc3, 0x97, 0xc4, 0x8f, 0xc3, 0x80, 0xc4, 0x8f, 0xc6, 0xa6, 0xc5, - 0x8e, 0xce, 0x89, 0xc4, 0xa6, 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0x8f, 0xe2, 0xb1, 0xb7, - 0xc9, 0x84, 0xe1, 0x9a, 0xa1, 0xc6, 0x97, 0xe1, 0x9b, 0x85, 0xc3, 0xaf, 0xc6, 0xbf, - 0x3e, 0xe2, 0xb1, 0xbf, 0xc7, 0xa9, 0x39, 0xc4, 0x80, 0xc3, 0x80, 0xc6, 0x87, 0xc3, - 0xa9, 0x4c, 0x66, 0xc8, 0xa5, 0x3b, 0xc5, 0x83, 0x48, 0xc6, 0xbd, 0xc5, 0xbd, 0xc7, - 0x8f, 0xc8, 0xaf, 0xc7, 0x9c, 0xe1, 0x9a, 0xb5, 0xcd, 0xbc, 0xc5, 0x9a, 0xc2, 0xa1, - 0xe2, 0xb1, 0xbf, 0xe1, 0x9b, 0x91, 0xc4, 0x8d, 0xc5, 0x9b, 0xc3, 0x9d, 0xc5, 0x90, - 0xe1, 0x9b, 0x82, 0x71, 0xc2, 0xb9, 0xc7, 0xa4, 0xcd, 0xbc, 0xc5, 0x80, 0xc8, 0x8e, - 0xc7, 0x83, 0x53, 0xc8, 0xb1, 0xc4, 0x83, 0xe2, 0xb1, 0xa0, 0xc5, 0x86, 0xc5, 0xa7, - 0xc4, 0xb0, 0xc6, 0x9b, 0xc8, 0xa6, 0xc8, 0xb2, 0xc5, 0x89, 0xc8, 0xb7, 0xc9, 0x83, - 0xc5, 0xaa, 0xc3, 0x9a, 0xc4, 0xae, 0xc4, 0xbb, 0xc6, 0x9f, 0xc6, 0xac, 0xc8, 0x8b, - 0xc9, 0x8e, 0x70, 0xc5, 0x88, 0x6e, 0xc6, 0x9e, 0xe1, 0x9a, 0xb7, 0xcd, 0xb5, 0xc3, - 0x9d, 0xe2, 0xb1, 0xb2, 0xc4, 0x90, 0xe1, 0x9b, 0x97, 0xc7, 0xb0, 0xc6, 0xa0, 0xe2, - 0xb1, 0xaa, 0xc7, 0x8e, 0xc5, 0xb4, 0x3c, 0xc7, 0xa8, 0xc9, 0x81, 0xc2, 0xb6, 0xc5, - 0xa8, 0x21, 0x78, 0xe2, 0xb1, 0xab, 0xce, 0x84, 0xc5, 0x85, 0xc6, 0x83, 0xc4, 0x82, - 0xc7, 0x90, 0xc6, 0xb5, 0xc6, 0xb9, 0xc8, 0xac, 0xc7, 0xb9, 0xc3, 0xb1, 0xc5, 0x85, - 0xe1, 0x9a, 0xa5, 0x50, 0x44, 0xc5, 0xb7, 0xe1, 0x9a, 0xac, 0xc4, 0x9c, 0xc7, 0x90, - 0xc5, 0x85, 0xc8, 0xbe, 0xc2, 0xb5, 0xc6, 0xb7, 0xc7, 0xba, 0xc6, 0x98, 0xe1, 0x9b, - 0xa8, 0xe2, 0xb1, 0xb9, 0xc5, 0xae, 0xc7, 0x83, 0xc5, 0xb4, 0xc4, 0x98, 0xc6, 0x9f, - 0xc5, 0x84, 0xc3, 0x92, 0xe1, 0x9b, 0x85, 0xc5, 0x95, 0x31, 0xc3, 0x8e, 0xe1, 0x9a, - 0xa0, 0x66, 0xc8, 0xbf, 0xc6, 0x96, 0xc7, 0xbb, 0xc2, 0xb2, 0xe2, 0xb1, 0xbf, 0xc4, - 0x96, 0xe1, 0x9a, 0xb6, 0xc8, 0xa5, 0xc5, 0xb6, 0xc6, 0xa7, 0xc8, 0x8d, 0xc3, 0xa0, - 0xc7, 0xae, 0xc7, 0xb8, 0xe1, 0x9b, 0x85, 0xc7, 0x8a, 0xc4, 0xa4, 0xc4, 0x9d, 0xc4, - 0xbe, 0xe1, 0x9a, 0xb5, 0xc4, 0x85, 0xc9, 0x83, 0xc3, 0xb5, 0xc3, 0xba, 0xc4, 0x9d, - 0xc6, 0xad, 0x68, 0xe1, 0x9b, 0xb0, 0xc4, 0x86, 0xc7, 0xb6, 0xc6, 0x92, 0xc9, 0x80, - 0xc5, 0x80, 0xcd, 0xb1, 0xc7, 0x85, 0xc4, 0xae, 0xc6, 0x95, 0xe2, 0xb1, 0xb2, 0xc5, - 0x9d, 0xc8, 0x99, 0xc4, 0x91, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, 0x91, 0xc4, 0xbc, 0xc4, - 0x85, 0xe1, 0x9b, 0xa1, 0xc5, 0x86, 0x26, 0xc3, 0xa8, 0xc3, 0x88, 0xc4, 0xb8, 0xe2, - 0xb1, 0xa7, 0xc2, 0xa5, 0xe1, 0x9b, 0x98, 0xc4, 0xb3, 0x7c, 0xc3, 0xb1, 0xe1, 0x9b, - 0x94, 0xc6, 0x9b, 0xcd, 0xbc, 0xcd, 0xb2, 0xc8, 0x8c, 0xc6, 0x8c, 0xe2, 0xb1, 0xb0, - 0x52, 0xc3, 0x9b, 0xc3, 0x8c, 0x5e, 0xc5, 0x90, 0xc3, 0xa4, 0xc3, 0x8a, 0x58, 0xc8, - 0x9e, 0xc5, 0xba, 0xc5, 0xb3, 0x6c, 0xc2, 0xab, 0xc4, 0xa1, 0x38, 0xc6, 0xb6, 0xe1, - 0x9b, 0x9f, 0x71, 0xc9, 0x84, 0xe2, 0xb1, 0xb9, 0xc3, 0x9a, 0xc6, 0x83, 0xe1, 0x9a, - 0xa4, 0xc6, 0x85, 0xc3, 0x8c, 0x25, 0x4e, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x08, 0x32, 0x00, 0xcc, 0x9c, 0xa5, 0x39, 0xbe, 0xc9, 0x29, 0x51, 0x50, 0x4d, 0xca, - 0xf2, 0xc5, 0xe0, 0xe8, 0xe3, 0x57, 0xd7, 0xea, 0xed, 0x18, 0xb0, 0x15, 0x8b, 0x69, - 0x2c, 0xe4, 0xce, 0x9d, + 0xae, 0xc8, 0x2d, 0x62, 0x1d, 0x97, 0xcf, 0x35, 0xfb, 0xef, 0x86, 0x88, 0xc5, 0xc8, + 0x30, 0xa0, 0xfd, 0x9c, 0x4a, 0xf7, 0x37, 0x0a, 0x15, 0xc8, 0x99, 0xb2, 0x84, 0x86, + 0xb3, 0xf0, 0x96, 0x20, ], }, TestVector { key: [ - 0xff, 0x63, 0xc7, 0x89, 0x25, 0x1c, 0x10, 0x43, 0xc6, 0xf9, 0x6c, 0x66, 0xbf, 0x5b, - 0x0f, 0x61, 0xc9, 0xd6, 0x5f, 0xef, 0x5a, 0xaf, 0x42, 0x84, 0xa6, 0xa5, 0x69, 0x94, - 0x94, 0x1c, 0x05, 0xfa, + 0x0b, 0xb4, 0x91, 0x3d, 0xba, 0xf1, 0x4e, 0xf6, 0xd0, 0xad, 0xeb, 0x8b, 0x70, 0x27, + 0xbf, 0x0b, 0x9a, 0x8f, 0x59, 0x0d, 0x3e, 0x2d, 0x95, 0xa1, 0x2d, 0xba, 0xaf, 0x0b, + 0x95, 0x33, 0xdc, 0xa4, ], description: [ - 0xc8, 0x8a, 0xc5, 0xb0, 0xe1, 0x9a, 0xb2, 0xc8, 0xbc, 0xc8, 0xbc, 0xc5, 0x9e, 0x63, - 0xcd, 0xb4, 0xc7, 0xbf, 0xc6, 0xbd, 0xc8, 0x99, 0xc3, 0x8c, 0xc8, 0x9c, 0x45, 0xc9, - 0x85, 0xcd, 0xb3, 0xc6, 0xb8, 0xc8, 0x91, 0x4e, 0xc9, 0x82, 0xc5, 0xab, 0xc5, 0x8a, - 0xce, 0x87, 0xe1, 0x9a, 0xbd, 0xc8, 0xa3, 0xc8, 0xa9, 0xc7, 0x90, 0xc6, 0x9c, 0xe1, - 0x9b, 0xa0, 0x41, 0x4c, 0xc2, 0xbb, 0xc7, 0x93, 0xe1, 0x9a, 0xa3, 0xc5, 0xba, 0xc6, - 0x86, 0xcd, 0xbd, 0xc5, 0x8d, 0xc4, 0xa4, 0xc8, 0xb5, 0xc3, 0x9d, 0xc3, 0xae, 0xc5, - 0x98, 0xe1, 0x9b, 0x91, 0x63, 0x66, 0xc3, 0xbc, 0xc8, 0xae, 0x7e, 0x40, 0xc2, 0xa8, - 0xc3, 0x8a, 0xc4, 0xac, 0x35, 0x3d, 0xcd, 0xbd, 0xc6, 0xad, 0xc3, 0x9b, 0xc6, 0x81, - 0xc5, 0xab, 0xc4, 0x8f, 0x28, 0xc4, 0x9d, 0xe1, 0x9b, 0x8e, 0xe1, 0x9b, 0xa4, 0xc5, - 0x86, 0xe1, 0x9a, 0xba, 0x50, 0xc6, 0xbc, 0xc6, 0x9b, 0xc7, 0xac, 0xc4, 0xb4, 0xe1, - 0x9a, 0xa9, 0xe1, 0x9b, 0xae, 0xc3, 0x91, 0xc6, 0x82, 0xc4, 0xa8, 0xc5, 0xa8, 0xc6, - 0xae, 0x2d, 0xe1, 0x9b, 0x9e, 0xc8, 0x8e, 0xe1, 0x9b, 0xa7, 0xc5, 0x8e, 0xc8, 0x8d, - 0xc3, 0x96, 0xc7, 0x9f, 0xc3, 0xb4, 0x3a, 0xcd, 0xb6, 0xc6, 0x8a, 0x6c, 0xc3, 0x9e, - 0xc9, 0x81, 0x65, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, 0xa2, 0xc7, 0x82, 0xe2, 0xb1, 0xad, - 0xe2, 0xb1, 0xa8, 0xc8, 0x96, 0xc8, 0xaa, 0xc6, 0xbc, 0x6b, 0xe1, 0x9a, 0xb4, 0xc5, - 0x9f, 0xc4, 0x92, 0xc6, 0x8e, 0xc3, 0x80, 0xc5, 0xb8, 0xc3, 0xa4, 0x2d, 0x38, 0xc5, - 0xb9, 0xc7, 0xb7, 0xc3, 0x8f, 0xc2, 0xb3, 0x62, 0xc5, 0x87, 0x21, 0xc6, 0x8f, 0xc7, - 0xb7, 0xe1, 0x9a, 0xb4, 0xc4, 0x84, 0x3e, 0xc7, 0x89, 0xc8, 0xaf, 0xc6, 0x98, 0xc6, - 0xb7, 0xc8, 0x9f, 0xc7, 0x9a, 0xc7, 0x96, 0xc3, 0xbb, 0x55, 0xe2, 0xb1, 0xb5, 0xc5, - 0xad, 0x2e, 0xc3, 0x86, 0xe1, 0x9b, 0x95, 0xc8, 0x81, 0xc3, 0x9b, 0xe1, 0x9b, 0xa4, - 0xcd, 0xb6, 0xc8, 0x8d, 0xc3, 0xa4, 0xc3, 0x89, 0xc8, 0x9d, 0xc8, 0xbe, 0x37, 0x25, - 0xc6, 0x99, 0x32, 0xc6, 0x92, 0xe1, 0x9b, 0x8b, 0x3a, 0x5f, 0x36, 0xc8, 0x9a, 0xc7, - 0xb3, 0x73, 0xc7, 0xaf, 0x7a, 0xc4, 0xac, 0xc7, 0x8b, 0xc8, 0x96, 0xc7, 0x82, 0xc8, - 0x8f, 0xc6, 0xb7, 0x37, 0xc3, 0xbc, 0xc5, 0x89, 0x2c, 0xc9, 0x84, 0xc5, 0xb7, 0xc6, - 0xb9, 0xc6, 0x90, 0xc7, 0x9f, 0xe2, 0xb1, 0xa5, 0xc5, 0x89, 0xc8, 0x8e, 0xc6, 0x8e, - 0xe1, 0x9b, 0x8e, 0xc8, 0xa6, 0xe1, 0x9a, 0xa4, 0xc5, 0xac, 0xc3, 0xa2, 0xc5, 0x9a, - 0x50, 0xc6, 0xa3, 0x44, 0xc6, 0x90, 0xc3, 0xae, 0x60, 0xc3, 0x8c, 0xc4, 0xb9, 0xc4, - 0x94, 0xc4, 0x9f, 0xc4, 0xa3, 0xc8, 0xb6, 0xc2, 0xa8, 0xc2, 0xa5, 0xc5, 0xb4, 0xe2, - 0xb1, 0xa2, 0x3a, 0xc7, 0xbd, 0x78, 0x78, 0xc3, 0xa9, 0xc2, 0xbc, 0xc4, 0xba, 0xc7, - 0x84, 0xc5, 0xb8, 0xe1, 0x9a, 0xaa, 0xe1, 0x9b, 0x83, 0xc3, 0x98, 0xc3, 0xb7, 0xc8, - 0x84, 0xcd, 0xbc, 0xcd, 0xba, 0xc4, 0xbe, 0xc2, 0xa9, 0xe1, 0x9a, 0xa0, 0xc5, 0xbd, - 0x5d, 0xc6, 0x92, 0xc8, 0xa0, 0x42, 0xc3, 0xb8, 0xe1, 0x9b, 0x8e, 0xc9, 0x89, 0xc2, - 0xb6, 0xc2, 0xb6, 0xc5, 0xbc, 0xc3, 0x88, 0xc5, 0x9b, 0xc8, 0xae, 0xc6, 0x98, 0xc7, - 0x9a, 0xc4, 0x82, 0xc6, 0x90, 0xc6, 0xa3, 0xc4, 0x98, 0xc9, 0x8f, 0xe1, 0x9a, 0xb1, - 0xe2, 0xb1, 0xbb, 0xc3, 0x97, 0xc8, 0xba, 0xc8, 0xab, 0xc7, 0xad, 0x4a, 0x3f, 0xe2, - 0xb1, 0xbb, 0xce, 0x8a, 0xc3, 0xa6, 0xc7, 0xbe, 0xc5, 0x8b, 0xe2, 0xb1, 0xbe, 0xc2, - 0xac, 0xc8, 0xbb, 0xc6, 0xb8, 0xc4, 0x8d, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0xf1, 0xfb, 0x77, 0xa6, 0xf4, 0x53, 0x77, 0x23, 0x9c, 0x47, 0x57, 0xff, 0xee, 0xe4, - 0xb2, 0x66, 0x42, 0x1b, 0xfc, 0x50, 0x00, 0xe3, 0x27, 0x68, 0x85, 0x5f, 0xa0, 0x6a, - 0x0f, 0x5d, 0xe2, 0x27, + 0x4b, 0xec, 0xc4, 0x9b, 0x22, 0x54, 0xb4, 0xdd, 0x36, 0x28, 0xac, 0x96, 0xdc, 0xda, + 0x24, 0x70, 0x0e, 0xf8, 0xd7, 0x30, 0x5a, 0x25, 0x4e, 0x8e, 0x0c, 0xa6, 0xce, 0x23, + 0x91, 0x3f, 0xd8, 0x0d, ], }, TestVector { key: [ - 0xbf, 0x39, 0x20, 0xce, 0x2e, 0x9e, 0x95, 0xb0, 0xee, 0xce, 0x13, 0x0a, 0x50, 0xba, - 0x7d, 0xcc, 0x6f, 0x26, 0x51, 0x2a, 0x9f, 0xc7, 0xb8, 0x04, 0xaf, 0xf0, 0x89, 0xf5, - 0x0c, 0xbc, 0xff, 0xf7, + 0xae, 0x36, 0xb6, 0x1a, 0x3d, 0x10, 0xf1, 0xaa, 0x75, 0x2a, 0xb1, 0xdc, 0x16, 0xe3, + 0xe4, 0x9b, 0x6a, 0xc0, 0xd2, 0xae, 0x19, 0x07, 0xd2, 0xe6, 0x94, 0x25, 0xec, 0x12, + 0xc9, 0x3a, 0xae, 0xbc, ], description: [ - 0x2d, 0xc4, 0x8b, 0xc5, 0xa1, 0xc2, 0xa3, 0xc6, 0x99, 0x41, 0xe2, 0xb1, 0xb6, 0x63, - 0x4a, 0xc5, 0xa5, 0xe2, 0xb1, 0xbe, 0xc2, 0xbe, 0xe1, 0x9b, 0x9a, 0xc7, 0xa1, 0xc3, - 0x85, 0xc7, 0xac, 0xc7, 0x99, 0xc3, 0x90, 0xc5, 0x98, 0xc7, 0x9d, 0xc6, 0x8d, 0xc8, - 0xad, 0xc8, 0xbe, 0x61, 0xc3, 0x9d, 0x55, 0x66, 0xc5, 0x89, 0xc6, 0x97, 0xc6, 0xb5, - 0xc3, 0xbe, 0xc4, 0x84, 0xc5, 0x96, 0xc3, 0x8c, 0xc7, 0xa5, 0xe1, 0x9b, 0x94, 0xc2, - 0xab, 0xc3, 0xbd, 0xc6, 0x95, 0x2b, 0xc8, 0x88, 0xc7, 0xa4, 0x68, 0xc8, 0xa5, 0xe1, - 0x9a, 0xbf, 0xc8, 0x84, 0xc4, 0x98, 0xc5, 0xa5, 0xe1, 0x9b, 0x8e, 0xe2, 0xb1, 0xba, - 0x28, 0xc6, 0xab, 0xc8, 0x93, 0xc7, 0xb5, 0xc2, 0xa1, 0xc5, 0x80, 0xc6, 0xb0, 0xc6, - 0x94, 0xc8, 0x84, 0xc2, 0xb7, 0xc5, 0x87, 0xe1, 0x9b, 0x9e, 0xc7, 0x93, 0x6c, 0xe1, - 0x9b, 0xa5, 0x41, 0x62, 0xcd, 0xb1, 0xc7, 0x94, 0xc8, 0xac, 0x3b, 0xc3, 0x95, 0xc4, - 0x83, 0xc6, 0xbb, 0xe2, 0xb1, 0xa2, 0xe1, 0x9a, 0xa6, 0xc9, 0x81, 0xe1, 0x9b, 0x85, - 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0x8c, 0xc3, 0xac, 0xc3, 0xa5, 0xc3, 0x80, 0xc3, 0x9d, - 0xc3, 0x9f, 0xc3, 0x96, 0xc3, 0xbb, 0xe2, 0xb1, 0xb4, 0xc8, 0xb1, 0x3b, 0xc5, 0x82, - 0x49, 0xc4, 0x90, 0xc4, 0xbd, 0xc9, 0x81, 0x4e, 0xc5, 0x8e, 0xc4, 0x94, 0xc3, 0xa7, - 0xc9, 0x89, 0xc6, 0x90, 0xc5, 0x8e, 0x3e, 0xe1, 0x9b, 0x99, 0x63, 0xc8, 0xb5, 0xc6, - 0xab, 0x38, 0xc8, 0xaf, 0xc5, 0xad, 0xc8, 0x8e, 0xc5, 0xab, 0xcd, 0xb0, 0xc5, 0xa3, - 0xc3, 0xb7, 0xc7, 0x85, 0xc2, 0xa7, 0x6d, 0xc2, 0xb7, 0x2f, 0xc3, 0xbd, 0xc7, 0x83, - 0xc5, 0xbb, 0xc2, 0xbf, 0xe2, 0xb1, 0xb8, 0xc4, 0xbc, 0xe1, 0x9b, 0xa5, 0xc7, 0x8c, - 0x71, 0x3d, 0xc7, 0xa0, 0xc9, 0x89, 0xc5, 0xb1, 0xc5, 0xa8, 0xc4, 0xa1, 0x5a, 0xe1, - 0x9a, 0xa4, 0xc7, 0xa6, 0xc6, 0x95, 0xc4, 0x90, 0xc7, 0x90, 0xe1, 0x9b, 0x90, 0xc3, - 0x92, 0xe1, 0x9a, 0xbd, 0xc7, 0xb2, 0xc7, 0xa9, 0xc6, 0xbb, 0xc6, 0x83, 0x21, 0xc9, - 0x87, 0xc3, 0x94, 0xc4, 0xac, 0xc2, 0xbf, 0xc4, 0x88, 0xc2, 0xa4, 0xc4, 0xbe, 0xc4, - 0xb2, 0xcd, 0xb6, 0xe2, 0xb1, 0xaa, 0xc9, 0x85, 0xc3, 0x97, 0xc8, 0x80, 0x78, 0xc8, - 0x95, 0xc6, 0x9f, 0xe1, 0x9b, 0xab, 0xc5, 0x8a, 0xc9, 0x82, 0xc8, 0x9a, 0x59, 0xe2, - 0xb1, 0xa7, 0xe1, 0x9b, 0xa2, 0x67, 0xc6, 0xb4, 0xc9, 0x8f, 0xc8, 0xbf, 0xc8, 0x85, - 0xc8, 0xb6, 0xc5, 0x94, 0x68, 0xe1, 0x9a, 0xaf, 0xe2, 0xb1, 0xa6, 0xc8, 0xae, 0xc4, - 0x89, 0xe1, 0x9a, 0xa2, 0xc7, 0xb9, 0xc8, 0xa0, 0xc2, 0xaf, 0xc7, 0x90, 0xc4, 0xb0, - 0xc4, 0xa7, 0xc5, 0xba, 0xc9, 0x82, 0xc3, 0x91, 0xe1, 0x9a, 0xa3, 0xc4, 0x92, 0x54, - 0xe1, 0x9a, 0xaa, 0xe1, 0x9b, 0xa7, 0xe1, 0x9a, 0xac, 0xc4, 0xb5, 0xe1, 0x9b, 0x9c, - 0xc5, 0x91, 0xce, 0x8c, 0xc5, 0xb1, 0x78, 0x66, 0xc5, 0x99, 0xcd, 0xbe, 0xc6, 0xa7, - 0xe1, 0x9b, 0x9e, 0xe2, 0xb1, 0xa4, 0xc3, 0x8e, 0x47, 0xc3, 0xae, 0xce, 0x86, 0x69, - 0xc6, 0x8a, 0xc3, 0x8e, 0xe1, 0x9b, 0xad, 0xc9, 0x88, 0xe1, 0x9b, 0x96, 0x7c, 0xe1, - 0x9b, 0x95, 0xc7, 0xba, 0xc8, 0xab, 0xe1, 0x9b, 0x85, 0xc7, 0x94, 0xc3, 0xa6, 0xe1, - 0x9b, 0xaa, 0x6d, 0xe1, 0x9a, 0xaf, 0xc4, 0x90, 0x79, 0xc3, 0xb5, 0xe2, 0xb1, 0xae, - 0x59, 0xc8, 0xab, 0xc8, 0xb2, 0xc8, 0xad, 0xe2, 0xb1, 0xb5, 0x50, 0xc5, 0xaf, 0x52, - 0xc6, 0xa6, 0xe1, 0x9b, 0x8b, 0xe1, 0x9a, 0xa5, 0x52, 0xcd, 0xbd, 0xc3, 0x86, 0x38, - 0xc4, 0xae, 0xc9, 0x81, 0xc5, 0x96, 0xc6, 0x94, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x10, 0xc3, 0x37, 0x4c, 0xc5, 0xd2, 0x6d, 0x14, 0xda, 0x3d, 0x1d, 0x41, 0x7e, 0x60, - 0x2c, 0x75, 0x2e, 0xfe, 0x36, 0x4f, 0x6c, 0x2f, 0x9e, 0xf3, 0x93, 0x39, 0x1d, 0x1b, - 0x48, 0xd3, 0x35, 0x2c, + 0xfb, 0xd0, 0x1e, 0x66, 0xf8, 0x29, 0xbf, 0xbf, 0x9d, 0x25, 0xd7, 0x36, 0xbc, 0xb3, + 0xa1, 0x04, 0x91, 0x82, 0x81, 0x4e, 0x4d, 0xdf, 0xc2, 0x30, 0x95, 0x63, 0x8f, 0x2f, + 0xf4, 0x3c, 0x15, 0x9b, ], }, TestVector { key: [ - 0x2a, 0x15, 0xb5, 0xe8, 0x6e, 0xe7, 0x0e, 0xe6, 0xab, 0xfb, 0xca, 0x6b, 0x2f, 0x15, - 0x6d, 0x43, 0xf1, 0x85, 0x7d, 0xb5, 0xcb, 0x5e, 0x6d, 0xd6, 0xb7, 0x23, 0x17, 0x20, - 0x05, 0xfc, 0x2f, 0x83, + 0x61, 0xbb, 0x33, 0x91, 0x59, 0xdf, 0x98, 0x20, 0xef, 0xae, 0xb6, 0x1d, 0x9a, 0x10, + 0xcd, 0xc1, 0x3b, 0x4c, 0x99, 0xfd, 0xc8, 0x6d, 0x94, 0x85, 0x11, 0x5d, 0xfd, 0x83, + 0x62, 0x36, 0xac, 0xf8, ], description: [ - 0x2c, 0xc3, 0x8b, 0x50, 0xe1, 0x9a, 0xb0, 0xc8, 0x96, 0xc7, 0xaf, 0x31, 0xc3, 0x9e, - 0xc3, 0x95, 0xc9, 0x87, 0xe1, 0x9b, 0x9f, 0x52, 0xe1, 0x9b, 0x8b, 0xc2, 0xb2, 0xc7, - 0x98, 0xe1, 0x9b, 0x84, 0xc2, 0xa6, 0xc2, 0xaa, 0xc7, 0xaa, 0xc3, 0x80, 0xc7, 0x95, - 0xc3, 0x8e, 0xe2, 0xb1, 0xba, 0x36, 0xc3, 0xa7, 0xc4, 0xa7, 0xe1, 0x9b, 0x8f, 0xe1, - 0x9b, 0x85, 0xc5, 0x87, 0xc7, 0xbb, 0xc5, 0x85, 0xc5, 0x93, 0xc5, 0x9c, 0xc8, 0x92, - 0x6b, 0xe1, 0x9b, 0x96, 0x78, 0xcd, 0xbe, 0xc4, 0x9a, 0xc7, 0x92, 0xc3, 0xb1, 0xc8, - 0xa8, 0xc3, 0x8b, 0x46, 0xc7, 0x94, 0xc5, 0x81, 0xc7, 0xa0, 0xc4, 0xb9, 0x78, 0x49, - 0xc5, 0xbb, 0xc5, 0xb5, 0xc5, 0x86, 0xc5, 0xb7, 0xc7, 0xb9, 0xc4, 0x86, 0xc5, 0xae, - 0xc7, 0xb4, 0x37, 0xc4, 0x89, 0x47, 0xe1, 0x9b, 0x88, 0xc6, 0x9d, 0xc4, 0xa8, 0xe2, - 0xb1, 0xa4, 0xc3, 0x9f, 0x3e, 0xc5, 0xa7, 0xc8, 0xbe, 0x41, 0xc9, 0x8a, 0xe1, 0x9a, - 0xad, 0xc2, 0xba, 0xc3, 0xba, 0xc4, 0x8b, 0xc5, 0x9b, 0xc5, 0xa7, 0x7a, 0xcd, 0xb6, - 0xc8, 0xb5, 0xc7, 0xa0, 0xc4, 0x81, 0xe1, 0x9b, 0x98, 0xc3, 0xb3, 0x72, 0xe1, 0x9a, - 0xad, 0xc6, 0x85, 0xcd, 0xb0, 0xce, 0x89, 0xc8, 0x86, 0xc3, 0x90, 0xc6, 0x83, 0x51, - 0xc7, 0x80, 0xc3, 0x8c, 0xe2, 0xb1, 0xa3, 0xc9, 0x8f, 0xc3, 0x8c, 0xc5, 0xad, 0xc3, - 0x86, 0xe1, 0x9b, 0xa7, 0x54, 0xc3, 0xb0, 0xce, 0x85, 0xc3, 0xbc, 0xe2, 0xb1, 0xa3, - 0xc4, 0x9f, 0x76, 0xc3, 0x91, 0xc5, 0xa0, 0xc4, 0x8f, 0xc5, 0x91, 0xc4, 0xa3, 0x33, - 0xc6, 0x9d, 0xe1, 0x9b, 0x8c, 0xc3, 0xa6, 0xc3, 0xb8, 0xe1, 0x9a, 0xa5, 0xe2, 0xb1, - 0xac, 0xc7, 0x9b, 0xc5, 0xaf, 0xc4, 0xb0, 0xe1, 0x9a, 0xb4, 0x4f, 0xe2, 0xb1, 0xa6, - 0x4e, 0x5f, 0xc8, 0xbf, 0xc3, 0xb3, 0xe1, 0x9b, 0x9a, 0xe1, 0x9a, 0xa4, 0xc7, 0x89, - 0xc6, 0x88, 0xcd, 0xbb, 0xc3, 0xa0, 0xc3, 0xb3, 0xcd, 0xb2, 0xc3, 0xbb, 0xc6, 0xa0, - 0xe1, 0x9b, 0xab, 0xc3, 0xa1, 0xc7, 0x97, 0x32, 0xe1, 0x9b, 0xa5, 0xc7, 0xac, 0xc5, - 0x9c, 0xc8, 0xbf, 0xc4, 0xbc, 0xc4, 0x8a, 0x3a, 0x60, 0xc6, 0x81, 0xe1, 0x9b, 0x80, - 0xc4, 0x82, 0xce, 0x89, 0xe1, 0x9a, 0xa7, 0xe1, 0x9b, 0x9f, 0xc7, 0x92, 0xe2, 0xb1, - 0xa7, 0xe1, 0x9b, 0x82, 0xc7, 0x82, 0xe1, 0x9b, 0x91, 0xc6, 0xb5, 0x5e, 0xc7, 0xb0, - 0x3a, 0xc3, 0xa7, 0xce, 0x89, 0xe1, 0x9a, 0xbf, 0xc4, 0xbe, 0xc5, 0x9e, 0xc5, 0xb0, - 0xe2, 0xb1, 0xb6, 0xc9, 0x8f, 0xc8, 0x94, 0xc3, 0xbd, 0x6b, 0x4c, 0xc3, 0xad, 0xc8, - 0xb3, 0xc4, 0x99, 0xc3, 0xa5, 0xe2, 0xb1, 0xaf, 0xc4, 0x9d, 0x24, 0xc3, 0x91, 0xc5, - 0xa6, 0xc2, 0xaa, 0xe1, 0x9a, 0xb9, 0xc5, 0x9d, 0xc3, 0xab, 0xc5, 0xa3, 0xc6, 0xb6, - 0xe1, 0x9a, 0xac, 0x73, 0x7d, 0x4f, 0xe2, 0xb1, 0xb9, 0xc3, 0x8d, 0xc2, 0xa9, 0x57, - 0x2f, 0xc4, 0x99, 0xc7, 0xa6, 0xc6, 0xbb, 0xe2, 0xb1, 0xa5, 0xc3, 0xb7, 0x70, 0xc6, - 0x8c, 0xc6, 0xa9, 0xc7, 0xbf, 0xc2, 0xa7, 0xc3, 0xa2, 0xc2, 0xb0, 0xc8, 0x81, 0xc3, - 0x81, 0xe1, 0x9a, 0xba, 0xc5, 0x9c, 0xc4, 0x90, 0xc4, 0xa7, 0x71, 0xc8, 0xa9, 0xe1, - 0x9b, 0x9c, 0xe2, 0xb1, 0xab, 0x3e, 0x78, 0xc2, 0xb1, 0xc5, 0x88, 0xc4, 0xb1, 0xc7, - 0x9e, 0x38, 0xc8, 0xac, 0x71, 0xcd, 0xba, 0xc8, 0xba, 0x69, 0xc3, 0x8a, 0xcd, 0xbd, - 0xe1, 0x9b, 0xb0, 0xc8, 0x99, 0xc7, 0xbb, 0xc8, 0xb2, 0xc9, 0x8e, 0xc8, 0xac, 0xc2, - 0xa9, 0xc3, 0xb1, 0x3e, 0xc5, 0xbf, 0xc8, 0x8a, 0xe2, 0xb1, 0xaf, 0xc7, 0xaf, 0xc7, - 0x88, 0x5b, 0x4b, 0xe1, 0x9b, 0x87, 0x5a, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x66, 0x9e, 0x20, 0x80, 0x8b, 0xa2, 0xa4, 0xd1, 0x31, 0xed, 0xeb, 0x7a, 0x39, 0x11, - 0xb1, 0xe1, 0x24, 0xd3, 0x77, 0x56, 0xd5, 0xb1, 0x3c, 0x61, 0xc6, 0x47, 0x73, 0x41, - 0xd2, 0x47, 0x57, 0xb6, + 0xd0, 0x46, 0xef, 0xd5, 0xe2, 0xf1, 0xdd, 0x27, 0x2c, 0x7e, 0x65, 0x8a, 0x72, 0x1d, + 0x36, 0x21, 0x4c, 0x4d, 0xbc, 0x03, 0xf5, 0x99, 0x04, 0x3e, 0x6e, 0xfc, 0xbf, 0xb5, + 0x6a, 0x6e, 0x90, 0x28, ], }, TestVector { key: [ - 0x48, 0xbe, 0xf1, 0xc3, 0x4e, 0x8a, 0x86, 0x4c, 0x7e, 0xaa, 0x0c, 0x85, 0x31, 0x63, - 0x83, 0xc3, 0xf1, 0xc9, 0xb1, 0x87, 0xd5, 0x01, 0x74, 0xb4, 0x9a, 0xfe, 0xbd, 0x99, - 0xc3, 0xa1, 0xaf, 0xf9, + 0x49, 0x26, 0x53, 0x80, 0xd2, 0xb0, 0x2e, 0x0a, 0x1d, 0x98, 0x8f, 0x3d, 0xe3, 0x45, + 0x8b, 0x6e, 0x00, 0x29, 0x1d, 0xb0, 0xe6, 0x2e, 0x17, 0x47, 0x91, 0xd0, 0x09, 0x29, + 0x9f, 0x61, 0xfe, 0xc4, ], description: [ - 0x5d, 0xc7, 0x88, 0xc2, 0xb9, 0x61, 0xc8, 0xb0, 0xc3, 0x98, 0xe2, 0xb1, 0xab, 0xc6, - 0xa9, 0xc8, 0xa7, 0xe2, 0xb1, 0xa9, 0xc5, 0xbb, 0x3a, 0x68, 0xc7, 0x83, 0xc8, 0xa1, - 0xc8, 0xbd, 0xc4, 0x9e, 0x6c, 0xc3, 0xab, 0xe1, 0x9b, 0xaf, 0xe1, 0x9b, 0x83, 0xc6, - 0xb7, 0xc2, 0xa4, 0xc4, 0x81, 0xc7, 0x9c, 0xc5, 0xb2, 0xe1, 0x9a, 0xaf, 0xe1, 0x9a, - 0xab, 0xc5, 0x88, 0xe1, 0x9a, 0xb0, 0xc6, 0xac, 0x63, 0xe1, 0x9b, 0xb0, 0xc7, 0xbe, - 0xc6, 0x8a, 0x3c, 0xc5, 0xb2, 0xc3, 0x89, 0xc2, 0xb0, 0x3d, 0xc2, 0xba, 0xe1, 0x9b, - 0x84, 0xc5, 0x8b, 0xe2, 0xb1, 0xb9, 0xc5, 0x91, 0x39, 0xc6, 0xb6, 0xc7, 0x9e, 0xc8, - 0x81, 0x74, 0xc7, 0xa8, 0xc8, 0xb0, 0xc2, 0xb6, 0xc4, 0x88, 0xc3, 0x9d, 0xc7, 0x89, - 0xc9, 0x8c, 0xc4, 0x85, 0xc3, 0x93, 0xc7, 0xaa, 0xc5, 0xb6, 0xc7, 0x9a, 0xc3, 0xae, - 0xe1, 0x9b, 0x81, 0xc3, 0x96, 0xc5, 0x80, 0xc5, 0x92, 0xc2, 0xa1, 0xc6, 0xa3, 0xe1, - 0x9a, 0xb7, 0xc2, 0xbf, 0xc5, 0xbb, 0xc7, 0xa9, 0xc7, 0x85, 0xc8, 0xbd, 0xc3, 0x8b, - 0xc7, 0xa6, 0xc3, 0xa0, 0xc6, 0x90, 0xe1, 0x9a, 0xb7, 0xc8, 0x88, 0xc4, 0x91, 0xc8, - 0x94, 0xc8, 0x9b, 0x6d, 0xc3, 0xa3, 0xc3, 0xb8, 0xc6, 0x88, 0xc5, 0xb1, 0x6e, 0xc7, - 0x87, 0x40, 0xc6, 0x8f, 0x7a, 0xc8, 0xa8, 0xc3, 0xb4, 0x46, 0xc3, 0xac, 0xc6, 0xa7, - 0xc6, 0x9c, 0xc8, 0x95, 0xc6, 0x87, 0xc6, 0x84, 0xc6, 0xb5, 0xc8, 0x97, 0xc3, 0xb8, - 0x69, 0x48, 0xe1, 0x9a, 0xaf, 0x53, 0xc4, 0xb8, 0xc3, 0x9c, 0xc4, 0xa8, 0xc5, 0xa6, - 0xc2, 0xbd, 0xc4, 0x92, 0xc2, 0xaf, 0xc2, 0xaf, 0xc4, 0xbb, 0xc7, 0x8c, 0xc3, 0xb9, - 0xc6, 0xb5, 0xc8, 0xa2, 0xc5, 0xb1, 0xc3, 0x81, 0xc6, 0x86, 0xc9, 0x8a, 0x4d, 0xc4, - 0xb8, 0xc4, 0xb4, 0xe1, 0x9a, 0xbf, 0xc2, 0xa2, 0xc4, 0x8d, 0xce, 0x87, 0xe2, 0xb1, - 0xbb, 0xe2, 0xb1, 0xa1, 0xc3, 0x87, 0xe1, 0x9a, 0xae, 0xc6, 0xb2, 0xc6, 0xa7, 0xc9, - 0x8d, 0xe1, 0x9b, 0xa8, 0xc4, 0x9a, 0xcd, 0xb1, 0xc5, 0x98, 0xc4, 0xbb, 0xc5, 0x95, - 0xc9, 0x8b, 0x61, 0xe2, 0xb1, 0xbf, 0xc3, 0xa6, 0xc5, 0xbd, 0xc4, 0x9c, 0xce, 0x85, - 0xe2, 0xb1, 0xa0, 0xc5, 0xbf, 0xc5, 0xbf, 0x34, 0xc7, 0x82, 0xcd, 0xb6, 0xe1, 0x9b, - 0x95, 0xc5, 0xaf, 0xc5, 0x98, 0xc8, 0x9f, 0xc2, 0xb8, 0xc4, 0xa5, 0xc5, 0xb8, 0xc4, - 0xad, 0xc8, 0xaf, 0xc6, 0x81, 0x6b, 0xc4, 0x8b, 0x55, 0xc7, 0xbe, 0xc3, 0xb4, 0xc6, - 0xa2, 0x62, 0xc8, 0xa0, 0xc3, 0x8d, 0xc3, 0xa8, 0x75, 0xc5, 0x90, 0xcd, 0xb1, 0x4d, - 0xc7, 0x9a, 0xc5, 0x87, 0xc5, 0xb5, 0xc6, 0x88, 0x25, 0xe2, 0xb1, 0xac, 0xc7, 0xa3, - 0xc9, 0x8d, 0xc8, 0x98, 0x6b, 0xc4, 0x9b, 0xc7, 0x90, 0xc8, 0x8e, 0xc8, 0x86, 0x36, - 0xe1, 0x9a, 0xaa, 0xc4, 0xa8, 0xe1, 0x9a, 0xa9, 0xc2, 0xb9, 0xe1, 0x9a, 0xb6, 0xc2, - 0xa8, 0xc2, 0xa4, 0xc3, 0x9a, 0xc3, 0x86, 0xc4, 0xb4, 0xc7, 0xa1, 0x53, 0xe2, 0xb1, - 0xa5, 0xc5, 0xa1, 0xe1, 0x9b, 0xa2, 0xc5, 0xaa, 0xc8, 0xa1, 0x2d, 0xc8, 0x96, 0x75, - 0xc2, 0xa6, 0xe1, 0x9b, 0x9b, 0xc6, 0xbb, 0xc9, 0x86, 0xc4, 0xa3, 0xc5, 0xb1, 0xe1, - 0x9b, 0x92, 0x39, 0x79, 0x5b, 0xc4, 0xbd, 0xe1, 0x9b, 0xa2, 0xe1, 0x9a, 0xa3, 0xc5, - 0xb6, 0xc8, 0x99, 0xc2, 0xb3, 0xe1, 0x9b, 0x8d, 0xc3, 0xbd, 0xc3, 0x86, 0xc4, 0x89, - 0xe2, 0xb1, 0xb2, 0xe1, 0x9b, 0xb0, 0x73, 0xe1, 0x9b, 0x9a, 0x34, 0xc4, 0x8a, 0x56, - 0xc2, 0xb5, 0xc4, 0xba, 0xe2, 0xb1, 0xa7, 0xc7, 0xa4, 0xcd, 0xbe, 0xe2, 0xb1, 0xb6, - 0xc8, 0xbc, 0xc8, 0x81, 0xc7, 0xac, 0xc8, 0x8e, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x31, 0x1a, 0x81, 0xd9, 0x40, 0x52, 0x81, 0x50, 0xe5, 0xb4, 0x70, 0x97, 0x96, 0xb6, - 0x03, 0x22, 0x7a, 0xd1, 0xde, 0x1c, 0x15, 0x00, 0xef, 0x44, 0x5c, 0x40, 0xa4, 0xb2, - 0xaa, 0x21, 0xa1, 0x06, + 0xe1, 0x39, 0xe7, 0x7a, 0x0b, 0x76, 0xfc, 0x01, 0xa1, 0xec, 0x3b, 0x46, 0xf0, 0x21, + 0x29, 0x7b, 0xfb, 0x41, 0xd1, 0x7f, 0x5f, 0x98, 0x3d, 0xed, 0x61, 0x81, 0xee, 0xd9, + 0x5d, 0xe4, 0x2e, 0xb6, ], }, TestVector { key: [ - 0xff, 0x08, 0xec, 0x66, 0x3e, 0x18, 0x56, 0x51, 0x3f, 0xf6, 0x90, 0x80, 0x0c, 0x56, - 0x49, 0x91, 0xb2, 0x51, 0x67, 0xc2, 0xdd, 0x14, 0x07, 0x98, 0x13, 0x73, 0xc6, 0xd5, - 0x30, 0x65, 0xe3, 0x67, + 0x19, 0x58, 0x53, 0x8b, 0x12, 0x17, 0xa0, 0x3d, 0x89, 0xcd, 0x83, 0xb8, 0x3d, 0x0b, + 0xdd, 0x40, 0xa6, 0x9a, 0xbe, 0x3a, 0xc2, 0x5d, 0x00, 0xc6, 0xd2, 0x69, 0x97, 0xf9, + 0xf2, 0x57, 0x4d, 0x4f, ], description: [ - 0xe1, 0x9b, 0x9e, 0xe1, 0x9a, 0xba, 0xc5, 0x9e, 0xe1, 0x9b, 0xa0, 0xc5, 0xbd, 0xe2, - 0xb1, 0xb8, 0xc8, 0x99, 0xc6, 0xb6, 0xc5, 0x9b, 0xc3, 0x83, 0xc2, 0xbd, 0xe1, 0x9a, - 0xbb, 0xe1, 0x9b, 0xa3, 0xc7, 0x8b, 0xc5, 0xb1, 0xc4, 0x9e, 0xe1, 0x9b, 0xa5, 0xe2, - 0xb1, 0xa5, 0xc8, 0xac, 0x58, 0xcd, 0xb2, 0xc6, 0x88, 0xc6, 0x85, 0xc7, 0x90, 0xc6, - 0x81, 0xe2, 0xb1, 0xb7, 0xc3, 0xb7, 0xc8, 0xb8, 0x7b, 0xe1, 0x9a, 0xb8, 0x64, 0xc4, - 0x85, 0x5f, 0xcd, 0xb3, 0xc8, 0xb1, 0xc9, 0x87, 0xc4, 0xbf, 0xc5, 0xbe, 0x2f, 0xe1, - 0x9b, 0x8c, 0xc7, 0xbc, 0xc5, 0xab, 0xe1, 0x9a, 0xb6, 0xe2, 0xb1, 0xa9, 0xc6, 0xb7, - 0xc4, 0x89, 0x63, 0xc3, 0xa5, 0xc2, 0xbf, 0xc6, 0x9b, 0x5c, 0xc5, 0x93, 0xc6, 0xb0, - 0xc4, 0xaa, 0xc8, 0xb3, 0xc8, 0x89, 0xc7, 0xbc, 0xc2, 0xa7, 0xc7, 0xa9, 0xc8, 0xb2, - 0xc7, 0xbd, 0xe1, 0x9b, 0xa5, 0xc5, 0xb5, 0xc4, 0x8e, 0xc9, 0x82, 0xc5, 0x84, 0xc6, - 0x86, 0xc3, 0x8f, 0xc4, 0x85, 0xc6, 0xa0, 0xc8, 0xa3, 0xc6, 0xa6, 0xe1, 0x9a, 0xa9, - 0xc5, 0x99, 0xc2, 0xa8, 0xc7, 0xbc, 0xe2, 0xb1, 0xbb, 0xc4, 0xa4, 0xc6, 0xb9, 0xc7, - 0x90, 0xc9, 0x8c, 0xc3, 0x80, 0xc7, 0x8f, 0xc5, 0x94, 0xc8, 0x88, 0xc9, 0x86, 0xc3, - 0xbd, 0xe2, 0xb1, 0xb1, 0xe2, 0xb1, 0xbe, 0x3c, 0xc6, 0x87, 0x7c, 0x6f, 0xc3, 0xbd, - 0xc6, 0x94, 0xc2, 0xa1, 0x7d, 0xc3, 0x87, 0xc2, 0xac, 0xcd, 0xb3, 0xc8, 0xa3, 0xc2, - 0xbb, 0x61, 0xc4, 0x97, 0xc9, 0x8d, 0x6c, 0xe2, 0xb1, 0xad, 0xc5, 0x8c, 0xc5, 0xa3, - 0xc2, 0xb2, 0xe2, 0xb1, 0xbf, 0xc5, 0xa2, 0xe1, 0x9b, 0x85, 0xc6, 0xb0, 0x78, 0xe1, - 0x9b, 0x80, 0xcd, 0xb6, 0xc5, 0x80, 0xc8, 0x99, 0xc2, 0xba, 0xc3, 0x96, 0xc6, 0x8c, - 0xc7, 0xaf, 0xc4, 0x97, 0xc3, 0x8b, 0xc4, 0xa4, 0xc6, 0xb0, 0xc7, 0x98, 0xc4, 0x8d, - 0x62, 0xc8, 0x8b, 0xc6, 0xaf, 0x4d, 0xc8, 0xb7, 0xc8, 0x8c, 0x5e, 0xc2, 0xab, 0xc4, - 0x86, 0xc5, 0xb1, 0x2c, 0xe2, 0xb1, 0xad, 0xe1, 0x9b, 0xa7, 0xc9, 0x8a, 0xc3, 0xb1, - 0xc3, 0xae, 0xc4, 0x98, 0xc7, 0xbe, 0xc5, 0x94, 0xc3, 0x8a, 0xce, 0x89, 0xcd, 0xbb, - 0xc6, 0xbc, 0xcd, 0xb1, 0xc4, 0x8a, 0xc5, 0x90, 0xc6, 0xa9, 0xe1, 0x9b, 0x85, 0xc9, - 0x8c, 0x63, 0xe1, 0x9a, 0xab, 0x57, 0xc3, 0xb7, 0xc6, 0xb9, 0xce, 0x86, 0xc4, 0xa7, - 0xc3, 0x80, 0xc8, 0xb6, 0xe1, 0x9b, 0x9c, 0xcd, 0xb6, 0xc3, 0xa3, 0xc4, 0x9c, 0xe2, - 0xb1, 0xa7, 0xc7, 0x88, 0xc4, 0xb6, 0xc8, 0x80, 0xe1, 0x9b, 0x95, 0x33, 0xc2, 0xb6, - 0xc6, 0x86, 0xc6, 0xae, 0xc6, 0x97, 0xc7, 0x9b, 0xc7, 0xbf, 0xc6, 0x95, 0xe1, 0x9b, - 0xab, 0xc5, 0x8b, 0x58, 0xc7, 0x9a, 0xc8, 0x81, 0xc2, 0xb2, 0xc3, 0x8a, 0xc9, 0x81, - 0xc6, 0x84, 0xc6, 0xb5, 0xc5, 0xa6, 0xc5, 0xaf, 0xc9, 0x8e, 0xc2, 0xbc, 0xc7, 0xb5, - 0xe1, 0x9b, 0x8b, 0xc8, 0x8c, 0xc9, 0x89, 0xe1, 0x9b, 0x91, 0xe1, 0x9a, 0xb8, 0x3b, - 0xc5, 0x88, 0xc2, 0xa5, 0xc8, 0xa0, 0xc4, 0x97, 0xe1, 0x9b, 0x8d, 0xc2, 0xa4, 0xc3, - 0x83, 0xc3, 0x9a, 0x4c, 0xe1, 0x9b, 0x80, 0xc4, 0xa5, 0xc3, 0xa9, 0xc9, 0x80, 0xc7, - 0xb3, 0xc7, 0xb4, 0xe1, 0x9b, 0x80, 0xe1, 0x9b, 0x8e, 0xc5, 0xb9, 0xc2, 0xb9, 0xc6, - 0xb7, 0xc8, 0xbc, 0xc5, 0xa6, 0xc4, 0x83, 0xe1, 0x9b, 0x80, 0xc8, 0x92, 0xc4, 0x94, - 0xe1, 0x9b, 0x8c, 0xc8, 0xbc, 0xc4, 0x8e, 0xe2, 0xb1, 0xb3, 0x38, 0xc8, 0x8d, 0xc9, - 0x8c, 0xc6, 0xbd, 0xc3, 0x90, 0xc6, 0xa9, 0xc3, 0xb6, 0x66, 0x38, 0xc8, 0x97, 0xe1, - 0x9a, 0xa1, 0xc8, 0xb2, 0xc5, 0xab, 0xc7, 0x99, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x4f, 0x95, 0x9d, 0x88, 0x63, 0xb8, 0x36, 0x0b, 0x43, 0x30, 0x2b, 0xef, 0x35, 0x13, - 0x1f, 0x69, 0xd4, 0xf4, 0x26, 0xb1, 0x38, 0x3e, 0x54, 0xae, 0x38, 0x96, 0x40, 0x31, - 0xa8, 0xe5, 0xf9, 0x21, + 0xb3, 0xd1, 0x28, 0x2b, 0xf4, 0x32, 0x3d, 0xc3, 0x01, 0xa2, 0xd5, 0x9b, 0x8b, 0x80, + 0x41, 0xe2, 0xd2, 0x9b, 0x69, 0xee, 0x9b, 0xbc, 0x1c, 0x41, 0x06, 0xd3, 0x60, 0x1e, + 0x40, 0x39, 0x61, 0x3e, ], }, TestVector { key: [ - 0x39, 0xc4, 0x51, 0xf4, 0xd8, 0xdd, 0xcf, 0x69, 0x05, 0xed, 0xd8, 0x82, 0x5a, 0xd9, - 0x81, 0xb9, 0xe7, 0x3c, 0xa6, 0x83, 0x1c, 0xa2, 0xb3, 0xd7, 0xe8, 0xce, 0xf3, 0xd0, - 0xba, 0xaa, 0x31, 0x1b, + 0x9a, 0x0e, 0x46, 0x39, 0xb4, 0x69, 0x1f, 0x02, 0x7c, 0x0d, 0xb7, 0xfe, 0xf1, 0xbb, + 0x5e, 0xf9, 0x0a, 0xcd, 0xb7, 0x08, 0x62, 0x6d, 0x2e, 0x1f, 0x3e, 0x38, 0x3e, 0xe7, + 0x5b, 0x31, 0xcf, 0x57, ], description: [ - 0xc7, 0x94, 0xc5, 0xac, 0xc4, 0x97, 0xc6, 0xba, 0xe1, 0x9b, 0x97, 0xc7, 0x84, 0xc8, - 0xb6, 0xe1, 0x9b, 0x9d, 0xc8, 0x9c, 0xcd, 0xb5, 0xc3, 0x93, 0x7d, 0xc8, 0xa7, 0xc4, - 0x86, 0xc6, 0xab, 0xc4, 0x88, 0xe2, 0xb1, 0xb1, 0x6b, 0xe1, 0x9a, 0xa6, 0x68, 0xc6, - 0x9c, 0xc2, 0xb0, 0xc6, 0xba, 0xc7, 0xa6, 0xc5, 0x8c, 0xc9, 0x89, 0xc8, 0xbe, 0xc3, - 0xbc, 0xc5, 0xb7, 0xc7, 0x95, 0x5c, 0xc3, 0x96, 0xc4, 0x89, 0xc6, 0x84, 0xc3, 0xb2, - 0xc9, 0x87, 0x38, 0x45, 0xc3, 0xa1, 0xe2, 0xb1, 0xb1, 0x41, 0xc5, 0xac, 0xc6, 0xa1, - 0xc2, 0xa4, 0x34, 0xc4, 0xb0, 0xc2, 0xb5, 0xc5, 0xa2, 0xe1, 0x9a, 0xa9, 0xc4, 0xb6, - 0xc5, 0xbd, 0xc2, 0xbd, 0xc4, 0xa2, 0xc6, 0x8c, 0xc2, 0xb4, 0xc8, 0xb1, 0xc3, 0x95, - 0xc2, 0xbf, 0xc7, 0x99, 0xe1, 0x9b, 0x99, 0xc6, 0x8a, 0xc8, 0xaf, 0xc6, 0x9f, 0xc4, - 0x93, 0x38, 0xc7, 0x94, 0xc8, 0xa2, 0xc8, 0x84, 0xc6, 0x8f, 0x3a, 0xc5, 0xbd, 0xe1, - 0x9b, 0x97, 0xc5, 0x88, 0xcd, 0xb6, 0xc5, 0xa1, 0xc6, 0x96, 0xc4, 0x9f, 0xc3, 0x94, - 0xc5, 0xa6, 0xc4, 0xa4, 0xcd, 0xb2, 0xc7, 0xbc, 0xc8, 0x8d, 0x78, 0xc9, 0x86, 0xe2, - 0xb1, 0xab, 0xce, 0x84, 0xcd, 0xbd, 0xc4, 0x95, 0x65, 0xc7, 0x88, 0xc4, 0x84, 0xce, - 0x8c, 0xc3, 0xb1, 0xc2, 0xaf, 0xc6, 0xbf, 0xc4, 0x92, 0x25, 0xc7, 0xbc, 0xe2, 0xb1, - 0xb0, 0xc5, 0x93, 0xc7, 0x8a, 0xc5, 0x92, 0x75, 0xc4, 0xb7, 0xc6, 0x86, 0xc3, 0xbf, - 0xc7, 0xb7, 0xc6, 0xae, 0x67, 0xc2, 0xa9, 0xc6, 0x9e, 0xc5, 0x97, 0xcd, 0xb0, 0xc3, - 0x92, 0xc3, 0xac, 0xc5, 0xbb, 0xc3, 0x9a, 0xc3, 0xa1, 0xc6, 0x87, 0xc3, 0x8e, 0xc3, - 0xb8, 0xc9, 0x80, 0xe1, 0x9a, 0xa7, 0xc7, 0xac, 0x65, 0x24, 0xc6, 0x9c, 0xc3, 0xb2, - 0xc4, 0x82, 0x64, 0xc7, 0x8e, 0xc5, 0x8b, 0xe1, 0x9b, 0x8a, 0xe1, 0x9b, 0x89, 0xc9, - 0x82, 0xc3, 0x97, 0xc2, 0xac, 0xc4, 0x80, 0xc6, 0x83, 0xc4, 0xa6, 0xc4, 0xb6, 0xce, - 0x89, 0x52, 0x59, 0xce, 0x85, 0xc9, 0x85, 0xc6, 0xa9, 0xc4, 0x80, 0xc9, 0x8b, 0xe1, - 0x9a, 0xbe, 0xc9, 0x8e, 0xc2, 0xae, 0xc8, 0x96, 0xc6, 0x95, 0xc8, 0xaa, 0xe1, 0x9b, - 0x9b, 0xe1, 0x9a, 0xac, 0xc2, 0xb1, 0xc2, 0xaf, 0xc8, 0x8e, 0xe1, 0x9a, 0xae, 0xe1, - 0x9a, 0xa7, 0xc4, 0xb7, 0xc8, 0x82, 0xc3, 0xb2, 0xc4, 0xab, 0xc4, 0xbf, 0xc7, 0x91, - 0xe1, 0x9b, 0x9b, 0xc8, 0x90, 0xc7, 0x93, 0xe1, 0x9b, 0xa3, 0xc7, 0xb5, 0xc5, 0xa0, - 0xc8, 0xa2, 0xc8, 0x86, 0xc9, 0x86, 0xc2, 0xaa, 0x3d, 0xc4, 0xbf, 0xc5, 0xbc, 0xc4, - 0x96, 0xc3, 0xa5, 0xc3, 0x90, 0xc5, 0xb9, 0xc3, 0xa8, 0xc7, 0x80, 0xc5, 0x84, 0xce, - 0x89, 0xcd, 0xb7, 0xc3, 0x9b, 0xc2, 0xa1, 0xc7, 0x87, 0xcd, 0xb3, 0xe2, 0xb1, 0xb0, - 0xc8, 0x8b, 0xe1, 0x9a, 0xb1, 0xe1, 0x9a, 0xaf, 0x35, 0xc3, 0xa9, 0xc7, 0x85, 0xc4, - 0x85, 0xcd, 0xb1, 0xc4, 0xa7, 0xc3, 0x83, 0xe1, 0x9b, 0x94, 0xe2, 0xb1, 0xbf, 0xc4, - 0x80, 0x29, 0x2a, 0xc3, 0xa2, 0xe1, 0x9b, 0x88, 0xc3, 0x87, 0xe1, 0x9a, 0xb0, 0xc2, - 0xb8, 0xc7, 0x85, 0xc8, 0xb3, 0xc5, 0x84, 0x63, 0xc5, 0x8d, 0x3b, 0xc8, 0x9f, 0x5e, - 0xe2, 0xb1, 0xa5, 0x5c, 0xc4, 0x9f, 0xc8, 0xb4, 0xe2, 0xb1, 0xa0, 0xc7, 0xa5, 0x37, - 0xc6, 0xa2, 0xc8, 0xad, 0xe1, 0x9b, 0xa3, 0xc8, 0x96, 0xc6, 0xb6, 0xe2, 0xb1, 0xa4, - 0xc2, 0xb7, 0xc3, 0x86, 0xc4, 0xb1, 0xc6, 0x9f, 0xc8, 0x8c, 0xc8, 0xb3, 0xe1, 0x9a, - 0xa6, 0xc7, 0xa2, 0xc3, 0xbd, 0xe1, 0x9b, 0x8e, 0xc3, 0x9d, 0x21, 0xe1, 0x9b, 0xa5, - 0xe1, 0x9b, 0x8a, 0xc8, 0xb2, 0x24, 0xc8, 0x91, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x2c, 0x25, 0xd3, 0x35, 0xaf, 0xa2, 0xd5, 0x69, 0x72, 0x42, 0xf6, 0x18, 0x5c, 0x00, - 0x69, 0xd7, 0x9b, 0x33, 0xc8, 0x4a, 0x3f, 0x7f, 0x5c, 0x3c, 0x26, 0x5d, 0x3e, 0x88, - 0x45, 0xac, 0xcd, 0x0e, + 0x2b, 0xb6, 0x4e, 0xa4, 0x07, 0xfd, 0x00, 0xb6, 0x4c, 0xe5, 0x96, 0x2e, 0x57, 0x3f, + 0xaf, 0x9a, 0x40, 0xfb, 0x3a, 0x4d, 0xc1, 0xcc, 0xbf, 0x87, 0xe1, 0xe0, 0xe7, 0x97, + 0x8a, 0x19, 0xbd, 0x39, ], }, TestVector { key: [ - 0xa2, 0x8d, 0x36, 0xc0, 0xa0, 0xe1, 0xd6, 0x54, 0x57, 0x44, 0x64, 0xec, 0x5e, 0x0c, - 0x8d, 0x87, 0x85, 0x6e, 0xb9, 0xdf, 0xd2, 0x1d, 0x4d, 0xa2, 0xb9, 0xea, 0x34, 0xfd, - 0xe7, 0x3b, 0x19, 0x42, + 0x7d, 0xd6, 0xd7, 0x61, 0xe1, 0x02, 0x01, 0x37, 0xfa, 0x01, 0xb4, 0xdd, 0xd3, 0xb0, + 0xf3, 0x48, 0x04, 0xcc, 0x10, 0xcc, 0x4e, 0x9f, 0x6e, 0x9d, 0xf5, 0xb6, 0x04, 0x69, + 0xf5, 0x79, 0x36, 0x67, ], description: [ - 0xc8, 0x96, 0xcd, 0xba, 0xc7, 0x94, 0x32, 0xc5, 0xbf, 0xc7, 0x9c, 0xc3, 0x94, 0xc5, - 0x97, 0xc7, 0x84, 0xc2, 0xb1, 0xc3, 0xa9, 0x25, 0xc2, 0xb6, 0xc7, 0x84, 0xce, 0x84, - 0xc7, 0x8d, 0xc8, 0xb3, 0xe1, 0x9a, 0xa3, 0xc3, 0xb1, 0xe1, 0x9a, 0xa4, 0xc7, 0xa6, - 0xc2, 0xa6, 0xe1, 0x9a, 0xb5, 0xc8, 0x97, 0x3f, 0xc7, 0x90, 0x55, 0xc3, 0x97, 0xc5, - 0xb6, 0xc5, 0xa3, 0xc7, 0x98, 0xc7, 0xba, 0xc7, 0xa7, 0xc8, 0x89, 0xc3, 0x80, 0xe2, - 0xb1, 0xb8, 0xc7, 0x8c, 0xc6, 0xa2, 0xc5, 0xb2, 0xc6, 0x90, 0xc4, 0x8f, 0xc4, 0x84, - 0xc7, 0xa3, 0xc2, 0xbd, 0x48, 0xc3, 0x97, 0xc7, 0x8b, 0xc7, 0x85, 0xc5, 0x83, 0xc7, - 0xb9, 0xe1, 0x9b, 0x96, 0xc8, 0x90, 0xc3, 0xbd, 0xe1, 0x9b, 0x99, 0xc8, 0x9b, 0xcd, - 0xb5, 0x28, 0xe1, 0x9b, 0xaa, 0xc5, 0x9a, 0xc6, 0xb7, 0x39, 0x75, 0x25, 0xc7, 0xb8, - 0xc5, 0xaa, 0xc8, 0xa5, 0xc5, 0xb3, 0xc7, 0x96, 0xc3, 0x8c, 0xc5, 0x87, 0x72, 0xe1, - 0x9a, 0xab, 0x72, 0xc9, 0x8b, 0xc3, 0xb0, 0xc8, 0x96, 0xc3, 0xb2, 0xc3, 0x82, 0x52, - 0x78, 0x68, 0x4d, 0xc5, 0x9e, 0xc5, 0x80, 0xe1, 0x9b, 0x84, 0xe2, 0xb1, 0xa6, 0xc6, - 0x8d, 0x51, 0xc8, 0xbe, 0xe1, 0x9b, 0x8d, 0xc2, 0xbc, 0xc6, 0xa8, 0xc7, 0x93, 0xc8, - 0x90, 0xc5, 0x99, 0x28, 0x6e, 0xc8, 0x95, 0x78, 0xe1, 0x9b, 0x83, 0xc4, 0xbe, 0xc8, - 0xb5, 0xc5, 0x80, 0x67, 0xc3, 0x9b, 0xe1, 0x9b, 0x89, 0xc5, 0x8c, 0x75, 0xc4, 0xb7, - 0xe1, 0x9b, 0x87, 0x47, 0xc3, 0xa9, 0xc5, 0x95, 0xc4, 0x93, 0xc3, 0x9d, 0xe1, 0x9b, - 0x82, 0xc7, 0x95, 0xc5, 0x84, 0xc5, 0x91, 0xe1, 0x9a, 0xa2, 0xc3, 0x95, 0xcd, 0xb6, - 0xe2, 0xb1, 0xbd, 0xc5, 0x91, 0xc4, 0xbb, 0xc7, 0x8a, 0xc7, 0xaa, 0xc8, 0xb3, 0xe1, - 0x9b, 0xa6, 0x5d, 0xcd, 0xb2, 0xc5, 0xab, 0xc4, 0xa0, 0x5b, 0xc2, 0xbe, 0x37, 0x60, - 0xc5, 0x8a, 0xe1, 0x9a, 0xbb, 0xc9, 0x82, 0xc5, 0xbd, 0xe1, 0x9b, 0xa0, 0xc3, 0x80, - 0xc7, 0xb0, 0xc7, 0xa7, 0xe1, 0x9b, 0xaf, 0x70, 0xc5, 0x98, 0xc4, 0x80, 0x5b, 0xc2, - 0xb1, 0xe2, 0xb1, 0xab, 0xc3, 0x8b, 0xc4, 0xa3, 0x2f, 0xc6, 0x9a, 0xc5, 0x84, 0x63, - 0xc3, 0xaf, 0xc3, 0x87, 0xe1, 0x9b, 0xa0, 0xc3, 0x82, 0x73, 0xc4, 0x98, 0xe1, 0x9b, - 0x91, 0xe1, 0x9a, 0xac, 0x76, 0xc9, 0x87, 0xc7, 0xa8, 0xc4, 0x90, 0xc2, 0xb1, 0x2e, - 0x4b, 0xc8, 0x8b, 0x58, 0xc8, 0xb1, 0xe1, 0x9a, 0xbf, 0xc8, 0xa2, 0xc6, 0x9f, 0xc4, - 0xab, 0xc4, 0xbf, 0xe1, 0x9b, 0x86, 0xe1, 0x9b, 0xa8, 0xce, 0x8c, 0xc5, 0xab, 0xc3, - 0x85, 0x75, 0xc3, 0xa7, 0xc7, 0xbc, 0xc7, 0xa5, 0xe2, 0xb1, 0xba, 0xc5, 0xad, 0x6b, - 0xc8, 0xbc, 0xc6, 0xb0, 0xc5, 0xa0, 0xc4, 0x8f, 0xc7, 0xbd, 0xe1, 0x9a, 0xa2, 0xc5, - 0x90, 0xc6, 0xa2, 0xc9, 0x84, 0xc6, 0xab, 0xc7, 0xb2, 0x7c, 0xc5, 0x86, 0x40, 0x3b, - 0xc3, 0x8f, 0xe1, 0x9a, 0xb4, 0xe2, 0xb1, 0xae, 0xc2, 0xb0, 0xc5, 0x90, 0xe2, 0xb1, - 0xad, 0xc3, 0x85, 0xcd, 0xba, 0xc3, 0x9d, 0xe1, 0x9b, 0xab, 0xe1, 0x9a, 0xbd, 0xc6, - 0xb8, 0xc6, 0xab, 0xc3, 0xb0, 0xc9, 0x87, 0xc5, 0xb0, 0xc2, 0xaa, 0xc8, 0x99, 0xc6, - 0x80, 0xc9, 0x84, 0xc4, 0xb6, 0xe1, 0x9b, 0x82, 0xc6, 0xa9, 0xc5, 0xac, 0x76, 0xce, - 0x85, 0xc6, 0xa9, 0xe1, 0x9b, 0xa5, 0xc3, 0xac, 0xc4, 0xa0, 0xe1, 0x9a, 0xa7, 0xc2, - 0xae, 0xc3, 0xb2, 0xc3, 0x83, 0xc6, 0xaa, 0xc5, 0x88, 0xe1, 0x9a, 0xab, 0xc4, 0x81, - 0xc4, 0x98, 0xc4, 0xa3, 0x62, 0x7d, 0xc6, 0x84, 0xc8, 0x85, 0xc5, 0x96, 0xc4, 0xad, - 0xe2, 0xb1, 0xbd, 0x34, 0xc6, 0x9c, 0x5a, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x19, 0x8f, 0x36, 0xf8, 0x2b, 0xca, 0x02, 0x8c, 0x9f, 0x8d, 0x8d, 0x20, 0x9f, 0x4c, - 0x4a, 0xf6, 0xd1, 0x44, 0x90, 0x5e, 0xbb, 0x17, 0xda, 0xf4, 0x15, 0xd3, 0x1d, 0x4a, - 0xf3, 0x7c, 0x46, 0x2e, + 0xb0, 0x42, 0x08, 0x91, 0xec, 0xa6, 0x2d, 0x05, 0xd6, 0x89, 0x51, 0x5a, 0x33, 0x90, + 0xec, 0x57, 0xd8, 0xf7, 0xe9, 0x53, 0xea, 0x89, 0xcc, 0x01, 0xdd, 0xd3, 0xc1, 0x94, + 0x39, 0xe5, 0x18, 0x21, ], }, TestVector { key: [ - 0x28, 0x37, 0xcd, 0x45, 0x6e, 0x33, 0x19, 0x9f, 0x05, 0xb5, 0xd9, 0x0a, 0x42, 0xa7, - 0xb3, 0xd7, 0x13, 0xac, 0xd4, 0xec, 0xe6, 0xfe, 0x32, 0xdf, 0x77, 0xcb, 0x17, 0x00, - 0x43, 0xa2, 0xfa, 0xc6, + 0xbb, 0xf4, 0x49, 0x82, 0xf1, 0xba, 0x3a, 0x2b, 0x9d, 0xd3, 0xc1, 0x77, 0x4d, 0x71, + 0xce, 0x33, 0x60, 0x59, 0x9b, 0x07, 0xf2, 0x11, 0xc8, 0x16, 0xb8, 0xc4, 0x3b, 0x98, + 0x42, 0x23, 0x09, 0x24, ], description: [ - 0xc2, 0xb0, 0x5d, 0x32, 0xc3, 0x9a, 0xc3, 0x98, 0xc4, 0x88, 0xc5, 0x8f, 0xc4, 0xa4, - 0xc3, 0x81, 0xc7, 0x91, 0xe1, 0x9b, 0x9e, 0xc8, 0x9e, 0xc4, 0x86, 0xe1, 0x9b, 0xa6, - 0xc8, 0x89, 0xc8, 0x84, 0xce, 0x8c, 0xc9, 0x83, 0xe2, 0xb1, 0xac, 0xcd, 0xb2, 0xc3, - 0xb8, 0xc8, 0x81, 0x65, 0xc3, 0x82, 0xc3, 0x93, 0xc4, 0x81, 0x7e, 0xe1, 0x9a, 0xb0, - 0xc5, 0x82, 0xc9, 0x8f, 0xc4, 0xb9, 0xc3, 0xbe, 0xc8, 0x8d, 0xc7, 0xab, 0xce, 0x8c, - 0xe1, 0x9a, 0xb5, 0xc7, 0x8d, 0xc7, 0x87, 0xc7, 0xba, 0xc6, 0xa2, 0xc4, 0xa3, 0xc7, - 0x93, 0xc8, 0xa8, 0xc3, 0x90, 0xc2, 0xaa, 0x5f, 0xc7, 0xbb, 0xc3, 0xad, 0xe1, 0x9a, - 0xa1, 0xc8, 0xa7, 0xc3, 0xaa, 0x7e, 0xc3, 0xaa, 0xe2, 0xb1, 0xa0, 0xcd, 0xb1, 0xc4, - 0xa9, 0xc5, 0x98, 0x75, 0xc8, 0xa3, 0x5b, 0x2c, 0x44, 0xe2, 0xb1, 0xb4, 0xc6, 0x92, - 0xc3, 0x95, 0xc5, 0x8e, 0xc8, 0xa6, 0xc8, 0xb8, 0xc9, 0x82, 0xc7, 0x87, 0xc5, 0xa7, - 0xc8, 0x9f, 0x50, 0xc5, 0x9b, 0xc4, 0x9e, 0x56, 0x7c, 0xc5, 0xba, 0xc3, 0x85, 0xe1, - 0x9b, 0x8d, 0xe1, 0x9a, 0xbf, 0xc7, 0xaf, 0xc4, 0x89, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, - 0x95, 0xc8, 0xa8, 0xc6, 0xad, 0xe1, 0x9b, 0x80, 0xc7, 0x8d, 0x31, 0xc5, 0x83, 0xcd, - 0xb7, 0xc4, 0x9f, 0xc3, 0xa8, 0xc6, 0xa0, 0xe1, 0x9a, 0xa9, 0xc6, 0x8a, 0xc4, 0x9f, - 0x57, 0xc8, 0xaf, 0xc7, 0xa7, 0xe1, 0x9b, 0x9f, 0xc6, 0x88, 0xc8, 0xa4, 0xe2, 0xb1, - 0xbd, 0x3d, 0xc4, 0x83, 0xe1, 0x9b, 0xa1, 0x59, 0xe1, 0x9b, 0x94, 0x7c, 0x2b, 0xe1, - 0x9b, 0x86, 0xe1, 0x9a, 0xbb, 0xc7, 0xb7, 0xc9, 0x86, 0xc7, 0x9e, 0xc5, 0x82, 0xe2, - 0xb1, 0xb7, 0xc3, 0x98, 0xc5, 0xb9, 0xc3, 0xbe, 0xe1, 0x9b, 0x93, 0xc9, 0x87, 0xc7, - 0x92, 0xc9, 0x83, 0xc8, 0x8e, 0x30, 0xe1, 0x9b, 0x98, 0xc5, 0xba, 0xc6, 0x8a, 0x39, - 0x59, 0xc5, 0x96, 0xc4, 0x9f, 0xc7, 0x82, 0xe1, 0x9a, 0xb4, 0xc9, 0x8b, 0xc5, 0xbc, - 0xc3, 0xa6, 0xc8, 0x95, 0xc6, 0xa1, 0xc4, 0xba, 0xc6, 0xb0, 0xc5, 0xba, 0x7b, 0xc4, - 0x85, 0xc5, 0xb7, 0xc4, 0x85, 0xc7, 0x93, 0xc3, 0x8d, 0xc5, 0x85, 0xc7, 0xad, 0xc5, - 0x9e, 0xc4, 0xbc, 0xc2, 0xa4, 0xe1, 0x9b, 0x87, 0xc2, 0xab, 0xc8, 0xb1, 0xc6, 0x87, - 0x77, 0xc6, 0xb8, 0xc5, 0x85, 0xc4, 0x8c, 0xc7, 0xa3, 0xc3, 0x85, 0xc2, 0xb8, 0x42, - 0xc7, 0xa7, 0xce, 0x88, 0xe1, 0x9a, 0xaa, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0x9d, 0xe1, - 0x9b, 0xa6, 0xc6, 0xa4, 0xc7, 0x87, 0xc6, 0x81, 0xc4, 0x84, 0xc4, 0xae, 0xc9, 0x86, - 0xe2, 0xb1, 0xa8, 0xc2, 0xbc, 0xc4, 0x93, 0xe1, 0x9b, 0x88, 0xc7, 0x81, 0xc2, 0xa3, - 0xc4, 0xbf, 0xc7, 0x9d, 0xe1, 0x9b, 0x93, 0xe1, 0x9b, 0xa1, 0xe1, 0x9a, 0xb1, 0xc8, - 0xb3, 0xc2, 0xb9, 0xe1, 0x9b, 0x9c, 0x37, 0x64, 0xc3, 0xbf, 0xe2, 0xb1, 0xb0, 0x42, - 0xc8, 0xae, 0x7e, 0xc7, 0x92, 0xc4, 0xbd, 0xc6, 0x98, 0xc3, 0xab, 0xc3, 0x9d, 0xc4, - 0xa4, 0xc5, 0x99, 0xc5, 0x84, 0xc3, 0xba, 0xc7, 0xa0, 0xc6, 0x92, 0xc8, 0xad, 0xc5, - 0xb8, 0xc4, 0xb6, 0xc7, 0x90, 0xc6, 0xa3, 0xc3, 0xab, 0xc3, 0x95, 0xc4, 0x91, 0xce, - 0x84, 0x30, 0xc4, 0xb5, 0xc7, 0x9a, 0xc6, 0x92, 0xc2, 0xba, 0xc3, 0x9e, 0xc7, 0x99, - 0xc4, 0x8d, 0xc3, 0x85, 0xc6, 0x87, 0xc7, 0x86, 0xc6, 0x82, 0xc6, 0x8a, 0x26, 0xc4, - 0x8b, 0xc4, 0xbe, 0x7c, 0x58, 0xc8, 0xa6, 0xc4, 0xab, 0xc4, 0xbe, 0xce, 0x8a, 0xc4, - 0xb7, 0xc3, 0xb9, 0xc5, 0x94, 0xe1, 0x9b, 0x9a, 0xc8, 0xbf, 0xc7, 0xa6, 0xc5, 0xbd, - 0xc4, 0xa8, 0xc5, 0x8f, 0xc5, 0xa3, 0xcd, 0xb4, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x9a, 0xcc, 0xb2, 0xc5, 0xad, 0xae, 0x30, 0xab, 0xdb, 0x76, 0x58, 0x9d, 0xec, 0xdd, - 0x71, 0xe4, 0x65, 0x75, 0x53, 0x8d, 0x80, 0x3c, 0x28, 0xd7, 0xe4, 0xb8, 0x89, 0x6a, - 0xd7, 0xfd, 0xc6, 0x87, + 0xd7, 0x65, 0x7f, 0x6b, 0xf8, 0xc7, 0x11, 0x02, 0x3d, 0xbb, 0x0e, 0x3c, 0x6b, 0x7d, + 0x19, 0xae, 0xc5, 0x22, 0x4b, 0x5b, 0xc8, 0x33, 0x73, 0xe6, 0x89, 0x31, 0xbb, 0x3c, + 0x77, 0x8d, 0x19, 0x07, ], }, TestVector { key: [ - 0x0a, 0xbb, 0x5f, 0xa5, 0xab, 0x94, 0x0d, 0x29, 0x57, 0x4b, 0x95, 0x15, 0x9c, 0x40, - 0xbd, 0x79, 0x43, 0x44, 0xea, 0x07, 0xa8, 0x7e, 0x0f, 0x0f, 0x5f, 0xac, 0xa5, 0xb4, - 0x31, 0x81, 0x6d, 0xe2, + 0xb5, 0x9c, 0x5f, 0x32, 0x34, 0xd6, 0xca, 0x36, 0xcc, 0x48, 0x3d, 0x67, 0xa8, 0x4f, + 0x37, 0xd6, 0xb2, 0x4b, 0x24, 0x45, 0x48, 0x25, 0xd2, 0xb7, 0xbf, 0xdc, 0x80, 0x2b, + 0x2e, 0x32, 0x8c, 0x43, ], description: [ - 0xcd, 0xbd, 0xe1, 0x9a, 0xb4, 0xc8, 0x9c, 0xc8, 0x96, 0xc6, 0xaa, 0xce, 0x88, 0xe1, - 0x9a, 0xb4, 0x2d, 0xc6, 0x81, 0xc7, 0x86, 0xc7, 0x9d, 0xc5, 0x86, 0xc4, 0x84, 0xe1, - 0x9b, 0x9e, 0xc6, 0x91, 0xe1, 0x9b, 0x89, 0x2d, 0xc4, 0x81, 0xc6, 0x88, 0x4c, 0xc2, - 0xbf, 0xc2, 0xaa, 0xc3, 0xb4, 0xc8, 0xae, 0xc7, 0x91, 0xc2, 0xb0, 0xc5, 0xa5, 0xc6, - 0xa3, 0xc4, 0x94, 0x38, 0xe1, 0x9a, 0xa9, 0xc4, 0xbe, 0xc3, 0x81, 0xe2, 0xb1, 0xba, - 0xc5, 0xa7, 0x44, 0xc3, 0xbb, 0xc8, 0x97, 0x5b, 0xc6, 0xbd, 0xc5, 0x9b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9a, 0xbd, 0xc2, 0xbf, 0xc3, 0x94, 0xc2, 0xb0, 0xc4, 0x9c, 0xc6, 0xa1, - 0xc3, 0xb6, 0xc2, 0xac, 0xe1, 0x9a, 0xa9, 0xc6, 0x90, 0x5c, 0xe2, 0xb1, 0xb2, 0x7c, - 0xc3, 0x86, 0x57, 0xe1, 0x9a, 0xa4, 0x71, 0xc7, 0x91, 0xe2, 0xb1, 0xbc, 0xc7, 0xab, - 0xc4, 0x86, 0xc5, 0xa1, 0xc5, 0x92, 0xc6, 0xa9, 0x78, 0x7a, 0xcd, 0xbd, 0xc4, 0xb2, - 0x75, 0xc8, 0xa4, 0x29, 0xc6, 0x9e, 0xc7, 0xa0, 0xc7, 0xa8, 0xc3, 0xa5, 0xc4, 0xb6, - 0xe1, 0x9b, 0x9d, 0x45, 0xc3, 0xa1, 0xc9, 0x8b, 0xc3, 0xbb, 0xc8, 0x86, 0xc7, 0x83, - 0xe1, 0x9b, 0x93, 0xc8, 0x9c, 0xc5, 0xba, 0xc7, 0xa8, 0xc7, 0x8d, 0xe1, 0x9a, 0xbf, - 0xcd, 0xb7, 0xc5, 0x91, 0xc4, 0x8f, 0x65, 0xc3, 0xa4, 0xc2, 0xb4, 0xe2, 0xb1, 0xb0, - 0xc8, 0xa9, 0xc8, 0xb1, 0xe1, 0x9b, 0x86, 0xc8, 0x85, 0xc4, 0x8d, 0xe1, 0x9a, 0xaf, - 0xe1, 0x9b, 0x81, 0xc3, 0xae, 0xc4, 0x90, 0xc8, 0xbb, 0x2a, 0xe1, 0x9a, 0xae, 0xc6, - 0xa3, 0xc4, 0xae, 0xc4, 0x93, 0x7b, 0xc7, 0x8e, 0xc8, 0x9c, 0xc3, 0xa3, 0xc5, 0xac, - 0xcd, 0xb7, 0x41, 0xc5, 0xb5, 0xc4, 0x95, 0xc3, 0x92, 0xc6, 0xaa, 0xe1, 0x9b, 0x83, - 0xe2, 0xb1, 0xb2, 0xe1, 0x9a, 0xbc, 0xc7, 0x87, 0xc7, 0xb7, 0xc5, 0x97, 0xc2, 0xb9, - 0x55, 0xe1, 0x9b, 0x91, 0x45, 0xc8, 0x8b, 0xe1, 0x9a, 0xa9, 0xe1, 0x9a, 0xad, 0xc6, - 0xab, 0xcd, 0xbd, 0xc8, 0xa2, 0xc3, 0x8c, 0x23, 0xe2, 0xb1, 0xa9, 0xe1, 0x9b, 0x8c, - 0xe1, 0x9a, 0xb7, 0xc6, 0x84, 0xc3, 0xa6, 0xc8, 0xb2, 0xc5, 0xbe, 0xc7, 0xbe, 0xe1, - 0x9a, 0xaa, 0xc3, 0xb1, 0xc6, 0xb3, 0xe1, 0x9a, 0xbe, 0xc4, 0xa0, 0xc2, 0xb9, 0x37, - 0xc5, 0x82, 0xc5, 0xbf, 0xc8, 0xa9, 0x44, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x9c, 0xe1, - 0x9b, 0xa6, 0xe1, 0x9b, 0x87, 0xe2, 0xb1, 0xaa, 0xc7, 0xab, 0xc7, 0xaf, 0xc7, 0x91, - 0xe2, 0xb1, 0xbf, 0xe1, 0x9a, 0xb9, 0xe1, 0x9b, 0x87, 0xc6, 0xb6, 0xc5, 0xa3, 0xc7, - 0x98, 0xc5, 0x90, 0xc8, 0x9b, 0xcd, 0xb2, 0xc4, 0x97, 0x7b, 0xe1, 0x9b, 0x96, 0xc3, - 0xa2, 0x6e, 0xc8, 0x90, 0x6f, 0xc6, 0x9e, 0xc9, 0x87, 0x6e, 0xc8, 0x82, 0xc4, 0x97, - 0xc3, 0xb0, 0xc4, 0x8d, 0xe2, 0xb1, 0xb6, 0xc7, 0x9b, 0xc3, 0x9a, 0xc8, 0xb5, 0xc6, - 0x95, 0xc3, 0xb6, 0x44, 0xc3, 0xac, 0xc5, 0x90, 0xe1, 0x9b, 0xa0, 0xc8, 0x92, 0x5d, - 0xc5, 0xad, 0xe1, 0x9b, 0xab, 0x7b, 0xc4, 0x97, 0xc7, 0xac, 0xe1, 0x9a, 0xb2, 0x2e, - 0xc3, 0xa8, 0xc6, 0xbc, 0x40, 0x23, 0xc6, 0xbf, 0x55, 0xc6, 0x82, 0xc7, 0x8a, 0x65, - 0xe1, 0x9b, 0x9b, 0xc3, 0xbc, 0xe2, 0xb1, 0xbd, 0x4b, 0xe2, 0xb1, 0xa7, 0xc6, 0x8d, - 0xc7, 0xae, 0xc3, 0x83, 0xc7, 0xb9, 0x64, 0xc6, 0xa6, 0xc8, 0x82, 0xc8, 0x9d, 0xc8, - 0x9f, 0xc8, 0xb2, 0xc6, 0x8c, 0xe2, 0xb1, 0xb8, 0xe1, 0x9b, 0xab, 0xc7, 0x9d, 0xc8, - 0xb5, 0xc5, 0xab, 0xcd, 0xba, 0x45, 0xe1, 0x9a, 0xab, 0xc3, 0x93, 0x37, 0xc2, 0xb8, - 0xc9, 0x8d, 0xc9, 0x88, 0xe1, 0x9b, 0x93, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x1a, 0x28, 0x12, 0x59, 0x8b, 0xa7, 0x5c, 0x9a, 0x69, 0x2e, 0x69, 0x19, 0x65, 0x7f, - 0x68, 0x3e, 0xa4, 0x52, 0xe1, 0xae, 0x66, 0x33, 0xba, 0xcf, 0xe1, 0xf4, 0x54, 0x55, - 0x04, 0xc2, 0x95, 0xb4, + 0x75, 0xb8, 0x7f, 0x88, 0x85, 0xb9, 0x7f, 0x00, 0x70, 0x93, 0x89, 0xeb, 0x57, 0x0a, + 0x59, 0x47, 0xd4, 0xca, 0x36, 0x19, 0x98, 0x10, 0xbd, 0x94, 0x37, 0xba, 0x7c, 0x4a, + 0x2b, 0x24, 0xcd, 0xab, ], }, TestVector { key: [ - 0x07, 0x82, 0x6a, 0x86, 0xb1, 0x72, 0xc5, 0x5a, 0x66, 0x40, 0x1e, 0x37, 0xfc, 0x69, - 0xf9, 0x2e, 0x6d, 0x62, 0xa0, 0x14, 0x6c, 0x67, 0x06, 0x29, 0xa2, 0xd6, 0x51, 0x34, - 0xdf, 0x3b, 0x22, 0xf6, + 0xff, 0x63, 0xc7, 0x89, 0x25, 0x1c, 0x10, 0x43, 0xc6, 0xf9, 0x6c, 0x66, 0xbf, 0x5b, + 0x0f, 0x61, 0xc9, 0xd6, 0x5f, 0xef, 0x5a, 0xaf, 0x42, 0x84, 0xa6, 0xa5, 0x69, 0x94, + 0x94, 0x1c, 0x05, 0xfa, ], description: [ - 0xc6, 0xbe, 0xc3, 0x90, 0xc3, 0x92, 0xc4, 0x97, 0x7e, 0xc6, 0x81, 0x34, 0xe1, 0x9b, - 0x86, 0xc8, 0x8e, 0x7e, 0xcd, 0xb4, 0xc6, 0x90, 0x7b, 0xc4, 0xae, 0xc7, 0x8a, 0xcd, - 0xbd, 0xc5, 0x98, 0xc5, 0xa2, 0xc2, 0xb7, 0x6a, 0xc5, 0x82, 0xc5, 0xac, 0xc2, 0xbf, - 0xc7, 0x83, 0x33, 0xe1, 0x9b, 0x87, 0xc5, 0xb8, 0xc8, 0xb7, 0xc5, 0xaa, 0xc5, 0xb1, - 0xc8, 0xbd, 0x47, 0x58, 0xc5, 0x90, 0xc6, 0x91, 0xc5, 0x89, 0x24, 0xc4, 0xbf, 0xc4, - 0x80, 0xc3, 0xa7, 0xc8, 0xaa, 0x69, 0x6e, 0xe1, 0x9b, 0xa0, 0xc2, 0xa1, 0x42, 0xc6, - 0x96, 0xc3, 0x9b, 0x76, 0x24, 0xcd, 0xbb, 0xc6, 0xaf, 0x52, 0x24, 0xc4, 0xa0, 0xe1, - 0x9b, 0x82, 0xc5, 0x82, 0xe1, 0x9b, 0x90, 0xc8, 0x92, 0xc5, 0xb1, 0xe2, 0xb1, 0xbd, - 0xc2, 0xb7, 0xc4, 0xa6, 0xce, 0x88, 0xe1, 0x9b, 0x91, 0x3e, 0x3b, 0xc8, 0x88, 0xc6, - 0xae, 0xe2, 0xb1, 0xa4, 0xc3, 0xa1, 0xc4, 0x84, 0xe1, 0x9a, 0xbd, 0xc3, 0x9c, 0xc8, - 0xa4, 0xe1, 0x9a, 0xba, 0xc7, 0xb1, 0xc2, 0xac, 0x6f, 0xc4, 0x87, 0xc8, 0xb9, 0xe1, - 0x9a, 0xae, 0xc2, 0xab, 0xc3, 0xad, 0xc3, 0xae, 0xc5, 0x8b, 0xc8, 0x9f, 0xce, 0x8c, - 0x4f, 0xc7, 0xbe, 0xc7, 0x8a, 0xc5, 0xbe, 0xc7, 0x92, 0xe1, 0x9b, 0x9d, 0xc5, 0x95, - 0xe1, 0x9a, 0xab, 0x57, 0xe1, 0x9a, 0xb0, 0xc4, 0x9e, 0x55, 0xc6, 0x96, 0xc4, 0xb2, - 0x29, 0xc9, 0x81, 0xc4, 0xa6, 0xc7, 0xa3, 0xc4, 0x91, 0xc6, 0x96, 0xc7, 0x80, 0xc7, - 0xb6, 0xe1, 0x9b, 0x8c, 0xc3, 0x9f, 0xc5, 0x92, 0xc8, 0x90, 0x72, 0xc6, 0x99, 0xe1, - 0x9a, 0xa3, 0x7e, 0xc3, 0xa6, 0x58, 0xc8, 0xb6, 0x6c, 0xc8, 0xb0, 0xc3, 0xbb, 0xe1, - 0x9a, 0xa4, 0xc2, 0xa5, 0xc3, 0x94, 0xcd, 0xb4, 0xc3, 0xb7, 0xc6, 0xa7, 0xc2, 0xaf, - 0xc4, 0xae, 0xc3, 0xa5, 0xe2, 0xb1, 0xb7, 0xe1, 0x9b, 0x86, 0x5d, 0xc5, 0x80, 0x3f, - 0xc6, 0x92, 0xc8, 0x8e, 0xc6, 0xb4, 0xc7, 0xac, 0xc6, 0xb4, 0xc3, 0xab, 0xc9, 0x8b, - 0xc4, 0x90, 0xe2, 0xb1, 0xa7, 0xc4, 0x96, 0xc4, 0x9a, 0xc8, 0xbd, 0xce, 0x87, 0xc6, - 0xaf, 0xc7, 0x83, 0x3c, 0xe1, 0x9b, 0xa2, 0xc2, 0xb4, 0xc4, 0x9d, 0x4d, 0xc3, 0x8a, - 0xc3, 0xa8, 0xc6, 0x93, 0x28, 0xc7, 0xbc, 0xc6, 0x9f, 0xe1, 0x9a, 0xa4, 0xc7, 0x8a, - 0xc7, 0xbd, 0xc3, 0x87, 0xe2, 0xb1, 0xb7, 0xc6, 0xac, 0xe1, 0x9b, 0x92, 0xc4, 0xa6, - 0xc5, 0x84, 0x3a, 0xc9, 0x8c, 0xc9, 0x8a, 0xc2, 0xa2, 0xc4, 0xae, 0xe1, 0x9a, 0xa8, - 0xc8, 0xa6, 0xc2, 0xbb, 0xe2, 0xb1, 0xa0, 0xc8, 0xab, 0xc7, 0x8a, 0xc7, 0x8a, 0xe1, - 0x9b, 0x97, 0xc4, 0x89, 0xc8, 0x9a, 0xe1, 0x9b, 0x91, 0xe1, 0x9b, 0x8b, 0x5c, 0xe1, - 0x9b, 0xa6, 0xc8, 0xa9, 0xc9, 0x80, 0x71, 0xc5, 0x95, 0xc8, 0xbd, 0xc5, 0x8f, 0xc5, - 0xa4, 0xc3, 0xb7, 0xc6, 0x85, 0xe1, 0x9a, 0xa9, 0xc6, 0xa2, 0xc8, 0xaa, 0xc7, 0x8c, - 0xc6, 0x9a, 0xc7, 0x81, 0xc3, 0xa0, 0xc4, 0xab, 0xc8, 0xa2, 0xc5, 0x9b, 0xc5, 0xbb, - 0xc7, 0x8e, 0xc6, 0x95, 0xc8, 0x9c, 0x6c, 0xc8, 0xbc, 0xe2, 0xb1, 0xaa, 0xc5, 0x85, - 0xc6, 0x83, 0xc4, 0xa1, 0xc4, 0x81, 0x4d, 0xe1, 0x9a, 0xa3, 0x5d, 0xc3, 0xb7, 0xc5, - 0xa4, 0xc6, 0xae, 0xe1, 0x9a, 0xad, 0xc4, 0xa4, 0xc3, 0xb8, 0xc3, 0xa7, 0x44, 0xc6, - 0xaa, 0xc7, 0xa5, 0xc4, 0xa4, 0xc5, 0xba, 0xc9, 0x85, 0xc3, 0xa6, 0xc3, 0x9d, 0xc4, - 0xa3, 0xc5, 0x97, 0xe1, 0x9a, 0xa1, 0x2d, 0x77, 0xc2, 0xa2, 0x3e, 0xc8, 0x8d, 0xc5, - 0xb1, 0xe1, 0x9a, 0xa9, 0xc6, 0xa2, 0xc5, 0xbf, 0xc7, 0xa4, 0xe1, 0x9a, 0xa9, 0xc6, - 0x82, 0xc3, 0xbb, 0xc3, 0xb9, 0xc6, 0x8a, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x9f, 0x0a, 0x47, 0x16, 0x90, 0xe2, 0x1a, 0x74, 0x79, 0x7a, 0x71, 0x12, 0x36, 0xfa, - 0x58, 0x85, 0x5e, 0x6e, 0xd1, 0xaa, 0xd5, 0x4c, 0x6c, 0xaf, 0xa8, 0xa3, 0x7f, 0xdb, - 0xd1, 0x9e, 0x75, 0x00, + 0xda, 0x94, 0x71, 0x63, 0xc0, 0x67, 0x83, 0x60, 0xfc, 0x58, 0xb4, 0x33, 0xa8, 0x97, + 0x66, 0x8e, 0x58, 0x2e, 0xce, 0x67, 0x8f, 0x31, 0xac, 0xb4, 0xb4, 0xad, 0x85, 0xbc, + 0xd5, 0xf7, 0xc1, 0xae, ], }, TestVector { key: [ - 0xe5, 0x21, 0x62, 0x0d, 0x68, 0x53, 0x7c, 0xa3, 0x0b, 0xf3, 0x2f, 0x4e, 0xd2, 0xc3, - 0x3c, 0x0c, 0xf8, 0x25, 0x2a, 0x79, 0xa8, 0xa7, 0x39, 0x7b, 0xf1, 0x1b, 0x67, 0x87, - 0x30, 0x52, 0x44, 0xee, + 0x45, 0x61, 0x9f, 0x20, 0x6c, 0x3b, 0xfc, 0x84, 0xfd, 0x42, 0x4f, 0xfb, 0x5c, 0x81, + 0x6f, 0x65, 0x4b, 0x27, 0xaa, 0x7f, 0x7b, 0x4b, 0xd6, 0x7e, 0xc5, 0xf9, 0xac, 0x6d, + 0x0f, 0x38, 0xdb, 0xb1, ], description: [ - 0xcd, 0xb4, 0xc6, 0x92, 0xc4, 0xa7, 0xc3, 0xb9, 0xc6, 0xb8, 0xcd, 0xba, 0xc4, 0xa4, - 0xc8, 0x9a, 0xc8, 0xb7, 0xe1, 0x9b, 0x92, 0xc5, 0xb2, 0xc7, 0xba, 0xc6, 0x86, 0xc8, - 0x87, 0xc5, 0x88, 0xc5, 0x87, 0xc7, 0xa0, 0xc8, 0x97, 0xc6, 0xad, 0x4e, 0xc4, 0xa4, - 0xc5, 0x9c, 0xc8, 0x89, 0xc5, 0xba, 0xc3, 0xa1, 0xc8, 0xa2, 0xc3, 0x9c, 0xc8, 0x88, - 0xe1, 0x9a, 0xa1, 0xc8, 0x9d, 0xc7, 0x8b, 0xc6, 0xb5, 0xc3, 0x87, 0xc3, 0x93, 0xc4, - 0xa3, 0xe2, 0xb1, 0xa2, 0x7b, 0xc9, 0x85, 0xc3, 0xb9, 0x3a, 0xc6, 0x86, 0xc3, 0x99, - 0xc7, 0xa2, 0xc7, 0x83, 0xce, 0x8a, 0xc7, 0xbd, 0xe1, 0x9b, 0xa7, 0xc8, 0xa9, 0xe2, - 0xb1, 0xb1, 0xc6, 0x9d, 0xc5, 0xbb, 0xc7, 0x98, 0xc6, 0x8a, 0xc6, 0x8d, 0xc5, 0xa2, - 0xc9, 0x89, 0xc3, 0xa3, 0x57, 0xc8, 0xa8, 0x66, 0xc7, 0x95, 0xc6, 0x86, 0xc4, 0xa2, - 0x79, 0xc8, 0x98, 0xc7, 0xa8, 0xc7, 0x86, 0xc6, 0xb4, 0xcd, 0xb6, 0xe1, 0x9a, 0xb2, - 0xc3, 0x9e, 0xc2, 0xb1, 0xc7, 0xbb, 0xc6, 0xa2, 0xc7, 0xb2, 0xc5, 0xa6, 0x48, 0xc2, - 0xbf, 0xc3, 0xac, 0x53, 0xc4, 0x80, 0xc2, 0xba, 0xc2, 0xbc, 0xc7, 0xad, 0xc7, 0xa7, - 0xc6, 0xb3, 0xe1, 0x9a, 0xad, 0xc8, 0x90, 0xe2, 0xb1, 0xaa, 0x31, 0xc5, 0xb9, 0xc5, - 0xbe, 0xe1, 0x9a, 0xb9, 0xc2, 0xb7, 0xc6, 0x91, 0xc3, 0xad, 0x7c, 0xc3, 0xa6, 0xc3, - 0x95, 0xc5, 0x8c, 0xc3, 0xb9, 0xc6, 0xa7, 0xc4, 0x9e, 0x7d, 0xce, 0x8c, 0x2e, 0xc7, - 0x97, 0xc6, 0x9b, 0x26, 0xc6, 0xa8, 0x7c, 0xc7, 0xa2, 0x4d, 0xc8, 0x9d, 0xc5, 0x8c, - 0xe2, 0xb1, 0xa5, 0xc7, 0xae, 0xc4, 0xbe, 0xe1, 0x9b, 0xa6, 0xc2, 0xae, 0xe2, 0xb1, - 0xaf, 0xc5, 0xb9, 0xc7, 0x87, 0x66, 0x5c, 0x53, 0xe2, 0xb1, 0xb1, 0xc8, 0xbf, 0xc5, - 0x8a, 0xc3, 0xa8, 0x21, 0xc3, 0x8c, 0xc4, 0x99, 0xc3, 0xba, 0xcd, 0xbe, 0xc8, 0xa6, - 0xc3, 0xbe, 0xc8, 0x90, 0xc4, 0x9d, 0xc4, 0x94, 0xc3, 0xbf, 0xc3, 0x9a, 0xe1, 0x9b, - 0x83, 0xc4, 0xb9, 0xc2, 0xa6, 0xc8, 0x8d, 0xc6, 0x82, 0xe1, 0x9a, 0xb0, 0xc6, 0x9b, - 0x31, 0xe1, 0x9b, 0x97, 0xc6, 0x91, 0xc3, 0x83, 0xc6, 0x9c, 0x4d, 0xc3, 0xb7, 0xc7, - 0x99, 0xe1, 0x9a, 0xac, 0xc2, 0xa3, 0xc6, 0xad, 0xc4, 0xb4, 0xc3, 0xa6, 0xe2, 0xb1, - 0xb2, 0x26, 0xc4, 0x84, 0xc7, 0x92, 0xc8, 0x8d, 0xc5, 0x93, 0x30, 0xc4, 0x94, 0xc5, - 0x88, 0xc5, 0xa1, 0xc2, 0xa1, 0xc7, 0x9f, 0xc4, 0xbb, 0xc7, 0x99, 0xc6, 0xac, 0xc6, - 0xa7, 0xc9, 0x87, 0x2b, 0xc6, 0x99, 0xce, 0x85, 0xe1, 0x9b, 0x9d, 0xc3, 0x90, 0xe1, - 0x9a, 0xad, 0xe1, 0x9b, 0x94, 0xc3, 0x97, 0xc4, 0x84, 0xc4, 0x9c, 0xc7, 0x84, 0xc3, - 0x8f, 0x79, 0xc5, 0xa1, 0xc8, 0x98, 0xc5, 0xa9, 0x64, 0xc3, 0xa9, 0x4d, 0xc4, 0x9c, - 0xc6, 0xba, 0xe2, 0xb1, 0xb8, 0xc5, 0xbe, 0xe2, 0xb1, 0xbf, 0xc3, 0x88, 0xc5, 0x81, - 0xc3, 0xbc, 0xc9, 0x84, 0xc6, 0xbb, 0xc6, 0xa3, 0xe1, 0x9b, 0x8c, 0x34, 0xc3, 0x85, - 0x78, 0xc8, 0xb8, 0xc2, 0xa4, 0xc5, 0xb2, 0xc6, 0x82, 0x40, 0xc6, 0xa3, 0xc3, 0xb0, - 0xc6, 0xb3, 0x72, 0xc2, 0xa1, 0xc6, 0x92, 0xc7, 0xa2, 0xe2, 0xb1, 0xa5, 0xc9, 0x8a, - 0xe2, 0xb1, 0xbb, 0xc2, 0xb5, 0xe2, 0xb1, 0xb0, 0xc4, 0x88, 0xc3, 0x95, 0xc6, 0xb2, - 0xc7, 0x9d, 0xc7, 0x96, 0xe2, 0xb1, 0xaa, 0x67, 0xc3, 0xa3, 0xc4, 0xbf, 0xc9, 0x8b, - 0xc4, 0xb9, 0xc4, 0xa8, 0xe2, 0xb1, 0xad, 0x41, 0xc3, 0xb4, 0xce, 0x86, 0xc4, 0xbe, - 0xc6, 0xa8, 0xe2, 0xb1, 0xa4, 0xc5, 0xbc, 0xc8, 0x94, 0xe1, 0x9b, 0x8b, 0xc5, 0x81, - 0xe1, 0x9b, 0x94, 0xc4, 0xae, 0xc5, 0x91, 0x5a, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x6e, 0xa8, 0x83, 0xd2, 0x4d, 0x3d, 0xbc, 0xf6, 0xc7, 0xad, 0x2b, 0xf7, 0xed, 0x87, - 0xc7, 0xb5, 0xaa, 0xd2, 0x13, 0xf0, 0xcf, 0x11, 0x2b, 0xff, 0xa0, 0xc8, 0x84, 0xb1, - 0xd0, 0xe0, 0x56, 0x9a, + 0x01, 0xcb, 0x2c, 0x3f, 0xae, 0x16, 0xf2, 0xe5, 0x82, 0x1e, 0x34, 0x64, 0x70, 0x17, + 0xf3, 0x68, 0x04, 0xb1, 0x7e, 0xfc, 0x8c, 0xb7, 0x69, 0x54, 0x79, 0x61, 0x5d, 0xe8, + 0xf3, 0x2d, 0x29, 0x21, ], }, TestVector { key: [ - 0x5e, 0x09, 0x49, 0x46, 0x12, 0x04, 0x4d, 0x6e, 0xf5, 0xb0, 0xbd, 0x0d, 0xc9, 0xb4, - 0xa0, 0xdc, 0x09, 0x47, 0x76, 0x00, 0x9e, 0x1e, 0x94, 0xce, 0x39, 0x1c, 0x27, 0xb8, - 0xb7, 0x51, 0x8f, 0xe0, + 0xbf, 0x39, 0x20, 0xce, 0x2e, 0x9e, 0x95, 0xb0, 0xee, 0xce, 0x13, 0x0a, 0x50, 0xba, + 0x7d, 0xcc, 0x6f, 0x26, 0x51, 0x2a, 0x9f, 0xc7, 0xb8, 0x04, 0xaf, 0xf0, 0x89, 0xf5, + 0x0c, 0xbc, 0xff, 0xf7, ], description: [ - 0xc7, 0x9b, 0xc7, 0xa3, 0xc3, 0xa4, 0xc4, 0xa7, 0xe1, 0x9a, 0xa4, 0x29, 0xc9, 0x88, - 0xc3, 0xa8, 0xe1, 0x9b, 0x9c, 0x71, 0xc5, 0xaa, 0xe2, 0xb1, 0xba, 0xc8, 0xac, 0xc7, - 0xa5, 0xc8, 0x8b, 0xcd, 0xbc, 0xe1, 0x9b, 0x83, 0xc9, 0x86, 0xe1, 0x9a, 0xad, 0xc6, - 0x87, 0xc8, 0xbc, 0xc8, 0xa0, 0xc3, 0x94, 0xe1, 0x9b, 0xa5, 0xc8, 0x94, 0xc3, 0xac, - 0xc3, 0x88, 0xe1, 0x9a, 0xa8, 0xc7, 0xb9, 0x5b, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0x9f, - 0x63, 0xc6, 0x95, 0xcd, 0xb3, 0xc3, 0x8d, 0xc6, 0x88, 0xc2, 0xaf, 0xc4, 0x93, 0x64, - 0xc6, 0x89, 0xc8, 0xa0, 0x5b, 0xc8, 0x8b, 0xc6, 0xb7, 0xe1, 0x9b, 0xa0, 0x4c, 0x31, - 0x31, 0xc3, 0x82, 0xc7, 0xa5, 0xc9, 0x8e, 0xc9, 0x8f, 0xe1, 0x9b, 0x93, 0xc7, 0x80, - 0xc4, 0x80, 0xc3, 0xb2, 0xc3, 0x88, 0xe2, 0xb1, 0xb9, 0xc8, 0xab, 0xcd, 0xbb, 0xc3, - 0x8c, 0xc9, 0x87, 0xe1, 0x9a, 0xaf, 0xc8, 0xa9, 0xc9, 0x84, 0xc4, 0x8b, 0xe1, 0x9b, - 0x90, 0xc7, 0xb2, 0xc5, 0xaa, 0xc6, 0x9d, 0xc8, 0xb3, 0xe1, 0x9b, 0x9f, 0xc2, 0xa6, - 0xc5, 0xba, 0xe1, 0x9b, 0xa4, 0xc4, 0x8a, 0x4f, 0xc3, 0x85, 0xc5, 0x9d, 0x5f, 0xc8, - 0xbf, 0x6d, 0x41, 0xc7, 0x8b, 0xe1, 0x9a, 0xb3, 0xc7, 0xb3, 0xc4, 0x89, 0xc6, 0xaf, - 0xc6, 0xb7, 0xc3, 0x8f, 0xc5, 0x9d, 0xc8, 0x82, 0xc8, 0x82, 0xc6, 0xb6, 0xc3, 0xbf, - 0xc8, 0xa4, 0xc6, 0xab, 0x5e, 0xc3, 0x9a, 0xc5, 0xa0, 0xe2, 0xb1, 0xb0, 0xc3, 0x90, - 0xc8, 0x99, 0xc5, 0xac, 0xe1, 0x9a, 0xa6, 0xc3, 0x95, 0xcd, 0xb4, 0xcd, 0xb3, 0xc6, - 0x9f, 0xc7, 0x80, 0xc8, 0xaa, 0xe1, 0x9a, 0xb7, 0xc7, 0xa6, 0x2c, 0xc5, 0x83, 0xc8, - 0xbe, 0xc8, 0x93, 0xc4, 0xa0, 0xc3, 0x9f, 0xc5, 0xa1, 0xc5, 0x8d, 0xe1, 0x9b, 0xa5, - 0xc6, 0x99, 0x4b, 0xc4, 0xbe, 0xc8, 0x87, 0xc8, 0x92, 0xe1, 0x9b, 0xae, 0xc8, 0x86, - 0xc7, 0x90, 0xc5, 0x85, 0xc2, 0xb6, 0xc5, 0x84, 0xe1, 0x9a, 0xa5, 0xc8, 0x86, 0xc4, - 0x8d, 0xc6, 0xb9, 0xc8, 0x90, 0x25, 0xc4, 0xa9, 0xc4, 0xbb, 0xc5, 0xb0, 0xe2, 0xb1, - 0xa9, 0xe1, 0x9b, 0xad, 0x60, 0xc4, 0x9b, 0xc8, 0xab, 0xc3, 0xad, 0xc6, 0xa2, 0xc7, - 0x9d, 0xe1, 0x9b, 0x89, 0xe1, 0x9b, 0x97, 0xe1, 0x9b, 0xa6, 0x32, 0xc6, 0x99, 0xc3, - 0x9e, 0xc9, 0x8e, 0x4c, 0xe1, 0x9b, 0x93, 0xc6, 0xa4, 0xc6, 0x8c, 0xe2, 0xb1, 0xb8, - 0xc7, 0x9f, 0x2a, 0xc5, 0xa1, 0xe1, 0x9b, 0x9f, 0xcd, 0xbb, 0xc3, 0x8f, 0xc7, 0x89, - 0xc7, 0xaf, 0x5e, 0xc7, 0x8b, 0xc8, 0xa4, 0xc6, 0x81, 0xcd, 0xb3, 0xc2, 0xa9, 0xc7, - 0xae, 0xc8, 0x83, 0xc6, 0xae, 0xe1, 0x9b, 0xa3, 0xc6, 0xa3, 0xc6, 0xa0, 0xe1, 0x9a, - 0xab, 0xc8, 0xab, 0xc5, 0x9c, 0xc8, 0x94, 0xc5, 0xa8, 0xe2, 0xb1, 0xb6, 0xc4, 0xae, - 0xc6, 0xbe, 0xc7, 0xa4, 0xc7, 0x87, 0xc8, 0x9d, 0xe1, 0x9a, 0xbf, 0xc4, 0xa7, 0xc3, - 0xb3, 0xc5, 0x9e, 0xe1, 0x9a, 0xa2, 0xe1, 0x9b, 0x9e, 0xc7, 0xad, 0x7e, 0xe1, 0x9b, - 0x93, 0xc6, 0xa8, 0xc4, 0xb5, 0xc6, 0xb1, 0xe1, 0x9b, 0xa0, 0xc4, 0xac, 0xc4, 0x91, - 0xc4, 0xbe, 0xc8, 0x89, 0x4f, 0xc6, 0xa2, 0xc5, 0xbb, 0xe1, 0x9b, 0x91, 0xc7, 0x9f, - 0xe1, 0x9b, 0xa4, 0xe1, 0x9b, 0x9a, 0xc7, 0xa9, 0xc4, 0xa6, 0xe1, 0x9b, 0x85, 0xc7, - 0xae, 0xc5, 0x91, 0xc6, 0x94, 0x42, 0x6c, 0xc4, 0xab, 0xc5, 0xa0, 0xc8, 0x89, 0xe1, - 0x9a, 0xb9, 0xc6, 0xac, 0xc6, 0xae, 0xc5, 0xa1, 0xcd, 0xb1, 0xc8, 0xb0, 0xc3, 0x84, - 0xc8, 0xbc, 0xc3, 0x9b, 0xc7, 0xbc, 0xc6, 0xbc, 0xc8, 0x82, 0xc4, 0xbf, 0xe1, 0x9b, - 0xaa, 0xc8, 0xae, 0xce, 0x85, 0xc6, 0x86, 0x4c, + 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, + 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, + 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, + 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, + 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, + 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, + 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, + 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, + 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, + 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, + 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, + 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, + 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, + 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, + 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, + 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, + 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, + 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, + 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, + 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, + 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, + 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, + 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, + 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, + 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, + 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, + 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, + 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, + 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, + 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, + 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, + 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, + 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, + 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, + 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, + 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, + 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, ], asset_base: [ - 0x86, 0x78, 0x20, 0x68, 0xdc, 0x11, 0xd4, 0x4f, 0xff, 0xfe, 0x8d, 0x44, 0x03, 0xad, - 0x6e, 0xf1, 0xe7, 0x7d, 0x20, 0xd2, 0x10, 0x83, 0x2e, 0x2d, 0xbf, 0x84, 0xdf, 0x09, - 0x7c, 0x87, 0x21, 0x24, + 0x26, 0x21, 0x1d, 0x3b, 0x0b, 0xcf, 0x80, 0x41, 0x43, 0x30, 0x1b, 0x45, 0x23, 0x7b, + 0x96, 0xc4, 0x97, 0xe6, 0xe3, 0x87, 0x2c, 0x75, 0xb8, 0xc1, 0x58, 0x67, 0x31, 0xda, + 0x39, 0x1e, 0xc4, 0x25, ], }, ] diff --git a/src/test_vectors/issuance_auth_sig.rs b/src/test_vectors/issuance_auth_sig.rs index fe71486e2..648a5cfb4 100644 --- a/src/test_vectors/issuance_auth_sig.rs +++ b/src/test_vectors/issuance_auth_sig.rs @@ -1,4 +1,4 @@ -// From https://github.com/zcash-hackworks/zcash-test-vectors/ (issuance_auth_sig) +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_issuance_auth_sig) pub(crate) struct TestVector { pub(crate) isk: [u8; 32], diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 4417713eb..56d189478 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -1,4 +1,4 @@ -// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_key_components) +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_key_components) pub(crate) struct TestVector { pub(crate) sk: [u8; 32], diff --git a/src/test_vectors/merkle_path.rs b/src/test_vectors/merkle_path.rs index ff0270d2d..930d7721d 100644 --- a/src/test_vectors/merkle_path.rs +++ b/src/test_vectors/merkle_path.rs @@ -1,3 +1,5 @@ +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_merkle_tree) + pub(crate) struct TestVector { pub(crate) leaves: [[u8; 32]; 16], pub(crate) paths: [[[u8; 32]; 4]; 16], @@ -5,7 +7,6 @@ pub(crate) struct TestVector { } pub(crate) fn test_vectors() -> Vec { - // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_merkle_tree.py vec![ TestVector { leaves: [ diff --git a/src/test_vectors/note_encryption.rs b/src/test_vectors/note_encryption_vanilla.rs similarity index 62% rename from src/test_vectors/note_encryption.rs rename to src/test_vectors/note_encryption_vanilla.rs index b4a1f3137..3011538f6 100644 --- a/src/test_vectors/note_encryption.rs +++ b/src/test_vectors/note_encryption_vanilla.rs @@ -1,5 +1,6 @@ +//! Test vectors for Orchard key components. + pub(crate) struct TestVector { - // make all fields public so we can use them in the test pub(crate) incoming_viewing_key: [u8; 64], pub(crate) ovk: [u8; 32], pub(crate) default_d: [u8; 11], @@ -21,8 +22,8 @@ pub(crate) struct TestVector { pub(crate) c_out: [u8; 80], } -// From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_note_encryption.py pub(crate) fn test_vectors() -> Vec { + // From https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/orchard_note_encryption.py vec![ TestVector { incoming_viewing_key: [ @@ -102,29 +103,29 @@ pub(crate) fn test_vectors() -> Vec { 0xf1, 0x1c, 0x83, 0x06, ], cmx: [ - 0x23, 0x75, 0x7c, 0x51, 0x58, 0x21, 0xcb, 0xc1, 0x84, 0x3c, 0x9a, 0x45, 0x7b, 0x7e, - 0x6a, 0xe6, 0x01, 0xad, 0xd2, 0xea, 0x10, 0xb9, 0xc8, 0x6d, 0x6b, 0x31, 0x7c, 0xe2, - 0xf1, 0x7b, 0xd9, 0x21, + 0xa5, 0x70, 0x6f, 0x3d, 0x1b, 0x68, 0x8e, 0x9d, 0xc6, 0x34, 0xee, 0xe4, 0xe6, 0x5b, + 0x02, 0x8a, 0x43, 0xee, 0xae, 0xd2, 0x43, 0x5b, 0xea, 0x2a, 0xe3, 0xd5, 0x16, 0x05, + 0x75, 0xc1, 0x1a, 0x3b, ], esk: [ - 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, 0x8b, 0xfe, 0x9b, 0x38, - 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, 0x8e, 0x33, 0x35, 0x4f, - 0xff, 0xf1, 0xbd, 0x1a, + 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, 0xd3, 0x5a, 0xd7, 0x46, + 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, 0x20, 0xa6, 0x25, 0xff, + 0x38, 0x77, 0xea, 0x3f, ], ephemeral_key: [ - 0x8a, 0x5e, 0x13, 0x2c, 0x3a, 0x07, 0x04, 0xf2, 0x45, 0x6f, 0xbd, 0x77, 0x7a, 0x13, - 0xd6, 0xec, 0x57, 0x65, 0x56, 0x71, 0xdb, 0x07, 0x2a, 0x7d, 0x27, 0x6a, 0xd9, 0x69, - 0xf5, 0xec, 0x45, 0x17, + 0xad, 0xdb, 0x47, 0xb6, 0xac, 0x5d, 0xfc, 0x16, 0x55, 0x89, 0x23, 0xd3, 0xa8, 0xf3, + 0x76, 0x09, 0x5c, 0x69, 0x5c, 0x04, 0x7c, 0x4e, 0x32, 0x66, 0xae, 0x67, 0x69, 0x87, + 0xf7, 0xe3, 0x13, 0x81, ], shared_secret: [ - 0x36, 0xd5, 0x4c, 0xab, 0xc6, 0x7f, 0x6c, 0xc7, 0x26, 0xa7, 0x30, 0xf3, 0xa0, 0xce, - 0xed, 0x58, 0x53, 0xf0, 0x8c, 0xd3, 0x81, 0x46, 0xc8, 0x34, 0x25, 0x98, 0x98, 0x7c, - 0x21, 0x50, 0x48, 0xa5, + 0x30, 0x3c, 0x1c, 0x3f, 0x2b, 0xcb, 0xb9, 0xd8, 0x49, 0x70, 0x15, 0xa6, 0xdf, 0xca, + 0x95, 0x4e, 0xce, 0x0d, 0x3b, 0x6c, 0xf1, 0x0a, 0xb9, 0xf7, 0x19, 0xeb, 0x89, 0x19, + 0x9e, 0xdf, 0xe9, 0x89, ], k_enc: [ - 0x82, 0xc4, 0x32, 0x65, 0x33, 0x7f, 0x1a, 0xb3, 0x7b, 0x18, 0xdf, 0x27, 0x75, 0x48, - 0x61, 0x82, 0x63, 0xb8, 0x02, 0x4d, 0x9b, 0x14, 0x5a, 0x05, 0xad, 0xe2, 0xeb, 0x54, - 0x79, 0x18, 0x03, 0x20, + 0xef, 0x9d, 0x62, 0x25, 0x68, 0x7c, 0x2c, 0x91, 0x7b, 0x5c, 0xad, 0xa1, 0x75, 0x23, + 0xe8, 0xfb, 0xdb, 0x08, 0x82, 0x25, 0xaf, 0x2d, 0xb5, 0x72, 0xbb, 0x40, 0x0e, 0x44, + 0x8b, 0x5e, 0xa8, 0x71, ], p_enc: [ 0x02, 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, 0x8d, 0x5f, @@ -170,68 +171,68 @@ pub(crate) fn test_vectors() -> Vec { 0xee, 0xcc, 0x40, 0xa9, ], c_enc: [ - 0x93, 0xe0, 0x48, 0x74, 0xb5, 0x83, 0x7c, 0x26, 0x1d, 0xaf, 0x1a, 0x27, 0xb7, 0x83, - 0xec, 0x48, 0x65, 0xd3, 0xbb, 0x72, 0x8e, 0xb1, 0x61, 0xda, 0xed, 0xb8, 0x44, 0x6a, - 0xb3, 0x8f, 0x07, 0x8e, 0xa8, 0x66, 0x2e, 0x4d, 0x2e, 0x9d, 0x00, 0xa3, 0x95, 0x27, - 0xdc, 0xde, 0x51, 0x7a, 0xc3, 0xdb, 0xf9, 0xd2, 0x7e, 0x3c, 0x79, 0xfa, 0x88, 0x1a, - 0xbb, 0x48, 0xb7, 0x0d, 0xbc, 0x28, 0xdd, 0xf4, 0xaf, 0x81, 0xae, 0xed, 0x2a, 0x29, - 0x86, 0x00, 0x51, 0x08, 0x48, 0xed, 0xbd, 0xc4, 0x2e, 0x88, 0x95, 0x48, 0x70, 0xd5, - 0xd6, 0x01, 0xcd, 0xf2, 0x90, 0x18, 0x1b, 0x53, 0x91, 0x05, 0xb9, 0xf6, 0x13, 0x86, - 0xcb, 0x07, 0x84, 0x6b, 0xc8, 0xe3, 0x19, 0xdf, 0xab, 0x8e, 0x10, 0x97, 0x66, 0xa2, - 0x8c, 0x1e, 0x0b, 0xbf, 0x91, 0x32, 0x02, 0xce, 0xcd, 0x1b, 0x48, 0x17, 0xa2, 0x28, - 0x2f, 0xc2, 0x9e, 0xd4, 0x4d, 0x9b, 0x04, 0x04, 0x9d, 0xe5, 0x5a, 0xcf, 0x54, 0x99, - 0xe5, 0xf5, 0x65, 0xd4, 0x8b, 0x8f, 0x19, 0x72, 0xc0, 0x43, 0x84, 0x77, 0x96, 0x23, - 0x0d, 0xc6, 0x8f, 0x32, 0x57, 0xc0, 0x85, 0x29, 0x14, 0x8c, 0x8e, 0x0c, 0x32, 0x7b, - 0x25, 0xb4, 0x59, 0x87, 0x7c, 0xde, 0xd9, 0x8f, 0xf7, 0x8e, 0x81, 0xfa, 0x69, 0x2e, - 0x14, 0xf8, 0xfd, 0xa1, 0xfe, 0x52, 0x4f, 0xf1, 0x50, 0x18, 0x1f, 0x73, 0x6e, 0xd3, - 0xa8, 0x8e, 0xc7, 0x89, 0xdc, 0x15, 0x95, 0x4a, 0x02, 0x63, 0x9a, 0x8a, 0x20, 0xca, - 0x38, 0xd8, 0x99, 0xbf, 0xd1, 0xc5, 0x73, 0xb0, 0x41, 0xee, 0x7b, 0xf2, 0x2b, 0x96, - 0x75, 0xbd, 0xa8, 0xc4, 0xb0, 0x58, 0xa0, 0x5a, 0x49, 0x33, 0x03, 0xb1, 0x1f, 0x35, - 0x81, 0xc1, 0x9d, 0x2d, 0xa9, 0x96, 0x6a, 0x71, 0x06, 0x6e, 0xc1, 0x7d, 0xcc, 0xd3, - 0x48, 0x20, 0x7e, 0xb3, 0x14, 0xf6, 0xcf, 0xc9, 0xd0, 0x6a, 0x62, 0x14, 0xc6, 0x72, - 0x10, 0x97, 0xa5, 0x2e, 0x27, 0x76, 0x66, 0x7c, 0x6b, 0xe9, 0xc8, 0x86, 0x2b, 0x17, - 0x3d, 0xb0, 0xe8, 0x04, 0xb1, 0x2c, 0xaa, 0xe9, 0xd9, 0xfa, 0x09, 0xf3, 0xf4, 0x8c, - 0xaf, 0x4b, 0xf7, 0x56, 0xa2, 0x78, 0x95, 0x0a, 0x25, 0x4e, 0xc4, 0x14, 0x76, 0x77, - 0xaa, 0xca, 0x21, 0x42, 0x96, 0x08, 0x1a, 0x2f, 0x62, 0x4a, 0x92, 0x78, 0x94, 0x6e, - 0x68, 0x9d, 0xd9, 0x14, 0x02, 0x90, 0x92, 0xe7, 0xfa, 0x8f, 0xbc, 0x8a, 0x04, 0x46, - 0x7d, 0x60, 0xed, 0xff, 0x5d, 0x97, 0xcb, 0x65, 0x09, 0xa0, 0xc7, 0x2c, 0xed, 0x77, - 0xac, 0xa8, 0x71, 0x30, 0x8e, 0x7d, 0xe2, 0xbe, 0xb1, 0x52, 0x0a, 0x34, 0x17, 0xd7, - 0x21, 0x3a, 0x9a, 0xbd, 0x47, 0x35, 0x8c, 0x4f, 0x32, 0x9f, 0x0f, 0x64, 0x41, 0x92, - 0x10, 0xa9, 0x9d, 0xb2, 0xde, 0x6e, 0x6d, 0x89, 0x21, 0xb0, 0xf4, 0xf9, 0x9f, 0xd6, - 0x45, 0xfa, 0xe0, 0xd6, 0x29, 0xce, 0x22, 0x11, 0x90, 0x5f, 0x25, 0xf4, 0x0d, 0x12, - 0x0b, 0x63, 0x27, 0x93, 0x75, 0xb5, 0x43, 0xc3, 0x1e, 0x3b, 0x55, 0x7e, 0x57, 0xa7, - 0xa8, 0x7c, 0x61, 0x79, 0xeb, 0xd3, 0x4f, 0x6d, 0xbb, 0x92, 0x0e, 0xc5, 0xe0, 0x5d, - 0x6a, 0x77, 0xec, 0xdf, 0x36, 0xb4, 0x57, 0xba, 0xb4, 0x56, 0x6c, 0x40, 0x8f, 0xb5, - 0x7d, 0xfc, 0xdd, 0xda, 0xa4, 0x2c, 0x51, 0x34, 0xaf, 0x3e, 0x97, 0x8d, 0xbf, 0xd0, - 0xdf, 0xb0, 0xca, 0x4f, 0xfa, 0xf1, 0x65, 0x0a, 0xbe, 0xe1, 0x62, 0x5f, 0x7f, 0x4b, - 0xf8, 0x25, 0x06, 0x01, 0x00, 0x64, 0x5b, 0x54, 0xc0, 0x04, 0x1f, 0xbf, 0xbd, 0xef, - 0xf7, 0xb9, 0x38, 0x04, 0xe9, 0xcc, 0x0c, 0xcd, 0x6f, 0x27, 0xbe, 0x40, 0x01, 0x6c, - 0x32, 0xd4, 0x2f, 0xe3, 0x66, 0xfa, 0xaa, 0x86, 0x87, 0xc2, 0xd1, 0x92, 0x61, 0x9f, - 0x56, 0x5b, 0x0c, 0x70, 0xea, 0x6a, 0x3f, 0x79, 0xd5, 0x3a, 0x52, 0x41, 0xe6, 0x9c, - 0x3c, 0xa6, 0x87, 0xa1, 0x12, 0xfb, 0x16, 0xc2, 0x5c, 0xc0, 0x83, 0x17, 0xdb, 0xa4, - 0x23, 0x97, 0x0c, 0x32, 0xdf, 0xb4, 0xbd, 0x69, 0x22, 0xe3, 0x36, 0xab, 0xf2, 0xfd, - 0xe2, 0xc3, 0xaa, 0x5d, 0xb2, 0x93, 0xef, 0x27, 0x47, 0x87, 0x6c, 0x8b, 0xd8, 0x6e, - 0xa1, 0x87, 0xcb, 0x60, 0x1a, 0xf7, + 0x1a, 0x9a, 0xdb, 0x14, 0x24, 0x98, 0xe3, 0xdc, 0xc7, 0x6f, 0xed, 0x77, 0x86, 0x14, + 0xdd, 0x31, 0x6c, 0x02, 0xfb, 0xb8, 0xba, 0x92, 0x44, 0xae, 0x4c, 0x2e, 0x32, 0xa0, + 0x7d, 0xae, 0xec, 0xa4, 0x12, 0x26, 0xb9, 0x8b, 0xfe, 0x74, 0xf9, 0xfc, 0xb2, 0x28, + 0xcf, 0xc1, 0x00, 0xf3, 0x18, 0x0f, 0x57, 0x75, 0xec, 0xe3, 0x8b, 0xe7, 0xed, 0x45, + 0xd9, 0x40, 0x21, 0xf4, 0x40, 0x1b, 0x2a, 0x4d, 0x75, 0x82, 0xb4, 0x28, 0xd4, 0x9e, + 0xc7, 0xf5, 0xb5, 0xa4, 0x98, 0x97, 0x3e, 0x60, 0xe3, 0x8e, 0x74, 0xf5, 0xc3, 0xe5, + 0x77, 0x82, 0x7c, 0x38, 0x28, 0x57, 0xd8, 0x16, 0x6b, 0x54, 0xe6, 0x4f, 0x66, 0xef, + 0x5c, 0x7e, 0x8c, 0x9b, 0xaa, 0x2a, 0x3f, 0xa9, 0xe3, 0x7d, 0x08, 0x77, 0x17, 0xd5, + 0xe9, 0x6b, 0xc2, 0xf7, 0x3d, 0x03, 0x14, 0x50, 0xdc, 0x24, 0x32, 0xba, 0x49, 0xd8, + 0xb7, 0x4d, 0xb2, 0x13, 0x09, 0x9e, 0xa9, 0xba, 0x04, 0xeb, 0x63, 0xb6, 0x57, 0x4d, + 0x46, 0xc0, 0x3c, 0xe7, 0x90, 0x0d, 0x4a, 0xc4, 0xbb, 0x18, 0x8e, 0xe9, 0x03, 0x0d, + 0x7f, 0x69, 0xc8, 0x95, 0xa9, 0x4f, 0xc1, 0x82, 0xf2, 0x25, 0xa9, 0x4f, 0x0c, 0xde, + 0x1b, 0x49, 0x88, 0x68, 0x71, 0xa3, 0x76, 0x34, 0x1e, 0xa9, 0x41, 0x71, 0xbe, 0xfd, + 0x95, 0xa8, 0x30, 0xfa, 0x18, 0x40, 0x70, 0x97, 0xdc, 0xa5, 0x11, 0x02, 0x54, 0x63, + 0xd4, 0x37, 0xe9, 0x69, 0x5c, 0xaa, 0x07, 0x9a, 0x2f, 0x68, 0xcd, 0xc7, 0xf2, 0xc1, + 0x32, 0x67, 0xbf, 0xf4, 0x19, 0x51, 0x37, 0xfa, 0x89, 0x53, 0x25, 0x2a, 0x81, 0xb2, + 0xaf, 0xa1, 0x58, 0x2b, 0x9b, 0xfb, 0x4a, 0xc9, 0x60, 0x37, 0xed, 0x29, 0x91, 0xd3, + 0xcb, 0xc7, 0xd5, 0x4a, 0xff, 0x6e, 0x62, 0x1b, 0x06, 0xa7, 0xb2, 0xb9, 0xca, 0xf2, + 0x95, 0x5e, 0xfa, 0xf4, 0xea, 0x8e, 0xfc, 0xfd, 0x02, 0x3a, 0x3c, 0x17, 0x48, 0xdf, + 0x3c, 0xbd, 0x43, 0xe0, 0xb9, 0xa8, 0xb0, 0x94, 0x56, 0x88, 0xd5, 0x20, 0x56, 0xc1, + 0xd1, 0x6e, 0xea, 0x37, 0xe7, 0x98, 0xba, 0x31, 0xdc, 0x3e, 0x5d, 0x49, 0x52, 0xbd, + 0x51, 0xec, 0x76, 0x9d, 0x57, 0x88, 0xb6, 0xe3, 0x5f, 0xe9, 0x04, 0x2b, 0x95, 0xd4, + 0xd2, 0x17, 0x81, 0x40, 0x0e, 0xaf, 0xf5, 0x86, 0x16, 0xad, 0x56, 0x27, 0x96, 0x63, + 0x6a, 0x50, 0xb8, 0xed, 0x6c, 0x7f, 0x98, 0x1d, 0xc7, 0xba, 0x81, 0x4e, 0xff, 0x15, + 0x2c, 0xb2, 0x28, 0xa2, 0xea, 0xd2, 0xf8, 0x32, 0x66, 0x2f, 0xa4, 0xa4, 0xa5, 0x07, + 0x97, 0xb0, 0xf8, 0x5b, 0x62, 0xd0, 0x8b, 0x1d, 0xd2, 0xd8, 0xe4, 0x3b, 0x4a, 0x5b, + 0xfb, 0xb1, 0x59, 0xed, 0x57, 0x8e, 0xf7, 0x47, 0x5d, 0xe0, 0xad, 0xa1, 0x3e, 0x17, + 0xad, 0x87, 0xcc, 0x23, 0x05, 0x67, 0x2b, 0xcc, 0x55, 0xa8, 0x88, 0x13, 0x17, 0xfd, + 0xc1, 0xbf, 0xc4, 0x59, 0xb6, 0x8b, 0x2d, 0xf7, 0x0c, 0xad, 0x37, 0x70, 0xed, 0x0f, + 0xd0, 0x2d, 0x64, 0xb9, 0x6f, 0x2b, 0xbf, 0x6f, 0x8f, 0x63, 0x2e, 0x86, 0x6c, 0xa5, + 0xd1, 0x96, 0xd2, 0x48, 0xad, 0x05, 0xc3, 0xde, 0x64, 0x41, 0x48, 0xa8, 0x0b, 0x51, + 0xad, 0xa9, 0x5b, 0xd0, 0x8d, 0x73, 0xcd, 0xbb, 0x45, 0x26, 0x4f, 0x3b, 0xd1, 0x13, + 0x83, 0x5b, 0x46, 0xf9, 0xbe, 0x7b, 0x6d, 0x23, 0xa4, 0x3b, 0xdd, 0xfe, 0x1e, 0x74, + 0x08, 0xc9, 0x70, 0x31, 0xe1, 0xa8, 0x21, 0x4b, 0xab, 0x46, 0x39, 0x10, 0x44, 0xb7, + 0x00, 0xd3, 0x8f, 0x51, 0x92, 0xc5, 0x7f, 0xe6, 0xf8, 0x71, 0x59, 0xb5, 0x55, 0x12, + 0x09, 0x4e, 0x29, 0xd2, 0xce, 0xba, 0xb8, 0x68, 0xc8, 0xf1, 0xad, 0xba, 0xd5, 0x70, + 0x77, 0xcb, 0xeb, 0x5e, 0x69, 0x65, 0x85, 0x82, 0xbf, 0x98, 0xd1, 0x9d, 0x64, 0xf4, + 0x4b, 0x0d, 0x50, 0xc7, 0xe2, 0x20, 0x9a, 0xb3, 0xfc, 0x56, 0xb4, 0xf4, 0x09, 0x12, + 0x3a, 0xae, 0xb0, 0x26, 0x3a, 0x22, 0x45, 0x1b, 0xc1, 0x4e, 0xd7, 0x56, 0xd0, 0x48, + 0x38, 0x5a, 0xed, 0xbb, 0x86, 0xa8, 0x46, 0x77, 0xbb, 0x2d, 0x21, 0xc5, 0x2c, 0xc9, + 0x49, 0x41, 0x47, 0xbf, 0x0f, 0xb1, 0x02, 0x74, 0x52, 0x82, 0x99, 0x09, 0x09, 0x72, + 0x62, 0x28, 0x18, 0x6e, 0x02, 0xc8, ], ock: [ - 0xb3, 0x25, 0xeb, 0xe5, 0x7a, 0x2c, 0x40, 0xa8, 0xb2, 0x11, 0xcf, 0xdf, 0x72, 0xa1, - 0xa2, 0x44, 0xf1, 0x53, 0x42, 0x85, 0x98, 0x88, 0xa3, 0x64, 0x52, 0x3e, 0xfd, 0x2a, - 0xc6, 0x6a, 0x1a, 0xd6, + 0x4e, 0x9d, 0x45, 0x94, 0x6b, 0x3e, 0xea, 0xe7, 0xfe, 0x30, 0x5d, 0x5b, 0x90, 0x50, + 0x36, 0x14, 0x1f, 0x9f, 0x40, 0x09, 0xa6, 0x29, 0x4b, 0x96, 0xc7, 0x22, 0xa4, 0xa0, + 0xbe, 0x68, 0x5d, 0xff, ], op: [ 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, - 0x49, 0x50, 0x69, 0x2c, 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, - 0x8b, 0xfe, 0x9b, 0x38, 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, - 0x8e, 0x33, 0x35, 0x4f, 0xff, 0xf1, 0xbd, 0x1a, + 0x49, 0x50, 0x69, 0x2c, 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, + 0xd3, 0x5a, 0xd7, 0x46, 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, + 0x20, 0xa6, 0x25, 0xff, 0x38, 0x77, 0xea, 0x3f, ], c_out: [ - 0x55, 0xb8, 0x90, 0x7c, 0x6d, 0x45, 0x4b, 0x83, 0x63, 0x4f, 0x1b, 0x9a, 0x1a, 0xa3, - 0xc3, 0xc9, 0x8a, 0xdc, 0x77, 0xd9, 0x6c, 0x2f, 0x62, 0x49, 0xec, 0x66, 0xdb, 0xae, - 0x4d, 0x0c, 0xc9, 0x40, 0xd7, 0x26, 0xbc, 0xd1, 0xec, 0x91, 0x18, 0x9f, 0xd3, 0x04, - 0x9a, 0x33, 0xf2, 0xea, 0x7d, 0x8b, 0x74, 0xaa, 0xc1, 0x7c, 0xda, 0x38, 0x83, 0x80, - 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, - 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, + 0xcb, 0xdf, 0x68, 0xa5, 0x7f, 0xb4, 0xa4, 0x6f, 0x34, 0x60, 0xff, 0x22, 0x7b, 0xc6, + 0x18, 0xda, 0xe1, 0x12, 0x29, 0x45, 0xb3, 0x80, 0xc7, 0xe5, 0x49, 0xcf, 0x4a, 0x6e, + 0x8b, 0xf3, 0x75, 0x49, 0xba, 0xe1, 0x89, 0x1f, 0xd8, 0xd1, 0xa4, 0x94, 0x4f, 0xdf, + 0x41, 0x0f, 0x07, 0x02, 0xed, 0xa5, 0x44, 0x2f, 0x0e, 0xa0, 0x1a, 0x5d, 0xf0, 0x12, + 0xa0, 0xae, 0x4d, 0x84, 0xed, 0x79, 0x80, 0x33, 0x28, 0xbd, 0x1f, 0xd5, 0xfa, 0xc7, + 0x19, 0x21, 0x6a, 0x77, 0x6d, 0xe6, 0x4f, 0xd1, 0x67, 0xdb, ], }, TestVector { @@ -312,29 +313,29 @@ pub(crate) fn test_vectors() -> Vec { 0xb1, 0x84, 0x92, 0x11, ], cmx: [ - 0x59, 0xb6, 0xf3, 0xd4, 0x03, 0x22, 0x3d, 0x6c, 0xe4, 0x3d, 0xed, 0xae, 0xe2, 0x35, - 0xfc, 0xa9, 0x5c, 0xc8, 0xb2, 0x49, 0x94, 0x1c, 0xcd, 0xb6, 0x6f, 0x3f, 0x61, 0x1c, - 0xc5, 0xe9, 0xf9, 0x0f, + 0x9e, 0x04, 0x32, 0xb2, 0xb3, 0x33, 0xcd, 0xe8, 0xce, 0x92, 0x1b, 0x77, 0xca, 0x7e, + 0x9e, 0x41, 0x51, 0xe3, 0x74, 0xd5, 0x16, 0xcd, 0xa1, 0x17, 0x63, 0x83, 0x6a, 0xf3, + 0xb6, 0x6f, 0x5b, 0x15, ], esk: [ - 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, 0xdd, 0x73, 0x4d, 0x0e, - 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, 0x22, 0xc0, 0x61, 0xe0, - 0xbd, 0xc9, 0xce, 0x14, + 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, 0x4d, 0x80, 0x4a, 0x17, + 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, 0x92, 0x1c, 0xd5, 0xda, + 0x8a, 0x6e, 0x1a, 0x08, ], ephemeral_key: [ - 0xd2, 0x9e, 0x0d, 0x00, 0x1e, 0xe7, 0x1e, 0x05, 0x99, 0x08, 0x65, 0x04, 0xd8, 0x62, - 0xc7, 0xf5, 0x2b, 0x08, 0x60, 0x77, 0x0d, 0x8a, 0x4b, 0x42, 0xa8, 0x68, 0x11, 0xac, - 0x31, 0x69, 0x85, 0x8c, + 0x91, 0x92, 0x3e, 0xd8, 0x2b, 0x76, 0xd7, 0x97, 0x30, 0x7c, 0xaa, 0x23, 0x02, 0xc0, + 0xcf, 0x75, 0x56, 0x12, 0x17, 0x24, 0x98, 0x67, 0x53, 0x2a, 0xe5, 0x1c, 0x2e, 0xa0, + 0x05, 0xed, 0xad, 0xb6, ], shared_secret: [ - 0x11, 0xa0, 0xac, 0x79, 0x9a, 0x29, 0xb0, 0xed, 0x19, 0x5e, 0xd8, 0x7b, 0x13, 0x83, - 0x22, 0x26, 0x3b, 0xbb, 0x9c, 0x31, 0x00, 0x8c, 0x29, 0x59, 0xaf, 0x2f, 0xc6, 0x36, - 0x68, 0x7e, 0xd9, 0xb0, + 0x53, 0xd7, 0xe4, 0x84, 0x3a, 0x36, 0xd5, 0x79, 0xb5, 0xa7, 0xc1, 0x04, 0x11, 0x96, + 0xbd, 0x4c, 0x85, 0x80, 0x5c, 0xcd, 0x0a, 0x3f, 0x95, 0xbc, 0x9e, 0x71, 0x06, 0x90, + 0xd1, 0x1b, 0x7a, 0xaa, ], k_enc: [ - 0x4b, 0xbf, 0x80, 0xe7, 0xa1, 0x70, 0x3a, 0xc1, 0x4a, 0xd7, 0xb5, 0x44, 0x8a, 0x2e, - 0x8e, 0x79, 0x49, 0x30, 0x49, 0xd1, 0x9a, 0x6a, 0x51, 0x31, 0x67, 0xd5, 0x5b, 0xdd, - 0x58, 0x6a, 0xc0, 0xd9, + 0xc2, 0xe3, 0x38, 0x9d, 0x6f, 0xc3, 0xcd, 0x06, 0x7f, 0x59, 0x0a, 0x93, 0x73, 0x05, + 0x04, 0xad, 0x9b, 0x63, 0xc4, 0x55, 0x45, 0x69, 0xb9, 0x62, 0x0f, 0x3e, 0xf0, 0xb0, + 0x65, 0x94, 0xde, 0xd6, ], p_enc: [ 0x02, 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, 0x40, 0x50, @@ -380,68 +381,68 @@ pub(crate) fn test_vectors() -> Vec { 0x8b, 0x1e, 0x88, 0x6f, ], c_enc: [ - 0x1b, 0x42, 0x34, 0x80, 0xbf, 0x37, 0x67, 0xf5, 0xeb, 0xfc, 0x40, 0xb8, 0xc8, 0x9c, - 0xc5, 0x34, 0xf1, 0x65, 0xc3, 0x5d, 0x19, 0xc8, 0xda, 0x6c, 0x32, 0x10, 0xe9, 0x52, - 0xca, 0xd8, 0x23, 0xa7, 0x84, 0x60, 0x21, 0xc3, 0xde, 0x4a, 0x86, 0x93, 0xb7, 0x1e, - 0x28, 0x7f, 0x46, 0x86, 0xac, 0x0a, 0xdd, 0xce, 0xd9, 0x4e, 0xba, 0x81, 0x0a, 0x99, - 0x8b, 0x82, 0x3a, 0x4a, 0xd2, 0x41, 0xaa, 0x9f, 0x4a, 0x3a, 0xe4, 0x82, 0x5d, 0xe9, - 0x95, 0xdd, 0x58, 0x73, 0x56, 0x62, 0x44, 0xbb, 0xd8, 0x75, 0xd0, 0x1b, 0xf3, 0x28, - 0xe8, 0x22, 0xca, 0xfd, 0xb8, 0x3e, 0xd7, 0x75, 0x3a, 0x88, 0x85, 0xd7, 0xae, 0xf2, - 0x45, 0x5a, 0x15, 0x2e, 0x23, 0xdf, 0xa2, 0xd6, 0x99, 0xb3, 0x5c, 0x33, 0xd3, 0x61, - 0x07, 0x2a, 0xe5, 0xc5, 0x12, 0x43, 0x4d, 0x34, 0x6f, 0x6c, 0x56, 0xfb, 0x5f, 0x11, - 0xb0, 0xb6, 0x47, 0xcb, 0xca, 0xfe, 0x02, 0xd8, 0x84, 0x55, 0xa6, 0x30, 0xa3, 0x50, - 0x86, 0x2b, 0x3c, 0xd1, 0x51, 0x3b, 0x6d, 0x6e, 0x41, 0x17, 0xc7, 0x5e, 0xc4, 0xb1, - 0x2f, 0xd7, 0x5a, 0x90, 0xf8, 0x2d, 0xce, 0xa1, 0xc7, 0x71, 0xfd, 0xda, 0x24, 0xec, - 0xf0, 0xa3, 0xe5, 0xb2, 0xe8, 0xa2, 0x24, 0x23, 0x6e, 0xf0, 0x9a, 0x93, 0xab, 0x59, - 0xe5, 0x9b, 0xdf, 0xb8, 0x72, 0x86, 0x0c, 0xc2, 0xd9, 0x11, 0x34, 0xca, 0xf2, 0x13, - 0x98, 0x48, 0xe3, 0x9a, 0xa6, 0x4b, 0xa2, 0xe6, 0xd7, 0x25, 0x20, 0x54, 0xf3, 0x7a, - 0xd5, 0x5c, 0x2c, 0xe5, 0xf8, 0x1b, 0x33, 0xcc, 0xb6, 0x8a, 0x94, 0x73, 0x71, 0x24, - 0x3a, 0x77, 0xe8, 0x43, 0x67, 0xd9, 0xd3, 0x5b, 0x11, 0x68, 0x14, 0x10, 0xea, 0x79, - 0x8b, 0x03, 0x87, 0xb8, 0xf1, 0x0b, 0x1f, 0x89, 0xc6, 0x8a, 0xd1, 0xcc, 0xa9, 0xa3, - 0xe0, 0x32, 0xf3, 0x49, 0x98, 0x79, 0xc8, 0x9a, 0xe6, 0x38, 0x2f, 0x38, 0x97, 0x22, - 0x01, 0x1f, 0x49, 0x25, 0x14, 0x3e, 0xa8, 0x50, 0x73, 0xe4, 0xff, 0x0c, 0xcf, 0x6d, - 0x77, 0x9b, 0xc3, 0xbf, 0x4c, 0x1b, 0x95, 0xfc, 0x7c, 0xf7, 0xf9, 0x91, 0xa2, 0x16, - 0x2a, 0xb9, 0x45, 0x41, 0xf3, 0x99, 0x8e, 0xf6, 0xbc, 0x3f, 0xe8, 0x02, 0x54, 0xab, - 0xa4, 0x1f, 0x15, 0x23, 0x15, 0x03, 0x45, 0x1b, 0x15, 0xe1, 0x08, 0x52, 0xf8, 0x5b, - 0xd2, 0xd1, 0x15, 0x93, 0x53, 0x14, 0xcd, 0x80, 0xc1, 0x23, 0xbe, 0x0b, 0x53, 0x0f, - 0xaa, 0xd6, 0xb5, 0x07, 0x49, 0x68, 0x22, 0x1d, 0xa0, 0x4b, 0x54, 0x6d, 0x96, 0x21, - 0x63, 0x29, 0x9d, 0x52, 0xce, 0xf4, 0x1e, 0x29, 0x6d, 0xa5, 0x9c, 0xb0, 0x76, 0xdb, - 0xe8, 0x99, 0x70, 0x4b, 0x61, 0x73, 0x0c, 0x19, 0xbd, 0x22, 0x1a, 0xd2, 0xbd, 0x29, - 0x81, 0xea, 0x95, 0x1b, 0xe0, 0x2c, 0x9f, 0x5b, 0xdf, 0x92, 0xd9, 0x87, 0x07, 0x46, - 0xb2, 0xa5, 0x8c, 0x3d, 0x18, 0xa7, 0xd3, 0xe5, 0xe2, 0xc6, 0x3a, 0xc2, 0x61, 0x58, - 0x37, 0xbe, 0x1c, 0x6f, 0xe0, 0x03, 0x65, 0x6c, 0x1b, 0x3d, 0x71, 0x50, 0x5f, 0x5e, - 0x21, 0x88, 0x10, 0x4e, 0x98, 0x91, 0x1b, 0x6a, 0x5e, 0x3f, 0x52, 0x82, 0xfa, 0xc0, - 0xc8, 0xfa, 0x1b, 0xa3, 0x6f, 0xfc, 0x07, 0xdc, 0x7a, 0x40, 0x9d, 0xf2, 0xeb, 0xa8, - 0xc7, 0x5f, 0x70, 0xbd, 0x59, 0xa6, 0xf0, 0x65, 0x1d, 0xc1, 0xb1, 0xb5, 0x96, 0xde, - 0x6a, 0xce, 0xc7, 0x78, 0xe2, 0xe3, 0x2f, 0x1e, 0xd4, 0x6d, 0xf7, 0xa9, 0xae, 0xf5, - 0x1d, 0xfe, 0x5a, 0xa5, 0x24, 0x36, 0xea, 0x07, 0xf5, 0x05, 0xd3, 0x39, 0xf2, 0x03, - 0x45, 0x86, 0x61, 0xc8, 0x3a, 0x9a, 0x5a, 0x27, 0xaa, 0x48, 0xb5, 0xec, 0x47, 0xf8, - 0xd6, 0x0d, 0x2a, 0x41, 0x00, 0x1f, 0xce, 0x30, 0xff, 0x75, 0x3a, 0x8a, 0x8c, 0xe4, - 0x92, 0xef, 0xcd, 0x1f, 0x75, 0x3b, 0x7f, 0x4a, 0xd7, 0x36, 0x62, 0x64, 0x47, 0xd1, - 0xb6, 0xf0, 0x7a, 0x61, 0x7d, 0x4b, 0xfc, 0xdb, 0x48, 0xaf, 0xef, 0x08, 0x2d, 0xae, - 0x1d, 0x76, 0x54, 0x4e, 0x8b, 0x63, 0xad, 0xcb, 0xb6, 0x0e, 0x14, 0x96, 0x69, 0x32, - 0x60, 0xc7, 0x20, 0xe6, 0x72, 0x1e, 0x00, 0x20, 0xef, 0xa3, 0xf8, 0xd8, 0x8d, 0x15, - 0xb5, 0xaa, 0x48, 0xa1, 0xb2, 0x2c, + 0x6d, 0x21, 0x18, 0x0a, 0xc4, 0x74, 0x94, 0x57, 0x8a, 0x90, 0x06, 0xaf, 0x5b, 0xeb, + 0x4e, 0x34, 0x55, 0x59, 0xab, 0xdb, 0x0e, 0x23, 0xed, 0x52, 0x65, 0xaf, 0x79, 0xce, + 0x0c, 0xc5, 0x96, 0x71, 0xea, 0x31, 0x7b, 0x3e, 0xb1, 0x52, 0x93, 0xd1, 0xe0, 0x4a, + 0x9a, 0xd8, 0x39, 0x69, 0xab, 0x9e, 0x17, 0x08, 0xf2, 0x28, 0x85, 0x3a, 0x28, 0x1f, + 0xcf, 0x6c, 0x97, 0x60, 0xae, 0x71, 0x96, 0x5b, 0xb1, 0xd4, 0x45, 0x2e, 0x5e, 0xd0, + 0x06, 0x00, 0xab, 0x58, 0x94, 0x27, 0x75, 0xb7, 0x4e, 0x12, 0x62, 0xb4, 0x22, 0x5d, + 0x3b, 0x61, 0x9c, 0x31, 0x65, 0x96, 0xd7, 0xcf, 0x9c, 0x93, 0xbd, 0xb5, 0x2a, 0xfa, + 0x77, 0x8a, 0xa1, 0x20, 0x8d, 0x56, 0xd0, 0x69, 0xe5, 0x6e, 0x27, 0x79, 0x61, 0x4d, + 0x56, 0xf4, 0x36, 0x10, 0x72, 0xbc, 0x15, 0x16, 0xa9, 0xb4, 0x56, 0x2a, 0x4f, 0x54, + 0x63, 0xa5, 0x13, 0xc4, 0x59, 0x42, 0x15, 0x70, 0xf3, 0x34, 0xef, 0xb6, 0xbc, 0xd2, + 0x08, 0xf8, 0xf8, 0x05, 0x0e, 0x15, 0x3d, 0x4e, 0x61, 0xf3, 0x1e, 0xdd, 0xbb, 0x5a, + 0x98, 0xf1, 0x70, 0xd3, 0xd0, 0x80, 0xe8, 0xec, 0x3f, 0x65, 0x20, 0xb6, 0xa2, 0xd6, + 0x08, 0x83, 0xa5, 0x87, 0xff, 0x0e, 0x98, 0x21, 0x1c, 0x73, 0x45, 0x16, 0xb5, 0xdc, + 0xc7, 0x5e, 0xf2, 0x3c, 0xfb, 0x9f, 0x55, 0xf1, 0xde, 0xed, 0xf1, 0x26, 0xc2, 0xce, + 0x17, 0x27, 0x3f, 0x41, 0xdb, 0xbb, 0xbd, 0x2f, 0x49, 0xe3, 0x55, 0x77, 0x6e, 0xc0, + 0x46, 0x98, 0x35, 0xf7, 0x9d, 0x94, 0x80, 0x42, 0xf8, 0x42, 0x0f, 0x11, 0xe1, 0xab, + 0xd7, 0x45, 0x06, 0xb7, 0x8b, 0x5e, 0x41, 0xcb, 0xe0, 0xc7, 0x07, 0x17, 0xf4, 0x6e, + 0x7e, 0xb9, 0xac, 0xdc, 0x35, 0x1c, 0x94, 0x98, 0x83, 0x3a, 0xfd, 0xed, 0x93, 0x06, + 0xa0, 0x43, 0x5b, 0x10, 0xb8, 0x3a, 0xe3, 0x95, 0xd5, 0x7f, 0x5b, 0x0a, 0x5d, 0x41, + 0xa9, 0x34, 0x2d, 0x02, 0xec, 0x58, 0xb6, 0xee, 0x16, 0x87, 0x77, 0x50, 0x16, 0xb8, + 0x74, 0x9b, 0x28, 0x7a, 0xbd, 0xd3, 0xed, 0x1a, 0x83, 0x5e, 0xa8, 0xf3, 0xb1, 0x4d, + 0x08, 0x18, 0xfe, 0x0d, 0x5d, 0x9a, 0x48, 0xeb, 0x02, 0x13, 0x64, 0x0e, 0xec, 0xc1, + 0x9a, 0x5d, 0x16, 0x61, 0xdb, 0x82, 0x2b, 0x77, 0x9b, 0x08, 0x0c, 0xd8, 0xba, 0x7f, + 0x3a, 0x27, 0x23, 0x21, 0xee, 0x5d, 0xa2, 0x27, 0x8c, 0x53, 0x85, 0x67, 0xd0, 0xd9, + 0xbb, 0x28, 0xce, 0x64, 0x21, 0x31, 0x15, 0x03, 0xa4, 0xa0, 0x17, 0x14, 0xcf, 0x91, + 0x01, 0x55, 0x2b, 0xa5, 0xef, 0xc8, 0x5c, 0x94, 0xd5, 0xe5, 0x09, 0x72, 0x7e, 0x5e, + 0x01, 0x1c, 0x15, 0xb1, 0xb2, 0xec, 0xdf, 0xf3, 0x99, 0xc0, 0xbe, 0x33, 0x42, 0xab, + 0x6e, 0xdd, 0xa8, 0xe3, 0xed, 0x81, 0x1a, 0x7d, 0x9c, 0x9c, 0xa4, 0xbb, 0x71, 0xa5, + 0x63, 0xe1, 0x59, 0x78, 0xbf, 0x8e, 0x64, 0x04, 0xac, 0x79, 0x6e, 0xb7, 0x81, 0xfd, + 0x2c, 0xf2, 0x19, 0x1b, 0x2f, 0x4d, 0x40, 0x76, 0xd9, 0x3c, 0xcc, 0x80, 0xf7, 0xe5, + 0x92, 0xfa, 0x66, 0x9b, 0x72, 0x26, 0x57, 0x82, 0xee, 0x8f, 0x5c, 0xe3, 0x03, 0x12, + 0xd3, 0x51, 0x2b, 0x35, 0x49, 0x0a, 0xfe, 0x00, 0x6b, 0xad, 0xb1, 0x62, 0x0d, 0x1b, + 0x0c, 0x79, 0xfb, 0xc4, 0xbe, 0xc5, 0x65, 0xd7, 0x46, 0x1d, 0x68, 0xef, 0x72, 0x27, + 0x79, 0x11, 0x77, 0x6c, 0xd5, 0xa7, 0xb5, 0xfc, 0x6f, 0xa8, 0xb3, 0xee, 0xfd, 0x7a, + 0x39, 0xe8, 0xe5, 0xb4, 0xf6, 0xa5, 0x0c, 0x7d, 0x58, 0xd9, 0xeb, 0x08, 0x38, 0x0d, + 0x32, 0x0b, 0x36, 0xea, 0x04, 0x37, 0x00, 0xac, 0xa7, 0x64, 0xb4, 0x8c, 0x3d, 0xa4, + 0x93, 0x67, 0xfa, 0x93, 0x35, 0x6a, 0xaa, 0x4f, 0x87, 0x08, 0xea, 0x6e, 0x34, 0x59, + 0x81, 0x84, 0x5b, 0xe7, 0x37, 0x6d, 0xa7, 0x98, 0x40, 0x53, 0xef, 0x7d, 0xd4, 0xb6, + 0xa7, 0x27, 0x92, 0x35, 0x6a, 0x6c, 0x34, 0x62, 0x68, 0x88, 0xcc, 0x70, 0xde, 0x49, + 0x9e, 0xf9, 0x10, 0x26, 0x95, 0xd9, 0xdb, 0x12, 0xaf, 0x29, 0x62, 0xfc, 0x75, 0xd4, + 0x36, 0x56, 0x19, 0xdb, 0x0e, 0x87, 0x6c, 0xdb, 0x82, 0x02, 0xe8, 0x16, 0xfd, 0xc2, + 0xcd, 0xf3, 0x7a, 0xd3, 0xbe, 0x3b, ], ock: [ - 0xab, 0xd0, 0xc2, 0x46, 0x97, 0xe4, 0x5b, 0x8b, 0xc4, 0x83, 0x0f, 0xb1, 0x46, 0x53, - 0x2e, 0xa0, 0xac, 0x84, 0x55, 0x81, 0xca, 0x35, 0x39, 0xd3, 0x41, 0x24, 0x73, 0x54, - 0x09, 0xd0, 0x15, 0xac, + 0x91, 0x36, 0x59, 0x30, 0x9e, 0xcf, 0xcd, 0xfd, 0x7e, 0x0c, 0xef, 0x23, 0xf8, 0x80, + 0xae, 0x4c, 0xf4, 0xd8, 0xcf, 0x67, 0x78, 0xb9, 0xc4, 0xe6, 0xf4, 0xc7, 0x71, 0x7b, + 0xf5, 0xca, 0xf0, 0x9e, ], op: [ 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, - 0x4a, 0xd7, 0xc7, 0x84, 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, - 0xdd, 0x73, 0x4d, 0x0e, 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, - 0x22, 0xc0, 0x61, 0xe0, 0xbd, 0xc9, 0xce, 0x14, + 0x4a, 0xd7, 0xc7, 0x84, 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, + 0x4d, 0x80, 0x4a, 0x17, 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, + 0x92, 0x1c, 0xd5, 0xda, 0x8a, 0x6e, 0x1a, 0x08, ], c_out: [ - 0xea, 0xdf, 0x7e, 0xeb, 0x10, 0x2d, 0xb1, 0x88, 0x58, 0x54, 0xc2, 0x9e, 0xb7, 0xb0, - 0x5c, 0x7c, 0x96, 0xbb, 0xb8, 0x90, 0x00, 0x2c, 0x4e, 0xd1, 0x14, 0xed, 0x62, 0xf5, - 0xf9, 0xcc, 0xb4, 0x41, 0x6b, 0x5e, 0xdd, 0xd9, 0xad, 0xb5, 0x5c, 0xe9, 0xc7, 0xa0, - 0xd8, 0x44, 0x2b, 0xbc, 0x8a, 0xfa, 0x5c, 0x77, 0xb9, 0x90, 0xad, 0x6d, 0x46, 0x12, - 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, - 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, + 0x4d, 0xf8, 0xda, 0x22, 0xec, 0x17, 0xf4, 0x16, 0xe0, 0x59, 0x1a, 0xac, 0xc1, 0x6b, + 0x6d, 0xd2, 0xbb, 0xbf, 0x47, 0xbe, 0x04, 0x30, 0x3d, 0xc8, 0x85, 0xd3, 0x5a, 0xc3, + 0xf9, 0x92, 0x3e, 0xea, 0x41, 0xf3, 0x6b, 0x3a, 0x4a, 0x5c, 0x5e, 0x73, 0x3e, 0x32, + 0x6e, 0x96, 0xdb, 0xe5, 0x5e, 0xf9, 0xe7, 0xe8, 0x42, 0x27, 0x0c, 0xbf, 0x46, 0x7c, + 0xdc, 0x16, 0x0e, 0xbf, 0x4f, 0x10, 0x9a, 0xd6, 0x92, 0x0a, 0x6a, 0xed, 0x4a, 0x01, + 0x71, 0xd9, 0x06, 0xe3, 0xe8, 0x13, 0x32, 0xe6, 0xc5, 0x61, ], }, TestVector { @@ -522,29 +523,29 @@ pub(crate) fn test_vectors() -> Vec { 0xb6, 0xd3, 0x4f, 0x1e, ], cmx: [ - 0x0b, 0x74, 0x59, 0x61, 0x6f, 0xc6, 0x93, 0x95, 0xe6, 0x44, 0x36, 0xcf, 0x4a, 0xe9, - 0x44, 0x1d, 0x37, 0x4b, 0x29, 0x04, 0x9e, 0x4c, 0x86, 0x22, 0x3a, 0x03, 0x83, 0xf4, - 0xe0, 0x24, 0x69, 0x05, + 0xd8, 0x19, 0xa6, 0x37, 0x7a, 0xce, 0x33, 0xf9, 0x21, 0xf2, 0x29, 0xf9, 0x32, 0x86, + 0x6d, 0x9f, 0xcd, 0xb9, 0xd0, 0x42, 0x6a, 0xfa, 0xca, 0x9e, 0x60, 0x50, 0xb4, 0x7a, + 0x83, 0x19, 0xd6, 0x0d, ], esk: [ - 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, 0xa1, 0xc4, 0x12, 0xbc, - 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, 0x95, 0x72, 0x92, 0x93, - 0x59, 0xe0, 0x4c, 0x3a, + 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, 0xb3, 0x5d, 0xa9, 0xc6, + 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, 0xec, 0x8a, 0xd7, 0xf7, + 0x4c, 0xd9, 0xb2, 0x1b, ], ephemeral_key: [ - 0x0e, 0x04, 0xd8, 0x52, 0x5d, 0xd6, 0x8f, 0x7a, 0xe8, 0x68, 0xca, 0x81, 0x1e, 0x88, - 0x33, 0xa7, 0xf4, 0x7d, 0x7a, 0xad, 0xd3, 0x76, 0x03, 0xac, 0xe6, 0x07, 0xee, 0x6c, - 0x86, 0x6b, 0xce, 0x23, + 0x5b, 0xcb, 0xf9, 0xf1, 0xd7, 0xdd, 0x68, 0xe7, 0xcc, 0x6d, 0x6c, 0x78, 0x49, 0x50, + 0xd1, 0xc2, 0xe0, 0xbe, 0x6a, 0x84, 0xa7, 0xa8, 0x8d, 0x6f, 0x7a, 0x20, 0x98, 0xc3, + 0xdc, 0xae, 0x3f, 0x2f, ], shared_secret: [ - 0x4a, 0x7a, 0x54, 0xac, 0x00, 0x41, 0x95, 0x98, 0xb0, 0x76, 0x01, 0x53, 0xe2, 0x6a, - 0xcc, 0xd2, 0x15, 0x05, 0x24, 0x16, 0x65, 0x17, 0x13, 0xee, 0xa1, 0x89, 0x19, 0xf3, - 0xe2, 0x62, 0xd3, 0xb6, + 0x37, 0x35, 0x1c, 0xe2, 0x57, 0xb2, 0x79, 0x4d, 0x86, 0xa5, 0x3d, 0x26, 0x8d, 0xc9, + 0x00, 0x06, 0x40, 0xc2, 0x76, 0xf3, 0xf4, 0x65, 0xe1, 0xaa, 0x70, 0xbf, 0xde, 0xf4, + 0x99, 0xa3, 0xd7, 0xaa, ], k_enc: [ - 0x30, 0x62, 0x6d, 0x92, 0xeb, 0x62, 0x0f, 0xd4, 0xa9, 0x28, 0xb4, 0x3f, 0xd5, 0x50, - 0x69, 0x74, 0x71, 0x76, 0x7d, 0xe4, 0x49, 0x6c, 0xfd, 0xad, 0xb1, 0xda, 0x18, 0xfc, - 0x0c, 0xdd, 0x5a, 0xa6, + 0xea, 0x22, 0x99, 0x65, 0x39, 0xd3, 0x74, 0xda, 0x6a, 0x75, 0x34, 0x39, 0x5a, 0xe9, + 0x23, 0x36, 0xfc, 0xa7, 0x85, 0x11, 0x20, 0xdd, 0x1a, 0xe4, 0x9e, 0x45, 0xb3, 0x3e, + 0x0b, 0xed, 0xe9, 0xac, ], p_enc: [ 0x02, 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, 0x47, 0xee, @@ -590,68 +591,68 @@ pub(crate) fn test_vectors() -> Vec { 0x55, 0x21, 0x93, 0xb1, ], c_enc: [ - 0x81, 0x56, 0x2d, 0xbe, 0xf7, 0xbb, 0x35, 0x3a, 0x62, 0xe7, 0xc8, 0x1e, 0xbe, 0x68, - 0x15, 0x6c, 0xb7, 0x5c, 0x5c, 0x7e, 0x3d, 0x96, 0xbb, 0xcd, 0x7d, 0xaf, 0xf5, 0x0c, - 0xb0, 0x95, 0x7d, 0x33, 0xdd, 0x99, 0x77, 0x9f, 0x7d, 0x3d, 0x72, 0xb1, 0x8d, 0xeb, - 0x7a, 0x69, 0x75, 0x10, 0xe0, 0x13, 0x5b, 0x8d, 0xf4, 0x83, 0xa4, 0xd7, 0x1d, 0x1a, - 0xb1, 0x08, 0x09, 0x6e, 0x76, 0x08, 0x91, 0xd5, 0x31, 0x07, 0xf0, 0x3d, 0xea, 0x4a, - 0xe8, 0xe4, 0xd3, 0xfe, 0xbd, 0x98, 0x77, 0xf8, 0x57, 0x0a, 0xa3, 0x09, 0xd0, 0x97, - 0xd4, 0x23, 0xbb, 0x76, 0x3f, 0xb3, 0xe7, 0xe9, 0xbe, 0x3c, 0x8f, 0xa0, 0x34, 0xc0, - 0x1d, 0x66, 0x4f, 0x47, 0xa0, 0xe7, 0x13, 0x3c, 0xa1, 0x1a, 0x48, 0xcd, 0x0e, 0xea, - 0x46, 0x35, 0xfa, 0x77, 0x25, 0x0a, 0x17, 0xbd, 0xf7, 0xb7, 0x32, 0xc8, 0x98, 0x46, - 0x51, 0x57, 0x4f, 0xd4, 0xf9, 0x9f, 0x7a, 0xa0, 0xdb, 0x28, 0xc2, 0x97, 0x31, 0x52, - 0xbf, 0x42, 0x6e, 0xe9, 0xa4, 0xd8, 0x41, 0xa9, 0x1d, 0x5d, 0x33, 0x57, 0x18, 0xee, - 0xcb, 0xc9, 0xc8, 0xb2, 0xa2, 0x00, 0x15, 0x70, 0xfe, 0x8b, 0x77, 0x91, 0x43, 0xdf, - 0x22, 0x95, 0x98, 0xa5, 0xbe, 0x25, 0x48, 0xcf, 0x35, 0x84, 0x25, 0x18, 0xcc, 0x1d, - 0xbc, 0x78, 0xcc, 0x2f, 0x0f, 0xc8, 0xea, 0x35, 0x7c, 0xe6, 0xc1, 0x7e, 0xb9, 0x7c, - 0x61, 0x38, 0xd5, 0x3e, 0x6c, 0x8e, 0x00, 0xf0, 0x7f, 0x80, 0x01, 0x25, 0x18, 0x2b, - 0x25, 0xa5, 0xe8, 0x75, 0xc5, 0x37, 0x72, 0x09, 0x52, 0x72, 0x22, 0x37, 0x1f, 0x72, - 0xbf, 0xbd, 0x46, 0x28, 0x44, 0xab, 0x06, 0xf3, 0xb3, 0xa1, 0xeb, 0xa3, 0x44, 0x23, - 0xb6, 0x9a, 0xbf, 0x5d, 0xe6, 0x64, 0xba, 0x83, 0xcd, 0x43, 0xb6, 0xa8, 0xe9, 0xd5, - 0xb7, 0xc5, 0x2a, 0xdb, 0x86, 0x15, 0x04, 0x1b, 0x90, 0xd9, 0x08, 0x83, 0x1a, 0x6f, - 0xf9, 0x2d, 0xb4, 0x8a, 0x14, 0xac, 0x4d, 0xfa, 0x67, 0xd0, 0x2c, 0x72, 0xe0, 0xc8, - 0x63, 0x15, 0x7d, 0x98, 0xf8, 0xf5, 0x45, 0x37, 0x92, 0x97, 0x43, 0xc9, 0x69, 0xbc, - 0x91, 0xc2, 0xc1, 0x37, 0x52, 0x04, 0x98, 0x3c, 0x99, 0x99, 0x97, 0x5f, 0xfa, 0x5e, - 0xe5, 0xfe, 0x1f, 0x69, 0x71, 0x99, 0x40, 0x5f, 0x09, 0x66, 0xe3, 0x1f, 0x34, 0xe1, - 0x52, 0x38, 0x44, 0x38, 0x18, 0x44, 0x98, 0x2b, 0x2c, 0x3b, 0x49, 0xa2, 0x09, 0xff, - 0xa3, 0xce, 0xe9, 0x79, 0xa8, 0x5b, 0x19, 0xb8, 0x50, 0xf4, 0x1d, 0xcc, 0xc4, 0x63, - 0xe2, 0x2e, 0x24, 0xa3, 0x04, 0x9d, 0x37, 0xb1, 0xfb, 0x37, 0x0d, 0xeb, 0xdd, 0xf4, - 0xde, 0x05, 0x46, 0x24, 0x5e, 0x4f, 0x02, 0xa9, 0x84, 0x98, 0xaf, 0x53, 0x2e, 0x27, - 0xac, 0xae, 0x5c, 0x7e, 0xd1, 0x43, 0xe6, 0xe9, 0xcc, 0xfa, 0x74, 0x35, 0x16, 0x02, - 0x16, 0x57, 0xac, 0xb2, 0x5e, 0x44, 0x47, 0x84, 0x5c, 0x5f, 0x9c, 0x59, 0x64, 0x60, - 0x7c, 0x4a, 0x78, 0x72, 0x1d, 0x98, 0x1a, 0x7f, 0xf2, 0xfd, 0xf6, 0xc0, 0x33, 0x62, - 0x8b, 0xff, 0xd6, 0xf0, 0xb8, 0xde, 0x0c, 0xd6, 0x35, 0xec, 0x22, 0xf8, 0xb5, 0x0e, - 0xd6, 0x37, 0xfe, 0x4e, 0x00, 0xf9, 0xd3, 0xc3, 0xd4, 0xf1, 0x81, 0x0b, 0x09, 0xb7, - 0x5c, 0x96, 0xe2, 0xfc, 0xf1, 0x11, 0x85, 0x31, 0x7e, 0xdf, 0xa3, 0x9d, 0x19, 0x25, - 0xde, 0xd8, 0x14, 0xdd, 0xe0, 0xef, 0x00, 0xa3, 0xfb, 0x47, 0xaf, 0x5d, 0x81, 0x20, - 0x94, 0xaf, 0x13, 0xd0, 0x1c, 0x98, 0x56, 0x9f, 0xf7, 0x73, 0x57, 0x87, 0xfa, 0x9b, - 0xd0, 0x1f, 0xa0, 0x69, 0x28, 0x27, 0x5f, 0xdd, 0x10, 0x38, 0x96, 0x5f, 0xb0, 0x6f, - 0xb3, 0x5e, 0xdb, 0x73, 0x80, 0xdd, 0x3c, 0x42, 0x41, 0x9e, 0x0c, 0x0e, 0xde, 0x4c, - 0x48, 0x6a, 0x9d, 0xb4, 0x95, 0x38, 0x86, 0xae, 0xc6, 0xad, 0x30, 0x70, 0x28, 0xeb, - 0x26, 0xa3, 0x7e, 0xf4, 0x71, 0x56, 0x7a, 0xd4, 0xbd, 0x4e, 0xaa, 0xb7, 0xa8, 0x2c, - 0xb0, 0xd6, 0xb5, 0xf0, 0x5e, 0x89, 0x4e, 0x53, 0x25, 0x82, 0x1d, 0x92, 0xbe, 0xd2, - 0xb8, 0x6f, 0xb2, 0x43, 0x37, 0xd5, 0x79, 0x28, 0x8f, 0x6d, 0xf7, 0x34, 0x77, 0x1d, - 0x9e, 0xf8, 0x35, 0x8b, 0xa9, 0x1a, + 0x12, 0xd6, 0x64, 0xed, 0x05, 0xd6, 0x46, 0x26, 0x89, 0xd4, 0xf2, 0x4a, 0xee, 0x5a, + 0x4f, 0x0f, 0x32, 0x35, 0xff, 0x11, 0x0b, 0x2d, 0xf9, 0x9f, 0x67, 0xd8, 0xc5, 0xb3, + 0x68, 0xdd, 0x47, 0x69, 0xd8, 0x44, 0xd3, 0xdd, 0xa0, 0x3f, 0x58, 0xc5, 0x48, 0x63, + 0x62, 0xe8, 0x90, 0x81, 0xa5, 0xdf, 0xd0, 0xa6, 0x06, 0xa3, 0x91, 0x26, 0x4b, 0x56, + 0xca, 0x3a, 0xfc, 0x4f, 0xe0, 0xe4, 0xc3, 0x05, 0xf3, 0x07, 0x78, 0x09, 0x4a, 0x00, + 0xb7, 0x33, 0x4b, 0xdd, 0x82, 0x45, 0xac, 0x56, 0x0e, 0xf3, 0x29, 0xbc, 0x68, 0x97, + 0xd4, 0xd7, 0xba, 0x31, 0xac, 0x84, 0x54, 0x44, 0x1a, 0x15, 0xc8, 0xd3, 0xce, 0xcc, + 0x71, 0x32, 0xdf, 0x0d, 0x9d, 0x0e, 0xcf, 0x92, 0x84, 0x34, 0xa0, 0xd2, 0x8c, 0x1b, + 0x00, 0x48, 0x52, 0x01, 0xec, 0x33, 0xbe, 0x9a, 0x28, 0x74, 0xb4, 0x29, 0x6c, 0x04, + 0x22, 0xc7, 0xe7, 0xa0, 0xa3, 0xa2, 0x2e, 0xc7, 0xe7, 0x21, 0xa4, 0x79, 0x22, 0x8d, + 0xa2, 0x8b, 0x47, 0x37, 0xaf, 0x52, 0x06, 0xdf, 0x7d, 0x74, 0xe4, 0x84, 0xc4, 0xf7, + 0xa8, 0x56, 0xbe, 0x8c, 0xd0, 0x4b, 0x21, 0x26, 0xb5, 0x27, 0x11, 0xe7, 0xb0, 0xaf, + 0x75, 0xc7, 0x52, 0x84, 0xa1, 0x57, 0x20, 0x40, 0xe8, 0xad, 0xe5, 0x85, 0xe8, 0xa4, + 0x82, 0x80, 0x03, 0x59, 0x67, 0x46, 0xc4, 0x0c, 0x9d, 0x76, 0x0d, 0x92, 0x74, 0xb1, + 0x25, 0x42, 0x2b, 0x63, 0x48, 0x1a, 0x17, 0xff, 0xba, 0xb8, 0xc2, 0xde, 0x13, 0xb2, + 0x19, 0xf5, 0x8a, 0x35, 0x95, 0x2d, 0x88, 0x7a, 0xed, 0xe8, 0xe0, 0x2f, 0x10, 0x33, + 0x8c, 0x23, 0x98, 0x23, 0xfb, 0x43, 0x49, 0x51, 0x84, 0x47, 0x12, 0xf6, 0x8d, 0x6e, + 0x4f, 0xef, 0xae, 0x2b, 0x79, 0x5b, 0xa9, 0x78, 0xe9, 0x81, 0xc1, 0x09, 0x27, 0xab, + 0xbc, 0x16, 0x30, 0x66, 0xa0, 0xe9, 0x60, 0xb3, 0xb8, 0xa3, 0x26, 0xc0, 0x39, 0x85, + 0x81, 0x10, 0x93, 0x99, 0xf6, 0xed, 0x60, 0x44, 0x9a, 0xa8, 0x58, 0xd5, 0xdd, 0x27, + 0xdb, 0xf8, 0x89, 0x9f, 0x9c, 0x9a, 0x50, 0x20, 0x5f, 0x25, 0xd0, 0xcc, 0x50, 0xb2, + 0xde, 0xe3, 0x63, 0x54, 0xc5, 0xe4, 0x48, 0x4d, 0x36, 0xf6, 0x3c, 0x97, 0x63, 0xd8, + 0x41, 0xad, 0x5e, 0x00, 0x21, 0x63, 0x6a, 0x85, 0x7c, 0xfb, 0x79, 0xa5, 0x12, 0x3c, + 0x3d, 0xfb, 0x77, 0x3d, 0x0c, 0x1b, 0xeb, 0x9f, 0x90, 0xa9, 0x72, 0xd0, 0xfc, 0x80, + 0x5f, 0x65, 0x5d, 0x69, 0x40, 0x85, 0x23, 0xb9, 0x9b, 0x62, 0xa8, 0xfa, 0xbe, 0xf0, + 0xc0, 0x24, 0xf2, 0x1f, 0x50, 0xe4, 0xc1, 0x12, 0xe2, 0xfe, 0xdd, 0x58, 0xca, 0xe9, + 0x60, 0x9a, 0xc6, 0xf7, 0xcc, 0x79, 0x83, 0x86, 0xc9, 0xd9, 0x06, 0x42, 0x1c, 0xa5, + 0x7c, 0xf8, 0x1b, 0x09, 0x6b, 0xba, 0xda, 0x64, 0xd0, 0xee, 0x76, 0x95, 0x18, 0x9d, + 0x5f, 0xb1, 0x7a, 0xe2, 0x53, 0x1d, 0xbb, 0x2c, 0x00, 0x58, 0x5a, 0x26, 0xa6, 0x8c, + 0x27, 0xf9, 0x77, 0x77, 0x84, 0x1a, 0x3e, 0x39, 0x30, 0xc7, 0x0f, 0xc3, 0xfa, 0x8e, + 0x2b, 0x7f, 0xc2, 0x1e, 0x87, 0xcf, 0x9f, 0x63, 0xb3, 0x63, 0xb8, 0x8d, 0xaa, 0x1f, + 0xb6, 0x7b, 0xda, 0xe8, 0xe5, 0x5b, 0x68, 0x51, 0x6d, 0x19, 0xdf, 0xef, 0xec, 0x9b, + 0x3d, 0x38, 0xe6, 0xe1, 0xd0, 0xa6, 0xe4, 0x51, 0xd6, 0xd1, 0xf5, 0x2d, 0x1f, 0x96, + 0xdd, 0x0d, 0x53, 0x6d, 0x68, 0xd2, 0x69, 0x86, 0x70, 0x9f, 0x41, 0xe7, 0x60, 0x74, + 0x05, 0x5b, 0xf7, 0x52, 0xbf, 0x38, 0x86, 0x92, 0xc8, 0x2c, 0xfd, 0xa1, 0xeb, 0xb0, + 0x17, 0x8b, 0x8e, 0x0c, 0x85, 0xad, 0x7b, 0x15, 0x99, 0x14, 0x42, 0x8e, 0x30, 0x21, + 0xda, 0xe3, 0x01, 0x0d, 0x65, 0x6c, 0x10, 0x36, 0xf4, 0xa5, 0x7e, 0x7f, 0xad, 0xe0, + 0xfc, 0x32, 0x2a, 0xa6, 0xfd, 0xde, 0x71, 0x4a, 0x8c, 0x53, 0x78, 0x79, 0xe7, 0x04, + 0x41, 0x6f, 0x51, 0x04, 0xdb, 0xbc, 0x8f, 0xf2, 0x42, 0xc1, 0x6d, 0x2d, 0xf4, 0xa8, + 0x41, 0xeb, 0x6b, 0x45, 0x3a, 0x12, 0x83, 0xf6, 0x5f, 0xe1, 0x0d, 0x70, 0xc8, 0x76, + 0x41, 0x8e, 0x44, 0x4a, 0xb3, 0x1b, 0x93, 0x71, 0xa2, 0x7d, 0x36, 0xd8, 0x6e, 0x8f, + 0x1c, 0x32, 0x77, 0xca, 0xfd, 0xf8, ], ock: [ - 0xb6, 0x36, 0xc3, 0x9a, 0x6b, 0xad, 0x22, 0x63, 0xb2, 0x44, 0x1e, 0xd5, 0xbb, 0xdb, - 0x01, 0x35, 0x88, 0xfb, 0x46, 0x27, 0x01, 0xe6, 0xf8, 0x76, 0x64, 0x6c, 0x8c, 0x17, - 0xfa, 0x2e, 0xfd, 0xe8, + 0xca, 0x6f, 0x98, 0xe6, 0xcf, 0x9f, 0xc3, 0x6a, 0xf5, 0xf6, 0x98, 0x82, 0x74, 0x2d, + 0x06, 0xec, 0x5d, 0x29, 0xac, 0x2a, 0x02, 0x89, 0x44, 0xa2, 0x01, 0x89, 0xd5, 0x1c, + 0x8a, 0x9b, 0xdc, 0xd6, ], op: [ 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, - 0x15, 0x37, 0x14, 0x0d, 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, - 0xa1, 0xc4, 0x12, 0xbc, 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, - 0x95, 0x72, 0x92, 0x93, 0x59, 0xe0, 0x4c, 0x3a, + 0x15, 0x37, 0x14, 0x0d, 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, + 0xb3, 0x5d, 0xa9, 0xc6, 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, + 0xec, 0x8a, 0xd7, 0xf7, 0x4c, 0xd9, 0xb2, 0x1b, ], c_out: [ - 0x46, 0xba, 0x14, 0xf8, 0x3f, 0xf5, 0xab, 0x76, 0x0f, 0x14, 0x20, 0xeb, 0xde, 0xd9, - 0x86, 0xfd, 0x93, 0x78, 0x27, 0xbc, 0x05, 0x69, 0x2e, 0xca, 0xdb, 0x65, 0x2e, 0xbb, - 0xc8, 0xf6, 0xd9, 0xb5, 0x2e, 0xc3, 0x97, 0x87, 0xd8, 0xeb, 0xdd, 0x50, 0x6c, 0xa1, - 0xa8, 0x5d, 0xc3, 0xd5, 0xba, 0x4c, 0x5b, 0x41, 0x52, 0x61, 0xb0, 0x75, 0x3a, 0xc1, - 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, - 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, + 0xa9, 0x5e, 0x1a, 0x22, 0x45, 0x65, 0x29, 0x5e, 0x9b, 0x55, 0x3a, 0xdd, 0xe8, 0xb0, + 0x14, 0x47, 0x5c, 0x68, 0x7b, 0x5d, 0x13, 0x49, 0xc1, 0xdf, 0x8a, 0xd4, 0xb7, 0xcf, + 0xd3, 0xdf, 0xc1, 0x00, 0x6c, 0x7c, 0x37, 0xde, 0x67, 0x6d, 0x6f, 0xde, 0x31, 0x8e, + 0x2f, 0xdf, 0xcc, 0x2e, 0x2e, 0x23, 0x2c, 0xc5, 0xf8, 0x85, 0x28, 0x39, 0xe7, 0xef, + 0xab, 0x8b, 0x20, 0x0e, 0xbc, 0x6a, 0x4d, 0xf8, 0x2a, 0x75, 0x21, 0xce, 0x0f, 0x38, + 0x4f, 0xe2, 0x7a, 0x0d, 0xec, 0x59, 0xe9, 0xd2, 0xc0, 0xe3, ], }, TestVector { @@ -732,29 +733,29 @@ pub(crate) fn test_vectors() -> Vec { 0xba, 0x03, 0x39, 0x26, ], cmx: [ - 0x05, 0xb5, 0xe3, 0x20, 0x76, 0xda, 0xe0, 0x94, 0x83, 0x35, 0xac, 0x3d, 0x65, 0x1c, - 0x6d, 0xbe, 0xa6, 0x4c, 0xe9, 0x11, 0x42, 0x3e, 0x2f, 0x2c, 0x7c, 0x1b, 0xdf, 0xa6, - 0xb1, 0x41, 0x41, 0x30, + 0x23, 0xad, 0xc3, 0xbf, 0x35, 0x0e, 0xb0, 0x84, 0xbd, 0x28, 0xbc, 0x2d, 0xcf, 0xb7, + 0x98, 0x3f, 0xf6, 0xb3, 0xb6, 0xf2, 0xeb, 0x2d, 0x6f, 0x12, 0x4f, 0xfc, 0x46, 0x85, + 0xab, 0xe8, 0xde, 0x3a, ], esk: [ - 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, 0xfe, 0x47, 0x9a, 0x1e, - 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, 0x92, 0x3a, 0x5d, 0x00, - 0xcb, 0x52, 0xa6, 0x13, + 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, 0x2c, 0xf1, 0xb8, 0x88, + 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, 0x98, 0x02, 0xf1, 0x53, + 0x6a, 0x9e, 0x9f, 0x2b, ], ephemeral_key: [ - 0x86, 0xee, 0x66, 0xa6, 0xc7, 0xd9, 0xb5, 0xc4, 0xf0, 0xe2, 0xd2, 0xa0, 0xe1, 0x56, - 0x1e, 0x2a, 0xfa, 0x55, 0x41, 0xa7, 0x24, 0xee, 0x02, 0x7f, 0xc7, 0x0b, 0xb7, 0xe8, - 0x0a, 0x2c, 0x60, 0x98, + 0x91, 0xaf, 0x13, 0x8e, 0xd9, 0x95, 0x44, 0x66, 0x95, 0x16, 0x1b, 0x14, 0x2d, 0xc2, + 0xde, 0x59, 0xac, 0x23, 0x05, 0xec, 0xbe, 0xc6, 0x29, 0x33, 0xf5, 0x2f, 0x2a, 0xa1, + 0xf9, 0xb2, 0x71, 0x86, ], shared_secret: [ - 0x88, 0xd1, 0x38, 0x2c, 0x14, 0x42, 0x02, 0xd0, 0xd7, 0x55, 0x75, 0x87, 0xb0, 0xd5, - 0xd0, 0x21, 0x69, 0x29, 0x2a, 0x25, 0x05, 0x43, 0xcb, 0x0a, 0x06, 0xc3, 0x4f, 0x45, - 0x2f, 0x7b, 0x3b, 0x36, + 0xe1, 0xd3, 0xaf, 0x73, 0x6a, 0xb9, 0xc6, 0x11, 0x6f, 0x46, 0x8f, 0x91, 0x66, 0x80, + 0x63, 0x20, 0x35, 0x0f, 0x7e, 0x73, 0x51, 0x3b, 0xa6, 0x05, 0x50, 0xeb, 0x2d, 0xf0, + 0x1f, 0xf7, 0x83, 0x2d, ], k_enc: [ - 0xe3, 0x73, 0xd8, 0x6e, 0xc9, 0xdd, 0xdd, 0x64, 0x5d, 0x9a, 0x6d, 0x06, 0xef, 0xce, - 0x22, 0xb8, 0x96, 0x42, 0x1d, 0x57, 0xa4, 0x4d, 0x37, 0xa6, 0x50, 0x4a, 0x5d, 0x19, - 0xdf, 0x21, 0x73, 0x73, + 0xb4, 0x3e, 0x43, 0x3e, 0x16, 0x45, 0xeb, 0x51, 0x5e, 0x4a, 0x4c, 0x7d, 0x10, 0xc9, + 0x3d, 0x08, 0xf2, 0xf1, 0xc3, 0x30, 0x95, 0xbf, 0x8c, 0x80, 0x0a, 0x04, 0x17, 0x62, + 0xab, 0x5c, 0xf8, 0x2c, ], p_enc: [ 0x02, 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, 0xfa, 0x3f, @@ -800,68 +801,68 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x65, 0x57, 0x53, ], c_enc: [ - 0xe7, 0x67, 0x81, 0xae, 0x63, 0x84, 0x1f, 0xff, 0xea, 0x30, 0x21, 0x96, 0x15, 0x94, - 0xc2, 0x2a, 0x87, 0x20, 0xc7, 0xd8, 0xaa, 0x80, 0x8b, 0xc8, 0x6e, 0x71, 0xa3, 0x6a, - 0xd7, 0xf8, 0x6f, 0xf8, 0x7c, 0x07, 0xd3, 0xc6, 0x50, 0xa0, 0x8e, 0x23, 0xe9, 0xb5, - 0x4f, 0x00, 0xb4, 0x0b, 0xa0, 0x15, 0x91, 0x69, 0xdf, 0xca, 0x34, 0xc1, 0x40, 0xce, - 0x93, 0x40, 0x19, 0xb2, 0xea, 0xa8, 0xea, 0x84, 0x35, 0x80, 0xb3, 0x5f, 0x14, 0xea, - 0x51, 0x92, 0xde, 0x8a, 0x12, 0xf9, 0xab, 0xc9, 0x06, 0x10, 0x15, 0xe1, 0x47, 0x9e, - 0xf9, 0x8d, 0x19, 0xa5, 0x34, 0xe9, 0xe4, 0x61, 0x64, 0xc3, 0xca, 0xc4, 0xeb, 0x54, - 0x26, 0x4c, 0xed, 0xcd, 0x83, 0xaf, 0xc2, 0xac, 0x2e, 0x08, 0x7e, 0x39, 0xdf, 0xba, - 0xe7, 0x6b, 0xd5, 0x50, 0xcc, 0x64, 0xa4, 0x04, 0xd2, 0x0c, 0x22, 0xca, 0x00, 0x3b, - 0xf7, 0x5b, 0x12, 0xfb, 0xb8, 0xc7, 0x15, 0x13, 0x72, 0x70, 0x0b, 0x43, 0x9b, 0x3e, - 0x06, 0x57, 0xec, 0xc3, 0x07, 0x70, 0x8f, 0xc3, 0x74, 0x94, 0xbd, 0x06, 0x39, 0xe8, - 0xe1, 0xea, 0xea, 0x37, 0x8f, 0x27, 0xa1, 0x35, 0x74, 0xb7, 0x1f, 0xa4, 0x88, 0x3b, - 0x80, 0x71, 0x2c, 0x7b, 0xeb, 0x5c, 0x30, 0x5f, 0x8d, 0x67, 0xe9, 0x19, 0x97, 0xf8, - 0x03, 0x19, 0xdd, 0xb1, 0x15, 0xb9, 0x51, 0x23, 0x89, 0x7a, 0xae, 0x5f, 0x2d, 0x14, - 0xff, 0xcf, 0xac, 0x7f, 0x65, 0x49, 0xca, 0x54, 0x8f, 0x6e, 0xab, 0xdf, 0x74, 0x81, - 0x70, 0x27, 0xd4, 0x2d, 0x92, 0xd5, 0xcd, 0xf8, 0x8e, 0xd8, 0xd5, 0x11, 0xd1, 0xb5, - 0xc4, 0x32, 0x2f, 0x77, 0x79, 0x74, 0x88, 0x6c, 0x0e, 0xd0, 0x13, 0x99, 0x18, 0x0a, - 0xfa, 0x59, 0x7d, 0xd2, 0xb7, 0x7c, 0x58, 0xb2, 0x7c, 0x8a, 0x61, 0x20, 0x69, 0xe3, - 0x86, 0xad, 0x63, 0x4c, 0xb0, 0x17, 0xa8, 0xe9, 0xf4, 0x8e, 0x37, 0xc4, 0x3e, 0xe8, - 0x73, 0x3a, 0x0a, 0xcb, 0x69, 0xf8, 0xed, 0x9f, 0x6f, 0x30, 0x5f, 0x3b, 0xd1, 0xe9, - 0x82, 0xb9, 0x4b, 0x1e, 0x51, 0xf4, 0xba, 0x98, 0x5b, 0x20, 0xec, 0x97, 0x4a, 0xc9, - 0xa7, 0x93, 0xaa, 0x26, 0x4d, 0x61, 0x5b, 0x9d, 0xea, 0x48, 0x59, 0xa4, 0xd4, 0xca, - 0xa7, 0x0d, 0x7a, 0x6b, 0x65, 0x30, 0x76, 0x85, 0xab, 0x53, 0x4e, 0x54, 0x55, 0x63, - 0x1f, 0x6d, 0x68, 0xa4, 0x51, 0xd8, 0xaf, 0x2d, 0x41, 0x82, 0x52, 0x80, 0x0f, 0x68, - 0x42, 0x31, 0xaf, 0xc2, 0x6d, 0x1f, 0xef, 0xc4, 0x03, 0xd7, 0x5f, 0x2e, 0x12, 0x0f, - 0x5b, 0xe2, 0xb6, 0x74, 0x48, 0x60, 0x09, 0x26, 0x7c, 0xbc, 0x0c, 0xb0, 0x01, 0xbb, - 0x47, 0xf0, 0xff, 0x46, 0x97, 0xea, 0xf5, 0x3d, 0xc9, 0x9c, 0x10, 0x77, 0x3a, 0x38, - 0xcd, 0x06, 0xb4, 0x8b, 0xa3, 0x91, 0x19, 0xdb, 0x49, 0x84, 0xd0, 0x9a, 0x5b, 0xde, - 0x13, 0x89, 0x0e, 0xa0, 0x61, 0x3d, 0x0c, 0xe0, 0x04, 0x3e, 0xae, 0x9a, 0x20, 0x89, - 0x14, 0x1f, 0xd9, 0x46, 0x59, 0x13, 0xc1, 0xcc, 0x33, 0x27, 0xa5, 0x59, 0x42, 0xb9, - 0xfd, 0x8f, 0xb8, 0x1c, 0x84, 0x7d, 0x8f, 0xdd, 0xf8, 0xbd, 0xba, 0xcf, 0xa0, 0xfb, - 0x05, 0x52, 0xc1, 0xfe, 0x4c, 0xc4, 0xc0, 0x7f, 0x4d, 0xcf, 0x15, 0x1c, 0x5e, 0x74, - 0xe8, 0xd6, 0x9b, 0x2b, 0x8b, 0xf7, 0xfd, 0x95, 0xec, 0xeb, 0x65, 0x5e, 0x00, 0x53, - 0x58, 0x16, 0xd3, 0x8b, 0x4a, 0x28, 0xd4, 0xa9, 0xae, 0xeb, 0xb6, 0x9a, 0xb4, 0xdd, - 0x12, 0xbf, 0x13, 0xfd, 0x5a, 0x45, 0x9b, 0x6b, 0xb6, 0x83, 0xff, 0xd9, 0xdd, 0x7b, - 0x0d, 0x0c, 0xe7, 0x29, 0x67, 0x75, 0x80, 0x8a, 0x84, 0x3f, 0x3b, 0x8c, 0xc7, 0x89, - 0xfd, 0x5f, 0x43, 0xe0, 0x84, 0xd8, 0x7d, 0x6a, 0xda, 0x8d, 0x1f, 0x28, 0xc2, 0x64, - 0xe6, 0x44, 0xe9, 0xad, 0x96, 0x5c, 0x28, 0x08, 0x8a, 0x52, 0xe4, 0xb3, 0x56, 0x42, - 0xf9, 0xb5, 0xe0, 0x66, 0x49, 0x90, 0x96, 0x3b, 0xc2, 0x3b, 0x9b, 0xb4, 0x8f, 0x46, - 0x74, 0x73, 0x53, 0x58, 0x0e, 0xcc, 0x45, 0x20, 0xcf, 0xf1, 0xfa, 0x7f, 0x8f, 0xbc, - 0x03, 0x0e, 0x64, 0x7d, 0xf1, 0x44, 0xee, 0x6c, 0xa5, 0xb3, 0x16, 0xb3, 0xaf, 0x90, - 0x48, 0x9a, 0x80, 0x9d, 0x9c, 0x9f, + 0x27, 0x62, 0x0d, 0xf5, 0xdb, 0x17, 0x76, 0x6e, 0xbd, 0x9a, 0x99, 0xd6, 0x9a, 0x9a, + 0x49, 0x38, 0x73, 0x21, 0xf0, 0xc9, 0x47, 0x25, 0x23, 0x57, 0xb5, 0xb7, 0x48, 0x49, + 0x38, 0xe3, 0xf5, 0xff, 0x9f, 0x32, 0x0e, 0x80, 0x6c, 0x4b, 0x54, 0xc3, 0x6e, 0x41, + 0x2e, 0x8a, 0x6e, 0xad, 0xe3, 0x5b, 0x83, 0x01, 0xf7, 0x34, 0xf3, 0x71, 0x2e, 0x6a, + 0xac, 0xe6, 0x99, 0xf5, 0x9e, 0x11, 0x2a, 0x7b, 0xf5, 0x44, 0x59, 0xdc, 0x5d, 0x9f, + 0x7b, 0xbf, 0x3b, 0x9f, 0x74, 0x6c, 0x45, 0xbb, 0xed, 0x69, 0xa4, 0x25, 0x1b, 0x29, + 0xf3, 0xd2, 0x15, 0xc2, 0x9f, 0x76, 0x1c, 0x7d, 0x05, 0x88, 0x19, 0xf0, 0xdd, 0x4e, + 0x70, 0x71, 0xb0, 0x77, 0xcb, 0x00, 0xcb, 0x93, 0x62, 0xa4, 0x98, 0x16, 0x88, 0x0d, + 0x49, 0xb7, 0x11, 0xf9, 0x20, 0x65, 0xf1, 0x53, 0x2e, 0x58, 0x18, 0x0b, 0xbd, 0xb4, + 0x91, 0xdb, 0xbb, 0x96, 0x8a, 0x09, 0xb5, 0x63, 0xce, 0x1d, 0x29, 0x87, 0x6f, 0xd0, + 0x52, 0x6d, 0x65, 0xda, 0x67, 0x27, 0xad, 0x40, 0xf9, 0x64, 0x02, 0xf9, 0x9a, 0xa5, + 0xac, 0x06, 0x42, 0x51, 0xc4, 0x65, 0xe3, 0xc7, 0xdb, 0x1f, 0xfe, 0xef, 0xac, 0xd7, + 0xf5, 0x1b, 0xa4, 0xf1, 0x9c, 0x6c, 0x17, 0x87, 0xa0, 0xff, 0xb4, 0x9d, 0xbb, 0x7b, + 0x0a, 0x2b, 0x15, 0x64, 0x03, 0xd6, 0x6c, 0x22, 0x13, 0xe5, 0x1d, 0x58, 0xea, 0xef, + 0xe8, 0x6d, 0x5d, 0xef, 0x0d, 0x24, 0xb7, 0xf2, 0xf8, 0xc1, 0x10, 0x32, 0x9a, 0x3a, + 0x73, 0xcb, 0x33, 0x50, 0x14, 0x0e, 0x6b, 0xf7, 0x2c, 0xb6, 0xaa, 0x22, 0x2d, 0xef, + 0x5a, 0x47, 0xe2, 0x1a, 0xf0, 0xb9, 0xae, 0xeb, 0x74, 0x8c, 0x01, 0xc6, 0x7a, 0xb6, + 0xc9, 0xfd, 0x6e, 0x53, 0x6a, 0x0d, 0x92, 0x76, 0x61, 0x51, 0xb1, 0xac, 0x7c, 0xc9, + 0x85, 0x5c, 0xa9, 0x8d, 0xea, 0x74, 0x85, 0x14, 0xef, 0xee, 0x89, 0xe8, 0x9a, 0x01, + 0x68, 0xf5, 0xdd, 0xf4, 0xac, 0x2b, 0x7c, 0xe1, 0xc9, 0xc2, 0x92, 0xfb, 0xef, 0x2f, + 0x45, 0x51, 0xa8, 0x88, 0xc3, 0x34, 0x5c, 0x65, 0x92, 0x30, 0x39, 0xfc, 0x21, 0xf7, + 0x31, 0x55, 0x9b, 0xd9, 0x24, 0xbc, 0x2c, 0x15, 0x5b, 0xc0, 0xbe, 0x80, 0x38, 0x4a, + 0x9e, 0x49, 0xbd, 0xa6, 0x9a, 0x70, 0x6b, 0x1a, 0xd6, 0xa2, 0x62, 0xab, 0xc6, 0x26, + 0x50, 0x77, 0x2f, 0xd7, 0xea, 0xbc, 0x3f, 0x75, 0xa9, 0xac, 0xca, 0xa2, 0x8b, 0xcd, + 0xea, 0x65, 0xf9, 0x4e, 0x16, 0xcc, 0x3d, 0x05, 0x38, 0xe5, 0x49, 0x86, 0x0a, 0x60, + 0x12, 0x5b, 0xb4, 0xbc, 0x0c, 0x23, 0xe3, 0x22, 0x27, 0x68, 0x2c, 0x09, 0xb5, 0xaa, + 0x30, 0x4a, 0x16, 0x09, 0x2a, 0xd4, 0xa3, 0xe2, 0xf6, 0x28, 0x3c, 0x38, 0x51, 0x80, + 0x6e, 0x72, 0x17, 0x3f, 0x7d, 0x32, 0x97, 0xed, 0x92, 0xe5, 0x32, 0x40, 0x39, 0xa7, + 0x31, 0x4f, 0x5f, 0xb7, 0x38, 0x6e, 0x09, 0x94, 0xf5, 0x2f, 0x8c, 0xcc, 0xf1, 0x87, + 0xd6, 0x20, 0x41, 0x0c, 0xce, 0x9d, 0x0b, 0x91, 0x93, 0xac, 0xec, 0x6d, 0x4c, 0x9b, + 0xd3, 0x4e, 0x08, 0x80, 0x58, 0x0a, 0xbe, 0xae, 0xd9, 0x7c, 0xb7, 0x80, 0x0f, 0x6a, + 0xbc, 0x67, 0xc2, 0x5c, 0x49, 0x19, 0x2e, 0x37, 0xdc, 0xf3, 0x3d, 0x1a, 0x59, 0x16, + 0x47, 0x5a, 0xe9, 0x99, 0x90, 0xd8, 0x29, 0xc1, 0xd5, 0x9e, 0x69, 0x2f, 0x47, 0x36, + 0x93, 0xbc, 0xe3, 0x58, 0x5a, 0xec, 0xd3, 0xc1, 0x3b, 0xae, 0x15, 0xcb, 0xef, 0xf2, + 0x98, 0x52, 0x2a, 0xab, 0xf4, 0x6b, 0xea, 0x3a, 0xbf, 0x63, 0x30, 0xa5, 0x6e, 0x37, + 0x24, 0x51, 0x81, 0x32, 0xce, 0x94, 0x39, 0x41, 0x6a, 0x28, 0xe9, 0x52, 0x0d, 0xdf, + 0x64, 0x17, 0x00, 0xb4, 0x6f, 0x37, 0x49, 0x50, 0xf3, 0x27, 0xaf, 0x3d, 0x0b, 0x3d, + 0x3b, 0x3f, 0x61, 0xa8, 0x84, 0xcf, 0x4f, 0x82, 0x02, 0x56, 0xfb, 0x91, 0x65, 0xdc, + 0xa0, 0xe4, 0x32, 0x60, 0xfc, 0xb5, 0x63, 0xef, 0x1a, 0xb4, 0xe7, 0x12, 0xef, 0x07, + 0x23, 0xd6, 0x75, 0x90, 0xa4, 0xff, 0xc3, 0x66, 0xc4, 0xa7, 0x92, 0x50, 0x29, 0x93, + 0x1b, 0xf0, 0x87, 0x3d, 0xac, 0xaa, 0xe9, 0x38, 0x5d, 0x9a, 0xd9, 0x1a, 0xed, 0x75, + 0x93, 0x9d, 0x8b, 0xd1, 0xaf, 0x5d, ], ock: [ - 0x85, 0x6e, 0x1a, 0x97, 0x09, 0xb0, 0xc4, 0x16, 0x93, 0x3f, 0x59, 0x70, 0x71, 0x5c, - 0x56, 0xe2, 0xe0, 0x5c, 0x2e, 0xa9, 0x7d, 0x81, 0x51, 0x25, 0x70, 0x14, 0x79, 0xc3, - 0x3a, 0x5d, 0x91, 0xcb, + 0x2a, 0xec, 0x11, 0xd4, 0xae, 0x79, 0x84, 0xe1, 0x69, 0xd1, 0xdf, 0xf1, 0xff, 0x0f, + 0x9a, 0xf5, 0x19, 0x96, 0x34, 0x51, 0xa4, 0x1c, 0x9f, 0x5a, 0xdc, 0x58, 0xe4, 0xf9, + 0x0a, 0xf3, 0x8d, 0x47, ], op: [ 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, - 0x14, 0x93, 0x16, 0x36, 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, - 0xfe, 0x47, 0x9a, 0x1e, 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, - 0x92, 0x3a, 0x5d, 0x00, 0xcb, 0x52, 0xa6, 0x13, + 0x14, 0x93, 0x16, 0x36, 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, + 0x2c, 0xf1, 0xb8, 0x88, 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, + 0x98, 0x02, 0xf1, 0x53, 0x6a, 0x9e, 0x9f, 0x2b, ], c_out: [ - 0x72, 0x36, 0xea, 0xb9, 0xf0, 0x12, 0x98, 0xc8, 0x4f, 0x38, 0x28, 0xf6, 0xac, 0x15, - 0x42, 0x76, 0xb5, 0xb7, 0x64, 0x62, 0xf5, 0x74, 0x2d, 0x69, 0xdc, 0x47, 0x7a, 0x10, - 0x5d, 0xc2, 0x71, 0x1b, 0x12, 0xe9, 0xb5, 0x82, 0x8c, 0x01, 0x76, 0xfe, 0xf4, 0x4a, - 0x54, 0x0f, 0x60, 0x95, 0x8e, 0x5a, 0x3e, 0xd6, 0xa2, 0xcc, 0x5e, 0xdd, 0xe9, 0x13, - 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, - 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, + 0xe6, 0xeb, 0x22, 0x47, 0xc9, 0x33, 0xe2, 0x4c, 0x9d, 0xf1, 0x28, 0xb1, 0xe0, 0x4e, + 0x8b, 0xc0, 0x5c, 0x65, 0xeb, 0x31, 0x97, 0xdf, 0x9b, 0xa8, 0x70, 0xd8, 0xa0, 0xa1, + 0x8d, 0x9c, 0x24, 0xb7, 0xc9, 0x78, 0xc3, 0x4d, 0x3c, 0x7b, 0xbd, 0x21, 0xe8, 0x7b, + 0x22, 0x39, 0x21, 0x87, 0x54, 0xd9, 0x67, 0x3a, 0x56, 0xa2, 0x73, 0x58, 0x0f, 0x6b, + 0x41, 0xc6, 0x91, 0xe5, 0xfd, 0x30, 0x9c, 0xd5, 0xd1, 0xd2, 0x6d, 0x57, 0x63, 0xa9, + 0xe8, 0xd2, 0x71, 0xc9, 0x77, 0x05, 0x0e, 0x05, 0xdc, 0x96, ], }, TestVector { @@ -942,29 +943,29 @@ pub(crate) fn test_vectors() -> Vec { 0x9d, 0xc1, 0x08, 0x1c, ], cmx: [ - 0xea, 0x7c, 0x13, 0xf7, 0xe1, 0x20, 0x5e, 0x78, 0xc8, 0xce, 0x4e, 0xe4, 0xfd, 0xcd, - 0xb7, 0xee, 0x76, 0x92, 0x8d, 0xdf, 0x6d, 0xbe, 0x1b, 0x2d, 0x6f, 0x69, 0x81, 0xb7, - 0xc9, 0x65, 0x79, 0x10, + 0xe3, 0x04, 0xcf, 0x08, 0xc7, 0x86, 0xaf, 0xcb, 0x1d, 0x65, 0x2f, 0x7a, 0x94, 0x17, + 0x29, 0x32, 0x01, 0x51, 0x71, 0x37, 0x93, 0x82, 0x89, 0x42, 0xcb, 0x88, 0xd0, 0x1f, + 0x68, 0x60, 0x4e, 0x1f, ], esk: [ - 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, 0x73, 0xe9, 0x05, 0x99, - 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, 0x89, 0xcc, 0x63, 0x00, - 0x06, 0x15, 0xb2, 0x0d, + 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, 0x40, 0xaf, 0x89, 0x3e, + 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, 0x6b, 0x5e, 0xd1, 0xf6, + 0xbf, 0x62, 0xbe, 0x3c, ], ephemeral_key: [ - 0x89, 0xfd, 0x2c, 0xf3, 0x79, 0x56, 0xba, 0xaf, 0x11, 0x27, 0xbb, 0x0e, 0x33, 0x40, - 0x01, 0x09, 0xdb, 0x03, 0x50, 0xf4, 0xab, 0xb7, 0xd6, 0xd8, 0x1f, 0xa5, 0x84, 0x8e, - 0x1b, 0xb1, 0x69, 0x26, + 0xdf, 0xe0, 0xf0, 0x0e, 0xb2, 0xb2, 0xf7, 0x08, 0x04, 0x19, 0x1b, 0x5b, 0x2d, 0xdf, + 0x57, 0x8f, 0x6a, 0xda, 0x21, 0x1b, 0x8b, 0x41, 0x7d, 0x95, 0xd2, 0xb7, 0x34, 0xff, + 0xa2, 0x2d, 0x81, 0x30, ], shared_secret: [ - 0xdb, 0xa6, 0x37, 0x94, 0xb6, 0x7c, 0x49, 0x6d, 0x01, 0x1c, 0xfb, 0x6b, 0xba, 0x29, - 0x7c, 0xa5, 0x7d, 0x18, 0xc7, 0xa9, 0xad, 0xdf, 0xfb, 0xc8, 0x37, 0x17, 0x6a, 0xcf, - 0x3a, 0x30, 0x1e, 0x23, + 0x0e, 0xc6, 0x82, 0xc8, 0xdc, 0x66, 0x41, 0x41, 0x02, 0x4f, 0x92, 0x9d, 0x1a, 0xe5, + 0xd3, 0x9c, 0x39, 0x4d, 0x05, 0xa2, 0x4d, 0xad, 0x0e, 0x4a, 0x6f, 0x94, 0x98, 0xed, + 0x5f, 0x87, 0xd4, 0x88, ], k_enc: [ - 0x80, 0xe7, 0x52, 0x2c, 0xb0, 0x32, 0x51, 0xc8, 0x55, 0x34, 0x1f, 0x06, 0xf9, 0x41, - 0x33, 0x41, 0xe1, 0x6e, 0x83, 0xb4, 0x89, 0xe1, 0x5a, 0x0a, 0x00, 0x65, 0xc3, 0x3b, - 0xf3, 0x81, 0x58, 0xc4, + 0xb1, 0x24, 0x5f, 0xb6, 0x37, 0x47, 0xc0, 0x13, 0x39, 0xcd, 0xe8, 0xf9, 0x35, 0x98, + 0xdf, 0xb2, 0xd3, 0x99, 0xec, 0x5e, 0x03, 0xbe, 0xa1, 0x3f, 0x3d, 0xbf, 0x01, 0xca, + 0xdb, 0x93, 0xc9, 0xba, ], p_enc: [ 0x02, 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, 0x7e, 0x65, @@ -1010,68 +1011,68 @@ pub(crate) fn test_vectors() -> Vec { 0xd7, 0x6b, 0xa4, 0x80, ], c_enc: [ - 0x3f, 0x4e, 0x9b, 0x18, 0x56, 0xe7, 0xbf, 0xba, 0x7a, 0xbb, 0xc9, 0x4a, 0x72, 0xb4, - 0xab, 0xb1, 0xd8, 0x46, 0x26, 0x79, 0x30, 0x77, 0xe8, 0x37, 0xda, 0xf3, 0x3f, 0xff, - 0xa2, 0x7c, 0x7a, 0x33, 0x97, 0x8a, 0x54, 0x32, 0x51, 0x0d, 0x99, 0x3c, 0x7d, 0x92, - 0x24, 0xc0, 0x97, 0xac, 0xc5, 0x25, 0x88, 0x1c, 0x76, 0x08, 0x3c, 0x1b, 0x65, 0x1a, - 0x9d, 0xe1, 0xb5, 0xc1, 0xa6, 0xe0, 0x48, 0x2f, 0xae, 0x8f, 0x98, 0x6a, 0xb5, 0x9f, - 0xa7, 0xcd, 0x43, 0x98, 0x99, 0x6e, 0x2b, 0xc0, 0x3a, 0xdc, 0xa9, 0x90, 0x32, 0x3b, - 0xaa, 0xbd, 0xda, 0xae, 0x40, 0xb0, 0x56, 0xb7, 0xac, 0x17, 0xf8, 0x20, 0xd1, 0x1c, - 0x0d, 0xec, 0xba, 0x14, 0xf2, 0x57, 0xa6, 0xcf, 0x09, 0x18, 0x19, 0x8f, 0x38, 0x9c, - 0xdb, 0x29, 0x55, 0x77, 0x25, 0x96, 0x92, 0x7c, 0xbf, 0x55, 0x88, 0x56, 0x13, 0x35, - 0xe7, 0xd6, 0x2e, 0x6a, 0x8a, 0xf7, 0xbc, 0x33, 0xb9, 0x9a, 0x55, 0xaf, 0xa1, 0xb7, - 0xef, 0x20, 0xeb, 0x4e, 0xd6, 0xde, 0x89, 0x69, 0xd2, 0x9f, 0x04, 0x21, 0xcd, 0x4d, - 0x99, 0x06, 0x66, 0xfd, 0xcf, 0x1e, 0xbd, 0x09, 0x06, 0x57, 0x02, 0x13, 0x4d, 0x31, - 0xc3, 0x29, 0x26, 0xa3, 0x8b, 0x6b, 0x6b, 0x48, 0xfd, 0xc9, 0xb3, 0xc7, 0x64, 0xc3, - 0xcd, 0x95, 0xb9, 0x72, 0xe7, 0x68, 0xeb, 0xd8, 0xaa, 0xe9, 0x0d, 0x6a, 0x4a, 0x98, - 0xb2, 0xd9, 0x2f, 0xd9, 0xdf, 0xa2, 0xa2, 0x99, 0xd0, 0x60, 0xe8, 0x5e, 0xf5, 0x68, - 0x3f, 0x51, 0xd0, 0x51, 0x4a, 0x6e, 0xba, 0x72, 0x57, 0x3f, 0x7b, 0xae, 0x84, 0xa2, - 0xfd, 0x92, 0xbe, 0x64, 0x24, 0x1c, 0x27, 0xa6, 0xe5, 0xce, 0xac, 0xbf, 0x37, 0xb2, - 0xd9, 0xa9, 0x75, 0xdf, 0x7a, 0xee, 0xbb, 0xa1, 0x4d, 0x8c, 0x81, 0x15, 0x8e, 0xcf, - 0x5a, 0x0a, 0x25, 0xe1, 0x2f, 0x98, 0x5d, 0x08, 0xfb, 0xb4, 0xa1, 0xc1, 0x3f, 0x76, - 0x1f, 0x3f, 0xfe, 0xe8, 0xd5, 0x38, 0xe3, 0x93, 0xf3, 0x58, 0x0b, 0x73, 0x82, 0xcd, - 0x0b, 0xf5, 0x17, 0xce, 0x78, 0x87, 0x1c, 0x19, 0xac, 0xf8, 0xca, 0x06, 0x5d, 0x7c, - 0x83, 0x87, 0xce, 0xcd, 0x0d, 0x37, 0xae, 0x21, 0x7f, 0x44, 0x06, 0x94, 0x77, 0x2a, - 0xbd, 0x4b, 0x36, 0x55, 0x56, 0x85, 0x4b, 0xaa, 0x8b, 0xcc, 0xa9, 0xc4, 0xfe, 0xf7, - 0x18, 0x99, 0x12, 0xf9, 0x8a, 0x25, 0x27, 0x68, 0x92, 0x76, 0xa4, 0x00, 0x8c, 0x83, - 0x8f, 0xe7, 0x4f, 0x7c, 0x2b, 0x75, 0x9f, 0xc2, 0xab, 0x7a, 0xfe, 0x37, 0x82, 0x80, - 0x6e, 0x31, 0xb1, 0xc5, 0x30, 0xcc, 0x46, 0x20, 0x3b, 0xb3, 0xa5, 0x66, 0xca, 0xf4, - 0xd1, 0x5b, 0x99, 0x40, 0xb4, 0x3f, 0x33, 0xa8, 0x6a, 0x65, 0xd4, 0x9d, 0xa8, 0xb6, - 0x78, 0x7d, 0xe0, 0x96, 0x38, 0xb4, 0x81, 0xf3, 0xa8, 0x10, 0x8a, 0x96, 0x9e, 0xca, - 0xdf, 0x90, 0x98, 0xbf, 0xf2, 0x14, 0x0c, 0x4b, 0x42, 0xe2, 0xb0, 0xfb, 0x10, 0xb9, - 0x02, 0x89, 0xb0, 0xc6, 0xdb, 0x8b, 0xc0, 0x85, 0xe8, 0xaf, 0xe9, 0x5d, 0xd3, 0x6a, - 0x45, 0x36, 0xea, 0xd7, 0xe9, 0x5c, 0x99, 0x66, 0x2c, 0xd9, 0x28, 0xc2, 0x2c, 0x3e, - 0xbf, 0x39, 0x79, 0x15, 0x78, 0xbc, 0x66, 0xfe, 0xa3, 0x01, 0x4d, 0x22, 0x92, 0x94, - 0x30, 0x83, 0xe7, 0x46, 0x81, 0x24, 0x52, 0xb0, 0x0b, 0xc2, 0xf3, 0xe4, 0x7c, 0x49, - 0x47, 0x46, 0xce, 0xd5, 0x57, 0xb1, 0x3a, 0xe3, 0x03, 0x0d, 0x8a, 0x95, 0x78, 0x10, - 0x2b, 0xba, 0xd2, 0xfc, 0x3b, 0x84, 0x5f, 0x31, 0xae, 0x16, 0xf8, 0xd8, 0x0b, 0x77, - 0xf8, 0x43, 0x15, 0x84, 0xa3, 0x7e, 0x8f, 0x30, 0xb0, 0xb9, 0x5c, 0xc4, 0x55, 0x5a, - 0xbc, 0x05, 0x3a, 0x0b, 0x4f, 0xf9, 0x13, 0xb0, 0x03, 0x69, 0xf1, 0x74, 0x7b, 0x1f, - 0x1c, 0x0a, 0xc8, 0x75, 0x4f, 0x01, 0x7e, 0x99, 0x47, 0xca, 0x63, 0x25, 0x5b, 0x3c, - 0x23, 0xf4, 0x56, 0xe2, 0x3f, 0x96, 0x76, 0x13, 0x99, 0x60, 0x1f, 0xd8, 0xda, 0xdb, - 0x5e, 0x3f, 0x90, 0xab, 0x1b, 0x20, 0x13, 0x81, 0x80, 0xed, 0x69, 0x73, 0x22, 0x39, - 0xc8, 0xc2, 0x15, 0xd9, 0xcc, 0x8a, 0xc8, 0x05, 0x9b, 0xde, 0x81, 0x63, 0x27, 0xd2, - 0x20, 0xb9, 0xa8, 0xec, 0xba, 0x5d, + 0x31, 0xec, 0x78, 0xd4, 0x02, 0x14, 0xc1, 0xbc, 0x7b, 0x25, 0x94, 0x7b, 0x42, 0xf3, + 0x54, 0x34, 0x60, 0x72, 0x90, 0x27, 0x7c, 0x44, 0xc4, 0x89, 0xe9, 0x38, 0x72, 0x2f, + 0x7c, 0x12, 0xff, 0x55, 0xc4, 0xf1, 0xdf, 0xbe, 0x0f, 0x1a, 0x65, 0xb1, 0x5c, 0x0c, + 0xc4, 0x7a, 0x46, 0xc9, 0xbb, 0x33, 0x5b, 0xd1, 0xa3, 0xe7, 0xe6, 0x62, 0xee, 0x85, + 0x84, 0x57, 0x6b, 0x6f, 0x42, 0x81, 0x95, 0xc9, 0x8c, 0x72, 0xfb, 0x99, 0x75, 0xc7, + 0x17, 0x9c, 0x4c, 0xab, 0x58, 0x66, 0xf5, 0xb4, 0x85, 0x42, 0x8b, 0x50, 0x8e, 0x2e, + 0x05, 0xbe, 0x0c, 0x98, 0x41, 0xa3, 0xa2, 0x91, 0x12, 0x80, 0x2c, 0x52, 0x15, 0xe2, + 0x51, 0x37, 0xcf, 0xdd, 0x13, 0x8c, 0x99, 0x39, 0x0e, 0xfb, 0xce, 0xb7, 0x52, 0x4e, + 0x84, 0x7c, 0x36, 0xb4, 0x3f, 0x3e, 0xde, 0x32, 0xf2, 0x3b, 0x39, 0x81, 0xf6, 0xd3, + 0xc3, 0x2b, 0x17, 0xbb, 0xbe, 0x65, 0xf2, 0xfd, 0x01, 0xab, 0xdd, 0x99, 0x87, 0xf1, + 0xb8, 0x88, 0xeb, 0xef, 0x41, 0xef, 0x45, 0x55, 0xc9, 0xfb, 0x0c, 0x8a, 0xee, 0x9b, + 0x6d, 0xd0, 0x85, 0xb9, 0xfb, 0xc7, 0x4f, 0xe4, 0x6a, 0x1e, 0x36, 0x3d, 0x68, 0x32, + 0xb5, 0x08, 0x20, 0x0e, 0x50, 0x0d, 0xa6, 0x95, 0x13, 0xb7, 0x9e, 0x81, 0xf7, 0x33, + 0xb6, 0x6c, 0x3f, 0x24, 0x3a, 0x28, 0x5b, 0xf8, 0x6f, 0xfe, 0xef, 0x4f, 0xfd, 0x1c, + 0xac, 0xa7, 0x83, 0x07, 0x26, 0x63, 0xbf, 0x9b, 0x48, 0x7f, 0xbc, 0x3e, 0x7f, 0x5a, + 0xd2, 0xf7, 0xac, 0xbf, 0x2b, 0x6e, 0x00, 0x8e, 0x3e, 0x4d, 0x6f, 0x31, 0xe1, 0x14, + 0x75, 0xe1, 0x96, 0x98, 0x9d, 0xb9, 0x62, 0x8a, 0x5d, 0x56, 0x39, 0x7c, 0x9a, 0x04, + 0x2a, 0xab, 0x55, 0xe1, 0xec, 0xc4, 0x92, 0xfe, 0x94, 0x27, 0xd4, 0x90, 0xf2, 0x73, + 0xb6, 0x01, 0xd6, 0x51, 0x05, 0x56, 0x82, 0xd3, 0x5b, 0x30, 0x75, 0xfa, 0xda, 0x85, + 0x25, 0x84, 0x48, 0x14, 0x95, 0x7f, 0xfc, 0x9b, 0xc7, 0xfb, 0x39, 0x39, 0x73, 0x7b, + 0x01, 0x50, 0x2e, 0x0b, 0x6f, 0x1f, 0x9b, 0x88, 0xf2, 0x71, 0x54, 0x80, 0xae, 0x42, + 0x2e, 0x9b, 0xb7, 0xb7, 0x6e, 0x5d, 0x22, 0xde, 0x0d, 0x3d, 0x7a, 0xea, 0x58, 0x10, + 0x01, 0xdc, 0xf4, 0x6a, 0x62, 0x2f, 0x08, 0x03, 0x10, 0xbe, 0x50, 0xdf, 0x07, 0x75, + 0x21, 0x92, 0xd4, 0xe4, 0x1a, 0xc5, 0x18, 0xe4, 0x24, 0x1e, 0x06, 0x67, 0x76, 0xa8, + 0xea, 0xec, 0xc7, 0x42, 0xfd, 0x2c, 0x1b, 0xf0, 0x6f, 0xc5, 0x8b, 0xd2, 0x8d, 0x1d, + 0x6c, 0x60, 0x1f, 0x91, 0x5d, 0x75, 0x2e, 0x7c, 0xc3, 0xd9, 0x76, 0x3c, 0x8b, 0x9e, + 0xec, 0x14, 0x2c, 0x84, 0x81, 0xf9, 0xc5, 0x23, 0x59, 0xbf, 0xbf, 0x51, 0x24, 0x36, + 0x67, 0x84, 0xe1, 0x71, 0xd7, 0xa4, 0xaa, 0x01, 0x5e, 0x85, 0x56, 0x47, 0x4a, 0x6d, + 0x0f, 0xee, 0x69, 0xb0, 0xd5, 0x3e, 0xe7, 0xf4, 0xed, 0xf5, 0xea, 0x59, 0xfa, 0x55, + 0x97, 0xf4, 0x8d, 0xd6, 0xaa, 0x88, 0x51, 0x84, 0x29, 0xac, 0x8c, 0x18, 0xc4, 0x73, + 0x8d, 0xb8, 0x01, 0x09, 0xa5, 0xe4, 0xbc, 0x81, 0xbb, 0x84, 0xb3, 0x7d, 0x9b, 0x2a, + 0xd4, 0xb1, 0xd2, 0x6b, 0x36, 0x3d, 0x16, 0x60, 0x72, 0xf0, 0x8c, 0x56, 0x70, 0x62, + 0x27, 0xa9, 0xf8, 0x32, 0x97, 0x03, 0x70, 0x12, 0xd1, 0xf6, 0xda, 0x24, 0xa8, 0x69, + 0xeb, 0x32, 0x97, 0xbc, 0xbc, 0xcc, 0x8d, 0x7d, 0xed, 0x03, 0x0a, 0x3d, 0x60, 0xdf, + 0x88, 0x82, 0xe0, 0x62, 0x9e, 0x36, 0x14, 0x3c, 0x09, 0xca, 0x05, 0x21, 0x43, 0xcb, + 0x56, 0x62, 0x93, 0x8f, 0xa9, 0xf1, 0x15, 0xdd, 0xc0, 0x96, 0x65, 0x4c, 0x0b, 0x40, + 0x59, 0x4c, 0xba, 0x19, 0xee, 0xd4, 0x99, 0x53, 0x2b, 0x70, 0x8a, 0xde, 0xbe, 0x47, + 0x72, 0x6a, 0x83, 0xaf, 0x46, 0x3c, 0x80, 0xba, 0x2a, 0x1f, 0xe0, 0x71, 0xe1, 0x66, + 0xc4, 0x4d, 0x70, 0xdd, 0xbb, 0xba, 0x67, 0x06, 0xa1, 0xdc, 0x43, 0x27, 0x26, 0xfe, + 0x0f, 0xdb, 0xc6, 0x28, 0x21, 0xb5, 0x04, 0xea, 0x11, 0x66, 0xda, 0x48, 0xa8, 0x1b, + 0x63, 0x5e, 0x37, 0x63, 0x33, 0xd9, 0xbe, 0xfe, 0xc4, 0x93, 0xa0, 0x7d, 0xf4, 0x7b, + 0xba, 0x0a, 0x2e, 0x2f, 0x65, 0xe7, ], ock: [ - 0xe6, 0xb7, 0x05, 0x50, 0xe1, 0xd7, 0xa2, 0xbe, 0x73, 0x04, 0x39, 0x64, 0x41, 0xec, - 0x6a, 0xc0, 0x47, 0x45, 0x99, 0xf9, 0xea, 0xd7, 0x55, 0xc2, 0xcf, 0x27, 0x6b, 0x87, - 0x50, 0xc5, 0xcf, 0x2d, + 0xec, 0xa3, 0x70, 0x7a, 0x74, 0x5d, 0x5d, 0x58, 0x65, 0x86, 0xb2, 0x35, 0xf2, 0x92, + 0xad, 0x20, 0x48, 0x93, 0x14, 0xc4, 0x58, 0x80, 0xd9, 0x83, 0x2b, 0x7f, 0x47, 0xee, + 0xbb, 0xd4, 0x5c, 0xfe, ], op: [ 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, - 0x03, 0x8e, 0x3d, 0xb3, 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, - 0x73, 0xe9, 0x05, 0x99, 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, - 0x89, 0xcc, 0x63, 0x00, 0x06, 0x15, 0xb2, 0x0d, + 0x03, 0x8e, 0x3d, 0xb3, 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, + 0x40, 0xaf, 0x89, 0x3e, 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, + 0x6b, 0x5e, 0xd1, 0xf6, 0xbf, 0x62, 0xbe, 0x3c, ], c_out: [ - 0x02, 0xb1, 0x37, 0x3e, 0xb1, 0x89, 0x56, 0x32, 0x2b, 0x47, 0xa1, 0x70, 0x0d, 0xb7, - 0x43, 0x31, 0x6e, 0xde, 0x46, 0x44, 0xd6, 0x59, 0x3c, 0xd7, 0x94, 0x22, 0xd7, 0x51, - 0x3d, 0x1b, 0x80, 0xe6, 0x85, 0x05, 0xdf, 0xe9, 0xd6, 0x86, 0x2e, 0x79, 0x4e, 0x30, - 0x28, 0x8b, 0xae, 0xa8, 0xb0, 0xbc, 0xb3, 0x8b, 0x35, 0x49, 0x77, 0xaa, 0xee, 0x57, - 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, - 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, + 0xd0, 0x65, 0x9a, 0x03, 0xc5, 0x3e, 0x15, 0xdc, 0x11, 0x01, 0xa6, 0x6e, 0xa8, 0x0d, + 0xf4, 0x14, 0x4d, 0x5e, 0xe0, 0x1c, 0x3d, 0xbf, 0x20, 0x2c, 0xe6, 0x08, 0x7e, 0x96, + 0xa8, 0x5a, 0xe1, 0x39, 0xdd, 0x46, 0xfc, 0x82, 0xa1, 0xc3, 0x7d, 0x06, 0x05, 0xf8, + 0x49, 0x98, 0x53, 0x13, 0x16, 0xf1, 0xf0, 0xcb, 0xc0, 0x4e, 0xa2, 0x0a, 0xa4, 0x04, + 0xb3, 0xd5, 0xb0, 0x42, 0x96, 0x01, 0x49, 0x81, 0x6d, 0x9b, 0x8f, 0x06, 0x2a, 0xfc, + 0xc1, 0x93, 0x89, 0x43, 0x82, 0x7a, 0x1b, 0x43, 0xfc, 0xbd, ], }, TestVector { @@ -1152,29 +1153,29 @@ pub(crate) fn test_vectors() -> Vec { 0xef, 0x13, 0xb8, 0x17, ], cmx: [ - 0x18, 0xfc, 0xbd, 0x40, 0xac, 0xf1, 0xa7, 0xf4, 0xd6, 0x09, 0x87, 0x9a, 0x5f, 0x5e, - 0x3b, 0x39, 0x70, 0x09, 0x4f, 0xf8, 0xbe, 0x84, 0x18, 0x60, 0x70, 0x16, 0xc6, 0xa6, - 0x97, 0xf8, 0x9c, 0x20, + 0xad, 0xc2, 0x44, 0x3a, 0xf9, 0x57, 0x67, 0x47, 0xca, 0x4f, 0x10, 0x4b, 0x1f, 0x5a, + 0x7a, 0xdc, 0x80, 0x5a, 0xc5, 0x5a, 0xcc, 0x56, 0x33, 0xa0, 0xb3, 0xc2, 0xdc, 0x7a, + 0xad, 0xff, 0x21, 0x26, ], esk: [ - 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, 0x6b, 0x8d, 0x6f, 0xea, - 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, 0xd5, 0xcb, 0xab, 0x1a, - 0xcc, 0xd5, 0x4e, 0x3a, + 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, 0x82, 0x35, 0x16, 0x58, + 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, 0xb0, 0x52, 0xd5, 0xb4, + 0x20, 0x41, 0xd8, 0x1c, ], ephemeral_key: [ - 0xcf, 0xe0, 0x3e, 0xb2, 0xd3, 0x36, 0x76, 0xb7, 0x73, 0x83, 0x7d, 0xa8, 0x39, 0x17, - 0x2d, 0x33, 0x33, 0x31, 0x88, 0xc9, 0xdf, 0xef, 0x05, 0xc8, 0x32, 0xa2, 0x5c, 0x86, - 0xd3, 0xbf, 0x0e, 0x8f, + 0x00, 0x5d, 0x31, 0x5b, 0xd1, 0x80, 0xa2, 0x94, 0x0b, 0xd7, 0xfb, 0x34, 0xa7, 0x0e, + 0x90, 0xe8, 0x32, 0x6c, 0xb1, 0x34, 0x30, 0x66, 0x05, 0x46, 0x53, 0xd2, 0x64, 0x4d, + 0x20, 0x45, 0xe3, 0x0f, ], shared_secret: [ - 0xd2, 0xc2, 0x88, 0x9e, 0x03, 0x7e, 0xac, 0x60, 0x60, 0x58, 0x68, 0x2b, 0xaa, 0x38, - 0x86, 0xa4, 0xc2, 0xdd, 0x44, 0xea, 0xdf, 0x8b, 0x2c, 0xe4, 0x39, 0x95, 0xde, 0xd7, - 0x61, 0xfd, 0xaf, 0xb5, + 0x8e, 0x59, 0x0d, 0x06, 0x3f, 0x7e, 0xc3, 0x8e, 0xb2, 0x00, 0x84, 0x70, 0xf9, 0xbb, + 0x42, 0x29, 0x04, 0xfc, 0x0b, 0xaf, 0x97, 0x80, 0xf8, 0xfd, 0x1f, 0x54, 0x22, 0xea, + 0x30, 0x8c, 0x47, 0xba, ], k_enc: [ - 0xfe, 0xe3, 0xe3, 0xb5, 0xfd, 0x6c, 0xd8, 0x54, 0x44, 0x2b, 0x2a, 0xc2, 0x97, 0x70, - 0xfb, 0x0e, 0x39, 0x32, 0xf4, 0x71, 0x52, 0x43, 0x26, 0xda, 0x4a, 0x57, 0xc2, 0x56, - 0x18, 0x06, 0x9e, 0x99, + 0xeb, 0xb2, 0xff, 0x9b, 0x1f, 0x29, 0x0d, 0xa5, 0x63, 0x27, 0xa9, 0x67, 0x71, 0xb2, + 0x5f, 0x71, 0x29, 0xff, 0x10, 0x2e, 0xe6, 0xd2, 0xb2, 0x0d, 0xa0, 0x9a, 0x06, 0x25, + 0xf8, 0xbb, 0x26, 0x07, ], p_enc: [ 0x02, 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, 0x91, 0x20, @@ -1220,68 +1221,68 @@ pub(crate) fn test_vectors() -> Vec { 0x34, 0x1e, 0x4e, 0x6f, ], c_enc: [ - 0xbe, 0x1d, 0xff, 0xd3, 0x37, 0x0c, 0x67, 0x56, 0x69, 0xcc, 0x9a, 0xe1, 0xd0, 0x30, - 0x2d, 0x7f, 0x90, 0x6d, 0x25, 0x23, 0x09, 0x3c, 0x24, 0xf4, 0x25, 0x7a, 0x83, 0xbc, - 0x4f, 0x36, 0x62, 0x3a, 0x08, 0x2c, 0xe6, 0xeb, 0x45, 0x21, 0x95, 0x71, 0x91, 0xd5, - 0x7e, 0x14, 0x11, 0xed, 0xe7, 0x1d, 0x44, 0xb5, 0x6c, 0x57, 0xcb, 0x22, 0x81, 0x4a, - 0x04, 0x69, 0x39, 0xd2, 0xff, 0xf9, 0x2b, 0x46, 0x62, 0x76, 0x2d, 0x4f, 0x21, 0xc0, - 0x78, 0x42, 0x74, 0x72, 0xb9, 0x18, 0x10, 0x10, 0x55, 0x56, 0xf4, 0xde, 0x0a, 0x27, - 0xe7, 0x70, 0x08, 0x47, 0x72, 0xcb, 0xfe, 0xbf, 0x87, 0xdb, 0x33, 0x14, 0xab, 0x70, - 0xf2, 0x6d, 0x11, 0xea, 0x5d, 0xe2, 0x67, 0xc3, 0xa9, 0xa8, 0xf4, 0x6b, 0xad, 0x13, - 0xc7, 0x36, 0x26, 0x10, 0xbd, 0xba, 0x81, 0x02, 0xd4, 0xb7, 0x26, 0xef, 0x26, 0xec, - 0x79, 0x4a, 0x15, 0x66, 0x57, 0x1b, 0xfd, 0xc1, 0x02, 0x47, 0x7d, 0xa5, 0xb4, 0x9b, - 0xbf, 0x9f, 0xe4, 0xb1, 0xa4, 0x4e, 0xd0, 0xb3, 0xbc, 0xed, 0x99, 0xba, 0x81, 0x9a, - 0x4f, 0x30, 0x22, 0x65, 0x49, 0x44, 0x5b, 0xc6, 0x1c, 0xff, 0x5c, 0x33, 0x16, 0x33, - 0x5f, 0x6b, 0xd4, 0xa9, 0xa4, 0x24, 0xc9, 0x4a, 0xe0, 0xb5, 0xcb, 0xe4, 0x8a, 0xfb, - 0x2b, 0x94, 0xd0, 0xc7, 0xe4, 0x4e, 0x32, 0x30, 0x95, 0xa7, 0x2e, 0x42, 0x64, 0xe9, - 0x1c, 0x48, 0x94, 0xb9, 0xe8, 0x45, 0xaf, 0x32, 0x35, 0x02, 0xda, 0xe8, 0xc1, 0x86, - 0x78, 0xa4, 0xf7, 0x40, 0xe5, 0xa6, 0x3a, 0x4c, 0x70, 0x29, 0x92, 0xfa, 0xcd, 0xd3, - 0x57, 0x35, 0xb1, 0xd1, 0x34, 0x8b, 0x91, 0x9c, 0x70, 0x0c, 0x42, 0xd3, 0x30, 0xd3, - 0x86, 0xaf, 0xb8, 0x73, 0xfa, 0xba, 0xd8, 0xcb, 0x32, 0x18, 0x15, 0x1b, 0x40, 0x18, - 0x01, 0xe3, 0x69, 0x34, 0x4f, 0xf2, 0x0a, 0xaa, 0x66, 0x73, 0x47, 0x4f, 0x4b, 0xfc, - 0x98, 0xd0, 0x7e, 0x36, 0x7b, 0xc4, 0x2e, 0xf1, 0xa0, 0x4f, 0xa1, 0xbc, 0x12, 0x52, - 0x18, 0x8d, 0xd9, 0xd3, 0xe0, 0x00, 0xe3, 0xf5, 0xe9, 0xdf, 0xc9, 0xe1, 0x3e, 0xe9, - 0xdb, 0x55, 0x04, 0x0d, 0x17, 0x22, 0x7d, 0xa4, 0x4a, 0x3e, 0x08, 0xfd, 0x5e, 0xc8, - 0x58, 0xc4, 0x9c, 0x2e, 0x6a, 0x71, 0x1f, 0x8e, 0x68, 0xd0, 0xa1, 0xdf, 0x88, 0xef, - 0x09, 0x40, 0xf7, 0x2e, 0xd7, 0x3e, 0xf4, 0x9e, 0x8a, 0x45, 0xae, 0x2e, 0x5e, 0x1b, - 0xf1, 0x37, 0xba, 0x58, 0xcf, 0xb9, 0x25, 0x79, 0xab, 0xb2, 0xa4, 0x93, 0x13, 0xa2, - 0xff, 0x3d, 0xb6, 0x16, 0x93, 0xd2, 0xb7, 0x58, 0xaf, 0x20, 0x47, 0x2a, 0xc6, 0x40, - 0x6b, 0xa3, 0x55, 0xb4, 0x8c, 0xee, 0x22, 0xe7, 0x0f, 0xb8, 0xf9, 0xd4, 0x8e, 0xa3, - 0x93, 0x4b, 0x62, 0x24, 0xac, 0xe2, 0x69, 0xb9, 0xef, 0x54, 0x6d, 0xbf, 0xc5, 0x2a, - 0xbe, 0xcf, 0xac, 0x59, 0x40, 0xf0, 0x40, 0xbd, 0x21, 0xe9, 0x0e, 0xfa, 0x82, 0x75, - 0x56, 0x1a, 0x88, 0xbc, 0x18, 0xe2, 0x6b, 0x98, 0x8d, 0x11, 0x79, 0xb7, 0xa2, 0xc3, - 0xaf, 0xd8, 0x6e, 0xf2, 0xa0, 0x90, 0x62, 0x52, 0x23, 0x23, 0x4b, 0x39, 0xc9, 0xe2, - 0x06, 0x8d, 0x94, 0x5d, 0xd7, 0x76, 0x3b, 0x01, 0x0c, 0x28, 0xc8, 0x9b, 0x72, 0xe2, - 0x55, 0x13, 0xb3, 0x9c, 0x3c, 0xe1, 0x17, 0x73, 0x42, 0x8a, 0xd3, 0x44, 0xe1, 0xd5, - 0xd5, 0x1b, 0x92, 0x00, 0x14, 0xf9, 0x17, 0x06, 0xff, 0xae, 0x3d, 0x86, 0x36, 0x14, - 0x77, 0xfd, 0x5d, 0xe0, 0x13, 0x42, 0x2c, 0x06, 0xa3, 0x32, 0xe3, 0x45, 0x79, 0x75, - 0xcf, 0x9b, 0xe9, 0xf9, 0xab, 0x3a, 0x06, 0x87, 0x2e, 0xf0, 0x71, 0x7d, 0x39, 0x08, - 0xbd, 0xeb, 0xf8, 0x41, 0x8c, 0xe5, 0x57, 0xd5, 0x2d, 0x51, 0xa2, 0x50, 0xc0, 0x8c, - 0x5b, 0x79, 0x3a, 0xd4, 0xbc, 0x0f, 0x16, 0xc6, 0x27, 0x89, 0xfe, 0xa2, 0xca, 0xb3, - 0x9c, 0xcc, 0xa4, 0x07, 0xee, 0x9e, 0x47, 0xf5, 0x6d, 0x20, 0xa7, 0x41, 0x91, 0x2c, - 0x6b, 0xad, 0xdb, 0xd7, 0xfa, 0x7b, 0x97, 0xe5, 0x46, 0x33, 0x61, 0x28, 0x74, 0x5a, - 0xe7, 0xd7, 0x30, 0xa5, 0x5a, 0x6a, 0xc7, 0xb8, 0xfc, 0xbd, 0x72, 0xce, 0x78, 0x95, - 0x9c, 0x7a, 0x79, 0x75, 0x21, 0x2c, + 0x96, 0x3b, 0xe3, 0x6e, 0xdc, 0xa4, 0x8b, 0x7c, 0x4a, 0x1c, 0xd6, 0xa1, 0x37, 0x2e, + 0x84, 0xc0, 0x54, 0x54, 0x83, 0x4c, 0x5e, 0xe1, 0x92, 0x5e, 0xed, 0xeb, 0x48, 0xda, + 0x16, 0x77, 0x79, 0xe3, 0x99, 0x83, 0x58, 0xcb, 0x92, 0x7a, 0x0a, 0x0b, 0x36, 0x9c, + 0x85, 0xee, 0xb3, 0x30, 0xf7, 0x00, 0x5c, 0x26, 0x9d, 0x0b, 0xe4, 0xf2, 0x38, 0x09, + 0x57, 0xb1, 0x62, 0x97, 0x7c, 0xae, 0x7a, 0x7b, 0x1d, 0x0b, 0xe5, 0xd0, 0xb7, 0x03, + 0xd3, 0x92, 0xac, 0xae, 0xd2, 0x4f, 0x52, 0x5b, 0x83, 0xcf, 0xdd, 0x7f, 0x35, 0xc1, + 0xf1, 0x74, 0xbf, 0x06, 0x6b, 0x7a, 0xfd, 0xb7, 0x45, 0xed, 0xbe, 0xdc, 0x0b, 0x46, + 0xa5, 0x91, 0x36, 0x21, 0x47, 0x61, 0x9d, 0x6b, 0xd3, 0xf3, 0xce, 0x6b, 0x45, 0x23, + 0xf0, 0x64, 0x9a, 0x7c, 0x65, 0x32, 0x2d, 0x05, 0xfa, 0xe2, 0x22, 0x70, 0x1a, 0x8c, + 0xd6, 0xca, 0xbf, 0x8d, 0xc3, 0x2f, 0x05, 0x5f, 0xeb, 0x14, 0x1e, 0x55, 0x6d, 0xdf, + 0xb1, 0x98, 0x30, 0xb7, 0x20, 0x4c, 0x30, 0x98, 0x4e, 0xdd, 0xf4, 0x34, 0xec, 0xc5, + 0xf0, 0xea, 0x82, 0x5c, 0xf8, 0xd9, 0xd5, 0x03, 0x8f, 0x28, 0xe2, 0x3e, 0xf3, 0x6b, + 0xa9, 0x38, 0x52, 0xe5, 0x8e, 0x85, 0xf8, 0x90, 0xb1, 0x77, 0x5c, 0x6d, 0x4c, 0x13, + 0x5b, 0xef, 0x0e, 0x2a, 0x19, 0x33, 0x02, 0xd9, 0x0a, 0x80, 0x4c, 0x85, 0x31, 0x25, + 0xaa, 0x5b, 0x11, 0x6f, 0x8c, 0x58, 0x0e, 0xb6, 0x54, 0xfe, 0x35, 0xe6, 0x73, 0x79, + 0x9e, 0x93, 0xcf, 0x58, 0xfe, 0x1e, 0x70, 0xcd, 0xe1, 0x19, 0xab, 0x58, 0x6c, 0x12, + 0xc4, 0x95, 0x75, 0xe6, 0x1a, 0xc4, 0xb7, 0x71, 0xfa, 0x8e, 0xbf, 0x76, 0xca, 0x95, + 0xd6, 0x51, 0xa4, 0xba, 0x87, 0x3b, 0x24, 0xcf, 0x97, 0xff, 0x75, 0x5b, 0xc7, 0x49, + 0xf4, 0x09, 0x6d, 0x2d, 0xa1, 0x5c, 0xf8, 0x30, 0x36, 0xcc, 0x22, 0x0f, 0x0a, 0x68, + 0x93, 0x43, 0x21, 0xc9, 0xae, 0x33, 0x4e, 0x2d, 0x99, 0xa9, 0x95, 0xe9, 0x29, 0x04, + 0xc1, 0x45, 0x23, 0x33, 0x19, 0x00, 0xcb, 0xca, 0x20, 0x4a, 0xdc, 0xb6, 0x93, 0x9d, + 0xc1, 0x71, 0x87, 0x53, 0x53, 0xa1, 0x1e, 0x12, 0xba, 0xcb, 0x2a, 0xab, 0x0f, 0x57, + 0x17, 0x9f, 0x1b, 0x67, 0xea, 0xcc, 0x7e, 0x7b, 0x6c, 0x5c, 0xc8, 0xa3, 0x78, 0x64, + 0x9b, 0x62, 0xb8, 0x52, 0xfa, 0x47, 0x6f, 0x93, 0x37, 0x88, 0x59, 0xd0, 0xd9, 0xa3, + 0x03, 0x3d, 0xa1, 0x31, 0x28, 0x17, 0x57, 0xad, 0x98, 0x5c, 0x86, 0xfe, 0x03, 0x7a, + 0x4e, 0xdd, 0x0a, 0x4a, 0x49, 0xee, 0x5c, 0x4f, 0x48, 0x15, 0xf0, 0x14, 0x73, 0xb9, + 0x60, 0xa1, 0x8a, 0x3b, 0x7f, 0x75, 0x07, 0xee, 0x3d, 0x8b, 0x39, 0x5a, 0x76, 0x68, + 0x40, 0x95, 0x5b, 0xaa, 0xdd, 0x0a, 0xbb, 0xf4, 0xf5, 0x91, 0x4e, 0x92, 0x10, 0xf5, + 0x9e, 0x4c, 0xd1, 0x3c, 0x82, 0xe0, 0xac, 0xf8, 0x79, 0x51, 0x78, 0x02, 0x91, 0xd0, + 0xa9, 0xa7, 0x0f, 0x6b, 0x4f, 0xf5, 0x0d, 0x81, 0x0d, 0x50, 0x90, 0x20, 0x45, 0x30, + 0xad, 0x69, 0x44, 0xb1, 0x3d, 0x23, 0x83, 0xab, 0xca, 0x42, 0x0c, 0xb6, 0xd9, 0xfc, + 0xd8, 0xfd, 0xcb, 0xe9, 0xb3, 0xb5, 0xf4, 0x2f, 0x0a, 0xf5, 0xdf, 0x36, 0x37, 0x8c, + 0xe7, 0x3d, 0xc9, 0x06, 0x16, 0x7d, 0xd4, 0xb3, 0x80, 0x41, 0x8f, 0x17, 0xe4, 0x50, + 0x61, 0x18, 0x57, 0x23, 0xda, 0xbb, 0x6f, 0xfd, 0xbb, 0xd5, 0xa4, 0x18, 0xc3, 0xc6, + 0xfd, 0x33, 0x70, 0x34, 0x09, 0x94, 0x27, 0x7b, 0x88, 0x8e, 0xe4, 0x9b, 0x08, 0x91, + 0xbb, 0xb9, 0x4b, 0x6b, 0x8b, 0x06, 0x5f, 0xd1, 0x92, 0x00, 0xdc, 0x3a, 0x68, 0x1c, + 0xa5, 0xff, 0x2a, 0x98, 0x8f, 0xa6, 0x6d, 0x02, 0x9d, 0xdd, 0xf9, 0xb0, 0x3a, 0x5e, + 0x6c, 0x6e, 0x99, 0xb6, 0x35, 0x41, 0x15, 0x6a, 0x09, 0x51, 0xd9, 0x08, 0x7d, 0xd8, + 0x83, 0xd5, 0x13, 0x9e, 0xe6, 0x7a, 0x8c, 0xe5, 0xdd, 0x6e, 0xf1, 0x4c, 0x9a, 0x10, + 0xdb, 0x81, 0x8b, 0x93, 0x69, 0x02, 0xc7, 0x99, 0x93, 0x90, 0xf9, 0x72, 0xba, 0xfa, + 0x5a, 0x57, 0x2f, 0xc8, 0x73, 0x42, 0xe2, 0xc5, 0x1c, 0xeb, 0x80, 0x30, 0xe0, 0x6b, + 0x72, 0x40, 0x95, 0xf9, 0x8d, 0x7b, ], ock: [ - 0xeb, 0x3e, 0xd9, 0xfc, 0xb3, 0xaa, 0x91, 0xc4, 0xf5, 0xec, 0xfd, 0x43, 0xdb, 0xda, - 0x40, 0x33, 0x06, 0x93, 0xc3, 0xa6, 0x56, 0x75, 0x45, 0xfd, 0x23, 0x6a, 0xf1, 0x90, - 0x8e, 0x29, 0x42, 0xa3, + 0x5b, 0x5b, 0x20, 0xfc, 0x46, 0xba, 0x14, 0xbd, 0x18, 0x43, 0xb6, 0xc7, 0x7e, 0xc3, + 0xf4, 0x55, 0xb7, 0x65, 0xb4, 0xd1, 0x2d, 0xb6, 0x52, 0xeb, 0x34, 0x20, 0x0c, 0x41, + 0x48, 0x88, 0x1f, 0xfc, ], op: [ 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, - 0x67, 0xa8, 0x60, 0x9e, 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, - 0x6b, 0x8d, 0x6f, 0xea, 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, - 0xd5, 0xcb, 0xab, 0x1a, 0xcc, 0xd5, 0x4e, 0x3a, + 0x67, 0xa8, 0x60, 0x9e, 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, + 0x82, 0x35, 0x16, 0x58, 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, + 0xb0, 0x52, 0xd5, 0xb4, 0x20, 0x41, 0xd8, 0x1c, ], c_out: [ - 0x60, 0xf3, 0xe8, 0x94, 0xe3, 0x86, 0x4e, 0xfb, 0x48, 0xcc, 0xae, 0x50, 0xe1, 0x0d, - 0xa7, 0x73, 0xdc, 0xcf, 0x85, 0x62, 0x45, 0x5d, 0x1b, 0x73, 0x1a, 0xad, 0x44, 0xe1, - 0x5e, 0x3e, 0x40, 0x18, 0x31, 0xce, 0x6f, 0x92, 0xf4, 0x53, 0x2d, 0x90, 0x83, 0x92, - 0x59, 0xce, 0x9c, 0xb1, 0x44, 0x62, 0x1f, 0x12, 0x01, 0x77, 0x8f, 0x61, 0x5d, 0x09, - 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, - 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, + 0xe0, 0x1b, 0x5c, 0x1e, 0x01, 0x90, 0x0f, 0xf7, 0x9b, 0xf7, 0x27, 0xf5, 0x37, 0xc4, + 0xac, 0x36, 0xf8, 0x06, 0x7a, 0x0c, 0xc5, 0xc8, 0xe9, 0xc8, 0x20, 0x44, 0x28, 0x43, + 0x69, 0x35, 0x30, 0x91, 0x8a, 0xea, 0x67, 0x2c, 0x4c, 0xd8, 0xfa, 0x3f, 0x6f, 0x2c, + 0xb6, 0x8b, 0x87, 0x17, 0x22, 0xe7, 0x78, 0xf6, 0xe2, 0x5e, 0x78, 0xae, 0x00, 0xa8, + 0x43, 0x28, 0xc4, 0xc2, 0xbf, 0x1c, 0x79, 0xb2, 0xc9, 0xd8, 0x69, 0x72, 0x60, 0xcd, + 0x44, 0x7e, 0x2e, 0xff, 0x31, 0x5d, 0x74, 0xb5, 0xb1, 0xfd, ], }, TestVector { @@ -1362,29 +1363,29 @@ pub(crate) fn test_vectors() -> Vec { 0x7f, 0x01, 0x02, 0x3e, ], cmx: [ - 0x1d, 0x51, 0xea, 0x92, 0xfa, 0x43, 0x55, 0x0a, 0x0e, 0xdd, 0xea, 0x23, 0x6e, 0x17, - 0xa0, 0x16, 0x93, 0xc2, 0x2d, 0x8d, 0xd8, 0x1c, 0x9c, 0x9e, 0xc8, 0x76, 0xa2, 0x4e, - 0x67, 0xd4, 0x93, 0x0b, + 0xcc, 0x29, 0x41, 0xe0, 0xf6, 0x38, 0x25, 0x7f, 0xb6, 0x51, 0x6a, 0x27, 0xc3, 0x0e, + 0xaa, 0xe0, 0xb4, 0x6d, 0x2f, 0xf0, 0x6a, 0x73, 0x50, 0x70, 0x41, 0x74, 0x6c, 0xdc, + 0x23, 0x07, 0x61, 0x25, ], esk: [ - 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, 0x14, 0xb0, 0xdf, 0x85, - 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, 0xc4, 0x84, 0xa9, 0xf4, - 0xc7, 0xda, 0x74, 0x36, + 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, 0xbf, 0xb7, 0x8a, 0xec, + 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, 0x77, 0xc9, 0x46, 0xe9, + 0xcd, 0x7a, 0x24, 0x23, ], ephemeral_key: [ - 0x8f, 0xbe, 0xb6, 0xb3, 0x03, 0x8e, 0x69, 0x49, 0x91, 0x6a, 0x2c, 0x06, 0x0e, 0xf9, - 0xa4, 0xb1, 0xfe, 0xf1, 0x3a, 0xce, 0x2f, 0xee, 0x00, 0x25, 0xda, 0x32, 0xc3, 0x6d, - 0x23, 0x1a, 0x61, 0x34, + 0xad, 0xa7, 0x60, 0x27, 0xdc, 0xae, 0xb5, 0xf1, 0x58, 0xac, 0x6c, 0x5c, 0x6d, 0x7f, + 0x05, 0x31, 0x8f, 0xec, 0x26, 0xd5, 0xc7, 0x94, 0xf2, 0xe9, 0x00, 0xcb, 0x96, 0x29, + 0x92, 0x49, 0xe0, 0xb5, ], shared_secret: [ - 0x67, 0xd6, 0x8a, 0x5a, 0x05, 0x93, 0xfd, 0x16, 0x7d, 0x38, 0x08, 0x2e, 0x49, 0xd2, - 0x30, 0x30, 0x86, 0xe5, 0x5a, 0x43, 0xc1, 0x24, 0xd5, 0xaa, 0xa8, 0x20, 0xab, 0x0c, - 0x3f, 0x5c, 0xc5, 0x37, + 0xc2, 0x5c, 0xf1, 0xd6, 0x53, 0x2e, 0x06, 0xcb, 0x8b, 0x15, 0x22, 0x14, 0x76, 0x6e, + 0xee, 0xd7, 0x5a, 0x17, 0x8c, 0x82, 0x2a, 0x11, 0x51, 0xf6, 0x9e, 0x92, 0xe9, 0xcf, + 0xfa, 0x47, 0xcb, 0x19, ], k_enc: [ - 0x6b, 0x8d, 0x83, 0xf2, 0xf1, 0xfd, 0x1e, 0xad, 0x7d, 0x45, 0x42, 0xb3, 0x63, 0x09, - 0x34, 0x07, 0xc5, 0x0a, 0x20, 0xed, 0x7f, 0x0e, 0x8c, 0xf2, 0xdb, 0x53, 0x6d, 0xb1, - 0xbe, 0x25, 0xe9, 0x8d, + 0xd4, 0xef, 0x89, 0xc4, 0x64, 0xbe, 0x8f, 0x42, 0xf6, 0xb7, 0xf2, 0x6d, 0x89, 0x37, + 0x8b, 0x73, 0xa3, 0x55, 0xa4, 0xfe, 0x24, 0x6c, 0x2e, 0xc8, 0xe8, 0x14, 0x6b, 0xef, + 0x7d, 0xdd, 0x14, 0x19, ], p_enc: [ 0x02, 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, 0x10, 0xb8, @@ -1430,68 +1431,68 @@ pub(crate) fn test_vectors() -> Vec { 0x1a, 0x81, 0xa3, 0x59, ], c_enc: [ - 0x77, 0xc6, 0xef, 0xc8, 0xb5, 0x42, 0xa7, 0x07, 0xc0, 0xa5, 0xcf, 0x5c, 0xe3, 0xf3, - 0xb9, 0x6d, 0xe1, 0x91, 0x95, 0x7c, 0x9f, 0xa6, 0xe9, 0xbb, 0x4b, 0x8d, 0x89, 0x9e, - 0x1f, 0x19, 0xe0, 0x20, 0xba, 0x7b, 0xb3, 0xfe, 0xf1, 0x67, 0x81, 0xc8, 0x8c, 0xc5, - 0xd4, 0x4a, 0x5e, 0xf8, 0x17, 0x31, 0x47, 0xdc, 0x3d, 0x1b, 0x51, 0x6a, 0xf6, 0xdd, - 0x77, 0xdd, 0xb6, 0xee, 0x67, 0xaa, 0xf5, 0x42, 0xce, 0xe2, 0xbe, 0xd3, 0xe4, 0xa0, - 0x7e, 0xce, 0x42, 0x8f, 0x22, 0xa8, 0x01, 0xcf, 0x01, 0xba, 0xad, 0x18, 0x27, 0xfd, - 0x42, 0x57, 0x46, 0xc5, 0x45, 0x00, 0x1c, 0x35, 0x6d, 0x0a, 0xbe, 0xaa, 0xa5, 0xa4, - 0x22, 0xdf, 0xff, 0x0e, 0xe2, 0x18, 0xac, 0x37, 0xef, 0x83, 0x97, 0xc6, 0x2c, 0xa8, - 0x6f, 0xab, 0xeb, 0xb6, 0x88, 0xb3, 0x8f, 0xb4, 0xa6, 0x54, 0x29, 0x11, 0xbe, 0x1c, - 0x5e, 0x71, 0x77, 0x8b, 0x5e, 0xb5, 0x3a, 0xf1, 0xc4, 0xcb, 0x4d, 0xd9, 0x94, 0x72, - 0x4f, 0x61, 0x0f, 0x38, 0x72, 0x4a, 0x73, 0xdf, 0x09, 0x2b, 0xea, 0xe8, 0xb8, 0x7f, - 0x7f, 0x6a, 0x2b, 0xc0, 0x9d, 0xf2, 0xaa, 0x18, 0xc2, 0xf8, 0xee, 0xba, 0x63, 0xee, - 0x0d, 0x31, 0x35, 0x3b, 0x6f, 0x28, 0x3e, 0xf5, 0x9a, 0xc1, 0x53, 0x60, 0x73, 0xda, - 0x7a, 0x6d, 0x82, 0xbf, 0xdc, 0x09, 0x74, 0x02, 0x08, 0x0f, 0xa1, 0x03, 0xcb, 0x8b, - 0x3e, 0xfb, 0x94, 0x1e, 0xe5, 0x01, 0xf6, 0x41, 0x2c, 0xfb, 0xc2, 0x50, 0xaf, 0xad, - 0xbe, 0x54, 0x4a, 0xc5, 0x1f, 0xce, 0x41, 0x5a, 0x24, 0x93, 0xba, 0x83, 0x9e, 0x38, - 0x18, 0xb0, 0xfe, 0x30, 0x18, 0xbf, 0xa4, 0x37, 0xf0, 0x6e, 0x31, 0x86, 0x14, 0x8a, - 0xa4, 0x05, 0xba, 0xb8, 0x21, 0xa2, 0x6e, 0xa0, 0x7f, 0x93, 0xcf, 0xe7, 0x56, 0x8f, - 0xe3, 0xef, 0x08, 0xfa, 0x0b, 0x80, 0xfc, 0xec, 0x5b, 0xd5, 0x91, 0x5f, 0x68, 0x8c, - 0xf5, 0x99, 0x31, 0x5e, 0x79, 0xaa, 0xea, 0x34, 0xd5, 0x18, 0xd9, 0x55, 0xfe, 0xef, - 0x30, 0x3f, 0x69, 0xb2, 0x87, 0xc6, 0xd0, 0x51, 0x6d, 0xa2, 0x39, 0xfb, 0xbd, 0xdb, - 0xaf, 0x25, 0x56, 0xeb, 0xce, 0x77, 0xa3, 0xd5, 0x97, 0x23, 0x5c, 0x22, 0xd3, 0x8c, - 0x5b, 0x5e, 0xeb, 0x98, 0xc7, 0xc0, 0x8d, 0xa8, 0xd3, 0x76, 0xbb, 0xa1, 0xb5, 0x07, - 0x85, 0xbe, 0x82, 0xbf, 0xe0, 0x9a, 0xe7, 0x1c, 0xcc, 0xaf, 0x31, 0xa2, 0xf0, 0xcf, - 0xa0, 0x76, 0xd1, 0xe4, 0xd1, 0xb5, 0x2f, 0xee, 0x45, 0xc8, 0xed, 0x23, 0xdf, 0x33, - 0xa8, 0x1c, 0xb1, 0xa8, 0xac, 0xec, 0x9f, 0x53, 0x5d, 0xa4, 0x96, 0x70, 0xf9, 0x98, - 0x6d, 0x5c, 0x92, 0xc8, 0x2b, 0x0a, 0xd2, 0x20, 0xf8, 0x5f, 0x3b, 0x38, 0x72, 0xeb, - 0xe0, 0x53, 0xcd, 0xeb, 0x96, 0x1b, 0xd2, 0xd3, 0xab, 0x3b, 0xcd, 0x67, 0x6e, 0x6f, - 0xd7, 0xcb, 0xe9, 0x79, 0x5e, 0x1f, 0x2d, 0x82, 0x87, 0x00, 0x7c, 0x91, 0x0e, 0x7b, - 0x43, 0x01, 0x69, 0xe4, 0x51, 0xf0, 0xb2, 0xd7, 0x63, 0xe5, 0x43, 0x03, 0x3b, 0xc6, - 0xc7, 0x38, 0x9f, 0xa1, 0x61, 0x5b, 0xa1, 0x9d, 0x1f, 0x27, 0x48, 0xb2, 0x17, 0xc9, - 0x60, 0xfe, 0x05, 0x04, 0x07, 0xc8, 0xf4, 0x73, 0x35, 0x6b, 0xaa, 0x6e, 0x0c, 0x7d, - 0x77, 0xfa, 0xc6, 0xc7, 0xdb, 0x45, 0x12, 0xaf, 0x57, 0x96, 0xb3, 0xbc, 0xf1, 0x23, - 0xe0, 0x90, 0xb9, 0x80, 0xeb, 0xc2, 0xd6, 0x4b, 0x86, 0xdd, 0x24, 0xcb, 0x9a, 0x6d, - 0xab, 0x1d, 0xb4, 0x13, 0x04, 0x75, 0x38, 0x90, 0x2e, 0x2e, 0x49, 0x0e, 0x4f, 0xc8, - 0x78, 0xaa, 0x04, 0xdb, 0xef, 0x66, 0x99, 0x63, 0x9c, 0x3d, 0xab, 0x17, 0xc5, 0x14, - 0x70, 0x48, 0xac, 0x6d, 0x48, 0x49, 0x0d, 0xc4, 0x88, 0x5e, 0xd9, 0x86, 0x70, 0x63, - 0x35, 0xf4, 0x1b, 0xa4, 0x15, 0x59, 0x65, 0x9e, 0x1b, 0x53, 0xda, 0x76, 0x51, 0x4c, - 0xc4, 0x0a, 0xdb, 0x66, 0xc3, 0x5c, 0xe5, 0x6f, 0x3a, 0xbe, 0x39, 0xe1, 0xae, 0xe5, - 0x84, 0x9f, 0xff, 0xcc, 0x6e, 0x1f, 0x1b, 0xf8, 0x11, 0xce, 0xb6, 0x65, 0xa6, 0xfc, - 0xf8, 0x80, 0x6b, 0xbb, 0xba, 0x4a, 0x5b, 0x87, 0x38, 0xa1, 0x17, 0xdc, 0xaf, 0xfb, - 0x4f, 0xdf, 0x10, 0x08, 0x00, 0x6f, + 0xea, 0x86, 0x7e, 0x07, 0xac, 0xb7, 0xfa, 0x03, 0xe7, 0x36, 0xce, 0xdd, 0xed, 0x82, + 0x3d, 0x19, 0x91, 0x30, 0xfb, 0x3f, 0xef, 0x62, 0xcc, 0x3e, 0xa9, 0xa0, 0xc9, 0x35, + 0xdf, 0x05, 0xc5, 0xad, 0x5e, 0x67, 0xf7, 0x4f, 0xcb, 0xa6, 0x67, 0xe0, 0x81, 0x1c, + 0xdc, 0x0c, 0xa9, 0xf3, 0xd7, 0x81, 0x76, 0x43, 0x75, 0x56, 0x47, 0xbe, 0x59, 0xdf, + 0x09, 0x6e, 0x46, 0x5e, 0xc1, 0x11, 0x24, 0x36, 0x3c, 0x98, 0x1c, 0x55, 0xd5, 0x5f, + 0x8d, 0x8a, 0xc8, 0xb6, 0x54, 0x0a, 0x98, 0xcf, 0xcc, 0x29, 0x4a, 0xa7, 0xcc, 0x62, + 0x95, 0x50, 0x85, 0x3a, 0x25, 0xbf, 0x6b, 0x32, 0x35, 0x16, 0xe1, 0x58, 0x2b, 0x4e, + 0x8b, 0x82, 0x95, 0xe2, 0x7f, 0x6b, 0x99, 0x94, 0x80, 0x2e, 0xfe, 0xf5, 0x43, 0x1f, + 0x03, 0x7d, 0x22, 0x09, 0xa0, 0x88, 0x07, 0x34, 0x6f, 0xb3, 0x9c, 0xad, 0xd8, 0x93, + 0xd6, 0x5f, 0x64, 0xc7, 0xfe, 0x92, 0xec, 0xbc, 0xdf, 0xe5, 0x55, 0x54, 0xca, 0xff, + 0xb0, 0xcf, 0x41, 0xeb, 0x5c, 0x55, 0x72, 0xba, 0x44, 0x39, 0x90, 0x00, 0xe9, 0xfa, + 0x9a, 0xaf, 0x6e, 0xb7, 0x6c, 0x2a, 0x8a, 0x5d, 0x7b, 0x6b, 0x52, 0xb9, 0xa9, 0xef, + 0x6e, 0xc3, 0xed, 0xa6, 0x65, 0xfe, 0x8a, 0xa8, 0x07, 0x48, 0xb8, 0x1f, 0x7d, 0x55, + 0x96, 0xf1, 0x94, 0x2f, 0xf7, 0x1d, 0x29, 0xc6, 0x78, 0xa3, 0xb6, 0xc6, 0x6b, 0xa7, + 0x0f, 0x45, 0xb1, 0xfc, 0xf2, 0x22, 0x38, 0x84, 0x50, 0x68, 0xf3, 0x60, 0xb0, 0x99, + 0xae, 0xe9, 0xf2, 0xf0, 0xef, 0x22, 0x33, 0x3f, 0xd6, 0x4f, 0xf1, 0x1e, 0x48, 0x15, + 0x43, 0xa5, 0x2b, 0xb3, 0x3f, 0x52, 0x3d, 0xe2, 0xec, 0x92, 0x3a, 0xe9, 0x86, 0x58, + 0x57, 0x71, 0x7b, 0x65, 0xd4, 0x4c, 0x3d, 0x9d, 0xb7, 0xb3, 0xec, 0xb2, 0xff, 0x02, + 0x25, 0x29, 0x7d, 0xeb, 0x83, 0xdd, 0x1b, 0x9a, 0x39, 0x4d, 0x69, 0x7c, 0x09, 0xd7, + 0xfe, 0xc6, 0x1e, 0xac, 0xee, 0x39, 0xa2, 0xf1, 0xce, 0xd9, 0xe6, 0xfd, 0xa5, 0xc0, + 0xf3, 0x27, 0x71, 0xc6, 0xce, 0x3f, 0x17, 0xbe, 0x0e, 0xef, 0x81, 0x10, 0x99, 0xc1, + 0x09, 0xe4, 0xfb, 0x6a, 0xec, 0x30, 0xdf, 0x04, 0x5b, 0x43, 0xda, 0x89, 0x30, 0x8b, + 0xc8, 0x37, 0x68, 0x8b, 0xb0, 0xf4, 0xa2, 0xc6, 0x04, 0xa1, 0x54, 0xa8, 0x47, 0xc5, + 0xd7, 0x87, 0x27, 0xf0, 0xe1, 0xab, 0x11, 0xe3, 0x40, 0xcf, 0xd4, 0xc7, 0xe8, 0xc6, + 0xba, 0xff, 0xfe, 0xfc, 0x74, 0xef, 0x55, 0x3d, 0x4b, 0x29, 0x26, 0x9f, 0x38, 0xb4, + 0xb7, 0xfe, 0x6e, 0x07, 0x3a, 0x70, 0xae, 0xf2, 0x0d, 0x6c, 0x23, 0x8b, 0x9f, 0xfd, + 0x24, 0x1f, 0xf6, 0x99, 0x99, 0x92, 0x30, 0xf0, 0xb3, 0x9c, 0x96, 0x3e, 0xfa, 0x00, + 0xef, 0x7f, 0x09, 0x2d, 0x76, 0x0c, 0x40, 0x9a, 0x2b, 0x6c, 0x26, 0xb4, 0x97, 0x82, + 0x9b, 0x81, 0xcb, 0xa4, 0xc8, 0x3b, 0x11, 0x44, 0xc6, 0x5a, 0x2d, 0x31, 0x78, 0xbb, + 0x28, 0xc1, 0xd8, 0xe3, 0x30, 0xd3, 0xf4, 0xaf, 0x90, 0x10, 0xad, 0x49, 0xa5, 0xdb, + 0x70, 0xd6, 0x6a, 0xf5, 0x70, 0x19, 0x21, 0x49, 0x80, 0x5f, 0xe1, 0xca, 0x61, 0xc6, + 0xd4, 0xec, 0xaf, 0xa7, 0x97, 0x51, 0x7f, 0x33, 0x06, 0xaf, 0x2a, 0x32, 0x27, 0x3b, + 0xf3, 0xd6, 0x98, 0xaa, 0x55, 0xa5, 0x72, 0xb2, 0xdf, 0x80, 0x36, 0xd9, 0x7c, 0xf5, + 0x8c, 0x12, 0x9f, 0x82, 0x85, 0xd0, 0xd7, 0xea, 0x04, 0xc1, 0x88, 0xa8, 0x39, 0x6e, + 0x73, 0x8b, 0xd4, 0x48, 0x46, 0x5e, 0x7b, 0x9a, 0x64, 0xb7, 0x96, 0x7b, 0xcb, 0x25, + 0xf8, 0xaa, 0x85, 0x9e, 0xa5, 0xca, 0x06, 0xc3, 0xdf, 0x39, 0x0f, 0xac, 0x8a, 0xc6, + 0x06, 0x05, 0x03, 0x1a, 0x02, 0x09, 0xbb, 0x80, 0x24, 0x0d, 0x05, 0x45, 0xf4, 0x11, + 0x77, 0xea, 0xb4, 0x40, 0x2e, 0x8a, 0x42, 0x3a, 0x40, 0xcc, 0xff, 0x58, 0x6b, 0x2e, + 0xdd, 0x6a, 0xcf, 0xb8, 0xf1, 0xd8, 0x0d, 0x8c, 0x60, 0x5f, 0x49, 0x05, 0x2e, 0x7a, + 0x30, 0x82, 0x6e, 0x1f, 0x03, 0x09, 0x9c, 0x71, 0x43, 0xad, 0x0b, 0x51, 0xfc, 0x63, + 0x6f, 0x1d, 0x87, 0x05, 0x83, 0xd6, 0xed, 0xce, 0xcd, 0xe9, 0x42, 0x38, 0x9e, 0x6c, + 0x01, 0x00, 0x66, 0x78, 0xda, 0xad, ], ock: [ - 0xb4, 0xf8, 0x8a, 0x29, 0x2d, 0x09, 0xd9, 0x35, 0xb4, 0x77, 0x5a, 0x29, 0x30, 0xeb, - 0x38, 0xce, 0xbd, 0x5a, 0xf6, 0xff, 0x3f, 0x39, 0xef, 0x5b, 0xb2, 0x4c, 0xd5, 0x72, - 0x81, 0xf0, 0x8c, 0xfb, + 0xf9, 0x59, 0x87, 0xcc, 0x0c, 0x73, 0x57, 0xc7, 0x20, 0x26, 0x27, 0xa5, 0xa5, 0x50, + 0x09, 0xef, 0xd7, 0x17, 0x55, 0x3e, 0x9d, 0x34, 0xc1, 0x5f, 0xad, 0xf5, 0xc9, 0x46, + 0xa9, 0xa0, 0x72, 0x17, ], op: [ 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, - 0x6b, 0x80, 0xbb, 0xb7, 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, - 0x14, 0xb0, 0xdf, 0x85, 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, - 0xc4, 0x84, 0xa9, 0xf4, 0xc7, 0xda, 0x74, 0x36, + 0x6b, 0x80, 0xbb, 0xb7, 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, + 0xbf, 0xb7, 0x8a, 0xec, 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, + 0x77, 0xc9, 0x46, 0xe9, 0xcd, 0x7a, 0x24, 0x23, ], c_out: [ - 0x94, 0xe3, 0x7f, 0xd6, 0x62, 0x82, 0xc0, 0x2e, 0x90, 0xe7, 0x69, 0x91, 0x4c, 0xaf, - 0x95, 0xa4, 0x95, 0xf4, 0x89, 0x7f, 0x55, 0xa5, 0xae, 0x95, 0xad, 0xe8, 0xbf, 0x67, - 0x61, 0xe3, 0x1b, 0xa5, 0xd1, 0xcf, 0xeb, 0x30, 0x6f, 0x4e, 0x22, 0x01, 0x42, 0x51, - 0xcb, 0xe3, 0xf8, 0x72, 0x4b, 0xe7, 0x69, 0x21, 0xe2, 0xad, 0xa4, 0x6e, 0x3b, 0x14, - 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, - 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, + 0x28, 0x9d, 0x00, 0xd4, 0x62, 0x78, 0x0b, 0xdb, 0xb6, 0xcd, 0x6c, 0xec, 0x93, 0x6b, + 0xe6, 0x5e, 0x63, 0x0d, 0x4a, 0x3c, 0x2a, 0xf7, 0x6e, 0x10, 0x4b, 0x17, 0x4e, 0x3d, + 0x5b, 0x71, 0x66, 0x39, 0xb0, 0x68, 0xb3, 0x85, 0x00, 0xd8, 0x04, 0x00, 0xee, 0x64, + 0x2f, 0x8e, 0x08, 0xc8, 0xdb, 0x29, 0xff, 0xd5, 0xa9, 0xda, 0xde, 0x84, 0xa5, 0x49, + 0x5d, 0x57, 0x7b, 0x2f, 0x56, 0xd3, 0x2b, 0x07, 0x96, 0xca, 0x23, 0xf0, 0x0f, 0x0f, + 0x8e, 0xf9, 0x93, 0x07, 0x4f, 0x88, 0x0d, 0x6a, 0xeb, 0xcb, ], }, TestVector { @@ -1572,29 +1573,29 @@ pub(crate) fn test_vectors() -> Vec { 0x9a, 0xda, 0x04, 0x08, ], cmx: [ - 0xbe, 0x43, 0xee, 0x84, 0x70, 0x70, 0x75, 0xac, 0x48, 0x08, 0xd0, 0x97, 0x54, 0x07, - 0xc0, 0x27, 0x36, 0xd7, 0x66, 0x64, 0xf4, 0xe7, 0xae, 0xce, 0x01, 0xd9, 0xcc, 0x68, - 0x32, 0x4a, 0xe9, 0x04, + 0xca, 0xa2, 0x8a, 0x69, 0x04, 0x54, 0x66, 0x37, 0xa7, 0xd4, 0xe5, 0xfb, 0xc2, 0x65, + 0x4c, 0xbf, 0x24, 0x4d, 0x18, 0x77, 0x9d, 0x35, 0x62, 0x25, 0x6c, 0x14, 0xd5, 0xb1, + 0x00, 0x5d, 0xc6, 0x0f, ], esk: [ - 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, 0x14, 0x49, 0x72, 0x62, - 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, 0xe2, 0x63, 0xf3, 0xe3, - 0x99, 0x07, 0xea, 0x0c, + 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, 0x42, 0x0e, 0xff, 0xd7, + 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, 0x91, 0x90, 0x01, 0xf8, + 0x66, 0xa8, 0xe9, 0x2c, ], ephemeral_key: [ - 0xfa, 0x19, 0xa1, 0x52, 0x7b, 0x76, 0x04, 0x8f, 0xf3, 0x7f, 0xa4, 0xf8, 0x27, 0x89, - 0xfe, 0x80, 0xb0, 0xcd, 0xd3, 0x5d, 0x5d, 0xa9, 0xc2, 0xec, 0x3f, 0xe3, 0x04, 0x38, - 0x05, 0xc0, 0x61, 0x23, + 0x00, 0x62, 0x7e, 0x29, 0xc1, 0x83, 0x3e, 0x4e, 0x8f, 0xad, 0xe0, 0x82, 0x52, 0xf3, + 0x83, 0x67, 0x78, 0xb9, 0x39, 0x4c, 0x1f, 0xfe, 0xab, 0x70, 0xbf, 0x35, 0x93, 0xd5, + 0x9a, 0x81, 0xa0, 0xa5, ], shared_secret: [ - 0x2d, 0xb5, 0xb8, 0x92, 0xb6, 0x1b, 0x9c, 0x55, 0x3b, 0x6c, 0x9b, 0x7a, 0xcc, 0x7d, - 0x71, 0x05, 0xc1, 0xdd, 0x4c, 0x28, 0xc6, 0x7f, 0x97, 0x8b, 0x6d, 0x79, 0xc7, 0x1b, - 0x98, 0xa0, 0xd0, 0x00, + 0xa9, 0x93, 0x34, 0x1f, 0x99, 0xeb, 0xa8, 0x2d, 0xb6, 0xec, 0x5e, 0x71, 0x3e, 0xe2, + 0x9c, 0x01, 0xf4, 0xce, 0x2a, 0x8b, 0xb6, 0xb5, 0xeb, 0xb6, 0x0b, 0xa6, 0xeb, 0xa9, + 0x6b, 0xa4, 0x17, 0x9b, ], k_enc: [ - 0x16, 0xe3, 0xf9, 0x85, 0xc0, 0x7f, 0xef, 0xe5, 0x30, 0xd9, 0xe6, 0x94, 0x5e, 0xde, - 0xc1, 0x90, 0x3b, 0xb1, 0xca, 0x8d, 0xa5, 0xa2, 0x5b, 0xe9, 0x59, 0x78, 0x63, 0x7a, - 0x40, 0x8c, 0x2e, 0xfe, + 0x35, 0x81, 0x19, 0x19, 0x3c, 0x9d, 0x2a, 0xb6, 0xd4, 0x95, 0xe0, 0x19, 0xf9, 0x7a, + 0x1c, 0x41, 0x30, 0xae, 0xe6, 0x3d, 0xae, 0xc6, 0xbb, 0xa2, 0xf2, 0x74, 0x40, 0x0f, + 0xd3, 0x4f, 0xad, 0x28, ], p_enc: [ 0x02, 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, 0x46, 0x49, @@ -1640,68 +1641,68 @@ pub(crate) fn test_vectors() -> Vec { 0x84, 0x37, 0x3f, 0x4f, ], c_enc: [ - 0x2d, 0x40, 0x4a, 0x68, 0x81, 0xa6, 0xee, 0x76, 0x0c, 0xb5, 0x3b, 0x9c, 0xc2, 0x71, - 0x5c, 0xa7, 0x6a, 0x3a, 0x2f, 0xc9, 0x69, 0x3b, 0x1a, 0xbb, 0xcd, 0xc7, 0x5c, 0xb6, - 0xd6, 0xc3, 0x6e, 0xcf, 0x84, 0xd6, 0x93, 0x67, 0x2c, 0x53, 0xce, 0xd8, 0x79, 0x8c, - 0xc8, 0xf1, 0xe5, 0x3b, 0x8a, 0x9d, 0xe7, 0xbb, 0xb5, 0xe8, 0xc5, 0xa4, 0x6c, 0x3a, - 0x74, 0x12, 0xdf, 0x11, 0xc5, 0xda, 0x16, 0xb4, 0xdd, 0x22, 0x90, 0x1a, 0x59, 0x2b, - 0x0e, 0x93, 0x29, 0x77, 0xba, 0x06, 0x67, 0x3d, 0x6f, 0xd0, 0x38, 0xac, 0xba, 0xa9, - 0xbf, 0x79, 0xc1, 0x5b, 0xa6, 0x2b, 0x6e, 0x30, 0x74, 0xef, 0x95, 0x3b, 0x81, 0x4c, - 0xf1, 0xbd, 0xf0, 0x15, 0x77, 0xed, 0x3e, 0x3f, 0xae, 0xf4, 0x71, 0x55, 0xc9, 0x1c, - 0x68, 0xee, 0x32, 0x88, 0x1b, 0x73, 0x74, 0x94, 0xb3, 0xb4, 0x76, 0x08, 0x3b, 0x3b, - 0xd1, 0x77, 0x93, 0xc4, 0x98, 0x93, 0x1e, 0xaa, 0x92, 0xb1, 0x7c, 0x7d, 0x10, 0x47, - 0x58, 0xfc, 0x8b, 0x34, 0x93, 0xd2, 0x47, 0x41, 0x7f, 0x5e, 0xc1, 0x97, 0x9a, 0x35, - 0x28, 0x93, 0xe9, 0x95, 0x63, 0xb6, 0xc3, 0xab, 0x95, 0xcc, 0x5a, 0xfa, 0x37, 0x32, - 0xef, 0xae, 0xce, 0x9e, 0x74, 0x32, 0xc8, 0x04, 0x15, 0xe2, 0x5f, 0x55, 0x56, 0x53, - 0xc7, 0xda, 0x5d, 0xb0, 0xcc, 0x61, 0x08, 0x74, 0x21, 0x95, 0x9b, 0xb1, 0xdf, 0x80, - 0x03, 0xb7, 0x3d, 0xa0, 0xbe, 0xf0, 0x60, 0xf3, 0xa8, 0x4c, 0x8b, 0xc2, 0x4c, 0xc7, - 0x6d, 0x0d, 0x9e, 0x9c, 0x33, 0x76, 0x5c, 0x20, 0xf0, 0x7d, 0x80, 0xe2, 0x0f, 0xdf, - 0x27, 0x81, 0x5d, 0xbd, 0x9d, 0x71, 0x7c, 0x09, 0x66, 0xf8, 0x0b, 0x94, 0xb9, 0x59, - 0x15, 0x08, 0x1e, 0xa4, 0x55, 0x37, 0xa5, 0xa0, 0x74, 0xb9, 0xc9, 0x4b, 0x43, 0xdd, - 0xf4, 0xa9, 0xcb, 0xad, 0xe9, 0x04, 0x51, 0x0e, 0xaa, 0x96, 0x9e, 0x66, 0x6c, 0x94, - 0x34, 0xb9, 0xf6, 0x3e, 0xae, 0x62, 0xad, 0x58, 0x27, 0x99, 0x62, 0xe9, 0x41, 0x33, - 0x05, 0x5c, 0xbc, 0xc4, 0xb1, 0x55, 0xc0, 0x0f, 0x1b, 0x83, 0xff, 0x41, 0x28, 0xa8, - 0xab, 0xb4, 0xce, 0x68, 0xe9, 0xf1, 0xe3, 0x08, 0xe6, 0xf9, 0x7e, 0x51, 0x3a, 0xf5, - 0x95, 0x47, 0x1a, 0x16, 0x77, 0xef, 0x78, 0xe9, 0x77, 0x0f, 0x43, 0xad, 0xde, 0x1a, - 0x64, 0x58, 0x6d, 0xe6, 0xa5, 0x87, 0xc3, 0xd6, 0x93, 0xfe, 0xa8, 0xfc, 0xc6, 0xac, - 0xc8, 0x94, 0x96, 0x1e, 0x2f, 0x47, 0xb2, 0x02, 0xe8, 0x6a, 0x57, 0x38, 0x79, 0xb5, - 0xbf, 0xd7, 0x29, 0xda, 0x2f, 0xbe, 0xfc, 0x64, 0x5c, 0xfa, 0xb1, 0x88, 0x0d, 0x51, - 0x76, 0x40, 0xdf, 0x5f, 0x53, 0xe5, 0x7c, 0x72, 0xd6, 0x5a, 0x63, 0x3a, 0xa5, 0x36, - 0xb2, 0x98, 0x34, 0xbf, 0x28, 0x16, 0xb1, 0xf7, 0x16, 0xbf, 0x43, 0x6d, 0x6b, 0x2b, - 0x6e, 0x47, 0x73, 0x28, 0xc9, 0x58, 0xa6, 0xb8, 0xcf, 0x73, 0xb9, 0x5d, 0x22, 0xf6, - 0x99, 0x3b, 0x3f, 0xc5, 0x25, 0xdb, 0x62, 0x7f, 0x6f, 0x38, 0xd0, 0x77, 0x9a, 0x1d, - 0x39, 0xaf, 0x05, 0xed, 0x74, 0xfd, 0xfe, 0xff, 0x98, 0x7a, 0x95, 0x88, 0xd8, 0x0b, - 0x7e, 0x79, 0x69, 0x4a, 0xe4, 0x55, 0x29, 0x29, 0x88, 0x1c, 0x5b, 0xfe, 0x20, 0x49, - 0x2f, 0xd6, 0xf3, 0x37, 0xca, 0x88, 0xdf, 0xb5, 0x01, 0xe5, 0x45, 0xd2, 0x36, 0x73, - 0xac, 0xac, 0xbc, 0x3d, 0x33, 0x14, 0xa8, 0xbb, 0xf5, 0xec, 0x70, 0xb7, 0x05, 0xcc, - 0x9d, 0x26, 0x57, 0xbd, 0xd5, 0xa7, 0x09, 0x15, 0xbe, 0xf6, 0xd0, 0xf0, 0x39, 0xd3, - 0xeb, 0xa6, 0xbb, 0x71, 0x5b, 0xe5, 0x1e, 0xbf, 0x6e, 0xf6, 0x59, 0xea, 0x32, 0xff, - 0x80, 0xc8, 0x2c, 0x04, 0x21, 0x67, 0x5f, 0xe3, 0x71, 0xef, 0x49, 0xf1, 0xb9, 0xe3, - 0x8f, 0x43, 0x7b, 0x4a, 0x76, 0x55, 0xdc, 0x29, 0x16, 0xaa, 0x30, 0x86, 0xde, 0x6c, - 0x62, 0xa8, 0x2b, 0x36, 0x1c, 0x05, 0x3f, 0xc6, 0x34, 0x54, 0xcc, 0xd0, 0x2c, 0x22, - 0xd4, 0x1f, 0xf5, 0xbb, 0x83, 0x62, 0xde, 0xaa, 0x70, 0x82, 0x5a, 0xd2, 0xf9, 0x93, - 0x63, 0x9f, 0xc4, 0x46, 0x06, 0x9d, 0x78, 0xa6, 0x1d, 0x33, 0x8d, 0xf5, 0x8f, 0x77, - 0x63, 0xe3, 0x55, 0xe6, 0xa9, 0xff, + 0x31, 0xac, 0xda, 0xa6, 0xc1, 0x76, 0xbb, 0x7a, 0x2c, 0x7d, 0x66, 0x09, 0xdc, 0x2c, + 0x5e, 0x7b, 0x2e, 0xe7, 0x1d, 0xa9, 0x3c, 0x73, 0x87, 0x52, 0x74, 0xfa, 0x6c, 0x2a, + 0xd6, 0x26, 0x13, 0xc7, 0x18, 0x9b, 0x35, 0x33, 0xec, 0xf0, 0x34, 0xd8, 0x76, 0xc7, + 0x26, 0xf1, 0xed, 0x99, 0x43, 0xd4, 0x45, 0x07, 0x87, 0x52, 0x75, 0xa8, 0xe3, 0x71, + 0x0a, 0x11, 0x8d, 0x91, 0x64, 0x72, 0x91, 0x28, 0x6c, 0xf8, 0x80, 0xa7, 0x82, 0xab, + 0xea, 0xa8, 0xa6, 0xc3, 0x2f, 0xdf, 0x6f, 0x30, 0x4b, 0x0e, 0xe5, 0xbc, 0xb1, 0x4b, + 0x82, 0x79, 0x2a, 0xa3, 0xaf, 0xd7, 0x24, 0x3f, 0x57, 0xb7, 0xdc, 0xa7, 0x93, 0x52, + 0x19, 0xdf, 0x98, 0x2c, 0xe1, 0x28, 0xae, 0xa6, 0xf6, 0xbd, 0x18, 0xe1, 0x30, 0x7e, + 0xba, 0x0e, 0x3d, 0xb0, 0x06, 0x14, 0xc2, 0x65, 0xc6, 0xf2, 0x8b, 0xfe, 0x58, 0xc1, + 0x1d, 0x4a, 0xc9, 0x6d, 0x49, 0x02, 0x96, 0x7b, 0x54, 0xbc, 0x5d, 0xd1, 0x5c, 0x14, + 0x3f, 0xf4, 0x2b, 0xbb, 0x62, 0xb9, 0x34, 0xb0, 0x9e, 0x79, 0xb6, 0x1e, 0xaf, 0xe7, + 0x9a, 0xbc, 0x86, 0x94, 0x47, 0x5b, 0x6c, 0x8e, 0x19, 0x94, 0xba, 0x05, 0x5e, 0xa3, + 0xc1, 0x82, 0x93, 0xb0, 0x3c, 0x42, 0x49, 0x50, 0x1d, 0xfd, 0xc0, 0x14, 0x60, 0xcf, + 0x78, 0xcd, 0x97, 0x51, 0x30, 0xae, 0x34, 0x05, 0xba, 0x7d, 0xdc, 0x71, 0x30, 0xcb, + 0xdb, 0xb9, 0x8c, 0x7a, 0xaf, 0x6b, 0x1d, 0x0b, 0x44, 0xa5, 0x16, 0x79, 0xaa, 0x63, + 0x0a, 0x43, 0xae, 0x23, 0xb3, 0xd2, 0x2f, 0x73, 0x4c, 0xe1, 0xdb, 0xed, 0xea, 0x17, + 0x5a, 0x00, 0x62, 0xb0, 0x6e, 0x23, 0xf4, 0xd0, 0x6d, 0x2a, 0xd0, 0x45, 0xae, 0x98, + 0x2d, 0xb4, 0x34, 0x8f, 0x20, 0xc8, 0x9b, 0xf9, 0x67, 0x0e, 0x2f, 0xda, 0x47, 0x2e, + 0x55, 0xce, 0x4c, 0x35, 0x82, 0xb7, 0x64, 0x43, 0xe0, 0xab, 0xbb, 0x77, 0x8a, 0xec, + 0xa0, 0xf3, 0x9c, 0x55, 0xb6, 0xab, 0xbe, 0xd8, 0x1f, 0xde, 0x89, 0xad, 0x2c, 0x56, + 0x7d, 0xfe, 0x27, 0x7b, 0xb2, 0x69, 0xac, 0x6a, 0xe0, 0xe1, 0x88, 0x39, 0x8d, 0xea, + 0x24, 0xad, 0xcc, 0xe1, 0x82, 0xe7, 0xfd, 0xdc, 0x80, 0xeb, 0xd7, 0x69, 0xd0, 0xf0, + 0x76, 0xf9, 0xaf, 0x2d, 0xd9, 0x83, 0x07, 0xa5, 0x27, 0xc6, 0x99, 0x42, 0xdf, 0xa3, + 0xe7, 0xf4, 0x86, 0x76, 0x10, 0x1a, 0x47, 0xeb, 0x07, 0x80, 0xb6, 0x90, 0xb1, 0xaf, + 0x10, 0xfc, 0xfb, 0x5e, 0xe2, 0xbd, 0x40, 0xd2, 0x7d, 0x10, 0x9b, 0xa1, 0x5a, 0xb0, + 0xb1, 0xe9, 0x55, 0x4f, 0xdd, 0xfa, 0x81, 0x6b, 0x99, 0xcd, 0x8f, 0xdd, 0xe6, 0x81, + 0xae, 0x6b, 0x6c, 0xbb, 0xfb, 0xf0, 0x2c, 0x36, 0x32, 0x68, 0xd0, 0xf3, 0xc6, 0xa7, + 0x26, 0x1b, 0x6d, 0x00, 0x87, 0xbc, 0xad, 0xb6, 0xfb, 0x9b, 0xf3, 0x93, 0x04, 0xfc, + 0x08, 0x41, 0x5d, 0x83, 0x6f, 0xe4, 0x09, 0xa4, 0x3f, 0xaf, 0x9e, 0x28, 0xfb, 0x48, + 0x3f, 0x4a, 0x47, 0xaa, 0xd7, 0xe1, 0xf7, 0x97, 0x30, 0xb3, 0x21, 0x53, 0x60, 0x80, + 0xdb, 0x35, 0x12, 0x48, 0xb2, 0x66, 0x9b, 0x6e, 0x74, 0x48, 0x90, 0x87, 0xae, 0x72, + 0xba, 0x15, 0xd2, 0xae, 0xdd, 0x0c, 0x1e, 0x7e, 0xb1, 0x5a, 0x2f, 0x5a, 0x77, 0x31, + 0xeb, 0x45, 0xa6, 0x17, 0x8a, 0x44, 0x87, 0x09, 0x31, 0xec, 0x8e, 0x34, 0x8c, 0x19, + 0x2b, 0xc8, 0x87, 0xc8, 0x63, 0x60, 0x56, 0x67, 0x6f, 0x58, 0xd0, 0xc6, 0x34, 0xfc, + 0x99, 0xea, 0x7b, 0x07, 0xfa, 0x1b, 0x62, 0x99, 0xae, 0x5d, 0xbf, 0xe0, 0x84, 0x45, + 0xad, 0x99, 0x9f, 0x45, 0xdf, 0x00, 0xf1, 0xa4, 0x7a, 0xa5, 0xef, 0x6f, 0x88, 0xcd, + 0xba, 0x80, 0xc8, 0x8f, 0x94, 0x01, 0xe6, 0xe9, 0x09, 0xca, 0x2c, 0x5d, 0xe2, 0xcf, + 0x8f, 0x6a, 0x98, 0x44, 0xca, 0x32, 0xfe, 0x91, 0xf7, 0x13, 0xfe, 0x10, 0xa0, 0x69, + 0x8a, 0x1b, 0x3b, 0xfd, 0xf4, 0x47, 0x43, 0x75, 0xb4, 0x79, 0x1d, 0xc8, 0x50, 0x50, + 0xc9, 0x28, 0x90, 0x0e, 0x73, 0x1f, 0x7c, 0x4a, 0x12, 0x9d, 0x8e, 0x21, 0xfc, 0xf4, + 0x17, 0x62, 0x7c, 0x47, 0xdd, 0xc9, 0xf5, 0x88, 0x40, 0x38, 0x41, 0x31, 0x7a, 0x9a, + 0xc2, 0x6e, 0xef, 0x6c, 0xda, 0x23, ], ock: [ - 0x8b, 0x0d, 0x29, 0x8e, 0xe8, 0xb4, 0x25, 0x34, 0xa4, 0x2f, 0xb9, 0x63, 0x5b, 0xa7, - 0x58, 0xea, 0x9f, 0x91, 0x8b, 0x83, 0x16, 0xc0, 0xe8, 0x94, 0xa9, 0x08, 0x48, 0x89, - 0x01, 0xd9, 0xfb, 0xa3, + 0x9c, 0x10, 0x3d, 0xd5, 0xd6, 0x38, 0x6c, 0xdd, 0x67, 0x69, 0x51, 0xe6, 0x56, 0x4b, + 0x16, 0x6b, 0xc5, 0xc5, 0x72, 0x32, 0xcf, 0xc3, 0x1e, 0x0e, 0x69, 0xce, 0x84, 0xda, + 0xe8, 0x32, 0x76, 0xbe, ], op: [ 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, - 0x17, 0x5b, 0xa9, 0x8b, 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, - 0x14, 0x49, 0x72, 0x62, 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, - 0xe2, 0x63, 0xf3, 0xe3, 0x99, 0x07, 0xea, 0x0c, + 0x17, 0x5b, 0xa9, 0x8b, 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, + 0x42, 0x0e, 0xff, 0xd7, 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, + 0x91, 0x90, 0x01, 0xf8, 0x66, 0xa8, 0xe9, 0x2c, ], c_out: [ - 0xf3, 0xbf, 0x90, 0x76, 0xf3, 0xdb, 0x66, 0x32, 0x6d, 0xa6, 0x0c, 0xc7, 0x94, 0x3c, - 0x85, 0x4d, 0x8d, 0xe9, 0x9f, 0x57, 0x53, 0xf7, 0x0c, 0x32, 0xed, 0x01, 0xfb, 0x2e, - 0x84, 0x9c, 0x9d, 0xc7, 0x3f, 0x80, 0xb5, 0xcb, 0xaa, 0xb4, 0x99, 0x2d, 0xd7, 0xe7, - 0x38, 0xb9, 0x61, 0xfd, 0x75, 0x3f, 0x7c, 0x5b, 0x29, 0x24, 0xd1, 0xd9, 0x63, 0x06, - 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, - 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, + 0xdf, 0x6b, 0xb6, 0x2e, 0x3b, 0x64, 0xf7, 0xe9, 0x37, 0xc1, 0xde, 0x38, 0xaa, 0xc5, + 0xe6, 0xb1, 0x61, 0x35, 0xba, 0x2f, 0x9d, 0xbe, 0xed, 0xb0, 0x7a, 0x45, 0xb6, 0xf0, + 0x9d, 0xf3, 0xeb, 0xec, 0xac, 0x04, 0x6c, 0x61, 0x92, 0xfb, 0xe8, 0x95, 0xd2, 0x31, + 0x02, 0x77, 0xb3, 0xe0, 0x3a, 0x90, 0xfd, 0xc8, 0x53, 0x48, 0x4a, 0x01, 0x5c, 0x88, + 0xd6, 0x63, 0x2e, 0x97, 0xba, 0x98, 0xad, 0xca, 0x9e, 0x49, 0xf5, 0x38, 0xc3, 0xa7, + 0xcb, 0x6d, 0x77, 0x23, 0xbd, 0xcc, 0x9c, 0x03, 0xae, 0x88, ], }, TestVector { @@ -1782,29 +1783,29 @@ pub(crate) fn test_vectors() -> Vec { 0x31, 0xe4, 0x8c, 0x0c, ], cmx: [ - 0x6d, 0x29, 0x97, 0xd1, 0xce, 0x0a, 0x94, 0x9a, 0x63, 0x70, 0x0f, 0x46, 0x1b, 0x57, - 0x12, 0xae, 0xeb, 0x43, 0xd4, 0x55, 0x04, 0xe3, 0x5b, 0xda, 0x16, 0x52, 0x97, 0x77, - 0xc7, 0x4d, 0x19, 0x1b, + 0xde, 0x7b, 0xf1, 0x55, 0x08, 0x29, 0x51, 0x96, 0x0a, 0x10, 0xbb, 0x8b, 0x75, 0x41, + 0x02, 0x43, 0x0f, 0x89, 0xf5, 0x32, 0x67, 0x24, 0x04, 0x36, 0x81, 0xf5, 0x06, 0xf7, + 0x48, 0xe2, 0x6f, 0x07, ], esk: [ - 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, 0x6b, 0xa0, 0x02, 0x0c, - 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, 0x57, 0x32, 0x63, 0xf4, - 0x99, 0xbd, 0x4c, 0x13, + 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, 0x59, 0xa1, 0x33, 0xf3, + 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, 0xdd, 0x63, 0xe0, 0x62, + 0x83, 0x05, 0x47, 0x08, ], ephemeral_key: [ - 0xe4, 0x76, 0x95, 0x86, 0x30, 0x4a, 0x6a, 0x9b, 0x3a, 0x2a, 0xef, 0x3a, 0xf5, 0x8b, - 0x97, 0xda, 0xc2, 0xcc, 0x4a, 0xeb, 0x38, 0x9f, 0x68, 0xc1, 0x28, 0x87, 0x73, 0x1e, - 0x0e, 0x12, 0xbc, 0x1e, + 0x18, 0x20, 0x84, 0x5b, 0x2d, 0x90, 0xe5, 0x45, 0x76, 0x0f, 0xca, 0x4d, 0xab, 0x30, + 0xa6, 0x78, 0x3e, 0x03, 0x1c, 0x0e, 0x54, 0x28, 0xcc, 0x22, 0x6f, 0x3f, 0x40, 0x1d, + 0xec, 0x20, 0x0b, 0x11, ], shared_secret: [ - 0xf6, 0xba, 0x4b, 0x1f, 0xbe, 0x01, 0xfa, 0x2f, 0x1d, 0xd4, 0x09, 0x3c, 0x5c, 0xc4, - 0x85, 0xa9, 0xbf, 0xd9, 0xef, 0x0f, 0x57, 0x89, 0x49, 0xd6, 0xe1, 0x00, 0xb0, 0x05, - 0x5c, 0xb8, 0xf3, 0x31, + 0x79, 0x38, 0x77, 0xa1, 0xae, 0xda, 0xe9, 0xac, 0x6d, 0xa3, 0xd7, 0xe8, 0x02, 0xb5, + 0xbc, 0x77, 0x3c, 0x0d, 0x93, 0x1c, 0x79, 0x6d, 0x17, 0x0c, 0x59, 0x7f, 0x22, 0xba, + 0x6f, 0xcc, 0xa2, 0x06, ], k_enc: [ - 0xd3, 0xc2, 0x20, 0x51, 0x00, 0x3e, 0x88, 0x2a, 0x5d, 0xdd, 0xfb, 0x48, 0x23, 0xd6, - 0x77, 0x26, 0x96, 0xa7, 0xe9, 0x9f, 0x26, 0xb1, 0xa6, 0xac, 0xd2, 0x4b, 0xee, 0xd5, - 0xf2, 0x2f, 0x9f, 0xf8, + 0x28, 0x20, 0xb9, 0x38, 0xd6, 0xfc, 0xea, 0x99, 0xa7, 0x23, 0x37, 0x50, 0xa0, 0xf0, + 0x9a, 0x32, 0x10, 0xad, 0x91, 0x73, 0x46, 0x16, 0x6a, 0xea, 0xdc, 0x89, 0xbb, 0x50, + 0xf4, 0x54, 0x50, 0xa3, ], p_enc: [ 0x02, 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, 0x22, 0x92, @@ -1850,68 +1851,68 @@ pub(crate) fn test_vectors() -> Vec { 0x3e, 0xcc, 0xc6, 0x23, ], c_enc: [ - 0x72, 0x29, 0xa0, 0xa5, 0x6a, 0x14, 0x4b, 0x04, 0x2c, 0x1e, 0xad, 0x91, 0x80, 0xac, - 0x54, 0xda, 0xc6, 0xc5, 0x5c, 0xf4, 0xc2, 0x2f, 0xbe, 0x7c, 0xde, 0x99, 0x96, 0x0b, - 0xc6, 0x20, 0xd4, 0xdd, 0x60, 0xe4, 0xbf, 0x18, 0xa0, 0xea, 0x7a, 0xd9, 0x09, 0x3b, - 0xcd, 0x3f, 0xf6, 0xd1, 0x61, 0x1c, 0x56, 0x5f, 0x88, 0xe7, 0x35, 0xef, 0x4c, 0x51, - 0x8c, 0x77, 0xd6, 0x22, 0x28, 0xe1, 0xe4, 0xa1, 0x35, 0xca, 0x6c, 0xb4, 0xed, 0x5a, - 0xbb, 0xdf, 0x3e, 0x81, 0xd0, 0x96, 0x50, 0xa8, 0xfa, 0x9b, 0x5c, 0x3d, 0x05, 0xb6, - 0xda, 0xcf, 0x3c, 0x3d, 0xb3, 0xb3, 0x63, 0xe4, 0x10, 0x57, 0x23, 0x70, 0x0c, 0x69, - 0x13, 0x9f, 0x81, 0xec, 0xc4, 0x8d, 0x88, 0x3d, 0xa0, 0x39, 0xdd, 0xed, 0x5e, 0xf6, - 0x04, 0x0a, 0xb2, 0x12, 0x0e, 0x53, 0x3b, 0x1f, 0xfd, 0x06, 0x74, 0xdb, 0x5b, 0x92, - 0x6e, 0x58, 0x7f, 0x16, 0xe7, 0xe8, 0x96, 0x2b, 0x12, 0x48, 0x35, 0xbd, 0x56, 0xcf, - 0xd8, 0xe7, 0x5b, 0xf6, 0xaa, 0x4d, 0xcd, 0x4d, 0x6f, 0x0b, 0x55, 0x61, 0x71, 0x9c, - 0x80, 0xaa, 0x82, 0xb3, 0xbc, 0xea, 0x16, 0x7a, 0x31, 0xc6, 0x69, 0x87, 0x61, 0xe2, - 0xd2, 0x6c, 0xb5, 0x6d, 0xd3, 0x04, 0x16, 0x72, 0x1c, 0x93, 0x37, 0x32, 0x92, 0x85, - 0x33, 0x58, 0xfa, 0xfe, 0x74, 0x95, 0x55, 0x8d, 0xb9, 0x9e, 0x47, 0xa3, 0xa1, 0x6e, - 0xd2, 0x2c, 0xdb, 0x9d, 0x7d, 0x16, 0xcf, 0xd9, 0xa7, 0xbb, 0x55, 0x9c, 0x72, 0x86, - 0xed, 0x84, 0xf8, 0x89, 0x9c, 0xb0, 0x52, 0x2e, 0x8a, 0x49, 0x7f, 0x3e, 0x14, 0x45, - 0x2b, 0xa8, 0xa9, 0x4a, 0x7f, 0x58, 0xe5, 0xde, 0x37, 0x1d, 0x76, 0xec, 0xc9, 0xef, - 0xe2, 0x0a, 0xe7, 0x9b, 0xee, 0x12, 0xbc, 0xe4, 0xe4, 0xb6, 0xf2, 0x35, 0x35, 0xe5, - 0xc3, 0xc4, 0x3a, 0x4c, 0xa2, 0x07, 0x6f, 0xd6, 0x73, 0xf0, 0x80, 0x6f, 0xa9, 0x85, - 0xc5, 0x88, 0xd1, 0x14, 0xc0, 0x7d, 0x8c, 0xe3, 0xa2, 0x33, 0xe5, 0x4d, 0x77, 0x11, - 0x6c, 0x8a, 0x2a, 0x56, 0xa6, 0x82, 0xe7, 0xa4, 0x85, 0xdf, 0x71, 0xb3, 0x02, 0xa0, - 0x36, 0xdd, 0xab, 0x21, 0x4d, 0xee, 0x77, 0x62, 0x19, 0xcc, 0x24, 0x25, 0x94, 0xf7, - 0x5b, 0x8e, 0xbd, 0x56, 0x6d, 0x74, 0xb1, 0x6c, 0x9e, 0xc0, 0x05, 0x8b, 0xca, 0x28, - 0x81, 0xb7, 0x9b, 0x10, 0xe8, 0xa8, 0x01, 0x08, 0x20, 0x61, 0x8a, 0xc6, 0x52, 0x6c, - 0xf9, 0x4b, 0x13, 0xd9, 0x75, 0x9f, 0x37, 0x33, 0x93, 0x34, 0xe8, 0xb2, 0xc6, 0xbd, - 0xd1, 0xd0, 0xf5, 0xe2, 0x46, 0x3c, 0xff, 0x2b, 0x8d, 0xa6, 0xd2, 0xc6, 0x86, 0xaa, - 0x98, 0x7c, 0xd1, 0xf0, 0x7e, 0x9a, 0xa2, 0x60, 0xdd, 0x04, 0x28, 0xa4, 0xff, 0x78, - 0xaa, 0x8f, 0xda, 0x47, 0x7a, 0xb3, 0x8a, 0xcf, 0xcc, 0xb1, 0x90, 0x91, 0x77, 0xb5, - 0x27, 0xe9, 0x38, 0xf1, 0xf9, 0xdc, 0xf3, 0x1f, 0x4f, 0x40, 0xa9, 0x62, 0x89, 0x51, - 0xfc, 0x2a, 0x7a, 0xbc, 0x04, 0x1e, 0x8c, 0x93, 0x36, 0x08, 0xbb, 0x47, 0xb4, 0x50, - 0xb2, 0x8f, 0xee, 0xe0, 0x41, 0x58, 0xa8, 0x17, 0x4b, 0xff, 0xe4, 0x97, 0x06, 0x02, - 0x48, 0x86, 0x42, 0xc1, 0x9e, 0x61, 0xd4, 0x73, 0xf3, 0xde, 0x0c, 0xb0, 0xb6, 0x4a, - 0x30, 0xd6, 0xf1, 0x46, 0x68, 0xd1, 0xb0, 0x17, 0x77, 0x56, 0x6f, 0xb5, 0xac, 0xc2, - 0xe9, 0x2e, 0x64, 0xd9, 0x75, 0x7f, 0xba, 0x13, 0xc1, 0xee, 0x9c, 0xd0, 0x3a, 0xbe, - 0x98, 0xbd, 0x7e, 0x8a, 0xd7, 0x04, 0x1c, 0x3f, 0xea, 0xe7, 0xc1, 0xa7, 0x24, 0x3a, - 0xe3, 0x61, 0x0a, 0xac, 0x64, 0xfe, 0xc6, 0xc9, 0xfc, 0x94, 0x3d, 0x6a, 0xbc, 0xe9, - 0x10, 0xad, 0xbe, 0x23, 0xb5, 0x46, 0xb4, 0xc2, 0x4a, 0xa9, 0xf2, 0xce, 0x5d, 0x97, - 0x06, 0x2e, 0xe0, 0xd1, 0xcc, 0xc4, 0x8c, 0xfd, 0x1f, 0xdb, 0xa7, 0xfd, 0xac, 0x0b, - 0x04, 0xd1, 0xb3, 0xdc, 0x7a, 0x70, 0x78, 0x1c, 0xdd, 0xa2, 0xa2, 0x70, 0x3d, 0xe0, - 0x03, 0xcd, 0x01, 0x51, 0xec, 0x65, 0xbf, 0x7d, 0x1a, 0xc6, 0x3b, 0xb7, 0x35, 0xbc, - 0x2b, 0xb6, 0x7a, 0xd2, 0xb0, 0x1e, 0xd6, 0xb9, 0xae, 0x2e, 0xbb, 0xd3, 0x7a, 0x8f, - 0x8e, 0xc1, 0xa6, 0x53, 0xa8, 0x7e, + 0xd9, 0x6a, 0xe8, 0x2f, 0xba, 0xff, 0xb9, 0xe4, 0xbd, 0x36, 0x47, 0x57, 0x96, 0x33, + 0xbc, 0x8a, 0x89, 0x66, 0xae, 0x4e, 0x18, 0x85, 0x99, 0xdc, 0x3c, 0xf0, 0x30, 0x41, + 0xd2, 0x64, 0x4f, 0x60, 0x3c, 0xe5, 0x56, 0x2e, 0x7f, 0xa1, 0xd3, 0x83, 0x12, 0x79, + 0xb6, 0x32, 0x60, 0x4d, 0x06, 0x5e, 0xd2, 0x46, 0xad, 0x2d, 0x4f, 0x73, 0xf3, 0xa4, + 0x1b, 0x2a, 0x27, 0x99, 0xe5, 0xba, 0xf8, 0x6e, 0x7d, 0x9f, 0xcc, 0x64, 0xd5, 0x6b, + 0xde, 0x56, 0xcb, 0xb0, 0x01, 0xeb, 0x7c, 0x7c, 0x0c, 0xf1, 0xe2, 0xae, 0xc3, 0xce, + 0xb1, 0x49, 0x2d, 0xdf, 0x4e, 0x35, 0x20, 0x76, 0x1f, 0x70, 0xf6, 0xa9, 0x5c, 0x9e, + 0xde, 0xed, 0x51, 0x43, 0x6d, 0xca, 0xcf, 0x71, 0x1e, 0xb5, 0x53, 0x24, 0xd3, 0xf0, + 0x1d, 0xcc, 0xa0, 0x1b, 0xca, 0x15, 0xba, 0xf2, 0x8f, 0xed, 0x81, 0x4c, 0xc3, 0x3a, + 0x43, 0x6b, 0xbc, 0x08, 0x60, 0x56, 0x78, 0x55, 0xa4, 0x9f, 0x5e, 0xfd, 0x49, 0xea, + 0x78, 0x30, 0xc2, 0xf6, 0x00, 0x61, 0xd8, 0x13, 0xa8, 0x49, 0xb4, 0x40, 0xb1, 0x2e, + 0x8f, 0x31, 0xe2, 0xdc, 0x0c, 0x39, 0x4c, 0xeb, 0x92, 0x4f, 0x0d, 0xc6, 0xd5, 0x7b, + 0xcc, 0x39, 0x1d, 0x4a, 0x5f, 0x56, 0x9f, 0x34, 0x74, 0x6b, 0x9d, 0x92, 0x08, 0x82, + 0x25, 0xb1, 0xaa, 0x3e, 0x90, 0x6f, 0x6d, 0xe4, 0xa7, 0x92, 0x2a, 0xc1, 0x16, 0xac, + 0xb2, 0x78, 0xe8, 0xef, 0xbb, 0xf6, 0xf1, 0xe3, 0xe0, 0x8d, 0x66, 0xb3, 0x4d, 0x6e, + 0xde, 0x34, 0xae, 0x78, 0x40, 0xa8, 0x80, 0x2b, 0x7c, 0x10, 0x0f, 0xa7, 0x98, 0x46, + 0x4d, 0xb5, 0x29, 0x45, 0xdb, 0xbe, 0x35, 0xe7, 0x7a, 0x77, 0x21, 0xb2, 0xe0, 0xf8, + 0xb9, 0xa1, 0x0f, 0x6b, 0xf9, 0xa2, 0x80, 0x8f, 0xa5, 0x85, 0xff, 0x21, 0xb0, 0xa3, + 0xaf, 0xfd, 0x5f, 0x3c, 0xb2, 0x30, 0x63, 0x4e, 0x2e, 0x43, 0xff, 0xde, 0x6d, 0x09, + 0x0a, 0xfc, 0xc6, 0x70, 0x4d, 0x7b, 0x3f, 0xc6, 0x15, 0x44, 0x85, 0x3b, 0xcd, 0xa7, + 0xa1, 0x06, 0xd8, 0x5b, 0xd8, 0xd8, 0x6c, 0x6f, 0x8c, 0xe0, 0x34, 0x01, 0x6e, 0xd9, + 0xa3, 0x69, 0x46, 0xf8, 0x52, 0x8b, 0x6f, 0x1e, 0x1a, 0x19, 0x82, 0xd6, 0x8d, 0x38, + 0x86, 0xe5, 0xea, 0xe6, 0xc1, 0xe3, 0x88, 0xf3, 0xde, 0xad, 0x0d, 0x35, 0x3b, 0x6c, + 0x0c, 0xbf, 0x57, 0xc2, 0xe4, 0x7d, 0x30, 0x72, 0x3e, 0xac, 0x95, 0x7b, 0x4a, 0xec, + 0x82, 0xc8, 0xa1, 0x00, 0x9e, 0x3d, 0x71, 0x96, 0x92, 0xb2, 0xfc, 0xbd, 0xda, 0xae, + 0x62, 0x5a, 0x89, 0x6a, 0x47, 0x29, 0x85, 0xb7, 0x9e, 0xb6, 0x2b, 0x1f, 0xe3, 0x3d, + 0x6e, 0x27, 0xbc, 0x1f, 0x10, 0xe4, 0xfe, 0x5c, 0x06, 0xb2, 0x4c, 0x59, 0x7f, 0x72, + 0x3c, 0x67, 0x13, 0x36, 0x13, 0xae, 0x8e, 0x15, 0x4d, 0x81, 0x69, 0x78, 0xb8, 0xfc, + 0xa6, 0x50, 0xc0, 0x1d, 0x77, 0x1a, 0x62, 0x69, 0x2a, 0x84, 0x82, 0x94, 0x2e, 0x28, + 0xfe, 0xf0, 0x45, 0x19, 0x9e, 0xd1, 0xa6, 0x64, 0x99, 0xeb, 0xa1, 0xee, 0xc1, 0x9a, + 0xc8, 0x4a, 0x12, 0xe4, 0x10, 0x29, 0xd2, 0x2f, 0x21, 0x87, 0x6e, 0xd7, 0x4a, 0x76, + 0xef, 0x39, 0xa0, 0x57, 0xce, 0x0a, 0x15, 0x8e, 0x68, 0x51, 0xec, 0x35, 0x6d, 0x97, + 0x7b, 0x1a, 0xa6, 0x8d, 0xcf, 0x70, 0x88, 0xa9, 0xf0, 0xf9, 0xe4, 0x75, 0xa2, 0xbb, + 0xc1, 0xc4, 0x49, 0x5b, 0x54, 0x6f, 0xff, 0xed, 0xaa, 0x66, 0xc4, 0xf9, 0x51, 0x74, + 0xc6, 0x2f, 0x56, 0x5a, 0x3c, 0xc0, 0xac, 0xaf, 0x85, 0x4a, 0xde, 0xd4, 0xb4, 0x25, + 0xa0, 0xc7, 0xdb, 0xcd, 0x37, 0x42, 0xa7, 0xe0, 0x59, 0x2e, 0x83, 0x73, 0x41, 0xf8, + 0x95, 0x32, 0x90, 0x99, 0xe1, 0x70, 0xb6, 0xff, 0xb1, 0x05, 0xfd, 0xbc, 0x77, 0x29, + 0x8e, 0x8c, 0x0f, 0x5e, 0xeb, 0x9e, 0x99, 0xc6, 0x58, 0x4b, 0xcf, 0xf1, 0x20, 0x20, + 0x9d, 0x69, 0x22, 0xb5, 0x34, 0xbe, 0xc9, 0xfa, 0xc1, 0xd7, 0xd2, 0x74, 0xdb, 0xcb, + 0x4a, 0x12, 0xea, 0x5a, 0x99, 0x21, 0x39, 0x2f, 0x00, 0x96, 0x60, 0x29, 0xff, 0x26, + 0x0e, 0xd2, 0x4c, 0x32, 0x78, 0x58, 0xe0, 0x34, 0x64, 0x0a, 0x8c, 0xfb, 0x28, 0xad, + 0x97, 0xe5, 0x3d, 0x80, 0xe1, 0xc9, ], ock: [ - 0x1b, 0xa4, 0xac, 0xd7, 0x75, 0x10, 0xc4, 0xf0, 0xc7, 0x66, 0xad, 0xf7, 0xc7, 0xdf, - 0x1d, 0x1c, 0x54, 0xd5, 0xbc, 0xe3, 0xd6, 0x0a, 0xf3, 0x5e, 0x8d, 0xd4, 0x8f, 0xdd, - 0x04, 0xa7, 0x8c, 0x0b, + 0x28, 0xcf, 0x3b, 0xea, 0xc3, 0xbd, 0xe2, 0xe9, 0x63, 0xaa, 0x60, 0x91, 0x3f, 0x10, + 0x5d, 0x25, 0x67, 0xcd, 0xaf, 0xbb, 0x66, 0x09, 0x08, 0x5a, 0x84, 0x3f, 0x75, 0x68, + 0xe4, 0x92, 0xd4, 0x4e, ], op: [ 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, - 0x01, 0x70, 0x89, 0x1a, 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, - 0x6b, 0xa0, 0x02, 0x0c, 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, - 0x57, 0x32, 0x63, 0xf4, 0x99, 0xbd, 0x4c, 0x13, + 0x01, 0x70, 0x89, 0x1a, 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, + 0x59, 0xa1, 0x33, 0xf3, 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, + 0xdd, 0x63, 0xe0, 0x62, 0x83, 0x05, 0x47, 0x08, ], c_out: [ - 0x43, 0x0d, 0xaa, 0x6b, 0x75, 0x63, 0x22, 0x80, 0xd5, 0xe6, 0xda, 0xcb, 0xd2, 0xa0, - 0xff, 0xe2, 0xaf, 0x98, 0x60, 0xc8, 0x3a, 0x3d, 0x2a, 0x87, 0xf1, 0x79, 0x62, 0x88, - 0xeb, 0xed, 0x64, 0xd0, 0xcd, 0xc4, 0x60, 0xe2, 0xc8, 0x61, 0xc4, 0xf9, 0x38, 0x7d, - 0x92, 0x59, 0xfc, 0x60, 0x01, 0xac, 0xd0, 0xe7, 0x6f, 0x3b, 0x0f, 0xdb, 0x5d, 0xac, - 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, - 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, + 0x0b, 0x2c, 0xc0, 0xa2, 0x2d, 0x06, 0xfc, 0x36, 0xa0, 0x8a, 0x7d, 0x82, 0x33, 0x8d, + 0x4a, 0xd0, 0x95, 0xa3, 0x93, 0xa1, 0xc2, 0x4a, 0x78, 0x8d, 0x45, 0x24, 0x35, 0x94, + 0x4a, 0xcc, 0xe6, 0x38, 0x1e, 0xcc, 0x69, 0x37, 0xf2, 0xc3, 0x8c, 0x89, 0xa5, 0xf5, + 0x1a, 0xa6, 0x0c, 0xa6, 0x58, 0xfe, 0x71, 0x37, 0x1c, 0x2a, 0x83, 0xf4, 0x96, 0xca, + 0x2e, 0x62, 0x49, 0x79, 0x2e, 0x09, 0xeb, 0x79, 0xea, 0x3a, 0x13, 0x80, 0x32, 0x18, + 0xff, 0x20, 0x88, 0x9d, 0x8c, 0x59, 0xc8, 0x5e, 0x90, 0x99, ], }, TestVector { @@ -1992,29 +1993,29 @@ pub(crate) fn test_vectors() -> Vec { 0xd3, 0x5c, 0x60, 0x12, ], cmx: [ - 0x6a, 0xba, 0x28, 0x10, 0x5b, 0xc0, 0x72, 0xc5, 0x2a, 0xb8, 0xa3, 0x14, 0x79, 0x7f, - 0xf8, 0x66, 0x66, 0xdf, 0xb7, 0xcd, 0x8a, 0x2a, 0xe1, 0x7c, 0x58, 0x5f, 0xb7, 0xb6, - 0x51, 0x5b, 0x97, 0x1c, + 0x4d, 0xa9, 0xdf, 0xdc, 0x70, 0x8c, 0xe8, 0xa0, 0x77, 0xa0, 0x6e, 0xc0, 0x67, 0x79, + 0x24, 0xcf, 0x37, 0x70, 0xed, 0xc2, 0x07, 0xfd, 0x5e, 0x7d, 0x69, 0x5f, 0x71, 0xb0, + 0x15, 0xbb, 0x03, 0x05, ], esk: [ - 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, 0xd5, 0x64, 0x6b, 0xc4, - 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, 0x15, 0x5b, 0xef, 0x4d, - 0x46, 0x1e, 0xec, 0x29, + 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, 0x52, 0x6d, 0x66, 0x54, + 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, 0xfb, 0xee, 0x5d, 0xe3, + 0x99, 0xca, 0x31, 0x26, ], ephemeral_key: [ - 0x95, 0x9b, 0xea, 0x8e, 0x11, 0x96, 0x8b, 0x0f, 0x34, 0x3c, 0x04, 0xcd, 0x6d, 0x50, - 0x16, 0xfc, 0xd4, 0x33, 0x90, 0x75, 0x36, 0xa2, 0x46, 0xba, 0x1c, 0x5d, 0x3e, 0x88, - 0x97, 0xf3, 0x23, 0x1c, + 0x2d, 0xa0, 0x59, 0x4c, 0xd8, 0x74, 0x91, 0x46, 0x52, 0x67, 0xe7, 0x2c, 0x61, 0x89, + 0x07, 0x91, 0xfe, 0xb4, 0x25, 0xa2, 0xbb, 0xcd, 0xda, 0xcf, 0xe4, 0x5a, 0x66, 0x62, + 0x2f, 0x49, 0xef, 0x35, ], shared_secret: [ - 0xe2, 0x69, 0x19, 0xb4, 0x0c, 0x70, 0xaf, 0x74, 0x1d, 0xf9, 0x04, 0x51, 0x72, 0x55, - 0x03, 0x58, 0x89, 0xee, 0x5a, 0x44, 0x42, 0x6d, 0x6a, 0xb8, 0x5c, 0x07, 0x4b, 0x86, - 0x2b, 0xa0, 0x63, 0x08, + 0xe0, 0xb1, 0x52, 0x67, 0xfd, 0x21, 0x08, 0xeb, 0xbd, 0xd4, 0x16, 0x3f, 0x83, 0xad, + 0xef, 0xb6, 0x1c, 0x3e, 0xdf, 0x56, 0x6d, 0x94, 0x6f, 0xa1, 0xc1, 0x5e, 0x96, 0x46, + 0x43, 0xb1, 0x9c, 0x8e, ], k_enc: [ - 0x09, 0xda, 0xc6, 0x51, 0x1c, 0x38, 0x44, 0x58, 0x7f, 0x82, 0x9c, 0x2f, 0x1e, 0xa0, - 0x37, 0xa8, 0x1a, 0x8d, 0x54, 0x85, 0xed, 0x04, 0xea, 0xf2, 0x75, 0x80, 0x05, 0xb3, - 0x2a, 0x20, 0x47, 0x0b, + 0x28, 0x48, 0xae, 0x53, 0xaa, 0xce, 0xbe, 0x7c, 0xab, 0x58, 0x73, 0x1d, 0xc2, 0x21, + 0x88, 0x1b, 0x60, 0x2c, 0xc5, 0xa5, 0x3b, 0xcc, 0x1f, 0x76, 0xc8, 0x20, 0xb0, 0xea, + 0x13, 0x55, 0x68, 0x8e, ], p_enc: [ 0x02, 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, 0xad, 0x95, @@ -2060,68 +2061,68 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0xc6, 0x38, 0xbf, ], c_enc: [ - 0x7b, 0x59, 0x87, 0x78, 0xa7, 0x28, 0x4d, 0x52, 0xa7, 0x47, 0x77, 0x4c, 0x54, 0xbd, - 0x92, 0x57, 0xb3, 0xf1, 0x7a, 0xf1, 0x3e, 0xcc, 0x72, 0xc0, 0xe3, 0xcd, 0x95, 0xeb, - 0xfa, 0xfa, 0xa3, 0x7d, 0x16, 0x65, 0x15, 0x53, 0xdd, 0x27, 0xf0, 0x1c, 0x9c, 0xf2, - 0x4b, 0x62, 0xd7, 0xdc, 0xfd, 0x52, 0xfa, 0x4b, 0x2b, 0x3b, 0x4a, 0x8c, 0xa9, 0xeb, - 0xfc, 0xe7, 0xf4, 0xfc, 0xec, 0x27, 0xe6, 0x05, 0x8e, 0x44, 0x68, 0xc1, 0x50, 0x10, - 0xd0, 0x17, 0xcb, 0x90, 0x1a, 0xbf, 0xb2, 0x2e, 0xad, 0x86, 0x99, 0x83, 0xf6, 0x9a, - 0xed, 0xf2, 0xda, 0x7d, 0x6a, 0xaf, 0xd1, 0x30, 0x6e, 0xe7, 0x36, 0xf2, 0xdb, 0x33, - 0xbc, 0xe4, 0xb0, 0x9f, 0xca, 0x74, 0x69, 0x2a, 0x52, 0x09, 0xa7, 0x39, 0x2b, 0x7e, - 0xa9, 0x68, 0x5b, 0xe9, 0xec, 0x43, 0x1f, 0xfe, 0x50, 0xf7, 0x0f, 0x90, 0x22, 0x74, - 0x05, 0x03, 0x45, 0x2a, 0xb5, 0x14, 0x92, 0xb1, 0xf7, 0x47, 0x7e, 0xda, 0x42, 0x7b, - 0x42, 0x3a, 0x93, 0x1b, 0x26, 0x38, 0x6c, 0x56, 0xe4, 0x27, 0x86, 0x3d, 0x46, 0xb1, - 0x99, 0xff, 0xa0, 0x8c, 0x52, 0x9f, 0xa5, 0x72, 0x1f, 0x68, 0xe9, 0x14, 0xf6, 0xea, - 0x6a, 0x8a, 0xe6, 0xae, 0xcb, 0xf7, 0x37, 0x47, 0x1e, 0xbd, 0x83, 0xdb, 0xa9, 0xa7, - 0xcd, 0x89, 0x75, 0x66, 0x20, 0x4e, 0x2b, 0xae, 0x63, 0xe3, 0x4e, 0x70, 0x32, 0x51, - 0x02, 0x96, 0x92, 0x0d, 0x7e, 0x7a, 0x7c, 0xcf, 0x0f, 0xeb, 0xe7, 0xa8, 0x33, 0x69, - 0x6a, 0x4b, 0x67, 0x41, 0x88, 0x5e, 0x9b, 0x94, 0x0c, 0x61, 0xdd, 0x8d, 0x44, 0x38, - 0x54, 0x74, 0x15, 0x31, 0x0b, 0x15, 0xcf, 0x18, 0xdc, 0x19, 0x90, 0x07, 0x8c, 0x70, - 0x8b, 0xea, 0xc3, 0x32, 0xa8, 0xe0, 0x81, 0x46, 0xa6, 0x95, 0x8e, 0xa6, 0xf4, 0x3f, - 0xd0, 0xc2, 0xc8, 0xe9, 0x99, 0xaa, 0x4f, 0xdf, 0x1e, 0x77, 0xef, 0xde, 0x54, 0xfd, - 0x65, 0xc6, 0x7a, 0x3f, 0x07, 0xda, 0xf5, 0xf6, 0x04, 0x49, 0x60, 0xa0, 0xb6, 0xdd, - 0x84, 0x1f, 0xf8, 0xb8, 0xa5, 0x92, 0xc7, 0xb1, 0x09, 0x34, 0x2c, 0x73, 0x5c, 0x2a, - 0x0e, 0x37, 0xb3, 0x0b, 0x8b, 0xaa, 0x5c, 0x77, 0x01, 0xeb, 0xc7, 0xa8, 0xf8, 0x20, - 0xc0, 0x22, 0x7c, 0xa5, 0x00, 0x3f, 0x36, 0xee, 0x68, 0xf7, 0xb2, 0x89, 0x81, 0xc2, - 0x73, 0x32, 0x03, 0x9d, 0xd6, 0xa4, 0x94, 0xf0, 0xcd, 0x02, 0xbd, 0xd2, 0x8f, 0x68, - 0x3e, 0xca, 0x1b, 0x03, 0x2a, 0xfc, 0x09, 0xdd, 0x0c, 0xd8, 0x56, 0xcb, 0xc1, 0xa3, - 0x5e, 0x74, 0xd4, 0x0c, 0x24, 0x53, 0xdf, 0xe2, 0x42, 0xc8, 0x6a, 0x7a, 0x60, 0xbc, - 0xbd, 0xdb, 0x17, 0x96, 0x6c, 0x7d, 0xba, 0x76, 0x9e, 0xab, 0xd1, 0xc1, 0x67, 0xb7, - 0xe8, 0x19, 0x78, 0xf9, 0x12, 0x8b, 0xac, 0x26, 0xa2, 0x8d, 0x77, 0x21, 0x30, 0x79, - 0xcb, 0x56, 0xc0, 0x95, 0xa7, 0xc0, 0x60, 0xde, 0x0e, 0x77, 0x5c, 0xa8, 0xac, 0x8e, - 0x6c, 0xa9, 0x4d, 0x19, 0xc6, 0x16, 0x2e, 0x44, 0xf7, 0xa8, 0xf0, 0x14, 0x9d, 0x31, - 0xd3, 0x46, 0x3d, 0x01, 0xb6, 0x1a, 0x14, 0x63, 0xa9, 0xde, 0x3d, 0x8a, 0xb7, 0x40, - 0x04, 0x0a, 0x76, 0xe0, 0x5b, 0x37, 0x64, 0x28, 0x86, 0x29, 0x87, 0x59, 0x5b, 0x87, - 0xce, 0xa6, 0x94, 0xfe, 0x92, 0x0a, 0x06, 0x7e, 0x81, 0x6b, 0x4f, 0x29, 0xa3, 0xa2, - 0x24, 0x50, 0x14, 0x0f, 0x13, 0x5d, 0x71, 0x9a, 0x97, 0x1b, 0x81, 0xfc, 0x19, 0x16, - 0x98, 0x0a, 0x55, 0xdd, 0xf8, 0xd9, 0x87, 0x30, 0x57, 0x36, 0x35, 0xa0, 0x70, 0x85, - 0xc4, 0xe7, 0x7c, 0x7e, 0x1c, 0xdb, 0xb6, 0x85, 0x42, 0x6e, 0xe4, 0x62, 0xcc, 0x30, - 0x83, 0xa3, 0xf5, 0xa3, 0xb9, 0x17, 0xc0, 0x6f, 0x9a, 0x96, 0xf9, 0xf7, 0xbd, 0x81, - 0xac, 0xa4, 0x9b, 0xef, 0x95, 0xb9, 0x28, 0x06, 0xc4, 0x2d, 0x09, 0x12, 0x01, 0x31, - 0x42, 0xb2, 0x2a, 0x7b, 0xad, 0x72, 0x12, 0x11, 0x46, 0x91, 0xf1, 0xdc, 0x72, 0x64, - 0xc6, 0x7e, 0x76, 0x34, 0xf5, 0xd7, 0x95, 0xc9, 0x75, 0x30, 0x62, 0xe3, 0x06, 0xc0, - 0x6b, 0xc1, 0x03, 0xaa, 0x01, 0xc1, 0x0d, 0x1f, 0x5d, 0xd4, 0xcd, 0x59, 0xf6, 0x53, - 0x2c, 0xb7, 0x23, 0xe3, 0xa0, 0x26, + 0xf1, 0x42, 0xc4, 0xe5, 0x0e, 0xef, 0x2c, 0x64, 0x44, 0xcc, 0xd4, 0x0b, 0x8c, 0x99, + 0xe5, 0x6a, 0x72, 0xec, 0x4e, 0x30, 0xcf, 0x73, 0x68, 0x75, 0xf0, 0xaa, 0x6b, 0x8e, + 0x6d, 0x9c, 0xc3, 0x67, 0x73, 0x2d, 0xbc, 0x9a, 0xf0, 0xb3, 0x7d, 0x1f, 0xca, 0x6d, + 0x5b, 0xdd, 0x1d, 0xc1, 0x23, 0x79, 0x29, 0x66, 0x99, 0x9d, 0x62, 0xea, 0xf8, 0xc5, + 0xfe, 0x8d, 0x99, 0x91, 0x84, 0xf2, 0x8b, 0x99, 0xec, 0xef, 0xcc, 0x8f, 0x14, 0x8d, + 0xbd, 0x52, 0x02, 0x6f, 0xdb, 0x48, 0xdf, 0xda, 0x7b, 0xad, 0xb6, 0xd1, 0xfc, 0xd2, + 0x9a, 0xd2, 0x19, 0xea, 0xbf, 0xbb, 0x44, 0x3f, 0x5d, 0x0f, 0x98, 0xb6, 0x6a, 0x3a, + 0x25, 0x73, 0x1b, 0x52, 0xd7, 0xf2, 0xdf, 0x70, 0x01, 0x4b, 0x4a, 0xc6, 0x99, 0x34, + 0x32, 0xf8, 0x98, 0x1e, 0x9c, 0xbf, 0xe1, 0x69, 0x13, 0xf6, 0x8a, 0x93, 0x5d, 0x2d, + 0xd0, 0x06, 0xd4, 0x28, 0xf1, 0x45, 0x53, 0xe7, 0x29, 0x86, 0xc7, 0x0f, 0xb4, 0x43, + 0x18, 0xd2, 0x7c, 0x4d, 0x6f, 0x6f, 0xd3, 0x92, 0x3a, 0xb0, 0xf6, 0x28, 0x9a, 0x02, + 0x48, 0x5e, 0x87, 0x17, 0xe5, 0x7d, 0xa0, 0x24, 0xeb, 0xe1, 0x6e, 0x9c, 0xf8, 0x35, + 0xcf, 0x53, 0xd2, 0x19, 0x4f, 0xd4, 0x25, 0x50, 0x06, 0xb8, 0x1b, 0xfd, 0x51, 0xd1, + 0xef, 0x5a, 0xe9, 0xf9, 0xef, 0x6a, 0xf6, 0x57, 0x41, 0x81, 0xe2, 0xe2, 0x26, 0x50, + 0xcb, 0x91, 0x2a, 0x6b, 0x89, 0x88, 0xa0, 0x28, 0x86, 0x32, 0xbc, 0x73, 0x62, 0xbb, + 0xe1, 0x87, 0x23, 0xd8, 0x27, 0xf7, 0x94, 0x58, 0x62, 0x26, 0x0d, 0xf7, 0x8e, 0x95, + 0xd7, 0xd5, 0xe3, 0x31, 0x3f, 0x5a, 0xff, 0x72, 0xe2, 0x1c, 0xe2, 0xdf, 0x00, 0xee, + 0x7e, 0x81, 0x5a, 0xba, 0x17, 0xcc, 0xde, 0x15, 0xc2, 0x7e, 0xee, 0x08, 0x5f, 0x52, + 0xf3, 0x6c, 0x02, 0xec, 0xd6, 0x6c, 0xe1, 0x8b, 0x40, 0x15, 0xbe, 0xb6, 0x09, 0x23, + 0x3f, 0x6e, 0xb2, 0x8e, 0x4a, 0xd5, 0xcd, 0xbe, 0x6f, 0xdc, 0xab, 0x68, 0xbf, 0xbb, + 0x6f, 0xfd, 0x87, 0xd3, 0x86, 0xd8, 0x7e, 0xb1, 0xfe, 0x00, 0x34, 0x27, 0x0f, 0x41, + 0x27, 0x1e, 0xa0, 0x1f, 0x9e, 0xae, 0xa9, 0xe8, 0x9f, 0x78, 0x35, 0x9e, 0x41, 0x73, + 0x94, 0xbb, 0x9d, 0xf5, 0xb6, 0x1c, 0x36, 0xe3, 0x0b, 0xc1, 0xce, 0x4a, 0xb1, 0xbd, + 0xd7, 0x9f, 0xa4, 0x08, 0x3e, 0x82, 0x8d, 0xd1, 0x04, 0xe4, 0x73, 0x80, 0xcd, 0x83, + 0xcd, 0x65, 0x9d, 0xf4, 0x4d, 0xb9, 0x43, 0xdc, 0x07, 0xbc, 0xc8, 0x07, 0x05, 0x04, + 0xa1, 0xc6, 0x55, 0x23, 0x02, 0xe7, 0x4b, 0xe4, 0xb9, 0xc4, 0x32, 0x75, 0xec, 0xc2, + 0x88, 0xce, 0xda, 0x41, 0x59, 0xa9, 0xcc, 0x55, 0x7c, 0x18, 0x19, 0x5c, 0xec, 0x92, + 0x62, 0x24, 0xd8, 0xd6, 0x9e, 0x98, 0xe1, 0x83, 0x5a, 0x2e, 0x29, 0x05, 0x63, 0xef, + 0x20, 0xd0, 0x83, 0xd1, 0x4e, 0x93, 0xcc, 0x1f, 0x3f, 0x76, 0x3e, 0xf5, 0x58, 0x0e, + 0x13, 0x5f, 0xae, 0x1b, 0xb8, 0x54, 0x4a, 0x0c, 0x5c, 0x6d, 0x88, 0x17, 0x41, 0xe4, + 0x51, 0x34, 0x47, 0xac, 0xeb, 0x09, 0x33, 0xe6, 0xeb, 0xaf, 0x0c, 0xe3, 0x13, 0xc1, + 0x8c, 0x9a, 0xf9, 0x5b, 0xa5, 0x61, 0x31, 0xf7, 0x8f, 0x42, 0x72, 0x41, 0x22, 0x65, + 0xbc, 0xf4, 0xc5, 0xf6, 0x80, 0x89, 0x3c, 0xcd, 0xa5, 0x73, 0x7d, 0xa8, 0x23, 0xb7, + 0x63, 0x6e, 0x98, 0xdb, 0xa5, 0x62, 0x44, 0xf2, 0xb9, 0x6a, 0x10, 0x90, 0xa6, 0x60, + 0x38, 0x15, 0xc0, 0xef, 0x54, 0x97, 0x50, 0xf2, 0x47, 0x06, 0x19, 0x0b, 0x55, 0x76, + 0x6e, 0x8a, 0x62, 0x09, 0xa1, 0xc2, 0x2f, 0x67, 0xe8, 0x77, 0x62, 0x66, 0xb6, 0xfa, + 0xe4, 0x5b, 0xf7, 0x94, 0x90, 0x7f, 0x64, 0x71, 0x4f, 0xbe, 0x26, 0xc3, 0x0a, 0xc4, + 0x04, 0x11, 0xf5, 0xe6, 0x4f, 0xc1, 0x66, 0xc8, 0x4f, 0x28, 0xb8, 0x23, 0xfd, 0xaa, + 0x68, 0x32, 0xa3, 0x25, 0x63, 0x31, 0x7d, 0x25, 0x4c, 0x53, 0x16, 0x9b, 0x9f, 0xfb, + 0x24, 0x53, 0xa1, 0x12, 0x2f, 0xa4, 0x4c, 0x7f, 0x17, 0xc1, 0x36, 0xb5, 0x7e, 0x20, + 0xad, 0x17, 0x7a, 0x7e, 0xee, 0xbf, 0x9f, 0x56, 0xfb, 0x0b, 0x55, 0xcc, 0xcf, 0x68, + 0x2b, 0x8a, 0x5b, 0xd8, 0xa7, 0x45, ], ock: [ - 0x4a, 0x25, 0x25, 0x4c, 0xcc, 0x44, 0x4e, 0xc6, 0x1c, 0x2b, 0xac, 0xeb, 0x2e, 0xe3, - 0x97, 0x7a, 0x63, 0x32, 0x44, 0x9a, 0x3a, 0x53, 0xad, 0xd2, 0x31, 0xab, 0xf3, 0xd1, - 0x8b, 0xb3, 0x29, 0x3d, + 0x06, 0x3c, 0x83, 0xa4, 0x95, 0x74, 0xe7, 0x80, 0x35, 0x89, 0xcc, 0x3d, 0x34, 0xb4, + 0x38, 0x90, 0xf3, 0xd7, 0x63, 0x87, 0x35, 0xe7, 0xbd, 0x5e, 0xbd, 0xd1, 0xa5, 0xea, + 0xb9, 0xd9, 0xc5, 0xd6, ], op: [ 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, - 0x44, 0x6d, 0xf4, 0x39, 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, - 0xd5, 0x64, 0x6b, 0xc4, 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, - 0x15, 0x5b, 0xef, 0x4d, 0x46, 0x1e, 0xec, 0x29, + 0x44, 0x6d, 0xf4, 0x39, 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, + 0x52, 0x6d, 0x66, 0x54, 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, + 0xfb, 0xee, 0x5d, 0xe3, 0x99, 0xca, 0x31, 0x26, ], c_out: [ - 0x7b, 0xf4, 0x12, 0x7d, 0x22, 0xcc, 0x57, 0x35, 0x87, 0x51, 0x2f, 0xf8, 0x1e, 0x55, - 0x3e, 0x3c, 0x98, 0x23, 0x5f, 0x51, 0xc7, 0x23, 0x7e, 0x9e, 0x76, 0x1a, 0x08, 0xf2, - 0xe1, 0xe8, 0x0d, 0x04, 0x26, 0x98, 0xfc, 0x3b, 0x1d, 0x03, 0x18, 0xf1, 0xfd, 0xca, - 0x8e, 0x41, 0xa3, 0x16, 0xd6, 0xaf, 0x3a, 0xc0, 0xc4, 0x0c, 0xe1, 0x99, 0x47, 0xa2, - 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, - 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, + 0xca, 0xb7, 0x8d, 0xd1, 0x83, 0xf3, 0xe1, 0x6a, 0xf7, 0x6e, 0x9a, 0x90, 0x3d, 0xd4, + 0x2a, 0x96, 0x67, 0xbf, 0xe7, 0x08, 0xce, 0x88, 0x79, 0xb8, 0x38, 0x6e, 0x62, 0xac, + 0x9f, 0x66, 0x74, 0xf4, 0x93, 0x59, 0x5d, 0xa5, 0x06, 0xe9, 0xef, 0x06, 0xbb, 0xa2, + 0x4a, 0x93, 0x80, 0x60, 0xe5, 0xd3, 0x82, 0xcc, 0x75, 0xdf, 0xab, 0x97, 0xe0, 0xf8, + 0x49, 0x4b, 0x47, 0x6a, 0xdf, 0x4f, 0xfd, 0x96, 0xff, 0x7f, 0x1b, 0x4f, 0x16, 0xf8, + 0x59, 0x4b, 0x7c, 0x5a, 0x21, 0x9c, 0x7a, 0x00, 0xad, 0x15, ], }, ] diff --git a/src/test_vectors/note_encryption_v3.rs b/src/test_vectors/note_encryption_zsa.rs similarity index 99% rename from src/test_vectors/note_encryption_v3.rs rename to src/test_vectors/note_encryption_zsa.rs index 79b514869..25cd361fa 100644 --- a/src/test_vectors/note_encryption_v3.rs +++ b/src/test_vectors/note_encryption_zsa.rs @@ -1,4 +1,4 @@ -// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_note_encryption) +// From https://github.com/zcash-hackworks/zcash-test-vectors/ (orchard_zsa_note_encryption) pub(crate) struct TestVector { pub(crate) incoming_viewing_key: [u8; 64], @@ -10,7 +10,7 @@ pub(crate) struct TestVector { pub(crate) asset: [u8; 32], pub(crate) memo: [u8; 512], pub(crate) cv_net: [u8; 32], - pub(crate) rho: [u8; 32], + pub(crate) nf_old: [u8; 32], pub(crate) cmx: [u8; 32], pub(crate) esk: [u8; 32], pub(crate) ephemeral_key: [u8; 32], @@ -101,7 +101,8 @@ pub(crate) fn test_vectors() -> Vec { 0x42, 0xc2, 0x38, 0x51, 0x38, 0x15, 0x30, 0x2d, 0xf0, 0xf4, 0x83, 0x04, 0x21, 0xa6, 0xc1, 0x3e, 0x71, 0x01, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, 0x05, 0xee, 0xf3, 0x27, @@ -319,7 +320,8 @@ pub(crate) fn test_vectors() -> Vec { 0xa2, 0x17, 0x64, 0x10, 0x4a, 0x23, 0xea, 0xf6, 0xba, 0x49, 0x6c, 0xb9, 0xb8, 0xe8, 0x25, 0x7a, 0xd8, 0xb3, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, 0x4d, 0xb2, 0xc7, 0x31, @@ -537,7 +539,8 @@ pub(crate) fn test_vectors() -> Vec { 0x9d, 0x5e, 0x64, 0x07, 0x19, 0xbc, 0xa5, 0xc8, 0xed, 0x49, 0x99, 0x97, 0x34, 0xe6, 0xc5, 0xb3, 0x73, 0x3e, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, 0x25, 0xb9, 0xff, 0x16, @@ -755,7 +758,8 @@ pub(crate) fn test_vectors() -> Vec { 0xfa, 0xde, 0x94, 0xfa, 0x0b, 0x46, 0xe3, 0xb1, 0xa5, 0x73, 0x34, 0x99, 0x34, 0xe2, 0x32, 0xb5, 0x0e, 0x96, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, 0xf5, 0x0e, 0x92, 0x37, @@ -973,7 +977,8 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x95, 0x89, 0xbe, 0x69, 0xd8, 0x28, 0xbe, 0x54, 0x30, 0x69, 0x16, 0x41, 0x3c, 0xd2, 0x50, 0x21, 0x17, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, 0x3c, 0xfb, 0xf1, 0x31, @@ -1191,7 +1196,8 @@ pub(crate) fn test_vectors() -> Vec { 0x6e, 0x62, 0xe4, 0xed, 0xc7, 0x86, 0xd9, 0xe0, 0xb2, 0x7d, 0x26, 0x62, 0x8b, 0x79, 0xda, 0x6b, 0x15, 0x14, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, 0x21, 0x38, 0xab, 0x29, @@ -1409,7 +1415,8 @@ pub(crate) fn test_vectors() -> Vec { 0x0a, 0x12, 0x01, 0x2d, 0x63, 0xc0, 0x09, 0xc6, 0x77, 0x44, 0xba, 0xe0, 0xd5, 0x83, 0x88, 0xff, 0xee, 0x2f, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, 0x92, 0xd7, 0xa0, 0x24, @@ -1627,7 +1634,8 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x51, 0x00, 0x89, 0x08, 0xa6, 0xcd, 0xd0, 0xaa, 0x02, 0x1b, 0x88, 0x8b, 0x98, 0xe2, 0x3c, 0x39, 0x11, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, 0x3e, 0xe8, 0xed, 0x20, @@ -1845,7 +1853,8 @@ pub(crate) fn test_vectors() -> Vec { 0x7e, 0xed, 0xd2, 0xa7, 0x06, 0x44, 0x07, 0x34, 0x78, 0x41, 0x01, 0xae, 0x2d, 0x8e, 0x87, 0xe5, 0x05, 0xad, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, 0x45, 0x89, 0x35, 0x14, @@ -2063,7 +2072,8 @@ pub(crate) fn test_vectors() -> Vec { 0xbd, 0xb9, 0x6f, 0x1c, 0xe0, 0x57, 0xc3, 0x30, 0xd1, 0xcc, 0xba, 0x2f, 0x7d, 0xa8, 0x71, 0x55, 0x00, 0xb5, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, 0xa3, 0x18, 0x53, 0x3e, @@ -2281,7 +2291,8 @@ pub(crate) fn test_vectors() -> Vec { 0x2c, 0x3b, 0x94, 0x21, 0x3e, 0x86, 0x47, 0x3b, 0x5e, 0x2f, 0xdd, 0x70, 0x97, 0x80, 0xbc, 0xca, 0x68, 0xb4, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, 0xa9, 0x4a, 0x06, 0x04, 0xb8, 0x00, 0x6c, 0xc7, 0x94, 0xbc, 0xab, 0x57, 0x73, 0x49, 0xbc, 0xf8, 0x63, 0x37, @@ -2499,7 +2510,8 @@ pub(crate) fn test_vectors() -> Vec { 0x87, 0x2e, 0xf2, 0x17, 0x35, 0x43, 0xac, 0x81, 0x4c, 0x32, 0xb4, 0xb6, 0x9c, 0x9c, 0x34, 0x5e, 0x46, 0x98, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, 0x51, 0x1c, 0x9b, 0xab, 0x65, 0xb6, 0xd8, 0xd5, 0xc5, 0xbd, 0x1e, 0x32, 0x77, 0x1a, 0xb6, 0xf6, 0x4c, 0x26, @@ -2717,7 +2729,8 @@ pub(crate) fn test_vectors() -> Vec { 0xce, 0xe7, 0x81, 0xe4, 0x00, 0x28, 0x5c, 0xc6, 0x66, 0xbc, 0x6c, 0x41, 0x89, 0xdb, 0x2d, 0xda, 0x71, 0x92, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, 0xe0, 0xe8, 0x14, 0x11, 0x94, 0x7e, 0x9e, 0x69, 0xb7, 0x19, 0xfa, 0xb7, 0x41, 0x72, 0x1d, 0x40, 0x9b, 0x33, @@ -2935,7 +2948,8 @@ pub(crate) fn test_vectors() -> Vec { 0x80, 0x2d, 0x65, 0x00, 0x74, 0xdb, 0xd7, 0xe0, 0x6a, 0x48, 0x98, 0x03, 0x15, 0x30, 0x78, 0xe9, 0x97, 0x0b, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, 0x85, 0x72, 0xa3, 0x05, 0xfa, 0x3b, 0x70, 0x68, 0xa3, 0x78, 0x38, 0x27, 0xaf, 0xe2, 0x14, 0x7a, 0x27, 0x10, @@ -3153,7 +3167,8 @@ pub(crate) fn test_vectors() -> Vec { 0x34, 0xda, 0xf4, 0xe5, 0x98, 0x34, 0xcd, 0x65, 0xd7, 0x9f, 0xfc, 0x41, 0xdd, 0xf0, 0x68, 0x2d, 0xc2, 0xab, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, 0x4d, 0x4b, 0x32, 0x36, 0xdb, 0x1f, 0x32, 0xac, 0xa7, 0x94, 0x5c, 0xf2, 0x6e, 0xc8, 0xb9, 0xd0, 0xb7, 0x32, @@ -3371,7 +3386,8 @@ pub(crate) fn test_vectors() -> Vec { 0xd7, 0xda, 0xfb, 0xbe, 0x53, 0xb0, 0xa9, 0x6b, 0x08, 0x1c, 0x90, 0xba, 0xde, 0xd9, 0xbe, 0x4b, 0x4f, 0x87, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, 0x4f, 0xfb, 0xc2, 0x36, 0x9c, 0xb1, 0x48, 0xeb, 0x76, 0xf1, 0xed, 0xf1, 0xb5, 0xc7, 0x41, 0x84, 0x28, 0x2a, @@ -3589,7 +3605,8 @@ pub(crate) fn test_vectors() -> Vec { 0x73, 0x07, 0x93, 0xf4, 0x36, 0x33, 0x1f, 0xfe, 0x66, 0x30, 0xc7, 0xca, 0x2d, 0x9b, 0x23, 0x2a, 0xe1, 0x98, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, 0x53, 0xb9, 0x3b, 0xcb, 0xb4, 0x37, 0x57, 0x1c, 0x62, 0xf3, 0x75, 0x60, 0x7e, 0x90, 0x4e, 0xb3, 0xa2, 0x08, @@ -3807,7 +3824,8 @@ pub(crate) fn test_vectors() -> Vec { 0x95, 0x26, 0xa6, 0xe9, 0x4a, 0x49, 0x70, 0x10, 0xe3, 0x2a, 0x8a, 0x76, 0xbc, 0xdf, 0xa7, 0x20, 0xb8, 0xa6, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, 0xa5, 0xed, 0x09, 0xc6, 0xee, 0x3b, 0x7f, 0x39, 0x34, 0x14, 0xe1, 0x1c, 0xd4, 0x20, 0x4c, 0x3f, 0x8d, 0x26, @@ -4025,7 +4043,8 @@ pub(crate) fn test_vectors() -> Vec { 0x3a, 0x2a, 0xf5, 0x46, 0x32, 0xf8, 0x30, 0x08, 0x14, 0x68, 0x29, 0x65, 0x94, 0x5e, 0x7e, 0x33, 0x2a, 0x0d, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, 0x67, 0x93, 0xc3, 0xfe, 0xfa, 0xda, 0xee, 0xa8, 0xe2, 0x3c, 0x44, 0xd5, 0xe0, 0x18, 0x4b, 0xc8, 0x45, 0x10, @@ -4243,7 +4262,8 @@ pub(crate) fn test_vectors() -> Vec { 0xd3, 0x7d, 0x17, 0x17, 0xa4, 0x8d, 0x8f, 0x00, 0x6c, 0x1f, 0xf5, 0x86, 0x21, 0x46, 0x29, 0x55, 0x39, 0x1c, ], - rho: [ + // FIXME: used instead of rho, which was possibly modified in zsa1 version + nf_old: [ 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, 0xd0, 0x28, 0x44, 0x22, 0x13, 0x50, 0x86, 0x4e, 0xed, 0x56, 0x3d, 0xab, 0x30, 0x22, 0x7f, 0x28, 0x4b, 0x2e, diff --git a/src/value.rs b/src/value.rs index b156770d2..a9cb843d0 100644 --- a/src/value.rs +++ b/src/value.rs @@ -107,11 +107,13 @@ impl NoteValue { NoteValue(value) } - pub(crate) fn from_bytes(bytes: [u8; 8]) -> Self { + /// Creates a note value from a byte array. + pub fn from_bytes(bytes: [u8; 8]) -> Self { NoteValue(u64::from_le_bytes(bytes)) } - pub(crate) fn to_bytes(self) -> [u8; 8] { + /// Converts the note value to a byte array. + pub fn to_bytes(self) -> [u8; 8] { self.0.to_le_bytes() } @@ -222,14 +224,16 @@ impl Neg for ValueSum { } impl<'a> Sum<&'a ValueSum> for Result { - fn sum>(iter: I) -> Self { - iter.fold(Ok(ValueSum(0)), |acc, v| (acc? + *v).ok_or(OverflowError)) + fn sum>(mut iter: I) -> Self { + iter.try_fold(ValueSum(0), |acc, v| acc + *v) + .ok_or(OverflowError) } } impl Sum for Result { - fn sum>(iter: I) -> Self { - iter.fold(Ok(ValueSum(0)), |acc, v| (acc? + v).ok_or(OverflowError)) + fn sum>(mut iter: I) -> Self { + iter.try_fold(ValueSum(0), |acc, v| acc + v) + .ok_or(OverflowError) } } @@ -247,6 +251,12 @@ impl From for i128 { } } +impl From for ValueSum { + fn from(value: NoteValue) -> Self { + Self(value.into()) + } +} + /// The blinding factor for a [`ValueCommitment`]. #[derive(Clone, Copy, Debug)] pub struct ValueCommitTrapdoor(pallas::Scalar); diff --git a/tests/builder.rs b/tests/builder.rs index 845fa2367..d1e50de64 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -6,7 +6,8 @@ use orchard::{ circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment}, - note_encryption_v3::OrchardDomainV3, + note_encryption::OrchardDomain, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, Anchor, Bundle, Note, @@ -14,7 +15,11 @@ use orchard::{ use rand::rngs::OsRng; use zcash_note_encryption_zsa::try_note_decryption; -pub fn verify_bundle(bundle: &Bundle, vk: &VerifyingKey, verify_proof: bool) { +pub fn verify_bundle( + bundle: &Bundle, + vk: &VerifyingKey, + verify_proof: bool, +) { if verify_proof { assert!(matches!(bundle.verify_proof(vk), Ok(()))); } @@ -47,24 +52,38 @@ pub fn build_merkle_path(note: &Note) -> (MerklePath, Anchor) { (merkle_path, anchor) } -#[test] -fn bundle_chain() { +trait BundleOrchardFlavor: OrchardFlavor { + const DEFAULT_BUNDLE_TYPE: BundleType; + const SPENDS_DISABLED_FLAGS: Flags; +} + +impl BundleOrchardFlavor for OrchardVanilla { + const DEFAULT_BUNDLE_TYPE: BundleType = BundleType::DEFAULT_VANILLA; + const SPENDS_DISABLED_FLAGS: Flags = Flags::SPENDS_DISABLED_WITHOUT_ZSA; +} + +impl BundleOrchardFlavor for OrchardZSA { + const DEFAULT_BUNDLE_TYPE: BundleType = BundleType::DEFAULT_ZSA; + const SPENDS_DISABLED_FLAGS: Flags = Flags::SPENDS_DISABLED_WITH_ZSA; +} + +fn bundle_chain() { let mut rng = OsRng; - let pk = ProvingKey::build(); - let vk = VerifyingKey::build(); + let pk = ProvingKey::build::(); + let vk = VerifyingKey::build::(); let sk = SpendingKey::from_bytes([0; 32]).unwrap(); let fvk = FullViewingKey::from(&sk); let recipient = fvk.address_at(0u32, Scope::External); // Create a shielding bundle. - let shielding_bundle: Bundle<_, i64> = { + let shielding_bundle: Bundle<_, i64, FL> = { // Use the empty tree. let anchor = MerkleHashOrchard::empty_root(32.into()).into(); let mut builder = Builder::new( BundleType::Transactional { - flags: Flags::SPENDS_DISABLED, + flags: FL::SPENDS_DISABLED_FLAGS, bundle_required: false, }, anchor, @@ -96,21 +115,43 @@ fn bundle_chain() { // Verify the shielding bundle. verify_bundle(&shielding_bundle, &vk, true); - // Create a shielded bundle spending the previous output. - let shielded_bundle: Bundle<_, i64> = { + let note = { let ivk = PreparedIncomingViewingKey::new(&fvk.to_ivk(Scope::External)); - let (note, _, _) = shielding_bundle + shielding_bundle .actions() .iter() .find_map(|action| { - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); try_note_decryption(&domain, &ivk, action) }) - .unwrap(); + .unwrap() + .0 + }; + + // Test that spend adding attempt fails when spends are disabled. + // Note: We do not need a separate positive test for spends enabled + // as the following code adds spends with spends enabled. + { + let (merkle_path, anchor) = build_merkle_path(¬e); + + let mut builder = Builder::new( + BundleType::Transactional { + // Intentionally testing with SPENDS_DISABLED_WITHOUT_ZSA as SPENDS_DISABLED_WITH_ZSA is already + // tested above (for OrchardZSA case). Both should work. + flags: Flags::SPENDS_DISABLED_WITHOUT_ZSA, + bundle_required: false, + }, + anchor, + ); + + assert!(builder.add_spend(fvk.clone(), note, merkle_path).is_err()); + } + // Create a shielded bundle spending the previous output. + let shielded_bundle: Bundle<_, i64, FL> = { let (merkle_path, anchor) = build_merkle_path(¬e); - let mut builder = Builder::new(BundleType::DEFAULT_VANILLA, anchor); + let mut builder = Builder::new(FL::DEFAULT_BUNDLE_TYPE, anchor); assert_eq!(builder.add_spend(fvk, note, merkle_path), Ok(())); assert_eq!( builder.add_output( @@ -133,3 +174,13 @@ fn bundle_chain() { // Verify the shielded bundle. verify_bundle(&shielded_bundle, &vk, true); } + +#[test] +fn bundle_chain_vanilla() { + bundle_chain::() +} + +#[test] +fn bundle_chain_zsa() { + bundle_chain::() +} diff --git a/tests/zsa.rs b/tests/zsa.rs index 4d6826b08..fced143a0 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -7,12 +7,14 @@ use orchard::bundle::Authorized; use orchard::issuance::{verify_issue_bundle, IssueBundle, IssueInfo, Signed, Unauthorized}; use orchard::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use orchard::note::{AssetBase, ExtractedNoteCommitment}; -use orchard::note_encryption_v3::OrchardDomainV3; + use orchard::tree::{MerkleHashOrchard, MerklePath}; use orchard::{ builder::{Builder, BundleType}, circuit::{ProvingKey, VerifyingKey}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, + note_encryption::OrchardDomain, + orchard_flavor::OrchardZSA, value::NoteValue, Address, Anchor, Bundle, Note, }; @@ -50,8 +52,9 @@ impl Keychain { } fn prepare_keys() -> Keychain { - let pk = ProvingKey::build(); - let vk = VerifyingKey::build(); + // FIXME: consider adding test for OrchardDomainVanilla as well + let pk = ProvingKey::build::(); + let vk = VerifyingKey::build::(); let sk = SpendingKey::from_bytes([0; 32]).unwrap(); let fvk = FullViewingKey::from(&sk); @@ -84,7 +87,7 @@ fn build_and_sign_bundle( mut rng: OsRng, pk: &ProvingKey, sk: &SpendingKey, -) -> Bundle { +) -> Bundle { let unauthorized = builder.build(&mut rng).unwrap().unwrap().0; let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(pk, &mut rng).unwrap(); @@ -179,7 +182,7 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { fn create_native_note(keys: &Keychain) -> Note { let mut rng = OsRng; - let shielding_bundle: Bundle<_, i64> = { + let shielding_bundle: Bundle<_, i64, OrchardZSA> = { // Use the empty tree. let anchor = MerkleHashOrchard::empty_root(32.into()).into(); @@ -204,7 +207,7 @@ fn create_native_note(keys: &Keychain) -> Note { .actions() .iter() .find_map(|action| { - let domain = OrchardDomainV3::for_action(action); + let domain = OrchardDomain::for_action(action); try_note_decryption(&domain, &PreparedIncomingViewingKey::new(&ivk), action) }) .unwrap(); @@ -237,7 +240,7 @@ fn build_and_verify_bundle( keys: &Keychain, ) -> Result<(), String> { let rng = OsRng; - let shielded_bundle: Bundle<_, i64> = { + let shielded_bundle: Bundle<_, i64, OrchardZSA> = { let mut builder = Builder::new(BundleType::DEFAULT_ZSA, anchor); spends @@ -254,7 +257,8 @@ fn build_and_verify_bundle( .map_err(|err| err.to_string())?; assets_to_burn .into_iter() - .try_for_each(|(asset, value)| builder.add_burn(asset, value))?; + .try_for_each(|(asset, value)| builder.add_burn(asset, value)) + .map_err(|err| err.to_string())?; build_and_sign_bundle(builder, rng, keys.pk(), keys.sk()) }; @@ -265,7 +269,7 @@ fn build_and_verify_bundle( Ok(()) } -fn verify_unique_spent_nullifiers(bundle: &Bundle) -> bool { +fn verify_unique_spent_nullifiers(bundle: &Bundle) -> bool { let mut unique_nulifiers = Vec::new(); let spent_nullifiers = bundle .actions() From 6e6112c80eb751a93c0fd1d881e9ca69887e1154 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 31 Jul 2024 13:12:12 +0200 Subject: [PATCH 70/92] Synchronize Orchard with updates from zcash_note_encryption for zcash PR #2 issues resolve (#111) Orchard has been synced with the changes from [PR #10](https://github.com/QED-it/zcash_note_encryption/pull/10) in the `zcash_note_encryption` repository. This update includes the following changes: - Implements new `parse_note_plaintext_bytes`, `parse_note_ciphertext_bytes`, and `parse_compact_note_plaintext_bytes` methods of the `Domain` trait from `zcash_note_encryption`. - Uses the `NoteBytes` trait and `NoteBytesData` structure from `zcash_note_encryption` instead of having local definitions and implementations. ### Note This PR uses the `resolve_zcash_pr2_issues` branch of `zcash_note_encryption` in `Cargo.toml`. Before merging this PR, [PR #10](https://github.com/zcash/zcash_note_encryption/pull/10) needs to be merged into the `zsa1` branch of `zcash_note_encryption`. Then, this Orchard PR branch should be updated to use the `zsa1` branch of `zcash_note_encryption` befor merging this PR. --------- Co-authored-by: Dmitry Demin --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/note_encryption/compact_action.rs | 18 +++++--- src/note_encryption/domain.rs | 13 +++--- src/note_encryption/orchard_domain.rs | 44 +------------------ src/note_encryption/orchard_domain_vanilla.rs | 12 ++--- src/note_encryption/orchard_domain_zsa.rs | 12 ++--- 7 files changed, 37 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff6675ce4..9b6afc650 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2552,7 +2552,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#b8bd2a186fc04ec4f55b2db44df7374f03ab5725" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#58384553aab76b2ee6d6eb328cf2187fa824ec9a" dependencies = [ "chacha20", "chacha20poly1305", diff --git a/Cargo.toml b/Cargo.toml index 53da31cb3..7b0389cdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex-header.html"] [dependencies] aes = "0.8" bitvec = "1" -blake2b_simd = "=1.0.1" # Last version required rust 1.66 +blake2b_simd = "1" half = "=2.2.1" # Last version requires Rust 1.70 ff = "0.13" fpe = "0.6" diff --git a/src/note_encryption/compact_action.rs b/src/note_encryption/compact_action.rs index 77fc768b8..d7494d1c8 100644 --- a/src/note_encryption/compact_action.rs +++ b/src/note_encryption/compact_action.rs @@ -2,7 +2,7 @@ use std::fmt; -use zcash_note_encryption_zsa::{EphemeralKeyBytes, ShieldedOutput}; +use zcash_note_encryption_zsa::{note_bytes::NoteBytes, EphemeralKeyBytes, ShieldedOutput}; use crate::{ action::Action, @@ -25,7 +25,10 @@ impl ShieldedOutput> for Action D::CompactNoteCiphertextBytes { - self.encrypted_note().enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE].into() + D::CompactNoteCiphertextBytes::from_slice( + &self.encrypted_note().enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE], + ) + .unwrap() } } @@ -71,7 +74,7 @@ impl ShieldedOutput> for CompactAction< } fn enc_ciphertext_compact(&self) -> D::CompactNoteCiphertextBytes { - self.enc_ciphertext + D::CompactNoteCiphertextBytes::from_slice(self.enc_ciphertext.as_ref()).unwrap() } } @@ -112,7 +115,7 @@ impl CompactAction { pub mod testing { use rand::RngCore; - use zcash_note_encryption_zsa::{Domain, NoteEncryption}; + use zcash_note_encryption_zsa::{note_bytes::NoteBytes, Domain, NoteEncryption, MEMO_SIZE}; use crate::{ address::Address, @@ -145,7 +148,7 @@ pub mod testing { } }; let note = Note::from_parts(recipient, value, AssetBase::native(), rho, rseed).unwrap(); - let encryptor = NoteEncryption::>::new(ovk, note, [0u8; 512]); + let encryptor = NoteEncryption::>::new(ovk, note, [0u8; MEMO_SIZE]); let cmx = ExtractedNoteCommitment::from(note.commitment()); let ephemeral_key = OrchardDomain::::epk_bytes(encryptor.epk()); let enc_ciphertext = encryptor.encrypt_note_plaintext(); @@ -155,7 +158,10 @@ pub mod testing { nullifier: nf_old, cmx, ephemeral_key, - enc_ciphertext: enc_ciphertext.as_ref()[..52].try_into().unwrap(), + enc_ciphertext: D::CompactNoteCiphertextBytes::from_slice( + &enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE], + ) + .unwrap(), }, note, ) diff --git a/src/note_encryption/domain.rs b/src/note_encryption/domain.rs index c91ad81b4..ec6dc8ad3 100644 --- a/src/note_encryption/domain.rs +++ b/src/note_encryption/domain.rs @@ -7,8 +7,8 @@ use group::ff::PrimeField; use blake2b_simd::Params; use zcash_note_encryption_zsa::{ - BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, OutgoingCipherKey, MEMO_SIZE, - OUT_PLAINTEXT_SIZE, + note_bytes::NoteBytes, BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, + OutgoingCipherKey, MEMO_SIZE, OUT_PLAINTEXT_SIZE, }; use crate::{ @@ -255,12 +255,15 @@ impl Domain for OrchardDomain { parse_note_plaintext_without_memo::(self.rho, plaintext, |_| Some(*pk_d)) } - fn extract_memo( + fn split_plaintext_at_memo( &self, plaintext: &D::NotePlaintextBytes, - ) -> (Self::CompactNotePlaintextBytes, Self::Memo) { + ) -> Option<(Self::CompactNotePlaintextBytes, Self::Memo)> { let (compact, memo) = plaintext.as_ref().split_at(D::COMPACT_NOTE_SIZE); - (compact.into(), memo.try_into().unwrap()) + Some(( + Self::CompactNotePlaintextBytes::from_slice(compact)?, + memo.try_into().ok()?, + )) } fn extract_pk_d(out_plaintext: &OutPlaintextBytes) -> Option { diff --git a/src/note_encryption/orchard_domain.rs b/src/note_encryption/orchard_domain.rs index aa70fded6..7ee11530a 100644 --- a/src/note_encryption/orchard_domain.rs +++ b/src/note_encryption/orchard_domain.rs @@ -3,7 +3,7 @@ use core::fmt; -use zcash_note_encryption_zsa::{AEAD_TAG_SIZE, MEMO_SIZE}; +use zcash_note_encryption_zsa::{note_bytes::NoteBytes, AEAD_TAG_SIZE, MEMO_SIZE}; use crate::{ action::Action, @@ -13,48 +13,6 @@ use crate::{ use super::{compact_action::CompactAction, domain::Memo}; -/// Represents a fixed-size array of bytes for note components. -#[derive(Clone, Copy, Debug)] -pub struct NoteBytesData(pub [u8; N]); - -impl AsRef<[u8]> for NoteBytesData { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - -impl AsMut<[u8]> for NoteBytesData { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0 - } -} - -impl From<&[u8]> for NoteBytesData { - fn from(s: &[u8]) -> Self { - Self(s.try_into().unwrap()) - } -} - -impl From<(&[u8], &[u8])> for NoteBytesData { - fn from(s: (&[u8], &[u8])) -> Self { - Self([s.0, s.1].concat().try_into().unwrap()) - } -} - -/// Provides a unified interface for handling fixed-size byte arrays used in Orchard note encryption. -pub trait NoteBytes: - AsRef<[u8]> - + AsMut<[u8]> - + for<'a> From<&'a [u8]> - + for<'a> From<(&'a [u8], &'a [u8])> - + Clone - + Copy - + Send -{ -} - -impl NoteBytes for NoteBytesData {} - /// Represents the Orchard protocol domain specifics required for note encryption and decryption. pub trait OrchardDomainCommon: fmt::Debug + Clone { /// The size of a compact note, specific to the Orchard protocol. diff --git a/src/note_encryption/orchard_domain_vanilla.rs b/src/note_encryption/orchard_domain_vanilla.rs index d49c361da..187e12289 100644 --- a/src/note_encryption/orchard_domain_vanilla.rs +++ b/src/note_encryption/orchard_domain_vanilla.rs @@ -1,5 +1,7 @@ //! This module implements the note encryption logic specific for the `OrchardVanilla` flavor. +use zcash_note_encryption_zsa::note_bytes::NoteBytesData; + use crate::{ note::{AssetBase, Note}, orchard_flavor::OrchardVanilla, @@ -9,7 +11,7 @@ use super::{ domain::{ build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, NOTE_VERSION_BYTE_V2, }, - orchard_domain::{NoteBytesData, OrchardDomainCommon}, + orchard_domain::OrchardDomainCommon, }; impl OrchardDomainCommon for OrchardVanilla { @@ -40,8 +42,8 @@ mod tests { use rand::rngs::OsRng; use zcash_note_encryption_zsa::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, - EphemeralKeyBytes, + note_bytes::NoteBytesData, try_compact_note_decryption, try_note_decryption, + try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; use crate::{ @@ -63,7 +65,7 @@ mod tests { use super::super::{ compact_action::CompactAction, domain::{parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard}, - orchard_domain::{NoteBytesData, OrchardDomain}, + orchard_domain::OrchardDomain, }; type OrchardDomainVanilla = OrchardDomain; @@ -85,7 +87,7 @@ mod tests { // Decode. let domain = OrchardDomainVanilla::for_rho(rho); - let (compact, parsed_memo) = domain.extract_memo(&plaintext); + let (compact, parsed_memo) = domain.split_plaintext_at_memo(&plaintext).unwrap(); assert!(parse_note_version(compact.as_ref()).is_some()); diff --git a/src/note_encryption/orchard_domain_zsa.rs b/src/note_encryption/orchard_domain_zsa.rs index 4979e8c91..52a23bbe1 100644 --- a/src/note_encryption/orchard_domain_zsa.rs +++ b/src/note_encryption/orchard_domain_zsa.rs @@ -1,5 +1,7 @@ //! This module implements the note encryption logic specific for the `OrchardZSA` flavor. +use zcash_note_encryption_zsa::note_bytes::NoteBytesData; + use crate::{ note::{AssetBase, Note}, orchard_flavor::OrchardZSA, @@ -10,7 +12,7 @@ use super::{ build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, COMPACT_NOTE_SIZE_ZSA, NOTE_VERSION_BYTE_V3, }, - orchard_domain::{NoteBytesData, OrchardDomainCommon}, + orchard_domain::OrchardDomainCommon, }; impl OrchardDomainCommon for OrchardZSA { @@ -47,8 +49,8 @@ mod tests { use rand::rngs::OsRng; use zcash_note_encryption_zsa::{ - try_compact_note_decryption, try_note_decryption, try_output_recovery_with_ovk, Domain, - EphemeralKeyBytes, + note_bytes::NoteBytesData, try_compact_note_decryption, try_note_decryption, + try_output_recovery_with_ovk, Domain, EphemeralKeyBytes, }; use crate::{ @@ -70,7 +72,7 @@ mod tests { use super::super::{ compact_action::CompactAction, domain::{parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard}, - orchard_domain::{NoteBytesData, OrchardDomain}, + orchard_domain::OrchardDomain, }; type OrchardDomainZSA = OrchardDomain; @@ -92,7 +94,7 @@ mod tests { // Decode. let domain = OrchardDomainZSA::for_rho(rho); - let (compact, parsed_memo) = domain.extract_memo(&plaintext); + let (compact, parsed_memo) = domain.split_plaintext_at_memo(&plaintext).unwrap(); assert!(parse_note_version(compact.as_ref()).is_some()); From 07b3697b271f04c736a5f7e130d186e68a85fd8c Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 14 Aug 2024 09:49:01 +0200 Subject: [PATCH 71/92] Update ShieldedOutput implementation to return reference from enc_ciphertext (#112) This PR updates the `ShieldedOutput` implementation for the `Action`/`CompactAction` struct to align with the recent changes in the `zcash_note_encryption` crate. Specifically, the `enc_ciphertext` method now returns a reference instead of a copy. This change was discussed and suggested in PR zcash/zcash_note_encryption#2 review. --------- Co-authored-by: Dmitry Demin --- Cargo.lock | 2 +- src/bundle/commitments.rs | 4 +--- src/note_encryption.rs | 2 ++ src/note_encryption/compact_action.rs | 9 +++++---- src/note_encryption/domain.rs | 5 ++++- src/note_encryption/orchard_domain.rs | 7 +++++-- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b6afc650..ed3c2f7ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2552,7 +2552,7 @@ dependencies = [ [[package]] name = "zcash_note_encryption" version = "0.4.0" -source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#58384553aab76b2ee6d6eb328cf2187fa824ec9a" +source = "git+https://github.com/QED-it/zcash_note_encryption?branch=zsa1#76745f00551d4442dee11ad64a8400b75132d18f" dependencies = [ "chacha20", "chacha20poly1305", diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 953c9d474..1572987bd 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -2,13 +2,11 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; -use zcash_note_encryption_zsa::MEMO_SIZE; - use crate::{ bundle::{Authorization, Authorized, Bundle}, issuance::{IssueAuth, IssueBundle, Signed}, note::AssetBase, - note_encryption::OrchardDomainCommon, + note_encryption::{OrchardDomainCommon, MEMO_SIZE}, orchard_flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, }; diff --git a/src/note_encryption.rs b/src/note_encryption.rs index 8f2607e89..26d293209 100644 --- a/src/note_encryption.rs +++ b/src/note_encryption.rs @@ -11,6 +11,8 @@ mod orchard_domain; mod orchard_domain_vanilla; mod orchard_domain_zsa; +pub(crate) use domain::MEMO_SIZE; + pub use { compact_action::CompactAction, orchard_domain::{OrchardDomain, OrchardDomainCommon}, diff --git a/src/note_encryption/compact_action.rs b/src/note_encryption/compact_action.rs index d7494d1c8..8ed04d983 100644 --- a/src/note_encryption/compact_action.rs +++ b/src/note_encryption/compact_action.rs @@ -20,8 +20,8 @@ impl ShieldedOutput> for Action Option { - Some(self.encrypted_note().enc_ciphertext) + fn enc_ciphertext(&self) -> Option<&D::NoteCiphertextBytes> { + Some(&self.encrypted_note().enc_ciphertext) } fn enc_ciphertext_compact(&self) -> D::CompactNoteCiphertextBytes { @@ -69,7 +69,7 @@ impl ShieldedOutput> for CompactAction< self.cmx.to_bytes() } - fn enc_ciphertext(&self) -> Option { + fn enc_ciphertext(&self) -> Option<&D::NoteCiphertextBytes> { None } @@ -115,12 +115,13 @@ impl CompactAction { pub mod testing { use rand::RngCore; - use zcash_note_encryption_zsa::{note_bytes::NoteBytes, Domain, NoteEncryption, MEMO_SIZE}; + use zcash_note_encryption_zsa::{note_bytes::NoteBytes, Domain, NoteEncryption}; use crate::{ address::Address, keys::OutgoingViewingKey, note::{AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, Rho}, + note_encryption::MEMO_SIZE, value::NoteValue, }; diff --git a/src/note_encryption/domain.rs b/src/note_encryption/domain.rs index ec6dc8ad3..91d4ba4f2 100644 --- a/src/note_encryption/domain.rs +++ b/src/note_encryption/domain.rs @@ -8,7 +8,7 @@ use blake2b_simd::Params; use zcash_note_encryption_zsa::{ note_bytes::NoteBytes, BatchDomain, Domain, EphemeralKeyBytes, OutPlaintextBytes, - OutgoingCipherKey, MEMO_SIZE, OUT_PLAINTEXT_SIZE, + OutgoingCipherKey, OUT_PLAINTEXT_SIZE, }; use crate::{ @@ -51,6 +51,9 @@ pub(super) const NOTE_VERSION_BYTE_V2: u8 = 0x02; /// The version byte for ZSA. pub(super) const NOTE_VERSION_BYTE_V3: u8 = 0x03; +/// The size of the memo. +pub(crate) const MEMO_SIZE: usize = 512; + pub(super) type Memo = [u8; MEMO_SIZE]; /// Defined in [Zcash Protocol Spec § 5.4.2: Pseudo Random Functions][concreteprfs]. diff --git a/src/note_encryption/orchard_domain.rs b/src/note_encryption/orchard_domain.rs index 7ee11530a..e56f15cd1 100644 --- a/src/note_encryption/orchard_domain.rs +++ b/src/note_encryption/orchard_domain.rs @@ -3,7 +3,7 @@ use core::fmt; -use zcash_note_encryption_zsa::{note_bytes::NoteBytes, AEAD_TAG_SIZE, MEMO_SIZE}; +use zcash_note_encryption_zsa::{note_bytes::NoteBytes, AEAD_TAG_SIZE}; use crate::{ action::Action, @@ -11,7 +11,10 @@ use crate::{ Note, }; -use super::{compact_action::CompactAction, domain::Memo}; +use super::{ + compact_action::CompactAction, + domain::{Memo, MEMO_SIZE}, +}; /// Represents the Orchard protocol domain specifics required for note encryption and decryption. pub trait OrchardDomainCommon: fmt::Debug + Clone { From 3ba9e5b8d208bb44222cb2fe8bcd603c71abf444 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 19 Sep 2024 15:08:16 +0200 Subject: [PATCH 72/92] Remove redundancy in vanilla/zsa circuits - Unified `NoteCommitConfig` and `Config` to have the same configs for both Vanilla and ZSA circuits - Numerous functions and structures initially defined separately for Vanilla and ZSA have been unified into a single definition, incorporating the generic parameter `Lookup`. --- Cargo.lock | 4 +- Cargo.toml | 6 +- src/circuit.rs | 42 +- src/circuit/circuit_description_zsa | 850 ++---- src/circuit/circuit_proof_test_case_zsa.bin | Bin 5283 -> 5283 bytes src/circuit/circuit_vanilla.rs | 95 +- src/circuit/circuit_vanilla/gadget.rs | 190 -- src/circuit/circuit_vanilla/note_commit.rs | 2365 ----------------- src/circuit/circuit_zsa.rs | 148 +- src/circuit/circuit_zsa/gadget.rs | 245 -- src/circuit/commit_ivk.rs | 6 +- src/circuit/derive_nullifier.rs | 113 + src/circuit/gadget.rs | 132 +- src/circuit/{circuit_zsa => }/note_commit.rs | 1220 ++++++--- .../{circuit_zsa => }/value_commit_orchard.rs | 185 +- 15 files changed, 1517 insertions(+), 4084 deletions(-) delete mode 100644 src/circuit/circuit_vanilla/gadget.rs delete mode 100644 src/circuit/circuit_vanilla/note_commit.rs delete mode 100644 src/circuit/circuit_zsa/gadget.rs create mode 100644 src/circuit/derive_nullifier.rs rename src/circuit/{circuit_zsa => }/note_commit.rs (70%) rename src/circuit/{circuit_zsa => }/value_commit_orchard.rs (67%) diff --git a/Cargo.lock b/Cargo.lock index ed3c2f7ae..3cda52aa9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1016,7 +1016,7 @@ dependencies = [ [[package]] name = "halo2_gadgets" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" dependencies = [ "arrayvec", "bitvec", @@ -1040,7 +1040,7 @@ checksum = "47716fe1ae67969c5e0b2ef826f32db8c3be72be325e1aa3c1951d06b5575ec5" [[package]] name = "halo2_proofs" version = "0.3.0" -source = "git+https://github.com/QED-it/halo2?rev=7f5c0babd61f8ca46c9165a1adfac298d3fd3a11#7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" +source = "git+https://github.com/QED-it/halo2?branch=zsa1#1195c9af90205829ba20662bdfaf20dcc878807d" dependencies = [ "blake2b_simd", "ff", diff --git a/Cargo.toml b/Cargo.toml index 7b0389cdd..ade4c8274 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,8 +30,8 @@ half = "=2.2.1" # Last version requires Rust 1.70 ff = "0.13" fpe = "0.6" group = { version = "0.13", features = ["wnaf-memuse"] } -halo2_gadgets = { git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11" } -halo2_proofs = { git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" } +halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] } hex = "0.4" k256 = { version = "0.13.0", features = ["arithmetic", "schnorr"] } lazy_static = "1" @@ -58,7 +58,7 @@ plotters = { version = "0.3.0", optional = true } [dev-dependencies] bridgetree = "0.4" criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70 -halo2_gadgets = { git = "https://github.com/QED-it/halo2", rev = "7f5c0babd61f8ca46c9165a1adfac298d3fd3a11", features = ["test-dependencies"] } +halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] } proptest = "1.0.0" zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1", features = ["pre-zip-212"] } incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] } diff --git a/src/circuit.rs b/src/circuit.rs index e72d3e121..b0be32ce7 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -6,9 +6,17 @@ use core::fmt; use group::{Curve, GroupEncoding}; +use halo2_gadgets::{ + ecc::chip::EccConfig, + poseidon::Pow5Config as PoseidonConfig, + sinsemilla::{chip::SinsemillaConfig, merkle::chip::MerkleConfig}, + utilities::lookup_range_check::PallasLookupRangeCheck, +}; use halo2_proofs::{ circuit::{floor_planner, Layouter, Value}, - plonk::{self, BatchVerifier, SingleVerifier}, + plonk::{ + self, Advice, BatchVerifier, Column, Instance as InstanceColumn, Selector, SingleVerifier, + }, transcript::{Blake2bRead, Blake2bWrite}, }; use memuse::DynamicUsage; @@ -18,7 +26,12 @@ use rand::RngCore; use crate::{ builder::SpendInfo, bundle::Flags, - constants::MERKLE_DEPTH_ORCHARD, + circuit::{ + commit_ivk::CommitIvkConfig, gadget::add_chip::AddConfig, note_commit::NoteCommitConfig, + }, + constants::{ + OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, MERKLE_DEPTH_ORCHARD, + }, keys::{ CommitIvkRandomness, DiversifiedTransmissionKey, NullifierDerivingKey, SpendValidatingKey, }, @@ -37,8 +50,11 @@ mod circuit_vanilla; mod circuit_zsa; pub(in crate::circuit) mod commit_ivk; +pub(in crate::circuit) mod derive_nullifier; pub(in crate::circuit) mod gadget; +pub(in crate::circuit) mod note_commit; pub(in crate::circuit) mod orchard_sinsemilla_chip; +pub(in crate::circuit) mod value_commit_orchard; /// Size of the Orchard circuit. const K: u32 = 11; @@ -55,6 +71,28 @@ const ENABLE_SPEND: usize = 7; const ENABLE_OUTPUT: usize = 8; const ENABLE_ZSA: usize = 9; +/// Configuration needed to use the Orchard Action circuit. +#[derive(Clone, Debug)] +pub struct Config { + primary: Column, + q_orchard: Selector, + advices: [Column; 10], + add_config: AddConfig, + ecc_config: EccConfig, + poseidon_config: PoseidonConfig, + merkle_config_1: + MerkleConfig, + merkle_config_2: + MerkleConfig, + sinsemilla_config_1: + SinsemillaConfig, + sinsemilla_config_2: + SinsemillaConfig, + commit_ivk_config: CommitIvkConfig, + old_note_commit_config: NoteCommitConfig, + new_note_commit_config: NoteCommitConfig, +} + /// The `OrchardCircuit` trait defines an interface for different implementations of the PLONK circuit /// for the different Orchard protocol flavors (Vanilla and ZSA). It serves as a bridge between /// plonk::Circuit interfaces and specific requirements of the Orchard protocol's variations. diff --git a/src/circuit/circuit_description_zsa b/src/circuit/circuit_description_zsa index 6513b720e..535f080aa 100644 --- a/src/circuit/circuit_description_zsa +++ b/src/circuit/circuit_description_zsa @@ -10,7 +10,7 @@ PinnedVerificationKey { num_fixed_columns: 33, num_advice_columns: 10, num_instance_columns: 1, - num_selectors: 61, + num_selectors: 60, gates: [ Product( Product( @@ -26420,32 +26420,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -26460,7 +26444,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26519,32 +26503,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -26559,7 +26527,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26618,32 +26586,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -26658,7 +26610,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26691,32 +26643,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -26731,7 +26667,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26764,32 +26700,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -26804,7 +26724,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26875,32 +26795,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -26915,7 +26819,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -26974,32 +26878,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27014,7 +26902,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27047,32 +26935,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27087,7 +26959,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27120,32 +26992,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27160,7 +27016,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000003, ), Negated( Fixed { @@ -27193,32 +27049,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27233,7 +27073,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27273,32 +27113,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27313,7 +27137,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27372,32 +27196,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27412,7 +27220,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27471,32 +27279,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27511,7 +27303,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27558,32 +27350,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27598,7 +27374,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27631,32 +27407,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27671,7 +27431,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27704,32 +27464,16 @@ PinnedVerificationKey { Product( Product( Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), + Fixed { + query_index: 32, + column_index: 32, + rotation: Rotation( + 0, ), - ), + }, Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, + 0x0000000000000000000000000000000000000000000000000000000000000001, ), Negated( Fixed { @@ -27744,7 +27488,7 @@ PinnedVerificationKey { ), Sum( Constant( - 0x0000000000000000000000000000000000000000000000000000000000000004, + 0x0000000000000000000000000000000000000000000000000000000000000002, ), Negated( Fixed { @@ -27774,304 +27518,6 @@ PinnedVerificationKey { }, ), ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 2, - column_index: 2, - rotation: Rotation( - 0, - ), - }, - Negated( - Sum( - Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), - ), - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Advice { - query_index: 3, - column_index: 3, - rotation: Rotation( - 0, - ), - }, - Negated( - Sum( - Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Advice { - query_index: 0, - column_index: 0, - rotation: Rotation( - 0, - ), - }, - ), - Product( - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), - ), - Advice { - query_index: 1, - column_index: 1, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - ), - ), - Product( - Product( - Product( - Product( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000002, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000003, - ), - Negated( - Fixed { - query_index: 32, - column_index: 32, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - Product( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - Sum( - Constant( - 0x0000000000000000000000000000000000000000000000000000000000000001, - ), - Negated( - Advice { - query_index: 4, - column_index: 4, - rotation: Rotation( - 0, - ), - }, - ), - ), - ), - ), ], advice_queries: [ ( @@ -29489,32 +28935,32 @@ PinnedVerificationKey { (0x2c47c46efa6b729a216455d1887eb910e21f50bedb97d48fd76f89e3abf4e5a4, 0x20da2ca8dde7430e2b663c22d10eeb6b511e341b6a29fe9dd094ab249da4f5db), (0x12da47c8091b8de4fc979e49f7b173d352504f18ccc461ecc5bbe4a798078ba8, 0x2d7eb25b36bb9419d081f457f4424ffc9c3b47d558063bc5c58de550c041cdf9), (0x33a7a93684fd8f5890cc6df73bfee688ff4c778b237afac6a00807d74750f07e, 0x09ba011a18d53d7cf20a020d179ba3a2dd93c1c5fa1c5906d51c16e78c15b2e1), - (0x00f0d0db9c11b86736183d8ef1c4e621a045ad11e4ece8b32e65cd3937193ff0, 0x173d130f6ce49e3ac2be51d550dc1854fec456c82f6ddaa46bcb4c29c9be3601), + (0x2be5e08e9f02057bb5da2591660ea8ddd550114ad4e4751f0407e52424071469, 0x0761484d4ca67f3258780134d76837a261e262315f66c38d818efb7ee8fa9048), (0x334105dd96996a08df56e88261dcd87c5356cfc0f2b8ae0a9419899d5def147b, 0x09ddf24ae765eda056cf59b16ac14464240c83e253135682c02e6546f89dd396), (0x04706edf95516db26def46d92def64d6a61cb357ac5ace44a1015c33238778fa, 0x03560c6396e34aac8e541a7811eb0b7fb1b70262af59976f933135f3bf5b21b1), (0x0b89c282c8f2d54e66c7a11e6b4338a2f06a7c9430f7d3376328f12fa001cac5, 0x098b5c8ee6548183ccb4e60cdfee10b509db34ed136daf3530a426e8f200e89d), (0x2f7f85b86b6adcf714d0df7878f4604d33fd319f39bd00fd5c34378247a155b5, 0x3a2f025447b83b65d148e99c93fe8bb991a81ef6d2f827f010680467361c47fc), - (0x2f6abda2aac141daa71c4840e9219e8436e17490a00d8515671b680f46ffbfab, 0x2c75aee9bdf500ef2a0168b6fa0f10c842985c5c426815e19e6f6636d6cf398a), - (0x0efdfd083488fd21fd34b09babfcea5e011189a37a52b4dc0afb218d5e604059, 0x397ed924bd171cf27208fe866cc124716d635d44f0cba045700e4136a3185179), - (0x0bb5f4d46d728f99749505115a25d8c8f281f46b5fe187a5ed722a68c1f0d8ac, 0x3e31c0c30fb0b01202f35c9336e40e91791d6b92800b2ab62bc9e0d7736a91b8), - (0x2c129e36dba381b51ffea33bf3a8ee685044217aa05865845e870971284b3d80, 0x0a07fed35f5d06923fcec6487e015d1c591d1be2d0028445227fecf733d765b0), - (0x2341c41103ad0c10434f84c82e13070b4018d325e0340f71a980600bac88dba8, 0x18965a11e1ebaea864ccd67f34faf358b5aa34690213eecda9cd94f3ea0db644), - (0x045ceb3c0119d08391456db1c30335869ee9bd9d90898c4d9f65d6486f2e3a60, 0x138805b0eab5b97ecc613077f5d91c5690f642d1d40801e6ace05a2e4947aa0c), + (0x03b29c3e0e5df6f3ba9ce0fb052c0535c8a5b8288faba258ea9e8d6bd6fcf4b2, 0x2bb6c203fc3401bb6de372cd6c8cf7b973f0a6742f39f4b7ec80be443eb65e6c), + (0x1534590f918b8ec3c3f212bce6212e2706b9784926bc3f4c008932f3974b5244, 0x2767f413af8fea55f2226c21f9ae9c9bf9b14e3c181cf2cf94eb6e7efb024f71), + (0x3370cb937349996acaba056ebd00abe986a7d2b60151690da5f5ddebe9d2e644, 0x354521f558c5aad2e0d8b120c885a3a327e6fea64ab78a395317a2ecd542e17b), + (0x0513729700f3ff1cba8d080688f61eac7705283fcf9eb89bd30a539d2f810e32, 0x0ddf8fd425035d59dd4f7c3f7c51767bf9e2352b5a898aa06ee0bef28b468d1c), + (0x081c000b483d260442735f5220efb4f58220d165ef0eb9c89633d0c92d3d9f4b, 0x3be8b1162974276224d52329c972240dbebf5f4db5391c0af15d7253a4a76594), + (0x238572760915711b6ce8a15275a0cfb64d2080cda36053b44c6ead1b2fd8036f, 0x1689fcc8a2962850097bba60487c325070e63236aae3d60c89bf592dbc5405e6), ], permutation: VerifyingKey { commitments: [ - (0x0a10cdf73732c92a9bfccca2a25375be5b665c4bec263a273de481f9cf0b5295, 0x3a00666c4f8b7e78be743934fcde87d488bed7562c7d9058e6216eb6c02d913f), - (0x3e39086d109bc5cacb5876df02e676d8a45de411fb6060582dfde9935d4c9eb5, 0x23b2462b03a2f4a16fc1a85afb3add387576544976a9a79d6d8fa7b6470e7433), - (0x0113540e4a2c0f5abdd94d0cac1560ae76e123321f2eb00ab54b2af05a342d24, 0x35c1e8432935ea039417295e65156588fc7073b51ff6295c698e6a80a3b54d8f), - (0x365d7cd6bfef5ffe3ad7a119137e07c833648fe14e705cb4a1cf8ee26ea1a20a, 0x18ee51fd1b2a568be36f26daaebcb86cc6938fd2d5e46f072bcc275ad709fded), - (0x39d1e52ce9c0cafc4c1a1626b1e0d8bf6a656cf8766f01f6e56fa9636d751c09, 0x3b5d5f81057a46a881474047ded09537dddb788eec68649b41d115bf97ef2a7a), - (0x2489c689eb055e5b8e7905aba42e69cf32ff72f53413a0aff1a21111b22754c0, 0x05fc261835cd944336ec75d4dd2e763693b68137f79838b7e68a144190c2142a), - (0x0be557c80085a65b612710201b738d5b78966eb79515355dab5a95fbfe486dc6, 0x0b658d0f6f39f59dbd4b422edcf73303176a8d5ff2b4126786cce72c1222bd69), - (0x3b9be0eb6f48b9b85d25517d30e5e97da5a888c9cc0440945dbaa62836a996c2, 0x15f297866cfc657bcd6f0e2214fbcb7443a3d6cf3acba1702220949539ed22bf), - (0x178fe0b2e7f7bf3008b0f2b3cf31c0cb4feee66e1a77ae310d81274e357eca08, 0x396df2ba8eb452acc143f2d240ef7d0f641cc2b9601ef2b25b5258e4107b663f), - (0x3972e2487754d8ccc6cfffa905f883c9c2338334894bd59e379a2be11b367df7, 0x2d64ca17acc3ae2a3948b80c2943a40137806607e979d43a834e66ae6e6913aa), - (0x135852e8c481f1e13f3facb7a11ffb358046ef6463757e69208f430652eda7e1, 0x3eccd189556c08b0cad7659259b7ab3336815134c1c1e26a1a55437d17d7fa93), - (0x3a4d8286e222f01440ecedf6873305351edccac685093cdc42395043a6838ebc, 0x19dace40c3d00ae4a842708359d5c2e4c67d1490676b601a57285297f94d290f), + (0x08c7dcef56c18bf78f712fe2c16781929e03b64117550c39e17bf2383084a262, 0x3e0484351466570def03cfba67249d1319bbc6ddd25bf83ebc7d86e502c099af), + (0x3bac5ab5303fbedef8955951cb40620418d47d813aedd62f5e8250b5d2e61d6e, 0x20da35a54cef9724662e2cb262954cfe6edd83bba4a5da78e963ef4a115f0ea8), + (0x1364f575d78b2fcc8227f020b97377aa6e5656b39538e62cb07ffcd523a0e8c4, 0x379bc25e8b3eaff7b52780614a6baf84bd9a114b51596cbf20d8ce5030059939), + (0x30dba0200970e98364c2d8d911700e12e648b1b530ec8f5959ebc9480bc9bdce, 0x1b50964ecea23e32fb3ee2c09e2898d14b293781750bbb3c237df8cfcd62fb93), + (0x346924d8eb634112cdadc6efddcdf33b8c7ca0d1d1ce6e08ca448403094ff556, 0x18f016b8560913fae264ad71a172935b88e044e1b8b147fa7dc7c63b56bf8351), + (0x1af9c9e534c43e4c3d1508bfd77b7d16cd764df511682f7ab2cd9dad9f918762, 0x36f70dcd60250de9208d26e0988e608e873df83d2484ff31ecf9fbfe23f391b3), + (0x01dda2447cbb6875d7600645c36341f692fe9255586eff537aa09b0c922436f3, 0x10d86b9d008679bbc1a8b657e2bd5fa7c5f59fd6c7ce8a911d3fe6820bded560), + (0x0198f863c3b0bb695922e22db57de978aa6a473524720a3411b195ba18206889, 0x223e3135e0dc4ee6e37b96c3a4bbf31522a250a2fbf3d46ba6305b24b8856d2d), + (0x227b5e52351a78a543ec665cba5c8d0f68a676c32b5ff5756bccb9185725b118, 0x3eb92023a61cccd8b150c223b22d73f0ab93a986b1898737f01cad79d1154aaa), + (0x06a4d7a90016ab77a50c8b62ee2406e28aaa19eae367e0898c28671691d9182f, 0x2580100de1db3945fa17446530ad9612cffb79ce2ef3a958f4fa3aa6caaa1695), + (0x024b6a9c117a288e3bae8949a94061ff99bc1d9419d663fed2382925ac6d74f4, 0x0d4da543cd644e5340091759177e3eb31a080909f24b0e606dafc701608fe6aa), + (0x04201f7a9c50a80bf2bd23957dbc2d45982fb413015aeedf32333957b0a65774, 0x31f8f5844762616c90a802a85bf658effdf70a2523a94e812ae9063640488075), (0x21d210b41675a1eae44cbd0f3fd27d69e30716c71873f6089cee61acacd403ab, 0x2275e97c7e84f68bfaa528a9d8be4e059f7abefd80d03fbfca774e8414a9b7c1), (0x0f9e7de28e0f650d99d99d95c0fcd39c9dac9db5aa1973319f66922d6eb9f7d5, 0x1ba644ecc18ad711ddd33af7f695f6834e9f35c93d47a6a5273dabbe800fc7e6), (0x0aab3ab73afac76277cd94a891de15e42ceb09f3a9865dab5c814bebfbb4453f, 0x27119fec3736d99abeeef1ad7b857db7e754e0c158780ed3dd0cdd4dc2453e10), diff --git a/src/circuit/circuit_proof_test_case_zsa.bin b/src/circuit/circuit_proof_test_case_zsa.bin index e64bc990c57fa43775d9c4cd66922d7c0f00d09d..22cbd647707141f23b249899b7a1fc0b4fb8295d 100644 GIT binary patch literal 5283 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 literal 5283 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 diff --git a/src/circuit/circuit_vanilla.rs b/src/circuit/circuit_vanilla.rs index 8d38a6458..7f756e322 100644 --- a/src/circuit/circuit_vanilla.rs +++ b/src/circuit/circuit_vanilla.rs @@ -7,74 +7,42 @@ use group::Curve; use pasta_curves::pallas; use halo2_gadgets::{ - ecc::{ - chip::{EccChip, EccConfig}, - FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarFixedShort, ScalarVar, - }, - poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, + ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, + poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip}, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - merkle::{ - chip::{MerkleChip, MerkleConfig}, - MerklePath, - }, + chip::SinsemillaChip, + merkle::{chip::MerkleChip, MerklePath}, + }, + utilities::lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfig, PallasLookupRangeCheckConfig, }, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, }; - use halo2_proofs::{ circuit::{Layouter, Value}, - plonk::{self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector}, + plonk::{self, Constraints, Expression}, poly::Rotation, }; use crate::{ - constants::{ - OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - }, + circuit::commit_ivk::gadgets::commit_ivk, + circuit::derive_nullifier::gadgets::derive_nullifier, + circuit::note_commit::gadgets::note_commit, + circuit::value_commit_orchard::gadgets::value_commit_orchard, + circuit::Config, + constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains}, orchard_flavor::OrchardVanilla, }; use super::{ - commit_ivk::{self, CommitIvkChip, CommitIvkConfig}, - gadget::{ - add_chip::{self, AddChip, AddConfig}, - AddInstruction, - }, + commit_ivk::CommitIvkChip, + gadget::{add_chip::AddChip, assign_free_advice}, + note_commit::NoteCommitChip, Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, RK_X, RK_Y, }; -use self::{ - gadget::assign_free_advice, - note_commit::{NoteCommitChip, NoteCommitConfig}, -}; - -mod gadget; -mod note_commit; - -/// Configuration needed to use the Orchard Action circuit. -#[derive(Clone, Debug)] -pub struct Config { - primary: Column, - q_orchard: Selector, - advices: [Column; 10], - add_config: AddConfig, - ecc_config: EccConfig, - poseidon_config: PoseidonConfig, - merkle_config_1: MerkleConfig, - merkle_config_2: MerkleConfig, - sinsemilla_config_1: - SinsemillaConfig, - sinsemilla_config_2: - SinsemillaConfig, - commit_ivk_config: CommitIvkConfig, - old_note_commit_config: NoteCommitConfig, - new_note_commit_config: NoteCommitConfig, -} - impl OrchardCircuit for OrchardVanilla { - type Config = Config; + type Config = Config; fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { // Advice columns used in the Orchard circuit. @@ -241,12 +209,12 @@ impl OrchardCircuit for OrchardVanilla { // Configuration to handle decomposition and canonicity checking // for NoteCommit_old. let old_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone()); + NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone(), false); // Configuration to handle decomposition and canonicity checking // for NoteCommit_new. let new_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); + NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone(), false); Config { primary, @@ -386,22 +354,18 @@ impl OrchardCircuit for OrchardVanilla { (magnitude, sign) }; - let v_net = ScalarFixedShort::new( - ecc_chip.clone(), - layouter.namespace(|| "v_net"), - v_net_magnitude_sign.clone(), - )?; let rcv = ScalarFixed::new( ecc_chip.clone(), layouter.namespace(|| "rcv"), circuit.rcv.as_ref().map(|rcv| rcv.inner()), )?; - let cv_net = gadget::value_commit_orchard( + let cv_net = value_commit_orchard( layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), ecc_chip.clone(), - v_net, + v_net_magnitude_sign.clone(), rcv, + None, )?; // Constrain cv_net to equal public input @@ -414,8 +378,8 @@ impl OrchardCircuit for OrchardVanilla { // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). let nf_old = { - let nf_old = gadget::derive_nullifier( - layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old)"), + let nf_old = derive_nullifier( + &mut layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_old, cm_old)"), config.poseidon_chip(), config.add_chip(), ecc_chip.clone(), @@ -423,6 +387,7 @@ impl OrchardCircuit for OrchardVanilla { &psi_old, &cm_old, nk.clone(), + None, )?; // Constrain nf_old to equal public input @@ -464,7 +429,7 @@ impl OrchardCircuit for OrchardVanilla { circuit.rivk.map(|rivk| rivk.inner()), )?; - gadget::commit_ivk( + commit_ivk( config.sinsemilla_chip_1(), ecc_chip.clone(), config.commit_ivk_chip(), @@ -511,7 +476,7 @@ impl OrchardCircuit for OrchardVanilla { )?; // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let derived_cm_old = gadget::note_commit( + let derived_cm_old = note_commit( layouter.namespace(|| { "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" }), @@ -524,6 +489,7 @@ impl OrchardCircuit for OrchardVanilla { rho_old, psi_old, rcm_old, + None, )?; // Constrain derived cm_old to equal witnessed cm_old @@ -571,7 +537,7 @@ impl OrchardCircuit for OrchardVanilla { )?; // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let cm_new = gadget::note_commit( + let cm_new = note_commit( layouter.namespace(|| { "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" }), @@ -584,6 +550,7 @@ impl OrchardCircuit for OrchardVanilla { rho_new, psi_new, rcm_new, + None, )?; let cmx = cm_new.extract_p(); diff --git a/src/circuit/circuit_vanilla/gadget.rs b/src/circuit/circuit_vanilla/gadget.rs deleted file mode 100644 index 5006f8083..000000000 --- a/src/circuit/circuit_vanilla/gadget.rs +++ /dev/null @@ -1,190 +0,0 @@ -//! Gadgets used in the Orchard circuit (Vanilla variation). - -use ff::Field; -use pasta_curves::pallas; - -use super::{add_chip, commit_ivk::CommitIvkChip, note_commit::NoteCommitChip, AddInstruction}; -use crate::constants::{ - NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - ValueCommitV, -}; -use halo2_gadgets::{ - ecc::{ - chip::EccChip, EccInstructions, FixedPoint, FixedPointBaseField, FixedPointShort, Point, - ScalarFixed, ScalarFixedShort, X, - }, - poseidon::{ - primitives::{self as poseidon, ConstantLength}, - Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, - }, - sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, -}; -use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - plonk::{self, Advice, Assigned, Column}, -}; - -impl super::Config { - pub(super) fn add_chip(&self) -> add_chip::AddChip { - add_chip::AddChip::construct(self.add_config.clone()) - } - - pub(super) fn commit_ivk_chip(&self) -> CommitIvkChip { - CommitIvkChip::construct(self.commit_ivk_config.clone()) - } - - pub(super) fn ecc_chip(&self) -> EccChip { - EccChip::construct(self.ecc_config.clone()) - } - - pub(super) fn sinsemilla_chip_1( - &self, - ) -> SinsemillaChip { - SinsemillaChip::construct(self.sinsemilla_config_1.clone()) - } - - pub(super) fn sinsemilla_chip_2( - &self, - ) -> SinsemillaChip { - SinsemillaChip::construct(self.sinsemilla_config_2.clone()) - } - - pub(super) fn merkle_chip_1( - &self, - ) -> MerkleChip { - MerkleChip::construct(self.merkle_config_1.clone()) - } - - pub(super) fn merkle_chip_2( - &self, - ) -> MerkleChip { - MerkleChip::construct(self.merkle_config_2.clone()) - } - - pub(super) fn poseidon_chip(&self) -> PoseidonChip { - PoseidonChip::construct(self.poseidon_config.clone()) - } - - pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { - NoteCommitChip::construct(self.new_note_commit_config.clone()) - } - - pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { - NoteCommitChip::construct(self.old_note_commit_config.clone()) - } -} - -/// Witnesses the given value in a standalone region. -/// -/// Usages of this helper are technically superfluous, as the single-cell region is only -/// ever used in equality constraints. We could eliminate them with a -/// [write-on-copy abstraction](https://github.com/zcash/halo2/issues/334). -pub(in crate::circuit) fn assign_free_advice( - mut layouter: impl Layouter, - column: Column, - value: Value, -) -> Result, plonk::Error> -where - for<'v> Assigned: From<&'v V>, -{ - layouter.assign_region( - || "load private", - |mut region| region.assign_advice(|| "load private", column, 0, || value), - ) -} - -/// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. -/// -/// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit -pub(in crate::circuit) fn value_commit_orchard< - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - ecc_chip: EccChip, - v: ScalarFixedShort, - rcv: ScalarFixed, -) -> Result, plonk::Error> { - // commitment = [v] ValueCommitV - let (commitment, _) = { - let value_commit_v = ValueCommitV; - let value_commit_v = FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); - value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v)? - }; - - // blind = [rcv] ValueCommitR - let (blind, _rcv) = { - let value_commit_r = OrchardFixedBasesFull::ValueCommitR; - let value_commit_r = FixedPoint::from_inner(ecc_chip, value_commit_r); - - // [rcv] ValueCommitR - value_commit_r.mul(layouter.namespace(|| "[rcv] ValueCommitR"), rcv)? - }; - - // [v] ValueCommitV + [rcv] ValueCommitR - commitment.add(layouter.namespace(|| "cv"), &blind) -} - -/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. -/// -/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers -#[allow(clippy::too_many_arguments)] -pub(in crate::circuit) fn derive_nullifier< - PoseidonChip: PoseidonSpongeInstructions, 3, 2>, - AddChip: AddInstruction, - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - poseidon_chip: PoseidonChip, - add_chip: AddChip, - ecc_chip: EccChip, - rho: AssignedCell, - psi: &AssignedCell, - cm: &Point, - nk: AssignedCell, -) -> Result, plonk::Error> { - // hash = poseidon_hash(nk, rho) - let hash = { - let poseidon_message = [nk, rho]; - let poseidon_hasher = - PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; - poseidon_hasher.hash( - layouter.namespace(|| "Poseidon hash (nk, rho)"), - poseidon_message, - )? - }; - - // Add hash output to psi. - // `scalar` = poseidon_hash(nk, rho) + psi. - let scalar = add_chip.add( - layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), - &hash, - psi, - )?; - - // Multiply scalar by NullifierK - // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. - // - let product = { - let nullifier_k = FixedPointBaseField::from_inner(ecc_chip, NullifierK); - nullifier_k.mul( - layouter.namespace(|| "[poseidon_output + psi] NullifierK"), - scalar, - )? - }; - - // Add cm to multiplied fixed base to get nf - // cm + [poseidon_output + psi] NullifierK - cm.add(layouter.namespace(|| "nf"), &product) - .map(|res| res.extract_p()) -} - -pub(in crate::circuit) use super::commit_ivk::gadgets::commit_ivk; -pub(in crate::circuit) use super::note_commit::gadgets::note_commit; diff --git a/src/circuit/circuit_vanilla/note_commit.rs b/src/circuit/circuit_vanilla/note_commit.rs deleted file mode 100644 index 986149e0f..000000000 --- a/src/circuit/circuit_vanilla/note_commit.rs +++ /dev/null @@ -1,2365 +0,0 @@ -//! Note commitment logic for the Orchard circuit (Vanilla variation). - -use core::iter; - -use group::ff::PrimeField; -use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, - poly::Rotation, -}; -use pasta_curves::pallas; - -use crate::{ - constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}, - value::NoteValue, -}; -use halo2_gadgets::{ - ecc::{ - chip::{EccChip, NonIdentityEccPoint}, - Point, ScalarFixed, - }, - sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - CommitDomain, Message, MessagePiece, - }, - utilities::{ - bool_check, - lookup_range_check::{LookupRangeCheck, PallasLookupRangeCheckConfig}, - FieldValue, RangeConstrained, - }, -}; - -type NoteCommitPiece = MessagePiece< - pallas::Affine, - SinsemillaChip, - 10, - 253, ->; - -/// The values of the running sum at the start and end of the range being used for a -/// canonicity check. -type CanonicityBounds = ( - AssignedCell, - AssignedCell, -); - -/* - - We need to hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi, - where - - g★_d is the representation of the point g_d, with 255 bits used for the - x-coordinate and 1 bit used for the y-coordinate; - - pk★_d is the representation of the point pk_d, with 255 bits used for the - x-coordinate and 1 bit used for the y-coordinate; - - v is a 64-bit value; - - rho is a base field element (255 bits); and - - psi is a base field element (255 bits). -*/ - -/// b = b_0 || b_1 || b_2 || b_3 -/// = (bits 250..=253 of x(g_d)) || (bit 254 of x(g_d)) || (ỹ bit of g_d) || (bits 0..=3 of pk★_d) -/// -/// | A_6 | A_7 | A_8 | q_notecommit_b | -/// ------------------------------------ -/// | b | b_0 | b_1 | 1 | -/// | | b_2 | b_3 | 0 | -/// -/// -#[derive(Clone, Debug)] -struct DecomposeB { - q_notecommit_b: Selector, - col_l: Column, - col_m: Column, - col_r: Column, -} - -impl DecomposeB { - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - two_pow_4: pallas::Base, - two_pow_5: pallas::Base, - two_pow_6: pallas::Base, - ) -> Self { - let q_notecommit_b = meta.selector(); - - meta.create_gate("NoteCommit MessagePiece b", |meta| { - let q_notecommit_b = meta.query_selector(q_notecommit_b); - - // b has been constrained to 10 bits by the Sinsemilla hash. - let b = meta.query_advice(col_l, Rotation::cur()); - // b_0 has been constrained to be 4 bits outside this gate. - let b_0 = meta.query_advice(col_m, Rotation::cur()); - // This gate constrains b_1 to be boolean. - let b_1 = meta.query_advice(col_r, Rotation::cur()); - // This gate constrains b_2 to be boolean. - let b_2 = meta.query_advice(col_m, Rotation::next()); - // b_3 has been constrained to 4 bits outside this gate. - let b_3 = meta.query_advice(col_r, Rotation::next()); - - // b = b_0 + (2^4) b_1 + (2^5) b_2 + (2^6) b_3 - let decomposition_check = - b - (b_0 + b_1.clone() * two_pow_4 + b_2.clone() * two_pow_5 + b_3 * two_pow_6); - - Constraints::with_selector( - q_notecommit_b, - [ - ("bool_check b_1", bool_check(b_1)), - ("bool_check b_2", bool_check(b_2)), - ("decomposition", decomposition_check), - ], - ) - }); - - Self { - q_notecommit_b, - col_l, - col_m, - col_r, - } - } - - #[allow(clippy::type_complexity)] - fn decompose( - lookup_config: &PallasLookupRangeCheckConfig, - chip: SinsemillaChip, - layouter: &mut impl Layouter, - g_d: &NonIdentityEccPoint, - pk_d: &NonIdentityEccPoint, - ) -> Result< - ( - NoteCommitPiece, - RangeConstrained>, - RangeConstrained>, - RangeConstrained>, - RangeConstrained>, - ), - Error, - > { - let (gd_x, gd_y) = (g_d.x(), g_d.y()); - - // Constrain b_0 to be 4 bits - let b_0 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "b_0"), - gd_x.value(), - 250..254, - )?; - - // b_1, b_2 will be boolean-constrained in the gate. - let b_1 = RangeConstrained::bitrange_of(gd_x.value(), 254..255); - let b_2 = RangeConstrained::bitrange_of(gd_y.value(), 0..1); - - // Constrain b_3 to be 4 bits - let b_3 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "b_3"), - pk_d.x().value(), - 0..4, - )?; - - let b = MessagePiece::from_subpieces( - chip, - layouter.namespace(|| "b"), - [b_0.value(), b_1, b_2, b_3.value()], - )?; - - Ok((b, b_0, b_1, b_2, b_3)) - } - - fn assign( - &self, - layouter: &mut impl Layouter, - b: NoteCommitPiece, - b_0: RangeConstrained>, - b_1: RangeConstrained>, - b_2: RangeConstrained>, - b_3: RangeConstrained>, - ) -> Result, Error> { - layouter.assign_region( - || "NoteCommit MessagePiece b", - |mut region| { - self.q_notecommit_b.enable(&mut region, 0)?; - - b.inner() - .cell_value() - .copy_advice(|| "b", &mut region, self.col_l, 0)?; - b_0.inner() - .copy_advice(|| "b_0", &mut region, self.col_m, 0)?; - let b_1 = region.assign_advice(|| "b_1", self.col_r, 0, || *b_1.inner())?; - - b_2.inner() - .copy_advice(|| "b_2", &mut region, self.col_m, 1)?; - b_3.inner() - .copy_advice(|| "b_3", &mut region, self.col_r, 1)?; - - Ok(b_1) - }, - ) - } -} - -/// d = d_0 || d_1 || d_2 || d_3 -/// = (bit 254 of x(pk_d)) || (ỹ bit of pk_d) || (bits 0..=7 of v) || (bits 8..=57 of v) -/// -/// | A_6 | A_7 | A_8 | q_notecommit_d | -/// ------------------------------------ -/// | d | d_0 | d_1 | 1 | -/// | | d_2 | d_3 | 0 | -/// -/// -#[derive(Clone, Debug)] -struct DecomposeD { - q_notecommit_d: Selector, - col_l: Column, - col_m: Column, - col_r: Column, -} - -impl DecomposeD { - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - two: pallas::Base, - two_pow_2: pallas::Base, - two_pow_10: pallas::Base, - ) -> Self { - let q_notecommit_d = meta.selector(); - - meta.create_gate("NoteCommit MessagePiece d", |meta| { - let q_notecommit_d = meta.query_selector(q_notecommit_d); - - // d has been constrained to 60 bits by the Sinsemilla hash. - let d = meta.query_advice(col_l, Rotation::cur()); - // This gate constrains d_0 to be boolean. - let d_0 = meta.query_advice(col_m, Rotation::cur()); - // This gate constrains d_1 to be boolean. - let d_1 = meta.query_advice(col_r, Rotation::cur()); - // d_2 has been constrained to 8 bits outside this gate. - let d_2 = meta.query_advice(col_m, Rotation::next()); - // d_3 is set to z1_d. - let d_3 = meta.query_advice(col_r, Rotation::next()); - - // d = d_0 + (2) d_1 + (2^2) d_2 + (2^10) d_3 - let decomposition_check = - d - (d_0.clone() + d_1.clone() * two + d_2 * two_pow_2 + d_3 * two_pow_10); - - Constraints::with_selector( - q_notecommit_d, - [ - ("bool_check d_0", bool_check(d_0)), - ("bool_check d_1", bool_check(d_1)), - ("decomposition", decomposition_check), - ], - ) - }); - - Self { - q_notecommit_d, - col_l, - col_m, - col_r, - } - } - - #[allow(clippy::type_complexity)] - fn decompose( - lookup_config: &PallasLookupRangeCheckConfig, - chip: SinsemillaChip, - layouter: &mut impl Layouter, - pk_d: &NonIdentityEccPoint, - value: &AssignedCell, - ) -> Result< - ( - NoteCommitPiece, - RangeConstrained>, - RangeConstrained>, - RangeConstrained>, - ), - Error, - > { - let value_val = value.value().map(|v| pallas::Base::from(v.inner())); - - // d_0, d_1 will be boolean-constrained in the gate. - let d_0 = RangeConstrained::bitrange_of(pk_d.x().value(), 254..255); - let d_1 = RangeConstrained::bitrange_of(pk_d.y().value(), 0..1); - - // Constrain d_2 to be 8 bits - let d_2 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "d_2"), - value_val.as_ref(), - 0..8, - )?; - - // d_3 = z1_d from the SinsemillaHash(d) running sum output. - let d_3 = RangeConstrained::bitrange_of(value_val.as_ref(), 8..58); - - let d = MessagePiece::from_subpieces( - chip, - layouter.namespace(|| "d"), - [d_0, d_1, d_2.value(), d_3], - )?; - - Ok((d, d_0, d_1, d_2)) - } - - fn assign( - &self, - layouter: &mut impl Layouter, - d: NoteCommitPiece, - d_0: RangeConstrained>, - d_1: RangeConstrained>, - d_2: RangeConstrained>, - z1_d: AssignedCell, - ) -> Result, Error> { - layouter.assign_region( - || "NoteCommit MessagePiece d", - |mut region| { - self.q_notecommit_d.enable(&mut region, 0)?; - - d.inner() - .cell_value() - .copy_advice(|| "d", &mut region, self.col_l, 0)?; - let d_0 = region.assign_advice(|| "d_0", self.col_m, 0, || *d_0.inner())?; - d_1.inner() - .copy_advice(|| "d_1", &mut region, self.col_r, 0)?; - - d_2.inner() - .copy_advice(|| "d_2", &mut region, self.col_m, 1)?; - z1_d.copy_advice(|| "d_3 = z1_d", &mut region, self.col_r, 1)?; - - Ok(d_0) - }, - ) - } -} - -/// e = e_0 || e_1 = (bits 58..=63 of v) || (bits 0..=3 of rho) -/// -/// | A_6 | A_7 | A_8 | q_notecommit_e | -/// ------------------------------------ -/// | e | e_0 | e_1 | 1 | -/// -/// -#[derive(Clone, Debug)] -struct DecomposeE { - q_notecommit_e: Selector, - col_l: Column, - col_m: Column, - col_r: Column, -} - -impl DecomposeE { - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - two_pow_6: pallas::Base, - ) -> Self { - let q_notecommit_e = meta.selector(); - - meta.create_gate("NoteCommit MessagePiece e", |meta| { - let q_notecommit_e = meta.query_selector(q_notecommit_e); - - // e has been constrained to 10 bits by the Sinsemilla hash. - let e = meta.query_advice(col_l, Rotation::cur()); - // e_0 has been constrained to 6 bits outside this gate. - let e_0 = meta.query_advice(col_m, Rotation::cur()); - // e_1 has been constrained to 4 bits outside this gate. - let e_1 = meta.query_advice(col_r, Rotation::cur()); - - // e = e_0 + (2^6) e_1 - let decomposition_check = e - (e_0 + e_1 * two_pow_6); - - Constraints::with_selector(q_notecommit_e, Some(("decomposition", decomposition_check))) - }); - - Self { - q_notecommit_e, - col_l, - col_m, - col_r, - } - } - - #[allow(clippy::type_complexity)] - fn decompose( - lookup_config: &PallasLookupRangeCheckConfig, - chip: SinsemillaChip, - layouter: &mut impl Layouter, - value: &AssignedCell, - rho: &AssignedCell, - ) -> Result< - ( - NoteCommitPiece, - RangeConstrained>, - RangeConstrained>, - ), - Error, - > { - let value_val = value.value().map(|v| pallas::Base::from(v.inner())); - - // Constrain e_0 to be 6 bits. - let e_0 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "e_0"), - value_val.as_ref(), - 58..64, - )?; - - // Constrain e_1 to be 4 bits. - let e_1 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "e_1"), - rho.value(), - 0..4, - )?; - - let e = MessagePiece::from_subpieces( - chip, - layouter.namespace(|| "e"), - [e_0.value(), e_1.value()], - )?; - - Ok((e, e_0, e_1)) - } - - fn assign( - &self, - layouter: &mut impl Layouter, - e: NoteCommitPiece, - e_0: RangeConstrained>, - e_1: RangeConstrained>, - ) -> Result<(), Error> { - layouter.assign_region( - || "NoteCommit MessagePiece e", - |mut region| { - self.q_notecommit_e.enable(&mut region, 0)?; - - e.inner() - .cell_value() - .copy_advice(|| "e", &mut region, self.col_l, 0)?; - e_0.inner() - .copy_advice(|| "e_0", &mut region, self.col_m, 0)?; - e_1.inner() - .copy_advice(|| "e_1", &mut region, self.col_r, 0)?; - - Ok(()) - }, - ) - } -} - -/// g = g_0 || g_1 || g_2 -/// = (bit 254 of rho) || (bits 0..=8 of psi) || (bits 9..=248 of psi) -/// -/// | A_6 | A_7 | q_notecommit_g | -/// ------------------------------ -/// | g | g_0 | 1 | -/// | g_1 | g_2 | 0 | -/// -/// -#[derive(Clone, Debug)] -struct DecomposeG { - q_notecommit_g: Selector, - col_l: Column, - col_m: Column, -} - -impl DecomposeG { - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - two: pallas::Base, - two_pow_10: pallas::Base, - ) -> Self { - let q_notecommit_g = meta.selector(); - - meta.create_gate("NoteCommit MessagePiece g", |meta| { - let q_notecommit_g = meta.query_selector(q_notecommit_g); - - // g has been constrained to 250 bits by the Sinsemilla hash. - let g = meta.query_advice(col_l, Rotation::cur()); - // This gate constrains g_0 to be boolean. - let g_0 = meta.query_advice(col_m, Rotation::cur()); - // g_1 has been constrained to 9 bits outside this gate. - let g_1 = meta.query_advice(col_l, Rotation::next()); - // g_2 is set to z1_g. - let g_2 = meta.query_advice(col_m, Rotation::next()); - - // g = g_0 + (2) g_1 + (2^10) g_2 - let decomposition_check = g - (g_0.clone() + g_1 * two + g_2 * two_pow_10); - - Constraints::with_selector( - q_notecommit_g, - [ - ("bool_check g_0", bool_check(g_0)), - ("decomposition", decomposition_check), - ], - ) - }); - - Self { - q_notecommit_g, - col_l, - col_m, - } - } - - #[allow(clippy::type_complexity)] - fn decompose( - lookup_config: &PallasLookupRangeCheckConfig, - chip: SinsemillaChip, - layouter: &mut impl Layouter, - rho: &AssignedCell, - psi: &AssignedCell, - ) -> Result< - ( - NoteCommitPiece, - RangeConstrained>, - RangeConstrained>, - ), - Error, - > { - // g_0 will be boolean-constrained in the gate. - let g_0 = RangeConstrained::bitrange_of(rho.value(), 254..255); - - // Constrain g_1 to be 9 bits. - let g_1 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "g_1"), - psi.value(), - 0..9, - )?; - - // g_2 = z1_g from the SinsemillaHash(g) running sum output. - let g_2 = RangeConstrained::bitrange_of(psi.value(), 9..249); - - let g = MessagePiece::from_subpieces( - chip, - layouter.namespace(|| "g"), - [g_0, g_1.value(), g_2], - )?; - - Ok((g, g_0, g_1)) - } - - fn assign( - &self, - layouter: &mut impl Layouter, - g: NoteCommitPiece, - g_0: RangeConstrained>, - g_1: RangeConstrained>, - z1_g: AssignedCell, - ) -> Result, Error> { - layouter.assign_region( - || "NoteCommit MessagePiece g", - |mut region| { - self.q_notecommit_g.enable(&mut region, 0)?; - - g.inner() - .cell_value() - .copy_advice(|| "g", &mut region, self.col_l, 0)?; - let g_0 = region.assign_advice(|| "g_0", self.col_m, 0, || *g_0.inner())?; - - g_1.inner() - .copy_advice(|| "g_1", &mut region, self.col_l, 1)?; - z1_g.copy_advice(|| "g_2 = z1_g", &mut region, self.col_m, 1)?; - - Ok(g_0) - }, - ) - } -} - -/// h = h_0 || h_1 || h_2 -/// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits -/// -/// | A_6 | A_7 | A_8 | q_notecommit_h | -/// ------------------------------------ -/// | h | h_0 | h_1 | 1 | -/// -/// -#[derive(Clone, Debug)] -struct DecomposeH { - q_notecommit_h: Selector, - col_l: Column, - col_m: Column, - col_r: Column, -} - -impl DecomposeH { - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - two_pow_5: pallas::Base, - ) -> Self { - let q_notecommit_h = meta.selector(); - - meta.create_gate("NoteCommit MessagePiece h", |meta| { - let q_notecommit_h = meta.query_selector(q_notecommit_h); - - // h has been constrained to 10 bits by the Sinsemilla hash. - let h = meta.query_advice(col_l, Rotation::cur()); - // h_0 has been constrained to be 5 bits outside this gate. - let h_0 = meta.query_advice(col_m, Rotation::cur()); - // This gate constrains h_1 to be boolean. - let h_1 = meta.query_advice(col_r, Rotation::cur()); - - // h = h_0 + (2^5) h_1 - let decomposition_check = h - (h_0 + h_1.clone() * two_pow_5); - - Constraints::with_selector( - q_notecommit_h, - [ - ("bool_check h_1", bool_check(h_1)), - ("decomposition", decomposition_check), - ], - ) - }); - - Self { - q_notecommit_h, - col_l, - col_m, - col_r, - } - } - - #[allow(clippy::type_complexity)] - fn decompose( - lookup_config: &PallasLookupRangeCheckConfig, - chip: SinsemillaChip, - layouter: &mut impl Layouter, - psi: &AssignedCell, - ) -> Result< - ( - NoteCommitPiece, - RangeConstrained>, - RangeConstrained>, - ), - Error, - > { - // Constrain h_0 to be 5 bits. - let h_0 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "h_0"), - psi.value(), - 249..254, - )?; - - // h_1 will be boolean-constrained in the gate. - let h_1 = RangeConstrained::bitrange_of(psi.value(), 254..255); - - let h = MessagePiece::from_subpieces( - chip, - layouter.namespace(|| "h"), - [ - h_0.value(), - h_1, - RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..4), - ], - )?; - - Ok((h, h_0, h_1)) - } - - fn assign( - &self, - layouter: &mut impl Layouter, - h: NoteCommitPiece, - h_0: RangeConstrained>, - h_1: RangeConstrained>, - ) -> Result, Error> { - layouter.assign_region( - || "NoteCommit MessagePiece h", - |mut region| { - self.q_notecommit_h.enable(&mut region, 0)?; - - h.inner() - .cell_value() - .copy_advice(|| "h", &mut region, self.col_l, 0)?; - h_0.inner() - .copy_advice(|| "h_0", &mut region, self.col_m, 0)?; - let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?; - - Ok(h_1) - }, - ) - } -} - -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_g_d | -/// ----------------------------------------------------------- -/// | x(g_d) | b_0 | a | z13_a | 1 | -/// | | b_1 | a_prime | z13_a_prime | 0 | -/// -/// -#[derive(Clone, Debug)] -struct GdCanonicity { - q_notecommit_g_d: Selector, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, -} - -impl GdCanonicity { - #[allow(clippy::too_many_arguments)] - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, - two_pow_130: Expression, - two_pow_250: pallas::Base, - two_pow_254: pallas::Base, - t_p: Expression, - ) -> Self { - let q_notecommit_g_d = meta.selector(); - - meta.create_gate("NoteCommit input g_d", |meta| { - let q_notecommit_g_d = meta.query_selector(q_notecommit_g_d); - - let gd_x = meta.query_advice(col_l, Rotation::cur()); - - // b_0 has been constrained to be 4 bits outside this gate. - let b_0 = meta.query_advice(col_m, Rotation::cur()); - // b_1 has been constrained to be boolean outside this gate. - let b_1 = meta.query_advice(col_m, Rotation::next()); - - // a has been constrained to 250 bits by the Sinsemilla hash. - let a = meta.query_advice(col_r, Rotation::cur()); - let a_prime = meta.query_advice(col_r, Rotation::next()); - - let z13_a = meta.query_advice(col_z, Rotation::cur()); - let z13_a_prime = meta.query_advice(col_z, Rotation::next()); - - // x(g_d) = a + (2^250)b_0 + (2^254)b_1 - let decomposition_check = { - let sum = a.clone() + b_0.clone() * two_pow_250 + b_1.clone() * two_pow_254; - sum - gd_x - }; - - // a_prime = a + 2^130 - t_P - let a_prime_check = a + two_pow_130 - t_p - a_prime; - - // The gd_x_canonicity_checks are enforced if and only if `b_1` = 1. - // x(g_d) = a (250 bits) || b_0 (4 bits) || b_1 (1 bit) - let canonicity_checks = iter::empty() - .chain(Some(("b_1 = 1 => b_0", b_0))) - .chain(Some(("b_1 = 1 => z13_a", z13_a))) - .chain(Some(("b_1 = 1 => z13_a_prime", z13_a_prime))) - .map(move |(name, poly)| (name, b_1.clone() * poly)); - - Constraints::with_selector( - q_notecommit_g_d, - iter::empty() - .chain(Some(("decomposition", decomposition_check))) - .chain(Some(("a_prime_check", a_prime_check))) - .chain(canonicity_checks), - ) - }); - - Self { - q_notecommit_g_d, - col_l, - col_m, - col_r, - col_z, - } - } - - #[allow(clippy::too_many_arguments)] - fn assign( - &self, - layouter: &mut impl Layouter, - g_d: &NonIdentityEccPoint, - a: NoteCommitPiece, - b_0: RangeConstrained>, - b_1: AssignedCell, - a_prime: AssignedCell, - z13_a: AssignedCell, - z13_a_prime: AssignedCell, - ) -> Result<(), Error> { - layouter.assign_region( - || "NoteCommit input g_d", - |mut region| { - g_d.x().copy_advice(|| "gd_x", &mut region, self.col_l, 0)?; - - b_0.inner() - .copy_advice(|| "b_0", &mut region, self.col_m, 0)?; - b_1.copy_advice(|| "b_1", &mut region, self.col_m, 1)?; - - a.inner() - .cell_value() - .copy_advice(|| "a", &mut region, self.col_r, 0)?; - a_prime.copy_advice(|| "a_prime", &mut region, self.col_r, 1)?; - - z13_a.copy_advice(|| "z13_a", &mut region, self.col_z, 0)?; - z13_a_prime.copy_advice(|| "z13_a_prime", &mut region, self.col_z, 1)?; - - self.q_notecommit_g_d.enable(&mut region, 0) - }, - ) - } -} - -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d | -/// ------------------------------------------------------------------- -/// | x(pk_d) | b_3 | c | z13_c | 1 | -/// | | d_0 | b3_c_prime | z14_b3_c_prime | 0 | -/// -/// -#[derive(Clone, Debug)] -struct PkdCanonicity { - q_notecommit_pk_d: Selector, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, -} - -impl PkdCanonicity { - #[allow(clippy::too_many_arguments)] - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, - two_pow_4: pallas::Base, - two_pow_140: Expression, - two_pow_254: pallas::Base, - t_p: Expression, - ) -> Self { - let q_notecommit_pk_d = meta.selector(); - - meta.create_gate("NoteCommit input pk_d", |meta| { - let q_notecommit_pk_d = meta.query_selector(q_notecommit_pk_d); - - let pkd_x = meta.query_advice(col_l, Rotation::cur()); - - // `b_3` has been constrained to 4 bits outside this gate. - let b_3 = meta.query_advice(col_m, Rotation::cur()); - // d_0 has been constrained to be boolean outside this gate. - let d_0 = meta.query_advice(col_m, Rotation::next()); - - // `c` has been constrained to 250 bits by the Sinsemilla hash. - let c = meta.query_advice(col_r, Rotation::cur()); - let b3_c_prime = meta.query_advice(col_r, Rotation::next()); - - let z13_c = meta.query_advice(col_z, Rotation::cur()); - let z14_b3_c_prime = meta.query_advice(col_z, Rotation::next()); - - // x(pk_d) = b_3 + (2^4)c + (2^254)d_0 - let decomposition_check = { - let sum = b_3.clone() + c.clone() * two_pow_4 + d_0.clone() * two_pow_254; - sum - pkd_x - }; - - // b3_c_prime = b_3 + (2^4)c + 2^140 - t_P - let b3_c_prime_check = b_3 + (c * two_pow_4) + two_pow_140 - t_p - b3_c_prime; - - // The pkd_x_canonicity_checks are enforced if and only if `d_0` = 1. - // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` - let canonicity_checks = iter::empty() - .chain(Some(("d_0 = 1 => z13_c", z13_c))) - .chain(Some(("d_0 = 1 => z14_b3_c_prime", z14_b3_c_prime))) - .map(move |(name, poly)| (name, d_0.clone() * poly)); - - Constraints::with_selector( - q_notecommit_pk_d, - iter::empty() - .chain(Some(("decomposition", decomposition_check))) - .chain(Some(("b3_c_prime_check", b3_c_prime_check))) - .chain(canonicity_checks), - ) - }); - - Self { - q_notecommit_pk_d, - col_l, - col_m, - col_r, - col_z, - } - } - - #[allow(clippy::too_many_arguments)] - fn assign( - &self, - layouter: &mut impl Layouter, - pk_d: &NonIdentityEccPoint, - b_3: RangeConstrained>, - c: NoteCommitPiece, - d_0: AssignedCell, - b3_c_prime: AssignedCell, - z13_c: AssignedCell, - z14_b3_c_prime: AssignedCell, - ) -> Result<(), Error> { - layouter.assign_region( - || "NoteCommit input pk_d", - |mut region| { - pk_d.x() - .copy_advice(|| "pkd_x", &mut region, self.col_l, 0)?; - - b_3.inner() - .copy_advice(|| "b_3", &mut region, self.col_m, 0)?; - d_0.copy_advice(|| "d_0", &mut region, self.col_m, 1)?; - - c.inner() - .cell_value() - .copy_advice(|| "c", &mut region, self.col_r, 0)?; - b3_c_prime.copy_advice(|| "b3_c_prime", &mut region, self.col_r, 1)?; - - z13_c.copy_advice(|| "z13_c", &mut region, self.col_z, 0)?; - z14_b3_c_prime.copy_advice(|| "z14_b3_c_prime", &mut region, self.col_z, 1)?; - - self.q_notecommit_pk_d.enable(&mut region, 0) - }, - ) - } -} - -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_value | -/// ------------------------------------------------ -/// | value | d_2 | d_3 | e_0 | 1 | -/// -/// -#[derive(Clone, Debug)] -struct ValueCanonicity { - q_notecommit_value: Selector, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, -} - -impl ValueCanonicity { - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, - two_pow_8: pallas::Base, - two_pow_58: pallas::Base, - ) -> Self { - let q_notecommit_value = meta.selector(); - - meta.create_gate("NoteCommit input value", |meta| { - let q_notecommit_value = meta.query_selector(q_notecommit_value); - - let value = meta.query_advice(col_l, Rotation::cur()); - // d_2 has been constrained to 8 bits outside this gate. - let d_2 = meta.query_advice(col_m, Rotation::cur()); - // z1_d has been constrained to 50 bits by the Sinsemilla hash. - let z1_d = meta.query_advice(col_r, Rotation::cur()); - let d_3 = z1_d; - // `e_0` has been constrained to 6 bits outside this gate. - let e_0 = meta.query_advice(col_z, Rotation::cur()); - - // value = d_2 + (2^8)d_3 + (2^58)e_0 - let value_check = d_2 + d_3 * two_pow_8 + e_0 * two_pow_58 - value; - - Constraints::with_selector(q_notecommit_value, Some(("value_check", value_check))) - }); - - Self { - q_notecommit_value, - col_l, - col_m, - col_r, - col_z, - } - } - - fn assign( - &self, - layouter: &mut impl Layouter, - value: AssignedCell, - d_2: RangeConstrained>, - z1_d: AssignedCell, - e_0: RangeConstrained>, - ) -> Result<(), Error> { - layouter.assign_region( - || "NoteCommit input value", - |mut region| { - value.copy_advice(|| "value", &mut region, self.col_l, 0)?; - d_2.inner() - .copy_advice(|| "d_2", &mut region, self.col_m, 0)?; - z1_d.copy_advice(|| "d3 = z1_d", &mut region, self.col_r, 0)?; - e_0.inner() - .copy_advice(|| "e_0", &mut region, self.col_z, 0)?; - - self.q_notecommit_value.enable(&mut region, 0) - }, - ) - } -} - -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_rho | -/// -------------------------------------------------------------- -/// | rho | e_1 | f | z13_f | 1 | -/// | | g_0 | e1_f_prime | z14_e1_f_prime | 0 | -/// -/// -#[derive(Clone, Debug)] -struct RhoCanonicity { - q_notecommit_rho: Selector, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, -} - -impl RhoCanonicity { - #[allow(clippy::too_many_arguments)] - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, - two_pow_4: pallas::Base, - two_pow_140: Expression, - two_pow_254: pallas::Base, - t_p: Expression, - ) -> Self { - let q_notecommit_rho = meta.selector(); - - meta.create_gate("NoteCommit input rho", |meta| { - let q_notecommit_rho = meta.query_selector(q_notecommit_rho); - - let rho = meta.query_advice(col_l, Rotation::cur()); - - // `e_1` has been constrained to 4 bits outside this gate. - let e_1 = meta.query_advice(col_m, Rotation::cur()); - let g_0 = meta.query_advice(col_m, Rotation::next()); - - // `f` has been constrained to 250 bits by the Sinsemilla hash. - let f = meta.query_advice(col_r, Rotation::cur()); - let e1_f_prime = meta.query_advice(col_r, Rotation::next()); - - let z13_f = meta.query_advice(col_z, Rotation::cur()); - let z14_e1_f_prime = meta.query_advice(col_z, Rotation::next()); - - // rho = e_1 + (2^4) f + (2^254) g_0 - let decomposition_check = { - let sum = e_1.clone() + f.clone() * two_pow_4 + g_0.clone() * two_pow_254; - sum - rho - }; - - // e1_f_prime = e_1 + (2^4)f + 2^140 - t_P - let e1_f_prime_check = e_1 + (f * two_pow_4) + two_pow_140 - t_p - e1_f_prime; - - // The rho_canonicity_checks are enforced if and only if `g_0` = 1. - // rho = e_1 (4 bits) || f (250 bits) || g_0 (1 bit) - let canonicity_checks = iter::empty() - .chain(Some(("g_0 = 1 => z13_f", z13_f))) - .chain(Some(("g_0 = 1 => z14_e1_f_prime", z14_e1_f_prime))) - .map(move |(name, poly)| (name, g_0.clone() * poly)); - - Constraints::with_selector( - q_notecommit_rho, - iter::empty() - .chain(Some(("decomposition", decomposition_check))) - .chain(Some(("e1_f_prime_check", e1_f_prime_check))) - .chain(canonicity_checks), - ) - }); - - Self { - q_notecommit_rho, - col_l, - col_m, - col_r, - col_z, - } - } - - #[allow(clippy::too_many_arguments)] - fn assign( - &self, - layouter: &mut impl Layouter, - rho: AssignedCell, - e_1: RangeConstrained>, - f: NoteCommitPiece, - g_0: AssignedCell, - e1_f_prime: AssignedCell, - z13_f: AssignedCell, - z14_e1_f_prime: AssignedCell, - ) -> Result<(), Error> { - layouter.assign_region( - || "NoteCommit input rho", - |mut region| { - rho.copy_advice(|| "rho", &mut region, self.col_l, 0)?; - - e_1.inner() - .copy_advice(|| "e_1", &mut region, self.col_m, 0)?; - g_0.copy_advice(|| "g_0", &mut region, self.col_m, 1)?; - - f.inner() - .cell_value() - .copy_advice(|| "f", &mut region, self.col_r, 0)?; - e1_f_prime.copy_advice(|| "e1_f_prime", &mut region, self.col_r, 1)?; - - z13_f.copy_advice(|| "z13_f", &mut region, self.col_z, 0)?; - z14_e1_f_prime.copy_advice(|| "z14_e1_f_prime", &mut region, self.col_z, 1)?; - - self.q_notecommit_rho.enable(&mut region, 0) - }, - ) - } -} - -/// | A_6 | A_7 | A_8 | A_9 | q_notecommit_psi | -/// ---------------------------------------------------------------- -/// | psi | g_1 | g_2 | z13_g | 1 | -/// | h_0 | h_1 | g1_g2_prime | z13_g1_g2_prime | 0 | -/// -/// -#[derive(Clone, Debug)] -struct PsiCanonicity { - q_notecommit_psi: Selector, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, -} - -impl PsiCanonicity { - #[allow(clippy::too_many_arguments)] - fn configure( - meta: &mut ConstraintSystem, - col_l: Column, - col_m: Column, - col_r: Column, - col_z: Column, - two_pow_9: pallas::Base, - two_pow_130: Expression, - two_pow_249: pallas::Base, - two_pow_254: pallas::Base, - t_p: Expression, - ) -> Self { - let q_notecommit_psi = meta.selector(); - - meta.create_gate("NoteCommit input psi", |meta| { - let q_notecommit_psi = meta.query_selector(q_notecommit_psi); - - let psi = meta.query_advice(col_l, Rotation::cur()); - let h_0 = meta.query_advice(col_l, Rotation::next()); - - let g_1 = meta.query_advice(col_m, Rotation::cur()); - let h_1 = meta.query_advice(col_m, Rotation::next()); - - let z1_g = meta.query_advice(col_r, Rotation::cur()); - let g_2 = z1_g; - let g1_g2_prime = meta.query_advice(col_r, Rotation::next()); - - let z13_g = meta.query_advice(col_z, Rotation::cur()); - let z13_g1_g2_prime = meta.query_advice(col_z, Rotation::next()); - - // psi = g_1 + (2^9) g_2 + (2^249) h_0 + (2^254) h_1 - let decomposition_check = { - let sum = g_1.clone() - + g_2.clone() * two_pow_9 - + h_0.clone() * two_pow_249 - + h_1.clone() * two_pow_254; - sum - psi - }; - - // g1_g2_prime = g_1 + (2^9)g_2 + 2^130 - t_P - let g1_g2_prime_check = g_1 + (g_2 * two_pow_9) + two_pow_130 - t_p - g1_g2_prime; - - // The psi_canonicity_checks are enforced if and only if `h_1` = 1. - // `psi` = `g_1 (9 bits) || g_2 (240 bits) || h_0 (5 bits) || h_1 (1 bit)` - let canonicity_checks = iter::empty() - .chain(Some(("h_1 = 1 => h_0", h_0))) - .chain(Some(("h_1 = 1 => z13_g", z13_g))) - .chain(Some(("h_1 = 1 => z13_g1_g2_prime", z13_g1_g2_prime))) - .map(move |(name, poly)| (name, h_1.clone() * poly)); - - Constraints::with_selector( - q_notecommit_psi, - iter::empty() - .chain(Some(("decomposition", decomposition_check))) - .chain(Some(("g1_g2_prime_check", g1_g2_prime_check))) - .chain(canonicity_checks), - ) - }); - - Self { - q_notecommit_psi, - col_l, - col_m, - col_r, - col_z, - } - } - - #[allow(clippy::too_many_arguments)] - fn assign( - &self, - layouter: &mut impl Layouter, - psi: AssignedCell, - g_1: RangeConstrained>, - z1_g: AssignedCell, - h_0: RangeConstrained>, - h_1: AssignedCell, - g1_g2_prime: AssignedCell, - z13_g: AssignedCell, - z13_g1_g2_prime: AssignedCell, - ) -> Result<(), Error> { - layouter.assign_region( - || "NoteCommit input psi", - |mut region| { - psi.copy_advice(|| "psi", &mut region, self.col_l, 0)?; - h_0.inner() - .copy_advice(|| "h_0", &mut region, self.col_l, 1)?; - - g_1.inner() - .copy_advice(|| "g_1", &mut region, self.col_m, 0)?; - h_1.copy_advice(|| "h_1", &mut region, self.col_m, 1)?; - - z1_g.copy_advice(|| "g_2 = z1_g", &mut region, self.col_r, 0)?; - g1_g2_prime.copy_advice(|| "g1_g2_prime", &mut region, self.col_r, 1)?; - - z13_g.copy_advice(|| "z13_g", &mut region, self.col_z, 0)?; - z13_g1_g2_prime.copy_advice(|| "z13_g1_g2_prime", &mut region, self.col_z, 1)?; - - self.q_notecommit_psi.enable(&mut region, 0) - }, - ) - } -} - -/// Check decomposition and canonicity of y-coordinates. -/// This is used for both y(g_d) and y(pk_d). -/// -/// y = LSB || k_0 || k_1 || k_2 || k_3 -/// = (bit 0) || (bits 1..=9) || (bits 10..=249) || (bits 250..=253) || (bit 254) -/// -/// These pieces are laid out in the following configuration: -/// | A_5 | A_6 | A_7 | A_8 | A_9 | q_y_canon | -/// --------------------------------------------------------- -/// | y | lsb | k_0 | k_2 | k_3 | 1 | -/// | j | z1_j| z13_j | j_prime | z13_j_prime | 0 | -/// where z1_j = k_1. -#[derive(Clone, Debug)] -struct YCanonicity { - q_y_canon: Selector, - advices: [Column; 10], -} - -impl YCanonicity { - #[allow(clippy::too_many_arguments)] - fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 10], - two: pallas::Base, - two_pow_10: pallas::Base, - two_pow_130: Expression, - two_pow_250: pallas::Base, - two_pow_254: pallas::Base, - t_p: Expression, - ) -> Self { - let q_y_canon = meta.selector(); - - meta.create_gate("y coordinate checks", |meta| { - let q_y_canon = meta.query_selector(q_y_canon); - let y = meta.query_advice(advices[5], Rotation::cur()); - // LSB has been boolean-constrained outside this gate. - let lsb = meta.query_advice(advices[6], Rotation::cur()); - // k_0 has been constrained to 9 bits outside this gate. - let k_0 = meta.query_advice(advices[7], Rotation::cur()); - // k_1 = z1_j (witnessed in the next rotation). - // k_2 has been constrained to 4 bits outside this gate. - let k_2 = meta.query_advice(advices[8], Rotation::cur()); - // This gate constrains k_3 to be boolean. - let k_3 = meta.query_advice(advices[9], Rotation::cur()); - - // j = LSB + (2)k_0 + (2^10)k_1 - let j = meta.query_advice(advices[5], Rotation::next()); - let z1_j = meta.query_advice(advices[6], Rotation::next()); - let z13_j = meta.query_advice(advices[7], Rotation::next()); - - // j_prime = j + 2^130 - t_P - let j_prime = meta.query_advice(advices[8], Rotation::next()); - let z13_j_prime = meta.query_advice(advices[9], Rotation::next()); - - // Decomposition checks - // https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial - let decomposition_checks = { - // Check that k_3 is boolean - let k3_check = bool_check(k_3.clone()); - // Check that j = LSB + (2)k_0 + (2^10)k_1 - let k_1 = z1_j; - let j_check = j.clone() - (lsb + k_0 * two + k_1 * two_pow_10); - // Check that y = j + (2^250)k_2 + (2^254)k_3 - let y_check = - y - (j.clone() + k_2.clone() * two_pow_250 + k_3.clone() * two_pow_254); - // Check that j_prime = j + 2^130 - t_P - let j_prime_check = j + two_pow_130 - t_p - j_prime; - - iter::empty() - .chain(Some(("k3_check", k3_check))) - .chain(Some(("j_check", j_check))) - .chain(Some(("y_check", y_check))) - .chain(Some(("j_prime_check", j_prime_check))) - }; - - // Canonicity checks. These are enforced if and only if k_3 = 1. - // https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial - let canonicity_checks = { - iter::empty() - .chain(Some(("k_3 = 1 => k_2 = 0", k_2))) - .chain(Some(("k_3 = 1 => z13_j = 0", z13_j))) - .chain(Some(("k_3 = 1 => z13_j_prime = 0", z13_j_prime))) - .map(move |(name, poly)| (name, k_3.clone() * poly)) - }; - - Constraints::with_selector(q_y_canon, decomposition_checks.chain(canonicity_checks)) - }); - - Self { q_y_canon, advices } - } - - #[allow(clippy::too_many_arguments)] - fn assign( - &self, - layouter: &mut impl Layouter, - y: AssignedCell, - lsb: RangeConstrained>, - k_0: RangeConstrained>, - k_2: RangeConstrained>, - k_3: RangeConstrained>, - j: AssignedCell, - z1_j: AssignedCell, - z13_j: AssignedCell, - j_prime: AssignedCell, - z13_j_prime: AssignedCell, - ) -> Result>, Error> - { - layouter.assign_region( - || "y canonicity", - |mut region| { - self.q_y_canon.enable(&mut region, 0)?; - - // Offset 0 - let lsb = { - let offset = 0; - - // Copy y. - y.copy_advice(|| "copy y", &mut region, self.advices[5], offset)?; - // Witness LSB. - let lsb = region - .assign_advice(|| "witness LSB", self.advices[6], offset, || *lsb.inner()) - // SAFETY: This is sound because we just assigned this cell from a - // range-constrained value. - .map(|cell| RangeConstrained::unsound_unchecked(cell, lsb.num_bits()))?; - // Witness k_0. - k_0.inner() - .copy_advice(|| "copy k_0", &mut region, self.advices[7], offset)?; - // Copy k_2. - k_2.inner() - .copy_advice(|| "copy k_2", &mut region, self.advices[8], offset)?; - // Witness k_3. - region.assign_advice( - || "witness k_3", - self.advices[9], - offset, - || *k_3.inner(), - )?; - - lsb - }; - - // Offset 1 - { - let offset = 1; - - // Copy j. - j.copy_advice(|| "copy j", &mut region, self.advices[5], offset)?; - // Copy z1_j. - z1_j.copy_advice(|| "copy z1_j", &mut region, self.advices[6], offset)?; - // Copy z13_j. - z13_j.copy_advice(|| "copy z13_j", &mut region, self.advices[7], offset)?; - // Copy j_prime. - j_prime.copy_advice(|| "copy j_prime", &mut region, self.advices[8], offset)?; - // Copy z13_j_prime. - z13_j_prime.copy_advice( - || "copy z13_j_prime", - &mut region, - self.advices[9], - offset, - )?; - } - - Ok(lsb) - }, - ) - } -} - -#[allow(non_snake_case)] -#[derive(Clone, Debug)] -pub struct NoteCommitConfig { - b: DecomposeB, - d: DecomposeD, - e: DecomposeE, - g: DecomposeG, - h: DecomposeH, - g_d: GdCanonicity, - pk_d: PkdCanonicity, - value: ValueCanonicity, - rho: RhoCanonicity, - psi: PsiCanonicity, - y_canon: YCanonicity, - advices: [Column; 10], - sinsemilla_config: - SinsemillaConfig, -} - -#[derive(Clone, Debug)] -pub struct NoteCommitChip { - config: NoteCommitConfig, -} - -impl NoteCommitChip { - #[allow(non_snake_case)] - #[allow(clippy::many_single_char_names)] - pub(in crate::circuit) fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 10], - sinsemilla_config: SinsemillaConfig< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >, - ) -> NoteCommitConfig { - // Useful constants - let two = pallas::Base::from(2); - let two_pow_2 = pallas::Base::from(1 << 2); - let two_pow_4 = two_pow_2.square(); - let two_pow_5 = two_pow_4 * two; - let two_pow_6 = two_pow_5 * two; - let two_pow_8 = two_pow_4.square(); - let two_pow_9 = two_pow_8 * two; - let two_pow_10 = two_pow_9 * two; - let two_pow_58 = pallas::Base::from(1 << 58); - let two_pow_130 = Expression::Constant(pallas::Base::from_u128(1 << 65).square()); - let two_pow_140 = Expression::Constant(pallas::Base::from_u128(1 << 70).square()); - let two_pow_249 = pallas::Base::from_u128(1 << 124).square() * two; - let two_pow_250 = two_pow_249 * two; - let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); - - let t_p = Expression::Constant(pallas::Base::from_u128(T_P)); - - // Columns used for MessagePiece and message input gates. - let col_l = advices[6]; - let col_m = advices[7]; - let col_r = advices[8]; - let col_z = advices[9]; - - let b = DecomposeB::configure(meta, col_l, col_m, col_r, two_pow_4, two_pow_5, two_pow_6); - let d = DecomposeD::configure(meta, col_l, col_m, col_r, two, two_pow_2, two_pow_10); - let e = DecomposeE::configure(meta, col_l, col_m, col_r, two_pow_6); - let g = DecomposeG::configure(meta, col_l, col_m, two, two_pow_10); - let h = DecomposeH::configure(meta, col_l, col_m, col_r, two_pow_5); - - let g_d = GdCanonicity::configure( - meta, - col_l, - col_m, - col_r, - col_z, - two_pow_130.clone(), - two_pow_250, - two_pow_254, - t_p.clone(), - ); - - let pk_d = PkdCanonicity::configure( - meta, - col_l, - col_m, - col_r, - col_z, - two_pow_4, - two_pow_140.clone(), - two_pow_254, - t_p.clone(), - ); - - let value = - ValueCanonicity::configure(meta, col_l, col_m, col_r, col_z, two_pow_8, two_pow_58); - - let rho = RhoCanonicity::configure( - meta, - col_l, - col_m, - col_r, - col_z, - two_pow_4, - two_pow_140, - two_pow_254, - t_p.clone(), - ); - - let psi = PsiCanonicity::configure( - meta, - col_l, - col_m, - col_r, - col_z, - two_pow_9, - two_pow_130.clone(), - two_pow_249, - two_pow_254, - t_p.clone(), - ); - - let y_canon = YCanonicity::configure( - meta, - advices, - two, - two_pow_10, - two_pow_130, - two_pow_250, - two_pow_254, - t_p, - ); - - NoteCommitConfig { - b, - d, - e, - g, - h, - g_d, - pk_d, - value, - rho, - psi, - y_canon, - advices, - sinsemilla_config, - } - } - - pub(in crate::circuit) fn construct(config: NoteCommitConfig) -> Self { - Self { config } - } -} - -pub(in crate::circuit) mod gadgets { - use halo2_proofs::circuit::{Chip, Value}; - - use super::*; - - #[allow(clippy::many_single_char_names)] - #[allow(clippy::type_complexity)] - #[allow(clippy::too_many_arguments)] - pub(in crate::circuit) fn note_commit( - mut layouter: impl Layouter, - chip: SinsemillaChip, - ecc_chip: EccChip, - note_commit_chip: NoteCommitChip, - g_d: &NonIdentityEccPoint, - pk_d: &NonIdentityEccPoint, - value: AssignedCell, - rho: AssignedCell, - psi: AssignedCell, - rcm: ScalarFixed>, - ) -> Result>, Error> { - let lookup_config = chip.config().lookup_config(); - - // `a` = bits 0..=249 of `x(g_d)` - let a = MessagePiece::from_subpieces( - chip.clone(), - layouter.namespace(|| "a"), - [RangeConstrained::bitrange_of(g_d.x().value(), 0..250)], - )?; - - // b = b_0 || b_1 || b_2 || b_3 - // = (bits 250..=253 of x(g_d)) || (bit 254 of x(g_d)) || (ỹ bit of g_d) || (bits 0..=3 of pk★_d) - let (b, b_0, b_1, b_2, b_3) = - DecomposeB::decompose(&lookup_config, chip.clone(), &mut layouter, g_d, pk_d)?; - - // c = bits 4..=253 of pk★_d - let c = MessagePiece::from_subpieces( - chip.clone(), - layouter.namespace(|| "c"), - [RangeConstrained::bitrange_of(pk_d.x().value(), 4..254)], - )?; - - // d = d_0 || d_1 || d_2 || d_3 - // = (bit 254 of x(pk_d)) || (ỹ bit of pk_d) || (bits 0..=7 of v) || (bits 8..=57 of v) - let (d, d_0, d_1, d_2) = - DecomposeD::decompose(&lookup_config, chip.clone(), &mut layouter, pk_d, &value)?; - - // e = e_0 || e_1 = (bits 58..=63 of v) || (bits 0..=3 of rho) - let (e, e_0, e_1) = - DecomposeE::decompose(&lookup_config, chip.clone(), &mut layouter, &value, &rho)?; - - // f = bits 4..=253 inclusive of rho - let f = MessagePiece::from_subpieces( - chip.clone(), - layouter.namespace(|| "f"), - [RangeConstrained::bitrange_of(rho.value(), 4..254)], - )?; - - // g = g_0 || g_1 || g_2 - // = (bit 254 of rho) || (bits 0..=8 of psi) || (bits 9..=248 of psi) - let (g, g_0, g_1) = - DecomposeG::decompose(&lookup_config, chip.clone(), &mut layouter, &rho, &psi)?; - - // h = h_0 || h_1 || h_2 - // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits - let (h, h_0, h_1) = - DecomposeH::decompose(&lookup_config, chip.clone(), &mut layouter, &psi)?; - - // Check decomposition of `y(g_d)`. - let b_2 = y_canonicity( - &lookup_config, - ¬e_commit_chip.config.y_canon, - layouter.namespace(|| "y(g_d) decomposition"), - g_d.y(), - b_2, - )?; - // Check decomposition of `y(pk_d)`. - let d_1 = y_canonicity( - &lookup_config, - ¬e_commit_chip.config.y_canon, - layouter.namespace(|| "y(pk_d) decomposition"), - pk_d.y(), - d_1, - )?; - - // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) - // - // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition - // constraints allows ⊥ to occur, and then during synthesis it detects these edge - // cases and raises an error (aborting proof creation). - // - // https://p.z.cash/ZKS:action-cm-old-integrity?partial - // https://p.z.cash/ZKS:action-cmx-new-integrity?partial - let (cm, zs) = { - let message = Message::from_pieces( - chip.clone(), - vec![ - a.clone(), - b.clone(), - c.clone(), - d.clone(), - e.clone(), - f.clone(), - g.clone(), - h.clone(), - ], - ); - let domain = CommitDomain::new(chip, ecc_chip, &OrchardCommitDomains::NoteCommit); - domain.commit( - layouter.namespace(|| "Process NoteCommit inputs"), - message, - rcm, - )? - }; - - // `CommitDomain::commit` returns the running sum for each `MessagePiece`. Grab - // the outputs that we will need for canonicity checks. - let z13_a = zs[0][13].clone(); - let z13_c = zs[2][13].clone(); - let z1_d = zs[3][1].clone(); - let z13_f = zs[5][13].clone(); - let z1_g = zs[6][1].clone(); - let g_2 = z1_g.clone(); - let z13_g = zs[6][13].clone(); - - // Witness and constrain the bounds we need to ensure canonicity. - let (a_prime, z13_a_prime) = canon_bitshift_130( - &lookup_config, - layouter.namespace(|| "x(g_d) canonicity"), - a.inner().cell_value(), - )?; - - let (b3_c_prime, z14_b3_c_prime) = pkd_x_canonicity( - &lookup_config, - layouter.namespace(|| "x(pk_d) canonicity"), - b_3.clone(), - c.inner().cell_value(), - )?; - - let (e1_f_prime, z14_e1_f_prime) = rho_canonicity( - &lookup_config, - layouter.namespace(|| "rho canonicity"), - e_1.clone(), - f.inner().cell_value(), - )?; - - let (g1_g2_prime, z13_g1_g2_prime) = psi_canonicity( - &lookup_config, - layouter.namespace(|| "psi canonicity"), - g_1.clone(), - g_2, - )?; - - // Finally, assign values to all of the NoteCommit regions. - let cfg = note_commit_chip.config; - - let b_1 = cfg - .b - .assign(&mut layouter, b, b_0.clone(), b_1, b_2, b_3.clone())?; - - let d_0 = cfg - .d - .assign(&mut layouter, d, d_0, d_1, d_2.clone(), z1_d.clone())?; - - cfg.e.assign(&mut layouter, e, e_0.clone(), e_1.clone())?; - - let g_0 = cfg - .g - .assign(&mut layouter, g, g_0, g_1.clone(), z1_g.clone())?; - - let h_1 = cfg.h.assign(&mut layouter, h, h_0.clone(), h_1)?; - - cfg.g_d - .assign(&mut layouter, g_d, a, b_0, b_1, a_prime, z13_a, z13_a_prime)?; - - cfg.pk_d.assign( - &mut layouter, - pk_d, - b_3, - c, - d_0, - b3_c_prime, - z13_c, - z14_b3_c_prime, - )?; - - cfg.value.assign(&mut layouter, value, d_2, z1_d, e_0)?; - - cfg.rho.assign( - &mut layouter, - rho, - e_1, - f, - g_0, - e1_f_prime, - z13_f, - z14_e1_f_prime, - )?; - - cfg.psi.assign( - &mut layouter, - psi, - g_1, - z1_g, - h_0, - h_1, - g1_g2_prime, - z13_g, - z13_g1_g2_prime, - )?; - - Ok(cm) - } - - /// A canonicity check helper used in checking x(g_d), y(g_d), and y(pk_d). - /// - /// Specifications: - /// - [`g_d` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-g_d?partial) - /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) - fn canon_bitshift_130( - lookup_config: &PallasLookupRangeCheckConfig, - mut layouter: impl Layouter, - a: AssignedCell, - ) -> Result { - // element = `a (250 bits) || b_0 (4 bits) || b_1 (1 bit)` - // - b_1 = 1 => b_0 = 0 - // - b_1 = 1 => a < t_P - // - 0 ≤ a < 2^130 (z_13 of SinsemillaHash(a)) - // - 0 ≤ a + 2^130 - t_P < 2^130 (thirteen 10-bit lookups) - - // Decompose the low 130 bits of a_prime = a + 2^130 - t_P, and output - // the running sum at the end of it. If a_prime < 2^130, the running sum - // will be 0. - let a_prime = { - let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); - let t_p = Value::known(pallas::Base::from_u128(T_P)); - a.value() + two_pow_130 - t_p - }; - let zs = lookup_config.witness_check( - layouter.namespace(|| "Decompose low 130 bits of (a + 2^130 - t_P)"), - a_prime, - 13, - false, - )?; - let a_prime = zs[0].clone(); - assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z_13] - - Ok((a_prime, zs[13].clone())) - } - - /// Check canonicity of `x(pk_d)` encoding. - /// - /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-pk_d?partial). - fn pkd_x_canonicity( - lookup_config: &PallasLookupRangeCheckConfig, - mut layouter: impl Layouter, - b_3: RangeConstrained>, - c: AssignedCell, - ) -> Result { - // `x(pk_d)` = `b_3 (4 bits) || c (250 bits) || d_0 (1 bit)` - // - d_0 = 1 => b_3 + 2^4 c < t_P - // - 0 ≤ b_3 + 2^4 c < 2^134 - // - b_3 is part of the Sinsemilla message piece - // b = b_0 (4 bits) || b_1 (1 bit) || b_2 (1 bit) || b_3 (4 bits) - // - b_3 is individually constrained to be 4 bits. - // - z_13 of SinsemillaHash(c) == 0 constrains bits 4..=253 of pkd_x - // to 130 bits. z13_c is directly checked in the gate. - // - 0 ≤ b_3 + 2^4 c + 2^140 - t_P < 2^140 (14 ten-bit lookups) - - // Decompose the low 140 bits of b3_c_prime = b_3 + 2^4 c + 2^140 - t_P, - // and output the running sum at the end of it. - // If b3_c_prime < 2^140, the running sum will be 0. - let b3_c_prime = { - let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4)); - let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); - let t_p = Value::known(pallas::Base::from_u128(T_P)); - b_3.inner().value() + (two_pow_4 * c.value()) + two_pow_140 - t_p - }; - - let zs = lookup_config.witness_check( - layouter.namespace(|| "Decompose low 140 bits of (b_3 + 2^4 c + 2^140 - t_P)"), - b3_c_prime, - 14, - false, - )?; - let b3_c_prime = zs[0].clone(); - assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z_13, z_14] - - Ok((b3_c_prime, zs[14].clone())) - } - - /// Check canonicity of `rho` encoding. - /// - /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-rho?partial). - fn rho_canonicity( - lookup_config: &PallasLookupRangeCheckConfig, - mut layouter: impl Layouter, - e_1: RangeConstrained>, - f: AssignedCell, - ) -> Result { - // `rho` = `e_1 (4 bits) || f (250 bits) || g_0 (1 bit)` - // - g_0 = 1 => e_1 + 2^4 f < t_P - // - 0 ≤ e_1 + 2^4 f < 2^134 - // - e_1 is part of the Sinsemilla message piece - // e = e_0 (56 bits) || e_1 (4 bits) - // - e_1 is individually constrained to be 4 bits. - // - z_13 of SinsemillaHash(f) == 0 constrains bits 4..=253 of rho - // to 130 bits. z13_f == 0 is directly checked in the gate. - // - 0 ≤ e_1 + 2^4 f + 2^140 - t_P < 2^140 (14 ten-bit lookups) - - let e1_f_prime = { - let two_pow_4 = Value::known(pallas::Base::from(1u64 << 4)); - let two_pow_140 = Value::known(pallas::Base::from_u128(1u128 << 70).square()); - let t_p = Value::known(pallas::Base::from_u128(T_P)); - e_1.inner().value() + (two_pow_4 * f.value()) + two_pow_140 - t_p - }; - - // Decompose the low 140 bits of e1_f_prime = e_1 + 2^4 f + 2^140 - t_P, - // and output the running sum at the end of it. - // If e1_f_prime < 2^140, the running sum will be 0. - let zs = lookup_config.witness_check( - layouter.namespace(|| "Decompose low 140 bits of (e_1 + 2^4 f + 2^140 - t_P)"), - e1_f_prime, - 14, - false, - )?; - let e1_f_prime = zs[0].clone(); - assert_eq!(zs.len(), 15); // [z_0, z_1, ..., z_13, z_14] - - Ok((e1_f_prime, zs[14].clone())) - } - - /// Check canonicity of `psi` encoding. - /// - /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-psi?partial). - fn psi_canonicity( - lookup_config: &PallasLookupRangeCheckConfig, - mut layouter: impl Layouter, - g_1: RangeConstrained>, - g_2: AssignedCell, - ) -> Result { - // `psi` = `g_1 (9 bits) || g_2 (240 bits) || h_0 (5 bits) || h_1 (1 bit)` - // - h_1 = 1 => (h_0 = 0) ∧ (g_1 + 2^9 g_2 < t_P) - // - 0 ≤ g_1 + 2^9 g_2 < 2^130 - // - g_1 is individually constrained to be 9 bits - // - z_13 of SinsemillaHash(g) == 0 constrains bits 0..=248 of psi - // to 130 bits. z13_g == 0 is directly checked in the gate. - // - 0 ≤ g_1 + (2^9)g_2 + 2^130 - t_P < 2^130 (13 ten-bit lookups) - - // Decompose the low 130 bits of g1_g2_prime = g_1 + (2^9)g_2 + 2^130 - t_P, - // and output the running sum at the end of it. - // If g1_g2_prime < 2^130, the running sum will be 0. - let g1_g2_prime = { - let two_pow_9 = Value::known(pallas::Base::from(1u64 << 9)); - let two_pow_130 = Value::known(pallas::Base::from_u128(1u128 << 65).square()); - let t_p = Value::known(pallas::Base::from_u128(T_P)); - g_1.inner().value() + (two_pow_9 * g_2.value()) + two_pow_130 - t_p - }; - - let zs = lookup_config.witness_check( - layouter.namespace(|| "Decompose low 130 bits of (g_1 + (2^9)g_2 + 2^130 - t_P)"), - g1_g2_prime, - 13, - false, - )?; - let g1_g2_prime = zs[0].clone(); - assert_eq!(zs.len(), 14); // [z_0, z_1, ..., z_13] - - Ok((g1_g2_prime, zs[13].clone())) - } - - /// Check canonicity of y-coordinate given its LSB as a value. - /// Also, witness the LSB and return the witnessed cell. - /// - /// Specifications: - /// - [`y` decomposition](https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial) - /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) - fn y_canonicity( - lookup_config: &PallasLookupRangeCheckConfig, - y_canon: &YCanonicity, - mut layouter: impl Layouter, - y: AssignedCell, - lsb: RangeConstrained>, - ) -> Result>, Error> - { - // Decompose the field element - // y = LSB || k_0 || k_1 || k_2 || k_3 - // = (bit 0) || (bits 1..=9) || (bits 10..=249) || (bits 250..=253) || (bit 254) - - // Range-constrain k_0 to be 9 bits. - let k_0 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "k_0"), - y.value(), - 1..10, - )?; - - // k_1 will be constrained by the decomposition of j. - let k_1 = RangeConstrained::bitrange_of(y.value(), 10..250); - - // Range-constrain k_2 to be 4 bits. - let k_2 = RangeConstrained::witness_short( - lookup_config, - layouter.namespace(|| "k_2"), - y.value(), - 250..254, - )?; - - // k_3 will be boolean-constrained in the gate. - let k_3 = RangeConstrained::bitrange_of(y.value(), 254..255); - - // Decompose j = LSB + (2)k_0 + (2^10)k_1 using 25 ten-bit lookups. - let (j, z1_j, z13_j) = { - let j = { - let two = Value::known(pallas::Base::from(2)); - let two_pow_10 = Value::known(pallas::Base::from(1 << 10)); - lsb.inner().value() + two * k_0.inner().value() + two_pow_10 * k_1.inner().value() - }; - let zs = lookup_config.witness_check( - layouter.namespace(|| "Decompose j = LSB + (2)k_0 + (2^10)k_1"), - j, - 25, - true, - )?; - (zs[0].clone(), zs[1].clone(), zs[13].clone()) - }; - - // Decompose j_prime = j + 2^130 - t_P using 13 ten-bit lookups. - // We can reuse the canon_bitshift_130 logic here. - let (j_prime, z13_j_prime) = canon_bitshift_130( - lookup_config, - layouter.namespace(|| "j_prime = j + 2^130 - t_P"), - j.clone(), - )?; - - y_canon.assign( - &mut layouter, - y, - lsb, - k_0, - k_2, - k_3, - j, - z1_j, - z13_j, - j_prime, - z13_j_prime, - ) - } -} - -#[cfg(test)] -mod tests { - use core::iter; - - use super::NoteCommitConfig; - use crate::{ - circuit::circuit_vanilla::{ - gadget::assign_free_advice, - note_commit::{gadgets, NoteCommitChip}, - }, - constants::{ - fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, - OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q, - }, - value::NoteValue, - }; - use halo2_gadgets::{ - ecc::{ - chip::{EccChip, EccConfig}, - NonIdentityPoint, ScalarFixed, - }, - sinsemilla::chip::SinsemillaChip, - sinsemilla::primitives::CommitDomain, - utilities::lookup_range_check::{LookupRangeCheck, LookupRangeCheckConfig}, - }; - - use ff::{Field, PrimeField, PrimeFieldBits}; - use group::Curve; - use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use pasta_curves::{arithmetic::CurveAffine, pallas}; - - use rand::{rngs::OsRng, RngCore}; - - #[test] - fn note_commit() { - #[derive(Default)] - struct MyCircuit { - gd_x: Value, - gd_y_lsb: Value, - pkd_x: Value, - pkd_y_lsb: Value, - rho: Value, - psi: Value, - } - - impl Circuit for MyCircuit { - type Config = (NoteCommitConfig, EccConfig); - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - // Shared fixed column for loading constants. - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let table_idx = meta.lookup_table_column(); - let lookup = ( - table_idx, - meta.lookup_table_column(), - meta.lookup_table_column(), - ); - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - - let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); - let sinsemilla_config = SinsemillaChip::< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >::configure( - meta, - advices[..5].try_into().unwrap(), - advices[2], - lagrange_coeffs[0], - lookup, - range_check, - false, - ); - let note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config); - - let ecc_config = EccChip::::configure( - meta, - advices, - lagrange_coeffs, - range_check, - ); - - (note_commit_config, ecc_config) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let (note_commit_config, ecc_config) = config; - - // Load the Sinsemilla generator lookup table used by the whole circuit. - SinsemillaChip::< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - >::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?; - - // Construct a Sinsemilla chip - let sinsemilla_chip = - SinsemillaChip::construct(note_commit_config.sinsemilla_config.clone()); - - // Construct an ECC chip - let ecc_chip = EccChip::construct(ecc_config); - - // Construct a NoteCommit chip - let note_commit_chip = NoteCommitChip::construct(note_commit_config.clone()); - - // Witness g_d - let g_d = { - let g_d = self.gd_x.zip(self.gd_y_lsb).map(|(x, y_lsb)| { - // Calculate y = (x^3 + 5).sqrt() - let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); - if bool::from(y.is_odd() ^ y_lsb.is_odd()) { - y = -y; - } - pallas::Affine::from_xy(x, y).unwrap() - }); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness g_d"), - g_d, - )? - }; - - // Witness pk_d - let pk_d = { - let pk_d = self.pkd_x.zip(self.pkd_y_lsb).map(|(x, y_lsb)| { - // Calculate y = (x^3 + 5).sqrt() - let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); - if bool::from(y.is_odd() ^ y_lsb.is_odd()) { - y = -y; - } - pallas::Affine::from_xy(x, y).unwrap() - }); - - NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "witness pk_d"), - pk_d, - )? - }; - - // Witness a random non-negative u64 note value - // A note value cannot be negative. - let value = { - let mut rng = OsRng; - NoteValue::from_raw(rng.next_u64()) - }; - let value_var = { - assign_free_advice( - layouter.namespace(|| "witness value"), - note_commit_config.advices[0], - Value::known(value), - )? - }; - - // Witness rho - let rho = assign_free_advice( - layouter.namespace(|| "witness rho"), - note_commit_config.advices[0], - self.rho, - )?; - - // Witness psi - let psi = assign_free_advice( - layouter.namespace(|| "witness psi"), - note_commit_config.advices[0], - self.psi, - )?; - - let rcm = pallas::Scalar::random(OsRng); - let rcm_gadget = ScalarFixed::new( - ecc_chip.clone(), - layouter.namespace(|| "rcm"), - Value::known(rcm), - )?; - - let cm = gadgets::note_commit( - layouter.namespace(|| "Hash NoteCommit pieces"), - sinsemilla_chip, - ecc_chip.clone(), - note_commit_chip, - g_d.inner(), - pk_d.inner(), - value_var, - rho, - psi, - rcm_gadget, - )?; - let expected_cm = { - let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); - // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi - let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one(); - let point = self - .gd_x - .zip(self.gd_y_lsb) - .zip(self.pkd_x.zip(self.pkd_y_lsb)) - .zip(self.rho.zip(self.psi)) - .map(|(((gd_x, gd_y_lsb), (pkd_x, pkd_y_lsb)), (rho, psi))| { - domain - .commit( - iter::empty() - .chain( - gd_x.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ) - .chain(Some(lsb(gd_y_lsb))) - .chain( - pkd_x - .to_le_bits() - .iter() - .by_vals() - .take(L_ORCHARD_BASE), - ) - .chain(Some(lsb(pkd_y_lsb))) - .chain(value.to_le_bits().iter().by_vals().take(L_VALUE)) - .chain( - rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ) - .chain( - psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), - ), - &rcm, - ) - .unwrap() - .to_affine() - }); - NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)? - }; - cm.constrain_equal(layouter.namespace(|| "cm == expected cm"), &expected_cm) - } - } - - let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); - // Test different values of `ak`, `nk` - let circuits = [ - // `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points) - // `rho` = 0, `psi` = 0 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::one()), - rho: Value::known(pallas::Base::zero()), - psi: Value::known(pallas::Base::zero()), - }, - // `rho` = T_Q - 1, `psi` = T_Q - 1 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::zero()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), - rho: Value::known(pallas::Base::from_u128(T_Q - 1)), - psi: Value::known(pallas::Base::from_u128(T_Q - 1)), - }, - // `rho` = T_Q, `psi` = T_Q - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), - rho: Value::known(pallas::Base::from_u128(T_Q)), - psi: Value::known(pallas::Base::from_u128(T_Q)), - }, - // `rho` = 2^127 - 1, `psi` = 2^127 - 1 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::zero()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::one()), - rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)), - psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)), - }, - // `rho` = 2^127, `psi` = 2^127 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::zero()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), - rho: Value::known(pallas::Base::from_u128(1 << 127)), - psi: Value::known(pallas::Base::from_u128(1 << 127)), - }, - // `rho` = 2^254 - 1, `psi` = 2^254 - 1 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::one()), - rho: Value::known(two_pow_254 - pallas::Base::one()), - psi: Value::known(two_pow_254 - pallas::Base::one()), - }, - // `rho` = 2^254, `psi` = 2^254 - MyCircuit { - gd_x: Value::known(-pallas::Base::one()), - gd_y_lsb: Value::known(pallas::Base::one()), - pkd_x: Value::known(-pallas::Base::one()), - pkd_y_lsb: Value::known(pallas::Base::zero()), - rho: Value::known(two_pow_254), - psi: Value::known(two_pow_254), - }, - ]; - - for circuit in circuits.iter() { - let prover = MockProver::::run(11, circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } -} diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs index 0fc7cf6db..f4985137c 100644 --- a/src/circuit/circuit_zsa.rs +++ b/src/circuit/circuit_zsa.rs @@ -9,100 +9,47 @@ use group::Curve; use pasta_curves::{arithmetic::CurveAffine, pallas}; use halo2_gadgets::{ - ecc::{ - chip::{EccChip, EccConfig}, - FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar, - }, - poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}, + ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, + poseidon::{primitives as poseidon, Pow5Chip as PoseidonChip}, sinsemilla::{ - chip::{SinsemillaChip, SinsemillaConfig}, - merkle::{ - chip::{MerkleChip, MerkleConfig}, - MerklePath, - }, + chip::SinsemillaChip, + merkle::{chip::MerkleChip, MerklePath}, }, utilities::{ bool_check, - cond_swap::{CondSwapChip, CondSwapConfig}, - lookup_range_check::{LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig}, + lookup_range_check::{LookupRangeCheck4_5BConfig, PallasLookupRangeCheck4_5BConfig}, }, }; use halo2_proofs::{ circuit::{Layouter, Value}, - plonk::{self, Advice, Column, Constraints, Expression, Instance as InstanceColumn, Selector}, + plonk::{self, Constraints, Expression}, poly::Rotation, }; -use crate::{ - constants::OrchardFixedBasesFull, - constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, - note::AssetBase, - orchard_flavor::OrchardZSA, -}; - use super::{ - commit_ivk::{ - self, {CommitIvkChip, CommitIvkConfig}, - }, - gadget::{ - add_chip::{self, AddChip, AddConfig}, - AddInstruction, - }, + commit_ivk::CommitIvkChip, + derive_nullifier::ZsaNullifierParams, + gadget::{add_chip::AddChip, assign_free_advice, assign_is_native_asset, assign_split_flag}, + note_commit::NoteCommitChip, + value_commit_orchard::ZsaValueCommitParams, Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, ENABLE_ZSA, NF_OLD, RK_X, RK_Y, }; - -use self::{ - gadget::{assign_free_advice, assign_is_native_asset, assign_split_flag}, - note_commit::{NoteCommitChip, NoteCommitConfig}, +use crate::{ + circuit::commit_ivk::gadgets::commit_ivk, + circuit::derive_nullifier::gadgets::derive_nullifier, + circuit::note_commit::{gadgets::note_commit, ZsaNoteCommitParams}, + circuit::value_commit_orchard::gadgets::value_commit_orchard, + circuit::Config, + constants::OrchardFixedBasesFull, + constants::{OrchardFixedBases, OrchardHashDomains}, + note::AssetBase, + orchard_flavor::OrchardZSA, }; -pub mod gadget; -mod note_commit; -mod value_commit_orchard; - -/// Configuration needed to use the Orchard Action circuit. -#[derive(Clone, Debug)] -pub struct Config { - primary: Column, - q_orchard: Selector, - advices: [Column; 10], - add_config: AddConfig, - ecc_config: EccConfig, - poseidon_config: PoseidonConfig, - merkle_config_1: MerkleConfig< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, - merkle_config_2: MerkleConfig< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, - sinsemilla_config_1: SinsemillaConfig< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, - sinsemilla_config_2: SinsemillaConfig< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, - commit_ivk_config: CommitIvkConfig, - old_note_commit_config: NoteCommitConfig, - new_note_commit_config: NoteCommitConfig, - cond_swap_config: CondSwapConfig, -} - impl OrchardCircuit for OrchardZSA { - type Config = Config; + type Config = Config; fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { // Advice columns used in the Orchard circuit. @@ -277,7 +224,7 @@ impl OrchardCircuit for OrchardZSA { // We have a lot of free space in the right-most advice columns; use one of them // for all of our range checks. - let range_check = LookupRangeCheck45BConfig::configure_with_tag( + let range_check = LookupRangeCheck4_5BConfig::configure_with_tag( meta, advices[9], table_idx, @@ -286,7 +233,7 @@ impl OrchardCircuit for OrchardZSA { // Configuration for curve point operations. // This uses 10 advice columns and spans the whole circuit. - let ecc_config = EccChip::::configure( + let ecc_config = EccChip::::configure( meta, advices, lagrange_coeffs, @@ -349,14 +296,12 @@ impl OrchardCircuit for OrchardZSA { // Configuration to handle decomposition and canonicity checking // for NoteCommit_old. let old_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone()); + NoteCommitChip::configure(meta, advices, sinsemilla_config_1.clone(), true); // Configuration to handle decomposition and canonicity checking // for NoteCommit_new. let new_note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone()); - - let cond_swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); + NoteCommitChip::configure(meta, advices, sinsemilla_config_2.clone(), true); Config { primary, @@ -372,7 +317,6 @@ impl OrchardCircuit for OrchardZSA { commit_ivk_config, old_note_commit_config, new_note_commit_config, - cond_swap_config, } } @@ -545,13 +489,15 @@ impl OrchardCircuit for OrchardZSA { circuit.rcv.as_ref().map(|rcv| rcv.inner()), )?; - let cv_net = gadget::value_commit_orchard( + let cv_net = value_commit_orchard( layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net_magnitude_sign)"), - config.sinsemilla_chip_1(), ecc_chip.clone(), v_net_magnitude_sign.clone(), rcv, - asset.clone(), + Some(ZsaValueCommitParams { + sinsemilla_chip: config.sinsemilla_chip_1(), + asset: asset.clone(), + }), )?; // Constrain cv_net to equal public input @@ -564,17 +510,19 @@ impl OrchardCircuit for OrchardZSA { // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). let nf_old = { - let nf_old = gadget::derive_nullifier( - layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), + let nf_old = derive_nullifier( + &mut layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), config.poseidon_chip(), config.add_chip(), ecc_chip.clone(), - config.cond_swap_chip(), rho_old.clone(), &psi_nf, &cm_old, nk.clone(), - split_flag.clone(), + Some(ZsaNullifierParams { + cond_swap_chip: config.cond_swap_chip(), + split_flag: split_flag.clone(), + }), )?; // Constrain nf_old to equal public input @@ -616,7 +564,7 @@ impl OrchardCircuit for OrchardZSA { circuit.rivk.map(|rivk| rivk.inner()), )?; - gadget::commit_ivk( + commit_ivk( config.sinsemilla_chip_1(), ecc_chip.clone(), config.commit_ivk_chip(), @@ -663,22 +611,24 @@ impl OrchardCircuit for OrchardZSA { )?; // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let derived_cm_old = gadget::note_commit( + let derived_cm_old = note_commit( layouter.namespace(|| { "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" }), config.sinsemilla_chip_1(), config.ecc_chip(), config.note_commit_chip_old(), - config.cond_swap_chip(), g_d_old.inner(), pk_d_old.inner(), v_old.clone(), rho_old, psi_old.clone(), - asset.inner(), rcm_old, - is_native_asset.clone(), + Some(ZsaNoteCommitParams { + cond_swap_chip: config.cond_swap_chip(), + asset: asset.inner().clone(), + is_native_asset: is_native_asset.clone(), + }), )?; // Constrain derived cm_old to equal witnessed cm_old @@ -726,22 +676,24 @@ impl OrchardCircuit for OrchardZSA { )?; // g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi) - let cm_new = gadget::note_commit( + let cm_new = note_commit( layouter.namespace(|| { "g★_d || pk★_d || i2lebsp_{64}(v) || i2lebsp_{255}(rho) || i2lebsp_{255}(psi)" }), config.sinsemilla_chip_2(), config.ecc_chip(), config.note_commit_chip_new(), - config.cond_swap_chip(), g_d_new.inner(), pk_d_new.inner(), v_new.clone(), rho_new, psi_new, - asset.inner(), rcm_new, - is_native_asset.clone(), + Some(ZsaNoteCommitParams { + cond_swap_chip: config.cond_swap_chip(), + asset: asset.inner().clone(), + is_native_asset: is_native_asset.clone(), + }), )?; let cmx = cm_new.extract_p(); diff --git a/src/circuit/circuit_zsa/gadget.rs b/src/circuit/circuit_zsa/gadget.rs deleted file mode 100644 index 9919dc682..000000000 --- a/src/circuit/circuit_zsa/gadget.rs +++ /dev/null @@ -1,245 +0,0 @@ -//! Gadgets used in the Orchard circuit (ZSA variation). - -use ff::Field; -use group::Curve; -use pasta_curves::arithmetic::CurveExt; -use pasta_curves::pallas; - -use super::{add_chip, commit_ivk::CommitIvkChip, note_commit::NoteCommitChip, AddInstruction}; -use crate::constants::{NullifierK, OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; -use crate::note::AssetBase; -use halo2_gadgets::{ - ecc::{chip::EccChip, chip::EccPoint, EccInstructions, FixedPointBaseField, Point, X}, - poseidon::{ - primitives::{self as poseidon, ConstantLength}, - Hash as PoseidonHash, PoseidonSpongeInstructions, Pow5Chip as PoseidonChip, - }, - sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, - utilities::{cond_swap::CondSwapChip, lookup_range_check::PallasLookupRangeCheck45BConfig}, -}; -use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - plonk::{self, Advice, Assigned, Column}, -}; - -impl super::Config { - pub(super) fn add_chip(&self) -> add_chip::AddChip { - add_chip::AddChip::construct(self.add_config.clone()) - } - - pub(super) fn commit_ivk_chip(&self) -> CommitIvkChip { - CommitIvkChip::construct(self.commit_ivk_config.clone()) - } - - pub(super) fn ecc_chip(&self) -> EccChip { - EccChip::construct(self.ecc_config.clone()) - } - - pub(super) fn sinsemilla_chip_1( - &self, - ) -> SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - > { - SinsemillaChip::construct(self.sinsemilla_config_1.clone()) - } - - pub(super) fn sinsemilla_chip_2( - &self, - ) -> SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - > { - SinsemillaChip::construct(self.sinsemilla_config_2.clone()) - } - - pub(super) fn merkle_chip_1( - &self, - ) -> MerkleChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - > { - MerkleChip::construct(self.merkle_config_1.clone()) - } - - pub(super) fn merkle_chip_2( - &self, - ) -> MerkleChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - > { - MerkleChip::construct(self.merkle_config_2.clone()) - } - - pub(super) fn poseidon_chip(&self) -> PoseidonChip { - PoseidonChip::construct(self.poseidon_config.clone()) - } - - pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { - NoteCommitChip::construct(self.new_note_commit_config.clone()) - } - - pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { - NoteCommitChip::construct(self.old_note_commit_config.clone()) - } - - pub(super) fn cond_swap_chip(&self) -> CondSwapChip { - CondSwapChip::construct(self.cond_swap_config.clone()) - } -} - -/// Witnesses the given value in a standalone region. -/// -/// Usages of this helper are technically superfluous, as the single-cell region is only -/// ever used in equality constraints. We could eliminate them with a -/// [write-on-copy abstraction](https://github.com/zcash/halo2/issues/334). -pub(in crate::circuit) fn assign_free_advice( - mut layouter: impl Layouter, - column: Column, - value: Value, -) -> Result, plonk::Error> -where - for<'v> Assigned: From<&'v V>, -{ - layouter.assign_region( - || "load private", - |mut region| region.assign_advice(|| "load private", column, 0, || value), - ) -} - -/// Witnesses is_native_asset. -pub(in crate::circuit) fn assign_is_native_asset( - layouter: impl Layouter, - column: Column, - asset: Value, -) -> Result, plonk::Error> -where - Assigned: for<'v> From<&'v pasta_curves::Fp>, -{ - assign_free_advice( - layouter, - column, - asset.map(|asset| { - if bool::from(asset.is_native()) { - pallas::Base::one() - } else { - pallas::Base::zero() - } - }), - ) -} - -/// Witnesses split_flag. -pub(in crate::circuit) fn assign_split_flag( - layouter: impl Layouter, - column: Column, - split_flag: Value, -) -> Result, plonk::Error> -where - Assigned: for<'v> From<&'v pasta_curves::Fp>, -{ - assign_free_advice( - layouter, - column, - split_flag.map(|split_flag| { - if split_flag { - pallas::Base::one() - } else { - pallas::Base::zero() - } - }), - ) -} - -/// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. -/// -/// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers -#[allow(clippy::too_many_arguments)] -pub(in crate::circuit) fn derive_nullifier< - PoseidonChip: PoseidonSpongeInstructions, 3, 2>, - AddChip: AddInstruction, - EccChip: EccInstructions< - pallas::Affine, - FixedPoints = OrchardFixedBases, - Point = EccPoint, - Var = AssignedCell, - >, ->( - mut layouter: impl Layouter, - poseidon_chip: PoseidonChip, - add_chip: AddChip, - ecc_chip: EccChip, - cond_swap_chip: CondSwapChip, - rho: AssignedCell, - psi: &AssignedCell, - cm: &Point, - nk: AssignedCell, - split_flag: AssignedCell, -) -> Result, plonk::Error> { - // hash = poseidon_hash(nk, rho) - let hash = { - let poseidon_message = [nk, rho]; - let poseidon_hasher = - PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; - poseidon_hasher.hash( - layouter.namespace(|| "Poseidon hash (nk, rho)"), - poseidon_message, - )? - }; - - // Add hash output to psi. - // `scalar` = poseidon_hash(nk, rho) + psi. - let scalar = add_chip.add( - layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), - &hash, - psi, - )?; - - // Multiply scalar by NullifierK - // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. - // - let product = { - let nullifier_k = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK); - nullifier_k.mul( - layouter.namespace(|| "[poseidon_output + psi] NullifierK"), - scalar, - )? - }; - - // Add cm to multiplied fixed base - // nf = cm + [poseidon_output + psi] NullifierK - let nf = cm.add(layouter.namespace(|| "nf"), &product)?; - - // Add NullifierL to nf - // split_note_nf = NullifierL + nf - let nullifier_l = Point::new_from_constant( - ecc_chip.clone(), - layouter.namespace(|| "witness NullifierL constant"), - pallas::Point::hash_to_curve("z.cash:Orchard")(b"L").to_affine(), - )?; - let split_note_nf = nullifier_l.add(layouter.namespace(|| "split_note_nf"), &nf)?; - - // Select the desired nullifier according to split_flag - Ok(Point::from_inner( - ecc_chip, - cond_swap_chip.mux_on_points( - layouter.namespace(|| "mux on nf"), - &split_flag, - nf.inner(), - split_note_nf.inner(), - )?, - ) - .extract_p()) -} - -pub(in crate::circuit) use super::commit_ivk::gadgets::commit_ivk; -pub(in crate::circuit) use super::note_commit::gadgets::note_commit; -pub(in crate::circuit) use super::value_commit_orchard::gadgets::value_commit_orchard; diff --git a/src/circuit/commit_ivk.rs b/src/circuit/commit_ivk.rs index bfface3ff..95c9f7746 100644 --- a/src/circuit/commit_ivk.rs +++ b/src/circuit/commit_ivk.rs @@ -683,7 +683,7 @@ mod tests { }, utilities::{ lookup_range_check::{ - PallasLookupRangeCheck, PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheck, PallasLookupRangeCheck4_5BConfig, PallasLookupRangeCheckConfig, }, UtilitiesInstructions, @@ -705,7 +705,7 @@ mod tests { const ENABLE_HASH_FROM_PRIVATE_POINT: bool = false; } - impl MyLookup for PallasLookupRangeCheck45BConfig { + impl MyLookup for PallasLookupRangeCheck4_5BConfig { const ENABLE_HASH_FROM_PRIVATE_POINT: bool = true; } @@ -943,6 +943,6 @@ mod tests { #[test] fn commit_ivk_zsa() { - commit_ivk::() + commit_ivk::() } } diff --git a/src/circuit/derive_nullifier.rs b/src/circuit/derive_nullifier.rs new file mode 100644 index 000000000..4b74f20a6 --- /dev/null +++ b/src/circuit/derive_nullifier.rs @@ -0,0 +1,113 @@ +//! Derive nullifier logic for the Orchard circuit. + +use halo2_gadgets::utilities::cond_swap::CondSwapChip; +use halo2_proofs::circuit::AssignedCell; +use pasta_curves::{arithmetic::CurveExt, pallas}; + +pub struct ZsaNullifierParams { + pub cond_swap_chip: CondSwapChip, + pub split_flag: AssignedCell, +} + +pub(in crate::circuit) mod gadgets { + use super::*; + + use group::Curve; + + use crate::{ + circuit::gadget::AddInstruction, + constants::{NullifierK, OrchardFixedBases}, + }; + use halo2_gadgets::{ + ecc::{chip::EccPoint, EccInstructions, FixedPointBaseField, Point, X}, + poseidon::{ + primitives::{self as poseidon, ConstantLength}, + Hash as PoseidonHash, PoseidonSpongeInstructions, + }, + }; + use halo2_proofs::{circuit::Layouter, plonk}; + + /// `DeriveNullifier` from [Section 4.16: Note Commitments and Nullifiers]. + /// + /// [Section 4.16: Note Commitments and Nullifiers]: https://zips.z.cash/protocol/protocol.pdf#commitmentsandnullifiers + #[allow(clippy::too_many_arguments)] + pub(in crate::circuit) fn derive_nullifier< + PoseidonChip: PoseidonSpongeInstructions, 3, 2>, + AddChip: AddInstruction, + EccChip: EccInstructions< + pallas::Affine, + FixedPoints = OrchardFixedBases, + Point = EccPoint, + Var = AssignedCell, + >, + >( + layouter: &mut impl Layouter, + poseidon_chip: PoseidonChip, + add_chip: AddChip, + ecc_chip: EccChip, + rho: AssignedCell, + psi: &AssignedCell, + cm: &Point, + nk: AssignedCell, + zsa_params: Option, + ) -> Result, plonk::Error> { + // hash = poseidon_hash(nk, rho) + let hash = { + let poseidon_message = [nk, rho]; + let poseidon_hasher = + PoseidonHash::init(poseidon_chip, layouter.namespace(|| "Poseidon init"))?; + poseidon_hasher.hash( + layouter.namespace(|| "Poseidon hash (nk, rho)"), + poseidon_message, + )? + }; + + // Add hash output to psi. + // `scalar` = poseidon_hash(nk, rho) + psi. + let scalar = add_chip.add( + layouter.namespace(|| "scalar = poseidon_hash(nk, rho) + psi"), + &hash, + psi, + )?; + + // Multiply scalar by NullifierK + // `product` = [poseidon_hash(nk, rho) + psi] NullifierK. + let product = { + let nullifier_k = FixedPointBaseField::from_inner(ecc_chip.clone(), NullifierK); + nullifier_k.mul( + layouter.namespace(|| "[poseidon_output + psi] NullifierK"), + scalar, + )? + }; + + // Add cm to multiplied fixed base + // nf = cm + [poseidon_output + psi] NullifierK + let nf = cm.add(layouter.namespace(|| "nf"), &product)?; + + match zsa_params { + None => Ok(nf.extract_p()), + Some(zsa_params) => { + // Add NullifierL to nf + // split_note_nf = NullifierL + nf + let nullifier_l = Point::new_from_constant( + ecc_chip.clone(), + layouter.namespace(|| "witness NullifierL constant"), + pallas::Point::hash_to_curve("z.cash:Orchard")(b"L").to_affine(), + )?; + let split_note_nf = nullifier_l.add(layouter.namespace(|| "split_note_nf"), &nf)?; + + // Select the desired nullifier according to split_flag + Ok(Point::from_inner( + ecc_chip, + zsa_params.cond_swap_chip.mux_on_points( + layouter.namespace(|| "mux on nf"), + &zsa_params.split_flag, + nf.inner(), + split_note_nf.inner(), + )?, + ) + .extract_p()) + } + } + } +} diff --git a/src/circuit/gadget.rs b/src/circuit/gadget.rs index c62f825f7..2675fef13 100644 --- a/src/circuit/gadget.rs +++ b/src/circuit/gadget.rs @@ -1,10 +1,23 @@ //! Common gadgets and functions used in the Orchard circuit. use ff::Field; +use halo2_gadgets::{ + ecc::chip::EccChip, + poseidon::Pow5Chip as PoseidonChip, + sinsemilla::{chip::SinsemillaChip, merkle::chip::MerkleChip}, + utilities::{cond_swap::CondSwapChip, lookup_range_check::PallasLookupRangeCheck}, +}; +use pasta_curves::pallas; +use crate::{ + circuit::{commit_ivk::CommitIvkChip, note_commit::NoteCommitChip, Config}, + constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, + note::AssetBase, +}; use halo2_proofs::{ + circuit::Value, circuit::{AssignedCell, Chip, Layouter}, - plonk, + plonk::{self, Advice, Assigned, Column}, }; pub(in crate::circuit) mod add_chip; @@ -19,3 +32,120 @@ pub(in crate::circuit) trait AddInstruction: Chip { b: &AssignedCell, ) -> Result, plonk::Error>; } + +impl Config { + pub(super) fn add_chip(&self) -> add_chip::AddChip { + add_chip::AddChip::construct(self.add_config.clone()) + } + + pub(super) fn commit_ivk_chip(&self) -> CommitIvkChip { + CommitIvkChip::construct(self.commit_ivk_config.clone()) + } + + pub(super) fn ecc_chip(&self) -> EccChip { + EccChip::construct(self.ecc_config.clone()) + } + + pub(super) fn sinsemilla_chip_1( + &self, + ) -> SinsemillaChip { + SinsemillaChip::construct(self.sinsemilla_config_1.clone()) + } + + pub(super) fn sinsemilla_chip_2( + &self, + ) -> SinsemillaChip { + SinsemillaChip::construct(self.sinsemilla_config_2.clone()) + } + + pub(super) fn merkle_chip_1( + &self, + ) -> MerkleChip { + MerkleChip::construct(self.merkle_config_1.clone()) + } + + pub(super) fn merkle_chip_2( + &self, + ) -> MerkleChip { + MerkleChip::construct(self.merkle_config_2.clone()) + } + + pub(super) fn poseidon_chip(&self) -> PoseidonChip { + PoseidonChip::construct(self.poseidon_config.clone()) + } + + pub(super) fn note_commit_chip_new(&self) -> NoteCommitChip { + NoteCommitChip::construct(self.new_note_commit_config.clone()) + } + + pub(super) fn note_commit_chip_old(&self) -> NoteCommitChip { + NoteCommitChip::construct(self.old_note_commit_config.clone()) + } + + pub(super) fn cond_swap_chip(&self) -> CondSwapChip { + CondSwapChip::construct(self.merkle_config_1.cond_swap_config.clone()) + } +} + +/// Witnesses the given value in a standalone region. +/// +/// Usages of this helper are technically superfluous, as the single-cell region is only +/// ever used in equality constraints. We could eliminate them with a +/// [write-on-copy abstraction](https://github.com/zcash/halo2/issues/334). +pub(in crate::circuit) fn assign_free_advice( + mut layouter: impl Layouter, + column: Column, + value: Value, +) -> Result, plonk::Error> +where + for<'v> Assigned: From<&'v V>, +{ + layouter.assign_region( + || "load private", + |mut region| region.assign_advice(|| "load private", column, 0, || value), + ) +} + +/// Witnesses is_native_asset. +pub(in crate::circuit) fn assign_is_native_asset( + layouter: impl Layouter, + column: Column, + asset: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + asset.map(|asset| { + if bool::from(asset.is_native()) { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) +} + +/// Witnesses split_flag. +pub(in crate::circuit) fn assign_split_flag( + layouter: impl Layouter, + column: Column, + split_flag: Value, +) -> Result, plonk::Error> +where + Assigned: for<'v> From<&'v pasta_curves::Fp>, +{ + assign_free_advice( + layouter, + column, + split_flag.map(|split_flag| { + if split_flag { + pallas::Base::one() + } else { + pallas::Base::zero() + } + }), + ) +} diff --git a/src/circuit/circuit_zsa/note_commit.rs b/src/circuit/note_commit.rs similarity index 70% rename from src/circuit/circuit_zsa/note_commit.rs rename to src/circuit/note_commit.rs index 4f9a6a86a..ba2e1fd44 100644 --- a/src/circuit/circuit_zsa/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -1,44 +1,35 @@ -//! Note commitment logic for the Orchard circuit (ZSA variation). - -use core::iter; - -use group::ff::PrimeField; -use halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, - poly::Rotation, -}; -use pasta_curves::pallas; +//! Note commitment logic for the Orchard circuit. use crate::{ constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_P}, value::NoteValue, }; +use group::ff::PrimeField; use halo2_gadgets::{ ecc::{ chip::{EccChip, NonIdentityEccPoint}, - NonIdentityPoint, Point, ScalarFixed, + {NonIdentityPoint, Point, ScalarFixed}, }, sinsemilla::{ chip::{SinsemillaChip, SinsemillaConfig}, CommitDomain, Message, MessagePiece, }, utilities::{ - bool_check, - cond_swap::CondSwapChip, - lookup_range_check::{LookupRangeCheck, PallasLookupRangeCheck45BConfig}, + bool_check, cond_swap::CondSwapChip, lookup_range_check::PallasLookupRangeCheck, FieldValue, RangeConstrained, }, }; +use halo2_proofs::{ + circuit::{AssignedCell, Chip, Layouter, Value}, + plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, + poly::Rotation, +}; +use pasta_curves::pallas; +use std::iter; -type NoteCommitPiece = MessagePiece< +type NoteCommitPiece = MessagePiece< pallas::Affine, - SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + SinsemillaChip, 10, 253, >; @@ -73,14 +64,15 @@ type CanonicityBounds = ( /// /// #[derive(Clone, Debug)] -struct DecomposeB { +struct DecomposeB { q_notecommit_b: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeB { +impl DecomposeB { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -125,24 +117,20 @@ impl DecomposeB { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &PallasLookupRangeCheck45BConfig, - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, RangeConstrained>, @@ -184,7 +172,7 @@ impl DecomposeB { fn assign( &self, layouter: &mut impl Layouter, - b: NoteCommitPiece, + b: NoteCommitPiece, b_0: RangeConstrained>, b_1: RangeConstrained>, b_2: RangeConstrained>, @@ -223,14 +211,15 @@ impl DecomposeB { /// /// #[derive(Clone, Debug)] -struct DecomposeD { +struct DecomposeD { q_notecommit_d: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeD { +impl DecomposeD { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -275,24 +264,20 @@ impl DecomposeD { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &PallasLookupRangeCheck45BConfig, - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, pk_d: &NonIdentityEccPoint, value: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, RangeConstrained>, @@ -328,7 +313,7 @@ impl DecomposeD { fn assign( &self, layouter: &mut impl Layouter, - d: NoteCommitPiece, + d: NoteCommitPiece, d_0: RangeConstrained>, d_1: RangeConstrained>, d_2: RangeConstrained>, @@ -364,14 +349,15 @@ impl DecomposeD { /// /// #[derive(Clone, Debug)] -struct DecomposeE { +struct DecomposeE { q_notecommit_e: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeE { +impl DecomposeE { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -402,24 +388,20 @@ impl DecomposeE { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &PallasLookupRangeCheck45BConfig, - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, value: &AssignedCell, rho: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, ), @@ -455,7 +437,7 @@ impl DecomposeE { fn assign( &self, layouter: &mut impl Layouter, - e: NoteCommitPiece, + e: NoteCommitPiece, e_0: RangeConstrained>, e_1: RangeConstrained>, ) -> Result<(), Error> { @@ -488,13 +470,14 @@ impl DecomposeE { /// /// #[derive(Clone, Debug)] -struct DecomposeG { +struct DecomposeG { q_notecommit_g: Selector, col_l: Column, col_m: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeG { +impl DecomposeG { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -532,24 +515,20 @@ impl DecomposeG { q_notecommit_g, col_l, col_m, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &PallasLookupRangeCheck45BConfig, - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, rho: &AssignedCell, psi: &AssignedCell, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, ), @@ -581,7 +560,7 @@ impl DecomposeG { fn assign( &self, layouter: &mut impl Layouter, - g: NoteCommitPiece, + g: NoteCommitPiece, g_0: RangeConstrained>, g_1: RangeConstrained>, z1_g: AssignedCell, @@ -605,6 +584,130 @@ impl DecomposeG { ) } } + +/// For Vanilla Orchard circuit, +/// h = h_0 || h_1 || h_2 +/// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits +/// +/// | A_6 | A_7 | A_8 | q_notecommit_h | +/// ------------------------------------ +/// | h | h_0 | h_1 | 1 | +/// +/// +#[derive(Clone, Debug)] +struct DecomposeHVanilla { + q_notecommit_h: Selector, + col_l: Column, + col_m: Column, + col_r: Column, + _lookup_marker: std::marker::PhantomData, +} + +impl DecomposeHVanilla { + fn configure( + meta: &mut ConstraintSystem, + col_l: Column, + col_m: Column, + col_r: Column, + two_pow_5: pallas::Base, + ) -> Self { + let q_notecommit_h = meta.selector(); + + meta.create_gate("NoteCommit MessagePiece h", |meta| { + let q_notecommit_h = meta.query_selector(q_notecommit_h); + + // h has been constrained to 10 bits by the Sinsemilla hash. + let h = meta.query_advice(col_l, Rotation::cur()); + // h_0 has been constrained to be 5 bits outside this gate. + let h_0 = meta.query_advice(col_m, Rotation::cur()); + // This gate constrains h_1 to be boolean. + let h_1 = meta.query_advice(col_r, Rotation::cur()); + + // h = h_0 + (2^5) h_1 + let decomposition_check = h - (h_0 + h_1.clone() * two_pow_5); + + Constraints::with_selector( + q_notecommit_h, + [ + ("bool_check h_1", bool_check(h_1)), + ("decomposition", decomposition_check), + ], + ) + }); + + Self { + q_notecommit_h, + col_l, + col_m, + col_r, + _lookup_marker: std::marker::PhantomData, + } + } + + #[allow(clippy::type_complexity)] + fn decompose( + lookup_config: &Lookup, + chip: SinsemillaChip, + layouter: &mut impl Layouter, + psi: &AssignedCell, + ) -> Result< + ( + NoteCommitPiece, + RangeConstrained>, + RangeConstrained>, + ), + Error, + > { + // Constrain h_0 to be 5 bits. + let h_0 = RangeConstrained::witness_short( + lookup_config, + layouter.namespace(|| "h_0"), + psi.value(), + 249..254, + )?; + + // h_1 will be boolean-constrained in the gate. + let h_1 = RangeConstrained::bitrange_of(psi.value(), 254..255); + + let h = MessagePiece::from_subpieces( + chip, + layouter.namespace(|| "h"), + [ + h_0.value(), + h_1, + RangeConstrained::bitrange_of(Value::known(&pallas::Base::zero()), 0..4), + ], + )?; + + Ok((h, h_0, h_1)) + } + + fn assign( + &self, + layouter: &mut impl Layouter, + h: NoteCommitPiece, + h_0: RangeConstrained>, + h_1: RangeConstrained>, + ) -> Result, Error> { + layouter.assign_region( + || "NoteCommit MessagePiece h", + |mut region| { + self.q_notecommit_h.enable(&mut region, 0)?; + + h.inner() + .cell_value() + .copy_advice(|| "h", &mut region, self.col_l, 0)?; + h_0.inner() + .copy_advice(|| "h_0", &mut region, self.col_m, 0)?; + let h_1 = region.assign_advice(|| "h_1", self.col_r, 0, || *h_1.inner())?; + + Ok(h_1) + }, + ) + } +} + +/// For ZSA Orchard circuit, /// h_zec = h_0 || h_1 || h_2_zec /// = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits /// @@ -618,14 +721,15 @@ impl DecomposeG { /// /// #[derive(Clone, Debug)] -struct DecomposeH { +struct DecomposeHZsa { q_notecommit_h: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeH { +impl DecomposeHZsa { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -673,25 +777,21 @@ impl DecomposeH { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - lookup_config: &PallasLookupRangeCheck45BConfig, - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + lookup_config: &Lookup, + chip: SinsemillaChip, layouter: &mut impl Layouter, psi: &AssignedCell, asset: &NonIdentityEccPoint, ) -> Result< ( - NoteCommitPiece, - NoteCommitPiece, + NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, RangeConstrained>, @@ -739,8 +839,8 @@ impl DecomposeH { fn assign( &self, layouter: &mut impl Layouter, - h_zec: NoteCommitPiece, - h_zsa: NoteCommitPiece, + h_zec: NoteCommitPiece, + h_zsa: NoteCommitPiece, h_0: RangeConstrained>, h_1: RangeConstrained>, h_2_zsa: RangeConstrained>, @@ -782,14 +882,15 @@ impl DecomposeH { /// /// https://p.z.cash/orchard-0.1:note-commit-decomposition-j?partial #[derive(Clone, Debug)] -struct DecomposeJ { +struct DecomposeJ { q_notecommit_j: Selector, col_l: Column, col_m: Column, col_r: Column, + _lookup_marker: std::marker::PhantomData, } -impl DecomposeJ { +impl DecomposeJ { fn configure( meta: &mut ConstraintSystem, col_l: Column, @@ -827,22 +928,18 @@ impl DecomposeJ { col_l, col_m, col_r, + _lookup_marker: std::marker::PhantomData, } } #[allow(clippy::type_complexity)] fn decompose( - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + chip: SinsemillaChip, layouter: &mut impl Layouter, asset: &NonIdentityEccPoint, ) -> Result< ( - NoteCommitPiece, + NoteCommitPiece, RangeConstrained>, RangeConstrained>, ), @@ -868,7 +965,7 @@ impl DecomposeJ { fn assign( &self, layouter: &mut impl Layouter, - j: NoteCommitPiece, + j: NoteCommitPiece, j_0: RangeConstrained>, j_1: RangeConstrained>, ) -> Result, Error> { @@ -897,15 +994,16 @@ impl DecomposeJ { /// /// #[derive(Clone, Debug)] -struct GdCanonicity { +struct GdCanonicity { q_notecommit_g_d: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, + _lookup_marker: std::marker::PhantomData, } -impl GdCanonicity { +impl GdCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -969,6 +1067,7 @@ impl GdCanonicity { col_m, col_r, col_z, + _lookup_marker: std::marker::PhantomData, } } @@ -977,7 +1076,7 @@ impl GdCanonicity { &self, layouter: &mut impl Layouter, g_d: &NonIdentityEccPoint, - a: NoteCommitPiece, + a: NoteCommitPiece, b_0: RangeConstrained>, b_1: AssignedCell, a_prime: AssignedCell, @@ -1006,6 +1105,7 @@ impl GdCanonicity { ) } } + /// For pk_d /// | A_6 | A_7 | A_8 | A_9 | q_notecommit_pk_d_asset | /// ------------------------------------------------------------------------- @@ -1020,15 +1120,16 @@ impl GdCanonicity { /// /// #[derive(Clone, Debug)] -struct PkdAssetCanonicity { +struct PkdAssetCanonicity { q_notecommit_pk_d_asset: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, + _lookup_marker: std::marker::PhantomData, } -impl PkdAssetCanonicity { +impl PkdAssetCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -1094,6 +1195,7 @@ impl PkdAssetCanonicity { col_m, col_r, col_z, + _lookup_marker: std::marker::PhantomData, } } @@ -1106,7 +1208,7 @@ impl PkdAssetCanonicity { layouter: &mut impl Layouter, pk_d: &NonIdentityEccPoint, b_3: RangeConstrained>, - c: NoteCommitPiece, + c: NoteCommitPiece, d_0: AssignedCell, b3_c_prime: AssignedCell, z13_c: AssignedCell, @@ -1220,15 +1322,16 @@ impl ValueCanonicity { /// /// #[derive(Clone, Debug)] -struct RhoCanonicity { +struct RhoCanonicity { q_notecommit_rho: Selector, col_l: Column, col_m: Column, col_r: Column, col_z: Column, + _lookup_marker: std::marker::PhantomData, } -impl RhoCanonicity { +impl RhoCanonicity { #[allow(clippy::too_many_arguments)] fn configure( meta: &mut ConstraintSystem, @@ -1290,6 +1393,7 @@ impl RhoCanonicity { col_m, col_r, col_z, + _lookup_marker: std::marker::PhantomData, } } @@ -1299,7 +1403,7 @@ impl RhoCanonicity { layouter: &mut impl Layouter, rho: AssignedCell, e_1: RangeConstrained>, - f: NoteCommitPiece, + f: NoteCommitPiece, g_0: AssignedCell, e1_f_prime: AssignedCell, z13_f: AssignedCell, @@ -1619,34 +1723,46 @@ impl YCanonicity { #[allow(non_snake_case)] #[derive(Clone, Debug)] -pub struct NoteCommitConfig { - b: DecomposeB, - d: DecomposeD, - e: DecomposeE, - g: DecomposeG, - h: DecomposeH, - j: DecomposeJ, - g_d: GdCanonicity, - pk_d_asset: PkdAssetCanonicity, +pub struct NoteCommitConfig { + b: DecomposeB, + d: DecomposeD, + e: DecomposeE, + g: DecomposeG, + g_d: GdCanonicity, + pk_d_asset: PkdAssetCanonicity, value: ValueCanonicity, - rho: RhoCanonicity, + rho: RhoCanonicity, psi: PsiCanonicity, y_canon: YCanonicity, advices: [Column; 10], - sinsemilla_config: SinsemillaConfig< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, + sinsemilla_config: + SinsemillaConfig, + specific_config_for_circuit: SpecificConfigForCircuit, +} + +#[derive(Clone, Debug)] +pub enum SpecificConfigForCircuit { + Vanilla(NoteCommitConfigForVanillaCircuit), + Zsa(NoteCommitConfigForZsaCircuit), +} + +#[derive(Clone, Debug)] +pub struct NoteCommitConfigForVanillaCircuit { + h_vanilla: DecomposeHVanilla, } #[derive(Clone, Debug)] -pub struct NoteCommitChip { - config: NoteCommitConfig, +pub struct NoteCommitConfigForZsaCircuit { + h_zsa: DecomposeHZsa, + j: DecomposeJ, } -impl NoteCommitChip { +#[derive(Clone, Debug)] +pub struct NoteCommitChip { + pub config: NoteCommitConfig, +} + +impl NoteCommitChip { #[allow(non_snake_case)] #[allow(clippy::many_single_char_names)] pub(in crate::circuit) fn configure( @@ -1656,9 +1772,10 @@ impl NoteCommitChip { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, - PallasLookupRangeCheck45BConfig, + Lookup, >, - ) -> NoteCommitConfig { + is_zsa_circuit: bool, + ) -> NoteCommitConfig { // Useful constants let two = pallas::Base::from(2); let two_pow_2 = pallas::Base::from(1 << 2); @@ -1687,8 +1804,14 @@ impl NoteCommitChip { let d = DecomposeD::configure(meta, col_l, col_m, col_r, two, two_pow_2, two_pow_10); let e = DecomposeE::configure(meta, col_l, col_m, col_r, two_pow_6); let g = DecomposeG::configure(meta, col_l, col_m, two, two_pow_10); - let h = DecomposeH::configure(meta, col_l, col_m, col_r, two_pow_5, two_pow_6); - let j = DecomposeJ::configure(meta, col_l, col_m, col_r, two); + let specific_config_for_circuit = if is_zsa_circuit { + let h = DecomposeHZsa::configure(meta, col_l, col_m, col_r, two_pow_5, two_pow_6); + let j = DecomposeJ::configure(meta, col_l, col_m, col_r, two); + SpecificConfigForCircuit::Zsa(NoteCommitConfigForZsaCircuit { h_zsa: h, j }) + } else { + let h = DecomposeHVanilla::configure(meta, col_l, col_m, col_r, two_pow_5); + SpecificConfigForCircuit::Vanilla(NoteCommitConfigForVanillaCircuit { h_vanilla: h }) + }; let g_d = GdCanonicity::configure( meta, @@ -1758,8 +1881,6 @@ impl NoteCommitChip { d, e, g, - h, - j, g_d, pk_d_asset, value, @@ -1768,48 +1889,54 @@ impl NoteCommitChip { y_canon, advices, sinsemilla_config, + specific_config_for_circuit, } } - pub(in crate::circuit) fn construct(config: NoteCommitConfig) -> Self { + pub(in crate::circuit) fn construct(config: NoteCommitConfig) -> Self { Self { config } } } -pub(in crate::circuit) mod gadgets { - use halo2_proofs::circuit::{Chip, Value}; +pub struct ZsaNoteCommitParams { + pub cond_swap_chip: CondSwapChip, + pub asset: NonIdentityEccPoint, + pub is_native_asset: AssignedCell, +} +pub struct ZsaFinalDecomposition { + pub h_zsa: NoteCommitPiece, + pub h_2_zsa: RangeConstrained>, + pub i: NoteCommitPiece, + pub j: NoteCommitPiece, + pub j_0: RangeConstrained>, + pub j_1: RangeConstrained>, +} +pub(in crate::circuit) mod gadgets { use super::*; #[allow(clippy::many_single_char_names)] #[allow(clippy::type_complexity)] #[allow(clippy::too_many_arguments)] - pub(in crate::circuit) fn note_commit( + pub(in crate::circuit) fn note_commit( mut layouter: impl Layouter, - chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, - ecc_chip: EccChip, - note_commit_chip: NoteCommitChip, - cond_swap_chip: CondSwapChip, + chip: SinsemillaChip, + ecc_chip: EccChip, + note_commit_chip: NoteCommitChip, g_d: &NonIdentityEccPoint, pk_d: &NonIdentityEccPoint, value: AssignedCell, rho: AssignedCell, psi: AssignedCell, - asset: &NonIdentityEccPoint, - rcm: ScalarFixed< - pallas::Affine, - EccChip, - >, - is_native_asset: AssignedCell, - ) -> Result< - Point>, - Error, - > { + rcm: ScalarFixed>, + zsa_params: Option, + ) -> Result>, Error> { + match (&zsa_params, ¬e_commit_chip.config.specific_config_for_circuit) { + (Some(_), SpecificConfigForCircuit::Zsa(_)) => {}, + (None, SpecificConfigForCircuit::Vanilla(_)) => {}, + _ => panic!("ZSA parameters must be provided for ZSA circuits, and must not be provided for vanilla circuits"), + } + let lookup_config = chip.config().lookup_config(); // `a` = bits 0..=249 of `x(g_d)` @@ -1852,22 +1979,69 @@ pub(in crate::circuit) mod gadgets { let (g, g_0, g_1) = DecomposeG::decompose(&lookup_config, chip.clone(), &mut layouter, &rho, &psi)?; - // h_zec = h_0 || h_1 || h_2_zec - // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits - // h_zsa = h_0 || h_1 || h_2_zsa - // = (bits 249..=253 of psi) || (bit 254 of psi) || (bits 0..=3 of x(asset)) - let (h_zec, h_zsa, h_0, h_1, h_2_zsa) = - DecomposeH::decompose(&lookup_config, chip.clone(), &mut layouter, &psi, asset)?; + let (h_zec, h_0, h_1, zsa_decomposition) = match &zsa_params { + None => { + // h_zec = h_0 || h_1 || h_2 + // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits + let (h_zec, h_0, h_1) = DecomposeHVanilla::decompose( + &lookup_config, + chip.clone(), + &mut layouter, + &psi, + )?; + (h_zec, h_0, h_1, None) + } + Some(zsa_params) => { + // h_zec = h_0 || h_1 || h_2_zec + // = (bits 249..=253 of psi) || (bit 254 of psi) || 4 zero bits + // h_zsa = h_0 || h_1 || h_2_zsa + // = (bits 249..=253 of psi) || (bit 254 of psi) || (bits 0..=3 of x(asset)) + let (h_zec, h_zsa, h_0, h_1, h_2_zsa) = DecomposeHZsa::decompose( + &lookup_config, + chip.clone(), + &mut layouter, + &psi, + &zsa_params.asset, + )?; - // i = bits 4..=253 of asset - let i = MessagePiece::from_subpieces( - chip.clone(), - layouter.namespace(|| "i"), - [RangeConstrained::bitrange_of(asset.x().value(), 4..254)], - )?; + // i = bits 4..=253 of asset + let i = MessagePiece::from_subpieces( + chip.clone(), + layouter.namespace(|| "i"), + [RangeConstrained::bitrange_of( + zsa_params.asset.x().value(), + 4..254, + )], + )?; - // j = j_0 || j_1 || j_2 = (bit 254 of x(asset)) || (ỹ bit of asset) || 8 zero bits - let (j, j_0, j_1) = DecomposeJ::decompose(chip.clone(), &mut layouter, asset)?; + // j = j_0 || j_1 || j_2 = (bit 254 of x(asset)) || (ỹ bit of asset) || 8 zero bits + let (j, j_0, j_1) = + DecomposeJ::decompose(chip.clone(), &mut layouter, &zsa_params.asset)?; + + // Check decomposition of `y(asset)`. + let j_1 = y_canonicity( + &lookup_config, + ¬e_commit_chip.config.y_canon, + layouter.namespace(|| "y(asset) decomposition"), + zsa_params.asset.y(), + j_1, + )?; + + ( + h_zec, + h_0, + h_1, + Some(ZsaFinalDecomposition { + h_zsa, + h_2_zsa, + i, + j, + j_0, + j_1, + }), + ) + } + }; // Check decomposition of `y(g_d)`. let b_2 = y_canonicity( @@ -1877,6 +2051,7 @@ pub(in crate::circuit) mod gadgets { g_d.y(), b_2, )?; + // Check decomposition of `y(pk_d)`. let d_1 = y_canonicity( &lookup_config, @@ -1885,129 +2060,162 @@ pub(in crate::circuit) mod gadgets { pk_d.y(), d_1, )?; - // Check decomposition of `y(asset)`. - let j_1 = y_canonicity( - &lookup_config, - ¬e_commit_chip.config.y_canon, - layouter.namespace(|| "y(asset) decomposition"), - asset.y(), - j_1, - )?; - // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) - // - // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition - // constraints allows ⊥ to occur, and then during synthesis it detects these edge - // cases and raises an error (aborting proof creation). - // - // https://p.z.cash/ZKS:action-cm-old-integrity?partial - // https://p.z.cash/ZKS:action-cmx-new-integrity?partial - let (cm, zs_common, zs_zsa_suffix) = { - let message_common_prefix = Message::from_pieces( - chip.clone(), - vec![ - a.clone(), - b.clone(), - c.clone(), - d.clone(), - e.clone(), - f.clone(), - g.clone(), - ], - ); - - let message_suffix_zec = Message::from_pieces(chip.clone(), vec![h_zec.clone()]); - - let message_suffix_zsa = - Message::from_pieces(chip.clone(), vec![h_zsa.clone(), i.clone(), j.clone()]); - - // We will evaluate - // - `hash_point_zec = hash(Q_ZEC, message_common_prefix || message_suffix_zec)`, and - // - `hash_point_zsa = hash(Q_ZSA, message_common_prefix || message_suffix_zsa)`. - // by sharing a portion of the hash evaluation process between `hash_point_zec` and - // `hash_point_zsa`: - // 1. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} - // 2. common_hash = hash(Q, message_common_prefix) // this part is shared - // 3. hash_point_zec = hash(common_hash, message_suffix_zec) - // 4. hash_point_zsa = hash(common_hash, message_suffix_zsa) - // 5. hash_point = if (is_native_asset == 0) {hash_point_zsa} else {hash_point_zec} - let zec_domain = CommitDomain::new( - chip.clone(), - ecc_chip.clone(), - &OrchardCommitDomains::NoteCommit, - ); - let zsa_domain = - CommitDomain::new(chip, ecc_chip.clone(), &OrchardCommitDomains::NoteZsaCommit); - - // Perform a MUX to select the desired initial Q point - // q_init = q_init_zec if is_native_asset is true - // q_init = q_init_zsa if is_native_asset is false - let q_init = { - let q_init_zec = NonIdentityPoint::new( - ecc_chip.clone(), - layouter.namespace(|| "q_init_zec"), - Value::known(zec_domain.q_init()), + let (cm, zs_common, zs_zsa_suffix) = match (&zsa_params, &zsa_decomposition) { + (None, None) => { + // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi) + // + // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition + // constraints allows ⊥ to occur, and then during synthesis it detects these edge + // cases and raises an error (aborting proof creation). + // + // https://p.z.cash/ZKS:action-cm-old-integrity?partial + // https://p.z.cash/ZKS:action-cmx-new-integrity?partial + let message = Message::from_pieces( + chip.clone(), + vec![ + a.clone(), + b.clone(), + c.clone(), + d.clone(), + e.clone(), + f.clone(), + g.clone(), + h_zec.clone(), + ], + ); + let domain = CommitDomain::new(chip, ecc_chip, &OrchardCommitDomains::NoteCommit); + let (cm, zs) = domain.commit( + layouter.namespace(|| "Process NoteCommit inputs"), + message, + rcm, )?; + (cm, zs, vec![]) + } + (Some(zsa_params), Some(zsa_decomposition)) => { + // cm = NoteCommit^Orchard_rcm(g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi || asset) + // + // `cm = ⊥` is handled internally to `CommitDomain::commit`: incomplete addition + // constraints allows ⊥ to occur, and then during synthesis it detects these edge + // cases and raises an error (aborting proof creation). + // + // https://p.z.cash/ZKS:action-cm-old-integrity?partial + // https://p.z.cash/ZKS:action-cmx-new-integrity?partial + let message_common_prefix = Message::from_pieces( + chip.clone(), + vec![ + a.clone(), + b.clone(), + c.clone(), + d.clone(), + e.clone(), + f.clone(), + g.clone(), + ], + ); + + let message_suffix_zec = Message::from_pieces(chip.clone(), vec![h_zec.clone()]); + + let message_suffix_zsa = Message::from_pieces( + chip.clone(), + vec![ + zsa_decomposition.h_zsa.clone(), + zsa_decomposition.i.clone(), + zsa_decomposition.j.clone(), + ], + ); - let q_init_zsa = NonIdentityPoint::new( + // We will evaluate + // - `hash_point_zec = hash(Q_ZEC, message_common_prefix || message_suffix_zec)`, and + // - `hash_point_zsa = hash(Q_ZSA, message_common_prefix || message_suffix_zsa)`. + // by sharing a portion of the hash evaluation process between `hash_point_zec` and + // `hash_point_zsa`: + // 1. Q = if (is_native_asset == 0) {Q_ZSA} else {Q_ZEC} + // 2. common_hash = hash(Q, message_common_prefix) // this part is shared + // 3. hash_point_zec = hash(common_hash, message_suffix_zec) + // 4. hash_point_zsa = hash(common_hash, message_suffix_zsa) + // 5. hash_point = if (is_native_asset == 0) {hash_point_zsa} else {hash_point_zec} + let zec_domain = CommitDomain::new( + chip.clone(), ecc_chip.clone(), - layouter.namespace(|| "q_init_zsa"), - Value::known(zsa_domain.q_init()), - )?; + &OrchardCommitDomains::NoteCommit, + ); + let zsa_domain = + CommitDomain::new(chip, ecc_chip.clone(), &OrchardCommitDomains::NoteZsaCommit); + + // Perform a MUX to select the desired initial Q point + // q_init = q_init_zec if is_native_asset is true + // q_init = q_init_zsa if is_native_asset is false + let q_init = { + let q_init_zec = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "q_init_zec"), + Value::known(zec_domain.q_init()), + )?; - cond_swap_chip.mux_on_non_identity_points( - layouter.namespace(|| "mux on hash point"), - &is_native_asset, - q_init_zsa.inner(), - q_init_zec.inner(), - )? - }; + let q_init_zsa = NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "q_init_zsa"), + Value::known(zsa_domain.q_init()), + )?; - // common_hash = hash(q_init, message_common_prefix) - // - // To evaluate the different hash, we could use either zec_domain or zsa_domain - // because we use a private initial point. - let (common_hash, zs_common) = zec_domain.hash_with_private_init( - layouter.namespace(|| "hash common prefix note"), - &q_init, - message_common_prefix, - )?; + zsa_params.cond_swap_chip.mux_on_non_identity_points( + layouter.namespace(|| "mux on hash point"), + &zsa_params.is_native_asset, + q_init_zsa.inner(), + q_init_zec.inner(), + )? + }; - // hash_point_zec = hash(common_hash, message_suffix_zec) = hash(q_init, message_zec) - let (hash_point_zec, _zs_zec) = zec_domain.hash_with_private_init( - layouter.namespace(|| "hash suffix ZEC note"), - common_hash.inner(), - message_suffix_zec, - )?; + // common_hash = hash(q_init, message_common_prefix) + // + // To evaluate the different hash, we could use either zec_domain or zsa_domain + // because we use a private initial point. + let (common_hash, zs_common) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash common prefix note"), + &q_init, + message_common_prefix, + )?; - // hash_point_zsa = hash(common_hash, message_suffix_zsa) = hash(q_init, message_zsa) - let (hash_point_zsa, zs_zsa) = zec_domain.hash_with_private_init( - layouter.namespace(|| "hash suffix ZSA note"), - common_hash.inner(), - message_suffix_zsa, - )?; + // hash_point_zec = hash(common_hash, message_suffix_zec) = hash(q_init, message_zec) + let (hash_point_zec, _zs_zec) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash suffix ZEC note"), + common_hash.inner(), + message_suffix_zec, + )?; - // Perform a MUX to select the desired hash point - // hash_point = hash_zec if is_native_asset is true - // hash_point = hash_zsa if is_native_asset is false - let hash_point = Point::from_inner( - ecc_chip, - cond_swap_chip.mux_on_points( - layouter.namespace(|| "mux on hash point"), - &is_native_asset, - &(hash_point_zsa.inner().clone().into()), - &(hash_point_zec.inner().clone().into()), - )?, - ); + // hash_point_zsa = hash(common_hash, message_suffix_zsa) = hash(q_init, message_zsa) + let (hash_point_zsa, zs_zsa) = zec_domain.hash_with_private_init( + layouter.namespace(|| "hash suffix ZSA note"), + common_hash.inner(), + message_suffix_zsa, + )?; + + // Perform a MUX to select the desired hash point + // hash_point = hash_zec if is_native_asset is true + // hash_point = hash_zsa if is_native_asset is false + let hash_point = Point::from_inner( + ecc_chip, + zsa_params.cond_swap_chip.mux_on_points( + layouter.namespace(|| "mux on hash point"), + &zsa_params.is_native_asset, + &(hash_point_zsa.inner().clone().into()), + &(hash_point_zec.inner().clone().into()), + )?, + ); - // To evaluate the blinding factor, we could use either zec_domain or zsa_domain - // because they have both the same `R` constant. - let blinding_factor = - zec_domain.blinding_factor(layouter.namespace(|| "[r] R"), rcm)?; - let commitment = - hash_point.add(layouter.namespace(|| "M + [r] R"), &blinding_factor)?; + // To evaluate the blinding factor, we could use either zec_domain or zsa_domain + // because they have both the same `R` constant. + let blinding_factor = + zec_domain.blinding_factor(layouter.namespace(|| "[r] R"), rcm)?; + let commitment = + hash_point.add(layouter.namespace(|| "M + [r] R"), &blinding_factor)?; - (commitment, zs_common, zs_zsa) + (commitment, zs_common, zs_zsa) + } + _ => { + panic!("Either both zsa_params and zsa_decomposition must be provided, or neither.") + } }; // `CommitDomain::hash` returns the running sum for each `MessagePiece`. Grab @@ -2019,7 +2227,6 @@ pub(in crate::circuit) mod gadgets { let z1_g = zs_common[6][1].clone(); let g_2 = z1_g.clone(); let z13_g = zs_common[6][13].clone(); - let z13_i = zs_zsa_suffix[1][13].clone(); // Witness and constrain the bounds we need to ensure canonicity. let (a_prime, z13_a_prime) = canon_bitshift_130( @@ -2035,13 +2242,6 @@ pub(in crate::circuit) mod gadgets { c.inner().cell_value(), )?; - let (h2_i_prime, z14_h2_i_prime) = pkd_asset_x_canonicity( - &lookup_config, - layouter.namespace(|| "x(asset) canonicity"), - h_2_zsa.clone(), - i.inner().cell_value(), - )?; - let (e1_f_prime, z14_e1_f_prime) = rho_canonicity( &lookup_config, layouter.namespace(|| "rho canonicity"), @@ -2057,7 +2257,7 @@ pub(in crate::circuit) mod gadgets { )?; // Finally, assign values to all of the NoteCommit regions. - let cfg = note_commit_chip.config; + let cfg = note_commit_chip.config.clone(); let b_1 = cfg .b @@ -2073,16 +2273,25 @@ pub(in crate::circuit) mod gadgets { .g .assign(&mut layouter, g, g_0, g_1.clone(), z1_g.clone())?; - let h_1 = cfg.h.assign( - &mut layouter, - h_zec, - h_zsa, - h_0.clone(), - h_1, - h_2_zsa.clone(), - )?; - - let j_0 = cfg.j.assign(&mut layouter, j, j_0, j_1)?; + let h_1 = match ( + &zsa_decomposition, + ¬e_commit_chip.config.specific_config_for_circuit, + ) { + (None, SpecificConfigForCircuit::Vanilla(specific_config)) => specific_config + .h_vanilla + .assign(&mut layouter, h_zec, h_0.clone(), h_1)?, + (Some(zsa_decomposition), SpecificConfigForCircuit::Zsa(specific_config)) => { + specific_config.h_zsa.assign( + &mut layouter, + h_zec, + zsa_decomposition.h_zsa.clone(), + h_0.clone(), + h_1, + zsa_decomposition.h_2_zsa.clone(), + )? + } + _ => panic!("zsa_decomposition is required with a ZSA configuration but must be omitted with a Vanilla configuration."), + }; cfg.g_d .assign(&mut layouter, g_d, a, b_0, b_1, a_prime, z13_a, z13_a_prime)?; @@ -2098,17 +2307,6 @@ pub(in crate::circuit) mod gadgets { z14_b3_c_prime, )?; - cfg.pk_d_asset.assign( - &mut layouter, - asset, - h_2_zsa, - i, - j_0, - h2_i_prime, - z13_i, - z14_h2_i_prime, - )?; - cfg.value.assign(&mut layouter, value, d_2, z1_d, e_0)?; cfg.rho.assign( @@ -2134,6 +2332,42 @@ pub(in crate::circuit) mod gadgets { z13_g1_g2_prime, )?; + if let ( + Some(zsa_decomposition), + Some(zsa_params), + SpecificConfigForCircuit::Zsa(specific_config), + ) = ( + zsa_decomposition, + &zsa_params, + ¬e_commit_chip.config.specific_config_for_circuit, + ) { + let j_0 = specific_config.j.assign( + &mut layouter, + zsa_decomposition.j, + zsa_decomposition.j_0, + zsa_decomposition.j_1, + )?; + + let (h2_i_prime, z14_h2_i_prime) = pkd_asset_x_canonicity( + &lookup_config, + layouter.namespace(|| "x(asset) canonicity"), + zsa_decomposition.h_2_zsa.clone(), + zsa_decomposition.i.inner().cell_value(), + )?; + + let z13_i = zs_zsa_suffix[1][13].clone(); + cfg.pk_d_asset.assign( + &mut layouter, + &zsa_params.asset, + zsa_decomposition.h_2_zsa, + zsa_decomposition.i, + j_0, + h2_i_prime, + z13_i, + z14_h2_i_prime, + )?; + } + Ok(cm) } @@ -2142,8 +2376,8 @@ pub(in crate::circuit) mod gadgets { /// Specifications: /// - [`g_d` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-g_d?partial) /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) - fn canon_bitshift_130( - lookup_config: &PallasLookupRangeCheck45BConfig, + fn canon_bitshift_130( + lookup_config: &Lookup, mut layouter: impl Layouter, a: AssignedCell, ) -> Result { @@ -2176,8 +2410,8 @@ pub(in crate::circuit) mod gadgets { /// Check canonicity of `x(pk_d)` and `x(asset)` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-pk_d?partial). - fn pkd_asset_x_canonicity( - lookup_config: &PallasLookupRangeCheck45BConfig, + fn pkd_asset_x_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, b_3: RangeConstrained>, c: AssignedCell, @@ -2219,8 +2453,8 @@ pub(in crate::circuit) mod gadgets { /// Check canonicity of `rho` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-rho?partial). - fn rho_canonicity( - lookup_config: &PallasLookupRangeCheck45BConfig, + fn rho_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, e_1: RangeConstrained>, f: AssignedCell, @@ -2260,8 +2494,8 @@ pub(in crate::circuit) mod gadgets { /// Check canonicity of `psi` encoding. /// /// [Specification](https://p.z.cash/orchard-0.1:note-commit-canonicity-psi?partial). - fn psi_canonicity( - lookup_config: &PallasLookupRangeCheck45BConfig, + fn psi_canonicity( + lookup_config: &Lookup, mut layouter: impl Layouter, g_1: RangeConstrained>, g_2: AssignedCell, @@ -2302,8 +2536,8 @@ pub(in crate::circuit) mod gadgets { /// Specifications: /// - [`y` decomposition](https://p.z.cash/orchard-0.1:note-commit-decomposition-y?partial) /// - [`y` canonicity](https://p.z.cash/orchard-0.1:note-commit-canonicity-y?partial) - fn y_canonicity( - lookup_config: &PallasLookupRangeCheck45BConfig, + fn y_canonicity( + lookup_config: &Lookup, y_canon: &YCanonicity, mut layouter: impl Layouter, y: AssignedCell, @@ -2378,13 +2612,16 @@ pub(in crate::circuit) mod gadgets { #[cfg(test)] mod tests { - use super::NoteCommitConfig; + use core::iter; + use crate::{ - circuit::circuit_zsa::{ - gadget::{assign_free_advice, assign_is_native_asset}, - note_commit::{gadgets, NoteCommitChip}, + circuit::gadget::{assign_free_advice, assign_is_native_asset}, + circuit::note_commit::gadgets, + circuit::note_commit::{NoteCommitChip, NoteCommitConfig}, + constants::{ + fixed_bases::NOTE_COMMITMENT_PERSONALIZATION, OrchardCommitDomains, OrchardFixedBases, + OrchardHashDomains, L_ORCHARD_BASE, L_VALUE, T_Q, }, - constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains, T_Q}, note::{commitment::NoteCommitTrapdoor, AssetBase, NoteCommitment}, value::NoteValue, }; @@ -2393,14 +2630,17 @@ mod tests { chip::{EccChip, EccConfig}, NonIdentityPoint, ScalarFixed, }, - sinsemilla::chip::SinsemillaChip, + sinsemilla::{chip::SinsemillaChip, primitives::CommitDomain}, utilities::{ cond_swap::{CondSwapChip, CondSwapConfig}, - lookup_range_check::PallasLookupRangeCheck45BConfig, + lookup_range_check::{ + LookupRangeCheck, LookupRangeCheckConfig, PallasLookupRangeCheck4_5BConfig, + PallasLookupRangeCheckConfig, + }, }, }; - use ff::{Field, PrimeField}; + use ff::{Field, PrimeField, PrimeFieldBits}; use group::{Curve, Group, GroupEncoding}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, @@ -2409,10 +2649,326 @@ mod tests { }; use pasta_curves::{arithmetic::CurveAffine, pallas, EpAffine}; + use crate::circuit::note_commit::ZsaNoteCommitParams; use rand::{rngs::OsRng, RngCore}; #[test] - fn note_commit() { + fn note_commit_vanilla() { + #[derive(Default)] + struct MyCircuit { + gd_x: Value, + gd_y_lsb: Value, + pkd_x: Value, + pkd_y_lsb: Value, + rho: Value, + psi: Value, + } + + impl Circuit for MyCircuit { + type Config = ( + NoteCommitConfig, + EccConfig, + ); + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + let advices = [ + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + ]; + + // Shared fixed column for loading constants. + let constants = meta.fixed_column(); + meta.enable_constant(constants); + + for advice in advices.iter() { + meta.enable_equality(*advice); + } + + let table_idx = meta.lookup_table_column(); + let lookup = ( + table_idx, + meta.lookup_table_column(), + meta.lookup_table_column(), + ); + let lagrange_coeffs = [ + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + meta.fixed_column(), + ]; + + let range_check = LookupRangeCheckConfig::configure(meta, advices[9], table_idx); + let sinsemilla_config = SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >::configure( + meta, + advices[..5].try_into().unwrap(), + advices[2], + lagrange_coeffs[0], + lookup, + range_check, + false, + ); + let note_commit_config = + NoteCommitChip::configure(meta, advices, sinsemilla_config, false); + + let ecc_config = EccChip::::configure( + meta, + advices, + lagrange_coeffs, + range_check, + ); + + (note_commit_config, ecc_config) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + let (note_commit_config, ecc_config) = config; + + // Load the Sinsemilla generator lookup table used by the whole circuit. + SinsemillaChip::< + OrchardHashDomains, + OrchardCommitDomains, + OrchardFixedBases, + >::load(note_commit_config.sinsemilla_config.clone(), &mut layouter)?; + + // Construct a Sinsemilla chip + let sinsemilla_chip = + SinsemillaChip::construct(note_commit_config.sinsemilla_config.clone()); + + // Construct an ECC chip + let ecc_chip = EccChip::construct(ecc_config); + + // Construct a NoteCommit chip + let note_commit_chip = NoteCommitChip::construct(note_commit_config.clone()); + + // Witness g_d + let g_d = { + let g_d = self.gd_x.zip(self.gd_y_lsb).map(|(x, y_lsb)| { + // Calculate y = (x^3 + 5).sqrt() + let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); + if bool::from(y.is_odd() ^ y_lsb.is_odd()) { + y = -y; + } + pallas::Affine::from_xy(x, y).unwrap() + }); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness g_d"), + g_d, + )? + }; + + // Witness pk_d + let pk_d = { + let pk_d = self.pkd_x.zip(self.pkd_y_lsb).map(|(x, y_lsb)| { + // Calculate y = (x^3 + 5).sqrt() + let mut y = (x.square() * x + pallas::Affine::b()).sqrt().unwrap(); + if bool::from(y.is_odd() ^ y_lsb.is_odd()) { + y = -y; + } + pallas::Affine::from_xy(x, y).unwrap() + }); + + NonIdentityPoint::new( + ecc_chip.clone(), + layouter.namespace(|| "witness pk_d"), + pk_d, + )? + }; + + // Witness a random non-negative u64 note value + // A note value cannot be negative. + let value = { + let mut rng = OsRng; + NoteValue::from_raw(rng.next_u64()) + }; + let value_var = { + assign_free_advice( + layouter.namespace(|| "witness value"), + note_commit_config.advices[0], + Value::known(value), + )? + }; + + // Witness rho + let rho = assign_free_advice( + layouter.namespace(|| "witness rho"), + note_commit_config.advices[0], + self.rho, + )?; + + // Witness psi + let psi = assign_free_advice( + layouter.namespace(|| "witness psi"), + note_commit_config.advices[0], + self.psi, + )?; + + let rcm = pallas::Scalar::random(OsRng); + let rcm_gadget = ScalarFixed::new( + ecc_chip.clone(), + layouter.namespace(|| "rcm"), + Value::known(rcm), + )?; + + let cm = gadgets::note_commit( + layouter.namespace(|| "Hash NoteCommit pieces"), + sinsemilla_chip, + ecc_chip.clone(), + note_commit_chip, + g_d.inner(), + pk_d.inner(), + value_var, + rho, + psi, + rcm_gadget, + None, + )?; + let expected_cm = { + let domain = CommitDomain::new(NOTE_COMMITMENT_PERSONALIZATION); + // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi + let lsb = |y_lsb: pallas::Base| y_lsb == pallas::Base::one(); + let point = self + .gd_x + .zip(self.gd_y_lsb) + .zip(self.pkd_x.zip(self.pkd_y_lsb)) + .zip(self.rho.zip(self.psi)) + .map(|(((gd_x, gd_y_lsb), (pkd_x, pkd_y_lsb)), (rho, psi))| { + domain + .commit( + iter::empty() + .chain( + gd_x.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ) + .chain(Some(lsb(gd_y_lsb))) + .chain( + pkd_x + .to_le_bits() + .iter() + .by_vals() + .take(L_ORCHARD_BASE), + ) + .chain(Some(lsb(pkd_y_lsb))) + .chain(value.to_le_bits().iter().by_vals().take(L_VALUE)) + .chain( + rho.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ) + .chain( + psi.to_le_bits().iter().by_vals().take(L_ORCHARD_BASE), + ), + &rcm, + ) + .unwrap() + .to_affine() + }); + NonIdentityPoint::new(ecc_chip, layouter.namespace(|| "witness cm"), point)? + }; + cm.constrain_equal(layouter.namespace(|| "cm == expected cm"), &expected_cm) + } + } + + let two_pow_254 = pallas::Base::from_u128(1 << 127).square(); + // Test different values of `ak`, `nk` + let circuits = [ + // `gd_x` = -1, `pkd_x` = -1 (these have to be x-coordinates of curve points) + // `rho` = 0, `psi` = 0 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(pallas::Base::zero()), + psi: Value::known(pallas::Base::zero()), + }, + // `rho` = T_Q - 1, `psi` = T_Q - 1 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(T_Q - 1)), + psi: Value::known(pallas::Base::from_u128(T_Q - 1)), + }, + // `rho` = T_Q, `psi` = T_Q + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(T_Q)), + psi: Value::known(pallas::Base::from_u128(T_Q)), + }, + // `rho` = 2^127 - 1, `psi` = 2^127 - 1 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + psi: Value::known(pallas::Base::from_u128((1 << 127) - 1)), + }, + // `rho` = 2^127, `psi` = 2^127 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::zero()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(pallas::Base::from_u128(1 << 127)), + psi: Value::known(pallas::Base::from_u128(1 << 127)), + }, + // `rho` = 2^254 - 1, `psi` = 2^254 - 1 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::one()), + rho: Value::known(two_pow_254 - pallas::Base::one()), + psi: Value::known(two_pow_254 - pallas::Base::one()), + }, + // `rho` = 2^254, `psi` = 2^254 + MyCircuit { + gd_x: Value::known(-pallas::Base::one()), + gd_y_lsb: Value::known(pallas::Base::one()), + pkd_x: Value::known(-pallas::Base::one()), + pkd_y_lsb: Value::known(pallas::Base::zero()), + rho: Value::known(two_pow_254), + psi: Value::known(two_pow_254), + }, + ]; + + for circuit in circuits.iter() { + let prover = MockProver::::run(11, circuit, vec![]).unwrap(); + assert_eq!(prover.verify(), Ok(())); + } + } + + #[test] + fn note_commit_zsa() { #[derive(Default)] struct MyCircuit { g_d: Value, @@ -2424,8 +2980,8 @@ mod tests { impl Circuit for MyCircuit { type Config = ( - NoteCommitConfig, - EccConfig, + NoteCommitConfig, + EccConfig, CondSwapConfig, ); type FloorPlanner = SimpleFloorPlanner; @@ -2474,7 +3030,7 @@ mod tests { meta.fixed_column(), ]; - let range_check = PallasLookupRangeCheck45BConfig::configure_with_tag( + let range_check = PallasLookupRangeCheck4_5BConfig::configure_with_tag( meta, advices[9], table_idx, @@ -2484,7 +3040,7 @@ mod tests { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, - PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheck4_5BConfig, >::configure( meta, advices[..5].try_into().unwrap(), @@ -2495,10 +3051,10 @@ mod tests { true, ); let note_commit_config = - NoteCommitChip::configure(meta, advices, sinsemilla_config); + NoteCommitChip::configure(meta, advices, sinsemilla_config, true); let ecc_config = - EccChip::::configure( + EccChip::::configure( meta, advices, lagrange_coeffs, @@ -2523,7 +3079,7 @@ mod tests { OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, - PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheck4_5BConfig, >::load( note_commit_config.sinsemilla_config.clone(), &mut layouter )?; @@ -2606,15 +3162,17 @@ mod tests { sinsemilla_chip, ecc_chip.clone(), note_commit_chip, - cond_swap_chip, g_d.inner(), pk_d.inner(), value_var, rho, psi, - asset.inner(), rcm_gadget, - is_native_asset, + Some(ZsaNoteCommitParams { + cond_swap_chip, + asset: asset.inner().clone(), + is_native_asset, + }), )?; let expected_cm = { // Hash g★_d || pk★_d || i2lebsp_{64}(v) || rho || psi diff --git a/src/circuit/circuit_zsa/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs similarity index 67% rename from src/circuit/circuit_zsa/value_commit_orchard.rs rename to src/circuit/value_commit_orchard.rs index a30b62d48..7d051013a 100644 --- a/src/circuit/circuit_zsa/value_commit_orchard.rs +++ b/src/circuit/value_commit_orchard.rs @@ -1,16 +1,32 @@ -//! Value commitment logic for the Orchard circuit (ZSA variation). +//! Value commitment logic for the Orchard circuit. + +use pasta_curves::pallas; + +use crate::constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}; + +use halo2_gadgets::utilities::lookup_range_check::PallasLookupRangeCheck; +use halo2_gadgets::{ + ecc::{chip::EccChip, NonIdentityPoint}, + sinsemilla::chip::SinsemillaChip, +}; + +pub struct ZsaValueCommitParams { + pub sinsemilla_chip: + SinsemillaChip, + pub asset: NonIdentityPoint>, +} pub(in crate::circuit) mod gadgets { - use pasta_curves::pallas; + use super::*; + + use crate::constants::{OrchardFixedBasesFull, ValueCommitV}; - use crate::constants::{ - OrchardCommitDomains, OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains, - }; use halo2_gadgets::{ - ecc::{chip::EccChip, FixedPoint, NonIdentityPoint, Point, ScalarFixed, ScalarVar}, - sinsemilla::{self, chip::SinsemillaChip}, - utilities::lookup_range_check::{LookupRangeCheck, PallasLookupRangeCheck45BConfig}, + ecc::{FixedPoint, FixedPointShort, Point, ScalarFixed, ScalarFixedShort, ScalarVar}, + sinsemilla, + utilities::lookup_range_check::PallasLookupRangeCheck, }; + use halo2_proofs::{ circuit::{AssignedCell, Chip, Layouter}, plonk, @@ -19,74 +35,83 @@ pub(in crate::circuit) mod gadgets { /// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. /// /// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit - pub(in crate::circuit) fn value_commit_orchard( + pub(in crate::circuit) fn value_commit_orchard( mut layouter: impl Layouter, - sinsemilla_chip: SinsemillaChip< - OrchardHashDomains, - OrchardCommitDomains, - OrchardFixedBases, - PallasLookupRangeCheck45BConfig, - >, - ecc_chip: EccChip, + ecc_chip: EccChip, v_net_magnitude_sign: ( AssignedCell, AssignedCell, ), - rcv: ScalarFixed< - pallas::Affine, - EccChip, - >, - asset: NonIdentityPoint< - pallas::Affine, - EccChip, - >, - ) -> Result< - Point>, - plonk::Error, - > { - // Check that magnitude is 64 bits. - { - let lookup_config = sinsemilla_chip.config().lookup_config(); - let (magnitude_words, magnitude_extra_bits) = (6, 4); - assert_eq!( - magnitude_words * sinsemilla::primitives::K + magnitude_extra_bits, - 64 - ); - let magnitude_zs = lookup_config.copy_check( - layouter.namespace(|| "magnitude lowest 60 bits"), - v_net_magnitude_sign.0.clone(), - magnitude_words, // 6 windows of 10 bits. - false, // Do not constrain the result here. - )?; - assert_eq!(magnitude_zs.len(), magnitude_words + 1); - lookup_config.copy_short_check( - layouter.namespace(|| "magnitude highest 4 bits"), - magnitude_zs[magnitude_words].clone(), - magnitude_extra_bits, // The 7th window must be a 4 bits value. - )?; - } + rcv: ScalarFixed>, + zsa_params: Option>, + ) -> Result>, plonk::Error> { + // Evaluate commitment = [v_net_magnitude_sign] asset + let commitment = match zsa_params { + None => { + let v_net = ScalarFixedShort::new( + ecc_chip.clone(), + layouter.namespace(|| "v_net"), + v_net_magnitude_sign, + )?; - // Multiply asset by magnitude, using the long scalar mul. - // TODO: implement a new variable base multiplication which is optimized for 64-bit scalar - // (the long scalar mul is optimized for pallas::Base scalar (~255-bits)) - // - // commitment = [magnitude] asset - let commitment = { - let magnitude_scalar = ScalarVar::from_base( - ecc_chip.clone(), - layouter.namespace(|| "magnitude"), - &v_net_magnitude_sign.0, - )?; - let (commitment, _) = - asset.mul(layouter.namespace(|| "[magnitude] asset"), magnitude_scalar)?; - commitment - }; + // commitment = [v_net] ValueCommitV + let (commitment, _) = { + let value_commit_v = ValueCommitV; + let value_commit_v = + FixedPointShort::from_inner(ecc_chip.clone(), value_commit_v); + value_commit_v.mul(layouter.namespace(|| "[v] ValueCommitV"), v_net)? + }; + commitment + } + Some(params) => { + // Check that magnitude is 64 bits + // Note: if zsa_params is not provided, this check will be performed inside the + // fixed-base short scalar multiplication. + { + let lookup_config = params.sinsemilla_chip.config().lookup_config(); + let (magnitude_words, magnitude_extra_bits) = (6, 4); + assert_eq!( + magnitude_words * sinsemilla::primitives::K + magnitude_extra_bits, + 64 + ); + let magnitude_zs = lookup_config.copy_check( + layouter.namespace(|| "magnitude lowest 60 bits"), + v_net_magnitude_sign.0.clone(), + magnitude_words, // 6 windows of 10 bits. + false, // Do not constrain the result here. + )?; + assert_eq!(magnitude_zs.len(), magnitude_words + 1); + lookup_config.copy_short_check( + layouter.namespace(|| "magnitude highest 4 bits"), + magnitude_zs[magnitude_words].clone(), + magnitude_extra_bits, // The 7th window must be a 4 bits value. + )?; + } + + // Multiply asset by magnitude, using the long scalar mul. + // TODO: implement a new variable base multiplication which is optimized for 64-bit scalar + // (the long scalar mul is optimized for pallas::Base scalar (~255-bits)) + // + // magnitude_asset = [magnitude] asset + let magnitude_asset = { + let magnitude_scalar = ScalarVar::from_base( + ecc_chip.clone(), + layouter.namespace(|| "magnitude"), + &v_net_magnitude_sign.0, + )?; + let (magnitude_asset, _) = params + .asset + .mul(layouter.namespace(|| "[magnitude] asset"), magnitude_scalar)?; + magnitude_asset + }; - // signed_commitment = [sign] commitment = [v_net_magnitude_sign] asset - let signed_commitment = commitment.mul_sign( - layouter.namespace(|| "[sign] commitment"), - &v_net_magnitude_sign.1, - )?; + // commitment = [sign] magnitude_asset = [v_net_magnitude_sign] asset + magnitude_asset.mul_sign( + layouter.namespace(|| "[sign] commitment"), + &v_net_magnitude_sign.1, + )? + } + }; // blind = [rcv] ValueCommitR let (blind, _rcv) = { @@ -98,14 +123,15 @@ pub(in crate::circuit) mod gadgets { }; // [v] ValueCommitV + [rcv] ValueCommitR - signed_commitment.add(layouter.namespace(|| "cv"), &blind) + commitment.add(layouter.namespace(|| "cv"), &blind) } } #[cfg(test)] mod tests { use crate::{ - circuit::circuit_zsa::gadget::{assign_free_advice, value_commit_orchard}, + circuit::gadget::assign_free_advice, + circuit::value_commit_orchard::gadgets::value_commit_orchard, circuit::K, constants::{OrchardCommitDomains, OrchardFixedBases, OrchardHashDomains}, note::AssetBase, @@ -118,7 +144,7 @@ mod tests { }, sinsemilla::chip::{SinsemillaChip, SinsemillaConfig}, utilities::lookup_range_check::{ - LookupRangeCheck45BConfig, PallasLookupRangeCheck45BConfig, + LookupRangeCheck4_5BConfig, PallasLookupRangeCheck4_5BConfig, }, }; @@ -130,6 +156,7 @@ mod tests { }; use pasta_curves::pallas; + use crate::circuit::value_commit_orchard::ZsaValueCommitParams; use rand::{rngs::OsRng, RngCore}; #[test] @@ -138,14 +165,14 @@ mod tests { pub struct MyConfig { primary: Column, advices: [Column; 10], - ecc_config: EccConfig, + ecc_config: EccConfig, // Sinsemilla config is only used to initialize the table_idx lookup table in the same // way as in the Orchard circuit sinsemilla_config: SinsemillaConfig< OrchardHashDomains, OrchardCommitDomains, OrchardFixedBases, - PallasLookupRangeCheck45BConfig, + PallasLookupRangeCheck4_5BConfig, >, } #[derive(Default)] @@ -207,7 +234,7 @@ mod tests { ]; meta.enable_constant(lagrange_coeffs[0]); - let range_check = LookupRangeCheck45BConfig::configure_with_tag( + let range_check = LookupRangeCheck4_5BConfig::configure_with_tag( meta, advices[9], table_idx, @@ -228,7 +255,7 @@ mod tests { primary, advices, ecc_config: - EccChip::::configure( + EccChip::::configure( meta, advices, lagrange_coeffs, @@ -307,11 +334,13 @@ mod tests { // Evaluate cv_net with value_commit_orchard let cv_net = value_commit_orchard( layouter.namespace(|| "cv_net = ValueCommit^Orchard_rcv(v_net)"), - sinsemilla_chip, ecc_chip, v_net_magnitude_sign, rcv, - asset, + Some(ZsaValueCommitParams { + sinsemilla_chip, + asset, + }), )?; // Constrain cv_net to equal public input From e2fb49d5e4ca0db0d52a8faf939e97573062d1ba Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Tue, 8 Oct 2024 20:15:50 +0530 Subject: [PATCH 73/92] Updating test vectors (#114) This updates the test vectors in this repository to match those created in https://github.com/QED-it/zcash-test-vectors/pull/22. --- src/test_vectors/asset_base.rs | 1714 +++++++++---------- src/test_vectors/keys.rs | 1048 ++++++------ src/test_vectors/note_encryption_vanilla.rs | 1450 ++++++++-------- src/test_vectors/note_encryption_zsa.rs | 20 - 4 files changed, 2101 insertions(+), 2131 deletions(-) diff --git a/src/test_vectors/asset_base.rs b/src/test_vectors/asset_base.rs index 4cfaa0207..b054359f2 100644 --- a/src/test_vectors/asset_base.rs +++ b/src/test_vectors/asset_base.rs @@ -15,1017 +15,1017 @@ pub(crate) fn test_vectors() -> Vec { 0x51, 0x6d, 0x9f, 0x31, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc2, 0xb9, 0xc3, 0x8b, 0xe1, 0x9a, 0xa4, 0xe1, 0x9b, 0x99, 0xc3, 0xbc, 0xc4, 0xad, + 0xc3, 0x8d, 0xce, 0x89, 0xc8, 0xa1, 0xc7, 0xb1, 0xc4, 0x9d, 0xc4, 0xa0, 0xc3, 0x99, + 0xc7, 0x97, 0xc3, 0xac, 0xc3, 0x8c, 0xe1, 0x9b, 0xa2, 0xc4, 0x86, 0xc4, 0x94, 0x3f, + 0xc7, 0xa6, 0xc4, 0xbb, 0x6a, 0xc2, 0xa6, 0xc7, 0xb4, 0xc6, 0x88, 0xc3, 0x8a, 0xc3, + 0xba, 0xc9, 0x8c, 0xe2, 0xb1, 0xaa, 0xc5, 0x9b, 0xe1, 0x9b, 0xa9, 0xc4, 0xb4, 0xc8, + 0x91, 0xc3, 0x8c, 0xc4, 0x92, 0x30, 0xc5, 0xa9, 0xce, 0x84, 0xc5, 0x90, 0x73, 0xe2, + 0xb1, 0xaa, 0xe2, 0xb1, 0xb8, 0xc5, 0xa3, 0xc3, 0x84, 0xe1, 0x9b, 0x83, 0xc7, 0xb1, + 0xc3, 0xb1, 0xc4, 0x94, 0xc6, 0xbe, 0x69, 0x44, 0xc7, 0xbd, 0xc8, 0xb9, 0xc7, 0x84, + 0xc3, 0xa9, 0xc7, 0x88, 0xc5, 0x8d, 0xc7, 0x91, 0xc9, 0x8a, 0xc3, 0xb9, 0xc4, 0xb1, + 0xc3, 0xb6, 0xc6, 0x82, 0xe1, 0x9b, 0x8f, 0xc4, 0x88, 0xe2, 0xb1, 0xba, 0xc7, 0xb5, + 0x42, 0xc4, 0xa9, 0xc4, 0x90, 0x61, 0xc6, 0x90, 0xc6, 0xb5, 0xc7, 0x9e, 0xc2, 0xb2, + 0xc9, 0x85, 0xc3, 0x9e, 0xc9, 0x84, 0xe2, 0xb1, 0xab, 0xc4, 0x98, 0xe1, 0x9a, 0xa3, + 0xc8, 0x91, 0xe1, 0x9a, 0xbc, 0xc7, 0xba, 0xc3, 0xa9, 0xc7, 0xb1, 0xc4, 0xbf, 0xc8, + 0xa2, 0xc5, 0xb3, 0xc8, 0xa4, 0xc4, 0xb2, 0xc4, 0xb7, 0x45, 0x32, 0xc8, 0x83, 0xc7, + 0xa6, 0xe1, 0x9a, 0xab, 0xc5, 0x88, 0xc8, 0x88, 0xc3, 0x92, 0xe2, 0xb1, 0xac, 0xc9, + 0x8a, 0x25, 0xc8, 0x98, 0xc6, 0xbc, 0xc6, 0xb6, 0x7a, 0xc4, 0xa6, 0xc7, 0xa3, 0xc4, + 0x8f, 0xe1, 0x9a, 0xb0, 0xc2, 0xaf, 0xe1, 0x9b, 0xaf, 0xc3, 0x8c, 0xc2, 0xbf, 0xc5, + 0xb5, 0xe2, 0xb1, 0xa1, 0xe1, 0x9b, 0xa3, 0xc8, 0x8f, 0x6c, 0xc3, 0xa2, 0xc4, 0x8c, + 0xc3, 0xb4, 0xe2, 0xb1, 0xab, 0x7c, 0xc8, 0x93, 0xc9, 0x8c, 0xc6, 0x8d, 0xc9, 0x8c, + 0xc8, 0xb3, 0xc7, 0x96, 0xc7, 0xa0, 0xc7, 0x9f, 0x69, 0xc6, 0x97, 0xc4, 0xbd, 0xe2, + 0xb1, 0xb5, 0xc6, 0xa4, 0xe1, 0x9b, 0x83, 0xe1, 0x9b, 0x83, 0xe2, 0xb1, 0xaa, 0xc7, + 0x85, 0xe2, 0xb1, 0xaf, 0x7d, 0xc6, 0x9b, 0xc2, 0xa5, 0xc7, 0x9c, 0xc5, 0xaf, 0xc7, + 0x97, 0xc8, 0x9e, 0xc3, 0x91, 0xc2, 0xa2, 0xc7, 0x9f, 0xc4, 0xbf, 0x62, 0xc3, 0x8e, + 0xc5, 0xbd, 0xc8, 0xb3, 0xcd, 0xb6, 0xc4, 0x95, 0x39, 0xc3, 0xa4, 0xe1, 0x9b, 0xad, + 0xe1, 0x9b, 0x84, 0xc8, 0xad, 0x42, 0xc8, 0xa1, 0x34, 0xc4, 0xbd, 0x6b, 0xc3, 0x83, + 0xc7, 0xa8, 0x48, 0x5e, 0xc5, 0x97, 0xc8, 0xb5, 0xc6, 0xa4, 0xc6, 0x94, 0xc7, 0x98, + 0xc6, 0xb2, 0xc4, 0x9a, 0x46, 0xc6, 0xad, 0xe1, 0x9b, 0x83, 0xc4, 0x8b, 0x3c, 0xc6, + 0x98, 0xc9, 0x8e, 0xc2, 0xbc, 0xc3, 0x80, 0xc7, 0x83, 0x6f, 0x63, 0xe1, 0x9b, 0xa0, + 0xc4, 0x94, 0xe1, 0x9a, 0xbc, 0xc3, 0xa9, 0xe1, 0x9a, 0xa4, 0xc5, 0x8c, 0xc8, 0x94, + 0xc7, 0xa3, 0xce, 0x87, 0xc9, 0x82, 0xe2, 0xb1, 0xa6, 0xc4, 0x81, 0xc4, 0xa8, 0xc6, + 0xb5, 0xc7, 0x93, 0xe1, 0x9b, 0x8c, 0xc5, 0x87, 0xc4, 0x97, 0xc7, 0x93, 0x4a, 0xc5, + 0x9e, 0xc9, 0x84, 0xe2, 0xb1, 0xa0, 0xc4, 0xab, 0xc7, 0x83, 0xc6, 0x88, 0xc5, 0xaa, + 0xc5, 0xa1, 0xe1, 0x9b, 0x86, 0xc7, 0x82, 0xe2, 0xb1, 0xa5, 0xc3, 0x9e, 0xc7, 0xbc, + 0xc6, 0x8b, 0x46, 0xe1, 0x9a, 0xa9, 0xc6, 0x95, 0xc4, 0xa7, 0xc6, 0x8d, 0xe1, 0x9b, + 0x8d, 0xc7, 0x95, 0xc3, 0xaf, 0xc6, 0x9a, 0xe2, 0xb1, 0xba, 0xc3, 0xaa, 0xc7, 0x82, + 0xe1, 0x9b, 0x9d, 0xc9, 0x80, 0x25, 0xc7, 0x8d, 0x28, 0x46, 0xe2, 0xb1, 0xb5, 0xc6, + 0x8b, 0xe2, 0xb1, 0xb4, 0xc3, 0x85, 0xc8, 0xbe, ], asset_base: [ - 0xa7, 0x62, 0x5a, 0x60, 0xff, 0x6a, 0xdc, 0x49, 0x8a, 0xc2, 0xf5, 0x7b, 0x4d, 0xbe, - 0xd3, 0x67, 0x26, 0xba, 0xe6, 0x40, 0x1f, 0x3e, 0x01, 0xc2, 0x61, 0x17, 0x0b, 0x02, - 0x81, 0x0f, 0x08, 0x19, + 0xb2, 0x5c, 0xbe, 0xdd, 0x3c, 0xae, 0xa0, 0x46, 0x24, 0x08, 0x21, 0xa9, 0x22, 0xcd, + 0xae, 0xb7, 0xfe, 0xcc, 0x4f, 0xed, 0x1d, 0x60, 0xc1, 0x61, 0x57, 0x9c, 0xd9, 0xcf, + 0x4e, 0x0c, 0xc9, 0x1f, ], }, TestVector { key: [ - 0x16, 0x88, 0x4f, 0x1d, 0xbc, 0x92, 0x90, 0x89, 0xa4, 0x17, 0x6e, 0x84, 0x0b, 0xb5, - 0x81, 0xc8, 0x0e, 0x16, 0xe9, 0xb1, 0xab, 0xd6, 0x54, 0xe6, 0x2c, 0x8b, 0x0b, 0x95, - 0x70, 0x20, 0xb7, 0x48, + 0xd5, 0x9a, 0x54, 0xb2, 0x87, 0x10, 0x58, 0xe8, 0xdf, 0x0e, 0x8d, 0xb3, 0x15, 0x6f, + 0xb5, 0x60, 0xd9, 0x8d, 0xa4, 0xdb, 0x99, 0x04, 0x2c, 0xe9, 0x85, 0x2f, 0x4b, 0x08, + 0xb1, 0xf4, 0x9f, 0xaa, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xe1, 0x9b, 0x93, 0xc6, 0xab, 0xe1, 0x9b, 0x88, 0xc2, 0xb5, 0x24, 0xc6, 0x85, 0xe2, + 0xb1, 0xae, 0xe1, 0x9a, 0xbe, 0xc6, 0x9c, 0xc5, 0xb1, 0xc3, 0xad, 0xc6, 0xaa, 0xc3, + 0xaf, 0xc3, 0x9d, 0xc2, 0xab, 0xc7, 0x9b, 0xc6, 0xad, 0xc3, 0xb3, 0xc7, 0xbe, 0xe1, + 0x9b, 0xac, 0xc7, 0x91, 0xc8, 0x9d, 0xc9, 0x82, 0xc4, 0xae, 0xc4, 0x81, 0xe1, 0x9b, + 0xa8, 0xc6, 0x84, 0xe2, 0xb1, 0xb0, 0xc5, 0x86, 0x61, 0xc6, 0x95, 0xcd, 0xb4, 0xc2, + 0xbd, 0xc6, 0xb4, 0xc4, 0x84, 0xc7, 0x97, 0xe2, 0xb1, 0xb6, 0xc9, 0x8a, 0xe1, 0x9a, + 0xbb, 0xcd, 0xbc, 0xcd, 0xb6, 0xc8, 0xbc, 0xe1, 0x9b, 0xb0, 0xe2, 0xb1, 0xa5, 0xc7, + 0x89, 0xe1, 0x9b, 0x92, 0xc5, 0xad, 0xe2, 0xb1, 0xad, 0xc3, 0x85, 0xe1, 0x9a, 0xbb, + 0xc7, 0xb3, 0xc6, 0xb4, 0xc5, 0xaf, 0xc5, 0x92, 0xe1, 0x9a, 0xb8, 0xc3, 0x88, 0xc2, + 0xb7, 0xe1, 0x9a, 0xab, 0xc8, 0xb2, 0xc7, 0x96, 0xc6, 0xb3, 0xe1, 0x9b, 0x89, 0x31, + 0xe1, 0x9a, 0xa7, 0xc4, 0x89, 0xc4, 0x96, 0x5d, 0xe1, 0x9b, 0xa6, 0xc4, 0x84, 0xc6, + 0x8d, 0xc7, 0xb9, 0xc8, 0x94, 0xe1, 0x9b, 0x8b, 0xc9, 0x8b, 0xc3, 0xb0, 0x44, 0x6f, + 0xce, 0x86, 0x71, 0xc6, 0xb2, 0xe1, 0x9a, 0xbf, 0xc6, 0x80, 0xc5, 0x98, 0xc4, 0xbd, + 0xc6, 0xbb, 0xc7, 0xad, 0xc5, 0xbb, 0x77, 0xc2, 0xb8, 0xc2, 0xb5, 0xc8, 0xbd, 0xc3, + 0xb1, 0xc8, 0x84, 0xcd, 0xb2, 0xc6, 0xa2, 0x7c, 0xc5, 0x81, 0x4f, 0xc5, 0xab, 0xc4, + 0xa5, 0xc4, 0xb6, 0xc3, 0x81, 0xc6, 0xba, 0xc4, 0x84, 0xe2, 0xb1, 0xa8, 0xc4, 0x9e, + 0xe1, 0x9b, 0xae, 0xc5, 0x9a, 0xc5, 0xa2, 0xc2, 0xbe, 0xc8, 0xb9, 0xe2, 0xb1, 0xb2, + 0xe2, 0xb1, 0xb9, 0xc8, 0xa8, 0x2c, 0xe1, 0x9b, 0x9d, 0xc3, 0xaf, 0xc3, 0x98, 0xc4, + 0x9d, 0xe1, 0x9b, 0x85, 0x55, 0xc8, 0x89, 0xc6, 0x8f, 0xc4, 0xb6, 0xc6, 0xab, 0xc6, + 0xaa, 0xc6, 0xb8, 0x32, 0xc4, 0x88, 0xc6, 0x95, 0xc7, 0x93, 0xc6, 0xa1, 0xc2, 0xb3, + 0xc4, 0xb3, 0xc5, 0x80, 0xc5, 0x93, 0x7a, 0xc5, 0xa4, 0x66, 0xc4, 0xa1, 0x47, 0x44, + 0xe1, 0x9a, 0xb5, 0x7d, 0xc6, 0xab, 0xc2, 0xa2, 0xc6, 0x86, 0xc8, 0x8b, 0xc8, 0x8d, + 0xc8, 0xa7, 0xc8, 0xae, 0xc3, 0xb6, 0xc8, 0xac, 0x24, 0x3d, 0xcd, 0xbc, 0xc3, 0x8f, + 0xc5, 0xbb, 0xc8, 0x92, 0xc3, 0xba, 0xc4, 0x84, 0xe1, 0x9a, 0xbb, 0xc5, 0x83, 0x6b, + 0x41, 0xc6, 0xb8, 0xc4, 0x9d, 0xc7, 0x89, 0xe1, 0x9b, 0x9c, 0x45, 0xc7, 0xb0, 0xc2, + 0xa3, 0xe1, 0x9a, 0xa4, 0xc8, 0x94, 0xc8, 0x92, 0xc9, 0x8e, 0x71, 0xc7, 0x8a, 0x5b, + 0xe1, 0x9b, 0xaa, 0xc6, 0xaf, 0xe1, 0x9b, 0xab, 0xe1, 0x9b, 0x9e, 0xe1, 0x9b, 0x83, + 0xc8, 0x9f, 0xe2, 0xb1, 0xb6, 0xe1, 0x9a, 0xb7, 0xc2, 0xa7, 0xc4, 0x83, 0x2f, 0xc2, + 0xae, 0xe2, 0xb1, 0xaf, 0xe1, 0x9a, 0xa1, 0xe1, 0x9a, 0xbe, 0x66, 0x3b, 0xc8, 0xaf, + 0xc8, 0xbd, 0xc7, 0xb8, 0xc9, 0x8d, 0xc5, 0x89, 0xc5, 0xa5, 0xe1, 0x9a, 0xae, 0xc8, + 0xa1, 0xc6, 0x8b, 0xc2, 0xa5, 0xc9, 0x80, 0xe2, 0xb1, 0xa4, 0xc3, 0xba, 0xe2, 0xb1, + 0xb7, 0xc5, 0x92, 0xc4, 0x9b, 0xc7, 0x87, 0xc6, 0xb5, 0xc5, 0xb3, 0xc6, 0x9c, 0x3c, + 0xc6, 0x9e, 0xc4, 0x9b, 0xc8, 0xa9, 0xc5, 0x8c, 0xe1, 0x9b, 0x90, 0xc7, 0xa8, 0xc7, + 0x9d, 0xc8, 0x9b, 0xc7, 0xb2, 0xe2, 0xb1, 0xae, 0xc6, 0x90, 0xc6, 0x8e, 0x70, 0xe1, + 0x9b, 0xa7, 0x32, 0xc5, 0x85, 0x66, 0xc5, 0xbb, 0xc7, 0xb8, 0xc7, 0x8b, 0xc8, 0xb1, + 0xc8, 0xaa, 0xc5, 0x8c, 0xc8, 0x82, 0xc6, 0xb2, 0xcd, 0xb7, 0xe1, 0x9b, 0x93, 0xc6, + 0x9e, 0xe1, 0x9b, 0x90, 0x4d, 0x70, 0xc8, 0xaf, ], asset_base: [ - 0xb9, 0xfc, 0x57, 0x2c, 0x5a, 0xd8, 0x81, 0x26, 0xff, 0x6b, 0x7c, 0x65, 0x9f, 0x78, - 0x74, 0x91, 0xf7, 0xc2, 0x7c, 0x5f, 0xe4, 0xff, 0x24, 0x20, 0x8a, 0x02, 0xbc, 0x94, - 0x5e, 0x55, 0x4a, 0xbf, + 0xbd, 0x7f, 0x79, 0xe7, 0xda, 0xdd, 0x1d, 0x48, 0x27, 0x06, 0x04, 0xcd, 0xdb, 0x1d, + 0x65, 0x44, 0x09, 0x29, 0xea, 0x25, 0xe7, 0x7b, 0x72, 0x85, 0x5f, 0xf6, 0xfd, 0x99, + 0x18, 0xa5, 0x91, 0xb6, ], }, TestVector { key: [ - 0xd4, 0x22, 0x9e, 0x19, 0x5e, 0x25, 0xf6, 0x02, 0xa2, 0x18, 0x61, 0x22, 0xcb, 0x4e, - 0x78, 0x76, 0x7b, 0x3c, 0x66, 0xac, 0x39, 0x08, 0x08, 0xd2, 0xd1, 0xb4, 0x04, 0x42, - 0xda, 0x7f, 0x00, 0x66, + 0x85, 0xbc, 0x7d, 0x64, 0xbe, 0x0d, 0xef, 0xc4, 0x77, 0xeb, 0x05, 0xe7, 0x95, 0xf7, + 0x69, 0x57, 0x62, 0x80, 0x02, 0x61, 0x62, 0x5a, 0x7b, 0x71, 0xa1, 0x4d, 0x18, 0xf0, + 0xef, 0x1f, 0x01, 0xb0, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc7, 0x96, 0xcd, 0xb7, 0xc3, 0x9b, 0xc7, 0x8d, 0xc4, 0x92, 0x7b, 0xcd, 0xb4, 0x34, + 0xc3, 0x84, 0xcd, 0xb6, 0xc2, 0xbc, 0x3d, 0xc6, 0xa7, 0xc8, 0xbc, 0xe1, 0x9b, 0x9f, + 0xc3, 0xbd, 0xc8, 0x9a, 0xc5, 0x81, 0xc4, 0xb7, 0x6c, 0xc5, 0xb3, 0xe1, 0x9a, 0xa5, + 0xe1, 0x9b, 0xa6, 0x44, 0xe1, 0x9b, 0xa4, 0xc5, 0xbc, 0xe1, 0x9b, 0x99, 0xc6, 0x91, + 0xc8, 0x9c, 0xc6, 0x93, 0xc5, 0x95, 0xc4, 0xa2, 0xe2, 0xb1, 0xa2, 0xc8, 0x84, 0x45, + 0xc2, 0xaa, 0x7e, 0xc2, 0xb7, 0xc3, 0x83, 0x66, 0xc4, 0x81, 0xc7, 0x98, 0xc8, 0x83, + 0x2b, 0xc6, 0xad, 0xc7, 0x9c, 0xc4, 0x8b, 0xe2, 0xb1, 0xaa, 0x78, 0xc4, 0xa8, 0xc4, + 0x86, 0xc6, 0x9a, 0xc8, 0xa2, 0x35, 0xc3, 0x81, 0xc6, 0x8f, 0xc6, 0x9b, 0xe1, 0x9b, + 0x93, 0xc6, 0x8c, 0xe1, 0x9b, 0x8e, 0xc4, 0xb1, 0xc6, 0xbc, 0xe2, 0xb1, 0xb3, 0x5a, + 0xc5, 0x98, 0xc6, 0xaa, 0xc4, 0xae, 0xc8, 0xa1, 0xe1, 0x9a, 0xbb, 0xc7, 0xad, 0xc5, + 0xae, 0xc5, 0xaa, 0xc6, 0x85, 0xc2, 0xb2, 0xe1, 0x9b, 0x9e, 0xc7, 0xb4, 0x6b, 0xc4, + 0xaf, 0xc7, 0xa9, 0xc4, 0xa6, 0xc8, 0xa8, 0xc4, 0x9e, 0xcd, 0xb1, 0xc7, 0xad, 0xc3, + 0xb8, 0xc3, 0x81, 0xc3, 0xa4, 0xc8, 0x98, 0xc3, 0xbd, 0xc4, 0xae, 0xe1, 0x9b, 0x84, + 0xc8, 0x8e, 0x6a, 0xc4, 0x96, 0xe1, 0x9a, 0xa6, 0xc6, 0x90, 0xe1, 0x9a, 0xbe, 0xc7, + 0xa1, 0x2b, 0xcd, 0xb2, 0xc8, 0xa5, 0xc7, 0x87, 0xc7, 0x95, 0x32, 0xc8, 0xa8, 0xc9, + 0x85, 0xc5, 0x84, 0xc5, 0x99, 0xc7, 0x9f, 0x63, 0x42, 0xc6, 0xb6, 0x42, 0x79, 0xc7, + 0x90, 0xc5, 0x9d, 0xe2, 0xb1, 0xb7, 0xc4, 0xab, 0xc5, 0xbf, 0xc3, 0xaf, 0x35, 0x49, + 0xc6, 0xb9, 0xe1, 0x9b, 0x88, 0xc5, 0xbe, 0xc3, 0xb1, 0x23, 0xe2, 0xb1, 0xa3, 0xc5, + 0x96, 0xc8, 0x8c, 0xe1, 0x9b, 0xa7, 0xc5, 0xa8, 0xc8, 0x95, 0xc7, 0xa6, 0xc8, 0xa7, + 0xe1, 0x9a, 0xaf, 0xc3, 0xa0, 0xc5, 0x82, 0xc6, 0x83, 0x70, 0xe2, 0xb1, 0xb1, 0xc8, + 0x86, 0xc7, 0xb4, 0xe1, 0x9b, 0x8b, 0xe1, 0x9a, 0xb3, 0xc5, 0xa2, 0xc3, 0x96, 0xc3, + 0xbd, 0xc9, 0x87, 0xc2, 0xa5, 0xce, 0x88, 0xc3, 0xa3, 0xe1, 0x9b, 0xa8, 0xc4, 0x8f, + 0xe1, 0x9a, 0xbf, 0xe1, 0x9b, 0x8b, 0xc2, 0xb3, 0xc3, 0xb7, 0xc6, 0xa1, 0xc5, 0x88, + 0xe1, 0x9b, 0xa3, 0xc6, 0xa3, 0xc3, 0x8c, 0xc3, 0xa4, 0xc6, 0xa1, 0xe1, 0x9b, 0x87, + 0xc8, 0xa0, 0xc3, 0x94, 0xc6, 0x9a, 0xc7, 0xb1, 0xc5, 0x85, 0xc6, 0xbf, 0xc8, 0x91, + 0xc6, 0x88, 0xc4, 0x9e, 0xc6, 0x9a, 0xcd, 0xb1, 0xc4, 0xa6, 0xc6, 0xb0, 0xc3, 0xbc, + 0x23, 0xc4, 0x9b, 0xc3, 0xa4, 0xc8, 0xb3, 0xe2, 0xb1, 0xa3, 0x73, 0xc6, 0xb6, 0xc8, + 0xb0, 0xc8, 0xb4, 0xc7, 0xa8, 0xc8, 0xa7, 0xc6, 0x80, 0xc4, 0xb0, 0xc7, 0xaf, 0x6c, + 0xc8, 0xbb, 0xc4, 0x81, 0xc3, 0x93, 0xc7, 0x8c, 0xc7, 0xb4, 0xe1, 0x9b, 0x9c, 0xc4, + 0xa1, 0xc6, 0xa8, 0xc7, 0xbc, 0xc3, 0x9d, 0xc4, 0x8a, 0xc6, 0x82, 0xc6, 0x9c, 0xc7, + 0xb4, 0xc3, 0x83, 0xc8, 0xae, 0xc3, 0x93, 0xe1, 0x9a, 0xab, 0xc7, 0x8a, 0xc7, 0xb5, + 0xc2, 0xbc, 0xc4, 0x92, 0xc3, 0x9b, 0xc7, 0x8c, 0xc5, 0xa3, 0xc9, 0x84, 0xc4, 0xb5, + 0xc3, 0xba, 0xc6, 0xb3, 0x46, 0xc7, 0x8f, 0xe1, 0x9a, 0xab, 0xc8, 0x8d, 0xc7, 0xac, + 0x40, 0xc7, 0xbd, 0xc8, 0xa1, 0xc4, 0xa8, 0xc4, 0x86, 0xc3, 0xaa, 0xc4, 0xbc, 0xc6, + 0x80, 0x76, 0xc7, 0xb0, 0xc4, 0x85, 0xc5, 0xb7, 0x2a, 0xc4, 0xb7, 0xc2, 0xb6, 0xc8, + 0xa8, 0xc6, 0xa6, 0x6f, 0xc4, 0xad, 0xc8, 0x90, 0xc4, 0xb9, 0xc8, 0x9a, 0xc6, 0x95, + 0xc5, 0x80, 0xc3, 0xa5, 0xe1, 0x9b, 0x83, 0x5a, ], asset_base: [ - 0x69, 0x03, 0x15, 0xe6, 0xb7, 0xbb, 0xbc, 0x9d, 0x88, 0x60, 0x17, 0xfd, 0x0e, 0xb1, - 0x38, 0x67, 0x16, 0xc2, 0xb4, 0x3f, 0x43, 0xf9, 0xa1, 0xc5, 0x42, 0x74, 0xd7, 0x4a, - 0x50, 0xbc, 0x22, 0x8d, + 0x6f, 0x2d, 0x95, 0xed, 0x1d, 0x96, 0x0b, 0x7a, 0xe1, 0xcf, 0x9c, 0x0b, 0x66, 0xe8, + 0x5a, 0xdd, 0x2c, 0xf1, 0xcd, 0x44, 0x6e, 0x02, 0x74, 0x51, 0x2e, 0x3b, 0x99, 0x6d, + 0x8e, 0xe7, 0x77, 0xa2, ], }, TestVector { key: [ - 0x72, 0x73, 0xb6, 0x57, 0xd9, 0x71, 0xa4, 0x5e, 0x72, 0x24, 0x0c, 0x7a, 0xaa, 0xa7, - 0xd0, 0x68, 0x5d, 0x06, 0xd7, 0x99, 0x9b, 0x0a, 0x19, 0xc4, 0xce, 0xa3, 0x27, 0x88, - 0xa6, 0xab, 0x51, 0x3d, + 0xd7, 0x5a, 0xf5, 0x78, 0x2a, 0x5c, 0x72, 0x16, 0x38, 0xf7, 0x59, 0x32, 0x91, 0x11, + 0x49, 0x93, 0x24, 0x05, 0x3a, 0x5d, 0x1e, 0x1b, 0x2a, 0x4a, 0xb3, 0xcd, 0xf7, 0xf8, + 0x24, 0x12, 0xff, 0x42, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc3, 0xa1, 0xc7, 0xa6, 0xc4, 0xa7, 0xc5, 0xa9, 0x37, 0xc4, 0x87, 0xc7, 0xb0, 0xe1, + 0x9a, 0xa1, 0xe2, 0xb1, 0xa1, 0xc6, 0x83, 0xc3, 0xa9, 0xc6, 0xa9, 0xc8, 0x82, 0xe2, + 0xb1, 0xab, 0xc4, 0xa5, 0xe1, 0x9b, 0x99, 0xc6, 0x9e, 0xe1, 0x9a, 0xaa, 0xc8, 0xa0, + 0xc8, 0xa2, 0xc4, 0x93, 0xe1, 0x9b, 0x83, 0xe1, 0x9b, 0x92, 0xe1, 0x9b, 0x86, 0xc5, + 0xb5, 0xc2, 0xb4, 0xc5, 0x97, 0xc6, 0x87, 0xc4, 0x9a, 0xe1, 0x9b, 0x85, 0xc8, 0x91, + 0xe1, 0x9a, 0xa7, 0xc6, 0xa1, 0xc3, 0x81, 0xc6, 0xab, 0xc5, 0x93, 0xc6, 0xb6, 0xc7, + 0x86, 0x3f, 0xcd, 0xb5, 0xe2, 0xb1, 0xa5, 0xc7, 0x86, 0xc5, 0x88, 0xc2, 0xa5, 0xc3, + 0xa5, 0xce, 0x87, 0xc5, 0x8c, 0xc5, 0x9d, 0xe1, 0x9b, 0xa7, 0x70, 0xc3, 0x98, 0xc2, + 0xb7, 0xe1, 0x9b, 0xb0, 0xc4, 0x85, 0xc6, 0x82, 0xc3, 0x85, 0xc4, 0x9c, 0xe1, 0x9b, + 0x9d, 0x2c, 0xc4, 0xa6, 0xc9, 0x86, 0xe1, 0x9b, 0xab, 0xc3, 0xb6, 0xc7, 0xad, 0xc5, + 0xbb, 0xe1, 0x9a, 0xa4, 0x39, 0xc5, 0x82, 0xc6, 0x85, 0xc9, 0x82, 0x41, 0xcd, 0xbb, + 0xc3, 0x81, 0xc6, 0x8b, 0xe1, 0x9b, 0xb0, 0xc4, 0xa6, 0x49, 0x6a, 0xce, 0x89, 0xc8, + 0xbb, 0xc6, 0xa5, 0xc5, 0xa7, 0xc7, 0xa9, 0xe2, 0xb1, 0xb7, 0x3c, 0xc5, 0xb5, 0xc3, + 0xbb, 0xc7, 0xad, 0xc3, 0x84, 0xc3, 0xac, 0xe2, 0xb1, 0xbd, 0xc8, 0xaa, 0x51, 0xc2, + 0xaa, 0xcd, 0xba, 0xc5, 0xa1, 0x52, 0x62, 0xc6, 0x9f, 0xc4, 0xb6, 0xc8, 0x83, 0x6f, + 0xc3, 0x9f, 0x48, 0xc6, 0x8f, 0x31, 0xc3, 0x83, 0xe1, 0x9b, 0x80, 0xc5, 0x93, 0xcd, + 0xba, 0xc4, 0xb6, 0xc7, 0x9c, 0xe1, 0x9b, 0x82, 0xe2, 0xb1, 0xb1, 0x28, 0xc6, 0x94, + 0xc7, 0x83, 0xc5, 0x9d, 0xc7, 0x86, 0xe1, 0x9a, 0xbe, 0xc5, 0xa9, 0xc7, 0x83, 0xe2, + 0xb1, 0xad, 0xe1, 0x9b, 0x81, 0xc3, 0x96, 0x60, 0xc4, 0xa3, 0xc2, 0xb7, 0xc5, 0xb6, + 0xc5, 0x93, 0x74, 0xc6, 0x97, 0x21, 0xe2, 0xb1, 0xae, 0xc2, 0xa8, 0xcd, 0xb1, 0xc6, + 0x89, 0xc3, 0xbe, 0xe1, 0x9a, 0xb3, 0xc4, 0xa4, 0xc5, 0x94, 0xc8, 0xb8, 0xe1, 0x9b, + 0x8e, 0xc5, 0x84, 0xc2, 0xbc, 0xc3, 0x86, 0x55, 0xe1, 0x9b, 0x87, 0xce, 0x85, 0xe1, + 0x9a, 0xb9, 0xc8, 0x90, 0xe1, 0x9b, 0x8e, 0x72, 0xc7, 0x82, 0xc3, 0x85, 0xc4, 0x9f, + 0xcd, 0xb5, 0xe1, 0x9b, 0xa7, 0xc3, 0x88, 0x73, 0xc2, 0xa5, 0xc6, 0x88, 0xc4, 0xb4, + 0xc5, 0xa9, 0xcd, 0xbe, 0xc3, 0x99, 0xe1, 0x9a, 0xbf, 0xc4, 0xb0, 0xc4, 0xbf, 0xe2, + 0xb1, 0xb1, 0xc3, 0x8e, 0x2a, 0xc5, 0x93, 0xc8, 0xb6, 0xc6, 0x89, 0xc6, 0x8b, 0x5a, + 0x64, 0xe1, 0x9b, 0x9d, 0x41, 0xc3, 0xba, 0xcd, 0xbe, 0xc7, 0x90, 0xc8, 0x8b, 0xc6, + 0x82, 0xc6, 0xb0, 0xe1, 0x9a, 0xb7, 0xc4, 0xa9, 0xc4, 0x9d, 0xe2, 0xb1, 0xab, 0xc4, + 0x84, 0xc5, 0xb4, 0xc8, 0xb7, 0xc7, 0x81, 0xc4, 0xad, 0xce, 0x88, 0xc8, 0xb7, 0xc3, + 0xa8, 0xcd, 0xbc, 0xc6, 0x97, 0xe2, 0xb1, 0xa8, 0xc8, 0x84, 0xc8, 0xa2, 0xe1, 0x9a, + 0xaa, 0xc5, 0xa4, 0xc5, 0xb3, 0xc5, 0x88, 0x25, 0xc7, 0xb4, 0xc6, 0xa7, 0xc4, 0xbc, + 0x36, 0x3c, 0xc8, 0x8b, 0x6a, 0xc9, 0x84, 0xe1, 0x9b, 0x9e, 0xc7, 0xa9, 0xe1, 0x9b, + 0x89, 0xc5, 0xb1, 0xc7, 0xb6, 0xc8, 0x8a, 0xcd, 0xb5, 0xc4, 0x80, 0xe1, 0x9b, 0x98, + 0xc6, 0x94, 0xc6, 0x82, 0xc4, 0xb4, 0xe1, 0x9a, 0xa3, 0xe1, 0x9b, 0x8f, 0xc3, 0xb6, + 0xc5, 0xb3, 0xe1, 0x9b, 0x8a, 0xc8, 0xa2, 0xc7, 0x97, 0xc3, 0xb9, 0xc5, 0xac, 0xe1, + 0x9a, 0xbb, 0xe1, 0x9b, 0xa5, 0xc5, 0xb2, 0xc5, 0x8c, 0xe1, 0x9b, 0x85, 0xc5, 0x8c, + 0xc7, 0xab, 0xc7, 0xab, 0xe2, 0xb1, 0xbb, 0x48, ], asset_base: [ - 0x9b, 0xe1, 0x71, 0xf6, 0xf2, 0x77, 0x5f, 0x14, 0xa8, 0x8a, 0xf7, 0x42, 0x5f, 0xb8, - 0x37, 0xe8, 0x4e, 0x4f, 0xb0, 0x8b, 0x69, 0xdc, 0xa7, 0x0d, 0x96, 0x70, 0x94, 0xd6, - 0x78, 0xb9, 0x66, 0x92, + 0x35, 0x3e, 0x4f, 0xa9, 0x48, 0x59, 0xab, 0x52, 0xfc, 0xc2, 0xdd, 0x1c, 0x91, 0x45, + 0x3c, 0x09, 0x3f, 0x15, 0x43, 0x31, 0x43, 0x65, 0x80, 0x38, 0xba, 0xc3, 0xaa, 0xf0, + 0x89, 0xf0, 0xd4, 0x23, ], }, TestVector { key: [ - 0xce, 0xb7, 0x5a, 0x43, 0x9f, 0xf0, 0x16, 0x15, 0x80, 0xbf, 0x29, 0x57, 0x24, 0xc6, - 0xd9, 0x2d, 0x31, 0xb7, 0xaa, 0x02, 0x84, 0x03, 0x39, 0x44, 0x49, 0x64, 0x48, 0x6f, - 0xae, 0xa8, 0x90, 0xe5, + 0x1b, 0x39, 0xca, 0x34, 0x32, 0x36, 0xdf, 0xab, 0x88, 0xfe, 0x78, 0x12, 0x10, 0xe1, + 0xe8, 0x79, 0x29, 0x3b, 0xe0, 0xf4, 0xc5, 0x1c, 0x86, 0xfd, 0x8a, 0x6f, 0xff, 0xdb, + 0xb4, 0xad, 0x26, 0x73, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xa5, 0xc2, 0xba, 0xc6, 0x8c, 0xc3, 0x81, 0xc6, 0x82, + 0xc4, 0x80, 0xc4, 0xa3, 0xc6, 0xad, 0xc3, 0x80, 0xc8, 0x8a, 0xc8, 0x99, 0xe2, 0xb1, + 0xae, 0xc5, 0xa2, 0xc8, 0x8e, 0xc3, 0xb4, 0xc6, 0x86, 0xc5, 0xa3, 0xc9, 0x88, 0xcd, + 0xb4, 0x25, 0xe2, 0xb1, 0xa4, 0x50, 0xc3, 0x88, 0xc4, 0xaf, 0xc8, 0x86, 0xc3, 0xa5, + 0xe1, 0x9b, 0x99, 0xc7, 0xb4, 0xc4, 0xb6, 0xc5, 0x99, 0xc5, 0x8b, 0xc8, 0x85, 0x21, + 0xe1, 0x9a, 0xaa, 0xc4, 0x95, 0xc3, 0xa9, 0xe1, 0x9a, 0xba, 0x5d, 0xc4, 0xa4, 0xc6, + 0x9b, 0x4e, 0x37, 0x35, 0xc2, 0xb2, 0xc7, 0x9b, 0xe1, 0x9a, 0xba, 0xc9, 0x80, 0xc7, + 0x9b, 0xc3, 0x9b, 0xc3, 0xb4, 0xe1, 0x9b, 0x9b, 0xc3, 0xb8, 0xc7, 0xbe, 0xc8, 0x9f, + 0xc8, 0xa0, 0xc7, 0x8a, 0xcd, 0xb3, 0xc2, 0xae, 0xc4, 0xaf, 0xc4, 0x84, 0x5b, 0xc8, + 0x87, 0xc9, 0x84, 0xc3, 0x87, 0xc8, 0xa9, 0xc3, 0xa5, 0xc4, 0x87, 0xc5, 0xbf, 0x37, + 0xc5, 0xac, 0xe1, 0x9a, 0xaa, 0xc6, 0x80, 0xe2, 0xb1, 0xa0, 0xc5, 0xb7, 0xc6, 0x8d, + 0xc3, 0xbb, 0xc7, 0x85, 0xc2, 0xb6, 0xc4, 0x90, 0xe1, 0x9a, 0xba, 0xc3, 0xb7, 0xe2, + 0xb1, 0xb6, 0xc6, 0xa8, 0xc7, 0xac, 0xc4, 0xaf, 0xce, 0x8a, 0xc6, 0x8f, 0xc2, 0xa1, + 0xc3, 0x82, 0xe1, 0x9b, 0x96, 0xc8, 0xb5, 0xc4, 0x9f, 0xc3, 0x88, 0xe1, 0x9b, 0xa6, + 0xc5, 0xb9, 0xc5, 0xad, 0xe1, 0x9a, 0xa2, 0xc3, 0x95, 0x5c, 0xe1, 0x9a, 0xb2, 0xcd, + 0xb2, 0xc8, 0xb3, 0xcd, 0xb7, 0x7b, 0xc5, 0xb6, 0xc8, 0xb0, 0x7a, 0xc7, 0x9e, 0x4a, + 0xc4, 0x86, 0xc3, 0xbf, 0xc7, 0xb2, 0xc8, 0xbc, 0xc9, 0x87, 0xc3, 0x8c, 0xe1, 0x9a, + 0xbb, 0xc8, 0x8d, 0xc3, 0x9a, 0xc9, 0x8e, 0xc5, 0xb3, 0xe2, 0xb1, 0xab, 0xc5, 0x89, + 0xc8, 0x9e, 0xe1, 0x9a, 0xb3, 0xc7, 0xb7, 0xc4, 0x8d, 0xe1, 0x9b, 0x84, 0xe1, 0x9b, + 0xa3, 0xc3, 0xbd, 0xc5, 0x80, 0xc5, 0xab, 0xc3, 0xa6, 0xc4, 0x90, 0xc7, 0x90, 0xe1, + 0x9b, 0x97, 0xc5, 0xbb, 0xc3, 0x80, 0xc5, 0x98, 0xc3, 0xa4, 0xe1, 0x9b, 0x9a, 0xc7, + 0x90, 0xc3, 0xb5, 0xc8, 0xaf, 0xc2, 0xac, 0xe1, 0x9b, 0x9f, 0xc5, 0x82, 0x34, 0xce, + 0x87, 0xc6, 0xa4, 0xc3, 0xa5, 0xc4, 0x89, 0x44, 0xc3, 0x8b, 0xc4, 0x84, 0xc7, 0xac, + 0xe1, 0x9b, 0xb0, 0xc5, 0x82, 0x76, 0xc8, 0x99, 0xc4, 0x9d, 0xc7, 0xad, 0xc3, 0xa3, + 0x31, 0xc3, 0xb2, 0xc5, 0x82, 0xc2, 0xbd, 0xc7, 0x8c, 0xc2, 0xb5, 0xe1, 0x9a, 0xaf, + 0xc7, 0x9a, 0xe1, 0x9a, 0xbb, 0xc5, 0xa9, 0xc6, 0x94, 0xc7, 0x82, 0xe2, 0xb1, 0xb5, + 0xc5, 0x9b, 0xe1, 0x9b, 0xa3, 0xc6, 0xb2, 0xc4, 0x88, 0x7d, 0xc4, 0x81, 0xc5, 0xb0, + 0xe1, 0x9a, 0xa4, 0xc8, 0xbb, 0xe2, 0xb1, 0xbe, 0xc4, 0x98, 0xc4, 0xba, 0xc8, 0x8d, + 0x68, 0xc4, 0x99, 0xc8, 0x86, 0x40, 0x59, 0xe1, 0x9a, 0xa1, 0xe1, 0x9b, 0x9a, 0xc7, + 0x89, 0xc8, 0x99, 0xc7, 0xa8, 0x4e, 0xc9, 0x81, 0xc5, 0x92, 0xc8, 0xb0, 0xcd, 0xb2, + 0xc7, 0xa4, 0xc8, 0x95, 0xe1, 0x9a, 0xb3, 0xc4, 0x88, 0x32, 0xc7, 0x88, 0xc2, 0xa7, + 0x34, 0x75, 0xc6, 0xb0, 0xc7, 0x9f, 0xc8, 0xb2, 0x50, 0xc5, 0x95, 0xc7, 0xb9, 0x50, + 0xc2, 0xa5, 0xc3, 0xa3, 0xc9, 0x84, 0xce, 0x85, 0xe1, 0x9b, 0xad, 0xc4, 0x9e, 0xe1, + 0x9b, 0xa3, 0xc5, 0x81, 0x5d, 0xc6, 0xb8, 0xe1, 0x9a, 0xb7, 0xc4, 0x99, 0xc2, 0xb2, + 0xc4, 0xa2, 0xc4, 0x99, 0xc6, 0x8f, 0x26, 0xc3, 0x88, 0xc4, 0xa3, 0xc5, 0x87, 0xc9, + 0x8f, 0x59, 0xc8, 0x85, 0xc7, 0x9a, 0xe1, 0x9b, 0x8a, 0xe2, 0xb1, 0xb7, 0xc8, 0x83, + 0xe1, 0x9b, 0x88, 0x61, 0xc6, 0xa9, 0xc4, 0xa2, ], asset_base: [ - 0x76, 0x3d, 0x56, 0xa8, 0x53, 0xf6, 0xac, 0x5e, 0xe8, 0xef, 0x29, 0x4e, 0xfd, 0x01, - 0x42, 0xbe, 0x6c, 0x23, 0xc5, 0x18, 0x96, 0xfc, 0xb8, 0x3c, 0x40, 0x09, 0x4d, 0x34, - 0x01, 0xc0, 0xc0, 0x94, + 0x76, 0xe9, 0x3a, 0xa6, 0xa3, 0x60, 0x1a, 0x94, 0xdf, 0xde, 0x01, 0xd9, 0x8c, 0x63, + 0xc6, 0xf1, 0x28, 0x5b, 0x22, 0x28, 0x47, 0x16, 0x86, 0x05, 0x85, 0x93, 0x7c, 0x3d, + 0xaf, 0x60, 0x7b, 0xbc, ], }, TestVector { key: [ - 0xec, 0x05, 0xbb, 0x7f, 0x06, 0x5e, 0x25, 0x6f, 0xf4, 0x54, 0xf8, 0xa8, 0xdf, 0x6f, - 0x2f, 0x9b, 0x8a, 0x8c, 0x95, 0x08, 0xca, 0xac, 0xfe, 0xe9, 0x52, 0x1c, 0xbe, 0x68, - 0x9d, 0xd1, 0x12, 0x0f, + 0x56, 0x6e, 0x78, 0x1a, 0xc9, 0x8e, 0x99, 0x13, 0x08, 0x98, 0x1b, 0x7c, 0xdc, 0x73, + 0x7c, 0x66, 0x78, 0x5b, 0xe5, 0x31, 0xe2, 0x0a, 0xef, 0x77, 0x7a, 0xac, 0xe0, 0x6d, + 0x38, 0xfa, 0x02, 0x6b, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc6, 0xa4, 0xc7, 0xae, 0xe1, 0x9a, 0xa6, 0xc8, 0x91, 0xc2, 0xb5, 0xc8, 0xaa, 0xc3, + 0x81, 0x2a, 0xc4, 0x90, 0xc6, 0xa0, 0xe1, 0x9a, 0xb0, 0xc3, 0x85, 0xc8, 0x8b, 0xc6, + 0xaa, 0x4d, 0xc8, 0x94, 0xc7, 0x98, 0xc8, 0xa7, 0xc8, 0x9b, 0xc3, 0x8f, 0xe1, 0x9b, + 0x81, 0xc2, 0xab, 0xe2, 0xb1, 0xa5, 0xc6, 0xb2, 0xce, 0x84, 0x73, 0xc5, 0xb1, 0x63, + 0xc2, 0xb7, 0xc2, 0xb7, 0xc9, 0x87, 0xce, 0x8c, 0xc3, 0xb4, 0xc4, 0xba, 0xe1, 0x9b, + 0x9b, 0x48, 0xcd, 0xbe, 0x28, 0xe2, 0xb1, 0xbd, 0xe1, 0x9a, 0xa9, 0xc5, 0x9d, 0x61, + 0xc4, 0xbe, 0xc2, 0xbf, 0xc3, 0x9f, 0xc7, 0xa5, 0xc5, 0xb0, 0x67, 0xc7, 0x99, 0xe2, + 0xb1, 0xa7, 0xc5, 0xac, 0xc4, 0xbe, 0xc8, 0xa6, 0xe1, 0x9a, 0xaa, 0xc7, 0xb9, 0xc9, + 0x88, 0xc6, 0x9f, 0xe2, 0xb1, 0xa2, 0xe1, 0x9a, 0xaa, 0xc3, 0x89, 0xc3, 0x83, 0xc7, + 0x87, 0xc2, 0xac, 0xc7, 0xa5, 0xe1, 0x9b, 0xae, 0xc4, 0xb0, 0xc3, 0xa6, 0xc6, 0x90, + 0xc7, 0xb2, 0xc3, 0xa7, 0xc2, 0xb8, 0xc5, 0x9a, 0xc5, 0xa1, 0xe1, 0x9b, 0x8c, 0xc5, + 0xac, 0xc8, 0xb7, 0xe2, 0xb1, 0xa8, 0xc3, 0xbc, 0xc9, 0x8e, 0x5e, 0xc2, 0xb4, 0xc7, + 0xb3, 0xc5, 0xba, 0xc8, 0xac, 0xc6, 0x92, 0x6c, 0x2a, 0xc4, 0x82, 0xc5, 0xac, 0xc5, + 0xaf, 0xc8, 0x99, 0xc8, 0xbd, 0xc2, 0xb3, 0xe1, 0x9a, 0xb4, 0x3f, 0xe1, 0x9a, 0xb5, + 0xcd, 0xb2, 0x6b, 0xc3, 0x98, 0xc3, 0xbd, 0xc3, 0x9c, 0xc2, 0xac, 0x3b, 0xc6, 0xa8, + 0xc3, 0x8c, 0x58, 0x2f, 0x5e, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0x95, 0xe1, 0x9b, 0xa1, + 0xe2, 0xb1, 0xba, 0xc7, 0xa4, 0xe2, 0xb1, 0xa0, 0xc4, 0x9d, 0xc3, 0xa4, 0xe1, 0x9b, + 0xa5, 0xe2, 0xb1, 0xab, 0xc6, 0x83, 0xc2, 0xa4, 0x4e, 0xc4, 0xb1, 0xe1, 0x9b, 0xa9, + 0xc8, 0xb1, 0xc5, 0x93, 0xe2, 0xb1, 0xae, 0xc7, 0x99, 0xc3, 0xbe, 0xe2, 0xb1, 0xa3, + 0x7a, 0x60, 0xc7, 0x94, 0xe2, 0xb1, 0xac, 0xe1, 0x9b, 0x80, 0xc8, 0xad, 0xc8, 0x93, + 0x48, 0xe1, 0x9b, 0x83, 0xc6, 0xab, 0xe1, 0x9a, 0xa2, 0xc4, 0xbe, 0xc3, 0x89, 0xc7, + 0xb7, 0xcd, 0xb5, 0xc6, 0x88, 0xe1, 0x9b, 0x85, 0x6a, 0x43, 0xc9, 0x84, 0xc7, 0x91, + 0x31, 0xc9, 0x8b, 0xe1, 0x9a, 0xa8, 0x6e, 0xc7, 0x96, 0xc3, 0x9c, 0x28, 0xc3, 0x90, + 0x41, 0xc5, 0x8b, 0xc5, 0x8d, 0xc2, 0xab, 0xcd, 0xb5, 0xc7, 0xb0, 0x5d, 0xc3, 0x8b, + 0xc8, 0xaa, 0xe2, 0xb1, 0xa6, 0xe2, 0xb1, 0xbf, 0xc6, 0xb7, 0xe1, 0x9a, 0xb8, 0xc5, + 0xbb, 0xe1, 0x9a, 0xaf, 0xe2, 0xb1, 0xb3, 0xc7, 0xa8, 0xc8, 0xb8, 0xc4, 0xb0, 0xe2, + 0xb1, 0xaf, 0xe1, 0x9b, 0xa9, 0xe1, 0x9b, 0x9f, 0xc3, 0x81, 0xc2, 0xaa, 0xc5, 0xae, + 0xc5, 0x83, 0x65, 0xc7, 0xbd, 0xc5, 0x9d, 0x2f, 0xc5, 0x91, 0xc6, 0xb6, 0xc2, 0xb9, + 0xc2, 0xa1, 0x4b, 0xc6, 0x9f, 0xc3, 0xb9, 0xcd, 0xb1, 0xe1, 0x9a, 0xbb, 0xc8, 0xad, + 0xc2, 0xa1, 0xc3, 0x9c, 0xc3, 0x8f, 0xc5, 0x8e, 0xc3, 0xb5, 0xc2, 0xb7, 0xc4, 0xa4, + 0xc5, 0xa5, 0xe1, 0x9b, 0x8b, 0xc4, 0xb2, 0xc2, 0xa2, 0xc7, 0x86, 0xc3, 0xb8, 0x4c, + 0xc3, 0x9b, 0xc5, 0x81, 0xc5, 0x95, 0xe1, 0x9b, 0x85, 0xc6, 0x94, 0xc4, 0xa6, 0xc4, + 0xac, 0x4f, 0xc3, 0xb0, 0xe1, 0x9b, 0xad, 0xc7, 0xa4, 0xc2, 0xa4, 0xc5, 0xa4, 0xe1, + 0x9a, 0xbb, 0xc4, 0xa4, 0xe1, 0x9a, 0xbf, 0xc3, 0xb6, 0xc6, 0xaf, 0xc6, 0xbb, 0xc8, + 0x94, 0xc3, 0xa6, 0xc3, 0xb4, 0xe1, 0x9b, 0x9c, 0xc3, 0x9b, 0xc7, 0xb3, 0xc5, 0xbc, + 0xce, 0x8a, 0xc7, 0xb2, 0xc3, 0xa9, 0x23, 0xc5, 0xa0, 0xc7, 0xba, 0xc2, 0xa1, 0xc9, + 0x85, 0xc6, 0xa9, 0xc7, 0xac, 0xc7, 0x9f, 0x5a, ], asset_base: [ - 0x90, 0x10, 0xb3, 0x4c, 0xdf, 0xfd, 0x95, 0x84, 0x96, 0x62, 0x44, 0xdd, 0x6c, 0x3a, - 0x23, 0x4f, 0xc6, 0xa0, 0x74, 0xf1, 0xa9, 0xc9, 0xb2, 0xd8, 0x3d, 0x1c, 0x2c, 0x04, - 0xf5, 0x30, 0x75, 0x0c, + 0x50, 0xf6, 0x66, 0x1f, 0x02, 0x22, 0x48, 0x1e, 0x18, 0x94, 0x80, 0x9a, 0x17, 0xd0, + 0xaf, 0xeb, 0x5e, 0xf9, 0x74, 0x34, 0x43, 0x5d, 0x32, 0xa0, 0x4b, 0x3b, 0x16, 0xb2, + 0x45, 0xc8, 0xed, 0x0a, ], }, TestVector { key: [ - 0xb0, 0xfa, 0x9d, 0x77, 0xfc, 0xbd, 0x96, 0x45, 0x91, 0x32, 0xe3, 0x05, 0xe3, 0x24, - 0xe7, 0x93, 0x6a, 0xe1, 0x3b, 0x15, 0x14, 0x7e, 0x20, 0x5d, 0x7b, 0xae, 0x42, 0xfa, - 0x7f, 0xaf, 0x5d, 0x1e, + 0x86, 0xcc, 0x5e, 0x4f, 0xea, 0x9b, 0x7c, 0x1d, 0x0e, 0x1f, 0xa8, 0xb6, 0xa8, 0xf2, + 0x31, 0xb4, 0x56, 0x2e, 0x53, 0x89, 0xe9, 0xe7, 0x92, 0x16, 0x57, 0x67, 0x96, 0xce, + 0x3a, 0x49, 0x40, 0x6b, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc2, 0xa1, 0xc4, 0x8e, 0xc3, 0x9f, 0xc5, 0xbb, 0x74, 0xc4, 0x82, 0xc5, 0xbb, 0x7d, + 0xc6, 0xae, 0xc8, 0xa9, 0xe2, 0xb1, 0xbf, 0xc7, 0x90, 0xc7, 0x93, 0xc9, 0x89, 0xc7, + 0xa5, 0xc6, 0x8b, 0xc7, 0xbd, 0xe2, 0xb1, 0xb9, 0xcd, 0xbd, 0x4c, 0xcd, 0xbe, 0xc5, + 0x8d, 0x4d, 0xc4, 0xb2, 0xe2, 0xb1, 0xa3, 0x31, 0xe1, 0x9a, 0xbe, 0xc8, 0xa1, 0xc4, + 0xab, 0x58, 0xc7, 0x89, 0xc4, 0xb3, 0x7d, 0xc9, 0x88, 0xc7, 0xbc, 0xc4, 0x8d, 0xc4, + 0xae, 0xc4, 0x98, 0xc7, 0xaa, 0xc3, 0xb4, 0xc5, 0xbe, 0xc6, 0x98, 0x2b, 0xc2, 0xb3, + 0xc7, 0xaa, 0xc6, 0x83, 0xc6, 0x92, 0xc6, 0xb8, 0xe1, 0x9b, 0xaf, 0xc4, 0x95, 0xc4, + 0xbc, 0xc8, 0xa5, 0xc3, 0xb9, 0xc3, 0xae, 0xc4, 0xa8, 0xc6, 0x82, 0xe1, 0x9a, 0xad, + 0xc3, 0xab, 0xc8, 0x88, 0xc4, 0x9c, 0xc5, 0xba, 0xce, 0x87, 0xc3, 0x8b, 0xc7, 0xaf, + 0xc8, 0xa6, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x9f, 0xc2, 0xb3, 0xc7, 0x9e, 0x73, 0xc5, + 0x8a, 0x5c, 0xc5, 0x90, 0xc5, 0xb7, 0xc6, 0x87, 0xc5, 0x9a, 0xc3, 0x86, 0x78, 0xe1, + 0x9b, 0x9c, 0xc7, 0xae, 0xc8, 0x94, 0xc9, 0x82, 0xc8, 0xb8, 0x69, 0xc8, 0xb3, 0xc5, + 0x92, 0xe1, 0x9a, 0xa7, 0xc6, 0xb1, 0xc3, 0x85, 0xc5, 0xa5, 0xc4, 0xab, 0xc7, 0x97, + 0xe1, 0x9a, 0xb2, 0xc7, 0xb7, 0xc8, 0xa9, 0xe1, 0x9b, 0x92, 0xc3, 0xb8, 0xce, 0x86, + 0xc5, 0xa1, 0x5d, 0xc4, 0xb9, 0xce, 0x88, 0xc6, 0xb1, 0xc7, 0xb2, 0xc6, 0x90, 0xc6, + 0xaf, 0xe1, 0x9a, 0xb5, 0xce, 0x8c, 0x25, 0x47, 0xc6, 0xb1, 0xc4, 0x92, 0xc8, 0xba, + 0xc6, 0x95, 0xc8, 0xa6, 0xe2, 0xb1, 0xb5, 0xc5, 0xb0, 0xe2, 0xb1, 0xb3, 0xc7, 0xa5, + 0xc5, 0x98, 0xc8, 0xbb, 0xc4, 0x9b, 0xc5, 0x83, 0xc4, 0x82, 0xe2, 0xb1, 0xbf, 0xc4, + 0x9b, 0xc6, 0xa8, 0xc8, 0x8e, 0xe1, 0x9b, 0x88, 0xc8, 0xba, 0x2d, 0x54, 0xe1, 0x9a, + 0xb1, 0xc2, 0xa9, 0xe1, 0x9b, 0x97, 0xc9, 0x8a, 0xc5, 0x8a, 0xc4, 0x80, 0xc8, 0xb1, + 0xc4, 0x9e, 0xc7, 0xac, 0xc3, 0x82, 0xc7, 0xb6, 0xc4, 0x8f, 0xc5, 0xa6, 0xc4, 0x98, + 0xe2, 0xb1, 0xa4, 0x3f, 0xcd, 0xb5, 0xc4, 0xa8, 0xc8, 0xa7, 0xe1, 0x9a, 0xb9, 0xc8, + 0xad, 0xe1, 0x9b, 0xaa, 0xc4, 0x97, 0xc7, 0xb9, 0x3d, 0xc6, 0xb9, 0xc8, 0x86, 0xc5, + 0x9d, 0xc2, 0xa4, 0xc7, 0xba, 0xc6, 0xb1, 0xc7, 0xbb, 0xe1, 0x9a, 0xa8, 0xc7, 0x99, + 0xc6, 0x93, 0x71, 0x5c, 0xc3, 0x91, 0xc8, 0x82, 0xc3, 0x9c, 0x3c, 0xc2, 0xa1, 0xe2, + 0xb1, 0xba, 0x5b, 0xc5, 0x9a, 0xc6, 0xba, 0x54, 0xce, 0x88, 0xe1, 0x9a, 0xad, 0x6a, + 0xc7, 0xb5, 0xe2, 0xb1, 0xbf, 0xc4, 0xbd, 0x39, 0xc9, 0x8b, 0xc8, 0x8e, 0x76, 0x49, + 0xc6, 0xb2, 0xc7, 0xbc, 0x31, 0xc7, 0xa8, 0xc9, 0x88, 0xc4, 0xab, 0xc5, 0x90, 0xc3, + 0x9f, 0xc3, 0x91, 0xe1, 0x9a, 0xbf, 0xe1, 0x9b, 0xab, 0xc5, 0xab, 0xe2, 0xb1, 0xbe, + 0xe2, 0xb1, 0xa6, 0xc9, 0x86, 0xc5, 0x97, 0xe1, 0x9a, 0xa1, 0x63, 0xc7, 0x9c, 0xc8, + 0xab, 0xe1, 0x9a, 0xaa, 0x3a, 0xc6, 0x8b, 0xc3, 0x82, 0xe2, 0xb1, 0xa7, 0xe1, 0x9b, + 0x9d, 0xc2, 0xb2, 0xe1, 0x9b, 0x98, 0x4c, 0xce, 0x85, 0xc5, 0xbb, 0x6c, 0xc4, 0xb5, + 0xc3, 0xb6, 0xc2, 0xa3, 0xc8, 0xb2, 0xc8, 0x8f, 0xc5, 0x8a, 0x3f, 0x74, 0xc7, 0x8c, + 0x63, 0xe1, 0x9a, 0xa6, 0xc3, 0x98, 0xc8, 0xb9, 0xc7, 0x9b, 0x45, 0xc6, 0x9a, 0xc7, + 0xb1, 0xc2, 0xba, 0x6c, 0x62, 0x66, 0xe1, 0x9a, 0xb7, 0xe1, 0x9b, 0xa3, 0xe1, 0x9b, + 0x8c, 0xe1, 0x9b, 0x80, 0xc2, 0xb0, 0xc8, 0xaa, 0xc5, 0xbc, 0xc5, 0xb0, 0xc4, 0xa0, + 0xcd, 0xb4, 0xc7, 0x9a, 0x3f, 0xc4, 0x85, 0x5a, ], asset_base: [ - 0xbd, 0x61, 0xcd, 0xd1, 0x35, 0x54, 0x21, 0x00, 0x57, 0xaa, 0xef, 0xc0, 0xf0, 0xc7, - 0xc0, 0xbe, 0x9c, 0xdb, 0xef, 0x14, 0xe8, 0x79, 0xac, 0x10, 0xf3, 0xd2, 0x66, 0xad, - 0x18, 0x39, 0xc2, 0x1b, + 0xc9, 0x01, 0x55, 0x24, 0x71, 0x2e, 0x93, 0xf3, 0x40, 0x41, 0x31, 0x02, 0xda, 0x68, + 0xaf, 0xb4, 0xf5, 0x5f, 0xa2, 0x94, 0x4a, 0xc4, 0xc8, 0x32, 0x34, 0xb5, 0x8a, 0x1d, + 0x7a, 0x9c, 0xb6, 0x95, ], }, TestVector { key: [ - 0x81, 0x8f, 0x50, 0xce, 0x47, 0x10, 0xf4, 0xeb, 0x11, 0xe7, 0x43, 0xe6, 0x40, 0x85, - 0x44, 0xaa, 0x3c, 0x12, 0x3c, 0x7f, 0x07, 0xe2, 0xaa, 0xbb, 0x91, 0xaf, 0xc4, 0xec, - 0x48, 0x78, 0x8d, 0xe9, + 0x43, 0x39, 0xfd, 0x2a, 0x6c, 0x66, 0x30, 0x2e, 0x31, 0x8e, 0x18, 0x41, 0xf7, 0xe6, + 0x36, 0xb7, 0x76, 0x58, 0xda, 0xfc, 0x9c, 0x8e, 0x96, 0x45, 0xc9, 0x46, 0xe9, 0x5e, + 0x56, 0x9c, 0x3c, 0x45, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc9, 0x80, 0xc4, 0x80, 0xe1, 0x9a, 0xb0, 0xc4, 0xa3, 0xc6, 0x8e, 0xc5, 0xb2, 0xc6, + 0x8e, 0x3f, 0xc8, 0xb7, 0xc6, 0xb4, 0xc6, 0xb5, 0x65, 0xc7, 0xa5, 0xc8, 0x9e, 0xc6, + 0x97, 0xc3, 0xb1, 0xc6, 0x9c, 0xcd, 0xbd, 0x29, 0xc9, 0x88, 0xc2, 0xa2, 0xce, 0x86, + 0xc3, 0xb8, 0xc6, 0x9f, 0x3e, 0xc8, 0x81, 0xc3, 0x99, 0xc3, 0x88, 0xc7, 0xa2, 0xc5, + 0xb5, 0xc5, 0xb0, 0xc6, 0xa2, 0xc8, 0x89, 0xc6, 0x8c, 0xe1, 0x9b, 0xae, 0xc7, 0x83, + 0xcd, 0xba, 0xcd, 0xb5, 0xc3, 0xbc, 0xe1, 0x9b, 0xab, 0xc5, 0x8e, 0xc7, 0xb3, 0xc7, + 0xa7, 0xc4, 0xb5, 0xc3, 0x8b, 0xc3, 0xbf, 0x5e, 0xe1, 0x9a, 0xa0, 0xc6, 0xbe, 0xc8, + 0xb5, 0x31, 0xe2, 0xb1, 0xbe, 0xc7, 0x90, 0x7a, 0xc6, 0x81, 0x2a, 0xc7, 0xb7, 0xc3, + 0xbc, 0xc2, 0xb4, 0xc8, 0xa4, 0xc6, 0xa8, 0x64, 0xc7, 0x99, 0xc4, 0xa4, 0xc2, 0xbb, + 0xcd, 0xb1, 0xc6, 0xb0, 0xe1, 0x9b, 0xad, 0xc6, 0x95, 0x43, 0xc8, 0xb9, 0xc5, 0x98, + 0xc7, 0xb6, 0xc7, 0x9d, 0xc4, 0x8d, 0xc3, 0x90, 0x6c, 0xc7, 0x98, 0xc9, 0x80, 0xc2, + 0xae, 0xc6, 0x80, 0xc8, 0xba, 0xcd, 0xba, 0xc7, 0xa7, 0x41, 0xc6, 0xbf, 0xc4, 0x96, + 0xc7, 0x84, 0xc3, 0xa7, 0xc9, 0x89, 0xc8, 0xa2, 0xc8, 0x92, 0x71, 0xc2, 0xb5, 0xc4, + 0x9c, 0xc3, 0xbc, 0xc3, 0x84, 0xe1, 0x9b, 0xa4, 0x3b, 0xc7, 0x9d, 0xc4, 0xb9, 0xc4, + 0x9a, 0xc5, 0x93, 0xe1, 0x9a, 0xbb, 0xc8, 0x96, 0xc7, 0xa9, 0xc6, 0x8d, 0xc8, 0xb7, + 0x72, 0xc5, 0x8d, 0xc5, 0x83, 0xc4, 0x80, 0xc2, 0xb3, 0xc3, 0xb2, 0xc7, 0xa1, 0xc8, + 0x9c, 0xc3, 0x9c, 0xc6, 0x8a, 0xc3, 0xa2, 0xe1, 0x9b, 0x93, 0xc5, 0xa1, 0xc2, 0xa1, + 0xe1, 0x9b, 0x9a, 0xc3, 0xa5, 0xc3, 0x97, 0xc7, 0x82, 0xc2, 0xb4, 0xc3, 0x89, 0xc3, + 0xb3, 0xc9, 0x83, 0x70, 0xc7, 0xb8, 0xc5, 0xa4, 0xc8, 0x83, 0xc4, 0xb5, 0xc8, 0x84, + 0xc8, 0xa3, 0xe1, 0x9b, 0x86, 0xc7, 0x8c, 0xe2, 0xb1, 0xb5, 0x68, 0x5e, 0xc3, 0x8f, + 0xe2, 0xb1, 0xa6, 0xc6, 0xa1, 0xc8, 0xb9, 0xc4, 0x92, 0xc9, 0x8a, 0xc3, 0x8c, 0xe1, + 0x9b, 0x83, 0xe1, 0x9b, 0xa3, 0x4b, 0x59, 0xc8, 0xb9, 0xc6, 0xa6, 0xc8, 0x8d, 0xc6, + 0x8f, 0xe2, 0xb1, 0xba, 0xc5, 0xa4, 0xc8, 0xa7, 0xc5, 0xad, 0xc3, 0x95, 0xe1, 0x9a, + 0xb5, 0xc5, 0xa4, 0xe2, 0xb1, 0xbd, 0xe1, 0x9b, 0xad, 0xc3, 0x92, 0xcd, 0xbe, 0xc6, + 0xa8, 0xc6, 0x83, 0xc4, 0x80, 0xe1, 0x9b, 0x84, 0xc3, 0xbc, 0xc5, 0x88, 0xe1, 0x9b, + 0x89, 0xc7, 0xb0, 0xc2, 0xba, 0xc3, 0x9f, 0xc9, 0x8e, 0xc3, 0x98, 0xc8, 0xbd, 0xc5, + 0x99, 0xc8, 0x90, 0xc2, 0xae, 0xe1, 0x9a, 0xb9, 0xe1, 0x9b, 0x8d, 0xc6, 0xb8, 0xc2, + 0xb0, 0xe1, 0x9b, 0xa9, 0xc7, 0x89, 0xc9, 0x8d, 0xc8, 0xaf, 0xc5, 0xa4, 0xc4, 0x9f, + 0xc4, 0x98, 0xc7, 0x84, 0xc8, 0x99, 0xc3, 0x86, 0xc5, 0xa8, 0xe1, 0x9b, 0x94, 0x7e, + 0xc8, 0xa2, 0xc8, 0x9b, 0xc3, 0xa1, 0xce, 0x89, 0xe2, 0xb1, 0xa6, 0x51, 0xc4, 0x88, + 0xc2, 0xa2, 0xe1, 0x9a, 0xb3, 0xe2, 0xb1, 0xb9, 0xe2, 0xb1, 0xa6, 0x41, 0xe2, 0xb1, + 0xbc, 0xc5, 0xa3, 0xc3, 0x9c, 0xc8, 0x95, 0xc5, 0xab, 0xc3, 0xb4, 0x42, 0xc6, 0xb3, + 0xe1, 0x9b, 0x96, 0xe1, 0x9b, 0x98, 0xe1, 0x9b, 0xa7, 0xc6, 0x92, 0xc4, 0xa1, 0xe1, + 0x9b, 0xac, 0xc8, 0xb0, 0xc6, 0x91, 0xc7, 0x8f, 0x25, 0xc9, 0x86, 0xc6, 0x83, 0xc3, + 0xb4, 0xc5, 0xb5, 0xc5, 0x9f, 0xe1, 0x9b, 0x8a, 0xc6, 0x9d, 0xc8, 0x8a, 0xe1, 0x9b, + 0xa3, 0xe1, 0x9b, 0xa6, 0xe1, 0x9a, 0xb8, 0xe2, 0xb1, 0xa1, 0xc4, 0x9a, 0xc6, 0x86, + 0xc3, 0xa7, 0x5c, 0xe1, 0x9b, 0x97, 0x47, 0x5a, ], asset_base: [ - 0xae, 0xc8, 0x2d, 0x62, 0x1d, 0x97, 0xcf, 0x35, 0xfb, 0xef, 0x86, 0x88, 0xc5, 0xc8, - 0x30, 0xa0, 0xfd, 0x9c, 0x4a, 0xf7, 0x37, 0x0a, 0x15, 0xc8, 0x99, 0xb2, 0x84, 0x86, - 0xb3, 0xf0, 0x96, 0x20, + 0x13, 0x42, 0x79, 0x82, 0x9b, 0x56, 0xe2, 0xb0, 0x4a, 0xa0, 0xfb, 0x95, 0xf7, 0xfc, + 0x73, 0x79, 0x67, 0x24, 0x5d, 0x49, 0x6a, 0x6d, 0xfa, 0xa0, 0x28, 0x35, 0x2c, 0x39, + 0x2a, 0x58, 0x0d, 0x22, ], }, TestVector { key: [ - 0x0b, 0xb4, 0x91, 0x3d, 0xba, 0xf1, 0x4e, 0xf6, 0xd0, 0xad, 0xeb, 0x8b, 0x70, 0x27, - 0xbf, 0x0b, 0x9a, 0x8f, 0x59, 0x0d, 0x3e, 0x2d, 0x95, 0xa1, 0x2d, 0xba, 0xaf, 0x0b, - 0x95, 0x33, 0xdc, 0xa4, + 0x46, 0x2e, 0xe2, 0x38, 0x00, 0xc2, 0x1e, 0x2b, 0xbd, 0x90, 0x2b, 0xf7, 0x2f, 0x60, + 0xe1, 0xab, 0x08, 0x26, 0xd3, 0x68, 0x0c, 0x6f, 0xd0, 0xa2, 0x6f, 0x87, 0xdb, 0xac, + 0xd0, 0xd7, 0x6c, 0xa0, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc6, 0x96, 0x5e, 0x38, 0xc5, 0xa9, 0x73, 0x21, 0xc9, 0x88, 0xcd, 0xb7, 0xc3, 0xba, + 0xc5, 0x83, 0xc5, 0x99, 0xc8, 0x80, 0xc6, 0xbb, 0xe1, 0x9a, 0xb3, 0xc5, 0x98, 0xe1, + 0x9a, 0xa1, 0x72, 0xe1, 0x9b, 0x83, 0xc7, 0xa7, 0xc8, 0xbb, 0xc7, 0x95, 0xc6, 0xa7, + 0xc7, 0x9b, 0xc4, 0xbf, 0xc7, 0x97, 0xc3, 0xb1, 0xc3, 0x84, 0xe2, 0xb1, 0xa4, 0xc9, + 0x83, 0xc4, 0x96, 0xe2, 0xb1, 0xae, 0xc5, 0xb3, 0xc4, 0x82, 0xc8, 0xbd, 0xe1, 0x9b, + 0x95, 0xc6, 0x92, 0xe1, 0x9a, 0xa8, 0xc3, 0xb2, 0x25, 0xe1, 0x9b, 0x96, 0xc7, 0x90, + 0xc9, 0x80, 0xc3, 0x93, 0xc4, 0xa4, 0xc7, 0xb1, 0xc7, 0x82, 0xc4, 0x9b, 0xc9, 0x80, + 0xc5, 0x8c, 0xe1, 0x9b, 0xa7, 0x48, 0xc4, 0xb7, 0xcd, 0xb6, 0xc9, 0x8d, 0xc8, 0x9f, + 0xc9, 0x8d, 0xc5, 0xb5, 0xc8, 0x95, 0x79, 0xc4, 0xb6, 0xc5, 0xbb, 0xc4, 0x96, 0xe1, + 0x9a, 0xbb, 0xc3, 0xb1, 0xc3, 0xbb, 0x64, 0xc4, 0xbb, 0xc7, 0x84, 0xc8, 0x82, 0xe1, + 0x9a, 0xa4, 0x33, 0xcd, 0xb4, 0xc7, 0x8b, 0xc6, 0xaa, 0xc8, 0xba, 0xc3, 0xb4, 0xe2, + 0xb1, 0xbb, 0xe1, 0x9a, 0xb7, 0xc5, 0x89, 0x7a, 0xc2, 0xaa, 0xc8, 0x97, 0xc4, 0x9c, + 0xc4, 0xab, 0xc6, 0xb1, 0xc3, 0x9d, 0xc3, 0x95, 0xc3, 0xbf, 0xe2, 0xb1, 0xbf, 0xce, + 0x8c, 0x7a, 0xc8, 0xab, 0xc5, 0xa1, 0xc5, 0xa4, 0xc5, 0xb4, 0x24, 0xe2, 0xb1, 0xbf, + 0xc5, 0xb9, 0xe1, 0x9a, 0xb3, 0x60, 0xc5, 0xb8, 0x45, 0xc9, 0x83, 0x74, 0xc7, 0x86, + 0xc2, 0xbe, 0xc5, 0xb9, 0xc7, 0xab, 0xc7, 0x86, 0xc4, 0x84, 0xc5, 0x9b, 0xc6, 0x91, + 0xc4, 0x93, 0xc3, 0x93, 0xc5, 0xa6, 0xc8, 0x93, 0xc7, 0xbd, 0xc2, 0xb3, 0xcd, 0xba, + 0xc3, 0xb9, 0xc2, 0xb8, 0xc3, 0x87, 0xc8, 0xa1, 0xc6, 0x83, 0xc5, 0xbd, 0xe1, 0x9a, + 0xa7, 0xc8, 0x92, 0x43, 0xe1, 0x9b, 0x80, 0xc3, 0xb5, 0xc7, 0x8f, 0x74, 0x5a, 0xc6, + 0x94, 0xc5, 0x80, 0xc9, 0x81, 0xc4, 0xbe, 0xc6, 0xb3, 0xc2, 0xa8, 0xc7, 0xb7, 0xc6, + 0xb9, 0xc3, 0x97, 0xc6, 0xb7, 0xc6, 0xb4, 0xc6, 0x80, 0xc2, 0xb7, 0xc8, 0xa3, 0xcd, + 0xb1, 0xc7, 0xb4, 0xc7, 0xb0, 0xc7, 0xb2, 0xc7, 0x9f, 0xc2, 0xa2, 0xc3, 0xa6, 0xe2, + 0xb1, 0xa1, 0xe2, 0xb1, 0xb3, 0xe1, 0x9b, 0xa6, 0xcd, 0xbd, 0xe1, 0x9b, 0x88, 0xc6, + 0xb1, 0xc3, 0xaf, 0x42, 0x6f, 0xe1, 0x9b, 0xa2, 0xe2, 0xb1, 0xa7, 0xc5, 0x86, 0x6c, + 0xc3, 0x9b, 0xc2, 0xbc, 0xc8, 0x8f, 0xc2, 0xa9, 0xc8, 0xbd, 0xe2, 0xb1, 0xbc, 0xe2, + 0xb1, 0xb5, 0xe1, 0x9b, 0x83, 0x37, 0x37, 0xe2, 0xb1, 0xa0, 0xcd, 0xb5, 0xc7, 0xb7, + 0x64, 0xc7, 0xbb, 0xc7, 0xa5, 0xe1, 0x9a, 0xb7, 0xc3, 0xb4, 0xc7, 0x95, 0xc2, 0xb5, + 0xe1, 0x9b, 0x82, 0xc9, 0x81, 0xc4, 0xb6, 0xc7, 0xae, 0x26, 0xc4, 0xb6, 0x3e, 0xc3, + 0xba, 0xc3, 0xb7, 0xc7, 0x89, 0xc8, 0x87, 0xc7, 0x9d, 0xc5, 0xa5, 0xe2, 0xb1, 0xa8, + 0xc3, 0x96, 0xcd, 0xb7, 0x75, 0xe2, 0xb1, 0xa0, 0xc7, 0xa6, 0xc7, 0x83, 0x30, 0xc7, + 0xb8, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0x9a, 0xc3, 0xb8, 0xe2, 0xb1, 0xa3, 0x26, 0xc6, + 0x8a, 0xc6, 0x90, 0xc3, 0x8f, 0xe2, 0xb1, 0xa2, 0xc4, 0x88, 0xc2, 0xb3, 0xc9, 0x82, + 0x79, 0xc7, 0x8a, 0xc4, 0xb3, 0x78, 0xc5, 0xb6, 0xc3, 0x9c, 0x36, 0xc4, 0xa7, 0xc3, + 0xab, 0xc6, 0x87, 0xc5, 0xb4, 0xc6, 0xa2, 0xc7, 0x97, 0xc5, 0x96, 0xc9, 0x8c, 0x2b, + 0xc6, 0x80, 0xc7, 0x99, 0xc8, 0xb7, 0xc7, 0xb9, 0xc3, 0xa1, 0xc7, 0x8e, 0x7a, 0xc8, + 0x91, 0xe1, 0x9a, 0xb2, 0xe1, 0x9a, 0xae, 0x5f, 0xe1, 0x9b, 0x9b, 0xc6, 0x93, 0x3f, + 0xc3, 0xbd, 0xc3, 0xb2, 0xc8, 0x9a, 0xc8, 0x9f, ], asset_base: [ - 0x4b, 0xec, 0xc4, 0x9b, 0x22, 0x54, 0xb4, 0xdd, 0x36, 0x28, 0xac, 0x96, 0xdc, 0xda, - 0x24, 0x70, 0x0e, 0xf8, 0xd7, 0x30, 0x5a, 0x25, 0x4e, 0x8e, 0x0c, 0xa6, 0xce, 0x23, - 0x91, 0x3f, 0xd8, 0x0d, + 0xe4, 0xb5, 0xf3, 0x96, 0x78, 0x10, 0xbc, 0x94, 0xfe, 0x85, 0x44, 0x13, 0x38, 0x48, + 0xab, 0x35, 0xf6, 0xa5, 0x22, 0x2b, 0x0e, 0x74, 0xa8, 0xd3, 0xf0, 0x35, 0xdb, 0xdc, + 0x31, 0xa6, 0x3d, 0x04, ], }, TestVector { key: [ - 0xae, 0x36, 0xb6, 0x1a, 0x3d, 0x10, 0xf1, 0xaa, 0x75, 0x2a, 0xb1, 0xdc, 0x16, 0xe3, - 0xe4, 0x9b, 0x6a, 0xc0, 0xd2, 0xae, 0x19, 0x07, 0xd2, 0xe6, 0x94, 0x25, 0xec, 0x12, - 0xc9, 0x3a, 0xae, 0xbc, + 0x9e, 0x94, 0xc3, 0xbb, 0x8a, 0xb5, 0x31, 0x98, 0xd3, 0x9e, 0xf1, 0xb4, 0x05, 0xd1, + 0x75, 0x39, 0x20, 0x6f, 0x1b, 0x9f, 0x8e, 0xe9, 0xbc, 0x62, 0x58, 0xb5, 0xfe, 0xf5, + 0xb3, 0x0a, 0xb9, 0x4d, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0x76, 0xe1, 0x9b, 0xa3, 0xc5, 0x8f, 0xc3, 0x95, 0xc6, 0xa6, 0x65, 0xc3, 0x9f, 0xc7, + 0xb0, 0xc6, 0x9c, 0xc4, 0x9d, 0xc5, 0xb8, 0xc6, 0x9c, 0x71, 0xe1, 0x9a, 0xbe, 0xc3, + 0xb4, 0xc8, 0xa4, 0xe1, 0x9b, 0xb0, 0x25, 0xc4, 0xaa, 0xc3, 0x9a, 0xe1, 0x9b, 0x8c, + 0xc8, 0x9e, 0x59, 0xe1, 0x9a, 0xb1, 0xc6, 0x91, 0xc2, 0xa2, 0x6b, 0xc7, 0xac, 0xc8, + 0xad, 0x77, 0xc7, 0xa4, 0xc5, 0xa2, 0xc6, 0x9d, 0xc3, 0x92, 0x29, 0x38, 0xc3, 0x9a, + 0xc9, 0x86, 0xc4, 0xac, 0xc2, 0xa4, 0xc3, 0x9b, 0xc6, 0xa4, 0x29, 0xce, 0x86, 0xc6, + 0xab, 0xe1, 0x9b, 0xa8, 0xe1, 0x9a, 0xb5, 0xc3, 0xa9, 0xc6, 0x84, 0xe1, 0x9a, 0xb1, + 0xc3, 0xb7, 0xe2, 0xb1, 0xbd, 0xc8, 0xb6, 0xc7, 0x9d, 0xc8, 0xa8, 0xc6, 0xa4, 0xe1, + 0x9a, 0xae, 0xe2, 0xb1, 0xad, 0xc5, 0xac, 0xc4, 0x99, 0xe1, 0x9a, 0xb1, 0xc9, 0x8c, + 0xc6, 0x85, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0xa6, 0xc4, 0xba, 0xcd, 0xbe, 0xe1, 0x9b, + 0x80, 0xe1, 0x9b, 0x9c, 0xc6, 0xb3, 0xc8, 0x84, 0xc5, 0x95, 0xc3, 0xae, 0xc9, 0x8a, + 0xc5, 0xbc, 0xc4, 0xbd, 0xc6, 0xbe, 0xe1, 0x9a, 0xa6, 0xe1, 0x9a, 0xb1, 0x51, 0xc8, + 0x93, 0xc3, 0x8e, 0xc6, 0x83, 0xc5, 0xbb, 0xe1, 0x9b, 0x89, 0xe1, 0x9b, 0x8a, 0xc5, + 0xb1, 0x6a, 0xe1, 0x9a, 0xad, 0xc7, 0xbc, 0xc4, 0x86, 0xc8, 0x82, 0xe1, 0x9b, 0x9a, + 0xc8, 0x86, 0x53, 0xce, 0x89, 0xc3, 0x87, 0xc4, 0xb9, 0xc6, 0x85, 0xc8, 0xa0, 0x28, + 0xe2, 0xb1, 0xae, 0x62, 0xc8, 0x8b, 0xc4, 0xa2, 0xc5, 0x88, 0xc7, 0x8b, 0xc6, 0x99, + 0x62, 0xce, 0x85, 0xc5, 0x8c, 0xcd, 0xb0, 0xc2, 0xbf, 0xc7, 0xae, 0x29, 0xe1, 0x9a, + 0xb6, 0xc2, 0xb0, 0xc9, 0x8e, 0xc9, 0x88, 0xc7, 0x86, 0x55, 0x7b, 0xc3, 0x93, 0xc3, + 0xa2, 0xc5, 0x9e, 0xe1, 0x9b, 0xa2, 0x40, 0xe1, 0x9b, 0xad, 0xc8, 0x85, 0xc5, 0x8a, + 0xc5, 0x80, 0xc4, 0x9b, 0xc3, 0x8f, 0xe1, 0x9b, 0x8d, 0xe1, 0x9b, 0x8a, 0x55, 0x4a, + 0x35, 0xc5, 0xa1, 0xc6, 0x94, 0xc7, 0x96, 0xc7, 0xa8, 0xc5, 0xaf, 0xc7, 0xbc, 0xc8, + 0xa7, 0xc8, 0x88, 0xc3, 0x8a, 0xc6, 0x84, 0xc7, 0xb6, 0x4b, 0xc6, 0x94, 0xe2, 0xb1, + 0xa6, 0xc2, 0xaa, 0xc7, 0xb2, 0xc8, 0xae, 0xc8, 0x97, 0xe2, 0xb1, 0xa5, 0xc3, 0xab, + 0xc4, 0xa4, 0xe1, 0x9a, 0xa3, 0xc4, 0x81, 0xc3, 0x8d, 0xcd, 0xbd, 0xc5, 0x91, 0xc3, + 0xb6, 0xe2, 0xb1, 0xa0, 0xc7, 0xa6, 0xc4, 0xb1, 0x23, 0xc7, 0xb1, 0xe1, 0x9b, 0x94, + 0xc5, 0xbc, 0xc6, 0x99, 0xc3, 0x87, 0xc6, 0x97, 0xc7, 0xb4, 0xc4, 0xb5, 0xc7, 0x9b, + 0x6b, 0xc5, 0x9c, 0xc4, 0x99, 0xc7, 0xba, 0x58, 0xe1, 0x9b, 0x88, 0xc7, 0xa1, 0xc6, + 0x90, 0xe1, 0x9b, 0x96, 0xe1, 0x9b, 0xaf, 0xc8, 0xba, 0xe1, 0x9a, 0xa4, 0x55, 0xc4, + 0x9c, 0xc7, 0xbe, 0xc4, 0x90, 0xc4, 0x80, 0xc2, 0xb5, 0xc7, 0x90, 0xce, 0x87, 0xc8, + 0x93, 0xc4, 0x9b, 0xcd, 0xb7, 0xc9, 0x8b, 0xc4, 0xbd, 0xe2, 0xb1, 0xbb, 0xc4, 0x8c, + 0xc3, 0x9f, 0xe1, 0x9a, 0xb3, 0xc4, 0x83, 0xc4, 0x98, 0xc7, 0x83, 0xe1, 0x9b, 0x9d, + 0xc3, 0x84, 0xe2, 0xb1, 0xbd, 0xc8, 0xbd, 0xc4, 0x82, 0xe1, 0x9b, 0xa7, 0xc5, 0x98, + 0xc3, 0xb0, 0xc5, 0x97, 0xc5, 0x94, 0xc7, 0xab, 0xce, 0x89, 0xc6, 0xb8, 0xc7, 0x86, + 0xc4, 0x94, 0xc4, 0x96, 0xc4, 0x81, 0x53, 0xcd, 0xbd, 0xc6, 0x86, 0xe1, 0x9b, 0x8e, + 0xc7, 0xb4, 0x3c, 0xe1, 0x9a, 0xa6, 0xc5, 0x9a, 0xe1, 0x9b, 0x96, 0xc8, 0xae, 0xe2, + 0xb1, 0xa9, 0xc7, 0xa2, 0xc5, 0x85, 0xc4, 0x97, 0xc4, 0x9c, 0xe1, 0x9a, 0xa1, 0xcd, + 0xbc, 0xc6, 0xaf, 0xc2, 0xac, 0xc9, 0x89, 0x5a, ], asset_base: [ - 0xfb, 0xd0, 0x1e, 0x66, 0xf8, 0x29, 0xbf, 0xbf, 0x9d, 0x25, 0xd7, 0x36, 0xbc, 0xb3, - 0xa1, 0x04, 0x91, 0x82, 0x81, 0x4e, 0x4d, 0xdf, 0xc2, 0x30, 0x95, 0x63, 0x8f, 0x2f, - 0xf4, 0x3c, 0x15, 0x9b, + 0x3f, 0xc0, 0xbc, 0x12, 0x07, 0x8b, 0xf1, 0xf2, 0x24, 0x09, 0x2d, 0xb5, 0x81, 0x0b, + 0x00, 0xaf, 0x8a, 0xe0, 0xb6, 0xe6, 0x35, 0x50, 0xcf, 0xdc, 0xf6, 0xd6, 0x01, 0x0f, + 0x73, 0xab, 0xb0, 0x3c, ], }, TestVector { key: [ - 0x61, 0xbb, 0x33, 0x91, 0x59, 0xdf, 0x98, 0x20, 0xef, 0xae, 0xb6, 0x1d, 0x9a, 0x10, - 0xcd, 0xc1, 0x3b, 0x4c, 0x99, 0xfd, 0xc8, 0x6d, 0x94, 0x85, 0x11, 0x5d, 0xfd, 0x83, - 0x62, 0x36, 0xac, 0xf8, + 0xb2, 0xa8, 0xb7, 0x91, 0x5b, 0x37, 0x72, 0x5a, 0xd1, 0xcf, 0x5d, 0xc6, 0xeb, 0x4c, + 0xd0, 0x9a, 0xf4, 0xe1, 0x87, 0xf8, 0xcf, 0x27, 0x37, 0xed, 0x33, 0x7c, 0x77, 0x6e, + 0x93, 0xe2, 0xa0, 0x89, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xe1, 0x9a, 0xa7, 0x70, 0xc6, 0xa8, 0xe1, 0x9b, 0x9a, 0xe1, 0x9b, 0xa2, 0xc5, 0xad, + 0x7b, 0xe2, 0xb1, 0xa0, 0xc6, 0xa6, 0xc7, 0x98, 0xc7, 0xaf, 0x36, 0x44, 0xc2, 0xb0, + 0xc8, 0x8d, 0xc4, 0xac, 0xc6, 0xab, 0x7a, 0xc9, 0x83, 0xc6, 0x97, 0xe1, 0x9b, 0xa4, + 0xe1, 0x9a, 0xa1, 0xc7, 0xb3, 0xc4, 0x92, 0xc8, 0x8f, 0xc3, 0xb4, 0xc4, 0xa6, 0xc8, + 0x82, 0xc7, 0xa7, 0xe1, 0x9a, 0xb6, 0xe2, 0xb1, 0xae, 0xc4, 0x8f, 0xe1, 0x9a, 0xa2, + 0xc7, 0xb6, 0xc5, 0xb7, 0xc5, 0xa2, 0xe2, 0xb1, 0xa2, 0xc4, 0xa7, 0xc7, 0xaa, 0xc8, + 0xa9, 0xe2, 0xb1, 0xa6, 0xc3, 0x99, 0xc6, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x8f, 0xc8, + 0xa8, 0xc7, 0x9c, 0xe1, 0x9b, 0xae, 0xc2, 0xaa, 0xc6, 0xbe, 0xc3, 0x94, 0xc5, 0x94, + 0xc3, 0x9f, 0xc6, 0xa2, 0x69, 0xe1, 0x9a, 0xab, 0xc7, 0x9d, 0xc3, 0xad, 0xc7, 0xaf, + 0xcd, 0xb5, 0xc7, 0xba, 0xc8, 0xa3, 0xc5, 0xa6, 0xe1, 0x9b, 0xae, 0xc3, 0xa5, 0xc6, + 0x8e, 0xce, 0x86, 0xc4, 0x98, 0xc5, 0xa3, 0x32, 0x39, 0xc7, 0x9e, 0xc7, 0xae, 0xe1, + 0x9a, 0xa7, 0xc3, 0x91, 0xc8, 0x84, 0xc3, 0xa0, 0xc5, 0xaf, 0x2c, 0x54, 0x4b, 0xc6, + 0x81, 0xc3, 0x81, 0x2a, 0xcd, 0xb7, 0xe2, 0xb1, 0xa8, 0x5e, 0x4a, 0xe2, 0xb1, 0xa5, + 0x2b, 0xc3, 0xa0, 0xc3, 0xb8, 0xc8, 0x91, 0xc7, 0x80, 0xc4, 0xb2, 0x66, 0x3f, 0xc4, + 0x8b, 0xc5, 0x8d, 0xc9, 0x85, 0x39, 0xc3, 0x87, 0xc4, 0x8d, 0xc2, 0xb9, 0xc3, 0xaf, + 0x45, 0xc7, 0x89, 0xc4, 0xaa, 0xc4, 0x94, 0xc4, 0x96, 0xce, 0x85, 0xe2, 0xb1, 0xb7, + 0xc4, 0xbf, 0xc6, 0x9b, 0xc4, 0xae, 0x23, 0xcd, 0xb1, 0xc2, 0xbc, 0xe1, 0x9b, 0x80, + 0xc5, 0x88, 0xc6, 0x88, 0xc4, 0xb2, 0xc7, 0xae, 0x5b, 0xc6, 0x8f, 0xc7, 0xab, 0xc5, + 0xb3, 0xe1, 0x9b, 0x83, 0xc3, 0xad, 0xc5, 0xad, 0xc7, 0xa7, 0xc2, 0xbc, 0xc8, 0x83, + 0x58, 0xc7, 0x89, 0xc7, 0xaa, 0xc9, 0x85, 0x3e, 0xc6, 0x92, 0xc7, 0x94, 0xc3, 0x92, + 0xc3, 0xa0, 0xc3, 0xb4, 0xc6, 0xa6, 0xcd, 0xb0, 0xc8, 0xa8, 0xc7, 0xa3, 0xe2, 0xb1, + 0xa3, 0x7b, 0xc6, 0x92, 0xc4, 0x91, 0xc8, 0xac, 0x50, 0xc8, 0x8b, 0xc4, 0xa9, 0xe1, + 0x9b, 0x90, 0xc4, 0xb5, 0xc8, 0x8e, 0xc3, 0xb7, 0xe2, 0xb1, 0xa2, 0xc6, 0xa1, 0xc3, + 0xb1, 0xc3, 0xba, 0x43, 0xce, 0x89, 0xc8, 0x98, 0x59, 0xcd, 0xbc, 0xe1, 0x9a, 0xa7, + 0xc8, 0xa0, 0xc6, 0x85, 0x5a, 0xc2, 0xb2, 0xc5, 0xbb, 0xc4, 0xb3, 0xc6, 0x8d, 0xc4, + 0xa6, 0xc2, 0xbd, 0xc4, 0x89, 0xe1, 0x9b, 0x9e, 0xc3, 0xae, 0xc4, 0x94, 0xc2, 0xb3, + 0xc5, 0x86, 0xc6, 0x8b, 0xc6, 0xb7, 0x2c, 0xc3, 0x9f, 0xc7, 0x80, 0xc4, 0x87, 0xc4, + 0xb0, 0xc8, 0x81, 0xc4, 0xa7, 0xce, 0x88, 0xc5, 0x86, 0xc5, 0x87, 0xe1, 0x9a, 0xa0, + 0xc6, 0x9e, 0xc6, 0x8d, 0xc7, 0x97, 0xc8, 0x9e, 0xc5, 0xb7, 0xc4, 0x9c, 0xc2, 0xba, + 0xc3, 0xac, 0xe1, 0x9b, 0x8e, 0xe1, 0x9a, 0xb6, 0x6d, 0xc5, 0x8c, 0x6d, 0xc2, 0xaf, + 0xc4, 0xa9, 0xc4, 0x97, 0xc3, 0x89, 0x4c, 0xc5, 0x9f, 0xc6, 0xbd, 0xc6, 0x8c, 0x68, + 0xc5, 0xab, 0xce, 0x84, 0xc2, 0xb2, 0xce, 0x8a, 0xc6, 0xa0, 0xc7, 0xb5, 0xc6, 0xbc, + 0xc3, 0x84, 0xc6, 0xbd, 0xc5, 0xad, 0xc3, 0x84, 0xe1, 0x9b, 0xaf, 0xe2, 0xb1, 0xbc, + 0xc6, 0xa8, 0xc3, 0x8d, 0xe2, 0xb1, 0xb2, 0xc3, 0xb9, 0xc9, 0x8f, 0x33, 0xc8, 0x8a, + 0xc4, 0xb5, 0xc6, 0x8a, 0xc4, 0x9f, 0xc8, 0x84, 0xc4, 0x9c, 0xc4, 0x9f, 0xc7, 0xa0, + 0xc8, 0x8d, 0xc7, 0x88, 0xe2, 0xb1, 0xb7, 0xe2, 0xb1, 0xa3, 0xe1, 0x9b, 0xad, 0x60, + 0xc4, 0x94, 0xc5, 0x80, 0xc8, 0x96, 0xc6, 0xb3, ], asset_base: [ - 0xd0, 0x46, 0xef, 0xd5, 0xe2, 0xf1, 0xdd, 0x27, 0x2c, 0x7e, 0x65, 0x8a, 0x72, 0x1d, - 0x36, 0x21, 0x4c, 0x4d, 0xbc, 0x03, 0xf5, 0x99, 0x04, 0x3e, 0x6e, 0xfc, 0xbf, 0xb5, - 0x6a, 0x6e, 0x90, 0x28, + 0x70, 0xc1, 0x47, 0xec, 0x23, 0x32, 0x10, 0xed, 0xdf, 0xab, 0x14, 0xcb, 0xca, 0x72, + 0x4d, 0xd2, 0x8e, 0x2b, 0xc5, 0x7f, 0xb7, 0xb0, 0xd3, 0x44, 0x6d, 0x79, 0x7f, 0x94, + 0xbc, 0xeb, 0xd0, 0xb8, ], }, TestVector { key: [ - 0x49, 0x26, 0x53, 0x80, 0xd2, 0xb0, 0x2e, 0x0a, 0x1d, 0x98, 0x8f, 0x3d, 0xe3, 0x45, - 0x8b, 0x6e, 0x00, 0x29, 0x1d, 0xb0, 0xe6, 0x2e, 0x17, 0x47, 0x91, 0xd0, 0x09, 0x29, - 0x9f, 0x61, 0xfe, 0xc4, + 0xe6, 0xdf, 0x3e, 0xbc, 0x84, 0x4c, 0x0c, 0x39, 0xcb, 0x25, 0xac, 0x91, 0xd6, 0xc1, + 0xd9, 0x20, 0x0f, 0x18, 0xfa, 0x7e, 0x8c, 0x93, 0x4c, 0x4d, 0x0c, 0x30, 0x9d, 0x79, + 0xb0, 0x4a, 0xb4, 0x43, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xe1, 0x9a, 0xa5, 0xc4, 0x80, 0xc3, 0x85, 0xc5, 0xa4, 0xc5, 0xbb, 0xc7, 0xbf, 0x34, + 0xc9, 0x84, 0xc7, 0x81, 0xc5, 0xbe, 0xc7, 0xbc, 0xe1, 0x9b, 0x97, 0xc5, 0x9e, 0xe2, + 0xb1, 0xbc, 0x37, 0xc8, 0x83, 0x30, 0xc8, 0x84, 0xc6, 0xb3, 0xc8, 0x97, 0xc6, 0xac, + 0xc4, 0xa0, 0x51, 0xc7, 0xab, 0xc8, 0xa3, 0xc3, 0xa9, 0xc5, 0x92, 0xc3, 0x8d, 0xc2, + 0xa3, 0xc5, 0xb9, 0xc8, 0xab, 0xc5, 0xa1, 0x70, 0xc7, 0x85, 0xc7, 0xbf, 0xcd, 0xbd, + 0xc6, 0xab, 0x4c, 0xe1, 0x9a, 0xa5, 0x36, 0xc5, 0xa1, 0xc4, 0xad, 0x4c, 0xc8, 0x92, + 0xc6, 0x9e, 0xc4, 0xbd, 0xc5, 0x95, 0xc3, 0xb4, 0x56, 0xc3, 0xb0, 0xc8, 0xa8, 0xe1, + 0x9a, 0xbf, 0xc4, 0x98, 0xc8, 0xaa, 0x33, 0xc4, 0x97, 0xe1, 0x9a, 0xb2, 0xc9, 0x86, + 0xc2, 0xb1, 0xe1, 0x9b, 0xa2, 0xe1, 0x9b, 0x97, 0xc5, 0xa6, 0x4b, 0xc3, 0x88, 0xe1, + 0x9a, 0xac, 0xce, 0x86, 0xc3, 0x8a, 0xc4, 0x98, 0xc4, 0x89, 0x48, 0xc7, 0xad, 0xe1, + 0x9b, 0x8f, 0xe1, 0x9b, 0xa8, 0xcd, 0xb2, 0xc3, 0xb1, 0xc4, 0xa6, 0xc3, 0xb2, 0xc4, + 0xb1, 0xc8, 0xb4, 0xc3, 0xa9, 0xc9, 0x8d, 0xc7, 0xb6, 0xc4, 0xa0, 0xc6, 0x9b, 0xc6, + 0xbd, 0xc7, 0xaf, 0xc3, 0x9c, 0xe2, 0xb1, 0xa0, 0xe1, 0x9b, 0x96, 0xc3, 0x87, 0xcd, + 0xb4, 0xc6, 0x8c, 0xcd, 0xb7, 0xc7, 0xba, 0xc3, 0x94, 0xc8, 0xa3, 0xc3, 0x9e, 0xe1, + 0x9a, 0xa9, 0xc6, 0x98, 0xc6, 0x8a, 0xc5, 0xb6, 0xc9, 0x8b, 0x59, 0xcd, 0xbc, 0xc6, + 0x91, 0xc6, 0xa1, 0xc4, 0x8a, 0xe1, 0x9b, 0xad, 0x31, 0xc9, 0x89, 0xc4, 0x97, 0xc3, + 0xa4, 0xc4, 0x8f, 0xce, 0x8a, 0xe1, 0x9b, 0x8c, 0xc3, 0x9c, 0xc3, 0x89, 0xc6, 0x83, + 0xc9, 0x81, 0xc8, 0x95, 0xc4, 0x9e, 0x39, 0xc8, 0x86, 0xc7, 0x97, 0xc7, 0x87, 0xc2, + 0xa8, 0x23, 0xc3, 0x90, 0xcd, 0xb0, 0xc3, 0x9f, 0xc6, 0xac, 0xc5, 0x81, 0xc7, 0xa2, + 0x78, 0x57, 0xc2, 0xaf, 0xc2, 0xa7, 0x5d, 0xc8, 0x8e, 0x73, 0xe1, 0x9b, 0xa8, 0xc8, + 0x95, 0xc5, 0x99, 0xc2, 0xb3, 0xc5, 0xb8, 0xe1, 0x9a, 0xa8, 0xc8, 0x85, 0xc7, 0x82, + 0xc8, 0x8a, 0x34, 0xc3, 0xbd, 0xe1, 0x9b, 0x99, 0xe1, 0x9b, 0xaa, 0xc8, 0xb2, 0xc5, + 0xa7, 0xc7, 0xb2, 0xc6, 0x98, 0x40, 0xe1, 0x9a, 0xb8, 0xe1, 0x9a, 0xb4, 0x77, 0xc2, + 0xa2, 0xe1, 0x9a, 0xa4, 0xc5, 0x84, 0xe2, 0xb1, 0xa7, 0xc4, 0xbc, 0xc5, 0xb3, 0xe2, + 0xb1, 0xa2, 0xc8, 0xb4, 0xc8, 0xbd, 0xc6, 0x98, 0xc8, 0xa9, 0x78, 0xc8, 0x9b, 0xc3, + 0x85, 0xc5, 0xaf, 0xc5, 0x83, 0x34, 0x5f, 0xc5, 0x88, 0xe1, 0x9a, 0xb3, 0x7d, 0xc4, + 0xa5, 0xc3, 0xb4, 0xe1, 0x9a, 0xb3, 0xc7, 0x8e, 0xc5, 0x86, 0xc4, 0x94, 0xc7, 0x89, + 0xe1, 0x9b, 0x8a, 0xe1, 0x9b, 0xa4, 0xc6, 0x9a, 0xc3, 0x8e, 0xc5, 0xa9, 0xc6, 0xbe, + 0xe2, 0xb1, 0xb5, 0xc4, 0xb2, 0xc3, 0x88, 0xc5, 0xb2, 0xc8, 0xa7, 0xe1, 0x9b, 0x8a, + 0xc4, 0x9f, 0xc7, 0x94, 0xe1, 0x9a, 0xb5, 0xc9, 0x83, 0xc6, 0xb5, 0xe2, 0xb1, 0xa0, + 0xc4, 0xb0, 0x59, 0xe1, 0x9b, 0x9f, 0xc4, 0xa9, 0xc3, 0x96, 0xc7, 0xba, 0xc5, 0xad, + 0xc3, 0xaf, 0xc3, 0xa1, 0xc6, 0x86, 0xc2, 0xb8, 0xe1, 0x9b, 0xa7, 0xc2, 0xb2, 0xc4, + 0x9d, 0xc8, 0x87, 0xc9, 0x89, 0xe1, 0x9a, 0xa8, 0xc4, 0x8a, 0xc5, 0xbe, 0x33, 0xc7, + 0x89, 0xce, 0x8c, 0xc9, 0x85, 0x4b, 0xc7, 0xa6, 0x76, 0xc8, 0xbc, 0xc2, 0xb2, 0xcd, + 0xbb, 0xe1, 0x9b, 0xa5, 0xc8, 0x9d, 0xc7, 0xa1, 0xc7, 0xb3, 0xe1, 0x9a, 0xb5, 0xc7, + 0x94, 0xc4, 0x86, 0xe1, 0x9a, 0xa2, 0xc8, 0xb1, 0xc3, 0x97, 0xc8, 0xb3, 0xe2, 0xb1, + 0xb2, 0xc6, 0xb9, 0xc3, 0xb5, 0x74, 0xc2, 0xb3, ], asset_base: [ - 0xe1, 0x39, 0xe7, 0x7a, 0x0b, 0x76, 0xfc, 0x01, 0xa1, 0xec, 0x3b, 0x46, 0xf0, 0x21, - 0x29, 0x7b, 0xfb, 0x41, 0xd1, 0x7f, 0x5f, 0x98, 0x3d, 0xed, 0x61, 0x81, 0xee, 0xd9, - 0x5d, 0xe4, 0x2e, 0xb6, + 0x85, 0x94, 0x73, 0xb4, 0x98, 0xbb, 0x99, 0x99, 0x4a, 0x06, 0x71, 0x0e, 0x5c, 0xd2, + 0x10, 0x78, 0xa5, 0x22, 0xea, 0xa5, 0xf6, 0xad, 0x2d, 0x22, 0xe5, 0x12, 0x57, 0x6d, + 0x8c, 0x89, 0x65, 0x21, ], }, TestVector { key: [ - 0x19, 0x58, 0x53, 0x8b, 0x12, 0x17, 0xa0, 0x3d, 0x89, 0xcd, 0x83, 0xb8, 0x3d, 0x0b, - 0xdd, 0x40, 0xa6, 0x9a, 0xbe, 0x3a, 0xc2, 0x5d, 0x00, 0xc6, 0xd2, 0x69, 0x97, 0xf9, - 0xf2, 0x57, 0x4d, 0x4f, + 0xdb, 0x1f, 0x0a, 0x56, 0x5c, 0x8c, 0x06, 0xa6, 0x3d, 0x4f, 0x75, 0x92, 0x62, 0x55, + 0xf4, 0xfa, 0x3c, 0x76, 0x44, 0x23, 0xc0, 0x49, 0x55, 0x02, 0x4e, 0xa0, 0x3b, 0xba, + 0x63, 0x63, 0x6c, 0x55, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc6, 0xa7, 0xe1, 0x9b, 0x8e, 0xc6, 0x8d, 0xc6, 0x88, 0xc2, 0xa3, 0xc4, 0xbe, 0xc6, + 0x93, 0xc5, 0x95, 0xe1, 0x9b, 0x88, 0xc3, 0x82, 0xc4, 0xa5, 0x32, 0xc7, 0x95, 0xc9, + 0x88, 0xc5, 0xbd, 0xe1, 0x9b, 0x85, 0xc9, 0x84, 0xc3, 0x80, 0xe2, 0xb1, 0xa8, 0xc6, + 0xac, 0xe1, 0x9b, 0x82, 0xc5, 0x82, 0x29, 0xc4, 0x80, 0xc8, 0x9c, 0xc6, 0x88, 0xc3, + 0xba, 0xc8, 0xa1, 0xe1, 0x9a, 0xb8, 0xc3, 0xbb, 0xc3, 0xb8, 0xc6, 0x90, 0x24, 0xc8, + 0x8b, 0xe1, 0x9a, 0xa1, 0x31, 0xc8, 0x9c, 0xe1, 0x9a, 0xa4, 0xe1, 0x9b, 0x82, 0xc2, + 0xb6, 0xc6, 0xb1, 0xe1, 0x9b, 0x87, 0x49, 0xc4, 0xba, 0xe2, 0xb1, 0xb5, 0x32, 0xc6, + 0x99, 0xc7, 0x9b, 0xc7, 0x85, 0x67, 0xc6, 0xa5, 0xc9, 0x8b, 0x45, 0x77, 0xc6, 0x9e, + 0x3d, 0xc4, 0x82, 0xe2, 0xb1, 0xaf, 0xc6, 0x87, 0xe1, 0x9a, 0xb0, 0xe1, 0x9a, 0xa0, + 0xc9, 0x88, 0xc3, 0x98, 0xc3, 0xa7, 0xc6, 0x9b, 0xc7, 0x9c, 0xc4, 0xb5, 0xc3, 0xaf, + 0xc4, 0xa9, 0xc3, 0xb8, 0xc5, 0xaf, 0xc2, 0xac, 0xc9, 0x8a, 0xe1, 0x9b, 0x8c, 0x47, + 0xe1, 0x9b, 0xaa, 0xe1, 0x9a, 0xb6, 0x24, 0xc8, 0x9c, 0x4f, 0xc8, 0xb7, 0x64, 0xe1, + 0x9a, 0xad, 0xc9, 0x87, 0xc2, 0xbe, 0xe1, 0x9b, 0x89, 0x6c, 0xe2, 0xb1, 0xac, 0xc5, + 0x8e, 0xe1, 0x9b, 0x87, 0xe2, 0xb1, 0xb0, 0xc3, 0xb1, 0xc3, 0x8e, 0xc3, 0x89, 0xe1, + 0x9b, 0x9f, 0xc4, 0xb7, 0x42, 0xc6, 0xb6, 0xc6, 0x9d, 0xc2, 0xa7, 0xc2, 0xb1, 0xc4, + 0xa5, 0xc6, 0xa3, 0xc8, 0x84, 0xc7, 0x85, 0x74, 0xe2, 0xb1, 0xbb, 0xe2, 0xb1, 0xaf, + 0xc7, 0x87, 0x5b, 0xc6, 0xa7, 0xc4, 0x91, 0xc5, 0x95, 0xc8, 0xa6, 0xc4, 0xb0, 0xe1, + 0x9b, 0xac, 0xe1, 0x9b, 0x8b, 0xc3, 0x95, 0xe1, 0x9a, 0xaf, 0xc3, 0x85, 0xc4, 0xbf, + 0xc2, 0xb0, 0xc5, 0x97, 0xc5, 0xa3, 0xc5, 0xb2, 0xc6, 0xad, 0x60, 0xc5, 0x8b, 0xc3, + 0x88, 0xe2, 0xb1, 0xb4, 0xc2, 0xbd, 0xc7, 0xbb, 0xe2, 0xb1, 0xab, 0xc4, 0x99, 0xc4, + 0x91, 0x21, 0xc9, 0x8d, 0xc6, 0x92, 0xc7, 0x95, 0x32, 0xe1, 0x9b, 0xa3, 0xc5, 0x86, + 0xc7, 0x95, 0xc8, 0xba, 0xe2, 0xb1, 0xbb, 0xc3, 0x89, 0xc6, 0x9c, 0xc6, 0x92, 0xe2, + 0xb1, 0xab, 0xc4, 0xaf, 0xc5, 0x81, 0xc4, 0x80, 0xc3, 0x98, 0xc4, 0xad, 0xc5, 0x8b, + 0xc6, 0xb5, 0x53, 0xc7, 0x8a, 0x43, 0xc4, 0x95, 0xc4, 0xad, 0xc8, 0xba, 0xe1, 0x9a, + 0xb8, 0x7b, 0xc3, 0xb2, 0x33, 0xc2, 0xb6, 0xc5, 0x8b, 0xe1, 0x9a, 0xb5, 0x74, 0x34, + 0xc8, 0x9f, 0xc6, 0x83, 0x3d, 0xc2, 0xb1, 0x6b, 0xc4, 0xa8, 0xc3, 0xb5, 0xc7, 0x8c, + 0xc7, 0x84, 0x2e, 0xc8, 0x85, 0xc4, 0x99, 0xc7, 0x8e, 0x60, 0x4b, 0xc4, 0x93, 0xe2, + 0xb1, 0xbe, 0xc7, 0x88, 0xc3, 0x86, 0x48, 0x5d, 0xc6, 0xa1, 0x78, 0xc7, 0xaa, 0xc7, + 0x85, 0x29, 0xc7, 0x82, 0xc3, 0x9c, 0xc6, 0xbe, 0xe1, 0x9b, 0x82, 0x2c, 0xc8, 0xa3, + 0xc8, 0x95, 0xc8, 0xbe, 0xc3, 0x94, 0xc8, 0xad, 0xcd, 0xb2, 0xc3, 0xa2, 0xc4, 0xbd, + 0xe1, 0x9b, 0x98, 0xe2, 0xb1, 0xac, 0xc3, 0x8d, 0xc3, 0x99, 0xc4, 0xb1, 0xe1, 0x9b, + 0x83, 0xe1, 0x9a, 0xb3, 0x72, 0xc6, 0xa2, 0x37, 0xe1, 0x9b, 0xaf, 0xc3, 0x98, 0xc4, + 0x99, 0xc3, 0xa0, 0xc7, 0xb5, 0xc6, 0x97, 0x6d, 0xc5, 0xb0, 0xc7, 0xa6, 0xe2, 0xb1, + 0xa5, 0xc5, 0xa8, 0xc3, 0xa8, 0xc5, 0x9b, 0xe1, 0x9a, 0xa1, 0xc7, 0xb5, 0x78, 0xe2, + 0xb1, 0xbb, 0xe1, 0x9b, 0xa7, 0xc6, 0xae, 0xe1, 0x9a, 0xbb, 0xc4, 0xba, 0xc5, 0xa7, + 0xc4, 0x86, 0xc5, 0x94, 0xc8, 0xb4, 0xc3, 0xa3, 0xc8, 0x83, 0xc8, 0x8a, 0xc5, 0xb6, + 0xcd, 0xbc, 0xe1, 0x9a, 0xbc, 0xe2, 0xb1, 0xa8, ], asset_base: [ - 0xb3, 0xd1, 0x28, 0x2b, 0xf4, 0x32, 0x3d, 0xc3, 0x01, 0xa2, 0xd5, 0x9b, 0x8b, 0x80, - 0x41, 0xe2, 0xd2, 0x9b, 0x69, 0xee, 0x9b, 0xbc, 0x1c, 0x41, 0x06, 0xd3, 0x60, 0x1e, - 0x40, 0x39, 0x61, 0x3e, + 0xb2, 0xea, 0x85, 0x07, 0x94, 0x73, 0xf8, 0x06, 0xce, 0x30, 0xca, 0xe0, 0xbf, 0x6c, + 0xb9, 0xc9, 0xeb, 0x91, 0x72, 0xc0, 0xb9, 0x86, 0x47, 0x7a, 0xb9, 0x04, 0xd1, 0xfa, + 0x68, 0x49, 0x01, 0x2e, ], }, TestVector { key: [ - 0x9a, 0x0e, 0x46, 0x39, 0xb4, 0x69, 0x1f, 0x02, 0x7c, 0x0d, 0xb7, 0xfe, 0xf1, 0xbb, - 0x5e, 0xf9, 0x0a, 0xcd, 0xb7, 0x08, 0x62, 0x6d, 0x2e, 0x1f, 0x3e, 0x38, 0x3e, 0xe7, - 0x5b, 0x31, 0xcf, 0x57, + 0x98, 0x9f, 0xc7, 0x01, 0x45, 0xd2, 0xfb, 0xb4, 0xd2, 0xe2, 0x79, 0xe5, 0xf9, 0x5d, + 0x72, 0x9f, 0x6a, 0xf4, 0xe9, 0x83, 0x28, 0x53, 0xf5, 0x97, 0xaf, 0x2f, 0xfb, 0xfb, + 0x88, 0xa6, 0x6e, 0xba, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xce, 0x8a, 0xc7, 0xb5, 0xc7, 0xbd, 0xc2, 0xae, 0x66, 0xc6, 0xbd, 0xc8, 0xa0, 0xc7, + 0x85, 0x4f, 0xe1, 0x9b, 0xa4, 0xc3, 0xb4, 0xe1, 0x9b, 0x92, 0xc6, 0xa6, 0xc6, 0x95, + 0xc5, 0x97, 0xc6, 0x97, 0xcd, 0xb2, 0xc6, 0x81, 0xc8, 0xaa, 0xe1, 0x9b, 0x8a, 0xc7, + 0xa0, 0xc4, 0xaa, 0xe1, 0x9b, 0xa9, 0x79, 0xe2, 0xb1, 0xb2, 0xc8, 0xba, 0xc3, 0x96, + 0xc8, 0x85, 0xe2, 0xb1, 0xb1, 0xc5, 0x82, 0x2e, 0xc7, 0x8b, 0xc7, 0x85, 0xe2, 0xb1, + 0xbb, 0xe1, 0x9b, 0xab, 0xc9, 0x8a, 0x3c, 0xc3, 0x9b, 0xc8, 0xac, 0xc2, 0xae, 0xc5, + 0x86, 0xc2, 0xbb, 0xc3, 0x89, 0xc8, 0x9a, 0x7b, 0xc2, 0xbe, 0xc7, 0x99, 0xc5, 0xb2, + 0xc4, 0x81, 0xc6, 0xb2, 0xc8, 0x96, 0xc7, 0xb2, 0xc8, 0xba, 0xc5, 0xac, 0xce, 0x88, + 0xc5, 0x94, 0xc3, 0xbd, 0xc8, 0x81, 0xc5, 0x94, 0xc3, 0xad, 0xc7, 0x83, 0x73, 0xc4, + 0xba, 0xe2, 0xb1, 0xad, 0xe1, 0x9a, 0xbb, 0xc5, 0x84, 0xc5, 0xbd, 0x40, 0xc3, 0x9c, + 0xc7, 0xbb, 0xc4, 0xbb, 0xc6, 0xba, 0x67, 0x41, 0xe2, 0xb1, 0xaf, 0xe1, 0x9a, 0xba, + 0xc6, 0xa9, 0xe1, 0x9b, 0x8d, 0x48, 0xc4, 0xa8, 0xc7, 0x88, 0xc3, 0x9b, 0xc8, 0x8a, + 0x65, 0xc3, 0xab, 0xe1, 0x9b, 0x9a, 0xe1, 0x9b, 0x8d, 0x52, 0xe1, 0x9a, 0xa1, 0xc8, + 0x8b, 0x29, 0xc3, 0x9a, 0xc7, 0x86, 0xc3, 0x95, 0xe2, 0xb1, 0xa8, 0xe1, 0x9b, 0x8f, + 0xc5, 0x94, 0xc4, 0x8e, 0x44, 0xc6, 0xa2, 0xc5, 0x88, 0x3e, 0x7a, 0xc8, 0x9f, 0xe1, + 0x9a, 0xa5, 0xc4, 0x9b, 0xc5, 0xa7, 0xc5, 0x91, 0xc3, 0x8e, 0xc7, 0xb2, 0xc4, 0x83, + 0x38, 0xe2, 0xb1, 0xb4, 0xc5, 0xb9, 0xc4, 0xbb, 0xc7, 0x88, 0x4d, 0xc2, 0xa5, 0xe2, + 0xb1, 0xaf, 0xe1, 0x9a, 0xaa, 0x72, 0xe2, 0xb1, 0xba, 0xc8, 0x8b, 0xe1, 0x9b, 0xaa, + 0xc7, 0x90, 0xc5, 0xaa, 0x29, 0xc7, 0xa8, 0xc5, 0x90, 0xc7, 0xa9, 0xcd, 0xb7, 0xc8, + 0xa9, 0xc8, 0x88, 0xc6, 0x8a, 0xc4, 0x84, 0xc4, 0xa2, 0xc7, 0xa2, 0xe1, 0x9a, 0xba, + 0xc2, 0xb4, 0xe1, 0x9b, 0x8d, 0xc6, 0x91, 0xcd, 0xb1, 0xc5, 0xa5, 0xc3, 0xb3, 0x39, + 0xe1, 0x9b, 0x85, 0xc4, 0xbe, 0xc4, 0x9e, 0xcd, 0xb1, 0xc6, 0x83, 0x69, 0xc3, 0xba, + 0xe1, 0x9b, 0x95, 0xc2, 0xbf, 0xc6, 0xbd, 0x53, 0xc7, 0xb9, 0xc8, 0x9b, 0x5b, 0xc9, + 0x8c, 0xc7, 0xa1, 0xc8, 0xaa, 0xcd, 0xbc, 0xc4, 0xb0, 0xcd, 0xb6, 0xc4, 0x93, 0xc4, + 0xab, 0xe1, 0x9b, 0x86, 0xc6, 0xaf, 0xc5, 0x9b, 0xc2, 0xb3, 0xc3, 0xa3, 0xe1, 0x9a, + 0xb1, 0xe1, 0x9b, 0x8a, 0xc5, 0x90, 0xc6, 0xa5, 0xc2, 0xae, 0x51, 0x5b, 0xce, 0x86, + 0xc9, 0x8c, 0xc7, 0x8f, 0xc6, 0x95, 0xc5, 0x88, 0xc7, 0x82, 0xc5, 0xa2, 0xce, 0x85, + 0xc8, 0x85, 0xc3, 0x85, 0xc7, 0xb1, 0xc7, 0xbe, 0xc8, 0x8c, 0xe1, 0x9b, 0x8d, 0xc8, + 0x90, 0xc4, 0xb6, 0xc3, 0xbf, 0xe1, 0x9b, 0x86, 0xc6, 0xb8, 0xe2, 0xb1, 0xb5, 0xc3, + 0x8e, 0xc8, 0x9b, 0xcd, 0xb7, 0xc5, 0x94, 0xc5, 0x86, 0xc5, 0x9f, 0xc4, 0xb0, 0xc7, + 0xa6, 0xc2, 0xbd, 0x70, 0xc6, 0xac, 0xc8, 0xb7, 0xe1, 0x9b, 0x96, 0xc5, 0xbe, 0xc5, + 0x97, 0xe1, 0x9a, 0xb9, 0xc3, 0xa7, 0xe2, 0xb1, 0xb4, 0xc5, 0xb6, 0x24, 0x49, 0x26, + 0xc5, 0x82, 0xc9, 0x8c, 0xc6, 0x9d, 0xc5, 0x93, 0xc3, 0x85, 0xc3, 0x98, 0xc8, 0xbe, + 0x4e, 0xc5, 0xae, 0x44, 0x67, 0xe1, 0x9a, 0xa5, 0xc7, 0xb1, 0xc4, 0xb6, 0xc7, 0xaf, + 0x5d, 0xc3, 0xb9, 0xc3, 0xb5, 0xc3, 0xab, 0xc7, 0x83, 0xc7, 0xb3, 0xe1, 0x9b, 0x99, + 0xc4, 0x9d, 0xc3, 0x83, 0xc3, 0xb4, 0xc5, 0xb2, 0xc7, 0xbe, 0x5e, 0xcd, 0xba, 0xc9, + 0x87, 0xe2, 0xb1, 0xbd, 0xc8, 0x8f, 0xc9, 0x8c, ], asset_base: [ - 0x2b, 0xb6, 0x4e, 0xa4, 0x07, 0xfd, 0x00, 0xb6, 0x4c, 0xe5, 0x96, 0x2e, 0x57, 0x3f, - 0xaf, 0x9a, 0x40, 0xfb, 0x3a, 0x4d, 0xc1, 0xcc, 0xbf, 0x87, 0xe1, 0xe0, 0xe7, 0x97, - 0x8a, 0x19, 0xbd, 0x39, + 0x1a, 0x51, 0xbf, 0x64, 0x82, 0x22, 0x09, 0x2a, 0x98, 0x5b, 0x0e, 0x94, 0xfa, 0x1d, + 0xb4, 0xb4, 0xbf, 0xad, 0x07, 0x8f, 0xbe, 0x75, 0xc1, 0xbf, 0x83, 0x1c, 0x47, 0xd3, + 0x54, 0x6f, 0xbc, 0x38, ], }, TestVector { key: [ - 0x7d, 0xd6, 0xd7, 0x61, 0xe1, 0x02, 0x01, 0x37, 0xfa, 0x01, 0xb4, 0xdd, 0xd3, 0xb0, - 0xf3, 0x48, 0x04, 0xcc, 0x10, 0xcc, 0x4e, 0x9f, 0x6e, 0x9d, 0xf5, 0xb6, 0x04, 0x69, - 0xf5, 0x79, 0x36, 0x67, + 0x1d, 0xa0, 0x2d, 0x7e, 0x6a, 0x75, 0x4b, 0xe4, 0xde, 0xfa, 0x04, 0x90, 0x29, 0xc7, + 0x94, 0x8b, 0x5e, 0xd2, 0x5b, 0x4d, 0x22, 0xbf, 0x87, 0x27, 0x0b, 0x9d, 0x32, 0xda, + 0x52, 0x81, 0x92, 0x24, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xe1, 0x9b, 0x9c, 0xe1, 0x9a, 0xa5, 0xc5, 0xb7, 0x2b, 0xc3, 0x81, 0xc3, 0x8d, 0xc8, + 0xb2, 0xc8, 0xb5, 0xc5, 0x81, 0xc5, 0x9e, 0xc7, 0xa7, 0xe1, 0x9b, 0x8b, 0xc7, 0xb7, + 0xe1, 0x9b, 0x80, 0x6d, 0xc8, 0x94, 0x64, 0xc6, 0x88, 0xe2, 0xb1, 0xa6, 0xc6, 0x8f, + 0xc9, 0x82, 0x5d, 0xe1, 0x9a, 0xae, 0xe2, 0xb1, 0xa8, 0xc2, 0xb1, 0xc7, 0xa3, 0xc8, + 0x87, 0xc3, 0xb4, 0xe2, 0xb1, 0xbe, 0xc6, 0xba, 0xc3, 0x9d, 0xc8, 0xbd, 0xe1, 0x9a, + 0xae, 0x74, 0xe2, 0xb1, 0xa2, 0xc8, 0x9f, 0xcd, 0xb2, 0xc4, 0x9a, 0xe1, 0x9a, 0xb7, + 0xc7, 0xa4, 0xe1, 0x9a, 0xa2, 0xc5, 0x95, 0xc7, 0x85, 0xc7, 0xa3, 0x4c, 0xc7, 0xb6, + 0xcd, 0xbd, 0x26, 0xc7, 0x9b, 0xc4, 0xb4, 0xc6, 0xa0, 0xe1, 0x9a, 0xbe, 0xce, 0x85, + 0xc2, 0xae, 0x38, 0xc7, 0xab, 0xc6, 0x87, 0xc5, 0xab, 0xc4, 0xb2, 0xc6, 0xb5, 0xc8, + 0xb3, 0xc7, 0xa6, 0xc3, 0xbd, 0xc5, 0xba, 0x4a, 0xc7, 0x8e, 0xc7, 0x8e, 0xc2, 0xb2, + 0x49, 0xc5, 0xb1, 0x5a, 0xc3, 0xaa, 0xc6, 0x8b, 0xc5, 0x86, 0x4f, 0xc8, 0xbd, 0x49, + 0xc3, 0x98, 0xc5, 0x8e, 0xc9, 0x8a, 0xc8, 0x92, 0x36, 0xe1, 0x9b, 0xad, 0xe1, 0x9b, + 0x9c, 0xc3, 0xa7, 0xc8, 0xab, 0xc4, 0xac, 0xe1, 0x9a, 0xa9, 0xc8, 0xbe, 0xc7, 0xb2, + 0xe1, 0x9a, 0xb3, 0xc8, 0x8c, 0xc7, 0x8f, 0xe2, 0xb1, 0xa3, 0xc5, 0xaf, 0xc6, 0x9f, + 0xc7, 0x92, 0xe1, 0x9b, 0xad, 0x4b, 0xc2, 0xb1, 0xc4, 0x9c, 0xcd, 0xbd, 0xc5, 0xba, + 0xc6, 0xb2, 0xe2, 0xb1, 0xb7, 0xc6, 0xb1, 0xc2, 0xba, 0xc6, 0xa8, 0xc8, 0x89, 0xc5, + 0x97, 0xc5, 0xaf, 0xe1, 0x9b, 0x8e, 0xc5, 0x9d, 0xc4, 0xa4, 0xc3, 0xb9, 0xc8, 0x8b, + 0xc7, 0x84, 0xc5, 0xaa, 0x7b, 0x78, 0xe1, 0x9b, 0x81, 0x60, 0x5e, 0xc3, 0x91, 0xc6, + 0xb4, 0x4f, 0xc9, 0x8d, 0xc4, 0xa3, 0xc5, 0x90, 0xe1, 0x9a, 0xbd, 0xc5, 0x93, 0xc3, + 0xab, 0xc6, 0x9e, 0xc7, 0xb5, 0xc5, 0xa5, 0xc7, 0xba, 0xe2, 0xb1, 0xb9, 0xe1, 0x9a, + 0xa9, 0x2a, 0xe1, 0x9a, 0xae, 0xc3, 0xb7, 0xc9, 0x87, 0x4c, 0xc7, 0x86, 0xc9, 0x81, + 0xc6, 0xba, 0xc8, 0x87, 0xc7, 0x96, 0x57, 0xc5, 0xab, 0xc2, 0xa5, 0xc3, 0x85, 0xc8, + 0x8f, 0xe1, 0x9b, 0x89, 0xc2, 0xb6, 0xc2, 0xa7, 0xc7, 0x80, 0xc8, 0xb4, 0xcd, 0xb4, + 0xc9, 0x88, 0xc8, 0x85, 0xc7, 0xb7, 0xc8, 0x99, 0x3d, 0xc7, 0x9f, 0xc7, 0x8f, 0xc4, + 0xa0, 0xc7, 0xb6, 0xc4, 0x80, 0xc3, 0x85, 0xe1, 0x9a, 0xbc, 0xc3, 0x90, 0xc4, 0xb0, + 0xc4, 0x83, 0xe1, 0x9a, 0xa4, 0xc9, 0x8e, 0x36, 0xc4, 0xb2, 0xc4, 0x94, 0xc6, 0xbf, + 0xe2, 0xb1, 0xbd, 0xc5, 0xae, 0xc2, 0xae, 0xe1, 0x9b, 0xa9, 0xc5, 0x96, 0xc8, 0x9d, + 0xc5, 0xb7, 0xc3, 0x8c, 0xc8, 0xae, 0xe2, 0xb1, 0xaf, 0xc5, 0xa6, 0xc4, 0xac, 0x24, + 0x6d, 0xc8, 0x99, 0xc7, 0x9d, 0x2c, 0xc2, 0xac, 0xc6, 0xbe, 0xc2, 0xac, 0xc9, 0x88, + 0xc5, 0xa8, 0xc6, 0xa1, 0xcd, 0xb2, 0xc6, 0xa7, 0x5d, 0xc8, 0xa0, 0xc8, 0xb2, 0xc4, + 0x83, 0xc3, 0xb9, 0xc4, 0xa0, 0xc5, 0x86, 0x54, 0x5d, 0xe1, 0x9b, 0xb0, 0xc5, 0x94, + 0x35, 0xe1, 0x9a, 0xb7, 0xe2, 0xb1, 0xa6, 0xc8, 0xa9, 0xc8, 0xa6, 0xcd, 0xb6, 0xc8, + 0xa1, 0x6b, 0xc5, 0x9b, 0x73, 0xc3, 0x98, 0xc3, 0xa3, 0xc5, 0xb8, 0xe1, 0x9b, 0x9f, + 0xc5, 0xb5, 0xc5, 0x99, 0xc4, 0xa2, 0xc3, 0x81, 0xc9, 0x87, 0xe1, 0x9a, 0xac, 0x59, + 0xc8, 0xbb, 0xc6, 0x8b, 0xc4, 0xa8, 0xc4, 0x95, 0xc8, 0xb9, 0xc2, 0xa6, 0xc5, 0xbc, + 0xc4, 0x87, 0xc5, 0x94, 0xc4, 0x9e, 0x5e, 0xc3, 0xb0, 0x2a, 0x3a, 0xe1, 0x9b, 0x81, + 0xc7, 0xab, 0xc5, 0x92, 0xc8, 0x8c, 0x5a, 0x5a, ], asset_base: [ - 0xb0, 0x42, 0x08, 0x91, 0xec, 0xa6, 0x2d, 0x05, 0xd6, 0x89, 0x51, 0x5a, 0x33, 0x90, - 0xec, 0x57, 0xd8, 0xf7, 0xe9, 0x53, 0xea, 0x89, 0xcc, 0x01, 0xdd, 0xd3, 0xc1, 0x94, - 0x39, 0xe5, 0x18, 0x21, + 0xb1, 0x08, 0xcf, 0xf7, 0x04, 0xbf, 0xce, 0x2b, 0xdb, 0x86, 0xdb, 0xb8, 0x40, 0x3f, + 0x02, 0x20, 0x3f, 0x1c, 0xa1, 0x50, 0x2d, 0x5e, 0x24, 0xe2, 0x21, 0xc2, 0x23, 0xd7, + 0xeb, 0x82, 0xb2, 0x18, ], }, TestVector { key: [ - 0xbb, 0xf4, 0x49, 0x82, 0xf1, 0xba, 0x3a, 0x2b, 0x9d, 0xd3, 0xc1, 0x77, 0x4d, 0x71, - 0xce, 0x33, 0x60, 0x59, 0x9b, 0x07, 0xf2, 0x11, 0xc8, 0x16, 0xb8, 0xc4, 0x3b, 0x98, - 0x42, 0x23, 0x09, 0x24, + 0x72, 0xab, 0x8e, 0x45, 0x8e, 0xd4, 0xc8, 0xf2, 0xc5, 0xba, 0xa1, 0x18, 0x50, 0xac, + 0xff, 0x71, 0x55, 0xd6, 0xad, 0x0d, 0xc9, 0x81, 0x55, 0x7b, 0x0a, 0x63, 0xab, 0xcb, + 0xf4, 0xa6, 0x8d, 0xe3, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0x6d, 0xc3, 0xbf, 0xc7, 0xa9, 0xc6, 0x93, 0xc4, 0x8b, 0xc4, 0xb2, 0xc8, 0xba, 0xc6, + 0xab, 0x2d, 0xc7, 0xa4, 0xe2, 0xb1, 0xa5, 0xc6, 0x8f, 0xc7, 0x9d, 0xe2, 0xb1, 0xb0, + 0xc8, 0xaa, 0xc3, 0x91, 0xc7, 0xbb, 0xe2, 0xb1, 0xaa, 0xe2, 0xb1, 0xa8, 0xc6, 0x97, + 0x24, 0xe1, 0x9b, 0xa6, 0x3d, 0xc3, 0x96, 0xc8, 0xaf, 0xc6, 0xb6, 0xc3, 0xbb, 0xc6, + 0xad, 0xc5, 0x81, 0xc8, 0xbb, 0xc7, 0x91, 0xc6, 0x93, 0xc6, 0x8c, 0x2c, 0xc7, 0x9f, + 0xc6, 0xa2, 0x67, 0xc6, 0xb3, 0xe2, 0xb1, 0xa0, 0xc2, 0xbe, 0xc4, 0x90, 0x4d, 0xe1, + 0x9b, 0x99, 0xc6, 0x92, 0xe1, 0x9a, 0xa2, 0xe1, 0x9a, 0xb7, 0xe1, 0x9a, 0xa9, 0xe1, + 0x9b, 0x94, 0xc6, 0xa1, 0x4a, 0xc4, 0xb8, 0xe1, 0x9a, 0xb9, 0xc2, 0xaa, 0xc7, 0x8e, + 0xe2, 0xb1, 0xa7, 0x25, 0xc4, 0xa5, 0xc6, 0x9a, 0xc5, 0x82, 0xc4, 0xb2, 0xe2, 0xb1, + 0xbf, 0xc8, 0x91, 0xc3, 0x8e, 0xcd, 0xb4, 0xc8, 0x82, 0xc4, 0xb2, 0xc8, 0xb4, 0xc5, + 0x9f, 0xc5, 0x9b, 0xe1, 0x9a, 0xb0, 0xc8, 0xa8, 0xc3, 0x9f, 0xc7, 0x9e, 0xe1, 0x9b, + 0x93, 0xe1, 0x9a, 0xaa, 0xc7, 0x94, 0xe2, 0xb1, 0xa7, 0x77, 0xc3, 0x9e, 0xc8, 0x85, + 0xc2, 0xab, 0x5f, 0xc3, 0x91, 0xc2, 0xa5, 0xc6, 0xa7, 0xc4, 0x80, 0xe1, 0x9b, 0x92, + 0xc2, 0xbf, 0xcd, 0xb4, 0xc5, 0xb9, 0xc8, 0xa1, 0xc8, 0x8c, 0xc4, 0x98, 0xc3, 0xa6, + 0xc2, 0xab, 0xc4, 0x8d, 0xe1, 0x9a, 0xb6, 0xc7, 0x97, 0xc3, 0xa7, 0xc7, 0x99, 0xc3, + 0x82, 0x65, 0xc7, 0x8f, 0xe1, 0x9b, 0x87, 0xc5, 0xa3, 0xe1, 0x9b, 0x96, 0xc7, 0x8a, + 0xe1, 0x9b, 0x9f, 0xc6, 0xb0, 0x4e, 0x50, 0xc6, 0xb6, 0xc2, 0xa7, 0xc8, 0xa7, 0xc5, + 0xbd, 0xc6, 0x96, 0xc6, 0x98, 0xc7, 0x96, 0x30, 0xc8, 0xa7, 0xc6, 0x8c, 0x2e, 0xc8, + 0x8c, 0x62, 0xe1, 0x9a, 0xbf, 0xc4, 0x8c, 0xc7, 0x89, 0xe1, 0x9a, 0xa4, 0xc8, 0xa5, + 0x45, 0xcd, 0xbe, 0xe1, 0x9b, 0xb0, 0xc3, 0x90, 0x40, 0xc3, 0xbe, 0xc4, 0x8f, 0xc6, + 0x89, 0xc5, 0xb9, 0x6b, 0xc8, 0xbd, 0xc3, 0x97, 0xe1, 0x9a, 0xa0, 0xc7, 0xb3, 0xc5, + 0xb7, 0xc7, 0x85, 0xc3, 0x92, 0xe2, 0xb1, 0xac, 0xc4, 0xb0, 0xc5, 0xbc, 0xc6, 0x9d, + 0xc6, 0xbb, 0xc6, 0x82, 0xc6, 0x94, 0xc5, 0xb8, 0xc9, 0x8f, 0xc5, 0xbc, 0xc5, 0xad, + 0xc7, 0x8f, 0xc5, 0xb0, 0xc7, 0x89, 0xc7, 0x82, 0xc6, 0x9c, 0x41, 0xc6, 0xbe, 0xc7, + 0x93, 0xc5, 0xa2, 0xc6, 0xa5, 0xc7, 0x9c, 0xc5, 0x8d, 0xc7, 0x9f, 0xe1, 0x9b, 0x80, + 0xc4, 0xba, 0xce, 0x8a, 0xc2, 0xaf, 0xc5, 0x8f, 0x79, 0xc5, 0xb7, 0xc6, 0x87, 0x48, + 0xc2, 0xa9, 0xc4, 0xb4, 0xc3, 0x9b, 0xc8, 0x87, 0xc9, 0x8c, 0xc8, 0xb2, 0xe1, 0x9b, + 0xa3, 0x68, 0xe2, 0xb1, 0xb6, 0xc5, 0x8c, 0xc2, 0xaa, 0x64, 0xc5, 0x85, 0x48, 0xc5, + 0x87, 0x54, 0xe2, 0xb1, 0xaf, 0xc5, 0x88, 0xc4, 0x8f, 0xc5, 0x94, 0xe1, 0x9b, 0xa4, + 0xe1, 0x9b, 0xa1, 0xc5, 0xa8, 0xc7, 0x92, 0xc4, 0xbc, 0xc4, 0xa8, 0xc8, 0x9f, 0xc3, + 0xbd, 0xe1, 0x9b, 0xab, 0xe2, 0xb1, 0xa2, 0xe1, 0x9a, 0xa3, 0xc5, 0xac, 0xc8, 0x8e, + 0xc7, 0xbf, 0xc3, 0xbb, 0xe1, 0x9b, 0x9a, 0xc5, 0x86, 0xc4, 0xae, 0xe2, 0xb1, 0xa9, + 0xc7, 0x8a, 0x25, 0xc7, 0xbc, 0xc8, 0x89, 0x31, 0xc4, 0x84, 0xc3, 0x9c, 0xc2, 0xbd, + 0xc3, 0x90, 0xe2, 0xb1, 0xb9, 0xc7, 0x97, 0xc5, 0xb7, 0xc3, 0x81, 0xc8, 0xa1, 0x6d, + 0xc7, 0xa4, 0xc8, 0x9f, 0xc9, 0x8f, 0xe1, 0x9b, 0x95, 0xe1, 0x9b, 0x9a, 0x3e, 0xc3, + 0x94, 0xc7, 0x94, 0xc4, 0xbc, 0xcd, 0xb4, 0xc8, 0xbd, 0xc7, 0xb1, 0x39, 0xc3, 0x8c, + 0xe2, 0xb1, 0xa5, 0xc8, 0x82, 0xc7, 0x8b, 0x5a, ], asset_base: [ - 0xd7, 0x65, 0x7f, 0x6b, 0xf8, 0xc7, 0x11, 0x02, 0x3d, 0xbb, 0x0e, 0x3c, 0x6b, 0x7d, - 0x19, 0xae, 0xc5, 0x22, 0x4b, 0x5b, 0xc8, 0x33, 0x73, 0xe6, 0x89, 0x31, 0xbb, 0x3c, - 0x77, 0x8d, 0x19, 0x07, + 0x9c, 0x64, 0x87, 0xfa, 0x7e, 0x3e, 0xd4, 0xc1, 0x7c, 0x02, 0x43, 0x93, 0x55, 0x14, + 0xc9, 0x45, 0x4a, 0x6f, 0x21, 0x3f, 0x7b, 0x1c, 0x5b, 0x32, 0xab, 0xd5, 0xa8, 0x6e, + 0x49, 0xe1, 0x35, 0x2d, ], }, TestVector { key: [ - 0xb5, 0x9c, 0x5f, 0x32, 0x34, 0xd6, 0xca, 0x36, 0xcc, 0x48, 0x3d, 0x67, 0xa8, 0x4f, - 0x37, 0xd6, 0xb2, 0x4b, 0x24, 0x45, 0x48, 0x25, 0xd2, 0xb7, 0xbf, 0xdc, 0x80, 0x2b, - 0x2e, 0x32, 0x8c, 0x43, + 0x0e, 0xf9, 0x1a, 0x2b, 0x56, 0xac, 0x5f, 0x19, 0xd1, 0xc9, 0xfb, 0x24, 0x98, 0x6c, + 0x01, 0x36, 0x2d, 0x66, 0x39, 0x16, 0x0c, 0x27, 0x5b, 0x28, 0x02, 0x46, 0x50, 0x05, + 0x14, 0x96, 0x98, 0x44, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0x49, 0xc2, 0xa7, 0xc3, 0xb0, 0x67, 0xe1, 0x9b, 0xa1, 0xc6, 0xa6, 0xc6, 0x95, 0xe1, + 0x9a, 0xa8, 0xc7, 0xae, 0xc8, 0xa1, 0xc7, 0xbc, 0xe1, 0x9a, 0xba, 0xc8, 0x86, 0xe2, + 0xb1, 0xa9, 0xc6, 0x8e, 0xe1, 0x9a, 0xb3, 0xe1, 0x9a, 0xa7, 0xc8, 0x88, 0xc3, 0x97, + 0xc7, 0xac, 0xc7, 0x97, 0x64, 0xc7, 0xae, 0xc5, 0xab, 0xc3, 0x9c, 0xc4, 0x8e, 0xc3, + 0x97, 0xc6, 0x83, 0xc4, 0x9e, 0xc9, 0x89, 0xc4, 0x9a, 0xc2, 0xaf, 0xc2, 0xaa, 0xc7, + 0x92, 0xcd, 0xb1, 0x65, 0xc5, 0x92, 0xe1, 0x9b, 0xa3, 0xc7, 0x83, 0x4c, 0x63, 0xc2, + 0xa5, 0xc4, 0xa5, 0x42, 0xc3, 0x9a, 0xc5, 0x85, 0xc5, 0x80, 0xc5, 0x9e, 0xc3, 0xa0, + 0xc8, 0xb0, 0xcd, 0xb6, 0x75, 0xc6, 0x96, 0xce, 0x84, 0xc5, 0x93, 0xe2, 0xb1, 0xb9, + 0xe2, 0xb1, 0xa8, 0xc7, 0xb0, 0x45, 0xc5, 0x8b, 0x7a, 0xc3, 0x84, 0xc6, 0x80, 0xc7, + 0x9b, 0xc5, 0x9c, 0xc3, 0xa3, 0xc8, 0xba, 0xcd, 0xbc, 0xcd, 0xbd, 0xc8, 0xa7, 0xc4, + 0x8a, 0xc5, 0xa2, 0xe2, 0xb1, 0xb7, 0xc4, 0x84, 0xcd, 0xbe, 0xc7, 0xa1, 0xc4, 0xa3, + 0xc5, 0x9d, 0xc7, 0xad, 0xc8, 0xb6, 0xc7, 0xb5, 0xc5, 0x8e, 0xe1, 0x9a, 0xb6, 0x65, + 0xe2, 0xb1, 0xb7, 0xc6, 0xaf, 0xc9, 0x8d, 0xe1, 0x9a, 0xbe, 0xc7, 0x8b, 0x5c, 0x74, + 0xc8, 0x8a, 0xc8, 0x83, 0xc3, 0x87, 0xc3, 0x83, 0xc6, 0xba, 0xc8, 0xbf, 0xc4, 0x9b, + 0x3e, 0xc7, 0x96, 0xc7, 0x8b, 0xc5, 0x81, 0xcd, 0xb2, 0xc5, 0x8e, 0xc8, 0x8d, 0xc3, + 0xa1, 0x5f, 0xc5, 0xa9, 0xc2, 0xbb, 0xe1, 0x9a, 0xa6, 0xc9, 0x88, 0x5e, 0xc9, 0x85, + 0xc8, 0x91, 0xe1, 0x9b, 0x8e, 0xc4, 0x8f, 0xe1, 0x9b, 0xa4, 0xe1, 0x9a, 0xa8, 0xc6, + 0xa5, 0x77, 0xc3, 0x85, 0xc7, 0x97, 0xc3, 0xaf, 0xe1, 0x9a, 0xaf, 0x64, 0x6d, 0xc8, + 0xa3, 0xc3, 0x92, 0xe2, 0xb1, 0xbd, 0xc8, 0xb7, 0xe1, 0x9b, 0x86, 0xe2, 0xb1, 0xb9, + 0xc6, 0xa1, 0xc3, 0x82, 0xc7, 0x8b, 0xc7, 0x91, 0xc9, 0x86, 0xc5, 0x89, 0xe1, 0x9b, + 0xae, 0xc8, 0xb6, 0xc4, 0xbb, 0x57, 0xc3, 0xa6, 0xc2, 0xa3, 0xc5, 0xad, 0x2a, 0x6e, + 0xc3, 0x90, 0xc5, 0xa1, 0xc4, 0x87, 0xc2, 0xb7, 0xc5, 0xb1, 0xc4, 0x99, 0xc6, 0xbd, + 0xe1, 0x9b, 0x81, 0xe1, 0x9b, 0x8e, 0x28, 0xc8, 0xb6, 0xc2, 0xb5, 0xe1, 0x9a, 0xa6, + 0xc6, 0x83, 0xe1, 0x9a, 0xbe, 0xc6, 0xbf, 0x2f, 0xc3, 0x80, 0xe1, 0x9a, 0xa2, 0xc7, + 0xa2, 0xc5, 0xb1, 0xe1, 0x9b, 0x83, 0xe1, 0x9a, 0xa7, 0xc6, 0x85, 0xc7, 0x93, 0xc5, + 0x95, 0xc8, 0xaf, 0xc7, 0x97, 0x2e, 0xe2, 0xb1, 0xaf, 0xc8, 0xbf, 0xe1, 0x9b, 0x81, + 0xc3, 0xac, 0x4d, 0xc3, 0xa0, 0xc6, 0x97, 0xe1, 0x9b, 0x92, 0xe1, 0x9b, 0x9f, 0xc4, + 0x9d, 0xc8, 0x9b, 0xc6, 0xab, 0xc7, 0x92, 0xc6, 0x95, 0xc5, 0xbf, 0x6b, 0xc7, 0xa0, + 0x5a, 0xc3, 0x94, 0xc6, 0x96, 0xc4, 0x8e, 0xc6, 0xac, 0xc6, 0xb9, 0xc3, 0xb1, 0xc8, + 0xbd, 0xc8, 0x88, 0xc5, 0xb5, 0xc6, 0x9f, 0xc3, 0x9b, 0xc7, 0xae, 0xc5, 0x9c, 0xc4, + 0xb5, 0xc6, 0x9e, 0xc3, 0x99, 0xc2, 0xa9, 0xc6, 0xba, 0xc8, 0x9f, 0xc7, 0x83, 0xc8, + 0xbb, 0x34, 0xc3, 0xb5, 0xc5, 0x8a, 0x3b, 0xc2, 0xaa, 0x7b, 0xc4, 0x8c, 0xc3, 0xbb, + 0xc8, 0xb9, 0xc5, 0xb5, 0xce, 0x87, 0xc2, 0xb8, 0xc3, 0x97, 0xe1, 0x9b, 0x84, 0xc8, + 0x85, 0xc2, 0xa8, 0xc2, 0xab, 0xc8, 0x9a, 0xc6, 0xb2, 0xe2, 0xb1, 0xac, 0xc4, 0xa8, + 0xc4, 0xb2, 0xc9, 0x8b, 0xc5, 0xb4, 0xc6, 0x84, 0xc3, 0xb0, 0xc6, 0xb9, 0xe2, 0xb1, + 0xae, 0x5b, 0xc8, 0x8b, 0xc3, 0xaa, 0xc5, 0x82, 0xc5, 0xb6, 0xc8, 0x8d, 0xc9, 0x83, + 0xc5, 0x91, 0xc9, 0x8c, 0xc2, 0xab, 0xc6, 0x9d, ], asset_base: [ - 0x75, 0xb8, 0x7f, 0x88, 0x85, 0xb9, 0x7f, 0x00, 0x70, 0x93, 0x89, 0xeb, 0x57, 0x0a, - 0x59, 0x47, 0xd4, 0xca, 0x36, 0x19, 0x98, 0x10, 0xbd, 0x94, 0x37, 0xba, 0x7c, 0x4a, - 0x2b, 0x24, 0xcd, 0xab, + 0xb2, 0x75, 0x51, 0xe5, 0x55, 0x32, 0x2a, 0x10, 0x94, 0x42, 0x4d, 0x4c, 0xe8, 0x6d, + 0xde, 0x6c, 0x6d, 0xf1, 0xbd, 0xec, 0xb6, 0x31, 0x5a, 0x6a, 0xa1, 0xc5, 0x58, 0xc9, + 0x82, 0x49, 0x54, 0x13, ], }, TestVector { key: [ - 0xff, 0x63, 0xc7, 0x89, 0x25, 0x1c, 0x10, 0x43, 0xc6, 0xf9, 0x6c, 0x66, 0xbf, 0x5b, - 0x0f, 0x61, 0xc9, 0xd6, 0x5f, 0xef, 0x5a, 0xaf, 0x42, 0x84, 0xa6, 0xa5, 0x69, 0x94, - 0x94, 0x1c, 0x05, 0xfa, + 0x0b, 0x08, 0x3c, 0x42, 0x29, 0xbd, 0x05, 0x85, 0xa4, 0xa0, 0xf5, 0xe8, 0x06, 0x55, + 0x2b, 0x65, 0xee, 0x24, 0xc7, 0x1a, 0x4a, 0x2a, 0x19, 0x7f, 0x9e, 0x85, 0x5e, 0xdc, + 0x2e, 0x1a, 0x09, 0xfa, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc5, 0xa0, 0x2a, 0xc4, 0xbc, 0xc6, 0x92, 0xc6, 0x9b, 0xc6, 0x9f, 0xe1, 0x9b, 0xaf, + 0xe2, 0xb1, 0xb7, 0xc4, 0x9a, 0xc8, 0x93, 0xe1, 0x9b, 0x8d, 0x2b, 0xc3, 0x8b, 0xe2, + 0xb1, 0xa0, 0xc5, 0xa4, 0xc6, 0x9d, 0xc3, 0xb6, 0xc6, 0xb4, 0xc4, 0xb5, 0x68, 0xcd, + 0xba, 0xc6, 0x91, 0xc3, 0xa5, 0xc2, 0xaf, 0xe2, 0xb1, 0xbe, 0x6d, 0xc9, 0x86, 0xc6, + 0x8c, 0x30, 0xc6, 0x90, 0xc7, 0xb3, 0xe1, 0x9b, 0x96, 0x6e, 0xc5, 0xac, 0xe2, 0xb1, + 0xbc, 0x41, 0xc6, 0xb6, 0xc6, 0xab, 0xe2, 0xb1, 0xb0, 0xc7, 0xa6, 0xe1, 0x9a, 0xa1, + 0xc2, 0xaa, 0xe1, 0x9b, 0x8a, 0xc6, 0xa9, 0xc4, 0x91, 0xc4, 0xb8, 0xc2, 0xb7, 0xce, + 0x8c, 0xc3, 0x98, 0x76, 0xc4, 0x98, 0xc5, 0xa4, 0xc7, 0x9f, 0xc5, 0xb9, 0xc8, 0x96, + 0xe1, 0x9a, 0xbf, 0xce, 0x88, 0xc5, 0xaf, 0xc4, 0x94, 0xc3, 0x84, 0xc7, 0xa3, 0xc3, + 0x8c, 0xc7, 0x99, 0xcd, 0xb5, 0xc7, 0x9c, 0xc7, 0xb7, 0xe1, 0x9b, 0x96, 0xc9, 0x82, + 0xe1, 0x9a, 0xb0, 0xc6, 0x8b, 0xc6, 0x8f, 0xc7, 0x8c, 0x3c, 0x68, 0xc8, 0x8d, 0xc5, + 0x8e, 0xc3, 0xaf, 0xc6, 0x90, 0xe1, 0x9a, 0xa5, 0xe1, 0x9a, 0xbe, 0x26, 0xcd, 0xbb, + 0xc6, 0x80, 0xc5, 0x82, 0x34, 0xc3, 0x8a, 0x36, 0xc8, 0xa6, 0xcd, 0xbb, 0xe1, 0x9b, + 0xa1, 0xc8, 0xaa, 0xc3, 0x86, 0x65, 0xc3, 0xaa, 0xc8, 0xa3, 0xc7, 0xa7, 0xc7, 0xa9, + 0xc3, 0xbb, 0x61, 0xc3, 0xbe, 0xc5, 0xae, 0xc2, 0xb0, 0x6c, 0xc5, 0x9a, 0xc4, 0xbc, + 0xc8, 0xb6, 0xc4, 0x82, 0xc4, 0x89, 0xc6, 0x8d, 0xc5, 0x90, 0xc8, 0x86, 0xc6, 0x8a, + 0xc7, 0xac, 0xc8, 0x87, 0xe1, 0x9a, 0xb3, 0xc2, 0xa2, 0x33, 0xc8, 0x8b, 0x2b, 0xc8, + 0x99, 0xc7, 0xae, 0x4e, 0xc5, 0xa2, 0xc5, 0xaa, 0x7e, 0xc7, 0x9b, 0xc6, 0x9d, 0xc6, + 0xbe, 0xc8, 0xa8, 0xc6, 0xa9, 0xc4, 0xb0, 0xe1, 0x9b, 0xa9, 0xce, 0x89, 0x41, 0x7a, + 0xc8, 0xbd, 0xe1, 0x9b, 0xaf, 0xc4, 0x8d, 0xc7, 0x88, 0x40, 0xc5, 0x9c, 0xe1, 0x9b, + 0x9d, 0xc2, 0xac, 0xc9, 0x8d, 0x41, 0xc5, 0xae, 0xe1, 0x9b, 0x87, 0xc7, 0x92, 0xc4, + 0x98, 0xc6, 0x97, 0xc2, 0xab, 0x63, 0xce, 0x8c, 0xe1, 0x9b, 0x9d, 0xc2, 0xbc, 0xc4, + 0xae, 0xc4, 0x97, 0xc8, 0x91, 0xc5, 0xa6, 0x66, 0xc4, 0xb4, 0xc4, 0xb0, 0xe1, 0x9a, + 0xb0, 0x65, 0xc8, 0xb4, 0xc7, 0x8b, 0xe1, 0x9a, 0xa2, 0xc5, 0x98, 0xc8, 0xa5, 0xc4, + 0x9f, 0xce, 0x86, 0xc7, 0xa8, 0xc3, 0xaf, 0xc8, 0xa0, 0xc7, 0x96, 0xc4, 0xa3, 0xc4, + 0x84, 0xc4, 0x98, 0xe1, 0x9b, 0x9e, 0xe2, 0xb1, 0xb1, 0xc2, 0xa3, 0xe1, 0x9b, 0xa7, + 0xc8, 0x8f, 0xe1, 0x9a, 0xa9, 0xc5, 0xba, 0xc5, 0x8b, 0xe1, 0x9b, 0x97, 0xc8, 0xaa, + 0xc7, 0x93, 0xc2, 0xaa, 0xc7, 0x96, 0xc3, 0xb5, 0xc5, 0xb0, 0xc8, 0x81, 0xc8, 0x93, + 0xc2, 0xac, 0xc5, 0xa0, 0x3f, 0x5d, 0xc7, 0x97, 0x4a, 0xc7, 0x91, 0xc9, 0x80, 0xc6, + 0x94, 0xc4, 0xba, 0xc3, 0x96, 0x3c, 0xe1, 0x9b, 0x90, 0xc3, 0x8f, 0xc5, 0xb1, 0xc3, + 0xa8, 0xc4, 0xb6, 0xc6, 0x8e, 0xcd, 0xb6, 0xe1, 0x9b, 0x89, 0x26, 0xc7, 0x9f, 0xc6, + 0x8c, 0xc3, 0xb5, 0xe1, 0x9b, 0xad, 0xc8, 0x85, 0xc2, 0xb7, 0xc6, 0x96, 0xc3, 0x8a, + 0xe2, 0xb1, 0xab, 0xc8, 0x9a, 0x31, 0xc8, 0x81, 0xc7, 0xa9, 0x44, 0xc4, 0xb2, 0xe1, + 0x9a, 0xb1, 0xe2, 0xb1, 0xa9, 0xc3, 0xa8, 0x2f, 0xc7, 0xa3, 0xc5, 0x83, 0xc5, 0xb5, + 0xe2, 0xb1, 0xa5, 0xc5, 0xbb, 0xc8, 0x84, 0xc5, 0xbf, 0xc7, 0xb5, 0xc5, 0x80, 0xc2, + 0xbc, 0xc5, 0xba, 0x74, 0xc8, 0x92, 0xc4, 0x99, 0xc7, 0xbc, 0xc7, 0x9d, 0xc2, 0xba, + 0xc5, 0x91, 0x75, 0xc7, 0xbd, 0xe1, 0x9a, 0xb4, ], asset_base: [ - 0xda, 0x94, 0x71, 0x63, 0xc0, 0x67, 0x83, 0x60, 0xfc, 0x58, 0xb4, 0x33, 0xa8, 0x97, - 0x66, 0x8e, 0x58, 0x2e, 0xce, 0x67, 0x8f, 0x31, 0xac, 0xb4, 0xb4, 0xad, 0x85, 0xbc, - 0xd5, 0xf7, 0xc1, 0xae, + 0x97, 0xf4, 0x4c, 0x37, 0x3a, 0x55, 0x30, 0xbd, 0xc9, 0xd4, 0xbb, 0x76, 0x26, 0x65, + 0x03, 0xb4, 0xfd, 0x4a, 0x24, 0xf0, 0x22, 0x23, 0x13, 0xe4, 0xff, 0x45, 0x97, 0x74, + 0xa6, 0x9a, 0x4f, 0x34, ], }, TestVector { key: [ - 0x45, 0x61, 0x9f, 0x20, 0x6c, 0x3b, 0xfc, 0x84, 0xfd, 0x42, 0x4f, 0xfb, 0x5c, 0x81, - 0x6f, 0x65, 0x4b, 0x27, 0xaa, 0x7f, 0x7b, 0x4b, 0xd6, 0x7e, 0xc5, 0xf9, 0xac, 0x6d, - 0x0f, 0x38, 0xdb, 0xb1, + 0x02, 0x66, 0x60, 0x55, 0xf4, 0x0b, 0x89, 0x61, 0x24, 0xe3, 0x67, 0x56, 0xa7, 0xa0, + 0x93, 0xbb, 0x8e, 0x0b, 0xaa, 0x26, 0x3c, 0xab, 0x79, 0x67, 0x3b, 0x0f, 0x3d, 0x09, + 0x74, 0x68, 0x8e, 0xa1, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xc7, 0xac, 0xc3, 0xa5, 0xc7, 0xa7, 0x62, 0xc3, 0xb5, 0x4d, 0xc6, 0x80, 0xc3, 0x83, + 0xe1, 0x9a, 0xa5, 0x3c, 0xc5, 0x84, 0xc8, 0x92, 0xc5, 0x8f, 0xc4, 0x95, 0xc8, 0x95, + 0xc3, 0xb4, 0xe1, 0x9b, 0x84, 0xc7, 0xa0, 0xc5, 0x83, 0xc9, 0x83, 0xe1, 0x9b, 0xb0, + 0xe2, 0xb1, 0xb6, 0xcd, 0xb1, 0xe1, 0x9a, 0xb2, 0xc7, 0x85, 0xc7, 0x8d, 0xe1, 0x9b, + 0x91, 0xc6, 0x9b, 0xc4, 0x8e, 0x63, 0xe1, 0x9a, 0xa7, 0x4c, 0xe1, 0x9b, 0xa0, 0xc6, + 0xb0, 0xe2, 0xb1, 0xb5, 0xc2, 0xa1, 0xe1, 0x9b, 0x93, 0xc3, 0xa1, 0xc6, 0xb5, 0x68, + 0xc5, 0xab, 0xc5, 0x8d, 0xc6, 0xb5, 0xc3, 0x8c, 0xce, 0x89, 0x4e, 0xc8, 0xb4, 0xc4, + 0xb4, 0xc2, 0xb0, 0xc8, 0x99, 0xc3, 0x86, 0xc4, 0x91, 0xe1, 0x9b, 0x91, 0xe1, 0x9b, + 0x88, 0x61, 0xc6, 0x8a, 0xc6, 0xa7, 0xc7, 0x8c, 0x71, 0x76, 0xc6, 0xbc, 0xe1, 0x9b, + 0x9a, 0x77, 0xc5, 0x9c, 0xc8, 0xaa, 0xc3, 0x95, 0xc7, 0x9f, 0xce, 0x8c, 0xc3, 0xa5, + 0xc4, 0x96, 0xc3, 0x95, 0xc3, 0xa2, 0xe1, 0x9b, 0x98, 0xc2, 0xb4, 0xc7, 0xb1, 0xcd, + 0xb1, 0xc4, 0xbb, 0x2d, 0xc8, 0xa8, 0xe1, 0x9a, 0xab, 0xc7, 0x8f, 0xc4, 0x83, 0xe1, + 0x9b, 0xa8, 0xc5, 0x93, 0xc8, 0x97, 0xe1, 0x9a, 0xa3, 0xc3, 0x81, 0xc3, 0x8a, 0x37, + 0xc4, 0xa9, 0xc2, 0xb8, 0x2b, 0xc8, 0xbb, 0xc7, 0x91, 0xe1, 0x9a, 0xb7, 0xc7, 0xa3, + 0x6c, 0xe1, 0x9b, 0x96, 0xc8, 0xbf, 0xc8, 0xaf, 0xc4, 0x98, 0xc9, 0x8e, 0xc8, 0x9e, + 0xc2, 0xb9, 0xc7, 0x80, 0xc3, 0xb2, 0xc3, 0xb0, 0xc3, 0xa1, 0xc5, 0xaf, 0xc5, 0x83, + 0xc4, 0x87, 0xe2, 0xb1, 0xbb, 0x4f, 0xc8, 0xa9, 0xc6, 0x9f, 0xc9, 0x8b, 0x67, 0xcd, + 0xb4, 0x5a, 0xc2, 0xa7, 0xe2, 0xb1, 0xa6, 0xc5, 0x8c, 0xc3, 0x8f, 0xc6, 0x8b, 0xc7, + 0x9c, 0xc9, 0x8a, 0xe2, 0xb1, 0xaa, 0xe2, 0xb1, 0xb0, 0xc8, 0xb7, 0xc4, 0x9e, 0xc6, + 0xbd, 0xc2, 0xb0, 0xc5, 0x91, 0xc6, 0xbb, 0xc5, 0xbb, 0xc6, 0xa0, 0xc3, 0xa8, 0xc2, + 0xa5, 0xc8, 0xb0, 0xc4, 0x91, 0xc2, 0xa9, 0xc2, 0xab, 0xc8, 0x99, 0xe1, 0x9a, 0xa4, + 0xc5, 0x87, 0xe1, 0x9a, 0xa2, 0xc7, 0xa6, 0x37, 0x73, 0xc8, 0x8b, 0x74, 0xc5, 0xab, + 0xc3, 0x85, 0xe1, 0x9b, 0x9c, 0xc6, 0x87, 0xc5, 0x82, 0xc4, 0xa9, 0xc8, 0x9b, 0xe2, + 0xb1, 0xb2, 0x6f, 0x51, 0x75, 0xc3, 0xab, 0xc2, 0xbd, 0x49, 0xc4, 0x97, 0x5e, 0xc8, + 0xb6, 0x5b, 0xc5, 0x9f, 0xc4, 0x98, 0xc8, 0x8f, 0x3a, 0xc6, 0x95, 0xc7, 0x8b, 0xc5, + 0x89, 0x3f, 0xc5, 0x9f, 0xe1, 0x9b, 0x9e, 0xe2, 0xb1, 0xb1, 0xc7, 0x84, 0xc4, 0xa6, + 0xe2, 0xb1, 0xa8, 0xc3, 0x85, 0xc3, 0xa5, 0xc8, 0x98, 0xc8, 0xa0, 0x5b, 0xc6, 0xba, + 0xe1, 0x9a, 0xa6, 0xc4, 0xad, 0xe2, 0xb1, 0xab, 0xc7, 0xa1, 0xe2, 0xb1, 0xbf, 0xe1, + 0x9b, 0xa8, 0x4c, 0xc4, 0x8f, 0x6a, 0xc5, 0x9d, 0xe1, 0x9b, 0xa8, 0xc6, 0xb5, 0xc8, + 0x8b, 0xce, 0x8c, 0xc7, 0xa2, 0xc6, 0xbd, 0x33, 0xc4, 0xb0, 0xe1, 0x9a, 0xb2, 0xc7, + 0x9d, 0xe2, 0xb1, 0xa5, 0xc2, 0xba, 0xc3, 0x8e, 0xc4, 0xbf, 0xc3, 0x9b, 0xc5, 0xad, + 0x73, 0xe1, 0x9a, 0xa6, 0x31, 0xc8, 0x93, 0xc9, 0x84, 0xc6, 0x84, 0xc2, 0xa9, 0xc2, + 0xa5, 0xe1, 0x9b, 0x91, 0xe1, 0x9b, 0xb0, 0xc3, 0x97, 0x4f, 0x6b, 0x48, 0xc3, 0xb2, + 0xe1, 0x9a, 0xb5, 0xc5, 0x8a, 0xc5, 0x92, 0xe1, 0x9b, 0x8d, 0xc7, 0x8d, 0xc4, 0xa6, + 0x26, 0xc3, 0xab, 0xc4, 0x95, 0xc3, 0xb4, 0xc7, 0x9f, 0xc8, 0xa6, 0xc7, 0xaa, 0xc6, + 0xb5, 0xc5, 0x8c, 0x66, 0xc9, 0x82, 0xc7, 0x8a, 0xc7, 0x92, 0xc9, 0x88, 0xc4, 0x84, + 0xe2, 0xb1, 0xb3, 0x47, 0xc6, 0xbb, 0xc8, 0x83, ], asset_base: [ - 0x01, 0xcb, 0x2c, 0x3f, 0xae, 0x16, 0xf2, 0xe5, 0x82, 0x1e, 0x34, 0x64, 0x70, 0x17, - 0xf3, 0x68, 0x04, 0xb1, 0x7e, 0xfc, 0x8c, 0xb7, 0x69, 0x54, 0x79, 0x61, 0x5d, 0xe8, - 0xf3, 0x2d, 0x29, 0x21, + 0xe7, 0x25, 0x94, 0x56, 0x3c, 0xb3, 0x92, 0xab, 0xbe, 0x95, 0x61, 0x61, 0xfa, 0xed, + 0x3d, 0x8d, 0xc4, 0xa1, 0xa0, 0x4e, 0x7c, 0x0d, 0x6e, 0x5b, 0xb8, 0x7d, 0x6c, 0xba, + 0x68, 0xc4, 0x45, 0x27, ], }, TestVector { key: [ - 0xbf, 0x39, 0x20, 0xce, 0x2e, 0x9e, 0x95, 0xb0, 0xee, 0xce, 0x13, 0x0a, 0x50, 0xba, - 0x7d, 0xcc, 0x6f, 0x26, 0x51, 0x2a, 0x9f, 0xc7, 0xb8, 0x04, 0xaf, 0xf0, 0x89, 0xf5, - 0x0c, 0xbc, 0xff, 0xf7, + 0x0a, 0xc2, 0x8d, 0x35, 0x85, 0x55, 0x65, 0x95, 0xac, 0x16, 0x8a, 0x8c, 0xa3, 0xa0, + 0x63, 0x31, 0x9c, 0xdf, 0xbb, 0x4f, 0xaf, 0x2c, 0xa2, 0x48, 0x1d, 0x4d, 0xaa, 0x04, + 0x2d, 0x7c, 0xad, 0xa5, ], description: [ - 0xe1, 0x9b, 0xa9, 0xc4, 0x80, 0xc4, 0xbb, 0xe1, 0x9b, 0xa4, 0xc5, 0xa5, 0xc4, 0xac, - 0xc5, 0xbb, 0x7e, 0xc6, 0x82, 0xc5, 0xaf, 0xc3, 0xbd, 0x3b, 0xc8, 0x88, 0xc3, 0xaa, - 0xc6, 0x97, 0x2c, 0xc6, 0x82, 0x76, 0xe2, 0xb1, 0xa1, 0xc3, 0x9f, 0xc3, 0xa1, 0xc4, - 0xa2, 0xc4, 0x92, 0xc6, 0xa8, 0xc4, 0x8e, 0xe1, 0x9a, 0xbb, 0xc5, 0xac, 0xcd, 0xb5, - 0xc6, 0x80, 0xc6, 0xa5, 0xc8, 0xba, 0xc2, 0xa2, 0xc8, 0xb3, 0xc8, 0xa3, 0xc4, 0x98, - 0x65, 0xe1, 0x9b, 0xb0, 0xe1, 0x9b, 0xa1, 0xc3, 0x96, 0x5c, 0xc8, 0x81, 0xc5, 0x93, - 0xc6, 0xac, 0xc7, 0x9e, 0xc3, 0x8c, 0x53, 0xc7, 0xb9, 0xc4, 0x88, 0xc3, 0xa4, 0xc7, - 0x96, 0x64, 0xc5, 0xa7, 0xc4, 0x81, 0x2b, 0x7a, 0xe2, 0xb1, 0xa1, 0xc6, 0xa9, 0xe1, - 0x9b, 0xa1, 0xc8, 0xa4, 0xe1, 0x9b, 0x9b, 0xc5, 0xbf, 0xc6, 0x8d, 0xe2, 0xb1, 0xa9, - 0xc8, 0xab, 0xe2, 0xb1, 0xb1, 0xc3, 0x99, 0xc5, 0x96, 0xc7, 0x95, 0xc6, 0xad, 0xc3, - 0xac, 0xc3, 0x8a, 0x25, 0xc7, 0xa5, 0xc6, 0xa8, 0xe1, 0x9b, 0x80, 0xe2, 0xb1, 0xaf, - 0xe1, 0x9b, 0xa1, 0xc7, 0xa0, 0xe1, 0x9b, 0xa6, 0xc5, 0xa0, 0xc7, 0x85, 0xc4, 0x99, - 0xc6, 0xb7, 0x6e, 0xe1, 0x9b, 0xb0, 0x3b, 0x54, 0xc8, 0xa4, 0xc3, 0x89, 0xe1, 0x9a, - 0xa4, 0x75, 0xc3, 0x9f, 0xc6, 0x98, 0xc4, 0xb8, 0xe1, 0x9b, 0xa7, 0xe2, 0xb1, 0xbb, - 0xc5, 0xad, 0xc7, 0xbc, 0xc3, 0xaf, 0xc4, 0x9e, 0x61, 0xc8, 0x87, 0x61, 0xc5, 0x82, - 0xe1, 0x9b, 0x8d, 0xc5, 0xbe, 0xc5, 0xa3, 0xc2, 0xb3, 0xc7, 0xb3, 0xc6, 0x90, 0xc8, - 0x8b, 0xc6, 0x81, 0xe2, 0xb1, 0xb1, 0xc3, 0xa3, 0xc2, 0xa6, 0xe1, 0x9a, 0xb4, 0xe1, - 0x9b, 0x81, 0xc6, 0x94, 0xc2, 0xb1, 0xc5, 0xaf, 0xc7, 0x84, 0xc3, 0xa6, 0xc5, 0xb6, - 0xc3, 0x8a, 0x5c, 0xe1, 0x9b, 0x85, 0xe1, 0x9b, 0xa2, 0xc4, 0x99, 0xc2, 0xb4, 0xc5, - 0x9b, 0xc8, 0xa8, 0xc8, 0x8f, 0x42, 0xc4, 0x8e, 0xe1, 0x9b, 0xaa, 0xc8, 0x89, 0x6e, - 0xc5, 0xaf, 0xe1, 0x9a, 0xa8, 0xe1, 0x9a, 0xac, 0xc4, 0xa5, 0xc4, 0x8b, 0xc7, 0x8a, - 0xe1, 0x9b, 0x93, 0xc8, 0xba, 0xc4, 0xbc, 0xc2, 0xa3, 0xc8, 0x9e, 0xc6, 0xbf, 0xc6, - 0xb2, 0xcd, 0xbc, 0xc3, 0x9d, 0xc4, 0x98, 0xe1, 0x9b, 0x8f, 0xc4, 0x96, 0xc5, 0xa8, - 0x77, 0xc4, 0x8d, 0xc5, 0x88, 0xc7, 0xa2, 0xc3, 0x81, 0xc7, 0x89, 0xc4, 0x92, 0xe1, - 0x9a, 0xb7, 0xc7, 0xb1, 0xe2, 0xb1, 0xab, 0xc4, 0x9b, 0x5e, 0xc4, 0x8b, 0xe2, 0xb1, - 0xa0, 0xe1, 0x9b, 0xad, 0xcd, 0xbd, 0xe1, 0x9a, 0xa1, 0xe2, 0xb1, 0xbb, 0xe1, 0x9a, - 0xbf, 0xc8, 0xb1, 0xc6, 0x97, 0xcd, 0xbc, 0xc7, 0xb4, 0xc3, 0xb1, 0xe1, 0x9b, 0x86, - 0x5d, 0xcd, 0xb2, 0xc6, 0xb0, 0xc9, 0x81, 0xc5, 0xac, 0x4a, 0xc8, 0x97, 0xc7, 0x94, - 0x64, 0xc3, 0x80, 0xc5, 0xb8, 0xe1, 0x9b, 0x9b, 0xc4, 0x9a, 0xc8, 0xb5, 0xe1, 0x9b, - 0x88, 0xe1, 0x9a, 0xa2, 0xc7, 0xae, 0xc4, 0xb5, 0x33, 0xc2, 0xb4, 0xc3, 0xb3, 0xc7, - 0xb0, 0xc5, 0xbb, 0xe1, 0x9b, 0x98, 0xc8, 0xb6, 0x3d, 0x30, 0xe1, 0x9a, 0xa3, 0xc6, - 0x95, 0xc3, 0x90, 0xc8, 0xae, 0xc9, 0x8f, 0xc3, 0x9b, 0xc6, 0xa7, 0x6a, 0xe1, 0x9a, - 0xb8, 0xe1, 0x9a, 0xb5, 0xc4, 0xb0, 0xe1, 0x9b, 0x9d, 0x7b, 0xc6, 0xb1, 0xc6, 0xae, - 0x30, 0xc8, 0xa0, 0xc5, 0x98, 0xc5, 0x91, 0xe1, 0x9a, 0xa3, 0xe2, 0xb1, 0xaf, 0xe2, - 0xb1, 0xa9, 0xe1, 0x9b, 0x90, 0xc8, 0x89, 0xcd, 0xb4, 0xe1, 0x9b, 0x83, 0xc5, 0x88, - 0xc2, 0xa5, 0xc6, 0x9c, 0xc2, 0xac, 0xc2, 0xb2, 0xe1, 0x9b, 0x88, 0x6f, 0xe1, 0x9b, - 0x9b, 0xc5, 0xb4, 0xc6, 0xa7, 0xc8, 0x8f, 0x5a, + 0xe2, 0xb1, 0xb0, 0xc6, 0x87, 0xc7, 0xb8, 0x58, 0xc8, 0x93, 0xe1, 0x9a, 0xb6, 0xc5, + 0xbf, 0xc3, 0xb0, 0xc5, 0x92, 0xc3, 0x83, 0x25, 0xc2, 0xb4, 0xc6, 0xbd, 0xc6, 0x87, + 0xe1, 0x9b, 0x81, 0xc4, 0x9e, 0xc6, 0x9c, 0xe1, 0x9b, 0x84, 0x46, 0x56, 0xe2, 0xb1, + 0xa4, 0xc3, 0xa9, 0xc5, 0xab, 0xe1, 0x9a, 0xbb, 0x55, 0xc4, 0x85, 0xc4, 0xa8, 0xc2, + 0xb1, 0xc8, 0xa4, 0xc3, 0xa4, 0x7e, 0xc4, 0x92, 0xc7, 0x9b, 0xc2, 0xac, 0xc3, 0xa1, + 0xc4, 0x81, 0xcd, 0xb2, 0xc2, 0xa6, 0xc2, 0xa1, 0xc3, 0xa2, 0xe1, 0x9b, 0x95, 0xc5, + 0xa4, 0xc7, 0xb5, 0xc8, 0x9f, 0xc9, 0x83, 0xe1, 0x9a, 0xa2, 0xc5, 0xb5, 0x25, 0xc5, + 0x9d, 0xc3, 0xb1, 0x5f, 0xc5, 0xa8, 0x69, 0xe1, 0x9b, 0x88, 0xc4, 0xb2, 0xe2, 0xb1, + 0xa8, 0xc8, 0xb8, 0x54, 0x4f, 0x2c, 0x6a, 0xc5, 0xbc, 0xc7, 0x84, 0xc8, 0x9b, 0xc6, + 0x89, 0xc5, 0x9a, 0xc5, 0xb1, 0xc7, 0x8e, 0xc6, 0xab, 0xc6, 0xbe, 0xc6, 0xae, 0xc8, + 0x8b, 0xc6, 0xbd, 0xc2, 0xa7, 0xc6, 0x9b, 0xc3, 0xb5, 0xc5, 0x8e, 0xc6, 0x92, 0xc8, + 0xaa, 0xc3, 0xb3, 0xc7, 0xbf, 0xc2, 0xb4, 0xc3, 0xa6, 0xc7, 0xb7, 0xc7, 0x9a, 0xc3, + 0xb1, 0xc2, 0xa7, 0xc4, 0xb8, 0xc6, 0x93, 0xc7, 0xae, 0xc6, 0x8c, 0x74, 0x5c, 0xc6, + 0xa1, 0x42, 0x4c, 0xc6, 0xb6, 0xc9, 0x8a, 0x50, 0xc8, 0xba, 0xc7, 0xa5, 0xc8, 0x9d, + 0xc8, 0x9b, 0xc5, 0xa0, 0xc7, 0x99, 0x21, 0x5e, 0x24, 0xc6, 0x93, 0xc6, 0x9b, 0xc7, + 0x8d, 0xc8, 0x9b, 0xe1, 0x9b, 0x93, 0xc6, 0x8f, 0xc4, 0xb6, 0xe1, 0x9a, 0xa5, 0x45, + 0xe1, 0x9b, 0x8e, 0xc6, 0xbe, 0xe1, 0x9b, 0x9e, 0xc6, 0xa8, 0xe1, 0x9a, 0xa7, 0xc4, + 0xa6, 0xc5, 0x84, 0xc6, 0xbb, 0xc8, 0xad, 0xcd, 0xb2, 0xc6, 0xb8, 0x37, 0xc6, 0xb0, + 0xe1, 0x9b, 0x84, 0xc3, 0x84, 0xc8, 0x80, 0xc4, 0xb5, 0xc6, 0x91, 0xe2, 0xb1, 0xa5, + 0xc7, 0x83, 0x60, 0xc5, 0x8f, 0xc5, 0xb0, 0xc7, 0xa0, 0xc8, 0x96, 0xc2, 0xb2, 0xc8, + 0xa7, 0xc6, 0x9f, 0x2d, 0xc6, 0x99, 0xc5, 0xb8, 0xe1, 0x9a, 0xa6, 0xc7, 0x9b, 0xc6, + 0x9b, 0xc7, 0x99, 0xc3, 0x84, 0x3c, 0xc6, 0x9a, 0x52, 0xc3, 0xb0, 0xc5, 0xb7, 0xc2, + 0xab, 0x56, 0xc3, 0x91, 0xc8, 0xbe, 0xc5, 0x84, 0xc8, 0x84, 0xc5, 0xb9, 0xc7, 0xac, + 0xc8, 0x86, 0xc5, 0xa0, 0xc2, 0xb0, 0xc3, 0xa7, 0xe1, 0x9a, 0xb9, 0xe1, 0x9b, 0x84, + 0xe1, 0x9b, 0x89, 0xc8, 0x80, 0xc6, 0x82, 0xc5, 0xb1, 0x73, 0xc6, 0x84, 0xc4, 0xb1, + 0xc8, 0x8b, 0xc4, 0xab, 0xc3, 0xa5, 0xc5, 0xbb, 0xe1, 0x9b, 0x84, 0x63, 0xc3, 0xac, + 0xc3, 0xad, 0xc3, 0xb8, 0xc5, 0xac, 0xc8, 0x8f, 0xc7, 0xb0, 0xc4, 0x9d, 0xe1, 0x9a, + 0xac, 0xc6, 0x86, 0x7d, 0xe1, 0x9a, 0xbe, 0xc8, 0xac, 0xcd, 0xbc, 0xcd, 0xba, 0xce, + 0x8c, 0xc5, 0x9e, 0x57, 0xc4, 0x83, 0xc8, 0x96, 0xc5, 0xb5, 0xe2, 0xb1, 0xac, 0xc4, + 0xa6, 0xc8, 0xaf, 0xc8, 0x84, 0x65, 0xc5, 0x85, 0x5d, 0xc4, 0xb0, 0xc5, 0xbe, 0xc5, + 0x9b, 0x3d, 0xc7, 0x80, 0xe1, 0x9b, 0x81, 0xc6, 0x94, 0xc4, 0xb3, 0xe1, 0x9b, 0xa7, + 0xe2, 0xb1, 0xa2, 0x3d, 0xc5, 0x82, 0x4e, 0x44, 0xe1, 0x9a, 0xb5, 0xc6, 0x90, 0xc3, + 0x85, 0xe1, 0x9b, 0x82, 0xe1, 0x9a, 0xb3, 0xc7, 0xa2, 0xc5, 0x93, 0xc6, 0xa9, 0xc5, + 0x92, 0xc6, 0xb3, 0xce, 0x84, 0xe1, 0x9b, 0x87, 0xe1, 0x9b, 0x97, 0xe1, 0x9b, 0x9e, + 0xc6, 0x81, 0xc4, 0xb7, 0xe1, 0x9b, 0x9e, 0x3d, 0xc7, 0xb8, 0xe1, 0x9b, 0x97, 0xe1, + 0x9b, 0x9f, 0xc4, 0x81, 0xc5, 0x8a, 0x2c, 0xc6, 0x9a, 0x21, 0xc4, 0xb8, 0xc4, 0xa9, + 0xc2, 0xa9, 0xc5, 0x89, 0xc8, 0xb5, 0x5a, 0x5a, ], asset_base: [ - 0x26, 0x21, 0x1d, 0x3b, 0x0b, 0xcf, 0x80, 0x41, 0x43, 0x30, 0x1b, 0x45, 0x23, 0x7b, - 0x96, 0xc4, 0x97, 0xe6, 0xe3, 0x87, 0x2c, 0x75, 0xb8, 0xc1, 0x58, 0x67, 0x31, 0xda, - 0x39, 0x1e, 0xc4, 0x25, + 0x0b, 0xcf, 0xbd, 0x87, 0x2f, 0xc5, 0xed, 0x4c, 0x82, 0x80, 0x35, 0x16, 0x69, 0x20, + 0x77, 0x21, 0xc6, 0xd2, 0x15, 0x67, 0xdd, 0x34, 0x10, 0x5c, 0x89, 0x7d, 0xbf, 0x66, + 0x19, 0x95, 0xa3, 0x1d, ], }, ] diff --git a/src/test_vectors/keys.rs b/src/test_vectors/keys.rs index 56d189478..0213eec1d 100644 --- a/src/test_vectors/keys.rs +++ b/src/test_vectors/keys.rs @@ -44,14 +44,14 @@ pub(crate) fn test_vectors() -> Vec { 0xd4, 0xe2, 0x0f, 0x15, ], isk: [ - 0x1c, 0xdd, 0x86, 0xb3, 0xcc, 0x43, 0x18, 0xd9, 0x61, 0x4f, 0xc8, 0x20, 0x90, 0x5d, - 0x04, 0x2b, 0xb1, 0xef, 0x9c, 0xa3, 0xf2, 0x49, 0x88, 0xc7, 0xb3, 0x53, 0x42, 0x01, - 0xcf, 0xb1, 0xcd, 0x8d, + 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, + 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, + 0x99, 0x0e, 0xd8, 0x3d, ], ik: [ - 0x16, 0x88, 0x4f, 0x1d, 0xbc, 0x92, 0x90, 0x89, 0xa4, 0x17, 0x6e, 0x84, 0x0b, 0xb5, - 0x81, 0xc8, 0x0e, 0x16, 0xe9, 0xb1, 0xab, 0xd6, 0x54, 0xe6, 0x2c, 0x8b, 0x0b, 0x95, - 0x70, 0x20, 0xb7, 0x48, + 0xd1, 0xa2, 0xfa, 0xb4, 0x17, 0x0c, 0x45, 0xc5, 0xf9, 0x79, 0xc8, 0xe7, 0x46, 0x3b, + 0x8e, 0x20, 0xf2, 0x34, 0xde, 0x35, 0xeb, 0x58, 0xa8, 0x38, 0xdf, 0x9a, 0x1f, 0xe9, + 0xb1, 0xa5, 0xaa, 0x45, ], nk: [ 0x9f, 0x2f, 0x82, 0x67, 0x38, 0x94, 0x5a, 0xd0, 0x1f, 0x47, 0xf7, 0x0d, 0xb0, 0xc3, @@ -111,7 +111,7 @@ pub(crate) fn test_vectors() -> Vec { 0x04, 0xfe, 0x32, 0xb2, 0x9b, 0x4f, 0x70, 0x6a, 0xa8, 0xf7, 0x42, 0x0f, 0x3d, 0x8e, 0x7a, 0x59, 0x70, 0x2f, ], - note_v: 4751042572350679487, + note_v: 15643327852135767324, note_rho: [ 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89, 0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63, 0xcc, 0xb8, 0xf6, 0x76, 0x49, 0x5c, 0x22, 0x2f, @@ -123,94 +123,94 @@ pub(crate) fn test_vectors() -> Vec { 0x0c, 0x1d, 0x37, 0x10, ], note_cmx: [ - 0x6a, 0xcb, 0x59, 0x4e, 0x29, 0x6f, 0xfe, 0x99, 0xa8, 0x5c, 0x17, 0x5a, 0xa4, 0x22, - 0xc8, 0x29, 0x3c, 0xe7, 0xe1, 0x9a, 0x92, 0xdf, 0x7f, 0x80, 0xae, 0x87, 0x66, 0x55, - 0x44, 0x25, 0x83, 0x38, + 0x45, 0x02, 0xe3, 0x39, 0x90, 0x1e, 0x39, 0x77, 0x17, 0x83, 0x91, 0x67, 0xcb, 0xb4, + 0x03, 0x7e, 0x0e, 0xcf, 0x68, 0x13, 0xb5, 0x1c, 0x81, 0xfe, 0x08, 0x5a, 0x7b, 0x78, + 0x2f, 0x12, 0x42, 0x28, ], note_nf: [ - 0x1c, 0x64, 0xc6, 0x82, 0x9a, 0x41, 0x21, 0xe1, 0x38, 0xd9, 0x8a, 0xae, 0xb4, 0xe6, - 0xbd, 0x4f, 0xf4, 0x5a, 0x1d, 0xb8, 0x6d, 0xef, 0x9f, 0x08, 0xd6, 0xaa, 0x60, 0x5a, - 0x97, 0xf3, 0x79, 0x39, + 0x1b, 0x32, 0xed, 0xbb, 0xe4, 0xd1, 0x8f, 0x28, 0x87, 0x6d, 0xe2, 0x62, 0x51, 0x8a, + 0xd3, 0x11, 0x22, 0x70, 0x1f, 0x8c, 0x0a, 0x52, 0xe9, 0x80, 0x47, 0xa3, 0x37, 0x87, + 0x6e, 0x7e, 0xea, 0x19, ], }, TestVector { sk: [ - 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31, 0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, - 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b, 0xe3, 0x4a, 0x98, 0x51, 0xa7, 0xaf, 0x9d, 0xb6, - 0x99, 0x0e, 0xd8, 0x3d, + 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, + 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, 0xe6, + 0x1d, 0xdf, 0x65, 0x8d, ], ask: [ - 0x41, 0xd4, 0x7c, 0xc9, 0x63, 0x13, 0xb4, 0x82, 0x1d, 0xfc, 0x12, 0x96, 0x51, 0xc3, - 0x13, 0x7f, 0x44, 0xd9, 0xca, 0xd1, 0x6b, 0x3d, 0xc0, 0x81, 0x33, 0xc3, 0xd2, 0xdf, - 0x0d, 0x0c, 0x53, 0x20, + 0x09, 0x25, 0x99, 0x63, 0x5a, 0xdb, 0x8e, 0x4e, 0x49, 0x04, 0x8d, 0x69, 0xd7, 0xfd, + 0x8c, 0xbd, 0x6a, 0x19, 0xda, 0x87, 0x4e, 0x63, 0xdd, 0xdc, 0xd9, 0xee, 0x13, 0xbf, + 0xa5, 0xce, 0x3b, 0x16, ], ak: [ - 0x6d, 0xe1, 0x34, 0x98, 0x30, 0xd6, 0x6d, 0x7b, 0x97, 0xfe, 0x23, 0x1f, 0xc7, 0xb0, - 0x2a, 0xd6, 0x43, 0x23, 0x62, 0x9c, 0xfe, 0xd1, 0xe3, 0xaa, 0x24, 0xef, 0x05, 0x2f, - 0x56, 0xe4, 0x00, 0x2a, + 0x6e, 0x44, 0x56, 0x73, 0x37, 0xc9, 0xa0, 0x26, 0xff, 0x00, 0xae, 0x91, 0x8b, 0xe7, + 0xc0, 0x8e, 0x50, 0x20, 0x44, 0x98, 0xbb, 0x43, 0x12, 0x30, 0x28, 0x4d, 0x05, 0xf1, + 0xce, 0x53, 0xef, 0x3f, ], isk: [ - 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04, 0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, - 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d, 0x32, 0x0d, 0xad, 0xd6, 0x4f, 0x54, 0x31, 0xe6, - 0x1d, 0xdf, 0x65, 0x8d, + 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, 0x59, + 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, + 0x89, 0x26, 0xc1, 0x03, ], ik: [ - 0x46, 0x2e, 0xe2, 0x38, 0x00, 0xc2, 0x1e, 0x2b, 0xbd, 0x90, 0x2b, 0xf7, 0x2f, 0x60, - 0xe1, 0xab, 0x08, 0x26, 0xd3, 0x68, 0x0c, 0x6f, 0xd0, 0xa2, 0x6f, 0x87, 0xdb, 0xac, - 0xd0, 0xd7, 0x6c, 0xa0, + 0x39, 0x62, 0x5b, 0x51, 0xaa, 0x0a, 0x3d, 0xde, 0x54, 0x6e, 0xde, 0x39, 0xa1, 0x23, + 0x2f, 0xa9, 0xba, 0xe8, 0x71, 0xab, 0x4f, 0x18, 0xe9, 0x0e, 0x5a, 0xe8, 0x03, 0x8c, + 0xce, 0xef, 0x66, 0x37, ], nk: [ - 0xa8, 0xb7, 0x3d, 0x97, 0x9b, 0x6e, 0xaa, 0xda, 0x89, 0x24, 0xbc, 0xbd, 0xc6, 0x3a, - 0x9e, 0xf4, 0xe8, 0x73, 0x46, 0xf2, 0x30, 0xab, 0xa6, 0xbb, 0xe1, 0xe2, 0xb4, 0x3c, - 0x5b, 0xea, 0x6b, 0x22, + 0x26, 0x84, 0x71, 0xe4, 0x66, 0xfe, 0x31, 0x2d, 0xd2, 0x07, 0x5d, 0x1a, 0x1a, 0x07, + 0xd8, 0x9b, 0x3e, 0xd2, 0x69, 0xba, 0x73, 0x97, 0xcf, 0x80, 0x14, 0xdd, 0x93, 0xbf, + 0xad, 0xd9, 0xa7, 0x34, ], rivk: [ - 0xda, 0xcb, 0x2f, 0x2a, 0x9c, 0xed, 0x36, 0x31, 0x71, 0x82, 0x1a, 0xaf, 0x5d, 0x8c, - 0xd9, 0x02, 0xbc, 0x5e, 0x3a, 0x5a, 0x41, 0xfb, 0x51, 0xae, 0x61, 0xa9, 0xf0, 0x2d, - 0xc8, 0x9d, 0x1d, 0x12, + 0x8d, 0x5e, 0x27, 0x86, 0xb5, 0x03, 0xc4, 0x65, 0xc7, 0x49, 0x03, 0x73, 0x46, 0x53, + 0xda, 0xff, 0xa3, 0x7a, 0x02, 0xad, 0x69, 0x76, 0x1a, 0x7c, 0x8a, 0x4d, 0x79, 0x83, + 0x02, 0xac, 0xe2, 0x3c, ], ivk: [ - 0x56, 0x3a, 0x6d, 0xb6, 0x0c, 0x74, 0xc2, 0xdb, 0x08, 0x49, 0x2c, 0xba, 0xe3, 0xbb, - 0x08, 0x3f, 0x1a, 0xea, 0xbf, 0xfb, 0xcf, 0x42, 0x55, 0x1d, 0x0a, 0xc6, 0x4f, 0x26, - 0x90, 0x53, 0x67, 0x11, + 0x35, 0xee, 0x37, 0x20, 0xc5, 0x5b, 0x02, 0x49, 0x75, 0x66, 0xa2, 0x50, 0x5d, 0x28, + 0x59, 0x60, 0xab, 0xf8, 0xc0, 0x5e, 0x68, 0x46, 0x9e, 0xad, 0x23, 0x91, 0xc9, 0x50, + 0xd6, 0xee, 0xc1, 0x10, ], ovk: [ - 0x71, 0xcd, 0x30, 0x64, 0x0f, 0xdb, 0x63, 0xf8, 0xd1, 0x30, 0x50, 0x29, 0xe9, 0x40, - 0xe5, 0x3f, 0xd5, 0xec, 0x04, 0xa8, 0xcc, 0xad, 0x41, 0x95, 0x78, 0xc2, 0x42, 0xfe, - 0xc0, 0x5b, 0x9a, 0xf7, + 0x60, 0x1a, 0xa8, 0xb5, 0x2f, 0xa8, 0x6b, 0x79, 0x5a, 0x18, 0x56, 0x0b, 0xcc, 0xc8, + 0x3d, 0xb1, 0xb5, 0xf9, 0x88, 0x25, 0x3c, 0xdd, 0x82, 0xf8, 0x84, 0x79, 0x2a, 0x04, + 0x25, 0x6f, 0x7b, 0x6d, ], dk: [ - 0x9d, 0x9b, 0xd4, 0x45, 0x25, 0xe7, 0xae, 0x06, 0xb0, 0x3a, 0xe6, 0xd4, 0xae, 0xcd, - 0xe6, 0xae, 0x09, 0x27, 0xa7, 0xc6, 0x67, 0xd5, 0xd9, 0xf8, 0x17, 0x6b, 0x54, 0x46, - 0x95, 0xdf, 0xec, 0x11, + 0x8a, 0x86, 0x44, 0xba, 0x40, 0xd0, 0xd0, 0x17, 0xf8, 0x1b, 0x04, 0xbb, 0x40, 0x0c, + 0x1b, 0xf8, 0x41, 0xfa, 0xce, 0x94, 0x6d, 0xc9, 0x8e, 0xc5, 0xde, 0xc6, 0xdd, 0x8f, + 0x9c, 0x32, 0x58, 0xee, ], default_d: [ - 0x78, 0x07, 0xca, 0x65, 0x08, 0x58, 0x81, 0x4d, 0x50, 0x22, 0xa8, + 0x44, 0x44, 0x93, 0xdb, 0xbc, 0x1a, 0x29, 0xe5, 0xe2, 0x6f, 0x6c, ], default_pk_d: [ - 0x3d, 0x3d, 0xe4, 0xd5, 0x2c, 0x77, 0xfd, 0x0b, 0x63, 0x0a, 0x40, 0xdc, 0x38, 0x21, - 0x24, 0x87, 0xb2, 0xff, 0x6e, 0xee, 0xf5, 0x6d, 0x8c, 0x6a, 0x61, 0x63, 0xe8, 0x54, - 0xaf, 0xf0, 0x41, 0x89, + 0x92, 0xcc, 0x30, 0xfa, 0xcd, 0x3a, 0xd8, 0xe6, 0xe4, 0xbb, 0xe6, 0xde, 0xdc, 0x71, + 0x9a, 0x09, 0x42, 0xaa, 0xf2, 0x77, 0xd6, 0xab, 0x39, 0x29, 0x2c, 0x26, 0x75, 0x78, + 0x15, 0x14, 0xd8, 0x93, ], internal_rivk: [ - 0x8a, 0x22, 0xa7, 0xf5, 0xa1, 0xe9, 0x1a, 0x92, 0xad, 0x39, 0x4b, 0x18, 0xeb, 0x73, - 0x38, 0xb5, 0x92, 0x47, 0x0d, 0xd4, 0x2b, 0xe8, 0xef, 0x84, 0xc9, 0x3e, 0x7c, 0xd8, - 0x45, 0xec, 0xfa, 0x32, + 0xc8, 0x17, 0xbf, 0x0f, 0x2d, 0xe1, 0xd1, 0xa4, 0x12, 0x52, 0x73, 0xb1, 0x15, 0x71, + 0xca, 0xe0, 0x67, 0x0c, 0xe3, 0xe4, 0x45, 0x6f, 0xbe, 0x0e, 0xb9, 0x03, 0x57, 0xda, + 0x15, 0xea, 0x2b, 0x03, ], internal_ivk: [ - 0x12, 0x11, 0x83, 0xcb, 0x3b, 0x8d, 0x06, 0xf5, 0x99, 0xbb, 0x38, 0xb3, 0x73, 0x22, - 0x85, 0x1e, 0x5f, 0xc9, 0x5a, 0xd0, 0xc9, 0x70, 0x7e, 0xe8, 0x5f, 0xb6, 0x5e, 0x21, - 0xf1, 0xa3, 0x0d, 0x13, + 0xcb, 0x28, 0xb7, 0xb9, 0x46, 0xe8, 0xf0, 0xb1, 0xa5, 0xda, 0x87, 0x6d, 0xda, 0x0c, + 0xac, 0x64, 0x1f, 0xc7, 0xfc, 0x16, 0x4e, 0x18, 0x99, 0xa6, 0xa5, 0xe0, 0xd8, 0x24, + 0x8c, 0xb1, 0x72, 0x3c, ], internal_ovk: [ - 0x93, 0x25, 0x2b, 0x24, 0xb4, 0x91, 0xd9, 0xc9, 0xc9, 0x97, 0x65, 0xc8, 0x4d, 0x4a, - 0xc7, 0xc2, 0xbf, 0xf0, 0x54, 0xcd, 0x9c, 0xad, 0xcd, 0x3e, 0x01, 0xb2, 0x6f, 0x21, - 0xe2, 0x84, 0x09, 0x09, + 0x6c, 0x94, 0xe6, 0xe4, 0x55, 0x9e, 0x70, 0xca, 0x50, 0xc5, 0x81, 0x25, 0x94, 0xf7, + 0x5c, 0x22, 0x93, 0x5d, 0x91, 0xea, 0xf7, 0x23, 0x56, 0x8e, 0xae, 0x2f, 0x9d, 0xc4, + 0xe9, 0x66, 0x0b, 0x53, ], internal_dk: [ - 0x6e, 0xea, 0x18, 0xfd, 0x0d, 0x50, 0x70, 0x7f, 0x90, 0xdf, 0x00, 0x2c, 0xbf, 0x30, - 0x9e, 0xca, 0x3c, 0x00, 0xd3, 0x98, 0xae, 0xde, 0x1f, 0xdc, 0x2a, 0xbf, 0xfc, 0x88, - 0x35, 0x38, 0x59, 0xaf, + 0x74, 0xb6, 0xa8, 0xee, 0x5b, 0x9b, 0x14, 0x84, 0x5e, 0x3e, 0x80, 0x7b, 0x84, 0x66, + 0x8e, 0xe4, 0xe4, 0x57, 0xd6, 0x40, 0xe3, 0xa3, 0xff, 0x61, 0x43, 0x6f, 0xe3, 0xda, + 0xcb, 0xaa, 0x01, 0xe9, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, @@ -229,94 +229,94 @@ pub(crate) fn test_vectors() -> Vec { 0xaa, 0xbe, 0x3f, 0x1a, ], note_cmx: [ - 0x3b, 0x7a, 0x77, 0x4e, 0x5a, 0xc0, 0x16, 0xfd, 0x2a, 0x8a, 0x2b, 0xa0, 0x21, 0x2e, - 0x67, 0xfe, 0x16, 0x92, 0x9b, 0xa7, 0x2e, 0x7b, 0x82, 0x70, 0x8b, 0xd5, 0x74, 0x96, - 0xfb, 0xb3, 0x0f, 0x22, + 0x23, 0x60, 0xbf, 0xad, 0x63, 0xb5, 0x1e, 0xfb, 0x16, 0x00, 0xa7, 0x6f, 0xf7, 0x3a, + 0xd7, 0x33, 0x54, 0x11, 0x31, 0x8a, 0x6a, 0x4b, 0x02, 0xb7, 0x57, 0x78, 0x3f, 0x01, + 0xdb, 0xa0, 0x40, 0x14, ], note_nf: [ - 0x6c, 0xba, 0xbc, 0xfe, 0x07, 0x58, 0xc0, 0x61, 0x75, 0x59, 0x3f, 0xcc, 0x89, 0x37, - 0x55, 0x9a, 0xc1, 0xc7, 0xb7, 0x22, 0xd5, 0x65, 0xa1, 0xf3, 0xfc, 0xf0, 0xb8, 0xc5, - 0x90, 0x37, 0x8a, 0x1c, + 0xd7, 0xa8, 0x9c, 0xee, 0x48, 0x18, 0xfc, 0x86, 0x4b, 0x11, 0xa0, 0x8f, 0x65, 0xad, + 0x3d, 0xbf, 0x26, 0xd4, 0x37, 0x99, 0x7f, 0x6a, 0xb8, 0xa6, 0x02, 0x58, 0x3b, 0xfc, + 0x6a, 0x62, 0x04, 0x10, ], }, TestVector { sk: [ - 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21, 0x03, 0x59, - 0x65, 0x55, 0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, - 0x89, 0x26, 0xc1, 0x03, + 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d, 0x99, 0x58, + 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, + 0x1c, 0xd0, 0x74, 0xa5, ], ask: [ - 0xe0, 0x9b, 0x65, 0x10, 0x87, 0x7d, 0xd4, 0x0e, 0x85, 0x4e, 0xe4, 0xb9, 0xc4, 0xc3, - 0x89, 0x8e, 0xc1, 0xe7, 0x26, 0x60, 0xfe, 0xf5, 0xb0, 0xab, 0xda, 0xdb, 0xa8, 0x08, - 0x10, 0x50, 0xae, 0x38, + 0xfa, 0x33, 0x7b, 0xa3, 0x9b, 0x90, 0x62, 0xd5, 0x11, 0x74, 0x68, 0x63, 0x83, 0xc8, + 0xa5, 0x99, 0x5a, 0x47, 0x6e, 0xc1, 0xe0, 0xc7, 0x0b, 0x68, 0xa2, 0x00, 0x3c, 0xd4, + 0x79, 0x25, 0x3e, 0x26, ], ak: [ - 0x53, 0xf7, 0x4b, 0x84, 0x33, 0xe9, 0x4a, 0xae, 0xb8, 0x5f, 0x5e, 0xb4, 0x1a, 0x89, - 0xc1, 0x0f, 0xe2, 0x0a, 0xe0, 0x03, 0xec, 0xf4, 0xbc, 0xe1, 0x63, 0x38, 0xd9, 0x75, - 0x88, 0x65, 0x6b, 0x38, + 0xc4, 0xfd, 0xec, 0x5a, 0xc0, 0xc4, 0x8b, 0xe1, 0xf2, 0xb0, 0x60, 0xfa, 0x21, 0x40, + 0x7f, 0x85, 0xd2, 0xd4, 0x52, 0xf2, 0x8f, 0xc6, 0x42, 0xed, 0x67, 0x50, 0xec, 0x6d, + 0x8c, 0xf8, 0x7c, 0x22, ], isk: [ - 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d, 0x99, 0x58, - 0x9c, 0x8b, 0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, - 0x1c, 0xd0, 0x74, 0xa5, + 0x58, 0xcf, 0xb5, 0xcd, 0x79, 0xf8, 0x80, 0x08, 0xe3, 0x15, 0xdc, 0x7d, 0x83, 0x88, + 0xe7, 0x6c, 0x17, 0x82, 0xfd, 0x27, 0x95, 0xd1, 0x8a, 0x76, 0x36, 0x24, 0xc2, 0x5f, + 0xa9, 0x59, 0xcc, 0x97, ], ik: [ - 0xcb, 0x48, 0x0d, 0x9b, 0x96, 0x27, 0x3e, 0x89, 0x91, 0x40, 0x89, 0xa1, 0x04, 0xc2, - 0xc9, 0x36, 0xd0, 0x75, 0x95, 0xd4, 0xf8, 0x46, 0xad, 0xa6, 0xca, 0xea, 0x68, 0x5c, - 0x88, 0x0b, 0x8a, 0xf8, + 0x78, 0xd1, 0xdc, 0xef, 0xee, 0x06, 0xc5, 0x66, 0x7f, 0x19, 0x76, 0xa5, 0x66, 0x73, + 0x13, 0x0b, 0x9e, 0x72, 0x05, 0xf3, 0xa5, 0x0a, 0xd1, 0x96, 0x00, 0x89, 0x6c, 0xe5, + 0xc2, 0x64, 0xfa, 0xf6, ], nk: [ - 0x6e, 0x37, 0x10, 0xbc, 0xa6, 0x80, 0x46, 0xc8, 0x3e, 0x54, 0x80, 0xbf, 0xe7, 0x3f, - 0xd7, 0x54, 0x13, 0x5d, 0xc0, 0x7f, 0xa1, 0xd1, 0x1b, 0x86, 0x5f, 0xd1, 0x5e, 0x7c, - 0x4e, 0x63, 0xe2, 0x02, + 0x9d, 0xca, 0xb0, 0x5e, 0x6c, 0x24, 0x15, 0xad, 0x65, 0xb6, 0x4e, 0x6a, 0x9a, 0xec, + 0xb1, 0x53, 0x60, 0x77, 0x87, 0x8d, 0x85, 0xc5, 0x33, 0x9a, 0x2b, 0x59, 0x79, 0x06, + 0xdf, 0xba, 0x9f, 0x3e, ], rivk: [ - 0xaa, 0xcc, 0xc8, 0x41, 0xfe, 0x74, 0x89, 0x49, 0xcf, 0x90, 0x59, 0xb5, 0x41, 0x1c, - 0x2c, 0xe8, 0xf0, 0x07, 0x05, 0x00, 0x23, 0x85, 0x2d, 0xd5, 0x8d, 0xb0, 0xb6, 0x9b, - 0x44, 0xfe, 0xf5, 0x33, + 0x4b, 0x61, 0x99, 0xae, 0x4c, 0x65, 0x21, 0x61, 0x11, 0x3d, 0x78, 0x75, 0xfa, 0x2f, + 0x85, 0xde, 0x60, 0xa1, 0xa2, 0x01, 0x73, 0x75, 0x9e, 0xa6, 0xb7, 0xcd, 0x8e, 0xc7, + 0xe5, 0x9b, 0x20, 0x35, ], ivk: [ - 0xa8, 0x1d, 0xfd, 0x18, 0xbf, 0x1e, 0x5e, 0xad, 0x3d, 0x10, 0x02, 0xf5, 0xfe, 0x4b, - 0xcb, 0x89, 0xde, 0xea, 0xf9, 0xd6, 0x4c, 0xf8, 0x0a, 0xef, 0xdc, 0xb6, 0xcd, 0x0c, - 0xb7, 0xd1, 0x79, 0x02, + 0x1d, 0x9e, 0x91, 0xca, 0x38, 0x82, 0x79, 0x59, 0x18, 0x53, 0x6b, 0x51, 0x14, 0xae, + 0x21, 0x63, 0x57, 0x62, 0xf1, 0x49, 0xc9, 0x59, 0x09, 0x80, 0x3f, 0x36, 0xea, 0x9f, + 0xca, 0x71, 0x1f, 0x2f, ], ovk: [ - 0x45, 0xcf, 0x1a, 0x1d, 0xf6, 0x62, 0xfe, 0xc0, 0xf7, 0x84, 0x7a, 0x63, 0xa0, 0xd7, - 0x95, 0x51, 0xe1, 0xb0, 0x49, 0xc3, 0xc3, 0x58, 0x7e, 0x68, 0x37, 0xa7, 0x54, 0x45, - 0xa0, 0x04, 0x12, 0xa7, + 0x94, 0x30, 0xaf, 0xfd, 0x7e, 0x29, 0x2b, 0xa8, 0xf7, 0xab, 0x0c, 0xc1, 0xfa, 0xcd, + 0x67, 0xb4, 0x99, 0x59, 0x4b, 0xf6, 0x8d, 0x93, 0xeb, 0x3a, 0xb7, 0x51, 0x5d, 0x88, + 0xa0, 0x87, 0xe0, 0xef, ], dk: [ - 0xa8, 0x61, 0xd9, 0xa4, 0x37, 0x61, 0x87, 0xb2, 0xb5, 0xc1, 0x9a, 0x5f, 0x89, 0x6f, - 0xa4, 0x75, 0xaa, 0x0e, 0xd3, 0x8b, 0x99, 0x54, 0xf3, 0x93, 0x8a, 0x04, 0xec, 0x41, - 0xe5, 0x4f, 0xaf, 0x1c, + 0x5f, 0x15, 0x10, 0x14, 0xd0, 0x9f, 0xe9, 0x14, 0x68, 0x52, 0x66, 0x1e, 0xcb, 0xe3, + 0x3c, 0x1e, 0xea, 0xcc, 0x6d, 0xd9, 0xf7, 0x3b, 0xd0, 0xd4, 0xdc, 0x82, 0x5f, 0x4f, + 0x2f, 0xc2, 0x94, 0xde, ], default_d: [ - 0x59, 0x8d, 0x20, 0x0e, 0x50, 0x9e, 0xc2, 0x4b, 0xdc, 0x7f, 0x1c, + 0x10, 0x23, 0x07, 0x3f, 0x95, 0x67, 0xce, 0xa8, 0x22, 0x82, 0xe1, ], default_pk_d: [ - 0x68, 0x10, 0x44, 0xee, 0x77, 0xd7, 0xf8, 0x6a, 0x0a, 0x5c, 0x0c, 0xbe, 0x89, 0xa7, - 0xef, 0x3b, 0x3f, 0x5a, 0x6e, 0x85, 0x99, 0x8f, 0x48, 0x48, 0x51, 0xc9, 0x8a, 0x22, - 0x80, 0x18, 0xa0, 0x1e, + 0x28, 0xb9, 0x35, 0x6e, 0x43, 0xb5, 0x75, 0x78, 0x1a, 0x09, 0x02, 0xbd, 0xbc, 0x93, + 0xe5, 0x57, 0x98, 0x78, 0xa8, 0x41, 0x63, 0x14, 0x70, 0xb4, 0x07, 0x9b, 0x05, 0x90, + 0x18, 0xa5, 0x20, 0x0d, ], internal_rivk: [ - 0xda, 0x3c, 0xdd, 0x9e, 0x0a, 0x3d, 0x1c, 0x41, 0x3e, 0x51, 0xb5, 0x34, 0x67, 0x7e, - 0x88, 0x3e, 0x85, 0x4b, 0x5f, 0x54, 0xbb, 0xdb, 0xba, 0x05, 0x04, 0xab, 0xb2, 0x2b, - 0x31, 0x5c, 0x4c, 0x1d, + 0xb2, 0x63, 0x58, 0x05, 0xef, 0x00, 0x78, 0xaf, 0x79, 0x32, 0xe3, 0x93, 0x40, 0x82, + 0x94, 0xcb, 0xc0, 0xf3, 0xfa, 0x93, 0x56, 0x8f, 0x2b, 0xbe, 0x07, 0x29, 0x8f, 0xc2, + 0xba, 0xf9, 0x53, 0x3a, ], internal_ivk: [ - 0x29, 0x3f, 0xf5, 0xf5, 0x2b, 0x40, 0xcf, 0x48, 0xeb, 0x4f, 0x21, 0x45, 0x24, 0xad, - 0xed, 0x6b, 0x53, 0x85, 0xf6, 0x09, 0x67, 0x56, 0xec, 0xa3, 0x0d, 0x46, 0xff, 0x47, - 0xa8, 0xc8, 0x6f, 0x0c, + 0xcb, 0x69, 0xdc, 0x54, 0x1d, 0x52, 0x7e, 0x1c, 0x1f, 0x4c, 0x7a, 0xd7, 0xd2, 0x67, + 0xe3, 0x18, 0xed, 0xaa, 0x79, 0x15, 0x61, 0xcd, 0x5c, 0xee, 0x51, 0x8e, 0x14, 0xaa, + 0xaa, 0x4c, 0x0e, 0x08, ], internal_ovk: [ - 0x0c, 0xfc, 0xe5, 0xec, 0xc4, 0x1f, 0x12, 0x02, 0xcb, 0x61, 0xa4, 0x7f, 0x6d, 0x55, - 0x9a, 0x63, 0x92, 0x25, 0xc5, 0xb4, 0x7a, 0x99, 0x65, 0xc3, 0x02, 0x00, 0xd1, 0xb7, - 0xea, 0x58, 0xc1, 0x30, + 0x25, 0x58, 0x8e, 0xdb, 0xf6, 0x77, 0x42, 0xab, 0x55, 0xca, 0x95, 0xa9, 0x0a, 0xe0, + 0xe0, 0x29, 0xa8, 0x7f, 0xc4, 0xcf, 0x9c, 0xf3, 0xf7, 0x00, 0x65, 0xe0, 0x64, 0xec, + 0xc4, 0xd6, 0x45, 0x8e, ], internal_dk: [ - 0x43, 0x81, 0x82, 0x5b, 0x76, 0xeb, 0x8d, 0x47, 0x0a, 0x8b, 0x98, 0xed, 0x53, 0xff, - 0xb4, 0xd1, 0xf2, 0x1e, 0x96, 0x45, 0x0b, 0xe9, 0x4b, 0x15, 0xa8, 0x52, 0x1e, 0xe8, - 0x6f, 0xb6, 0xea, 0xe8, + 0xad, 0x38, 0x62, 0x22, 0xdd, 0xd6, 0x65, 0x3b, 0xed, 0x73, 0x36, 0x64, 0x3d, 0xcb, + 0x63, 0x51, 0x4a, 0x25, 0x17, 0x7a, 0x81, 0xf5, 0x8f, 0x84, 0x06, 0x84, 0x4e, 0x16, + 0x42, 0xdb, 0x6e, 0x03, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, @@ -335,94 +335,94 @@ pub(crate) fn test_vectors() -> Vec { 0xd9, 0xee, 0xcf, 0xa1, ], note_cmx: [ - 0x1b, 0x83, 0x10, 0x6d, 0xf8, 0x12, 0xf5, 0xb3, 0x24, 0xbc, 0x8d, 0xc9, 0x87, 0x02, - 0x52, 0xfd, 0x7a, 0x44, 0xf2, 0xd7, 0x5b, 0xf5, 0x54, 0x41, 0xac, 0x92, 0x5b, 0x45, - 0x82, 0xf9, 0x75, 0x17, + 0x44, 0x41, 0x60, 0xcb, 0x6e, 0x4c, 0xe5, 0x98, 0xe9, 0x48, 0x82, 0x6a, 0x81, 0x6f, + 0xfa, 0xdb, 0xfb, 0xd2, 0x4b, 0xe0, 0x1d, 0x4e, 0xfd, 0x41, 0x37, 0x8f, 0x79, 0x2e, + 0xdb, 0xa9, 0xf0, 0x14, ], note_nf: [ - 0x4b, 0xf3, 0xd9, 0x9e, 0x14, 0xdb, 0x5c, 0xa1, 0xb5, 0x81, 0x8d, 0x93, 0x37, 0xe9, - 0x26, 0xb1, 0x3c, 0x55, 0x94, 0x12, 0xd5, 0x61, 0xb6, 0xc7, 0x30, 0x53, 0xe2, 0xc7, - 0xb2, 0x08, 0x5a, 0x2d, + 0xec, 0xe2, 0x42, 0x8b, 0x0b, 0x0a, 0x02, 0x26, 0xbb, 0x88, 0xf6, 0x4f, 0xfe, 0x2e, + 0x9c, 0x5e, 0x6d, 0x4c, 0x44, 0x3d, 0xa9, 0x46, 0xb0, 0x0d, 0x0d, 0x8f, 0x80, 0x1c, + 0x2f, 0x2d, 0xa9, 0x03, ], }, TestVector { sk: [ - 0x58, 0xcf, 0xb5, 0xcd, 0x79, 0xf8, 0x80, 0x08, 0xe3, 0x15, 0xdc, 0x7d, 0x83, 0x88, - 0xe7, 0x6c, 0x17, 0x82, 0xfd, 0x27, 0x95, 0xd1, 0x8a, 0x76, 0x36, 0x24, 0xc2, 0x5f, - 0xa9, 0x59, 0xcc, 0x97, + 0x48, 0x9c, 0xe7, 0x57, 0x45, 0x82, 0x4b, 0x77, 0x86, 0x8c, 0x53, 0x23, 0x9c, 0xfb, + 0xdf, 0x73, 0xca, 0xec, 0x65, 0x60, 0x40, 0x37, 0x31, 0x4f, 0xaa, 0xce, 0xb5, 0x62, + 0x18, 0xc6, 0xbd, 0x30, ], ask: [ - 0x74, 0xef, 0xaa, 0xff, 0x27, 0x9c, 0xde, 0x93, 0x36, 0x11, 0x7a, 0xa4, 0x68, 0xb4, - 0xed, 0xdb, 0x70, 0x38, 0xa1, 0x22, 0xef, 0x86, 0x7d, 0xba, 0x05, 0x3e, 0x33, 0x55, - 0x68, 0x0a, 0x8c, 0x3c, + 0x2c, 0x04, 0x9c, 0x69, 0xcf, 0x07, 0x87, 0x81, 0x61, 0xc0, 0xa3, 0x55, 0x24, 0x07, + 0x8a, 0x46, 0x55, 0x30, 0xb6, 0xec, 0xab, 0x1b, 0xd8, 0xd7, 0x48, 0xb1, 0xd8, 0x16, + 0x9e, 0x91, 0xe6, 0x08, ], ak: [ - 0xc4, 0x51, 0x8d, 0x3c, 0xde, 0xa6, 0x55, 0xa3, 0x2d, 0xf8, 0xe3, 0xf5, 0xc1, 0x51, - 0xb5, 0x42, 0x32, 0x85, 0x31, 0xca, 0x01, 0xa6, 0x3f, 0x3c, 0x03, 0xa3, 0xc2, 0x4e, - 0xa7, 0x32, 0x82, 0x3a, + 0x7d, 0xcf, 0x33, 0x91, 0x77, 0x05, 0x64, 0xc8, 0xf9, 0xe7, 0xc1, 0x7b, 0xf6, 0x7f, + 0x05, 0x4e, 0x5b, 0xd0, 0x40, 0xc4, 0xde, 0x28, 0xd8, 0xdd, 0x46, 0xd5, 0x8d, 0xf8, + 0xc5, 0xee, 0xe6, 0x2d, ], isk: [ - 0x48, 0x9c, 0xe7, 0x57, 0x45, 0x82, 0x4b, 0x77, 0x86, 0x8c, 0x53, 0x23, 0x9c, 0xfb, - 0xdf, 0x73, 0xca, 0xec, 0x65, 0x60, 0x40, 0x37, 0x31, 0x4f, 0xaa, 0xce, 0xb5, 0x62, - 0x18, 0xc6, 0xbd, 0x30, + 0x7f, 0x4f, 0x5c, 0xcb, 0xdb, 0xc5, 0x96, 0x63, 0x12, 0x77, 0xf8, 0xfe, 0xcd, 0x08, + 0xcb, 0x05, 0x6b, 0x95, 0xe3, 0x02, 0x5b, 0x97, 0x92, 0xff, 0xf7, 0xf2, 0x44, 0xfc, + 0x71, 0x62, 0x69, 0xb9, ], ik: [ - 0xed, 0x56, 0xef, 0x8b, 0x55, 0x28, 0x00, 0x0f, 0xc2, 0xee, 0xf3, 0x33, 0x50, 0x8f, - 0x4c, 0x32, 0x71, 0x62, 0xd8, 0x96, 0x3b, 0xad, 0x50, 0xcc, 0x55, 0xdc, 0x03, 0x7d, - 0xb9, 0x60, 0x7f, 0x52, + 0x39, 0xc4, 0x51, 0xf4, 0xd8, 0xdd, 0xcf, 0x69, 0x05, 0xed, 0xd8, 0x82, 0x5a, 0xd9, + 0x81, 0xb9, 0xe7, 0x3c, 0xa6, 0x83, 0x1c, 0xa2, 0xb3, 0xd7, 0xe8, 0xce, 0xf3, 0xd0, + 0xba, 0xaa, 0x31, 0x1b, ], nk: [ - 0x76, 0xff, 0xc1, 0xbb, 0x8d, 0xd7, 0xfb, 0x48, 0x7d, 0x48, 0xd0, 0x94, 0x29, 0x66, - 0x0b, 0xbc, 0x1d, 0xfc, 0xbf, 0x57, 0xc4, 0xa5, 0xa3, 0x21, 0x33, 0x24, 0x33, 0x44, - 0x70, 0xed, 0xdf, 0x33, + 0x8d, 0xa4, 0xba, 0x62, 0x70, 0xae, 0x6d, 0x89, 0xa8, 0x6a, 0x06, 0xbc, 0x84, 0xbb, + 0x41, 0x53, 0xac, 0xbc, 0x5f, 0x7d, 0xb7, 0xa9, 0x55, 0x6c, 0x57, 0x79, 0xcf, 0x76, + 0xb7, 0x66, 0x25, 0x03, ], rivk: [ - 0x22, 0xe2, 0xf3, 0x90, 0x11, 0xe6, 0x70, 0xc8, 0x0f, 0xba, 0xc8, 0x91, 0x59, 0xac, - 0x63, 0x4d, 0x84, 0xd7, 0xc1, 0x3e, 0xbe, 0xfb, 0x97, 0x3b, 0xa4, 0x1f, 0x0c, 0x79, - 0xf0, 0x33, 0xfc, 0x3f, + 0xf3, 0x50, 0x76, 0x23, 0x5d, 0x13, 0xd3, 0x20, 0xdd, 0xd5, 0x1c, 0xf8, 0x7f, 0xaa, + 0x09, 0x40, 0xed, 0x38, 0xa6, 0x06, 0xae, 0xe1, 0x8b, 0x90, 0x18, 0x30, 0xa8, 0x87, + 0x87, 0xb2, 0xa1, 0x32, ], ivk: [ - 0xe6, 0x80, 0xf5, 0xa7, 0x15, 0xb3, 0x2b, 0x9e, 0x1a, 0x14, 0x67, 0x9f, 0x11, 0x16, - 0xf1, 0x13, 0xaa, 0x04, 0x93, 0xf3, 0x82, 0x1b, 0x10, 0x8c, 0xa7, 0xe1, 0xc0, 0x71, - 0xad, 0x75, 0x2d, 0x22, + 0xcc, 0x27, 0xbc, 0x8f, 0xda, 0x30, 0x60, 0xa5, 0x95, 0x26, 0x23, 0xef, 0x80, 0xaa, + 0x64, 0x1c, 0x58, 0x43, 0x2a, 0x82, 0xd3, 0x26, 0x8b, 0x35, 0x89, 0xb1, 0x45, 0xf1, + 0x52, 0x0b, 0x43, 0x1d, ], ovk: [ - 0x2a, 0x34, 0xab, 0x11, 0xc4, 0x0c, 0x6b, 0x3b, 0x28, 0x54, 0x56, 0xa6, 0x91, 0x54, - 0xcb, 0xe4, 0x4c, 0xba, 0x01, 0xda, 0x6d, 0xb0, 0xc2, 0xb2, 0x2b, 0x84, 0xca, 0x27, - 0x2b, 0xae, 0x01, 0xad, + 0xae, 0xee, 0xcc, 0x69, 0x80, 0xf9, 0x7c, 0x1e, 0x6f, 0x89, 0x09, 0xaf, 0x63, 0x48, + 0xe4, 0xbd, 0x20, 0x83, 0x65, 0x81, 0x0d, 0x1b, 0x99, 0xe8, 0x47, 0x56, 0xa3, 0xcb, + 0xdf, 0x4c, 0x35, 0x98, ], dk: [ - 0xfa, 0xaa, 0xb4, 0xb9, 0x32, 0x46, 0x23, 0xc6, 0xc8, 0x6b, 0xd5, 0xdb, 0x70, 0xa7, - 0x18, 0xd9, 0x0b, 0xc0, 0xf1, 0x5b, 0x2b, 0x39, 0xeb, 0xfa, 0x82, 0xb5, 0xb1, 0xcc, - 0x14, 0x67, 0x0c, 0xbe, + 0x63, 0xc4, 0xf6, 0xcd, 0x2c, 0xbd, 0xbb, 0x5a, 0x04, 0x81, 0xba, 0x93, 0x4f, 0xd1, + 0xc1, 0xd7, 0x4c, 0x1c, 0xeb, 0xf0, 0xcb, 0x58, 0x39, 0x78, 0xc8, 0x5b, 0xa2, 0x0b, + 0x14, 0x81, 0x89, 0x17, ], default_d: [ - 0x66, 0x4c, 0xab, 0xf8, 0xf7, 0x68, 0x93, 0xcb, 0x8d, 0xa7, 0x84, + 0xa1, 0xc6, 0x51, 0x16, 0xe0, 0x0a, 0x9b, 0x10, 0x51, 0x18, 0x0e, ], default_pk_d: [ - 0x07, 0x7c, 0x84, 0x57, 0x8b, 0x1d, 0xae, 0x2f, 0x80, 0x69, 0xef, 0x67, 0xd2, 0x87, - 0x71, 0x8d, 0xaf, 0xf5, 0xa1, 0x69, 0x4e, 0x1a, 0x8e, 0xa2, 0x36, 0xc9, 0xe6, 0x94, - 0x61, 0x5f, 0xb8, 0x16, + 0x1a, 0xea, 0xce, 0xdd, 0x51, 0x8a, 0x38, 0x57, 0x7d, 0x6a, 0x70, 0x90, 0x45, 0x59, + 0x72, 0x15, 0x5b, 0x34, 0x44, 0xb3, 0x24, 0x29, 0x34, 0x5d, 0x39, 0x67, 0x50, 0x87, + 0xbd, 0xcc, 0x39, 0xb1, ], internal_rivk: [ - 0xc4, 0x01, 0xbc, 0x90, 0x7a, 0xaa, 0xed, 0xd1, 0x3b, 0x1f, 0xa7, 0x0d, 0x7a, 0xb2, - 0x8d, 0x71, 0x3b, 0x46, 0x38, 0xeb, 0xfb, 0xc8, 0xf9, 0xcc, 0x1d, 0xae, 0xd5, 0xac, - 0x2b, 0x76, 0x75, 0x33, + 0x69, 0xbe, 0x50, 0x0f, 0xdd, 0xc9, 0x8f, 0x2d, 0x11, 0x0f, 0x4e, 0xc6, 0x96, 0xd1, + 0xf5, 0x7c, 0xe6, 0x3d, 0x2c, 0xae, 0xd8, 0x85, 0x39, 0x74, 0x75, 0xc2, 0x5d, 0x21, + 0x09, 0x09, 0xf6, 0x1f, ], internal_ivk: [ - 0xea, 0x9b, 0xeb, 0x2d, 0x19, 0x6a, 0xd4, 0x79, 0x69, 0xf2, 0x03, 0xdd, 0x28, 0xa0, - 0xfb, 0xe2, 0x4b, 0x98, 0x12, 0xb1, 0x15, 0x5b, 0x17, 0x01, 0x96, 0x36, 0x6a, 0xcd, - 0x62, 0xf5, 0xeb, 0x0c, + 0x32, 0xee, 0xca, 0x1a, 0xa6, 0x74, 0x76, 0x74, 0xb9, 0x75, 0x25, 0x5d, 0x08, 0x4b, + 0x03, 0x5b, 0x98, 0x51, 0xcd, 0x50, 0x18, 0xdd, 0xf6, 0x47, 0xce, 0xb9, 0xe1, 0xde, + 0x9e, 0x43, 0x9b, 0x2c, ], internal_ovk: [ - 0x2f, 0x6d, 0x74, 0x4f, 0x40, 0xd6, 0xdc, 0xe6, 0x5e, 0x33, 0x5d, 0x3c, 0xb3, 0x96, - 0xc5, 0xaf, 0x54, 0xf0, 0xf7, 0xd5, 0x4f, 0xb4, 0x37, 0xec, 0x8e, 0x20, 0x29, 0x28, - 0x05, 0x8e, 0xfa, 0xdf, + 0x43, 0x48, 0xf7, 0x3e, 0x04, 0x54, 0x47, 0x05, 0x59, 0xad, 0x5e, 0x42, 0x29, 0x37, + 0xb8, 0x78, 0x87, 0x4d, 0x64, 0x64, 0xf9, 0x94, 0x08, 0x04, 0x17, 0xeb, 0x16, 0xb6, + 0xd0, 0xac, 0x1b, 0xa4, ], internal_dk: [ - 0x9f, 0xec, 0x61, 0xd0, 0x20, 0xb9, 0x29, 0x37, 0xbd, 0xf3, 0xc3, 0xce, 0x09, 0x43, - 0x3d, 0xdf, 0x01, 0xd4, 0xab, 0xe7, 0x43, 0x93, 0x94, 0x6e, 0x49, 0xcd, 0x79, 0xd1, - 0x19, 0x86, 0xb9, 0xfe, + 0x27, 0x6d, 0x6e, 0xf9, 0xed, 0x58, 0xfa, 0x8a, 0x81, 0x18, 0x02, 0xbd, 0x3a, 0x0c, + 0x44, 0xd7, 0x9d, 0xbb, 0xe0, 0x6b, 0x94, 0x20, 0x0d, 0x43, 0x44, 0x28, 0x5b, 0x26, + 0x60, 0x03, 0xf4, 0x45, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, @@ -441,94 +441,94 @@ pub(crate) fn test_vectors() -> Vec { 0x33, 0x57, 0xd7, 0x76, ], note_cmx: [ - 0xbb, 0x2d, 0xd3, 0x29, 0xdf, 0xca, 0x48, 0xdc, 0x11, 0x56, 0x36, 0x58, 0xd0, 0x7e, - 0x20, 0x4a, 0x1d, 0x21, 0x2d, 0x20, 0x27, 0xe1, 0x45, 0x7c, 0xe6, 0x96, 0x8c, 0xdf, - 0xb0, 0x07, 0x7e, 0x04, + 0x5f, 0x5f, 0x8c, 0xff, 0x89, 0xb1, 0xbe, 0xdc, 0x6f, 0x58, 0x4f, 0x0b, 0x85, 0x58, + 0x6a, 0x54, 0x4b, 0xc4, 0x25, 0x53, 0x88, 0xa5, 0xff, 0x72, 0xf6, 0x75, 0x13, 0x8b, + 0xcb, 0x70, 0xb2, 0x27, ], note_nf: [ - 0xd4, 0x0c, 0xe3, 0x47, 0xb2, 0x3e, 0x26, 0x36, 0xc2, 0xb4, 0xc5, 0x43, 0x39, 0x50, - 0x26, 0xab, 0xb4, 0xa1, 0x5f, 0x28, 0xf9, 0x0a, 0x67, 0xb7, 0x08, 0xd6, 0x4b, 0x22, - 0x6f, 0x3a, 0x39, 0x31, + 0x8f, 0xca, 0x6e, 0x8b, 0x77, 0xab, 0x9d, 0x19, 0xf2, 0xf8, 0x35, 0x39, 0xa2, 0x91, + 0x29, 0x2f, 0xb1, 0x5e, 0x00, 0x50, 0xde, 0xd7, 0x77, 0x13, 0x3e, 0x75, 0x1e, 0x9f, + 0x0a, 0xe2, 0xff, 0x35, ], }, TestVector { sk: [ - 0x7f, 0x4f, 0x5c, 0xcb, 0xdb, 0xc5, 0x96, 0x63, 0x12, 0x77, 0xf8, 0xfe, 0xcd, 0x08, - 0xcb, 0x05, 0x6b, 0x95, 0xe3, 0x02, 0x5b, 0x97, 0x92, 0xff, 0xf7, 0xf2, 0x44, 0xfc, - 0x71, 0x62, 0x69, 0xb9, + 0x26, 0xd6, 0x2e, 0x95, 0x96, 0xfa, 0x82, 0x5c, 0x6b, 0xf2, 0x1a, 0xff, 0x9e, 0x68, + 0x62, 0x5a, 0x19, 0x24, 0x40, 0xea, 0x06, 0x82, 0x81, 0x23, 0xd9, 0x78, 0x84, 0x80, + 0x6f, 0x15, 0xfa, 0x08, ], ask: [ - 0x0a, 0xfd, 0x61, 0xd4, 0x12, 0x57, 0xb5, 0xe9, 0x36, 0xb9, 0x29, 0x29, 0xa3, 0xe1, - 0xb8, 0x7d, 0x60, 0x89, 0x7c, 0xb3, 0xdc, 0x8e, 0x77, 0x3f, 0x4f, 0xa1, 0xef, 0x40, - 0xef, 0xb5, 0x4b, 0x04, + 0xfa, 0x92, 0x86, 0xf7, 0x67, 0x77, 0x23, 0x5c, 0x74, 0x3d, 0xfa, 0xc1, 0xb8, 0x83, + 0x0d, 0x9f, 0xe3, 0x33, 0xca, 0xd7, 0x21, 0xd5, 0x49, 0xa9, 0x47, 0xc7, 0x5e, 0xce, + 0x7d, 0x00, 0xf5, 0x38, ], ak: [ - 0x84, 0x7e, 0xc5, 0xb1, 0xe3, 0xdd, 0xfd, 0x93, 0xca, 0x0c, 0x67, 0xea, 0x48, 0x1b, - 0x40, 0x5b, 0xae, 0xef, 0x48, 0xb0, 0xf2, 0x7f, 0x87, 0xb8, 0x1f, 0xed, 0x32, 0xae, - 0x56, 0x31, 0x6f, 0x04, + 0x10, 0x07, 0x3a, 0x7a, 0xe1, 0x28, 0x59, 0x2d, 0xbe, 0xe5, 0x28, 0x2b, 0xc1, 0x24, + 0x1b, 0x94, 0x75, 0xa5, 0x98, 0x19, 0x62, 0xbd, 0xf2, 0x14, 0xe9, 0x35, 0xd9, 0xb3, + 0x27, 0xf0, 0x25, 0x24, ], isk: [ - 0x26, 0xd6, 0x2e, 0x95, 0x96, 0xfa, 0x82, 0x5c, 0x6b, 0xf2, 0x1a, 0xff, 0x9e, 0x68, - 0x62, 0x5a, 0x19, 0x24, 0x40, 0xea, 0x06, 0x82, 0x81, 0x23, 0xd9, 0x78, 0x84, 0x80, - 0x6f, 0x15, 0xfa, 0x08, + 0xe2, 0xf5, 0x7e, 0x34, 0xfb, 0xc7, 0x54, 0x23, 0xc3, 0x73, 0x7f, 0x5b, 0x2a, 0x06, + 0x15, 0xf5, 0x72, 0x2d, 0xb0, 0x41, 0xa3, 0xef, 0x66, 0xfa, 0x48, 0x3a, 0xfd, 0x3c, + 0x2e, 0x19, 0xe5, 0x94, ], ik: [ - 0x95, 0x9c, 0x44, 0x8d, 0xaf, 0xb6, 0xb7, 0xc2, 0x54, 0x90, 0x42, 0xdd, 0x75, 0x7a, - 0x81, 0xfa, 0x16, 0xca, 0xd4, 0xd2, 0x7f, 0xc1, 0x5f, 0x45, 0x33, 0xcd, 0xe2, 0x0c, - 0xc5, 0xb5, 0xcd, 0xc9, + 0x2b, 0x5d, 0xe5, 0x60, 0x92, 0xfe, 0xa3, 0x1a, 0x8e, 0xa9, 0xf8, 0x70, 0x84, 0x7d, + 0xc1, 0xfa, 0x87, 0xfd, 0x3c, 0x25, 0xcf, 0x70, 0x9a, 0x0e, 0xff, 0xd6, 0x99, 0xc2, + 0x96, 0x41, 0x31, 0x6e, ], nk: [ - 0xd7, 0xd8, 0xf3, 0xd5, 0x18, 0x22, 0xd3, 0x4a, 0xdf, 0x86, 0xeb, 0xd3, 0x53, 0x36, - 0x47, 0x73, 0x2c, 0x03, 0xf6, 0x42, 0xd6, 0xed, 0x06, 0xff, 0x61, 0xd2, 0x50, 0xd6, - 0xba, 0xfd, 0x59, 0x37, + 0x4f, 0xb7, 0x68, 0x10, 0x2e, 0x99, 0xbe, 0xfe, 0x6e, 0x76, 0xed, 0x4e, 0xea, 0x65, + 0x83, 0x54, 0x14, 0x78, 0x00, 0x4e, 0x96, 0x49, 0x26, 0xfd, 0x34, 0x70, 0x4a, 0xcc, + 0xd9, 0x2d, 0x0c, 0x1f, ], rivk: [ - 0xae, 0xea, 0xd1, 0x3e, 0x25, 0x36, 0xe8, 0xcb, 0xa6, 0x24, 0x46, 0xd8, 0xff, 0x10, - 0x99, 0x88, 0xce, 0xa9, 0xb2, 0x57, 0xce, 0xaf, 0xc8, 0xd2, 0x0b, 0x85, 0x07, 0xcc, - 0xc9, 0x81, 0x58, 0x2a, + 0x1a, 0x02, 0xd2, 0x88, 0x78, 0x30, 0xe0, 0xb4, 0xb6, 0xdf, 0xe3, 0xcf, 0x65, 0x8d, + 0x2c, 0x04, 0x05, 0x20, 0x26, 0x4b, 0x38, 0x12, 0xaf, 0xd7, 0x9e, 0x13, 0xed, 0xfc, + 0xb2, 0x53, 0xd4, 0x39, ], ivk: [ - 0x83, 0xbb, 0x91, 0x72, 0x72, 0xb0, 0xa0, 0x4b, 0x78, 0x21, 0xfb, 0x8e, 0xef, 0xd5, - 0x7b, 0xdb, 0x15, 0xa0, 0x28, 0x28, 0x73, 0x95, 0x46, 0x28, 0x5e, 0x7f, 0x19, 0x78, - 0x17, 0x43, 0xaa, 0x10, + 0xa6, 0x1a, 0x67, 0x10, 0x00, 0x60, 0x14, 0x96, 0x42, 0xca, 0x66, 0x90, 0xd2, 0x4e, + 0x9f, 0xc3, 0x13, 0xa1, 0x82, 0x59, 0xdb, 0x73, 0x0a, 0x50, 0xd7, 0xe7, 0x58, 0xc5, + 0xd5, 0x44, 0xd0, 0x1d, ], ovk: [ - 0x48, 0x25, 0xc8, 0x9b, 0xc8, 0xef, 0x4d, 0x75, 0x50, 0xa8, 0xdc, 0x1b, 0xda, 0x47, - 0xc4, 0xe4, 0x1a, 0x30, 0xca, 0x56, 0x72, 0x26, 0xd0, 0xb3, 0x78, 0xb0, 0xb9, 0xcc, - 0xb2, 0xfb, 0x36, 0xe5, + 0x72, 0x7a, 0x52, 0x1e, 0xf1, 0xf9, 0x1c, 0x43, 0xf2, 0x17, 0xc4, 0x54, 0xc6, 0x41, + 0xb8, 0x3e, 0xc4, 0xb1, 0x66, 0x1a, 0x3c, 0xac, 0x0e, 0x3f, 0x74, 0xa7, 0x48, 0x0f, + 0xda, 0xaf, 0xad, 0x9f, ], dk: [ - 0x17, 0x84, 0x93, 0x0e, 0xf3, 0xd2, 0x6a, 0xce, 0x1e, 0xad, 0xb7, 0x0b, 0x38, 0x81, - 0x0b, 0x98, 0xf1, 0x82, 0x33, 0x8d, 0x54, 0xff, 0xe8, 0x37, 0x78, 0xf2, 0x7b, 0xe2, - 0xd1, 0x20, 0x67, 0xc0, + 0x20, 0x9d, 0xbb, 0x87, 0x11, 0xd9, 0xee, 0xef, 0x7f, 0x22, 0x0f, 0xd4, 0x28, 0x09, + 0xfb, 0xbb, 0x4c, 0x4b, 0x92, 0x65, 0xd1, 0x62, 0xdf, 0xf2, 0x36, 0x78, 0xca, 0xe7, + 0x70, 0x2b, 0xc5, 0x5e, ], default_d: [ - 0x46, 0x3b, 0x71, 0x6d, 0x24, 0xdd, 0x01, 0x02, 0x03, 0xa7, 0x29, + 0xc5, 0x57, 0x04, 0x43, 0xf9, 0xc5, 0x17, 0xc5, 0x2b, 0x07, 0x68, ], default_pk_d: [ - 0x9e, 0x22, 0xd0, 0x82, 0xbf, 0xbe, 0x2f, 0x05, 0x20, 0x69, 0x13, 0xa8, 0x63, 0x15, - 0xf0, 0x80, 0xbb, 0x87, 0xe7, 0x87, 0xff, 0x51, 0x84, 0x53, 0xb0, 0x85, 0x0b, 0xc3, - 0x57, 0xd9, 0x18, 0x06, + 0xbd, 0x78, 0x5b, 0x8f, 0xa7, 0x56, 0x86, 0xd6, 0x9c, 0xd5, 0xaa, 0x5c, 0xb1, 0xff, + 0x1f, 0x58, 0xa1, 0x2d, 0x37, 0x75, 0x74, 0x28, 0x3a, 0xad, 0x1f, 0x06, 0xa9, 0xd9, + 0x63, 0x5e, 0x1d, 0x11, ], internal_rivk: [ - 0xdf, 0x5f, 0x4f, 0x62, 0x55, 0x28, 0xd5, 0x6b, 0x2e, 0x64, 0xaf, 0x93, 0xb4, 0x79, - 0xbf, 0x1c, 0x3b, 0x37, 0xab, 0x8a, 0xcb, 0x9b, 0x9d, 0x4a, 0x75, 0x75, 0xcc, 0x75, - 0x2a, 0x9c, 0x08, 0x1b, + 0xd7, 0xcf, 0x88, 0xd8, 0xe7, 0xca, 0x57, 0x0e, 0x4a, 0xa2, 0x29, 0xbf, 0x82, 0x68, + 0x0d, 0x4d, 0xec, 0xb7, 0xcd, 0x05, 0xb6, 0x8e, 0x5c, 0x9c, 0x2b, 0xf1, 0x26, 0xba, + 0x6f, 0x41, 0x34, 0x3d, ], internal_ivk: [ - 0xe3, 0x3c, 0xea, 0x19, 0xf7, 0x6a, 0x3b, 0xdc, 0x49, 0xc3, 0x2e, 0x32, 0x2f, 0xeb, - 0x87, 0x0e, 0xd2, 0xae, 0x18, 0x57, 0xca, 0x47, 0x03, 0x4a, 0x01, 0x60, 0x40, 0x0e, - 0x9c, 0xeb, 0x4c, 0x2b, + 0xc4, 0xd0, 0x70, 0xe8, 0x0e, 0x34, 0xb5, 0x03, 0x9f, 0x0d, 0xe6, 0x96, 0xb2, 0x11, + 0x35, 0x5f, 0x72, 0xc8, 0xf2, 0x52, 0xef, 0x81, 0xd0, 0xb7, 0x4c, 0xa1, 0xd1, 0x7b, + 0xed, 0x46, 0x4e, 0x1e, ], internal_ovk: [ - 0xc9, 0x3d, 0x92, 0x4f, 0x45, 0x96, 0x08, 0xef, 0x68, 0xa6, 0x36, 0xe2, 0xe2, 0xfe, - 0xd5, 0xeb, 0x9b, 0xe3, 0x8c, 0xeb, 0xae, 0x57, 0x1d, 0x0e, 0xeb, 0xf3, 0xe8, 0xa5, - 0x37, 0x4f, 0x99, 0x71, + 0xeb, 0xc7, 0x26, 0x70, 0x3c, 0xc4, 0x93, 0xd8, 0x81, 0x68, 0xa6, 0x7c, 0xfb, 0xb1, + 0x95, 0xdd, 0xb7, 0x91, 0xff, 0x83, 0x19, 0x63, 0xd1, 0xcf, 0xe4, 0x24, 0xe5, 0x83, + 0x3a, 0x01, 0x1a, 0xa6, ], internal_dk: [ - 0xec, 0xe1, 0xd3, 0x58, 0x8f, 0xc5, 0x0a, 0xa1, 0xf1, 0x06, 0x5d, 0x93, 0xf5, 0xd8, - 0xcf, 0xca, 0xf1, 0x35, 0x3a, 0xe1, 0xab, 0x39, 0x58, 0x9a, 0xb9, 0x28, 0xdf, 0xda, - 0xfe, 0x36, 0x84, 0x43, + 0x2a, 0xca, 0x74, 0x2a, 0x79, 0x77, 0xac, 0x71, 0xbd, 0x75, 0x5f, 0xd6, 0xb9, 0xe0, + 0x20, 0x70, 0x16, 0x74, 0x68, 0x88, 0x51, 0x4c, 0x52, 0x84, 0x0e, 0x58, 0xdb, 0xfc, + 0x6a, 0x3a, 0xd4, 0xc8, ], asset: [ 0x67, 0x43, 0xf9, 0x3a, 0x6e, 0xbd, 0xa7, 0x2a, 0x8c, 0x7c, 0x5a, 0x2b, 0x7f, 0xa3, @@ -547,99 +547,99 @@ pub(crate) fn test_vectors() -> Vec { 0x3e, 0x0f, 0x46, 0x0f, ], note_cmx: [ - 0xd6, 0x3a, 0x49, 0x61, 0x70, 0x68, 0x72, 0xdd, 0xf4, 0x0b, 0x6d, 0xd2, 0xa9, 0xc9, - 0xc1, 0xdb, 0xec, 0xb9, 0x7e, 0x72, 0xf0, 0x3f, 0x2f, 0x5a, 0xdd, 0x8b, 0x63, 0x53, - 0xe3, 0x9e, 0x59, 0x10, + 0x77, 0xb9, 0x90, 0x78, 0x30, 0x7c, 0x8b, 0x33, 0x0b, 0x74, 0xe1, 0x0e, 0x0a, 0xc9, + 0x02, 0x75, 0xfc, 0x9e, 0x46, 0x8c, 0xba, 0x67, 0x1c, 0x7c, 0xa2, 0xc5, 0xea, 0x12, + 0xfd, 0x8a, 0x45, 0x10, ], note_nf: [ - 0x7e, 0xbe, 0xaa, 0x1a, 0x59, 0xed, 0x46, 0x01, 0x45, 0x8b, 0xa4, 0x6d, 0xcc, 0x96, - 0x2e, 0xd8, 0x1c, 0x15, 0xc7, 0x7f, 0x7e, 0x44, 0x52, 0x48, 0xe4, 0xfb, 0x52, 0x1e, - 0x59, 0xaa, 0x23, 0x1c, + 0x5b, 0xf6, 0xcf, 0x6f, 0xa6, 0xcf, 0x95, 0x17, 0x30, 0xe0, 0x23, 0x28, 0x8d, 0xaa, + 0xd0, 0xc6, 0x7c, 0x19, 0xab, 0xd7, 0xf7, 0xc9, 0x89, 0xfc, 0x8c, 0x56, 0xda, 0x15, + 0xa6, 0x08, 0x71, 0x08, ], }, TestVector { sk: [ - 0xe2, 0xf5, 0x7e, 0x34, 0xfb, 0xc7, 0x54, 0x23, 0xc3, 0x73, 0x7f, 0x5b, 0x2a, 0x06, - 0x15, 0xf5, 0x72, 0x2d, 0xb0, 0x41, 0xa3, 0xef, 0x66, 0xfa, 0x48, 0x3a, 0xfd, 0x3c, - 0x2e, 0x19, 0xe5, 0x94, + 0x44, 0xa6, 0x4a, 0xdd, 0x6d, 0xf1, 0xd9, 0x63, 0xf5, 0xdd, 0x5b, 0x50, 0x10, 0xd3, + 0xd0, 0x25, 0xf0, 0x28, 0x7c, 0x4c, 0xf1, 0x9c, 0x75, 0xf3, 0x3d, 0x51, 0xdd, 0xdd, + 0xba, 0x5d, 0x65, 0x7b, ], ask: [ - 0x12, 0x4b, 0x26, 0x4c, 0x66, 0x07, 0xd3, 0x43, 0x5b, 0x4b, 0xbb, 0x10, 0x39, 0x31, - 0x4b, 0x39, 0x60, 0x4f, 0x06, 0x54, 0x10, 0x0e, 0xa9, 0x0a, 0x3f, 0x9b, 0xfa, 0xe5, - 0x4a, 0x45, 0xa8, 0x36, + 0xca, 0xac, 0x7a, 0xe5, 0x49, 0x2d, 0x63, 0xe8, 0x88, 0xaa, 0xf3, 0x80, 0x5f, 0xcb, + 0x79, 0xae, 0x4a, 0xbc, 0x4a, 0xe1, 0x58, 0x4d, 0xf3, 0x85, 0x8b, 0xd4, 0xe3, 0x2a, + 0xd1, 0xc6, 0xbd, 0x14, ], ak: [ - 0xbe, 0xbc, 0xa2, 0xb4, 0x46, 0x40, 0x91, 0x6a, 0xbf, 0x7e, 0xab, 0xb3, 0x44, 0x48, - 0xef, 0x19, 0xec, 0x7c, 0x02, 0x32, 0x8b, 0x12, 0x5e, 0xb5, 0xa1, 0x04, 0xcc, 0xf3, - 0x08, 0xfb, 0xd0, 0x3c, + 0xbc, 0x3c, 0x59, 0x11, 0x13, 0xdf, 0xd0, 0x29, 0x66, 0x3f, 0x03, 0x1c, 0xc1, 0x3f, + 0x7f, 0x94, 0xf4, 0x3c, 0x89, 0x8a, 0x79, 0x62, 0x90, 0x86, 0x11, 0x08, 0x99, 0xb2, + 0xb8, 0xe3, 0x3f, 0x13, ], isk: [ - 0x44, 0xa6, 0x4a, 0xdd, 0x6d, 0xf1, 0xd9, 0x63, 0xf5, 0xdd, 0x5b, 0x50, 0x10, 0xd3, - 0xd0, 0x25, 0xf0, 0x28, 0x7c, 0x4c, 0xf1, 0x9c, 0x75, 0xf3, 0x3d, 0x51, 0xdd, 0xdd, - 0xba, 0x5d, 0x65, 0x7b, + 0xc4, 0x8f, 0xbd, 0x46, 0x7f, 0x75, 0xb7, 0x80, 0x14, 0x9a, 0xe8, 0x80, 0x8f, 0x4e, + 0x68, 0xf5, 0x0c, 0x05, 0x36, 0xac, 0xdd, 0xf6, 0xf1, 0xae, 0xab, 0x01, 0x6b, 0x6b, + 0xc1, 0xec, 0x14, 0x4b, ], ik: [ - 0x0b, 0x93, 0xf6, 0x34, 0x6e, 0x57, 0x23, 0x27, 0x1b, 0x60, 0x7b, 0xc8, 0x08, 0x68, - 0x08, 0xf1, 0xbb, 0x03, 0x5d, 0x0d, 0xe5, 0x52, 0x4d, 0x06, 0x48, 0x08, 0x31, 0xe7, - 0x16, 0x31, 0x52, 0xd7, + 0xe2, 0xb7, 0xd3, 0x28, 0x92, 0x52, 0xf8, 0x69, 0x17, 0xd4, 0xcb, 0x43, 0x04, 0xbe, + 0x9a, 0x06, 0xd6, 0x25, 0xdb, 0x6f, 0xb2, 0xcb, 0xea, 0xf8, 0x84, 0xc2, 0x80, 0x66, + 0x94, 0x16, 0xad, 0x30, ], nk: [ - 0x49, 0xaf, 0xb9, 0xd3, 0x17, 0x63, 0x82, 0x90, 0x2b, 0x98, 0x5d, 0x7b, 0x04, 0xb3, - 0x77, 0x7b, 0x3e, 0x93, 0xf9, 0x25, 0xc0, 0xcf, 0x09, 0x40, 0x22, 0x91, 0xd6, 0x90, - 0x9d, 0x8b, 0x64, 0x0b, + 0x54, 0x81, 0x3a, 0x55, 0x4c, 0xd0, 0x88, 0xfd, 0xad, 0x77, 0x91, 0x00, 0xa5, 0xa4, + 0xe4, 0xb0, 0xec, 0x83, 0xd6, 0xc2, 0x8c, 0xa4, 0x8e, 0x0e, 0x6c, 0xd4, 0xc0, 0xae, + 0x3a, 0xec, 0x67, 0x1f, ], rivk: [ - 0x29, 0x1c, 0xe2, 0x3e, 0x99, 0x33, 0x8b, 0x88, 0x3c, 0x3e, 0xcc, 0x93, 0xed, 0x61, - 0x59, 0x74, 0x83, 0xea, 0x1f, 0xbc, 0x78, 0x3f, 0xa4, 0x5b, 0xa7, 0xba, 0xf8, 0xfb, - 0x14, 0x78, 0xfe, 0x1a, + 0x7c, 0xa6, 0x44, 0x60, 0x34, 0x5e, 0xe1, 0x58, 0x8a, 0x1d, 0x68, 0xa5, 0x19, 0xcc, + 0x43, 0xf2, 0x04, 0xf9, 0xcc, 0x09, 0xf1, 0x5c, 0x67, 0x2b, 0x84, 0x26, 0x7b, 0xfd, + 0xd6, 0xfe, 0xba, 0x0f, ], ivk: [ - 0x61, 0x58, 0x87, 0xc8, 0x04, 0xac, 0x73, 0x06, 0x24, 0x51, 0x93, 0x54, 0x3f, 0x8a, - 0x8b, 0x20, 0xde, 0x76, 0x67, 0xba, 0xdd, 0xd3, 0x52, 0x64, 0x78, 0x07, 0x63, 0x37, - 0x49, 0x20, 0xd1, 0x1f, + 0x1a, 0xc4, 0x6c, 0x8c, 0x2d, 0x85, 0xcd, 0xd1, 0x93, 0xd2, 0x19, 0xe2, 0x5b, 0x11, + 0xd8, 0xf8, 0xc7, 0x8a, 0x70, 0x29, 0x61, 0x40, 0x22, 0xfb, 0x6c, 0x48, 0x5f, 0x7a, + 0x79, 0x0b, 0xba, 0x3a, ], ovk: [ - 0x69, 0x96, 0x86, 0xa4, 0x13, 0xbc, 0x95, 0x43, 0xe8, 0xb3, 0x90, 0xc1, 0x51, 0x4a, - 0x41, 0xff, 0xa2, 0x80, 0xf1, 0xea, 0x8a, 0x52, 0xc6, 0x1a, 0x56, 0xea, 0x94, 0x98, - 0x6d, 0xd8, 0x66, 0x2c, + 0xc8, 0x07, 0x3c, 0x0e, 0x75, 0xfb, 0x45, 0xc5, 0x4b, 0x17, 0x04, 0xa4, 0xe9, 0x4c, + 0x26, 0x78, 0xe2, 0xfb, 0x36, 0xea, 0xea, 0x1e, 0xd8, 0x48, 0xb2, 0x47, 0xaa, 0x25, + 0x2f, 0xa5, 0x05, 0x86, ], dk: [ - 0x2b, 0xc7, 0xd4, 0x9f, 0xed, 0x53, 0xc1, 0x59, 0x21, 0x9d, 0x29, 0xb3, 0xe5, 0x51, - 0x08, 0xd6, 0x5d, 0x2a, 0x82, 0x3f, 0xce, 0x17, 0x51, 0x08, 0xdb, 0xc9, 0xc5, 0xb5, - 0x00, 0x4a, 0x7f, 0xd4, + 0x78, 0x2a, 0xb8, 0xbe, 0x6d, 0x3b, 0x74, 0x03, 0x62, 0x12, 0xe5, 0xea, 0xc8, 0x95, + 0x7f, 0xc4, 0x85, 0x6a, 0x4d, 0xd0, 0x4b, 0x60, 0x71, 0xa0, 0x55, 0x13, 0xa8, 0x6b, + 0x35, 0x05, 0xfb, 0x8f, ], default_d: [ - 0x80, 0x1a, 0x91, 0xc1, 0x78, 0x47, 0x23, 0x30, 0x82, 0x67, 0x9a, + 0xba, 0x03, 0xdb, 0x92, 0xca, 0xb9, 0x1d, 0x77, 0xfb, 0xff, 0x92, ], default_pk_d: [ - 0x8e, 0xa1, 0xac, 0x5f, 0x65, 0xc1, 0x79, 0x9b, 0x6c, 0x7a, 0x68, 0x4f, 0xf3, 0x5e, - 0x63, 0xbd, 0xdf, 0x75, 0xff, 0xf6, 0x9f, 0xc2, 0xd2, 0x83, 0x59, 0xf2, 0xd4, 0x96, - 0xff, 0x9e, 0xb7, 0x20, + 0x5e, 0x25, 0x56, 0xeb, 0x74, 0x70, 0x78, 0x26, 0x3b, 0x4d, 0xb4, 0xba, 0xc7, 0xf8, + 0x56, 0xe0, 0x66, 0x1b, 0x04, 0xed, 0xc6, 0x14, 0xb4, 0xeb, 0xd4, 0x96, 0x45, 0xf7, + 0x63, 0xd3, 0x23, 0x86, ], internal_rivk: [ - 0x29, 0x8e, 0xf3, 0x46, 0x9e, 0x43, 0x01, 0x93, 0x44, 0xfa, 0x27, 0x4b, 0x67, 0xcc, - 0xd3, 0xef, 0xda, 0x04, 0x02, 0x18, 0x07, 0x17, 0xea, 0x6c, 0x7e, 0x6f, 0x11, 0xdf, - 0x1c, 0x8e, 0xbe, 0x20, + 0xb9, 0xcc, 0x87, 0xef, 0x06, 0x4f, 0x87, 0xff, 0xe5, 0xd3, 0xc2, 0x3b, 0x69, 0x44, + 0x9e, 0x44, 0x6b, 0x21, 0x33, 0x3e, 0xe0, 0x39, 0x04, 0xad, 0xca, 0xb1, 0x6f, 0x05, + 0x15, 0xee, 0x78, 0x07, ], internal_ivk: [ - 0xa2, 0xea, 0xb2, 0x74, 0xa9, 0x69, 0xc4, 0x46, 0x8f, 0x66, 0x83, 0x9c, 0x72, 0xaa, - 0x6e, 0x65, 0xe6, 0x59, 0xb1, 0x2c, 0xd2, 0x17, 0xba, 0x91, 0x04, 0x21, 0xb8, 0x89, - 0x9f, 0xab, 0x59, 0x32, + 0x44, 0x35, 0x8f, 0x75, 0xda, 0x3a, 0x1d, 0xd9, 0xa2, 0xa2, 0xb0, 0x7c, 0x0b, 0x4e, + 0x2f, 0xc2, 0x01, 0x89, 0xd9, 0xfc, 0x3d, 0x0d, 0x8a, 0xae, 0xf8, 0x93, 0xfe, 0xed, + 0xae, 0x57, 0x26, 0x29, ], internal_ovk: [ - 0x81, 0xc1, 0xe2, 0xde, 0x44, 0xcb, 0xd6, 0xd5, 0xdd, 0x87, 0x6c, 0x87, 0xb5, 0xf8, - 0x28, 0x0b, 0xec, 0xa7, 0xfa, 0x77, 0x97, 0x76, 0x54, 0x73, 0xf5, 0x92, 0xd5, 0xfa, - 0xe3, 0xf7, 0xda, 0x9f, + 0xb5, 0xea, 0x50, 0xd3, 0xe5, 0xcd, 0x42, 0x99, 0x63, 0x30, 0xfb, 0xa6, 0xb8, 0x52, + 0x3e, 0xf8, 0x12, 0x26, 0x5b, 0x4b, 0xa4, 0x32, 0x58, 0x1c, 0x21, 0x03, 0xe3, 0x52, + 0xd1, 0x6d, 0xbb, 0x90, ], internal_dk: [ - 0x2b, 0x04, 0xdc, 0x9d, 0xed, 0xc2, 0xd0, 0x5e, 0x16, 0x37, 0x1b, 0xcb, 0x8a, 0x17, - 0x85, 0x44, 0x98, 0x53, 0xf0, 0xed, 0xaf, 0xeb, 0x09, 0xfd, 0xd4, 0x48, 0x3f, 0x42, - 0xec, 0x7a, 0xc1, 0xb6, + 0xdd, 0x13, 0xbb, 0x22, 0x13, 0x80, 0x96, 0xc7, 0xaf, 0x9a, 0x16, 0x98, 0x88, 0x4d, + 0x3d, 0xe8, 0x96, 0x06, 0x48, 0xf8, 0x74, 0xf9, 0x42, 0x22, 0xbd, 0x76, 0xb7, 0x67, + 0x82, 0x5e, 0x5d, 0xb6, ], asset: [ - 0xcc, 0x73, 0x29, 0xf3, 0xe9, 0xb4, 0xe5, 0x4c, 0x23, 0x6c, 0x29, 0xaf, 0x39, 0x23, - 0x10, 0x17, 0x56, 0xd9, 0xfa, 0x4b, 0xd0, 0xf7, 0xd2, 0xdd, 0xaa, 0xcb, 0x6b, 0x0f, - 0x86, 0xa2, 0x65, 0x8e, + 0x0c, 0x3a, 0x90, 0xb4, 0x9a, 0xd4, 0xbb, 0xc6, 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, + 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, 0x84, 0x1e, 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, + 0x90, 0x5a, 0xae, 0x08, ], note_v: 1456989545392107075, note_rho: [ @@ -653,438 +653,438 @@ pub(crate) fn test_vectors() -> Vec { 0x0d, 0xc0, 0xb7, 0x16, ], note_cmx: [ - 0x26, 0xc0, 0xb4, 0x92, 0xe5, 0x6c, 0xf6, 0xc5, 0xdd, 0x67, 0x9c, 0x84, 0x66, 0x7b, - 0x74, 0x41, 0x83, 0x63, 0xc7, 0xd9, 0x15, 0xed, 0x6b, 0x72, 0x50, 0xde, 0xa9, 0xd9, - 0xe7, 0xeb, 0x51, 0x39, + 0x38, 0x14, 0x8e, 0x9e, 0x3b, 0x05, 0x3a, 0x6d, 0x8f, 0xa7, 0x86, 0x07, 0xed, 0x57, + 0x64, 0x75, 0x83, 0xa7, 0xf9, 0x37, 0x55, 0x38, 0x84, 0x7b, 0x8c, 0x4a, 0xa0, 0xb4, + 0xeb, 0x43, 0xa7, 0x32, ], note_nf: [ - 0x7e, 0xec, 0xa6, 0x5c, 0xbd, 0xc5, 0x01, 0x18, 0x2f, 0x6e, 0x1b, 0x11, 0xa2, 0x3b, - 0x0f, 0xaa, 0x80, 0xfc, 0x26, 0xca, 0x16, 0xbc, 0x4c, 0xd0, 0x97, 0x33, 0xab, 0x0e, - 0x1d, 0x10, 0x8d, 0x16, + 0x37, 0x57, 0x49, 0xa6, 0xa1, 0xd6, 0x44, 0xa4, 0x83, 0xc7, 0x09, 0xee, 0xc4, 0xaa, + 0x87, 0xb8, 0x58, 0xba, 0x0f, 0x71, 0x1b, 0x76, 0x5b, 0xbf, 0xfa, 0x97, 0xa9, 0x3f, + 0x57, 0x4f, 0x29, 0x23, ], }, TestVector { sk: [ - 0xc4, 0x8f, 0xbd, 0x46, 0x7f, 0x75, 0xb7, 0x80, 0x14, 0x9a, 0xe8, 0x80, 0x8f, 0x4e, - 0x68, 0xf5, 0x0c, 0x05, 0x36, 0xac, 0xdd, 0xf6, 0xf1, 0xae, 0xab, 0x01, 0x6b, 0x6b, - 0xc1, 0xec, 0x14, 0x4b, + 0x03, 0xfd, 0x69, 0x44, 0x2e, 0xb7, 0x68, 0x1e, 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, + 0x92, 0xee, 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, + 0x64, 0x0a, 0x69, 0x30, ], ask: [ - 0xb1, 0xc5, 0x78, 0x06, 0x79, 0xa6, 0x48, 0x9f, 0x79, 0x78, 0xd0, 0x2d, 0x12, 0xb9, - 0xcf, 0x78, 0xe9, 0x18, 0x25, 0x6d, 0xfa, 0xae, 0xbe, 0xe5, 0xd8, 0x9d, 0x71, 0xe5, - 0xc1, 0xdc, 0x0e, 0x3b, + 0xd0, 0xa8, 0x8e, 0x38, 0xe2, 0xd6, 0x67, 0x96, 0xf4, 0x9f, 0x9f, 0x39, 0x48, 0x44, + 0xa3, 0x1e, 0x29, 0x02, 0xa4, 0x14, 0x0a, 0xbf, 0x96, 0x9d, 0x5a, 0x6a, 0x39, 0xd0, + 0xbe, 0x92, 0x16, 0x21, ], ak: [ - 0x95, 0x99, 0x81, 0xe9, 0x29, 0xa7, 0x15, 0xa3, 0x4e, 0x5b, 0x05, 0xc0, 0xc1, 0x23, - 0x1e, 0x52, 0x25, 0x96, 0xb9, 0x44, 0xd5, 0x24, 0xf6, 0x2c, 0x2a, 0x4b, 0xd6, 0x95, - 0x3e, 0x5a, 0x84, 0x13, + 0xb6, 0xd5, 0x12, 0x34, 0xfe, 0xf8, 0x7c, 0xaf, 0x48, 0x38, 0x54, 0x07, 0xeb, 0x1d, + 0x32, 0x71, 0xf9, 0xad, 0xc7, 0x1d, 0xe7, 0xc0, 0x81, 0xca, 0x6a, 0xae, 0xc0, 0xf9, + 0x18, 0x4f, 0x0c, 0x2a, ], isk: [ - 0x4e, 0x55, 0x3a, 0xcf, 0xd6, 0x70, 0xf7, 0x7e, 0x75, 0x5f, 0xc8, 0x8e, 0x06, 0x77, - 0xe3, 0x1b, 0xa4, 0x59, 0xb4, 0x4e, 0x30, 0x77, 0x68, 0x95, 0x8f, 0xe3, 0x78, 0x9d, - 0x41, 0xc2, 0xb1, 0xff, + 0xc9, 0x9b, 0x71, 0x41, 0xac, 0x62, 0x6a, 0xb4, 0x76, 0x1f, 0xd3, 0xf4, 0x1e, 0x72, + 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, 0xec, 0xa3, 0x64, 0xdd, 0x2f, 0x0f, + 0x07, 0x39, 0xf0, 0x53, ], ik: [ - 0xbf, 0xfe, 0xa0, 0x0a, 0xf9, 0x2b, 0x81, 0xbc, 0x57, 0x2b, 0xea, 0x4a, 0x26, 0x73, - 0x5a, 0x34, 0x9f, 0x4d, 0x76, 0xd1, 0x69, 0x68, 0xe5, 0x6c, 0x56, 0x5f, 0xd9, 0x2b, - 0xeb, 0x46, 0x08, 0x48, + 0x03, 0xd8, 0x30, 0x92, 0xd7, 0x09, 0xcb, 0x92, 0x8f, 0xf1, 0x50, 0xf0, 0x8e, 0xa2, + 0x68, 0xe8, 0x45, 0x41, 0x80, 0xcd, 0xc4, 0x9f, 0x07, 0xf5, 0xa3, 0xd9, 0xb2, 0x03, + 0x90, 0x68, 0xc9, 0x09, ], nk: [ - 0x7c, 0xf5, 0xe1, 0x97, 0xb7, 0x7a, 0x3c, 0xe4, 0xb6, 0x69, 0x61, 0x5b, 0x78, 0xd3, - 0x19, 0x65, 0x9a, 0x90, 0x46, 0x3e, 0x45, 0x93, 0x32, 0x47, 0x44, 0xb9, 0xb4, 0x19, - 0x35, 0xa9, 0xfd, 0x3a, + 0x0d, 0x47, 0x60, 0xf0, 0xe9, 0x3d, 0x2c, 0x4b, 0x67, 0x6e, 0x88, 0xfa, 0x40, 0xfa, + 0x8d, 0xb7, 0x1b, 0xb6, 0x5d, 0x49, 0xa3, 0xa0, 0xc4, 0x6f, 0xa7, 0xa2, 0xef, 0x14, + 0x68, 0x42, 0x2b, 0x01, ], rivk: [ - 0x61, 0xf7, 0x39, 0x8a, 0x70, 0x07, 0x07, 0x95, 0x94, 0xad, 0xa8, 0xc8, 0x37, 0x0d, - 0xd8, 0xa9, 0xe4, 0x90, 0x66, 0xee, 0xf2, 0xd6, 0x05, 0x9b, 0x02, 0xa1, 0x67, 0x68, - 0x26, 0xaa, 0x4a, 0x2d, + 0xd4, 0x2b, 0x9a, 0x02, 0x8a, 0xbb, 0xe3, 0x86, 0x43, 0x77, 0x48, 0xdb, 0x20, 0x9f, + 0xdb, 0xa8, 0x40, 0xf3, 0xf6, 0x82, 0xa5, 0x0c, 0x1e, 0xf0, 0xaf, 0xa4, 0xa9, 0xfe, + 0x7b, 0xa3, 0x3f, 0x2b, ], ivk: [ - 0xcc, 0xb2, 0x24, 0x66, 0xf1, 0xa3, 0xda, 0x33, 0xc2, 0xfd, 0xab, 0x63, 0x19, 0xde, - 0x82, 0x71, 0xff, 0xd9, 0xc7, 0xc7, 0xba, 0xfa, 0x24, 0x06, 0x8e, 0x72, 0x32, 0x1c, - 0x87, 0x67, 0x76, 0x2b, + 0xec, 0x8d, 0x1b, 0x93, 0x18, 0x3d, 0x20, 0x33, 0xc2, 0x7b, 0x18, 0xe8, 0xc8, 0xbc, + 0xe1, 0xa0, 0xc2, 0xcd, 0x49, 0x7a, 0x35, 0x84, 0xf1, 0x6e, 0x3b, 0x90, 0x79, 0xc9, + 0xa9, 0x33, 0x50, 0x27, ], ovk: [ - 0x12, 0xac, 0xb4, 0xf9, 0xf0, 0xb2, 0xcc, 0x5d, 0xfa, 0x03, 0x15, 0x46, 0x73, 0xd7, - 0xf3, 0x0c, 0x7f, 0x1c, 0xb1, 0x84, 0xa7, 0xce, 0x4e, 0xd8, 0x4b, 0x9d, 0x0b, 0x3d, - 0x8e, 0x68, 0x63, 0xd3, + 0x2f, 0x84, 0x6f, 0xbb, 0x28, 0xfb, 0x64, 0x2c, 0x43, 0x0a, 0x2b, 0xef, 0x8c, 0xb1, + 0xde, 0x58, 0x95, 0x2d, 0xa6, 0x22, 0xe5, 0x89, 0x38, 0xab, 0xaf, 0x10, 0xa6, 0x92, + 0x9a, 0x7f, 0xa1, 0xee, ], dk: [ - 0x51, 0xba, 0x5e, 0x4e, 0x4b, 0x8f, 0xbe, 0xf0, 0xd0, 0x1e, 0xf3, 0x8c, 0x77, 0xb4, - 0xba, 0x7f, 0xfa, 0x26, 0x72, 0xfa, 0x7a, 0xde, 0x50, 0x4f, 0xdb, 0x85, 0x91, 0x05, - 0x46, 0x7d, 0x0a, 0x91, + 0x7b, 0xf1, 0x6e, 0xcf, 0x21, 0x0e, 0xb5, 0x19, 0x02, 0xb4, 0x99, 0xd6, 0xbc, 0x5c, + 0xab, 0xb0, 0x77, 0x17, 0x64, 0x1a, 0xd4, 0xb0, 0x1a, 0xa5, 0x08, 0xac, 0x93, 0x11, + 0x0b, 0x36, 0x0c, 0x2c, ], default_d: [ - 0x7f, 0xd2, 0x1b, 0xf0, 0xf5, 0xf3, 0x2f, 0x7d, 0xf2, 0xec, 0x7f, + 0x49, 0xa0, 0xd1, 0xfa, 0x5b, 0x94, 0x5d, 0xd7, 0xb6, 0xc6, 0x64, ], default_pk_d: [ - 0x54, 0x92, 0x6e, 0xd8, 0xd4, 0xbc, 0x4c, 0xcd, 0xed, 0xc9, 0x91, 0xaa, 0x62, 0x19, - 0xc3, 0xf6, 0xb4, 0x58, 0xd6, 0x78, 0xc6, 0xd6, 0xc3, 0xc9, 0x0d, 0x57, 0xfc, 0x08, - 0x71, 0xc3, 0x50, 0xbe, + 0x56, 0xfd, 0x76, 0xdd, 0x5b, 0xb7, 0x44, 0xa9, 0x49, 0x4c, 0x08, 0xed, 0x92, 0xda, + 0x2c, 0xf3, 0xd7, 0x48, 0x44, 0x34, 0xc9, 0x54, 0x59, 0x23, 0xf3, 0x82, 0x1a, 0xcc, + 0x01, 0x32, 0x17, 0x1a, ], internal_rivk: [ - 0xd6, 0x2f, 0x96, 0x87, 0x62, 0x35, 0x26, 0x2b, 0x7e, 0x75, 0x5a, 0x3f, 0x1d, 0x4e, - 0x79, 0x99, 0x7e, 0xec, 0x6d, 0x46, 0x60, 0x39, 0x8f, 0xe0, 0x7e, 0x29, 0x0a, 0x31, - 0xac, 0xf0, 0xdb, 0x2c, + 0xcb, 0x53, 0x0d, 0x7b, 0x34, 0xfb, 0x08, 0x9c, 0x92, 0x72, 0x1c, 0x3e, 0xa0, 0xd2, + 0x14, 0x4d, 0x87, 0xb8, 0x9c, 0xa0, 0xc0, 0x6a, 0x9d, 0x44, 0x6d, 0x88, 0x1f, 0x4a, + 0x99, 0xa1, 0xf9, 0x33, ], internal_ivk: [ - 0x6e, 0x03, 0xa4, 0xfd, 0xba, 0x1e, 0xc7, 0xcd, 0xcf, 0x05, 0x09, 0x97, 0x60, 0xbb, - 0xb9, 0xa7, 0x0f, 0x42, 0x4d, 0xcb, 0x20, 0x88, 0x01, 0xd1, 0xe2, 0x7f, 0x12, 0xbd, - 0x4f, 0x14, 0x91, 0x1f, + 0xda, 0x1d, 0x87, 0xca, 0x7d, 0xf0, 0xf3, 0x9b, 0x24, 0xfc, 0x8f, 0x50, 0xa3, 0x05, + 0xd8, 0x3a, 0x03, 0xce, 0xba, 0x2a, 0x59, 0xd2, 0x7a, 0x7d, 0xd4, 0x01, 0x34, 0x05, + 0x18, 0x40, 0x18, 0x25, ], internal_ovk: [ - 0xba, 0xe4, 0x5d, 0xdd, 0xa9, 0xfe, 0x68, 0x60, 0xe7, 0xc8, 0x70, 0x09, 0x38, 0xb1, - 0x32, 0x4e, 0x6f, 0xe0, 0xe9, 0x88, 0x6e, 0xd8, 0xb0, 0xe2, 0xf9, 0xeb, 0x46, 0xe0, - 0x53, 0x1d, 0x2a, 0x5f, + 0x87, 0x66, 0x9c, 0x4e, 0x89, 0xf6, 0x8e, 0x3c, 0xe9, 0x60, 0x6e, 0xe7, 0x26, 0x52, + 0xb3, 0x89, 0x3d, 0xff, 0x01, 0x3f, 0x71, 0x89, 0x8f, 0x77, 0x82, 0x40, 0x4f, 0xba, + 0x8c, 0xef, 0x40, 0x3a, ], internal_dk: [ - 0xc1, 0xcf, 0x55, 0xea, 0xc9, 0xa8, 0x94, 0x18, 0x77, 0x6b, 0x9e, 0xfc, 0x67, 0xef, - 0xe9, 0x0b, 0xf3, 0x61, 0xee, 0xb0, 0x96, 0xed, 0x61, 0x86, 0xc4, 0x1a, 0x60, 0xc4, - 0x29, 0xa5, 0xb5, 0xa9, + 0x24, 0x5c, 0xf8, 0xf2, 0xe0, 0x54, 0xb1, 0xc0, 0x3b, 0x5f, 0x19, 0xf6, 0xd2, 0x9d, + 0x15, 0x69, 0x6f, 0x0f, 0x1d, 0x39, 0x21, 0xf6, 0xcf, 0x1d, 0x6f, 0x5f, 0x8f, 0xd5, + 0xd6, 0x61, 0x46, 0x50, ], asset: [ - 0xbc, 0x6b, 0xc2, 0x30, 0x7b, 0x48, 0x8d, 0x25, 0x56, 0xd7, 0xb7, 0x38, 0x0e, 0xa4, - 0xff, 0xd7, 0x12, 0xf6, 0xb0, 0x2f, 0xe8, 0x06, 0xb9, 0x45, 0x69, 0xcd, 0x40, 0x59, - 0xf3, 0x96, 0xbf, 0x29, + 0xb3, 0x25, 0xcd, 0xab, 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, 0xcd, 0xdb, + 0x41, 0x87, 0x2c, 0xfc, 0xc2, 0x14, 0xb1, 0x32, 0x32, 0xed, 0xc7, 0x86, 0x09, 0x75, + 0x3d, 0xbf, 0xf9, 0x30, ], - note_v: 94453636825041987, + note_v: 10781511188385845786, note_rho: [ - 0xb9, 0x9d, 0x0a, 0x40, 0xe5, 0xe1, 0x71, 0x1c, 0xa9, 0x44, 0xf7, 0x2d, 0x43, 0x6a, - 0x10, 0x2f, 0xca, 0x4b, 0x97, 0x69, 0x3d, 0xa0, 0xb0, 0x86, 0xfe, 0x9d, 0x2e, 0x71, - 0x62, 0x47, 0x0d, 0x02, + 0x7a, 0xe3, 0x5a, 0xf7, 0x16, 0x71, 0x18, 0x14, 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, + 0x49, 0x2f, 0xe7, 0x9f, 0x15, 0x81, 0xa1, 0x55, 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, + 0x2e, 0x65, 0x0b, 0x38, ], note_rseed: [ - 0xe0, 0xf0, 0x5d, 0x4b, 0xec, 0x95, 0x12, 0xbf, 0xb3, 0xf3, 0x83, 0x27, 0x29, 0x6e, - 0xfa, 0xa7, 0x43, 0x28, 0xb1, 0x18, 0xc2, 0x74, 0x02, 0xc7, 0x0c, 0x3a, 0x90, 0xb4, - 0x9a, 0xd4, 0xbb, 0xc6, + 0x6a, 0xd3, 0xa0, 0x8c, 0xb6, 0xb8, 0x31, 0x31, 0xac, 0x30, 0x0b, 0x08, 0x46, 0x35, + 0x4a, 0x7e, 0xef, 0x9c, 0x41, 0x0e, 0x4b, 0x62, 0xc4, 0x7c, 0x54, 0x26, 0x90, 0x7d, + 0xfc, 0x66, 0x85, 0xc5, ], note_cmx: [ - 0x98, 0xfc, 0x4e, 0x7f, 0x1d, 0xb8, 0x5a, 0xe6, 0x42, 0x14, 0xd8, 0x30, 0x06, 0xd8, - 0xac, 0xa8, 0xc2, 0x48, 0x73, 0x53, 0x2c, 0x22, 0x1b, 0x06, 0xd1, 0x8d, 0xf2, 0xb7, - 0xeb, 0x5f, 0xe5, 0x00, + 0xbe, 0xe1, 0xae, 0x8e, 0x13, 0xef, 0x9b, 0xda, 0x15, 0x3f, 0xa2, 0xde, 0xf1, 0xf7, + 0x23, 0x97, 0xa1, 0xce, 0xd9, 0x5f, 0x1d, 0x2a, 0x9f, 0x96, 0xfb, 0x09, 0x77, 0x5f, + 0x86, 0x7f, 0x7c, 0x32, ], note_nf: [ - 0x37, 0xd7, 0xe9, 0x3c, 0xec, 0xfc, 0x62, 0x08, 0x8c, 0xde, 0x33, 0x41, 0x47, 0x88, - 0xfe, 0xab, 0x15, 0x8a, 0x40, 0xb4, 0xe9, 0x4a, 0x51, 0x11, 0xa7, 0x07, 0xaf, 0x3a, - 0x44, 0x3b, 0xd1, 0x3a, + 0x46, 0xca, 0xbd, 0x45, 0x05, 0xe6, 0xf4, 0xf8, 0x6d, 0x2a, 0xa4, 0xbe, 0x6b, 0x14, + 0x61, 0x3a, 0xca, 0xa4, 0x13, 0x33, 0x34, 0x44, 0xcf, 0x3e, 0x48, 0x5e, 0x6b, 0xeb, + 0x39, 0xf2, 0xa7, 0x27, ], }, TestVector { sk: [ - 0x8e, 0x37, 0xc0, 0xaa, 0x7d, 0x9b, 0x3f, 0xe1, 0x77, 0x99, 0xd7, 0x3b, 0x84, 0x1e, - 0x75, 0x17, 0x13, 0xa0, 0x29, 0x43, 0x90, 0x5a, 0xae, 0x08, 0x03, 0xfd, 0x69, 0x44, - 0x2e, 0xb7, 0x68, 0x1e, + 0xeb, 0x0d, 0xc1, 0x56, 0x61, 0x2b, 0x9c, 0xb4, 0x34, 0xbc, 0x4b, 0x69, 0x33, 0x92, + 0xde, 0xb8, 0x7c, 0x53, 0x04, 0x35, 0x31, 0x2e, 0xdc, 0xed, 0xc6, 0xa9, 0x61, 0x13, + 0x33, 0x38, 0xd7, 0x86, ], ask: [ - 0xfb, 0x9c, 0xa6, 0xa7, 0xf2, 0x49, 0x20, 0x67, 0xaa, 0x19, 0x42, 0x01, 0xaa, 0xbc, - 0xd5, 0xc0, 0xce, 0xe9, 0x9f, 0x6d, 0x65, 0x0f, 0x0f, 0x10, 0x44, 0x96, 0xac, 0xc5, - 0x88, 0x34, 0x89, 0x2b, + 0x71, 0x37, 0xb4, 0x05, 0xf0, 0x52, 0x86, 0xe8, 0xf2, 0x77, 0x0c, 0xd2, 0x1e, 0x2f, + 0x2c, 0x15, 0x28, 0x76, 0x4d, 0x4a, 0xad, 0x93, 0x85, 0x04, 0x0e, 0xa2, 0xec, 0x74, + 0xaa, 0x6e, 0xa6, 0x31, ], ak: [ - 0xa0, 0xb2, 0x52, 0xde, 0x9e, 0x88, 0xee, 0xc0, 0x36, 0x2e, 0x43, 0x6f, 0x58, 0x52, - 0xf7, 0x4f, 0x7e, 0x3c, 0x74, 0x94, 0xe4, 0xa6, 0x65, 0x2f, 0xbf, 0xa7, 0x44, 0xdb, - 0xa3, 0xa9, 0x23, 0x14, + 0x78, 0xdb, 0xcc, 0x02, 0x0e, 0x1b, 0xbc, 0xe5, 0x4d, 0x0f, 0x54, 0x76, 0xa6, 0x64, + 0x3b, 0xc8, 0x2d, 0xae, 0x3e, 0x61, 0x4a, 0xc5, 0x8d, 0x05, 0x7f, 0xfc, 0x5d, 0x3c, + 0x60, 0xd7, 0x5e, 0x3e, ], isk: [ - 0xc2, 0xa0, 0x56, 0x00, 0x05, 0x4e, 0x92, 0xee, 0xd5, 0x55, 0x02, 0x8f, 0x21, 0xb6, - 0xa1, 0x55, 0x26, 0x8a, 0x2d, 0xd6, 0x64, 0x0a, 0x69, 0x30, 0x1a, 0x52, 0xa3, 0x8d, - 0x4d, 0x9f, 0x9f, 0x95, + 0x60, 0xfe, 0x49, 0xe3, 0x7e, 0x4f, 0x66, 0x69, 0x31, 0x67, 0x73, 0x19, 0xed, 0x89, + 0xf8, 0x55, 0x88, 0x74, 0x1b, 0x31, 0x28, 0x90, 0x1a, 0x93, 0xbd, 0x78, 0xe4, 0xbe, + 0x02, 0x25, 0xa9, 0xe2, ], ik: [ - 0x3e, 0x34, 0xea, 0xa1, 0x93, 0x26, 0x04, 0x49, 0xf3, 0xe8, 0x83, 0xfd, 0x5f, 0xbd, - 0x84, 0xfd, 0x99, 0xbf, 0x10, 0xa1, 0xa4, 0xdf, 0x14, 0x60, 0x98, 0x78, 0x4a, 0xe2, - 0xc3, 0xc2, 0xdb, 0xf7, + 0x78, 0xfe, 0x62, 0x0f, 0xc5, 0x91, 0x3f, 0xc1, 0x8a, 0xa2, 0x09, 0x36, 0x40, 0x9d, + 0x38, 0x8f, 0x0f, 0x10, 0x88, 0x14, 0xa7, 0x5e, 0x93, 0x1b, 0xea, 0xcb, 0x61, 0x83, + 0xa9, 0xbe, 0x18, 0xc4, ], nk: [ - 0xfe, 0x7d, 0xda, 0x8a, 0x42, 0xb1, 0x49, 0x04, 0xad, 0x4f, 0xf1, 0x14, 0xae, 0x3a, - 0x97, 0xd2, 0x01, 0xb6, 0x17, 0xf5, 0xd5, 0xd0, 0x2e, 0xe0, 0xde, 0x77, 0x4b, 0xb4, - 0x6e, 0xd0, 0x56, 0x37, + 0x88, 0xc5, 0xc9, 0x2d, 0x1c, 0xd0, 0xe5, 0x01, 0xc9, 0x1d, 0x80, 0x1c, 0x50, 0xdf, + 0x26, 0xd3, 0xbb, 0xbc, 0x5f, 0x7c, 0xc0, 0x49, 0xcb, 0xb2, 0x9d, 0xc3, 0x80, 0x17, + 0x85, 0x6f, 0xbb, 0x10, ], rivk: [ - 0xf8, 0xbf, 0x8f, 0x4f, 0x71, 0x88, 0x90, 0x67, 0xcb, 0x99, 0xf2, 0xec, 0xc5, 0x41, - 0x50, 0x6c, 0x23, 0x0a, 0xff, 0x88, 0x64, 0x26, 0x68, 0x59, 0xf0, 0x15, 0xdf, 0xf4, - 0xc4, 0x89, 0x5e, 0x32, + 0x7e, 0xc2, 0xbb, 0xc2, 0xe8, 0x1c, 0x38, 0x95, 0xe2, 0x3c, 0x74, 0x14, 0x3c, 0x52, + 0xce, 0x83, 0xde, 0xf8, 0x7d, 0xb0, 0xa7, 0x03, 0x94, 0xf7, 0xba, 0xa0, 0x70, 0x0f, + 0xce, 0x23, 0x43, 0x11, ], ivk: [ - 0x4b, 0x22, 0xa9, 0x1d, 0xfe, 0xa9, 0x16, 0x81, 0x91, 0x48, 0xb8, 0x3d, 0x80, 0x5d, - 0xe3, 0xc7, 0xc6, 0x3f, 0xe3, 0x58, 0x11, 0x41, 0xec, 0xdc, 0x26, 0x43, 0x28, 0xe5, - 0x7c, 0x0b, 0x43, 0x2b, + 0xdd, 0x92, 0x93, 0xed, 0x12, 0x10, 0x4c, 0x31, 0xd7, 0xa1, 0x2a, 0xbd, 0xd3, 0xcf, + 0x19, 0x56, 0x93, 0x93, 0x66, 0x84, 0x4c, 0x8a, 0x07, 0xf5, 0x08, 0x34, 0xa5, 0x86, + 0x15, 0x5b, 0xc2, 0x1a, ], ovk: [ - 0x12, 0xe5, 0xa1, 0x7f, 0x89, 0x12, 0xd9, 0x6b, 0xfd, 0xc7, 0xd3, 0x75, 0x3c, 0xe2, - 0xa8, 0x3a, 0xca, 0x2b, 0xc6, 0x45, 0x38, 0x3b, 0xc4, 0x54, 0x51, 0x11, 0x5e, 0xd5, - 0xb3, 0xf5, 0xbe, 0xaa, + 0xb5, 0xfc, 0x70, 0xd4, 0xee, 0x1b, 0x52, 0x8e, 0x20, 0xd0, 0xee, 0x81, 0x6e, 0x84, + 0x5e, 0xf8, 0x9c, 0x2c, 0xf4, 0x31, 0xa3, 0x18, 0x27, 0x22, 0xfd, 0xe8, 0xbb, 0x37, + 0x39, 0xc6, 0xd6, 0xac, ], dk: [ - 0xc6, 0xa0, 0xdc, 0x04, 0x56, 0xbc, 0x4c, 0x39, 0x9e, 0x20, 0x2d, 0x00, 0xd3, 0x2e, - 0xaf, 0xc9, 0xa8, 0xc0, 0xe2, 0x65, 0xa4, 0xae, 0xb1, 0x07, 0xa9, 0xa6, 0x4d, 0x93, - 0x8b, 0x14, 0xc0, 0x0f, + 0xc8, 0x57, 0x68, 0x3f, 0xfd, 0xc4, 0x6f, 0x1e, 0xf4, 0x01, 0xc0, 0x72, 0xae, 0xa0, + 0x23, 0x49, 0xa7, 0x75, 0xee, 0xe5, 0x5a, 0x5a, 0xad, 0x7b, 0x39, 0xda, 0xc9, 0xb1, + 0x07, 0x1f, 0x78, 0x2c, ], default_d: [ - 0x07, 0xd3, 0x0c, 0x15, 0x5a, 0x71, 0x0a, 0x2d, 0x03, 0x28, 0x25, + 0x2b, 0xc6, 0x0b, 0xe6, 0x02, 0x99, 0x36, 0x8b, 0x00, 0x6b, 0xf1, ], default_pk_d: [ - 0xd7, 0x8b, 0x08, 0x60, 0xbb, 0xf7, 0x82, 0x52, 0x83, 0x79, 0x8e, 0xa7, 0xa6, 0x62, - 0x98, 0x14, 0xed, 0xe8, 0x14, 0x8a, 0x53, 0x8d, 0xe6, 0x30, 0x0e, 0x0f, 0x88, 0x90, - 0x4f, 0x01, 0x4c, 0x19, + 0x88, 0x44, 0x53, 0xc6, 0x20, 0x2f, 0x5b, 0xda, 0x5b, 0x3c, 0xb7, 0xc1, 0x19, 0x35, + 0x1a, 0x4b, 0x7d, 0x27, 0x77, 0x7a, 0xf3, 0x75, 0x1b, 0xe6, 0x93, 0x33, 0x4a, 0x7d, + 0xcd, 0x62, 0x86, 0x14, ], internal_rivk: [ - 0xc4, 0x35, 0x16, 0x37, 0x67, 0x71, 0xad, 0xca, 0x2b, 0x7b, 0xeb, 0xe3, 0xe6, 0xa7, - 0x1c, 0xb6, 0x5c, 0xa8, 0xcf, 0x1f, 0xfb, 0x16, 0xc9, 0xc4, 0xf0, 0x48, 0x19, 0x86, - 0x87, 0x9e, 0xee, 0x28, + 0x7a, 0x20, 0x92, 0x16, 0xf7, 0x8a, 0x6d, 0xd5, 0x0d, 0x5a, 0xc2, 0x20, 0x8a, 0x39, + 0xa7, 0x0b, 0xa2, 0x80, 0x71, 0xd1, 0xdf, 0x72, 0x62, 0xb6, 0x27, 0x93, 0x44, 0x49, + 0x10, 0x24, 0xa3, 0x31, ], internal_ivk: [ - 0xaf, 0x6a, 0xbb, 0xb5, 0xde, 0x71, 0x0f, 0x0f, 0xb4, 0x0f, 0xa5, 0xa2, 0xe2, 0x7e, - 0x8c, 0x83, 0x2c, 0x69, 0x9c, 0x2b, 0x7f, 0x58, 0xbd, 0xa6, 0xbc, 0x9a, 0xd5, 0xb9, - 0x11, 0xc1, 0xf0, 0x20, + 0xf9, 0xb9, 0xd0, 0xd3, 0xe5, 0x30, 0xe2, 0x69, 0x9a, 0xdc, 0x7b, 0x3e, 0xbf, 0xd8, + 0x13, 0x9f, 0x0e, 0xf2, 0x1e, 0x5c, 0x10, 0x03, 0xc0, 0xd1, 0x1b, 0x8a, 0x8b, 0x47, + 0x93, 0xce, 0x00, 0x24, ], internal_ovk: [ - 0x08, 0x6a, 0x61, 0x0d, 0x50, 0x7d, 0xb9, 0xaa, 0x4f, 0x34, 0x90, 0x40, 0xd4, 0xf4, - 0xbf, 0x35, 0x58, 0x05, 0x68, 0xcf, 0x36, 0xe9, 0x3f, 0x40, 0x57, 0x5f, 0x7f, 0x2a, - 0x50, 0xb6, 0xa1, 0xde, + 0xa9, 0x6e, 0x11, 0xc5, 0x27, 0x11, 0xbf, 0x38, 0xee, 0x29, 0xd1, 0xc4, 0xb5, 0xa4, + 0x20, 0xbf, 0x83, 0x7c, 0x2a, 0x95, 0xc0, 0xaf, 0x5e, 0xa8, 0x83, 0xfb, 0x74, 0x74, + 0xca, 0xe6, 0xad, 0x9f, ], internal_dk: [ - 0xfa, 0xae, 0xd1, 0xb9, 0xd7, 0xee, 0x7b, 0x90, 0xb4, 0xa4, 0x70, 0xfd, 0x49, 0xdc, - 0xd2, 0x8c, 0x76, 0xe6, 0x0e, 0xfc, 0xb8, 0x0f, 0x4d, 0x9e, 0x40, 0xe6, 0x6f, 0xa7, - 0x76, 0xc7, 0x07, 0x1f, + 0x73, 0x7f, 0xae, 0x39, 0x10, 0xf9, 0x06, 0x3f, 0x60, 0x1e, 0x89, 0x02, 0x1b, 0x08, + 0xfa, 0x41, 0x40, 0x49, 0x1a, 0xfc, 0x55, 0xf7, 0x48, 0x66, 0x0e, 0x40, 0x73, 0x73, + 0xe8, 0x22, 0xd2, 0xfb, ], asset: [ - 0x1c, 0xe4, 0xc9, 0xbe, 0x0a, 0x6a, 0x49, 0x2f, 0xe7, 0x9f, 0x15, 0x81, 0xa1, 0x55, - 0xfa, 0x3a, 0x2b, 0x9d, 0xaf, 0xd8, 0x2e, 0x65, 0x0b, 0x38, 0x6a, 0xd3, 0xa0, 0x8c, - 0xb6, 0xb8, 0x31, 0x31, + 0x09, 0x07, 0x54, 0x17, 0xfc, 0xc0, 0x06, 0x2e, 0x49, 0xf0, 0x08, 0xc5, 0x1a, 0xd4, + 0x22, 0x74, 0x39, 0xc1, 0xb4, 0x47, 0x6c, 0xcd, 0x8e, 0x97, 0x86, 0x2d, 0xab, 0x7b, + 0xe1, 0xe8, 0xd3, 0x99, ], - note_v: 1448031623652762490, + note_v: 11605778395872469956, note_rho: [ - 0x76, 0x1f, 0xd3, 0xf4, 0x1e, 0x72, 0x8e, 0x1a, 0x28, 0xf8, 0x9d, 0xb8, 0x9f, 0xfd, - 0xec, 0xa3, 0x64, 0xdd, 0x2f, 0x0f, 0x07, 0x39, 0xf0, 0x53, 0x45, 0x56, 0x48, 0x31, - 0x99, 0xc7, 0x1f, 0x18, + 0x9a, 0x7c, 0x23, 0xa9, 0x96, 0x94, 0x1d, 0x88, 0x9e, 0x46, 0x22, 0xa9, 0xb9, 0xb1, + 0xd5, 0x9d, 0x5e, 0x31, 0x90, 0x94, 0x31, 0x8c, 0xd4, 0x05, 0xba, 0x27, 0xb7, 0xe2, + 0xc0, 0x84, 0x76, 0x2d, ], note_rseed: [ - 0x93, 0x41, 0xac, 0x9b, 0x78, 0xa2, 0x69, 0x16, 0x42, 0x06, 0xa0, 0xea, 0x1c, 0xe7, - 0x3b, 0xfb, 0x2a, 0x94, 0x2e, 0x73, 0x70, 0xb2, 0x47, 0xc0, 0x46, 0xf8, 0xe7, 0x5e, - 0xf8, 0xe3, 0xf8, 0xbd, + 0x31, 0x45, 0x3e, 0xc4, 0x54, 0x9a, 0x4d, 0x97, 0x72, 0x9d, 0x03, 0x34, 0x60, 0xfc, + 0xf8, 0x9d, 0x64, 0x94, 0xf2, 0xff, 0xd7, 0x89, 0xe9, 0x80, 0x82, 0xea, 0x5c, 0xe9, + 0x53, 0x4b, 0x3a, 0xcd, ], note_cmx: [ - 0xdf, 0x72, 0x6a, 0x0e, 0x47, 0xd8, 0xb7, 0xd9, 0xcc, 0xa2, 0x6a, 0x1f, 0x74, 0x55, - 0x4a, 0x81, 0x52, 0x5b, 0x1b, 0x7a, 0xf1, 0x6e, 0xfb, 0x52, 0xb9, 0x27, 0x8b, 0x7c, - 0x8a, 0xbf, 0x8c, 0x22, + 0x48, 0xda, 0xaa, 0xc9, 0x22, 0x2d, 0xe0, 0x05, 0x2d, 0x34, 0xd3, 0x21, 0xc5, 0x89, + 0x7f, 0x86, 0x18, 0xee, 0xfb, 0xd5, 0xd5, 0x69, 0x91, 0x84, 0x30, 0x54, 0x94, 0x5a, + 0x55, 0x9c, 0x39, 0x1c, ], note_nf: [ - 0x6a, 0xfb, 0x25, 0xb0, 0x7d, 0x0d, 0x60, 0xa3, 0x28, 0xef, 0x22, 0xd9, 0x06, 0xf3, - 0x53, 0x1d, 0x8b, 0x50, 0xc4, 0x10, 0x7b, 0xd1, 0xc7, 0x66, 0x2c, 0xd6, 0x7b, 0x5d, - 0xb2, 0x0a, 0x05, 0x28, + 0x3a, 0xe6, 0x3f, 0xcb, 0x97, 0xb0, 0x79, 0xfd, 0x66, 0xd9, 0x72, 0x80, 0xec, 0xbc, + 0x9f, 0xd2, 0x84, 0xfb, 0x09, 0x35, 0x99, 0x36, 0x90, 0x24, 0x1c, 0xd9, 0x26, 0x41, + 0x66, 0xe3, 0x03, 0x07, ], }, TestVector { sk: [ - 0x82, 0x1c, 0xf5, 0x77, 0x49, 0x18, 0x64, 0xe2, 0x0e, 0x6d, 0x08, 0xfd, 0x2e, 0x32, - 0xb5, 0x55, 0xc9, 0x2c, 0x66, 0x1f, 0x19, 0x58, 0x8b, 0x72, 0xa8, 0x95, 0x99, 0x71, - 0x0a, 0x88, 0x06, 0x12, + 0xc0, 0x5e, 0xf2, 0x7c, 0x6e, 0x22, 0xee, 0x27, 0x3e, 0x15, 0x78, 0x6e, 0x39, 0x4c, + 0x8f, 0x1b, 0xe3, 0x16, 0x82, 0xa3, 0x01, 0x47, 0x96, 0x3a, 0xc8, 0xda, 0x8d, 0x41, + 0xd8, 0x04, 0x25, 0x84, ], ask: [ - 0xf5, 0x90, 0xaa, 0x36, 0x24, 0x9c, 0x92, 0xdb, 0x3c, 0xb8, 0x45, 0x9e, 0x7c, 0x0a, - 0x19, 0xd9, 0x22, 0xa7, 0x5e, 0x78, 0x3f, 0xf3, 0x6e, 0x7d, 0x08, 0x10, 0x55, 0xcd, - 0x5f, 0xf2, 0x1c, 0x38, + 0xed, 0x13, 0xf6, 0x49, 0x3a, 0x75, 0x3e, 0x17, 0xed, 0xc2, 0xbe, 0x5e, 0xdc, 0xfb, + 0xf5, 0x84, 0x33, 0x50, 0x0d, 0x44, 0x39, 0xf0, 0xf7, 0x9e, 0xee, 0xa3, 0xfc, 0xc5, + 0x15, 0x8a, 0x94, 0x0f, ], ak: [ - 0x66, 0x38, 0xf1, 0x69, 0x63, 0x2d, 0xd9, 0x4d, 0x3b, 0x0c, 0x21, 0x4e, 0xac, 0xc8, - 0x52, 0xc1, 0xe4, 0xe0, 0x70, 0xcb, 0xdf, 0xb6, 0xe6, 0x2d, 0x08, 0x0f, 0x57, 0x68, - 0xa6, 0xaa, 0xd4, 0x23, + 0xfb, 0x04, 0x81, 0x83, 0xeb, 0x36, 0xaa, 0x92, 0xe0, 0x12, 0x52, 0xd7, 0xf7, 0x7d, + 0x5f, 0xf6, 0x6b, 0xed, 0xf7, 0xe2, 0x70, 0x2e, 0xf7, 0x96, 0x72, 0x8f, 0x7e, 0x2a, + 0x5f, 0xb3, 0x14, 0x18, ], isk: [ - 0x53, 0xca, 0x28, 0x5b, 0x63, 0x04, 0xb3, 0x7d, 0xa2, 0xb5, 0x29, 0x4f, 0x5c, 0xb3, - 0x54, 0xa8, 0x94, 0x32, 0x28, 0x48, 0xcc, 0xbd, 0xc7, 0xc2, 0x54, 0x5b, 0x7d, 0xa5, - 0x68, 0xaf, 0xac, 0x87, + 0xd7, 0xc1, 0x11, 0xa6, 0x8e, 0xf4, 0x4b, 0xcd, 0x0c, 0x15, 0x13, 0xad, 0x47, 0xca, + 0x61, 0xc6, 0x59, 0xcc, 0x5d, 0x32, 0x5b, 0x44, 0x0f, 0x6b, 0x9f, 0x59, 0xaf, 0xf6, + 0x68, 0x79, 0xbb, 0x66, ], ik: [ - 0x5e, 0x8e, 0x92, 0x06, 0x37, 0x1f, 0xe4, 0xa0, 0x1d, 0x1c, 0x8a, 0x2c, 0x36, 0xe2, - 0x1a, 0x22, 0x6b, 0x12, 0xb2, 0xf6, 0x56, 0xfc, 0xcc, 0x0e, 0x9c, 0x43, 0x22, 0x27, - 0x69, 0x31, 0x09, 0x91, + 0x0c, 0x40, 0xa2, 0x9b, 0xdb, 0xe3, 0xe4, 0x5d, 0x2c, 0xb7, 0xc1, 0x41, 0xed, 0xe0, + 0xce, 0x2c, 0xe9, 0x2c, 0xa6, 0xbf, 0x9f, 0x6b, 0xc0, 0x42, 0xb0, 0xe7, 0x25, 0x24, + 0xf4, 0x19, 0x5c, 0xa6, ], nk: [ - 0x64, 0x02, 0x41, 0x63, 0x14, 0x5b, 0x68, 0x66, 0x8d, 0x1c, 0x3f, 0x9c, 0x0f, 0x76, - 0xd3, 0x92, 0xd3, 0x71, 0x8f, 0x01, 0x75, 0x18, 0x1b, 0xa1, 0x4a, 0x0f, 0xc9, 0x5b, - 0x7f, 0xec, 0x65, 0x35, + 0x2c, 0x5c, 0xc2, 0x37, 0x14, 0xa6, 0x22, 0xa0, 0xb9, 0xe2, 0x0a, 0x1f, 0x0f, 0x23, + 0x07, 0x26, 0x90, 0xd3, 0x4e, 0x1e, 0xd2, 0x75, 0xfd, 0x22, 0x9b, 0xca, 0x65, 0x46, + 0x96, 0x5c, 0xf6, 0x3d, ], rivk: [ - 0x4a, 0x61, 0xd4, 0x32, 0x0d, 0x12, 0xdd, 0x47, 0xa6, 0xc2, 0x2d, 0x00, 0xd8, 0xb0, - 0x52, 0xb4, 0x83, 0xd0, 0x40, 0xda, 0xd3, 0x79, 0xbb, 0x29, 0x0b, 0x40, 0xd5, 0x0d, - 0x36, 0x71, 0xcd, 0x0c, + 0x7e, 0x13, 0x20, 0x87, 0x56, 0x5e, 0xe9, 0xc5, 0x5b, 0x6d, 0x6f, 0xea, 0x16, 0xba, + 0xee, 0xdc, 0xfb, 0x61, 0xa6, 0xed, 0xc3, 0xce, 0xc3, 0xb0, 0x5a, 0x96, 0x0d, 0x20, + 0x1d, 0xd1, 0xa4, 0x2a, ], ivk: [ - 0x2c, 0x2b, 0x90, 0xc8, 0x3c, 0x30, 0xc2, 0x71, 0x64, 0xce, 0x4d, 0xd9, 0x14, 0xe6, - 0xb8, 0x9e, 0x99, 0x50, 0xe4, 0xf9, 0xa7, 0xa2, 0x4a, 0xfb, 0xcf, 0x11, 0xfe, 0x0d, - 0x86, 0xb1, 0x36, 0x1d, + 0x4d, 0x73, 0x82, 0x9c, 0x52, 0x03, 0x47, 0x9f, 0x58, 0x44, 0xf8, 0xa5, 0x8f, 0x3c, + 0xef, 0xa9, 0xde, 0x8e, 0xaa, 0x95, 0xfa, 0x84, 0x22, 0x7b, 0xf7, 0xa8, 0xed, 0x69, + 0x08, 0xb3, 0xb7, 0x35, ], ovk: [ - 0x30, 0xe0, 0xa4, 0x48, 0xa6, 0x1e, 0x75, 0xa2, 0x5b, 0xd5, 0x89, 0x61, 0x12, 0x5a, - 0x8e, 0xae, 0x84, 0x45, 0x24, 0xde, 0x0d, 0x91, 0x22, 0xa1, 0x2a, 0x4d, 0x59, 0x6c, - 0xfe, 0xdf, 0xab, 0xc1, + 0xde, 0xf9, 0x9b, 0x97, 0x9d, 0xb5, 0x59, 0x7b, 0x55, 0x72, 0xa8, 0x43, 0x5b, 0x6d, + 0x00, 0xab, 0xe1, 0xbb, 0x84, 0x74, 0x67, 0xf3, 0x3c, 0xcb, 0x0b, 0x9d, 0x0c, 0xa3, + 0xdd, 0x11, 0xee, 0xa6, ], dk: [ - 0x33, 0xe4, 0x2c, 0x50, 0xa6, 0x37, 0xe9, 0xdb, 0x68, 0xbe, 0x33, 0x11, 0xbf, 0x5d, - 0x7f, 0xc4, 0x77, 0x4b, 0xe6, 0x19, 0x26, 0xc8, 0x7e, 0xe4, 0xc7, 0xef, 0x36, 0xf1, - 0x87, 0xbb, 0x8c, 0xea, + 0xb0, 0x84, 0xe4, 0x86, 0x25, 0x45, 0x43, 0x7e, 0x11, 0x7e, 0x7a, 0x7b, 0xa9, 0x67, + 0xa3, 0xfd, 0xa7, 0x2e, 0x9b, 0x0a, 0x1d, 0x82, 0x9a, 0xaa, 0x6d, 0x63, 0x8b, 0xb5, + 0x22, 0x1a, 0xe9, 0x41, ], default_d: [ - 0xc8, 0xa8, 0x3e, 0x75, 0xb1, 0x29, 0x1e, 0x29, 0x59, 0x00, 0xa5, + 0xda, 0x61, 0x78, 0xe2, 0x65, 0xc7, 0xbc, 0xe8, 0x7d, 0x3e, 0xca, ], default_pk_d: [ - 0xc5, 0xc1, 0x1c, 0x61, 0x37, 0xce, 0x83, 0x92, 0x69, 0xee, 0x46, 0xc7, 0x97, 0xeb, - 0xc4, 0x6c, 0x10, 0x53, 0x1c, 0x11, 0xc7, 0x51, 0xa7, 0xda, 0xab, 0xa6, 0x62, 0x2a, - 0x43, 0xe5, 0xaf, 0x35, + 0x14, 0xba, 0x11, 0x2b, 0x9e, 0xb9, 0xa8, 0xb8, 0x48, 0x55, 0x52, 0xbf, 0xf6, 0x77, + 0x36, 0x4c, 0x8b, 0x8d, 0x37, 0x2c, 0xc2, 0x98, 0x96, 0x00, 0xe9, 0x8a, 0x53, 0xa6, + 0xbe, 0xd1, 0xdc, 0x3a, ], internal_rivk: [ - 0x69, 0xa9, 0x4e, 0x8c, 0x99, 0x82, 0x59, 0xfe, 0x6e, 0x54, 0x6c, 0x83, 0x32, 0x8b, - 0x72, 0xf6, 0xf8, 0x3e, 0x80, 0x11, 0x70, 0x6a, 0x5e, 0x31, 0xc2, 0x0c, 0xf8, 0x85, - 0x1e, 0x13, 0x94, 0x37, + 0xab, 0x1b, 0x90, 0x4f, 0xb6, 0x34, 0x09, 0x39, 0x84, 0xbf, 0x42, 0x9f, 0xeb, 0x53, + 0x3f, 0x22, 0x5d, 0xa0, 0xad, 0x22, 0xb8, 0x85, 0x64, 0x4f, 0x0b, 0xec, 0x49, 0x2e, + 0xc6, 0x3f, 0x48, 0x18, ], internal_ivk: [ - 0x14, 0xb4, 0xf4, 0x27, 0xd3, 0x39, 0xd1, 0xba, 0x26, 0xae, 0xcd, 0x57, 0x6f, 0x65, - 0x60, 0x9f, 0x18, 0xd9, 0xfc, 0x35, 0xb5, 0xf6, 0xdb, 0x5a, 0xf4, 0xc2, 0xa4, 0x32, - 0x09, 0x5b, 0x88, 0x28, + 0x70, 0xf2, 0x2d, 0x49, 0x0e, 0x62, 0xb3, 0x3e, 0x39, 0xa9, 0xfe, 0x06, 0x50, 0xa6, + 0x0e, 0x09, 0x13, 0x1d, 0x77, 0xd9, 0xb9, 0x4a, 0x61, 0x52, 0xc1, 0x63, 0x9d, 0xa6, + 0xe7, 0xaa, 0x01, 0x1c, ], internal_ovk: [ - 0x01, 0xdb, 0x0e, 0x1d, 0x57, 0x47, 0x62, 0xfd, 0xf3, 0x18, 0xa4, 0xf0, 0x48, 0x57, - 0xcf, 0x3b, 0x35, 0x7e, 0xeb, 0xd7, 0xad, 0x92, 0x9e, 0xb9, 0xf8, 0xf1, 0x37, 0x33, - 0xda, 0x8f, 0x2d, 0x69, + 0x73, 0xa9, 0x08, 0x2e, 0x80, 0xd8, 0x5e, 0x44, 0x58, 0x54, 0xef, 0xb4, 0xdf, 0x15, + 0x89, 0xcf, 0xbf, 0x72, 0x5b, 0xe3, 0xf7, 0xa7, 0x77, 0xb6, 0xa5, 0x1a, 0x35, 0xea, + 0x5d, 0x74, 0xc3, 0xd9, ], internal_dk: [ - 0xf7, 0x6c, 0xb8, 0x2a, 0x6f, 0xe2, 0x49, 0xaf, 0xda, 0x87, 0xa7, 0xb5, 0xd8, 0xf7, - 0x7c, 0x4f, 0xba, 0x4d, 0x62, 0x73, 0xd8, 0x0e, 0xe4, 0x5a, 0x3d, 0xd5, 0xb6, 0x37, - 0xa4, 0x30, 0x5f, 0xdb, + 0x3f, 0x4b, 0xa3, 0xf2, 0x3c, 0x10, 0x3e, 0x92, 0x3e, 0x39, 0x26, 0xd0, 0x9d, 0xc0, + 0x10, 0xab, 0x08, 0xb3, 0x9c, 0x90, 0x8a, 0x61, 0x89, 0x7f, 0xa1, 0x27, 0x27, 0xa2, + 0x0b, 0xd6, 0x27, 0xbd, ], asset: [ - 0x57, 0xf4, 0xb4, 0x5d, 0x64, 0x19, 0xf0, 0xd2, 0xe2, 0xc5, 0xaf, 0x33, 0xae, 0x24, - 0x37, 0x85, 0xb3, 0x25, 0xcd, 0xab, 0x95, 0x40, 0x4f, 0xc7, 0xae, 0xd7, 0x05, 0x25, - 0xcd, 0xdb, 0x41, 0x87, + 0x88, 0xfd, 0x28, 0x59, 0x36, 0x2b, 0x18, 0x2f, 0x20, 0x7b, 0x31, 0x75, 0x96, 0x1f, + 0x64, 0x11, 0xa4, 0x93, 0xbf, 0xfd, 0x04, 0x8e, 0x7d, 0x0d, 0x87, 0xd8, 0x2f, 0xe6, + 0xf9, 0x90, 0xa2, 0xb0, ], - note_v: 3250512694054592767, + note_v: 1850337920518955814, note_rho: [ - 0xbd, 0xf9, 0x55, 0x59, 0x48, 0xcb, 0xd5, 0xa3, 0x32, 0xd0, 0x45, 0xde, 0x6b, 0xa6, - 0xbf, 0x44, 0x90, 0xad, 0xfe, 0x74, 0x44, 0xcd, 0x46, 0x7a, 0x09, 0x07, 0x54, 0x17, - 0xfc, 0xc0, 0x06, 0x2e, + 0x1e, 0x11, 0xbc, 0x33, 0xab, 0x75, 0xdd, 0x6c, 0xa0, 0x67, 0xfb, 0x73, 0xa0, 0x43, + 0xb6, 0x46, 0xa7, 0xcf, 0x39, 0xca, 0xb4, 0x92, 0x83, 0x86, 0x78, 0x6d, 0x2f, 0x24, + 0x14, 0x1e, 0xe1, 0x20, ], note_rseed: [ - 0x49, 0xf0, 0x08, 0xc5, 0x1a, 0xd4, 0x22, 0x74, 0x39, 0xc1, 0xb4, 0x47, 0x6c, 0xcd, - 0x8e, 0x97, 0x86, 0x2d, 0xab, 0x7b, 0xe1, 0xe8, 0xd3, 0x99, 0xc0, 0x5e, 0xf2, 0x7c, - 0x6e, 0x22, 0xee, 0x27, + 0xfd, 0xc3, 0x4d, 0x67, 0x64, 0xea, 0xfc, 0x66, 0x88, 0x0e, 0xe0, 0x20, 0x4f, 0x53, + 0xcc, 0x11, 0x67, 0xed, 0x20, 0xb4, 0x3a, 0x52, 0xde, 0xa3, 0xca, 0x7c, 0xff, 0x8e, + 0xf3, 0x5c, 0xd8, 0xe6, ], note_cmx: [ - 0x83, 0xc0, 0x41, 0xba, 0x80, 0x64, 0x27, 0x9b, 0x24, 0x02, 0xae, 0x1e, 0x60, 0x30, - 0xcb, 0x89, 0xc5, 0x0d, 0x96, 0x6e, 0x03, 0x93, 0x73, 0x5c, 0x45, 0x81, 0xd4, 0x98, - 0x11, 0x38, 0x8d, 0x01, + 0x2d, 0x50, 0xf6, 0x82, 0x85, 0x0c, 0x72, 0x2b, 0x5f, 0x26, 0x15, 0x7e, 0x9c, 0xe8, + 0x4d, 0x12, 0x63, 0x3c, 0xc1, 0x93, 0x02, 0x5e, 0x13, 0x0c, 0x0f, 0xf5, 0xf0, 0xde, + 0xf6, 0x8d, 0x84, 0x21, ], note_nf: [ - 0x1c, 0xe7, 0x2d, 0x48, 0x1c, 0xd5, 0x9e, 0x6c, 0x89, 0x5d, 0x2c, 0x65, 0x85, 0xe9, - 0x77, 0x27, 0x9d, 0x99, 0x27, 0x2e, 0x66, 0xa6, 0xda, 0xa4, 0x74, 0x20, 0xed, 0xbb, - 0xa7, 0xf8, 0x9f, 0x27, + 0xc7, 0x87, 0x80, 0x17, 0xd9, 0x2f, 0x36, 0xe3, 0xae, 0x78, 0x60, 0xeb, 0x0a, 0x8c, + 0x32, 0x3b, 0xa7, 0x4b, 0x23, 0xa7, 0x04, 0x48, 0x97, 0x84, 0x11, 0x77, 0xa6, 0x4d, + 0x50, 0x8a, 0x67, 0x20, ], }, TestVector { sk: [ - 0x3e, 0x15, 0x78, 0x6e, 0x39, 0x4c, 0x8f, 0x1b, 0xe3, 0x16, 0x82, 0xa3, 0x01, 0x47, - 0x96, 0x3a, 0xc8, 0xda, 0x8d, 0x41, 0xd8, 0x04, 0x25, 0x84, 0x26, 0xa3, 0xf7, 0x02, - 0x89, 0xb8, 0xad, 0x19, + 0xa2, 0x5f, 0x5a, 0xa0, 0x11, 0x1a, 0x6e, 0x68, 0xf3, 0x7b, 0xf6, 0xf3, 0xac, 0x2d, + 0x26, 0xb8, 0x46, 0x86, 0xe5, 0x69, 0xd5, 0x8d, 0x99, 0xc1, 0x38, 0x35, 0x97, 0xfa, + 0xd8, 0x11, 0x93, 0xc4, ], ask: [ - 0xd4, 0x21, 0xad, 0x5b, 0x18, 0x0c, 0x34, 0x4b, 0x93, 0xb4, 0xcf, 0x3c, 0xe9, 0x55, - 0x49, 0x1e, 0x00, 0x58, 0x45, 0xd9, 0x2e, 0x6f, 0xd6, 0xe9, 0xeb, 0x27, 0x6d, 0xfd, - 0xe6, 0xea, 0x89, 0x0c, + 0x91, 0xcb, 0x55, 0x3a, 0x4b, 0xfd, 0x80, 0xa0, 0x65, 0xbc, 0x32, 0xca, 0x6f, 0x8a, + 0x5d, 0xe1, 0xd7, 0x15, 0x99, 0xdb, 0x52, 0x7d, 0xb7, 0x04, 0x30, 0xee, 0x81, 0xc2, + 0x1e, 0x29, 0x05, 0x1a, ], ak: [ - 0x91, 0x34, 0xed, 0x63, 0xae, 0xe1, 0x94, 0xb4, 0xb5, 0x58, 0xf5, 0xf6, 0x55, 0xba, - 0xb5, 0x39, 0x39, 0x6b, 0x99, 0x67, 0x8e, 0xf9, 0x1f, 0x44, 0x5b, 0x51, 0x7c, 0x79, - 0xc5, 0x82, 0x18, 0x0e, + 0xf6, 0x5c, 0x7d, 0xf2, 0x87, 0x16, 0x69, 0xbd, 0x0d, 0x82, 0xaa, 0xfe, 0x1f, 0x89, + 0xfe, 0xfd, 0xaf, 0xd6, 0x28, 0x17, 0x65, 0x3c, 0x38, 0xc2, 0x4a, 0xda, 0xe0, 0xfc, + 0x62, 0xe0, 0xc0, 0x0f, ], isk: [ - 0xd8, 0xde, 0x13, 0xbe, 0x4e, 0xeb, 0xe3, 0xbd, 0x4c, 0x8a, 0x6f, 0x55, 0xd6, 0xe0, - 0xc3, 0x73, 0xd4, 0x56, 0x85, 0x18, 0x79, 0xf5, 0xfb, 0xc2, 0x82, 0xdb, 0x9e, 0x13, - 0x48, 0x06, 0xbf, 0xf7, + 0x90, 0x3f, 0x5d, 0x98, 0x48, 0xf1, 0x4f, 0xcb, 0xeb, 0x18, 0x37, 0x57, 0x0f, 0x54, + 0x4d, 0x63, 0x59, 0xeb, 0x23, 0xfa, 0xf3, 0x8a, 0x08, 0x22, 0xda, 0x36, 0xce, 0x42, + 0x6c, 0x4a, 0x2f, 0xbe, ], ik: [ - 0xb7, 0x47, 0x4b, 0x65, 0x52, 0xdf, 0xc5, 0xe1, 0xe2, 0x57, 0xca, 0xbf, 0xee, 0x40, - 0xe6, 0x08, 0x85, 0x7a, 0x2f, 0xbd, 0x48, 0xfd, 0xa6, 0x6e, 0x9c, 0x71, 0x31, 0x17, - 0x11, 0x58, 0x24, 0xa8, + 0x6c, 0xc4, 0x46, 0x5c, 0x0a, 0x64, 0xa5, 0xec, 0x41, 0x96, 0x8a, 0x80, 0x9f, 0x71, + 0x3d, 0xf6, 0xf3, 0x45, 0x1c, 0x5e, 0xec, 0xff, 0xf5, 0x31, 0x7a, 0x21, 0x0c, 0xc7, + 0xc8, 0x50, 0xbd, 0x51, ], nk: [ - 0x1b, 0x7d, 0x9f, 0x63, 0x24, 0x9b, 0x96, 0xe7, 0xde, 0x1e, 0xe9, 0xfc, 0xf9, 0x3b, - 0xbd, 0xa4, 0xeb, 0xe7, 0xe8, 0xe4, 0xc2, 0x1a, 0x6f, 0xe4, 0x24, 0xe9, 0x0b, 0x1d, - 0x72, 0x4f, 0x58, 0x39, + 0x5c, 0x39, 0x80, 0xe1, 0x5d, 0xba, 0xd3, 0x67, 0xf4, 0xa1, 0xd3, 0x89, 0x15, 0x78, + 0x30, 0x61, 0xe2, 0x87, 0x98, 0x17, 0x3f, 0x14, 0x7f, 0xaf, 0xb4, 0xcb, 0x2c, 0x6d, + 0x1f, 0x44, 0xc0, 0x06, ], rivk: [ - 0x60, 0x2b, 0x39, 0xb7, 0xca, 0xff, 0x4e, 0x65, 0x6d, 0x1e, 0x2e, 0x50, 0x87, 0xbf, - 0x19, 0xec, 0x40, 0x93, 0x92, 0x5b, 0x99, 0x36, 0xb2, 0x72, 0x70, 0x74, 0x8e, 0x1b, - 0x16, 0xe0, 0x2f, 0x05, + 0x1c, 0x91, 0x40, 0xc9, 0x47, 0x8f, 0x3a, 0x2b, 0xaf, 0xa6, 0x69, 0x0a, 0xbc, 0x5d, + 0x9e, 0x0d, 0x5e, 0x06, 0x01, 0xb3, 0x89, 0x4d, 0xb8, 0x3a, 0xb9, 0x9e, 0xe7, 0xe8, + 0x66, 0x4e, 0xab, 0x13, ], ivk: [ - 0x5c, 0xb0, 0x1e, 0x28, 0x3d, 0x8b, 0x9e, 0xb1, 0x39, 0xe7, 0x4d, 0x4a, 0x72, 0xca, - 0x45, 0x14, 0x6b, 0xa7, 0xdd, 0x5e, 0x33, 0xe2, 0x79, 0xd3, 0x59, 0xd0, 0xc2, 0x75, - 0x01, 0x5a, 0xc1, 0x18, + 0xcd, 0xdb, 0xbc, 0xe7, 0xf9, 0x62, 0x50, 0x76, 0x5a, 0x84, 0x60, 0xbb, 0x7a, 0xf1, + 0xa6, 0x4f, 0x2b, 0x9e, 0x9e, 0x62, 0x37, 0x67, 0x28, 0x0e, 0x41, 0x0f, 0x80, 0x1a, + 0xa8, 0x67, 0x81, 0x38, ], ovk: [ - 0x92, 0x13, 0x53, 0x2c, 0x80, 0xac, 0x0c, 0x31, 0x00, 0x1c, 0x08, 0x29, 0x67, 0x89, - 0x8c, 0xe1, 0x5e, 0xc6, 0x7e, 0xd5, 0xe6, 0x89, 0x65, 0x34, 0xb3, 0x3f, 0xc3, 0x4a, - 0x80, 0xda, 0x82, 0x83, + 0x6f, 0x31, 0x6e, 0x8e, 0x63, 0x21, 0x24, 0xdb, 0xf8, 0x99, 0x27, 0x54, 0x40, 0xea, + 0x2e, 0xb0, 0x5a, 0xb2, 0x07, 0xc1, 0x85, 0x06, 0x99, 0xf8, 0xe7, 0x9a, 0x3f, 0xa2, + 0x2d, 0x62, 0x9f, 0xc1, ], dk: [ - 0x54, 0x72, 0xf9, 0x27, 0x27, 0x9e, 0xd7, 0xce, 0xc0, 0x9e, 0x60, 0xe7, 0x13, 0xd9, - 0xaf, 0x82, 0xe6, 0x79, 0x6f, 0x60, 0x9b, 0x83, 0xe7, 0xff, 0xdf, 0x2e, 0xbf, 0x16, - 0x4a, 0xd8, 0xa2, 0xb6, + 0x48, 0x4d, 0xee, 0x22, 0x4f, 0xff, 0x5d, 0x93, 0xcf, 0x60, 0x47, 0x1c, 0xc3, 0x59, + 0xd0, 0x11, 0xb2, 0x25, 0x09, 0x34, 0x6d, 0x24, 0xc5, 0x24, 0x19, 0xae, 0x8e, 0x59, + 0x4f, 0x6b, 0x69, 0x51, ], default_d: [ - 0xac, 0xfb, 0x8d, 0xbc, 0x78, 0x27, 0x95, 0xb0, 0x21, 0xa1, 0xaf, + 0xd9, 0xf7, 0x9c, 0xe9, 0xb0, 0xd6, 0x41, 0x19, 0x27, 0x1b, 0xe0, ], default_pk_d: [ - 0x5c, 0x9e, 0xac, 0x4a, 0x26, 0x36, 0xef, 0x27, 0x0b, 0xd8, 0x98, 0x6b, 0x72, 0xb7, - 0x01, 0x45, 0x5d, 0x40, 0x14, 0xbb, 0x83, 0xe8, 0x31, 0xa7, 0x04, 0x01, 0x75, 0x3d, - 0xc7, 0xf5, 0x58, 0x3b, + 0x98, 0x58, 0xd5, 0x94, 0x2c, 0x7d, 0xea, 0xef, 0xf9, 0xc5, 0x41, 0xd5, 0x0f, 0x18, + 0x10, 0x66, 0xc5, 0x57, 0xe6, 0xc7, 0xdc, 0xf0, 0x5b, 0x31, 0x25, 0xc7, 0xcd, 0x3a, + 0x67, 0x67, 0x3e, 0xbd, ], internal_rivk: [ - 0x52, 0x22, 0xd7, 0x35, 0x07, 0x6e, 0x53, 0x15, 0x2a, 0x3d, 0x00, 0x33, 0x19, 0x6e, - 0xe7, 0x3c, 0x7f, 0x6b, 0xf6, 0x08, 0xce, 0x1a, 0x7d, 0x54, 0xac, 0xfc, 0x04, 0x54, - 0x91, 0x87, 0xe7, 0x02, + 0xe6, 0xff, 0x0f, 0xd9, 0xbf, 0xb9, 0xf8, 0x44, 0x9c, 0xa3, 0xf2, 0x76, 0x9b, 0x9d, + 0x32, 0x46, 0xd9, 0x6b, 0xd8, 0x1b, 0x57, 0xa4, 0xef, 0xaf, 0x78, 0xce, 0x77, 0xee, + 0xd5, 0x8d, 0x9c, 0x31, ], internal_ivk: [ - 0x44, 0xff, 0x25, 0xf6, 0xbd, 0x3e, 0xfc, 0xc1, 0x4a, 0x12, 0xdb, 0x7e, 0x2d, 0x2a, - 0xdd, 0xce, 0xe4, 0x84, 0x86, 0x22, 0xa9, 0x98, 0xb7, 0x83, 0x60, 0x88, 0x78, 0x36, - 0x0a, 0xb8, 0xd7, 0x24, + 0xd6, 0x50, 0xa5, 0x8d, 0xcb, 0x1f, 0x01, 0x53, 0x7e, 0x64, 0x81, 0xa1, 0x9b, 0xc6, + 0x84, 0x65, 0xa2, 0xd3, 0x70, 0x13, 0xb2, 0xc3, 0xd6, 0x33, 0x77, 0x19, 0xd1, 0x8c, + 0xc0, 0xa7, 0x87, 0x38, ], internal_ovk: [ - 0x21, 0x1d, 0x5c, 0x4e, 0x72, 0x3f, 0x62, 0xfc, 0xdd, 0x7f, 0x90, 0xe9, 0x54, 0xd1, - 0xba, 0x14, 0xe5, 0x9f, 0xb6, 0x0c, 0xdd, 0x7e, 0x44, 0xb7, 0xb9, 0x4a, 0x58, 0xcc, - 0x48, 0xfa, 0x96, 0x67, + 0x0f, 0x03, 0xa8, 0xda, 0x4c, 0x6a, 0x0a, 0x3a, 0xe6, 0xd2, 0x18, 0xf0, 0x36, 0xce, + 0x95, 0x33, 0x24, 0x13, 0xe3, 0x4e, 0x31, 0x92, 0xfd, 0xe2, 0x99, 0x03, 0x34, 0x63, + 0x21, 0x15, 0xd7, 0x8b, ], internal_dk: [ - 0xa6, 0xc2, 0x25, 0xd5, 0xac, 0xd0, 0x8e, 0x27, 0xb9, 0x46, 0x80, 0x71, 0x19, 0xc5, - 0xb0, 0x46, 0xb6, 0x97, 0x5c, 0xb1, 0xa0, 0x3a, 0xac, 0xf0, 0x89, 0x76, 0x39, 0xb0, - 0x65, 0x4c, 0x7e, 0x20, + 0x06, 0x14, 0x5a, 0x2e, 0xe8, 0xbb, 0xe0, 0x91, 0x31, 0xce, 0x4b, 0xfe, 0x10, 0x53, + 0x23, 0x9c, 0x1b, 0xbf, 0xb3, 0xec, 0xb1, 0x4f, 0x73, 0xa8, 0x4b, 0x8f, 0x11, 0xf2, + 0x39, 0x4f, 0xac, 0xc9, ], asset: [ - 0x0c, 0x15, 0x13, 0xad, 0x47, 0xca, 0x61, 0xc6, 0x59, 0xcc, 0x5d, 0x32, 0x5b, 0x44, - 0x0f, 0x6b, 0x9f, 0x59, 0xaf, 0xf6, 0x68, 0x79, 0xbb, 0x66, 0x88, 0xfd, 0x28, 0x59, - 0x36, 0x2b, 0x18, 0x2f, + 0xff, 0xeb, 0x0a, 0x8a, 0x2e, 0x29, 0x7a, 0x9d, 0x19, 0xba, 0x15, 0x02, 0x45, 0x90, + 0xe3, 0x32, 0x9d, 0x9f, 0xa9, 0x26, 0x1f, 0x99, 0x38, 0xa4, 0x03, 0x2d, 0xd3, 0x46, + 0x06, 0xc9, 0xcf, 0x9f, ], - note_v: 7844555504117092638, + note_v: 564606438193672641, note_rho: [ - 0xf3, 0x7b, 0xf6, 0xf3, 0xac, 0x2d, 0x26, 0xb8, 0x46, 0x86, 0xe5, 0x69, 0xd5, 0x8d, - 0x99, 0xc1, 0x38, 0x35, 0x97, 0xfa, 0xd8, 0x11, 0x93, 0xc4, 0xc1, 0xb1, 0x6e, 0x6a, - 0x90, 0xe2, 0xd5, 0x07, + 0x58, 0x6f, 0x69, 0x17, 0x34, 0x46, 0xd8, 0xe4, 0x8b, 0xf8, 0x4c, 0xbc, 0x00, 0x0a, + 0x80, 0x78, 0x99, 0x97, 0x3e, 0xb9, 0x3c, 0x5e, 0x81, 0x9a, 0xad, 0x66, 0x94, 0x13, + 0xf8, 0x38, 0x79, 0x33, ], note_rseed: [ - 0xcd, 0xfe, 0x6f, 0xbd, 0xaa, 0x86, 0x16, 0x3e, 0x9c, 0xf5, 0xde, 0x31, 0x00, 0xfb, - 0xca, 0x7e, 0x8d, 0xa0, 0x47, 0xb0, 0x90, 0xdb, 0x9f, 0x37, 0x95, 0x2f, 0xbf, 0xee, - 0x76, 0xaf, 0x61, 0x66, + 0xad, 0x15, 0x84, 0xaa, 0x35, 0xe4, 0x3f, 0x4e, 0xcd, 0x1e, 0x2d, 0x04, 0x07, 0xc0, + 0xb1, 0xb8, 0x99, 0x20, 0xff, 0xdf, 0xdb, 0x9b, 0xea, 0x51, 0xac, 0x95, 0xb5, 0x57, + 0xaf, 0x71, 0xb8, 0x9f, ], note_cmx: [ - 0x2e, 0xc3, 0xc2, 0x5f, 0xed, 0x4b, 0x55, 0xf2, 0x3a, 0xef, 0xd4, 0x2a, 0x69, 0x61, - 0x59, 0x72, 0x69, 0x87, 0x74, 0xe6, 0x6c, 0xe2, 0x7f, 0x1b, 0x25, 0x6a, 0xce, 0x16, - 0x51, 0x7f, 0xc0, 0x3c, + 0x6c, 0x90, 0x39, 0xd8, 0xb1, 0x63, 0x00, 0x14, 0x9e, 0xe7, 0x27, 0x3e, 0x5e, 0xef, + 0x5e, 0xdb, 0x90, 0x87, 0xd8, 0x6c, 0x11, 0xfa, 0xf7, 0xab, 0xaf, 0xcd, 0x21, 0xad, + 0x0a, 0x76, 0xf8, 0x11, ], note_nf: [ - 0xaf, 0x67, 0xf7, 0xdf, 0x55, 0x93, 0xc3, 0x90, 0x80, 0x60, 0xb0, 0x50, 0x35, 0x96, - 0xef, 0x32, 0x0b, 0xad, 0x21, 0x30, 0x20, 0xa8, 0x44, 0x7b, 0x69, 0x38, 0x81, 0xf2, - 0xfd, 0x35, 0x9f, 0x11, + 0x20, 0xc9, 0x4a, 0x43, 0xa7, 0xcf, 0xdc, 0x63, 0xd7, 0x07, 0x01, 0xf5, 0xad, 0xcc, + 0x79, 0x5a, 0x31, 0x08, 0x7d, 0x5e, 0xc3, 0x9a, 0x73, 0x6f, 0x81, 0xd8, 0x6e, 0x84, + 0x9a, 0xb2, 0xd6, 0x3b, ], }, ] diff --git a/src/test_vectors/note_encryption_vanilla.rs b/src/test_vectors/note_encryption_vanilla.rs index 3011538f6..72e88042c 100644 --- a/src/test_vectors/note_encryption_vanilla.rs +++ b/src/test_vectors/note_encryption_vanilla.rs @@ -96,36 +96,35 @@ pub(crate) fn test_vectors() -> Vec { 0x42, 0xc2, 0x38, 0x51, 0x38, 0x15, 0x30, 0x2d, 0xf0, 0xf4, 0x83, 0x04, 0x21, 0xa6, 0xc1, 0x3e, 0x71, 0x01, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0xc5, 0x96, 0xfb, 0xd3, 0x2e, 0xbb, 0xcb, 0xad, 0xae, 0x60, 0xd2, 0x85, 0xc7, 0xd7, - 0x5f, 0xa8, 0x36, 0xf9, 0xd2, 0xfa, 0x86, 0x10, 0x0a, 0xb8, 0x58, 0xea, 0x2d, 0xe1, - 0xf1, 0x1c, 0x83, 0x06, + 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, + 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, + 0x05, 0xee, 0xf3, 0x27, ], cmx: [ - 0xa5, 0x70, 0x6f, 0x3d, 0x1b, 0x68, 0x8e, 0x9d, 0xc6, 0x34, 0xee, 0xe4, 0xe6, 0x5b, - 0x02, 0x8a, 0x43, 0xee, 0xae, 0xd2, 0x43, 0x5b, 0xea, 0x2a, 0xe3, 0xd5, 0x16, 0x05, - 0x75, 0xc1, 0x1a, 0x3b, + 0x23, 0x75, 0x7c, 0x51, 0x58, 0x21, 0xcb, 0xc1, 0x84, 0x3c, 0x9a, 0x45, 0x7b, 0x7e, + 0x6a, 0xe6, 0x01, 0xad, 0xd2, 0xea, 0x10, 0xb9, 0xc8, 0x6d, 0x6b, 0x31, 0x7c, 0xe2, + 0xf1, 0x7b, 0xd9, 0x21, ], esk: [ - 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, 0xd3, 0x5a, 0xd7, 0x46, - 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, 0x20, 0xa6, 0x25, 0xff, - 0x38, 0x77, 0xea, 0x3f, + 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, 0x8b, 0xfe, 0x9b, 0x38, + 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, 0x8e, 0x33, 0x35, 0x4f, + 0xff, 0xf1, 0xbd, 0x1a, ], ephemeral_key: [ - 0xad, 0xdb, 0x47, 0xb6, 0xac, 0x5d, 0xfc, 0x16, 0x55, 0x89, 0x23, 0xd3, 0xa8, 0xf3, - 0x76, 0x09, 0x5c, 0x69, 0x5c, 0x04, 0x7c, 0x4e, 0x32, 0x66, 0xae, 0x67, 0x69, 0x87, - 0xf7, 0xe3, 0x13, 0x81, + 0x8a, 0x5e, 0x13, 0x2c, 0x3a, 0x07, 0x04, 0xf2, 0x45, 0x6f, 0xbd, 0x77, 0x7a, 0x13, + 0xd6, 0xec, 0x57, 0x65, 0x56, 0x71, 0xdb, 0x07, 0x2a, 0x7d, 0x27, 0x6a, 0xd9, 0x69, + 0xf5, 0xec, 0x45, 0x17, ], shared_secret: [ - 0x30, 0x3c, 0x1c, 0x3f, 0x2b, 0xcb, 0xb9, 0xd8, 0x49, 0x70, 0x15, 0xa6, 0xdf, 0xca, - 0x95, 0x4e, 0xce, 0x0d, 0x3b, 0x6c, 0xf1, 0x0a, 0xb9, 0xf7, 0x19, 0xeb, 0x89, 0x19, - 0x9e, 0xdf, 0xe9, 0x89, + 0x36, 0xd5, 0x4c, 0xab, 0xc6, 0x7f, 0x6c, 0xc7, 0x26, 0xa7, 0x30, 0xf3, 0xa0, 0xce, + 0xed, 0x58, 0x53, 0xf0, 0x8c, 0xd3, 0x81, 0x46, 0xc8, 0x34, 0x25, 0x98, 0x98, 0x7c, + 0x21, 0x50, 0x48, 0xa5, ], k_enc: [ - 0xef, 0x9d, 0x62, 0x25, 0x68, 0x7c, 0x2c, 0x91, 0x7b, 0x5c, 0xad, 0xa1, 0x75, 0x23, - 0xe8, 0xfb, 0xdb, 0x08, 0x82, 0x25, 0xaf, 0x2d, 0xb5, 0x72, 0xbb, 0x40, 0x0e, 0x44, - 0x8b, 0x5e, 0xa8, 0x71, + 0x82, 0xc4, 0x32, 0x65, 0x33, 0x7f, 0x1a, 0xb3, 0x7b, 0x18, 0xdf, 0x27, 0x75, 0x48, + 0x61, 0x82, 0x63, 0xb8, 0x02, 0x4d, 0x9b, 0x14, 0x5a, 0x05, 0xad, 0xe2, 0xeb, 0x54, + 0x79, 0x18, 0x03, 0x20, ], p_enc: [ 0x02, 0x56, 0xe8, 0x4b, 0x1a, 0xdc, 0x94, 0x23, 0xc3, 0x67, 0x6c, 0x04, 0x8d, 0x5f, @@ -171,68 +170,68 @@ pub(crate) fn test_vectors() -> Vec { 0xee, 0xcc, 0x40, 0xa9, ], c_enc: [ - 0x1a, 0x9a, 0xdb, 0x14, 0x24, 0x98, 0xe3, 0xdc, 0xc7, 0x6f, 0xed, 0x77, 0x86, 0x14, - 0xdd, 0x31, 0x6c, 0x02, 0xfb, 0xb8, 0xba, 0x92, 0x44, 0xae, 0x4c, 0x2e, 0x32, 0xa0, - 0x7d, 0xae, 0xec, 0xa4, 0x12, 0x26, 0xb9, 0x8b, 0xfe, 0x74, 0xf9, 0xfc, 0xb2, 0x28, - 0xcf, 0xc1, 0x00, 0xf3, 0x18, 0x0f, 0x57, 0x75, 0xec, 0xe3, 0x8b, 0xe7, 0xed, 0x45, - 0xd9, 0x40, 0x21, 0xf4, 0x40, 0x1b, 0x2a, 0x4d, 0x75, 0x82, 0xb4, 0x28, 0xd4, 0x9e, - 0xc7, 0xf5, 0xb5, 0xa4, 0x98, 0x97, 0x3e, 0x60, 0xe3, 0x8e, 0x74, 0xf5, 0xc3, 0xe5, - 0x77, 0x82, 0x7c, 0x38, 0x28, 0x57, 0xd8, 0x16, 0x6b, 0x54, 0xe6, 0x4f, 0x66, 0xef, - 0x5c, 0x7e, 0x8c, 0x9b, 0xaa, 0x2a, 0x3f, 0xa9, 0xe3, 0x7d, 0x08, 0x77, 0x17, 0xd5, - 0xe9, 0x6b, 0xc2, 0xf7, 0x3d, 0x03, 0x14, 0x50, 0xdc, 0x24, 0x32, 0xba, 0x49, 0xd8, - 0xb7, 0x4d, 0xb2, 0x13, 0x09, 0x9e, 0xa9, 0xba, 0x04, 0xeb, 0x63, 0xb6, 0x57, 0x4d, - 0x46, 0xc0, 0x3c, 0xe7, 0x90, 0x0d, 0x4a, 0xc4, 0xbb, 0x18, 0x8e, 0xe9, 0x03, 0x0d, - 0x7f, 0x69, 0xc8, 0x95, 0xa9, 0x4f, 0xc1, 0x82, 0xf2, 0x25, 0xa9, 0x4f, 0x0c, 0xde, - 0x1b, 0x49, 0x88, 0x68, 0x71, 0xa3, 0x76, 0x34, 0x1e, 0xa9, 0x41, 0x71, 0xbe, 0xfd, - 0x95, 0xa8, 0x30, 0xfa, 0x18, 0x40, 0x70, 0x97, 0xdc, 0xa5, 0x11, 0x02, 0x54, 0x63, - 0xd4, 0x37, 0xe9, 0x69, 0x5c, 0xaa, 0x07, 0x9a, 0x2f, 0x68, 0xcd, 0xc7, 0xf2, 0xc1, - 0x32, 0x67, 0xbf, 0xf4, 0x19, 0x51, 0x37, 0xfa, 0x89, 0x53, 0x25, 0x2a, 0x81, 0xb2, - 0xaf, 0xa1, 0x58, 0x2b, 0x9b, 0xfb, 0x4a, 0xc9, 0x60, 0x37, 0xed, 0x29, 0x91, 0xd3, - 0xcb, 0xc7, 0xd5, 0x4a, 0xff, 0x6e, 0x62, 0x1b, 0x06, 0xa7, 0xb2, 0xb9, 0xca, 0xf2, - 0x95, 0x5e, 0xfa, 0xf4, 0xea, 0x8e, 0xfc, 0xfd, 0x02, 0x3a, 0x3c, 0x17, 0x48, 0xdf, - 0x3c, 0xbd, 0x43, 0xe0, 0xb9, 0xa8, 0xb0, 0x94, 0x56, 0x88, 0xd5, 0x20, 0x56, 0xc1, - 0xd1, 0x6e, 0xea, 0x37, 0xe7, 0x98, 0xba, 0x31, 0xdc, 0x3e, 0x5d, 0x49, 0x52, 0xbd, - 0x51, 0xec, 0x76, 0x9d, 0x57, 0x88, 0xb6, 0xe3, 0x5f, 0xe9, 0x04, 0x2b, 0x95, 0xd4, - 0xd2, 0x17, 0x81, 0x40, 0x0e, 0xaf, 0xf5, 0x86, 0x16, 0xad, 0x56, 0x27, 0x96, 0x63, - 0x6a, 0x50, 0xb8, 0xed, 0x6c, 0x7f, 0x98, 0x1d, 0xc7, 0xba, 0x81, 0x4e, 0xff, 0x15, - 0x2c, 0xb2, 0x28, 0xa2, 0xea, 0xd2, 0xf8, 0x32, 0x66, 0x2f, 0xa4, 0xa4, 0xa5, 0x07, - 0x97, 0xb0, 0xf8, 0x5b, 0x62, 0xd0, 0x8b, 0x1d, 0xd2, 0xd8, 0xe4, 0x3b, 0x4a, 0x5b, - 0xfb, 0xb1, 0x59, 0xed, 0x57, 0x8e, 0xf7, 0x47, 0x5d, 0xe0, 0xad, 0xa1, 0x3e, 0x17, - 0xad, 0x87, 0xcc, 0x23, 0x05, 0x67, 0x2b, 0xcc, 0x55, 0xa8, 0x88, 0x13, 0x17, 0xfd, - 0xc1, 0xbf, 0xc4, 0x59, 0xb6, 0x8b, 0x2d, 0xf7, 0x0c, 0xad, 0x37, 0x70, 0xed, 0x0f, - 0xd0, 0x2d, 0x64, 0xb9, 0x6f, 0x2b, 0xbf, 0x6f, 0x8f, 0x63, 0x2e, 0x86, 0x6c, 0xa5, - 0xd1, 0x96, 0xd2, 0x48, 0xad, 0x05, 0xc3, 0xde, 0x64, 0x41, 0x48, 0xa8, 0x0b, 0x51, - 0xad, 0xa9, 0x5b, 0xd0, 0x8d, 0x73, 0xcd, 0xbb, 0x45, 0x26, 0x4f, 0x3b, 0xd1, 0x13, - 0x83, 0x5b, 0x46, 0xf9, 0xbe, 0x7b, 0x6d, 0x23, 0xa4, 0x3b, 0xdd, 0xfe, 0x1e, 0x74, - 0x08, 0xc9, 0x70, 0x31, 0xe1, 0xa8, 0x21, 0x4b, 0xab, 0x46, 0x39, 0x10, 0x44, 0xb7, - 0x00, 0xd3, 0x8f, 0x51, 0x92, 0xc5, 0x7f, 0xe6, 0xf8, 0x71, 0x59, 0xb5, 0x55, 0x12, - 0x09, 0x4e, 0x29, 0xd2, 0xce, 0xba, 0xb8, 0x68, 0xc8, 0xf1, 0xad, 0xba, 0xd5, 0x70, - 0x77, 0xcb, 0xeb, 0x5e, 0x69, 0x65, 0x85, 0x82, 0xbf, 0x98, 0xd1, 0x9d, 0x64, 0xf4, - 0x4b, 0x0d, 0x50, 0xc7, 0xe2, 0x20, 0x9a, 0xb3, 0xfc, 0x56, 0xb4, 0xf4, 0x09, 0x12, - 0x3a, 0xae, 0xb0, 0x26, 0x3a, 0x22, 0x45, 0x1b, 0xc1, 0x4e, 0xd7, 0x56, 0xd0, 0x48, - 0x38, 0x5a, 0xed, 0xbb, 0x86, 0xa8, 0x46, 0x77, 0xbb, 0x2d, 0x21, 0xc5, 0x2c, 0xc9, - 0x49, 0x41, 0x47, 0xbf, 0x0f, 0xb1, 0x02, 0x74, 0x52, 0x82, 0x99, 0x09, 0x09, 0x72, - 0x62, 0x28, 0x18, 0x6e, 0x02, 0xc8, + 0x93, 0xe0, 0x48, 0x74, 0xb5, 0x83, 0x7c, 0x26, 0x1d, 0xaf, 0x1a, 0x27, 0xb7, 0x83, + 0xec, 0x48, 0x65, 0xd3, 0xbb, 0x72, 0x8e, 0xb1, 0x61, 0xda, 0xed, 0xb8, 0x44, 0x6a, + 0xb3, 0x8f, 0x07, 0x8e, 0xa8, 0x66, 0x2e, 0x4d, 0x2e, 0x9d, 0x00, 0xa3, 0x95, 0x27, + 0xdc, 0xde, 0x51, 0x7a, 0xc3, 0xdb, 0xf9, 0xd2, 0x7e, 0x3c, 0x79, 0xfa, 0x88, 0x1a, + 0xbb, 0x48, 0xb7, 0x0d, 0xbc, 0x28, 0xdd, 0xf4, 0xaf, 0x81, 0xae, 0xed, 0x2a, 0x29, + 0x86, 0x00, 0x51, 0x08, 0x48, 0xed, 0xbd, 0xc4, 0x2e, 0x88, 0x95, 0x48, 0x70, 0xd5, + 0xd6, 0x01, 0xcd, 0xf2, 0x90, 0x18, 0x1b, 0x53, 0x91, 0x05, 0xb9, 0xf6, 0x13, 0x86, + 0xcb, 0x07, 0x84, 0x6b, 0xc8, 0xe3, 0x19, 0xdf, 0xab, 0x8e, 0x10, 0x97, 0x66, 0xa2, + 0x8c, 0x1e, 0x0b, 0xbf, 0x91, 0x32, 0x02, 0xce, 0xcd, 0x1b, 0x48, 0x17, 0xa2, 0x28, + 0x2f, 0xc2, 0x9e, 0xd4, 0x4d, 0x9b, 0x04, 0x04, 0x9d, 0xe5, 0x5a, 0xcf, 0x54, 0x99, + 0xe5, 0xf5, 0x65, 0xd4, 0x8b, 0x8f, 0x19, 0x72, 0xc0, 0x43, 0x84, 0x77, 0x96, 0x23, + 0x0d, 0xc6, 0x8f, 0x32, 0x57, 0xc0, 0x85, 0x29, 0x14, 0x8c, 0x8e, 0x0c, 0x32, 0x7b, + 0x25, 0xb4, 0x59, 0x87, 0x7c, 0xde, 0xd9, 0x8f, 0xf7, 0x8e, 0x81, 0xfa, 0x69, 0x2e, + 0x14, 0xf8, 0xfd, 0xa1, 0xfe, 0x52, 0x4f, 0xf1, 0x50, 0x18, 0x1f, 0x73, 0x6e, 0xd3, + 0xa8, 0x8e, 0xc7, 0x89, 0xdc, 0x15, 0x95, 0x4a, 0x02, 0x63, 0x9a, 0x8a, 0x20, 0xca, + 0x38, 0xd8, 0x99, 0xbf, 0xd1, 0xc5, 0x73, 0xb0, 0x41, 0xee, 0x7b, 0xf2, 0x2b, 0x96, + 0x75, 0xbd, 0xa8, 0xc4, 0xb0, 0x58, 0xa0, 0x5a, 0x49, 0x33, 0x03, 0xb1, 0x1f, 0x35, + 0x81, 0xc1, 0x9d, 0x2d, 0xa9, 0x96, 0x6a, 0x71, 0x06, 0x6e, 0xc1, 0x7d, 0xcc, 0xd3, + 0x48, 0x20, 0x7e, 0xb3, 0x14, 0xf6, 0xcf, 0xc9, 0xd0, 0x6a, 0x62, 0x14, 0xc6, 0x72, + 0x10, 0x97, 0xa5, 0x2e, 0x27, 0x76, 0x66, 0x7c, 0x6b, 0xe9, 0xc8, 0x86, 0x2b, 0x17, + 0x3d, 0xb0, 0xe8, 0x04, 0xb1, 0x2c, 0xaa, 0xe9, 0xd9, 0xfa, 0x09, 0xf3, 0xf4, 0x8c, + 0xaf, 0x4b, 0xf7, 0x56, 0xa2, 0x78, 0x95, 0x0a, 0x25, 0x4e, 0xc4, 0x14, 0x76, 0x77, + 0xaa, 0xca, 0x21, 0x42, 0x96, 0x08, 0x1a, 0x2f, 0x62, 0x4a, 0x92, 0x78, 0x94, 0x6e, + 0x68, 0x9d, 0xd9, 0x14, 0x02, 0x90, 0x92, 0xe7, 0xfa, 0x8f, 0xbc, 0x8a, 0x04, 0x46, + 0x7d, 0x60, 0xed, 0xff, 0x5d, 0x97, 0xcb, 0x65, 0x09, 0xa0, 0xc7, 0x2c, 0xed, 0x77, + 0xac, 0xa8, 0x71, 0x30, 0x8e, 0x7d, 0xe2, 0xbe, 0xb1, 0x52, 0x0a, 0x34, 0x17, 0xd7, + 0x21, 0x3a, 0x9a, 0xbd, 0x47, 0x35, 0x8c, 0x4f, 0x32, 0x9f, 0x0f, 0x64, 0x41, 0x92, + 0x10, 0xa9, 0x9d, 0xb2, 0xde, 0x6e, 0x6d, 0x89, 0x21, 0xb0, 0xf4, 0xf9, 0x9f, 0xd6, + 0x45, 0xfa, 0xe0, 0xd6, 0x29, 0xce, 0x22, 0x11, 0x90, 0x5f, 0x25, 0xf4, 0x0d, 0x12, + 0x0b, 0x63, 0x27, 0x93, 0x75, 0xb5, 0x43, 0xc3, 0x1e, 0x3b, 0x55, 0x7e, 0x57, 0xa7, + 0xa8, 0x7c, 0x61, 0x79, 0xeb, 0xd3, 0x4f, 0x6d, 0xbb, 0x92, 0x0e, 0xc5, 0xe0, 0x5d, + 0x6a, 0x77, 0xec, 0xdf, 0x36, 0xb4, 0x57, 0xba, 0xb4, 0x56, 0x6c, 0x40, 0x8f, 0xb5, + 0x7d, 0xfc, 0xdd, 0xda, 0xa4, 0x2c, 0x51, 0x34, 0xaf, 0x3e, 0x97, 0x8d, 0xbf, 0xd0, + 0xdf, 0xb0, 0xca, 0x4f, 0xfa, 0xf1, 0x65, 0x0a, 0xbe, 0xe1, 0x62, 0x5f, 0x7f, 0x4b, + 0xf8, 0x25, 0x06, 0x01, 0x00, 0x64, 0x5b, 0x54, 0xc0, 0x04, 0x1f, 0xbf, 0xbd, 0xef, + 0xf7, 0xb9, 0x38, 0x04, 0xe9, 0xcc, 0x0c, 0xcd, 0x6f, 0x27, 0xbe, 0x40, 0x01, 0x6c, + 0x32, 0xd4, 0x2f, 0xe3, 0x66, 0xfa, 0xaa, 0x86, 0x87, 0xc2, 0xd1, 0x92, 0x61, 0x9f, + 0x56, 0x5b, 0x0c, 0x70, 0xea, 0x6a, 0x3f, 0x79, 0xd5, 0x3a, 0x52, 0x41, 0xe6, 0x9c, + 0x3c, 0xa6, 0x87, 0xa1, 0x12, 0xfb, 0x16, 0xc2, 0x5c, 0xc0, 0x83, 0x17, 0xdb, 0xa4, + 0x23, 0x97, 0x0c, 0x32, 0xdf, 0xb4, 0xbd, 0x69, 0x22, 0xe3, 0x36, 0xab, 0xf2, 0xfd, + 0xe2, 0xc3, 0xaa, 0x5d, 0xb2, 0x93, 0xef, 0x27, 0x47, 0x87, 0x6c, 0x8b, 0xd8, 0x6e, + 0xa1, 0x87, 0xcb, 0x60, 0x1a, 0xf7, ], ock: [ - 0x4e, 0x9d, 0x45, 0x94, 0x6b, 0x3e, 0xea, 0xe7, 0xfe, 0x30, 0x5d, 0x5b, 0x90, 0x50, - 0x36, 0x14, 0x1f, 0x9f, 0x40, 0x09, 0xa6, 0x29, 0x4b, 0x96, 0xc7, 0x22, 0xa4, 0xa0, - 0xbe, 0x68, 0x5d, 0xff, + 0xb3, 0x25, 0xeb, 0xe5, 0x7a, 0x2c, 0x40, 0xa8, 0xb2, 0x11, 0xcf, 0xdf, 0x72, 0xa1, + 0xa2, 0x44, 0xf1, 0x53, 0x42, 0x85, 0x98, 0x88, 0xa3, 0x64, 0x52, 0x3e, 0xfd, 0x2a, + 0xc6, 0x6a, 0x1a, 0xd6, ], op: [ 0x63, 0xf7, 0x12, 0x5d, 0xf4, 0x83, 0x6f, 0xd2, 0x81, 0x6b, 0x02, 0x4e, 0xe7, 0x0e, 0xfe, 0x09, 0xfb, 0x9a, 0x7b, 0x38, 0x63, 0xc6, 0xea, 0xcd, 0xf9, 0x5e, 0x03, 0x89, - 0x49, 0x50, 0x69, 0x2c, 0x56, 0x66, 0x9d, 0x64, 0x3f, 0x78, 0x0b, 0x6a, 0xd8, 0xb3, - 0xd3, 0x5a, 0xd7, 0x46, 0x8a, 0xaa, 0x73, 0x27, 0x66, 0x57, 0x5f, 0x84, 0xa9, 0x5d, - 0x20, 0xa6, 0x25, 0xff, 0x38, 0x77, 0xea, 0x3f, + 0x49, 0x50, 0x69, 0x2c, 0x5b, 0xfe, 0x46, 0x9c, 0x33, 0xe4, 0x47, 0xba, 0x45, 0x6b, + 0x8b, 0xfe, 0x9b, 0x38, 0x5b, 0x39, 0x31, 0xb4, 0xba, 0xeb, 0x8f, 0x70, 0x23, 0xfe, + 0x8e, 0x33, 0x35, 0x4f, 0xff, 0xf1, 0xbd, 0x1a, ], c_out: [ - 0xcb, 0xdf, 0x68, 0xa5, 0x7f, 0xb4, 0xa4, 0x6f, 0x34, 0x60, 0xff, 0x22, 0x7b, 0xc6, - 0x18, 0xda, 0xe1, 0x12, 0x29, 0x45, 0xb3, 0x80, 0xc7, 0xe5, 0x49, 0xcf, 0x4a, 0x6e, - 0x8b, 0xf3, 0x75, 0x49, 0xba, 0xe1, 0x89, 0x1f, 0xd8, 0xd1, 0xa4, 0x94, 0x4f, 0xdf, - 0x41, 0x0f, 0x07, 0x02, 0xed, 0xa5, 0x44, 0x2f, 0x0e, 0xa0, 0x1a, 0x5d, 0xf0, 0x12, - 0xa0, 0xae, 0x4d, 0x84, 0xed, 0x79, 0x80, 0x33, 0x28, 0xbd, 0x1f, 0xd5, 0xfa, 0xc7, - 0x19, 0x21, 0x6a, 0x77, 0x6d, 0xe6, 0x4f, 0xd1, 0x67, 0xdb, + 0x55, 0xb8, 0x90, 0x7c, 0x6d, 0x45, 0x4b, 0x83, 0x63, 0x4f, 0x1b, 0x9a, 0x1a, 0xa3, + 0xc3, 0xc9, 0x8a, 0xdc, 0x77, 0xd9, 0x6c, 0x2f, 0x62, 0x49, 0xec, 0x66, 0xdb, 0xae, + 0x4d, 0x0c, 0xc9, 0x40, 0xd7, 0x26, 0xbc, 0xd1, 0xec, 0x91, 0x18, 0x9f, 0xd3, 0x04, + 0x9a, 0x33, 0xf2, 0xea, 0x7d, 0x8b, 0x74, 0xaa, 0xc1, 0x7c, 0xda, 0x38, 0x83, 0x80, + 0x2d, 0xb5, 0x96, 0x9d, 0x8d, 0x2f, 0x32, 0x25, 0x91, 0x9c, 0xe3, 0x88, 0x26, 0x41, + 0x5c, 0xc6, 0xb3, 0x38, 0x94, 0x4b, 0x48, 0x99, 0x54, 0x8b, ], }, TestVector { @@ -306,36 +305,35 @@ pub(crate) fn test_vectors() -> Vec { 0xa2, 0x17, 0x64, 0x10, 0x4a, 0x23, 0xea, 0xf6, 0xba, 0x49, 0x6c, 0xb9, 0xb8, 0xe8, 0x25, 0x7a, 0xd8, 0xb3, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0x33, 0x88, 0xda, 0x05, 0x06, 0xda, 0x9e, 0xa2, 0xd5, 0x16, 0x73, 0x9b, 0x95, 0x1c, - 0x7c, 0xc0, 0x58, 0x53, 0x36, 0xb4, 0x4d, 0xf9, 0xb3, 0xb5, 0x0e, 0x48, 0x93, 0xe4, - 0xb1, 0x84, 0x92, 0x11, + 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, + 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, + 0x4d, 0xb2, 0xc7, 0x31, ], cmx: [ - 0x9e, 0x04, 0x32, 0xb2, 0xb3, 0x33, 0xcd, 0xe8, 0xce, 0x92, 0x1b, 0x77, 0xca, 0x7e, - 0x9e, 0x41, 0x51, 0xe3, 0x74, 0xd5, 0x16, 0xcd, 0xa1, 0x17, 0x63, 0x83, 0x6a, 0xf3, - 0xb6, 0x6f, 0x5b, 0x15, + 0x59, 0xb6, 0xf3, 0xd4, 0x03, 0x22, 0x3d, 0x6c, 0xe4, 0x3d, 0xed, 0xae, 0xe2, 0x35, + 0xfc, 0xa9, 0x5c, 0xc8, 0xb2, 0x49, 0x94, 0x1c, 0xcd, 0xb6, 0x6f, 0x3f, 0x61, 0x1c, + 0xc5, 0xe9, 0xf9, 0x0f, ], esk: [ - 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, 0x4d, 0x80, 0x4a, 0x17, - 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, 0x92, 0x1c, 0xd5, 0xda, - 0x8a, 0x6e, 0x1a, 0x08, + 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, 0xdd, 0x73, 0x4d, 0x0e, + 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, 0x22, 0xc0, 0x61, 0xe0, + 0xbd, 0xc9, 0xce, 0x14, ], ephemeral_key: [ - 0x91, 0x92, 0x3e, 0xd8, 0x2b, 0x76, 0xd7, 0x97, 0x30, 0x7c, 0xaa, 0x23, 0x02, 0xc0, - 0xcf, 0x75, 0x56, 0x12, 0x17, 0x24, 0x98, 0x67, 0x53, 0x2a, 0xe5, 0x1c, 0x2e, 0xa0, - 0x05, 0xed, 0xad, 0xb6, + 0xd2, 0x9e, 0x0d, 0x00, 0x1e, 0xe7, 0x1e, 0x05, 0x99, 0x08, 0x65, 0x04, 0xd8, 0x62, + 0xc7, 0xf5, 0x2b, 0x08, 0x60, 0x77, 0x0d, 0x8a, 0x4b, 0x42, 0xa8, 0x68, 0x11, 0xac, + 0x31, 0x69, 0x85, 0x8c, ], shared_secret: [ - 0x53, 0xd7, 0xe4, 0x84, 0x3a, 0x36, 0xd5, 0x79, 0xb5, 0xa7, 0xc1, 0x04, 0x11, 0x96, - 0xbd, 0x4c, 0x85, 0x80, 0x5c, 0xcd, 0x0a, 0x3f, 0x95, 0xbc, 0x9e, 0x71, 0x06, 0x90, - 0xd1, 0x1b, 0x7a, 0xaa, + 0x11, 0xa0, 0xac, 0x79, 0x9a, 0x29, 0xb0, 0xed, 0x19, 0x5e, 0xd8, 0x7b, 0x13, 0x83, + 0x22, 0x26, 0x3b, 0xbb, 0x9c, 0x31, 0x00, 0x8c, 0x29, 0x59, 0xaf, 0x2f, 0xc6, 0x36, + 0x68, 0x7e, 0xd9, 0xb0, ], k_enc: [ - 0xc2, 0xe3, 0x38, 0x9d, 0x6f, 0xc3, 0xcd, 0x06, 0x7f, 0x59, 0x0a, 0x93, 0x73, 0x05, - 0x04, 0xad, 0x9b, 0x63, 0xc4, 0x55, 0x45, 0x69, 0xb9, 0x62, 0x0f, 0x3e, 0xf0, 0xb0, - 0x65, 0x94, 0xde, 0xd6, + 0x4b, 0xbf, 0x80, 0xe7, 0xa1, 0x70, 0x3a, 0xc1, 0x4a, 0xd7, 0xb5, 0x44, 0x8a, 0x2e, + 0x8e, 0x79, 0x49, 0x30, 0x49, 0xd1, 0x9a, 0x6a, 0x51, 0x31, 0x67, 0xd5, 0x5b, 0xdd, + 0x58, 0x6a, 0xc0, 0xd9, ], p_enc: [ 0x02, 0x55, 0x6e, 0x5e, 0x1b, 0xf5, 0x1b, 0xc6, 0xa6, 0x11, 0x58, 0xf7, 0x40, 0x50, @@ -381,68 +379,68 @@ pub(crate) fn test_vectors() -> Vec { 0x8b, 0x1e, 0x88, 0x6f, ], c_enc: [ - 0x6d, 0x21, 0x18, 0x0a, 0xc4, 0x74, 0x94, 0x57, 0x8a, 0x90, 0x06, 0xaf, 0x5b, 0xeb, - 0x4e, 0x34, 0x55, 0x59, 0xab, 0xdb, 0x0e, 0x23, 0xed, 0x52, 0x65, 0xaf, 0x79, 0xce, - 0x0c, 0xc5, 0x96, 0x71, 0xea, 0x31, 0x7b, 0x3e, 0xb1, 0x52, 0x93, 0xd1, 0xe0, 0x4a, - 0x9a, 0xd8, 0x39, 0x69, 0xab, 0x9e, 0x17, 0x08, 0xf2, 0x28, 0x85, 0x3a, 0x28, 0x1f, - 0xcf, 0x6c, 0x97, 0x60, 0xae, 0x71, 0x96, 0x5b, 0xb1, 0xd4, 0x45, 0x2e, 0x5e, 0xd0, - 0x06, 0x00, 0xab, 0x58, 0x94, 0x27, 0x75, 0xb7, 0x4e, 0x12, 0x62, 0xb4, 0x22, 0x5d, - 0x3b, 0x61, 0x9c, 0x31, 0x65, 0x96, 0xd7, 0xcf, 0x9c, 0x93, 0xbd, 0xb5, 0x2a, 0xfa, - 0x77, 0x8a, 0xa1, 0x20, 0x8d, 0x56, 0xd0, 0x69, 0xe5, 0x6e, 0x27, 0x79, 0x61, 0x4d, - 0x56, 0xf4, 0x36, 0x10, 0x72, 0xbc, 0x15, 0x16, 0xa9, 0xb4, 0x56, 0x2a, 0x4f, 0x54, - 0x63, 0xa5, 0x13, 0xc4, 0x59, 0x42, 0x15, 0x70, 0xf3, 0x34, 0xef, 0xb6, 0xbc, 0xd2, - 0x08, 0xf8, 0xf8, 0x05, 0x0e, 0x15, 0x3d, 0x4e, 0x61, 0xf3, 0x1e, 0xdd, 0xbb, 0x5a, - 0x98, 0xf1, 0x70, 0xd3, 0xd0, 0x80, 0xe8, 0xec, 0x3f, 0x65, 0x20, 0xb6, 0xa2, 0xd6, - 0x08, 0x83, 0xa5, 0x87, 0xff, 0x0e, 0x98, 0x21, 0x1c, 0x73, 0x45, 0x16, 0xb5, 0xdc, - 0xc7, 0x5e, 0xf2, 0x3c, 0xfb, 0x9f, 0x55, 0xf1, 0xde, 0xed, 0xf1, 0x26, 0xc2, 0xce, - 0x17, 0x27, 0x3f, 0x41, 0xdb, 0xbb, 0xbd, 0x2f, 0x49, 0xe3, 0x55, 0x77, 0x6e, 0xc0, - 0x46, 0x98, 0x35, 0xf7, 0x9d, 0x94, 0x80, 0x42, 0xf8, 0x42, 0x0f, 0x11, 0xe1, 0xab, - 0xd7, 0x45, 0x06, 0xb7, 0x8b, 0x5e, 0x41, 0xcb, 0xe0, 0xc7, 0x07, 0x17, 0xf4, 0x6e, - 0x7e, 0xb9, 0xac, 0xdc, 0x35, 0x1c, 0x94, 0x98, 0x83, 0x3a, 0xfd, 0xed, 0x93, 0x06, - 0xa0, 0x43, 0x5b, 0x10, 0xb8, 0x3a, 0xe3, 0x95, 0xd5, 0x7f, 0x5b, 0x0a, 0x5d, 0x41, - 0xa9, 0x34, 0x2d, 0x02, 0xec, 0x58, 0xb6, 0xee, 0x16, 0x87, 0x77, 0x50, 0x16, 0xb8, - 0x74, 0x9b, 0x28, 0x7a, 0xbd, 0xd3, 0xed, 0x1a, 0x83, 0x5e, 0xa8, 0xf3, 0xb1, 0x4d, - 0x08, 0x18, 0xfe, 0x0d, 0x5d, 0x9a, 0x48, 0xeb, 0x02, 0x13, 0x64, 0x0e, 0xec, 0xc1, - 0x9a, 0x5d, 0x16, 0x61, 0xdb, 0x82, 0x2b, 0x77, 0x9b, 0x08, 0x0c, 0xd8, 0xba, 0x7f, - 0x3a, 0x27, 0x23, 0x21, 0xee, 0x5d, 0xa2, 0x27, 0x8c, 0x53, 0x85, 0x67, 0xd0, 0xd9, - 0xbb, 0x28, 0xce, 0x64, 0x21, 0x31, 0x15, 0x03, 0xa4, 0xa0, 0x17, 0x14, 0xcf, 0x91, - 0x01, 0x55, 0x2b, 0xa5, 0xef, 0xc8, 0x5c, 0x94, 0xd5, 0xe5, 0x09, 0x72, 0x7e, 0x5e, - 0x01, 0x1c, 0x15, 0xb1, 0xb2, 0xec, 0xdf, 0xf3, 0x99, 0xc0, 0xbe, 0x33, 0x42, 0xab, - 0x6e, 0xdd, 0xa8, 0xe3, 0xed, 0x81, 0x1a, 0x7d, 0x9c, 0x9c, 0xa4, 0xbb, 0x71, 0xa5, - 0x63, 0xe1, 0x59, 0x78, 0xbf, 0x8e, 0x64, 0x04, 0xac, 0x79, 0x6e, 0xb7, 0x81, 0xfd, - 0x2c, 0xf2, 0x19, 0x1b, 0x2f, 0x4d, 0x40, 0x76, 0xd9, 0x3c, 0xcc, 0x80, 0xf7, 0xe5, - 0x92, 0xfa, 0x66, 0x9b, 0x72, 0x26, 0x57, 0x82, 0xee, 0x8f, 0x5c, 0xe3, 0x03, 0x12, - 0xd3, 0x51, 0x2b, 0x35, 0x49, 0x0a, 0xfe, 0x00, 0x6b, 0xad, 0xb1, 0x62, 0x0d, 0x1b, - 0x0c, 0x79, 0xfb, 0xc4, 0xbe, 0xc5, 0x65, 0xd7, 0x46, 0x1d, 0x68, 0xef, 0x72, 0x27, - 0x79, 0x11, 0x77, 0x6c, 0xd5, 0xa7, 0xb5, 0xfc, 0x6f, 0xa8, 0xb3, 0xee, 0xfd, 0x7a, - 0x39, 0xe8, 0xe5, 0xb4, 0xf6, 0xa5, 0x0c, 0x7d, 0x58, 0xd9, 0xeb, 0x08, 0x38, 0x0d, - 0x32, 0x0b, 0x36, 0xea, 0x04, 0x37, 0x00, 0xac, 0xa7, 0x64, 0xb4, 0x8c, 0x3d, 0xa4, - 0x93, 0x67, 0xfa, 0x93, 0x35, 0x6a, 0xaa, 0x4f, 0x87, 0x08, 0xea, 0x6e, 0x34, 0x59, - 0x81, 0x84, 0x5b, 0xe7, 0x37, 0x6d, 0xa7, 0x98, 0x40, 0x53, 0xef, 0x7d, 0xd4, 0xb6, - 0xa7, 0x27, 0x92, 0x35, 0x6a, 0x6c, 0x34, 0x62, 0x68, 0x88, 0xcc, 0x70, 0xde, 0x49, - 0x9e, 0xf9, 0x10, 0x26, 0x95, 0xd9, 0xdb, 0x12, 0xaf, 0x29, 0x62, 0xfc, 0x75, 0xd4, - 0x36, 0x56, 0x19, 0xdb, 0x0e, 0x87, 0x6c, 0xdb, 0x82, 0x02, 0xe8, 0x16, 0xfd, 0xc2, - 0xcd, 0xf3, 0x7a, 0xd3, 0xbe, 0x3b, + 0x1b, 0x42, 0x34, 0x80, 0xbf, 0x37, 0x67, 0xf5, 0xeb, 0xfc, 0x40, 0xb8, 0xc8, 0x9c, + 0xc5, 0x34, 0xf1, 0x65, 0xc3, 0x5d, 0x19, 0xc8, 0xda, 0x6c, 0x32, 0x10, 0xe9, 0x52, + 0xca, 0xd8, 0x23, 0xa7, 0x84, 0x60, 0x21, 0xc3, 0xde, 0x4a, 0x86, 0x93, 0xb7, 0x1e, + 0x28, 0x7f, 0x46, 0x86, 0xac, 0x0a, 0xdd, 0xce, 0xd9, 0x4e, 0xba, 0x81, 0x0a, 0x99, + 0x8b, 0x82, 0x3a, 0x4a, 0xd2, 0x41, 0xaa, 0x9f, 0x4a, 0x3a, 0xe4, 0x82, 0x5d, 0xe9, + 0x95, 0xdd, 0x58, 0x73, 0x56, 0x62, 0x44, 0xbb, 0xd8, 0x75, 0xd0, 0x1b, 0xf3, 0x28, + 0xe8, 0x22, 0xca, 0xfd, 0xb8, 0x3e, 0xd7, 0x75, 0x3a, 0x88, 0x85, 0xd7, 0xae, 0xf2, + 0x45, 0x5a, 0x15, 0x2e, 0x23, 0xdf, 0xa2, 0xd6, 0x99, 0xb3, 0x5c, 0x33, 0xd3, 0x61, + 0x07, 0x2a, 0xe5, 0xc5, 0x12, 0x43, 0x4d, 0x34, 0x6f, 0x6c, 0x56, 0xfb, 0x5f, 0x11, + 0xb0, 0xb6, 0x47, 0xcb, 0xca, 0xfe, 0x02, 0xd8, 0x84, 0x55, 0xa6, 0x30, 0xa3, 0x50, + 0x86, 0x2b, 0x3c, 0xd1, 0x51, 0x3b, 0x6d, 0x6e, 0x41, 0x17, 0xc7, 0x5e, 0xc4, 0xb1, + 0x2f, 0xd7, 0x5a, 0x90, 0xf8, 0x2d, 0xce, 0xa1, 0xc7, 0x71, 0xfd, 0xda, 0x24, 0xec, + 0xf0, 0xa3, 0xe5, 0xb2, 0xe8, 0xa2, 0x24, 0x23, 0x6e, 0xf0, 0x9a, 0x93, 0xab, 0x59, + 0xe5, 0x9b, 0xdf, 0xb8, 0x72, 0x86, 0x0c, 0xc2, 0xd9, 0x11, 0x34, 0xca, 0xf2, 0x13, + 0x98, 0x48, 0xe3, 0x9a, 0xa6, 0x4b, 0xa2, 0xe6, 0xd7, 0x25, 0x20, 0x54, 0xf3, 0x7a, + 0xd5, 0x5c, 0x2c, 0xe5, 0xf8, 0x1b, 0x33, 0xcc, 0xb6, 0x8a, 0x94, 0x73, 0x71, 0x24, + 0x3a, 0x77, 0xe8, 0x43, 0x67, 0xd9, 0xd3, 0x5b, 0x11, 0x68, 0x14, 0x10, 0xea, 0x79, + 0x8b, 0x03, 0x87, 0xb8, 0xf1, 0x0b, 0x1f, 0x89, 0xc6, 0x8a, 0xd1, 0xcc, 0xa9, 0xa3, + 0xe0, 0x32, 0xf3, 0x49, 0x98, 0x79, 0xc8, 0x9a, 0xe6, 0x38, 0x2f, 0x38, 0x97, 0x22, + 0x01, 0x1f, 0x49, 0x25, 0x14, 0x3e, 0xa8, 0x50, 0x73, 0xe4, 0xff, 0x0c, 0xcf, 0x6d, + 0x77, 0x9b, 0xc3, 0xbf, 0x4c, 0x1b, 0x95, 0xfc, 0x7c, 0xf7, 0xf9, 0x91, 0xa2, 0x16, + 0x2a, 0xb9, 0x45, 0x41, 0xf3, 0x99, 0x8e, 0xf6, 0xbc, 0x3f, 0xe8, 0x02, 0x54, 0xab, + 0xa4, 0x1f, 0x15, 0x23, 0x15, 0x03, 0x45, 0x1b, 0x15, 0xe1, 0x08, 0x52, 0xf8, 0x5b, + 0xd2, 0xd1, 0x15, 0x93, 0x53, 0x14, 0xcd, 0x80, 0xc1, 0x23, 0xbe, 0x0b, 0x53, 0x0f, + 0xaa, 0xd6, 0xb5, 0x07, 0x49, 0x68, 0x22, 0x1d, 0xa0, 0x4b, 0x54, 0x6d, 0x96, 0x21, + 0x63, 0x29, 0x9d, 0x52, 0xce, 0xf4, 0x1e, 0x29, 0x6d, 0xa5, 0x9c, 0xb0, 0x76, 0xdb, + 0xe8, 0x99, 0x70, 0x4b, 0x61, 0x73, 0x0c, 0x19, 0xbd, 0x22, 0x1a, 0xd2, 0xbd, 0x29, + 0x81, 0xea, 0x95, 0x1b, 0xe0, 0x2c, 0x9f, 0x5b, 0xdf, 0x92, 0xd9, 0x87, 0x07, 0x46, + 0xb2, 0xa5, 0x8c, 0x3d, 0x18, 0xa7, 0xd3, 0xe5, 0xe2, 0xc6, 0x3a, 0xc2, 0x61, 0x58, + 0x37, 0xbe, 0x1c, 0x6f, 0xe0, 0x03, 0x65, 0x6c, 0x1b, 0x3d, 0x71, 0x50, 0x5f, 0x5e, + 0x21, 0x88, 0x10, 0x4e, 0x98, 0x91, 0x1b, 0x6a, 0x5e, 0x3f, 0x52, 0x82, 0xfa, 0xc0, + 0xc8, 0xfa, 0x1b, 0xa3, 0x6f, 0xfc, 0x07, 0xdc, 0x7a, 0x40, 0x9d, 0xf2, 0xeb, 0xa8, + 0xc7, 0x5f, 0x70, 0xbd, 0x59, 0xa6, 0xf0, 0x65, 0x1d, 0xc1, 0xb1, 0xb5, 0x96, 0xde, + 0x6a, 0xce, 0xc7, 0x78, 0xe2, 0xe3, 0x2f, 0x1e, 0xd4, 0x6d, 0xf7, 0xa9, 0xae, 0xf5, + 0x1d, 0xfe, 0x5a, 0xa5, 0x24, 0x36, 0xea, 0x07, 0xf5, 0x05, 0xd3, 0x39, 0xf2, 0x03, + 0x45, 0x86, 0x61, 0xc8, 0x3a, 0x9a, 0x5a, 0x27, 0xaa, 0x48, 0xb5, 0xec, 0x47, 0xf8, + 0xd6, 0x0d, 0x2a, 0x41, 0x00, 0x1f, 0xce, 0x30, 0xff, 0x75, 0x3a, 0x8a, 0x8c, 0xe4, + 0x92, 0xef, 0xcd, 0x1f, 0x75, 0x3b, 0x7f, 0x4a, 0xd7, 0x36, 0x62, 0x64, 0x47, 0xd1, + 0xb6, 0xf0, 0x7a, 0x61, 0x7d, 0x4b, 0xfc, 0xdb, 0x48, 0xaf, 0xef, 0x08, 0x2d, 0xae, + 0x1d, 0x76, 0x54, 0x4e, 0x8b, 0x63, 0xad, 0xcb, 0xb6, 0x0e, 0x14, 0x96, 0x69, 0x32, + 0x60, 0xc7, 0x20, 0xe6, 0x72, 0x1e, 0x00, 0x20, 0xef, 0xa3, 0xf8, 0xd8, 0x8d, 0x15, + 0xb5, 0xaa, 0x48, 0xa1, 0xb2, 0x2c, ], ock: [ - 0x91, 0x36, 0x59, 0x30, 0x9e, 0xcf, 0xcd, 0xfd, 0x7e, 0x0c, 0xef, 0x23, 0xf8, 0x80, - 0xae, 0x4c, 0xf4, 0xd8, 0xcf, 0x67, 0x78, 0xb9, 0xc4, 0xe6, 0xf4, 0xc7, 0x71, 0x7b, - 0xf5, 0xca, 0xf0, 0x9e, + 0xab, 0xd0, 0xc2, 0x46, 0x97, 0xe4, 0x5b, 0x8b, 0xc4, 0x83, 0x0f, 0xb1, 0x46, 0x53, + 0x2e, 0xa0, 0xac, 0x84, 0x55, 0x81, 0xca, 0x35, 0x39, 0xd3, 0x41, 0x24, 0x73, 0x54, + 0x09, 0xd0, 0x15, 0xac, ], op: [ 0xb4, 0xca, 0xc5, 0x6f, 0x06, 0x2b, 0xfb, 0x2e, 0x27, 0x15, 0xea, 0xf9, 0xc8, 0xfc, 0xdb, 0xc2, 0x0c, 0x86, 0x79, 0x3f, 0x23, 0x57, 0xdd, 0xd0, 0x4a, 0xad, 0x39, 0xf9, - 0x4a, 0xd7, 0xc7, 0x84, 0x68, 0x65, 0x87, 0xce, 0x53, 0xc3, 0x39, 0xf9, 0xce, 0xcf, - 0x4d, 0x80, 0x4a, 0x17, 0x09, 0x39, 0x2b, 0x6a, 0xb1, 0x08, 0xea, 0x2c, 0x57, 0x79, - 0x92, 0x1c, 0xd5, 0xda, 0x8a, 0x6e, 0x1a, 0x08, + 0x4a, 0xd7, 0xc7, 0x84, 0x10, 0x87, 0x4a, 0x74, 0x22, 0x7a, 0xc7, 0x99, 0x5e, 0xdd, + 0xdd, 0x73, 0x4d, 0x0e, 0x00, 0xdc, 0xc9, 0xf4, 0x8a, 0x01, 0xdd, 0x5c, 0x4c, 0xb1, + 0x22, 0xc0, 0x61, 0xe0, 0xbd, 0xc9, 0xce, 0x14, ], c_out: [ - 0x4d, 0xf8, 0xda, 0x22, 0xec, 0x17, 0xf4, 0x16, 0xe0, 0x59, 0x1a, 0xac, 0xc1, 0x6b, - 0x6d, 0xd2, 0xbb, 0xbf, 0x47, 0xbe, 0x04, 0x30, 0x3d, 0xc8, 0x85, 0xd3, 0x5a, 0xc3, - 0xf9, 0x92, 0x3e, 0xea, 0x41, 0xf3, 0x6b, 0x3a, 0x4a, 0x5c, 0x5e, 0x73, 0x3e, 0x32, - 0x6e, 0x96, 0xdb, 0xe5, 0x5e, 0xf9, 0xe7, 0xe8, 0x42, 0x27, 0x0c, 0xbf, 0x46, 0x7c, - 0xdc, 0x16, 0x0e, 0xbf, 0x4f, 0x10, 0x9a, 0xd6, 0x92, 0x0a, 0x6a, 0xed, 0x4a, 0x01, - 0x71, 0xd9, 0x06, 0xe3, 0xe8, 0x13, 0x32, 0xe6, 0xc5, 0x61, + 0xea, 0xdf, 0x7e, 0xeb, 0x10, 0x2d, 0xb1, 0x88, 0x58, 0x54, 0xc2, 0x9e, 0xb7, 0xb0, + 0x5c, 0x7c, 0x96, 0xbb, 0xb8, 0x90, 0x00, 0x2c, 0x4e, 0xd1, 0x14, 0xed, 0x62, 0xf5, + 0xf9, 0xcc, 0xb4, 0x41, 0x6b, 0x5e, 0xdd, 0xd9, 0xad, 0xb5, 0x5c, 0xe9, 0xc7, 0xa0, + 0xd8, 0x44, 0x2b, 0xbc, 0x8a, 0xfa, 0x5c, 0x77, 0xb9, 0x90, 0xad, 0x6d, 0x46, 0x12, + 0x4d, 0xde, 0x70, 0x49, 0x48, 0x72, 0xb2, 0x20, 0x8a, 0x7c, 0x58, 0x02, 0xdf, 0xe9, + 0xbd, 0x1c, 0xa1, 0x9b, 0xef, 0x4b, 0x37, 0xc6, 0x13, 0xb2, ], }, TestVector { @@ -516,36 +514,35 @@ pub(crate) fn test_vectors() -> Vec { 0x9d, 0x5e, 0x64, 0x07, 0x19, 0xbc, 0xa5, 0xc8, 0xed, 0x49, 0x99, 0x97, 0x34, 0xe6, 0xc5, 0xb3, 0x73, 0x3e, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0xbe, 0xf8, 0xcf, 0x16, 0x98, 0xe4, 0x78, 0x47, 0xd3, 0x8e, 0x1a, 0xaa, 0x88, 0x86, - 0x10, 0x77, 0xcd, 0xb5, 0xad, 0x4c, 0xf6, 0x6f, 0xe4, 0x2f, 0xd6, 0x52, 0x57, 0x81, - 0xb6, 0xd3, 0x4f, 0x1e, + 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, + 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, + 0x25, 0xb9, 0xff, 0x16, ], cmx: [ - 0xd8, 0x19, 0xa6, 0x37, 0x7a, 0xce, 0x33, 0xf9, 0x21, 0xf2, 0x29, 0xf9, 0x32, 0x86, - 0x6d, 0x9f, 0xcd, 0xb9, 0xd0, 0x42, 0x6a, 0xfa, 0xca, 0x9e, 0x60, 0x50, 0xb4, 0x7a, - 0x83, 0x19, 0xd6, 0x0d, + 0x0b, 0x74, 0x59, 0x61, 0x6f, 0xc6, 0x93, 0x95, 0xe6, 0x44, 0x36, 0xcf, 0x4a, 0xe9, + 0x44, 0x1d, 0x37, 0x4b, 0x29, 0x04, 0x9e, 0x4c, 0x86, 0x22, 0x3a, 0x03, 0x83, 0xf4, + 0xe0, 0x24, 0x69, 0x05, ], esk: [ - 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, 0xb3, 0x5d, 0xa9, 0xc6, - 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, 0xec, 0x8a, 0xd7, 0xf7, - 0x4c, 0xd9, 0xb2, 0x1b, + 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, 0xa1, 0xc4, 0x12, 0xbc, + 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, 0x95, 0x72, 0x92, 0x93, + 0x59, 0xe0, 0x4c, 0x3a, ], ephemeral_key: [ - 0x5b, 0xcb, 0xf9, 0xf1, 0xd7, 0xdd, 0x68, 0xe7, 0xcc, 0x6d, 0x6c, 0x78, 0x49, 0x50, - 0xd1, 0xc2, 0xe0, 0xbe, 0x6a, 0x84, 0xa7, 0xa8, 0x8d, 0x6f, 0x7a, 0x20, 0x98, 0xc3, - 0xdc, 0xae, 0x3f, 0x2f, + 0x0e, 0x04, 0xd8, 0x52, 0x5d, 0xd6, 0x8f, 0x7a, 0xe8, 0x68, 0xca, 0x81, 0x1e, 0x88, + 0x33, 0xa7, 0xf4, 0x7d, 0x7a, 0xad, 0xd3, 0x76, 0x03, 0xac, 0xe6, 0x07, 0xee, 0x6c, + 0x86, 0x6b, 0xce, 0x23, ], shared_secret: [ - 0x37, 0x35, 0x1c, 0xe2, 0x57, 0xb2, 0x79, 0x4d, 0x86, 0xa5, 0x3d, 0x26, 0x8d, 0xc9, - 0x00, 0x06, 0x40, 0xc2, 0x76, 0xf3, 0xf4, 0x65, 0xe1, 0xaa, 0x70, 0xbf, 0xde, 0xf4, - 0x99, 0xa3, 0xd7, 0xaa, + 0x4a, 0x7a, 0x54, 0xac, 0x00, 0x41, 0x95, 0x98, 0xb0, 0x76, 0x01, 0x53, 0xe2, 0x6a, + 0xcc, 0xd2, 0x15, 0x05, 0x24, 0x16, 0x65, 0x17, 0x13, 0xee, 0xa1, 0x89, 0x19, 0xf3, + 0xe2, 0x62, 0xd3, 0xb6, ], k_enc: [ - 0xea, 0x22, 0x99, 0x65, 0x39, 0xd3, 0x74, 0xda, 0x6a, 0x75, 0x34, 0x39, 0x5a, 0xe9, - 0x23, 0x36, 0xfc, 0xa7, 0x85, 0x11, 0x20, 0xdd, 0x1a, 0xe4, 0x9e, 0x45, 0xb3, 0x3e, - 0x0b, 0xed, 0xe9, 0xac, + 0x30, 0x62, 0x6d, 0x92, 0xeb, 0x62, 0x0f, 0xd4, 0xa9, 0x28, 0xb4, 0x3f, 0xd5, 0x50, + 0x69, 0x74, 0x71, 0x76, 0x7d, 0xe4, 0x49, 0x6c, 0xfd, 0xad, 0xb1, 0xda, 0x18, 0xfc, + 0x0c, 0xdd, 0x5a, 0xa6, ], p_enc: [ 0x02, 0x08, 0xab, 0x2e, 0xe9, 0x9d, 0x4d, 0x9b, 0x98, 0x3d, 0xdd, 0x22, 0x47, 0xee, @@ -591,68 +588,68 @@ pub(crate) fn test_vectors() -> Vec { 0x55, 0x21, 0x93, 0xb1, ], c_enc: [ - 0x12, 0xd6, 0x64, 0xed, 0x05, 0xd6, 0x46, 0x26, 0x89, 0xd4, 0xf2, 0x4a, 0xee, 0x5a, - 0x4f, 0x0f, 0x32, 0x35, 0xff, 0x11, 0x0b, 0x2d, 0xf9, 0x9f, 0x67, 0xd8, 0xc5, 0xb3, - 0x68, 0xdd, 0x47, 0x69, 0xd8, 0x44, 0xd3, 0xdd, 0xa0, 0x3f, 0x58, 0xc5, 0x48, 0x63, - 0x62, 0xe8, 0x90, 0x81, 0xa5, 0xdf, 0xd0, 0xa6, 0x06, 0xa3, 0x91, 0x26, 0x4b, 0x56, - 0xca, 0x3a, 0xfc, 0x4f, 0xe0, 0xe4, 0xc3, 0x05, 0xf3, 0x07, 0x78, 0x09, 0x4a, 0x00, - 0xb7, 0x33, 0x4b, 0xdd, 0x82, 0x45, 0xac, 0x56, 0x0e, 0xf3, 0x29, 0xbc, 0x68, 0x97, - 0xd4, 0xd7, 0xba, 0x31, 0xac, 0x84, 0x54, 0x44, 0x1a, 0x15, 0xc8, 0xd3, 0xce, 0xcc, - 0x71, 0x32, 0xdf, 0x0d, 0x9d, 0x0e, 0xcf, 0x92, 0x84, 0x34, 0xa0, 0xd2, 0x8c, 0x1b, - 0x00, 0x48, 0x52, 0x01, 0xec, 0x33, 0xbe, 0x9a, 0x28, 0x74, 0xb4, 0x29, 0x6c, 0x04, - 0x22, 0xc7, 0xe7, 0xa0, 0xa3, 0xa2, 0x2e, 0xc7, 0xe7, 0x21, 0xa4, 0x79, 0x22, 0x8d, - 0xa2, 0x8b, 0x47, 0x37, 0xaf, 0x52, 0x06, 0xdf, 0x7d, 0x74, 0xe4, 0x84, 0xc4, 0xf7, - 0xa8, 0x56, 0xbe, 0x8c, 0xd0, 0x4b, 0x21, 0x26, 0xb5, 0x27, 0x11, 0xe7, 0xb0, 0xaf, - 0x75, 0xc7, 0x52, 0x84, 0xa1, 0x57, 0x20, 0x40, 0xe8, 0xad, 0xe5, 0x85, 0xe8, 0xa4, - 0x82, 0x80, 0x03, 0x59, 0x67, 0x46, 0xc4, 0x0c, 0x9d, 0x76, 0x0d, 0x92, 0x74, 0xb1, - 0x25, 0x42, 0x2b, 0x63, 0x48, 0x1a, 0x17, 0xff, 0xba, 0xb8, 0xc2, 0xde, 0x13, 0xb2, - 0x19, 0xf5, 0x8a, 0x35, 0x95, 0x2d, 0x88, 0x7a, 0xed, 0xe8, 0xe0, 0x2f, 0x10, 0x33, - 0x8c, 0x23, 0x98, 0x23, 0xfb, 0x43, 0x49, 0x51, 0x84, 0x47, 0x12, 0xf6, 0x8d, 0x6e, - 0x4f, 0xef, 0xae, 0x2b, 0x79, 0x5b, 0xa9, 0x78, 0xe9, 0x81, 0xc1, 0x09, 0x27, 0xab, - 0xbc, 0x16, 0x30, 0x66, 0xa0, 0xe9, 0x60, 0xb3, 0xb8, 0xa3, 0x26, 0xc0, 0x39, 0x85, - 0x81, 0x10, 0x93, 0x99, 0xf6, 0xed, 0x60, 0x44, 0x9a, 0xa8, 0x58, 0xd5, 0xdd, 0x27, - 0xdb, 0xf8, 0x89, 0x9f, 0x9c, 0x9a, 0x50, 0x20, 0x5f, 0x25, 0xd0, 0xcc, 0x50, 0xb2, - 0xde, 0xe3, 0x63, 0x54, 0xc5, 0xe4, 0x48, 0x4d, 0x36, 0xf6, 0x3c, 0x97, 0x63, 0xd8, - 0x41, 0xad, 0x5e, 0x00, 0x21, 0x63, 0x6a, 0x85, 0x7c, 0xfb, 0x79, 0xa5, 0x12, 0x3c, - 0x3d, 0xfb, 0x77, 0x3d, 0x0c, 0x1b, 0xeb, 0x9f, 0x90, 0xa9, 0x72, 0xd0, 0xfc, 0x80, - 0x5f, 0x65, 0x5d, 0x69, 0x40, 0x85, 0x23, 0xb9, 0x9b, 0x62, 0xa8, 0xfa, 0xbe, 0xf0, - 0xc0, 0x24, 0xf2, 0x1f, 0x50, 0xe4, 0xc1, 0x12, 0xe2, 0xfe, 0xdd, 0x58, 0xca, 0xe9, - 0x60, 0x9a, 0xc6, 0xf7, 0xcc, 0x79, 0x83, 0x86, 0xc9, 0xd9, 0x06, 0x42, 0x1c, 0xa5, - 0x7c, 0xf8, 0x1b, 0x09, 0x6b, 0xba, 0xda, 0x64, 0xd0, 0xee, 0x76, 0x95, 0x18, 0x9d, - 0x5f, 0xb1, 0x7a, 0xe2, 0x53, 0x1d, 0xbb, 0x2c, 0x00, 0x58, 0x5a, 0x26, 0xa6, 0x8c, - 0x27, 0xf9, 0x77, 0x77, 0x84, 0x1a, 0x3e, 0x39, 0x30, 0xc7, 0x0f, 0xc3, 0xfa, 0x8e, - 0x2b, 0x7f, 0xc2, 0x1e, 0x87, 0xcf, 0x9f, 0x63, 0xb3, 0x63, 0xb8, 0x8d, 0xaa, 0x1f, - 0xb6, 0x7b, 0xda, 0xe8, 0xe5, 0x5b, 0x68, 0x51, 0x6d, 0x19, 0xdf, 0xef, 0xec, 0x9b, - 0x3d, 0x38, 0xe6, 0xe1, 0xd0, 0xa6, 0xe4, 0x51, 0xd6, 0xd1, 0xf5, 0x2d, 0x1f, 0x96, - 0xdd, 0x0d, 0x53, 0x6d, 0x68, 0xd2, 0x69, 0x86, 0x70, 0x9f, 0x41, 0xe7, 0x60, 0x74, - 0x05, 0x5b, 0xf7, 0x52, 0xbf, 0x38, 0x86, 0x92, 0xc8, 0x2c, 0xfd, 0xa1, 0xeb, 0xb0, - 0x17, 0x8b, 0x8e, 0x0c, 0x85, 0xad, 0x7b, 0x15, 0x99, 0x14, 0x42, 0x8e, 0x30, 0x21, - 0xda, 0xe3, 0x01, 0x0d, 0x65, 0x6c, 0x10, 0x36, 0xf4, 0xa5, 0x7e, 0x7f, 0xad, 0xe0, - 0xfc, 0x32, 0x2a, 0xa6, 0xfd, 0xde, 0x71, 0x4a, 0x8c, 0x53, 0x78, 0x79, 0xe7, 0x04, - 0x41, 0x6f, 0x51, 0x04, 0xdb, 0xbc, 0x8f, 0xf2, 0x42, 0xc1, 0x6d, 0x2d, 0xf4, 0xa8, - 0x41, 0xeb, 0x6b, 0x45, 0x3a, 0x12, 0x83, 0xf6, 0x5f, 0xe1, 0x0d, 0x70, 0xc8, 0x76, - 0x41, 0x8e, 0x44, 0x4a, 0xb3, 0x1b, 0x93, 0x71, 0xa2, 0x7d, 0x36, 0xd8, 0x6e, 0x8f, - 0x1c, 0x32, 0x77, 0xca, 0xfd, 0xf8, + 0x81, 0x56, 0x2d, 0xbe, 0xf7, 0xbb, 0x35, 0x3a, 0x62, 0xe7, 0xc8, 0x1e, 0xbe, 0x68, + 0x15, 0x6c, 0xb7, 0x5c, 0x5c, 0x7e, 0x3d, 0x96, 0xbb, 0xcd, 0x7d, 0xaf, 0xf5, 0x0c, + 0xb0, 0x95, 0x7d, 0x33, 0xdd, 0x99, 0x77, 0x9f, 0x7d, 0x3d, 0x72, 0xb1, 0x8d, 0xeb, + 0x7a, 0x69, 0x75, 0x10, 0xe0, 0x13, 0x5b, 0x8d, 0xf4, 0x83, 0xa4, 0xd7, 0x1d, 0x1a, + 0xb1, 0x08, 0x09, 0x6e, 0x76, 0x08, 0x91, 0xd5, 0x31, 0x07, 0xf0, 0x3d, 0xea, 0x4a, + 0xe8, 0xe4, 0xd3, 0xfe, 0xbd, 0x98, 0x77, 0xf8, 0x57, 0x0a, 0xa3, 0x09, 0xd0, 0x97, + 0xd4, 0x23, 0xbb, 0x76, 0x3f, 0xb3, 0xe7, 0xe9, 0xbe, 0x3c, 0x8f, 0xa0, 0x34, 0xc0, + 0x1d, 0x66, 0x4f, 0x47, 0xa0, 0xe7, 0x13, 0x3c, 0xa1, 0x1a, 0x48, 0xcd, 0x0e, 0xea, + 0x46, 0x35, 0xfa, 0x77, 0x25, 0x0a, 0x17, 0xbd, 0xf7, 0xb7, 0x32, 0xc8, 0x98, 0x46, + 0x51, 0x57, 0x4f, 0xd4, 0xf9, 0x9f, 0x7a, 0xa0, 0xdb, 0x28, 0xc2, 0x97, 0x31, 0x52, + 0xbf, 0x42, 0x6e, 0xe9, 0xa4, 0xd8, 0x41, 0xa9, 0x1d, 0x5d, 0x33, 0x57, 0x18, 0xee, + 0xcb, 0xc9, 0xc8, 0xb2, 0xa2, 0x00, 0x15, 0x70, 0xfe, 0x8b, 0x77, 0x91, 0x43, 0xdf, + 0x22, 0x95, 0x98, 0xa5, 0xbe, 0x25, 0x48, 0xcf, 0x35, 0x84, 0x25, 0x18, 0xcc, 0x1d, + 0xbc, 0x78, 0xcc, 0x2f, 0x0f, 0xc8, 0xea, 0x35, 0x7c, 0xe6, 0xc1, 0x7e, 0xb9, 0x7c, + 0x61, 0x38, 0xd5, 0x3e, 0x6c, 0x8e, 0x00, 0xf0, 0x7f, 0x80, 0x01, 0x25, 0x18, 0x2b, + 0x25, 0xa5, 0xe8, 0x75, 0xc5, 0x37, 0x72, 0x09, 0x52, 0x72, 0x22, 0x37, 0x1f, 0x72, + 0xbf, 0xbd, 0x46, 0x28, 0x44, 0xab, 0x06, 0xf3, 0xb3, 0xa1, 0xeb, 0xa3, 0x44, 0x23, + 0xb6, 0x9a, 0xbf, 0x5d, 0xe6, 0x64, 0xba, 0x83, 0xcd, 0x43, 0xb6, 0xa8, 0xe9, 0xd5, + 0xb7, 0xc5, 0x2a, 0xdb, 0x86, 0x15, 0x04, 0x1b, 0x90, 0xd9, 0x08, 0x83, 0x1a, 0x6f, + 0xf9, 0x2d, 0xb4, 0x8a, 0x14, 0xac, 0x4d, 0xfa, 0x67, 0xd0, 0x2c, 0x72, 0xe0, 0xc8, + 0x63, 0x15, 0x7d, 0x98, 0xf8, 0xf5, 0x45, 0x37, 0x92, 0x97, 0x43, 0xc9, 0x69, 0xbc, + 0x91, 0xc2, 0xc1, 0x37, 0x52, 0x04, 0x98, 0x3c, 0x99, 0x99, 0x97, 0x5f, 0xfa, 0x5e, + 0xe5, 0xfe, 0x1f, 0x69, 0x71, 0x99, 0x40, 0x5f, 0x09, 0x66, 0xe3, 0x1f, 0x34, 0xe1, + 0x52, 0x38, 0x44, 0x38, 0x18, 0x44, 0x98, 0x2b, 0x2c, 0x3b, 0x49, 0xa2, 0x09, 0xff, + 0xa3, 0xce, 0xe9, 0x79, 0xa8, 0x5b, 0x19, 0xb8, 0x50, 0xf4, 0x1d, 0xcc, 0xc4, 0x63, + 0xe2, 0x2e, 0x24, 0xa3, 0x04, 0x9d, 0x37, 0xb1, 0xfb, 0x37, 0x0d, 0xeb, 0xdd, 0xf4, + 0xde, 0x05, 0x46, 0x24, 0x5e, 0x4f, 0x02, 0xa9, 0x84, 0x98, 0xaf, 0x53, 0x2e, 0x27, + 0xac, 0xae, 0x5c, 0x7e, 0xd1, 0x43, 0xe6, 0xe9, 0xcc, 0xfa, 0x74, 0x35, 0x16, 0x02, + 0x16, 0x57, 0xac, 0xb2, 0x5e, 0x44, 0x47, 0x84, 0x5c, 0x5f, 0x9c, 0x59, 0x64, 0x60, + 0x7c, 0x4a, 0x78, 0x72, 0x1d, 0x98, 0x1a, 0x7f, 0xf2, 0xfd, 0xf6, 0xc0, 0x33, 0x62, + 0x8b, 0xff, 0xd6, 0xf0, 0xb8, 0xde, 0x0c, 0xd6, 0x35, 0xec, 0x22, 0xf8, 0xb5, 0x0e, + 0xd6, 0x37, 0xfe, 0x4e, 0x00, 0xf9, 0xd3, 0xc3, 0xd4, 0xf1, 0x81, 0x0b, 0x09, 0xb7, + 0x5c, 0x96, 0xe2, 0xfc, 0xf1, 0x11, 0x85, 0x31, 0x7e, 0xdf, 0xa3, 0x9d, 0x19, 0x25, + 0xde, 0xd8, 0x14, 0xdd, 0xe0, 0xef, 0x00, 0xa3, 0xfb, 0x47, 0xaf, 0x5d, 0x81, 0x20, + 0x94, 0xaf, 0x13, 0xd0, 0x1c, 0x98, 0x56, 0x9f, 0xf7, 0x73, 0x57, 0x87, 0xfa, 0x9b, + 0xd0, 0x1f, 0xa0, 0x69, 0x28, 0x27, 0x5f, 0xdd, 0x10, 0x38, 0x96, 0x5f, 0xb0, 0x6f, + 0xb3, 0x5e, 0xdb, 0x73, 0x80, 0xdd, 0x3c, 0x42, 0x41, 0x9e, 0x0c, 0x0e, 0xde, 0x4c, + 0x48, 0x6a, 0x9d, 0xb4, 0x95, 0x38, 0x86, 0xae, 0xc6, 0xad, 0x30, 0x70, 0x28, 0xeb, + 0x26, 0xa3, 0x7e, 0xf4, 0x71, 0x56, 0x7a, 0xd4, 0xbd, 0x4e, 0xaa, 0xb7, 0xa8, 0x2c, + 0xb0, 0xd6, 0xb5, 0xf0, 0x5e, 0x89, 0x4e, 0x53, 0x25, 0x82, 0x1d, 0x92, 0xbe, 0xd2, + 0xb8, 0x6f, 0xb2, 0x43, 0x37, 0xd5, 0x79, 0x28, 0x8f, 0x6d, 0xf7, 0x34, 0x77, 0x1d, + 0x9e, 0xf8, 0x35, 0x8b, 0xa9, 0x1a, ], ock: [ - 0xca, 0x6f, 0x98, 0xe6, 0xcf, 0x9f, 0xc3, 0x6a, 0xf5, 0xf6, 0x98, 0x82, 0x74, 0x2d, - 0x06, 0xec, 0x5d, 0x29, 0xac, 0x2a, 0x02, 0x89, 0x44, 0xa2, 0x01, 0x89, 0xd5, 0x1c, - 0x8a, 0x9b, 0xdc, 0xd6, + 0xb6, 0x36, 0xc3, 0x9a, 0x6b, 0xad, 0x22, 0x63, 0xb2, 0x44, 0x1e, 0xd5, 0xbb, 0xdb, + 0x01, 0x35, 0x88, 0xfb, 0x46, 0x27, 0x01, 0xe6, 0xf8, 0x76, 0x64, 0x6c, 0x8c, 0x17, + 0xfa, 0x2e, 0xfd, 0xe8, ], op: [ 0x82, 0xfe, 0xf6, 0x43, 0xdb, 0xf4, 0x2d, 0xca, 0x51, 0x56, 0xfb, 0x51, 0xd4, 0xc4, 0xee, 0x00, 0x8a, 0x72, 0xf0, 0xdb, 0xc3, 0xf3, 0x1e, 0xfa, 0xb0, 0x75, 0xf2, 0x75, - 0x15, 0x37, 0x14, 0x0d, 0x59, 0xd1, 0x0a, 0x5b, 0x94, 0x15, 0x8a, 0x3f, 0x3a, 0x78, - 0xb3, 0x5d, 0xa9, 0xc6, 0x27, 0xbe, 0xdf, 0x7c, 0xfb, 0x84, 0x7e, 0x3e, 0x59, 0x86, - 0xec, 0x8a, 0xd7, 0xf7, 0x4c, 0xd9, 0xb2, 0x1b, + 0x15, 0x37, 0x14, 0x0d, 0xc4, 0x92, 0x42, 0xce, 0xe7, 0xe0, 0x86, 0x8f, 0x2a, 0x75, + 0xa1, 0xc4, 0x12, 0xbc, 0x44, 0xd5, 0x4c, 0x97, 0x09, 0xf6, 0x59, 0xde, 0xd3, 0x26, + 0x95, 0x72, 0x92, 0x93, 0x59, 0xe0, 0x4c, 0x3a, ], c_out: [ - 0xa9, 0x5e, 0x1a, 0x22, 0x45, 0x65, 0x29, 0x5e, 0x9b, 0x55, 0x3a, 0xdd, 0xe8, 0xb0, - 0x14, 0x47, 0x5c, 0x68, 0x7b, 0x5d, 0x13, 0x49, 0xc1, 0xdf, 0x8a, 0xd4, 0xb7, 0xcf, - 0xd3, 0xdf, 0xc1, 0x00, 0x6c, 0x7c, 0x37, 0xde, 0x67, 0x6d, 0x6f, 0xde, 0x31, 0x8e, - 0x2f, 0xdf, 0xcc, 0x2e, 0x2e, 0x23, 0x2c, 0xc5, 0xf8, 0x85, 0x28, 0x39, 0xe7, 0xef, - 0xab, 0x8b, 0x20, 0x0e, 0xbc, 0x6a, 0x4d, 0xf8, 0x2a, 0x75, 0x21, 0xce, 0x0f, 0x38, - 0x4f, 0xe2, 0x7a, 0x0d, 0xec, 0x59, 0xe9, 0xd2, 0xc0, 0xe3, + 0x46, 0xba, 0x14, 0xf8, 0x3f, 0xf5, 0xab, 0x76, 0x0f, 0x14, 0x20, 0xeb, 0xde, 0xd9, + 0x86, 0xfd, 0x93, 0x78, 0x27, 0xbc, 0x05, 0x69, 0x2e, 0xca, 0xdb, 0x65, 0x2e, 0xbb, + 0xc8, 0xf6, 0xd9, 0xb5, 0x2e, 0xc3, 0x97, 0x87, 0xd8, 0xeb, 0xdd, 0x50, 0x6c, 0xa1, + 0xa8, 0x5d, 0xc3, 0xd5, 0xba, 0x4c, 0x5b, 0x41, 0x52, 0x61, 0xb0, 0x75, 0x3a, 0xc1, + 0x0e, 0x01, 0x86, 0x45, 0x32, 0xa3, 0x57, 0x2c, 0x68, 0xaf, 0xe4, 0x0a, 0xc3, 0xc0, + 0x95, 0x7b, 0x7a, 0xfc, 0x23, 0xfd, 0x5e, 0x05, 0x17, 0xaa, ], }, TestVector { @@ -726,36 +723,35 @@ pub(crate) fn test_vectors() -> Vec { 0xfa, 0xde, 0x94, 0xfa, 0x0b, 0x46, 0xe3, 0xb1, 0xa5, 0x73, 0x34, 0x99, 0x34, 0xe2, 0x32, 0xb5, 0x0e, 0x96, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0x18, 0x89, 0x8e, 0x75, 0x21, 0x7b, 0x32, 0x9b, 0x3a, 0x56, 0x7b, 0x09, 0x37, 0x89, - 0xa4, 0xd8, 0x19, 0xcd, 0xb0, 0x34, 0x88, 0xb8, 0x10, 0xda, 0x22, 0x0c, 0x3f, 0x59, - 0xba, 0x03, 0x39, 0x26, + 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, + 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, + 0xf5, 0x0e, 0x92, 0x37, ], cmx: [ - 0x23, 0xad, 0xc3, 0xbf, 0x35, 0x0e, 0xb0, 0x84, 0xbd, 0x28, 0xbc, 0x2d, 0xcf, 0xb7, - 0x98, 0x3f, 0xf6, 0xb3, 0xb6, 0xf2, 0xeb, 0x2d, 0x6f, 0x12, 0x4f, 0xfc, 0x46, 0x85, - 0xab, 0xe8, 0xde, 0x3a, + 0x05, 0xb5, 0xe3, 0x20, 0x76, 0xda, 0xe0, 0x94, 0x83, 0x35, 0xac, 0x3d, 0x65, 0x1c, + 0x6d, 0xbe, 0xa6, 0x4c, 0xe9, 0x11, 0x42, 0x3e, 0x2f, 0x2c, 0x7c, 0x1b, 0xdf, 0xa6, + 0xb1, 0x41, 0x41, 0x30, ], esk: [ - 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, 0x2c, 0xf1, 0xb8, 0x88, - 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, 0x98, 0x02, 0xf1, 0x53, - 0x6a, 0x9e, 0x9f, 0x2b, + 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, 0xfe, 0x47, 0x9a, 0x1e, + 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, 0x92, 0x3a, 0x5d, 0x00, + 0xcb, 0x52, 0xa6, 0x13, ], ephemeral_key: [ - 0x91, 0xaf, 0x13, 0x8e, 0xd9, 0x95, 0x44, 0x66, 0x95, 0x16, 0x1b, 0x14, 0x2d, 0xc2, - 0xde, 0x59, 0xac, 0x23, 0x05, 0xec, 0xbe, 0xc6, 0x29, 0x33, 0xf5, 0x2f, 0x2a, 0xa1, - 0xf9, 0xb2, 0x71, 0x86, + 0x86, 0xee, 0x66, 0xa6, 0xc7, 0xd9, 0xb5, 0xc4, 0xf0, 0xe2, 0xd2, 0xa0, 0xe1, 0x56, + 0x1e, 0x2a, 0xfa, 0x55, 0x41, 0xa7, 0x24, 0xee, 0x02, 0x7f, 0xc7, 0x0b, 0xb7, 0xe8, + 0x0a, 0x2c, 0x60, 0x98, ], shared_secret: [ - 0xe1, 0xd3, 0xaf, 0x73, 0x6a, 0xb9, 0xc6, 0x11, 0x6f, 0x46, 0x8f, 0x91, 0x66, 0x80, - 0x63, 0x20, 0x35, 0x0f, 0x7e, 0x73, 0x51, 0x3b, 0xa6, 0x05, 0x50, 0xeb, 0x2d, 0xf0, - 0x1f, 0xf7, 0x83, 0x2d, + 0x88, 0xd1, 0x38, 0x2c, 0x14, 0x42, 0x02, 0xd0, 0xd7, 0x55, 0x75, 0x87, 0xb0, 0xd5, + 0xd0, 0x21, 0x69, 0x29, 0x2a, 0x25, 0x05, 0x43, 0xcb, 0x0a, 0x06, 0xc3, 0x4f, 0x45, + 0x2f, 0x7b, 0x3b, 0x36, ], k_enc: [ - 0xb4, 0x3e, 0x43, 0x3e, 0x16, 0x45, 0xeb, 0x51, 0x5e, 0x4a, 0x4c, 0x7d, 0x10, 0xc9, - 0x3d, 0x08, 0xf2, 0xf1, 0xc3, 0x30, 0x95, 0xbf, 0x8c, 0x80, 0x0a, 0x04, 0x17, 0x62, - 0xab, 0x5c, 0xf8, 0x2c, + 0xe3, 0x73, 0xd8, 0x6e, 0xc9, 0xdd, 0xdd, 0x64, 0x5d, 0x9a, 0x6d, 0x06, 0xef, 0xce, + 0x22, 0xb8, 0x96, 0x42, 0x1d, 0x57, 0xa4, 0x4d, 0x37, 0xa6, 0x50, 0x4a, 0x5d, 0x19, + 0xdf, 0x21, 0x73, 0x73, ], p_enc: [ 0x02, 0xaa, 0x14, 0x92, 0x9c, 0x57, 0x89, 0x85, 0x85, 0xce, 0x66, 0x5a, 0xfa, 0x3f, @@ -801,68 +797,68 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x65, 0x57, 0x53, ], c_enc: [ - 0x27, 0x62, 0x0d, 0xf5, 0xdb, 0x17, 0x76, 0x6e, 0xbd, 0x9a, 0x99, 0xd6, 0x9a, 0x9a, - 0x49, 0x38, 0x73, 0x21, 0xf0, 0xc9, 0x47, 0x25, 0x23, 0x57, 0xb5, 0xb7, 0x48, 0x49, - 0x38, 0xe3, 0xf5, 0xff, 0x9f, 0x32, 0x0e, 0x80, 0x6c, 0x4b, 0x54, 0xc3, 0x6e, 0x41, - 0x2e, 0x8a, 0x6e, 0xad, 0xe3, 0x5b, 0x83, 0x01, 0xf7, 0x34, 0xf3, 0x71, 0x2e, 0x6a, - 0xac, 0xe6, 0x99, 0xf5, 0x9e, 0x11, 0x2a, 0x7b, 0xf5, 0x44, 0x59, 0xdc, 0x5d, 0x9f, - 0x7b, 0xbf, 0x3b, 0x9f, 0x74, 0x6c, 0x45, 0xbb, 0xed, 0x69, 0xa4, 0x25, 0x1b, 0x29, - 0xf3, 0xd2, 0x15, 0xc2, 0x9f, 0x76, 0x1c, 0x7d, 0x05, 0x88, 0x19, 0xf0, 0xdd, 0x4e, - 0x70, 0x71, 0xb0, 0x77, 0xcb, 0x00, 0xcb, 0x93, 0x62, 0xa4, 0x98, 0x16, 0x88, 0x0d, - 0x49, 0xb7, 0x11, 0xf9, 0x20, 0x65, 0xf1, 0x53, 0x2e, 0x58, 0x18, 0x0b, 0xbd, 0xb4, - 0x91, 0xdb, 0xbb, 0x96, 0x8a, 0x09, 0xb5, 0x63, 0xce, 0x1d, 0x29, 0x87, 0x6f, 0xd0, - 0x52, 0x6d, 0x65, 0xda, 0x67, 0x27, 0xad, 0x40, 0xf9, 0x64, 0x02, 0xf9, 0x9a, 0xa5, - 0xac, 0x06, 0x42, 0x51, 0xc4, 0x65, 0xe3, 0xc7, 0xdb, 0x1f, 0xfe, 0xef, 0xac, 0xd7, - 0xf5, 0x1b, 0xa4, 0xf1, 0x9c, 0x6c, 0x17, 0x87, 0xa0, 0xff, 0xb4, 0x9d, 0xbb, 0x7b, - 0x0a, 0x2b, 0x15, 0x64, 0x03, 0xd6, 0x6c, 0x22, 0x13, 0xe5, 0x1d, 0x58, 0xea, 0xef, - 0xe8, 0x6d, 0x5d, 0xef, 0x0d, 0x24, 0xb7, 0xf2, 0xf8, 0xc1, 0x10, 0x32, 0x9a, 0x3a, - 0x73, 0xcb, 0x33, 0x50, 0x14, 0x0e, 0x6b, 0xf7, 0x2c, 0xb6, 0xaa, 0x22, 0x2d, 0xef, - 0x5a, 0x47, 0xe2, 0x1a, 0xf0, 0xb9, 0xae, 0xeb, 0x74, 0x8c, 0x01, 0xc6, 0x7a, 0xb6, - 0xc9, 0xfd, 0x6e, 0x53, 0x6a, 0x0d, 0x92, 0x76, 0x61, 0x51, 0xb1, 0xac, 0x7c, 0xc9, - 0x85, 0x5c, 0xa9, 0x8d, 0xea, 0x74, 0x85, 0x14, 0xef, 0xee, 0x89, 0xe8, 0x9a, 0x01, - 0x68, 0xf5, 0xdd, 0xf4, 0xac, 0x2b, 0x7c, 0xe1, 0xc9, 0xc2, 0x92, 0xfb, 0xef, 0x2f, - 0x45, 0x51, 0xa8, 0x88, 0xc3, 0x34, 0x5c, 0x65, 0x92, 0x30, 0x39, 0xfc, 0x21, 0xf7, - 0x31, 0x55, 0x9b, 0xd9, 0x24, 0xbc, 0x2c, 0x15, 0x5b, 0xc0, 0xbe, 0x80, 0x38, 0x4a, - 0x9e, 0x49, 0xbd, 0xa6, 0x9a, 0x70, 0x6b, 0x1a, 0xd6, 0xa2, 0x62, 0xab, 0xc6, 0x26, - 0x50, 0x77, 0x2f, 0xd7, 0xea, 0xbc, 0x3f, 0x75, 0xa9, 0xac, 0xca, 0xa2, 0x8b, 0xcd, - 0xea, 0x65, 0xf9, 0x4e, 0x16, 0xcc, 0x3d, 0x05, 0x38, 0xe5, 0x49, 0x86, 0x0a, 0x60, - 0x12, 0x5b, 0xb4, 0xbc, 0x0c, 0x23, 0xe3, 0x22, 0x27, 0x68, 0x2c, 0x09, 0xb5, 0xaa, - 0x30, 0x4a, 0x16, 0x09, 0x2a, 0xd4, 0xa3, 0xe2, 0xf6, 0x28, 0x3c, 0x38, 0x51, 0x80, - 0x6e, 0x72, 0x17, 0x3f, 0x7d, 0x32, 0x97, 0xed, 0x92, 0xe5, 0x32, 0x40, 0x39, 0xa7, - 0x31, 0x4f, 0x5f, 0xb7, 0x38, 0x6e, 0x09, 0x94, 0xf5, 0x2f, 0x8c, 0xcc, 0xf1, 0x87, - 0xd6, 0x20, 0x41, 0x0c, 0xce, 0x9d, 0x0b, 0x91, 0x93, 0xac, 0xec, 0x6d, 0x4c, 0x9b, - 0xd3, 0x4e, 0x08, 0x80, 0x58, 0x0a, 0xbe, 0xae, 0xd9, 0x7c, 0xb7, 0x80, 0x0f, 0x6a, - 0xbc, 0x67, 0xc2, 0x5c, 0x49, 0x19, 0x2e, 0x37, 0xdc, 0xf3, 0x3d, 0x1a, 0x59, 0x16, - 0x47, 0x5a, 0xe9, 0x99, 0x90, 0xd8, 0x29, 0xc1, 0xd5, 0x9e, 0x69, 0x2f, 0x47, 0x36, - 0x93, 0xbc, 0xe3, 0x58, 0x5a, 0xec, 0xd3, 0xc1, 0x3b, 0xae, 0x15, 0xcb, 0xef, 0xf2, - 0x98, 0x52, 0x2a, 0xab, 0xf4, 0x6b, 0xea, 0x3a, 0xbf, 0x63, 0x30, 0xa5, 0x6e, 0x37, - 0x24, 0x51, 0x81, 0x32, 0xce, 0x94, 0x39, 0x41, 0x6a, 0x28, 0xe9, 0x52, 0x0d, 0xdf, - 0x64, 0x17, 0x00, 0xb4, 0x6f, 0x37, 0x49, 0x50, 0xf3, 0x27, 0xaf, 0x3d, 0x0b, 0x3d, - 0x3b, 0x3f, 0x61, 0xa8, 0x84, 0xcf, 0x4f, 0x82, 0x02, 0x56, 0xfb, 0x91, 0x65, 0xdc, - 0xa0, 0xe4, 0x32, 0x60, 0xfc, 0xb5, 0x63, 0xef, 0x1a, 0xb4, 0xe7, 0x12, 0xef, 0x07, - 0x23, 0xd6, 0x75, 0x90, 0xa4, 0xff, 0xc3, 0x66, 0xc4, 0xa7, 0x92, 0x50, 0x29, 0x93, - 0x1b, 0xf0, 0x87, 0x3d, 0xac, 0xaa, 0xe9, 0x38, 0x5d, 0x9a, 0xd9, 0x1a, 0xed, 0x75, - 0x93, 0x9d, 0x8b, 0xd1, 0xaf, 0x5d, + 0xe7, 0x67, 0x81, 0xae, 0x63, 0x84, 0x1f, 0xff, 0xea, 0x30, 0x21, 0x96, 0x15, 0x94, + 0xc2, 0x2a, 0x87, 0x20, 0xc7, 0xd8, 0xaa, 0x80, 0x8b, 0xc8, 0x6e, 0x71, 0xa3, 0x6a, + 0xd7, 0xf8, 0x6f, 0xf8, 0x7c, 0x07, 0xd3, 0xc6, 0x50, 0xa0, 0x8e, 0x23, 0xe9, 0xb5, + 0x4f, 0x00, 0xb4, 0x0b, 0xa0, 0x15, 0x91, 0x69, 0xdf, 0xca, 0x34, 0xc1, 0x40, 0xce, + 0x93, 0x40, 0x19, 0xb2, 0xea, 0xa8, 0xea, 0x84, 0x35, 0x80, 0xb3, 0x5f, 0x14, 0xea, + 0x51, 0x92, 0xde, 0x8a, 0x12, 0xf9, 0xab, 0xc9, 0x06, 0x10, 0x15, 0xe1, 0x47, 0x9e, + 0xf9, 0x8d, 0x19, 0xa5, 0x34, 0xe9, 0xe4, 0x61, 0x64, 0xc3, 0xca, 0xc4, 0xeb, 0x54, + 0x26, 0x4c, 0xed, 0xcd, 0x83, 0xaf, 0xc2, 0xac, 0x2e, 0x08, 0x7e, 0x39, 0xdf, 0xba, + 0xe7, 0x6b, 0xd5, 0x50, 0xcc, 0x64, 0xa4, 0x04, 0xd2, 0x0c, 0x22, 0xca, 0x00, 0x3b, + 0xf7, 0x5b, 0x12, 0xfb, 0xb8, 0xc7, 0x15, 0x13, 0x72, 0x70, 0x0b, 0x43, 0x9b, 0x3e, + 0x06, 0x57, 0xec, 0xc3, 0x07, 0x70, 0x8f, 0xc3, 0x74, 0x94, 0xbd, 0x06, 0x39, 0xe8, + 0xe1, 0xea, 0xea, 0x37, 0x8f, 0x27, 0xa1, 0x35, 0x74, 0xb7, 0x1f, 0xa4, 0x88, 0x3b, + 0x80, 0x71, 0x2c, 0x7b, 0xeb, 0x5c, 0x30, 0x5f, 0x8d, 0x67, 0xe9, 0x19, 0x97, 0xf8, + 0x03, 0x19, 0xdd, 0xb1, 0x15, 0xb9, 0x51, 0x23, 0x89, 0x7a, 0xae, 0x5f, 0x2d, 0x14, + 0xff, 0xcf, 0xac, 0x7f, 0x65, 0x49, 0xca, 0x54, 0x8f, 0x6e, 0xab, 0xdf, 0x74, 0x81, + 0x70, 0x27, 0xd4, 0x2d, 0x92, 0xd5, 0xcd, 0xf8, 0x8e, 0xd8, 0xd5, 0x11, 0xd1, 0xb5, + 0xc4, 0x32, 0x2f, 0x77, 0x79, 0x74, 0x88, 0x6c, 0x0e, 0xd0, 0x13, 0x99, 0x18, 0x0a, + 0xfa, 0x59, 0x7d, 0xd2, 0xb7, 0x7c, 0x58, 0xb2, 0x7c, 0x8a, 0x61, 0x20, 0x69, 0xe3, + 0x86, 0xad, 0x63, 0x4c, 0xb0, 0x17, 0xa8, 0xe9, 0xf4, 0x8e, 0x37, 0xc4, 0x3e, 0xe8, + 0x73, 0x3a, 0x0a, 0xcb, 0x69, 0xf8, 0xed, 0x9f, 0x6f, 0x30, 0x5f, 0x3b, 0xd1, 0xe9, + 0x82, 0xb9, 0x4b, 0x1e, 0x51, 0xf4, 0xba, 0x98, 0x5b, 0x20, 0xec, 0x97, 0x4a, 0xc9, + 0xa7, 0x93, 0xaa, 0x26, 0x4d, 0x61, 0x5b, 0x9d, 0xea, 0x48, 0x59, 0xa4, 0xd4, 0xca, + 0xa7, 0x0d, 0x7a, 0x6b, 0x65, 0x30, 0x76, 0x85, 0xab, 0x53, 0x4e, 0x54, 0x55, 0x63, + 0x1f, 0x6d, 0x68, 0xa4, 0x51, 0xd8, 0xaf, 0x2d, 0x41, 0x82, 0x52, 0x80, 0x0f, 0x68, + 0x42, 0x31, 0xaf, 0xc2, 0x6d, 0x1f, 0xef, 0xc4, 0x03, 0xd7, 0x5f, 0x2e, 0x12, 0x0f, + 0x5b, 0xe2, 0xb6, 0x74, 0x48, 0x60, 0x09, 0x26, 0x7c, 0xbc, 0x0c, 0xb0, 0x01, 0xbb, + 0x47, 0xf0, 0xff, 0x46, 0x97, 0xea, 0xf5, 0x3d, 0xc9, 0x9c, 0x10, 0x77, 0x3a, 0x38, + 0xcd, 0x06, 0xb4, 0x8b, 0xa3, 0x91, 0x19, 0xdb, 0x49, 0x84, 0xd0, 0x9a, 0x5b, 0xde, + 0x13, 0x89, 0x0e, 0xa0, 0x61, 0x3d, 0x0c, 0xe0, 0x04, 0x3e, 0xae, 0x9a, 0x20, 0x89, + 0x14, 0x1f, 0xd9, 0x46, 0x59, 0x13, 0xc1, 0xcc, 0x33, 0x27, 0xa5, 0x59, 0x42, 0xb9, + 0xfd, 0x8f, 0xb8, 0x1c, 0x84, 0x7d, 0x8f, 0xdd, 0xf8, 0xbd, 0xba, 0xcf, 0xa0, 0xfb, + 0x05, 0x52, 0xc1, 0xfe, 0x4c, 0xc4, 0xc0, 0x7f, 0x4d, 0xcf, 0x15, 0x1c, 0x5e, 0x74, + 0xe8, 0xd6, 0x9b, 0x2b, 0x8b, 0xf7, 0xfd, 0x95, 0xec, 0xeb, 0x65, 0x5e, 0x00, 0x53, + 0x58, 0x16, 0xd3, 0x8b, 0x4a, 0x28, 0xd4, 0xa9, 0xae, 0xeb, 0xb6, 0x9a, 0xb4, 0xdd, + 0x12, 0xbf, 0x13, 0xfd, 0x5a, 0x45, 0x9b, 0x6b, 0xb6, 0x83, 0xff, 0xd9, 0xdd, 0x7b, + 0x0d, 0x0c, 0xe7, 0x29, 0x67, 0x75, 0x80, 0x8a, 0x84, 0x3f, 0x3b, 0x8c, 0xc7, 0x89, + 0xfd, 0x5f, 0x43, 0xe0, 0x84, 0xd8, 0x7d, 0x6a, 0xda, 0x8d, 0x1f, 0x28, 0xc2, 0x64, + 0xe6, 0x44, 0xe9, 0xad, 0x96, 0x5c, 0x28, 0x08, 0x8a, 0x52, 0xe4, 0xb3, 0x56, 0x42, + 0xf9, 0xb5, 0xe0, 0x66, 0x49, 0x90, 0x96, 0x3b, 0xc2, 0x3b, 0x9b, 0xb4, 0x8f, 0x46, + 0x74, 0x73, 0x53, 0x58, 0x0e, 0xcc, 0x45, 0x20, 0xcf, 0xf1, 0xfa, 0x7f, 0x8f, 0xbc, + 0x03, 0x0e, 0x64, 0x7d, 0xf1, 0x44, 0xee, 0x6c, 0xa5, 0xb3, 0x16, 0xb3, 0xaf, 0x90, + 0x48, 0x9a, 0x80, 0x9d, 0x9c, 0x9f, ], ock: [ - 0x2a, 0xec, 0x11, 0xd4, 0xae, 0x79, 0x84, 0xe1, 0x69, 0xd1, 0xdf, 0xf1, 0xff, 0x0f, - 0x9a, 0xf5, 0x19, 0x96, 0x34, 0x51, 0xa4, 0x1c, 0x9f, 0x5a, 0xdc, 0x58, 0xe4, 0xf9, - 0x0a, 0xf3, 0x8d, 0x47, + 0x85, 0x6e, 0x1a, 0x97, 0x09, 0xb0, 0xc4, 0x16, 0x93, 0x3f, 0x59, 0x70, 0x71, 0x5c, + 0x56, 0xe2, 0xe0, 0x5c, 0x2e, 0xa9, 0x7d, 0x81, 0x51, 0x25, 0x70, 0x14, 0x79, 0xc3, + 0x3a, 0x5d, 0x91, 0xcb, ], op: [ 0x78, 0xa4, 0xe3, 0x39, 0x88, 0xd7, 0x1d, 0x71, 0x8e, 0x59, 0x55, 0x55, 0x28, 0x4c, 0x24, 0x9a, 0x62, 0xb7, 0x12, 0x88, 0x06, 0xa5, 0x4c, 0x3b, 0x36, 0xa3, 0xaa, 0x57, - 0x14, 0x93, 0x16, 0x36, 0x34, 0x39, 0x22, 0x52, 0xc9, 0xcc, 0x9f, 0x45, 0x4b, 0x54, - 0x2c, 0xf1, 0xb8, 0x88, 0xb3, 0xab, 0x02, 0xe6, 0x05, 0xa8, 0xda, 0x26, 0x10, 0x7d, - 0x98, 0x02, 0xf1, 0x53, 0x6a, 0x9e, 0x9f, 0x2b, + 0x14, 0x93, 0x16, 0x36, 0x8b, 0x14, 0x62, 0x2d, 0x2f, 0x91, 0xf1, 0x69, 0x8d, 0x53, + 0xfe, 0x47, 0x9a, 0x1e, 0x5c, 0x00, 0x64, 0x98, 0xb9, 0x8b, 0x85, 0xb4, 0x50, 0xbd, + 0x92, 0x3a, 0x5d, 0x00, 0xcb, 0x52, 0xa6, 0x13, ], c_out: [ - 0xe6, 0xeb, 0x22, 0x47, 0xc9, 0x33, 0xe2, 0x4c, 0x9d, 0xf1, 0x28, 0xb1, 0xe0, 0x4e, - 0x8b, 0xc0, 0x5c, 0x65, 0xeb, 0x31, 0x97, 0xdf, 0x9b, 0xa8, 0x70, 0xd8, 0xa0, 0xa1, - 0x8d, 0x9c, 0x24, 0xb7, 0xc9, 0x78, 0xc3, 0x4d, 0x3c, 0x7b, 0xbd, 0x21, 0xe8, 0x7b, - 0x22, 0x39, 0x21, 0x87, 0x54, 0xd9, 0x67, 0x3a, 0x56, 0xa2, 0x73, 0x58, 0x0f, 0x6b, - 0x41, 0xc6, 0x91, 0xe5, 0xfd, 0x30, 0x9c, 0xd5, 0xd1, 0xd2, 0x6d, 0x57, 0x63, 0xa9, - 0xe8, 0xd2, 0x71, 0xc9, 0x77, 0x05, 0x0e, 0x05, 0xdc, 0x96, + 0x72, 0x36, 0xea, 0xb9, 0xf0, 0x12, 0x98, 0xc8, 0x4f, 0x38, 0x28, 0xf6, 0xac, 0x15, + 0x42, 0x76, 0xb5, 0xb7, 0x64, 0x62, 0xf5, 0x74, 0x2d, 0x69, 0xdc, 0x47, 0x7a, 0x10, + 0x5d, 0xc2, 0x71, 0x1b, 0x12, 0xe9, 0xb5, 0x82, 0x8c, 0x01, 0x76, 0xfe, 0xf4, 0x4a, + 0x54, 0x0f, 0x60, 0x95, 0x8e, 0x5a, 0x3e, 0xd6, 0xa2, 0xcc, 0x5e, 0xdd, 0xe9, 0x13, + 0xd1, 0x4c, 0xf8, 0xe8, 0xe2, 0x8e, 0xa2, 0x5c, 0x18, 0x62, 0x7a, 0x84, 0xa2, 0xbe, + 0x96, 0x1f, 0x44, 0x72, 0x67, 0x67, 0xe9, 0xf8, 0x43, 0x1b, ], }, TestVector { @@ -936,36 +932,35 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x95, 0x89, 0xbe, 0x69, 0xd8, 0x28, 0xbe, 0x54, 0x30, 0x69, 0x16, 0x41, 0x3c, 0xd2, 0x50, 0x21, 0x17, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0x23, 0x39, 0xa8, 0x95, 0x29, 0xcf, 0x35, 0x7b, 0x06, 0x7d, 0xd2, 0x8b, 0xe4, 0x06, - 0x6e, 0x16, 0x23, 0x6d, 0xc5, 0xd7, 0x87, 0x06, 0x14, 0x9a, 0x72, 0x8c, 0x3e, 0x3d, - 0x9d, 0xc1, 0x08, 0x1c, + 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, + 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, + 0x3c, 0xfb, 0xf1, 0x31, ], cmx: [ - 0xe3, 0x04, 0xcf, 0x08, 0xc7, 0x86, 0xaf, 0xcb, 0x1d, 0x65, 0x2f, 0x7a, 0x94, 0x17, - 0x29, 0x32, 0x01, 0x51, 0x71, 0x37, 0x93, 0x82, 0x89, 0x42, 0xcb, 0x88, 0xd0, 0x1f, - 0x68, 0x60, 0x4e, 0x1f, + 0xea, 0x7c, 0x13, 0xf7, 0xe1, 0x20, 0x5e, 0x78, 0xc8, 0xce, 0x4e, 0xe4, 0xfd, 0xcd, + 0xb7, 0xee, 0x76, 0x92, 0x8d, 0xdf, 0x6d, 0xbe, 0x1b, 0x2d, 0x6f, 0x69, 0x81, 0xb7, + 0xc9, 0x65, 0x79, 0x10, ], esk: [ - 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, 0x40, 0xaf, 0x89, 0x3e, - 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, 0x6b, 0x5e, 0xd1, 0xf6, - 0xbf, 0x62, 0xbe, 0x3c, + 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, 0x73, 0xe9, 0x05, 0x99, + 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, 0x89, 0xcc, 0x63, 0x00, + 0x06, 0x15, 0xb2, 0x0d, ], ephemeral_key: [ - 0xdf, 0xe0, 0xf0, 0x0e, 0xb2, 0xb2, 0xf7, 0x08, 0x04, 0x19, 0x1b, 0x5b, 0x2d, 0xdf, - 0x57, 0x8f, 0x6a, 0xda, 0x21, 0x1b, 0x8b, 0x41, 0x7d, 0x95, 0xd2, 0xb7, 0x34, 0xff, - 0xa2, 0x2d, 0x81, 0x30, + 0x89, 0xfd, 0x2c, 0xf3, 0x79, 0x56, 0xba, 0xaf, 0x11, 0x27, 0xbb, 0x0e, 0x33, 0x40, + 0x01, 0x09, 0xdb, 0x03, 0x50, 0xf4, 0xab, 0xb7, 0xd6, 0xd8, 0x1f, 0xa5, 0x84, 0x8e, + 0x1b, 0xb1, 0x69, 0x26, ], shared_secret: [ - 0x0e, 0xc6, 0x82, 0xc8, 0xdc, 0x66, 0x41, 0x41, 0x02, 0x4f, 0x92, 0x9d, 0x1a, 0xe5, - 0xd3, 0x9c, 0x39, 0x4d, 0x05, 0xa2, 0x4d, 0xad, 0x0e, 0x4a, 0x6f, 0x94, 0x98, 0xed, - 0x5f, 0x87, 0xd4, 0x88, + 0xdb, 0xa6, 0x37, 0x94, 0xb6, 0x7c, 0x49, 0x6d, 0x01, 0x1c, 0xfb, 0x6b, 0xba, 0x29, + 0x7c, 0xa5, 0x7d, 0x18, 0xc7, 0xa9, 0xad, 0xdf, 0xfb, 0xc8, 0x37, 0x17, 0x6a, 0xcf, + 0x3a, 0x30, 0x1e, 0x23, ], k_enc: [ - 0xb1, 0x24, 0x5f, 0xb6, 0x37, 0x47, 0xc0, 0x13, 0x39, 0xcd, 0xe8, 0xf9, 0x35, 0x98, - 0xdf, 0xb2, 0xd3, 0x99, 0xec, 0x5e, 0x03, 0xbe, 0xa1, 0x3f, 0x3d, 0xbf, 0x01, 0xca, - 0xdb, 0x93, 0xc9, 0xba, + 0x80, 0xe7, 0x52, 0x2c, 0xb0, 0x32, 0x51, 0xc8, 0x55, 0x34, 0x1f, 0x06, 0xf9, 0x41, + 0x33, 0x41, 0xe1, 0x6e, 0x83, 0xb4, 0x89, 0xe1, 0x5a, 0x0a, 0x00, 0x65, 0xc3, 0x3b, + 0xf3, 0x81, 0x58, 0xc4, ], p_enc: [ 0x02, 0xe0, 0x66, 0xb5, 0xe7, 0x96, 0x86, 0xe9, 0xf3, 0x6e, 0xce, 0xc7, 0x7e, 0x65, @@ -1011,68 +1006,68 @@ pub(crate) fn test_vectors() -> Vec { 0xd7, 0x6b, 0xa4, 0x80, ], c_enc: [ - 0x31, 0xec, 0x78, 0xd4, 0x02, 0x14, 0xc1, 0xbc, 0x7b, 0x25, 0x94, 0x7b, 0x42, 0xf3, - 0x54, 0x34, 0x60, 0x72, 0x90, 0x27, 0x7c, 0x44, 0xc4, 0x89, 0xe9, 0x38, 0x72, 0x2f, - 0x7c, 0x12, 0xff, 0x55, 0xc4, 0xf1, 0xdf, 0xbe, 0x0f, 0x1a, 0x65, 0xb1, 0x5c, 0x0c, - 0xc4, 0x7a, 0x46, 0xc9, 0xbb, 0x33, 0x5b, 0xd1, 0xa3, 0xe7, 0xe6, 0x62, 0xee, 0x85, - 0x84, 0x57, 0x6b, 0x6f, 0x42, 0x81, 0x95, 0xc9, 0x8c, 0x72, 0xfb, 0x99, 0x75, 0xc7, - 0x17, 0x9c, 0x4c, 0xab, 0x58, 0x66, 0xf5, 0xb4, 0x85, 0x42, 0x8b, 0x50, 0x8e, 0x2e, - 0x05, 0xbe, 0x0c, 0x98, 0x41, 0xa3, 0xa2, 0x91, 0x12, 0x80, 0x2c, 0x52, 0x15, 0xe2, - 0x51, 0x37, 0xcf, 0xdd, 0x13, 0x8c, 0x99, 0x39, 0x0e, 0xfb, 0xce, 0xb7, 0x52, 0x4e, - 0x84, 0x7c, 0x36, 0xb4, 0x3f, 0x3e, 0xde, 0x32, 0xf2, 0x3b, 0x39, 0x81, 0xf6, 0xd3, - 0xc3, 0x2b, 0x17, 0xbb, 0xbe, 0x65, 0xf2, 0xfd, 0x01, 0xab, 0xdd, 0x99, 0x87, 0xf1, - 0xb8, 0x88, 0xeb, 0xef, 0x41, 0xef, 0x45, 0x55, 0xc9, 0xfb, 0x0c, 0x8a, 0xee, 0x9b, - 0x6d, 0xd0, 0x85, 0xb9, 0xfb, 0xc7, 0x4f, 0xe4, 0x6a, 0x1e, 0x36, 0x3d, 0x68, 0x32, - 0xb5, 0x08, 0x20, 0x0e, 0x50, 0x0d, 0xa6, 0x95, 0x13, 0xb7, 0x9e, 0x81, 0xf7, 0x33, - 0xb6, 0x6c, 0x3f, 0x24, 0x3a, 0x28, 0x5b, 0xf8, 0x6f, 0xfe, 0xef, 0x4f, 0xfd, 0x1c, - 0xac, 0xa7, 0x83, 0x07, 0x26, 0x63, 0xbf, 0x9b, 0x48, 0x7f, 0xbc, 0x3e, 0x7f, 0x5a, - 0xd2, 0xf7, 0xac, 0xbf, 0x2b, 0x6e, 0x00, 0x8e, 0x3e, 0x4d, 0x6f, 0x31, 0xe1, 0x14, - 0x75, 0xe1, 0x96, 0x98, 0x9d, 0xb9, 0x62, 0x8a, 0x5d, 0x56, 0x39, 0x7c, 0x9a, 0x04, - 0x2a, 0xab, 0x55, 0xe1, 0xec, 0xc4, 0x92, 0xfe, 0x94, 0x27, 0xd4, 0x90, 0xf2, 0x73, - 0xb6, 0x01, 0xd6, 0x51, 0x05, 0x56, 0x82, 0xd3, 0x5b, 0x30, 0x75, 0xfa, 0xda, 0x85, - 0x25, 0x84, 0x48, 0x14, 0x95, 0x7f, 0xfc, 0x9b, 0xc7, 0xfb, 0x39, 0x39, 0x73, 0x7b, - 0x01, 0x50, 0x2e, 0x0b, 0x6f, 0x1f, 0x9b, 0x88, 0xf2, 0x71, 0x54, 0x80, 0xae, 0x42, - 0x2e, 0x9b, 0xb7, 0xb7, 0x6e, 0x5d, 0x22, 0xde, 0x0d, 0x3d, 0x7a, 0xea, 0x58, 0x10, - 0x01, 0xdc, 0xf4, 0x6a, 0x62, 0x2f, 0x08, 0x03, 0x10, 0xbe, 0x50, 0xdf, 0x07, 0x75, - 0x21, 0x92, 0xd4, 0xe4, 0x1a, 0xc5, 0x18, 0xe4, 0x24, 0x1e, 0x06, 0x67, 0x76, 0xa8, - 0xea, 0xec, 0xc7, 0x42, 0xfd, 0x2c, 0x1b, 0xf0, 0x6f, 0xc5, 0x8b, 0xd2, 0x8d, 0x1d, - 0x6c, 0x60, 0x1f, 0x91, 0x5d, 0x75, 0x2e, 0x7c, 0xc3, 0xd9, 0x76, 0x3c, 0x8b, 0x9e, - 0xec, 0x14, 0x2c, 0x84, 0x81, 0xf9, 0xc5, 0x23, 0x59, 0xbf, 0xbf, 0x51, 0x24, 0x36, - 0x67, 0x84, 0xe1, 0x71, 0xd7, 0xa4, 0xaa, 0x01, 0x5e, 0x85, 0x56, 0x47, 0x4a, 0x6d, - 0x0f, 0xee, 0x69, 0xb0, 0xd5, 0x3e, 0xe7, 0xf4, 0xed, 0xf5, 0xea, 0x59, 0xfa, 0x55, - 0x97, 0xf4, 0x8d, 0xd6, 0xaa, 0x88, 0x51, 0x84, 0x29, 0xac, 0x8c, 0x18, 0xc4, 0x73, - 0x8d, 0xb8, 0x01, 0x09, 0xa5, 0xe4, 0xbc, 0x81, 0xbb, 0x84, 0xb3, 0x7d, 0x9b, 0x2a, - 0xd4, 0xb1, 0xd2, 0x6b, 0x36, 0x3d, 0x16, 0x60, 0x72, 0xf0, 0x8c, 0x56, 0x70, 0x62, - 0x27, 0xa9, 0xf8, 0x32, 0x97, 0x03, 0x70, 0x12, 0xd1, 0xf6, 0xda, 0x24, 0xa8, 0x69, - 0xeb, 0x32, 0x97, 0xbc, 0xbc, 0xcc, 0x8d, 0x7d, 0xed, 0x03, 0x0a, 0x3d, 0x60, 0xdf, - 0x88, 0x82, 0xe0, 0x62, 0x9e, 0x36, 0x14, 0x3c, 0x09, 0xca, 0x05, 0x21, 0x43, 0xcb, - 0x56, 0x62, 0x93, 0x8f, 0xa9, 0xf1, 0x15, 0xdd, 0xc0, 0x96, 0x65, 0x4c, 0x0b, 0x40, - 0x59, 0x4c, 0xba, 0x19, 0xee, 0xd4, 0x99, 0x53, 0x2b, 0x70, 0x8a, 0xde, 0xbe, 0x47, - 0x72, 0x6a, 0x83, 0xaf, 0x46, 0x3c, 0x80, 0xba, 0x2a, 0x1f, 0xe0, 0x71, 0xe1, 0x66, - 0xc4, 0x4d, 0x70, 0xdd, 0xbb, 0xba, 0x67, 0x06, 0xa1, 0xdc, 0x43, 0x27, 0x26, 0xfe, - 0x0f, 0xdb, 0xc6, 0x28, 0x21, 0xb5, 0x04, 0xea, 0x11, 0x66, 0xda, 0x48, 0xa8, 0x1b, - 0x63, 0x5e, 0x37, 0x63, 0x33, 0xd9, 0xbe, 0xfe, 0xc4, 0x93, 0xa0, 0x7d, 0xf4, 0x7b, - 0xba, 0x0a, 0x2e, 0x2f, 0x65, 0xe7, + 0x3f, 0x4e, 0x9b, 0x18, 0x56, 0xe7, 0xbf, 0xba, 0x7a, 0xbb, 0xc9, 0x4a, 0x72, 0xb4, + 0xab, 0xb1, 0xd8, 0x46, 0x26, 0x79, 0x30, 0x77, 0xe8, 0x37, 0xda, 0xf3, 0x3f, 0xff, + 0xa2, 0x7c, 0x7a, 0x33, 0x97, 0x8a, 0x54, 0x32, 0x51, 0x0d, 0x99, 0x3c, 0x7d, 0x92, + 0x24, 0xc0, 0x97, 0xac, 0xc5, 0x25, 0x88, 0x1c, 0x76, 0x08, 0x3c, 0x1b, 0x65, 0x1a, + 0x9d, 0xe1, 0xb5, 0xc1, 0xa6, 0xe0, 0x48, 0x2f, 0xae, 0x8f, 0x98, 0x6a, 0xb5, 0x9f, + 0xa7, 0xcd, 0x43, 0x98, 0x99, 0x6e, 0x2b, 0xc0, 0x3a, 0xdc, 0xa9, 0x90, 0x32, 0x3b, + 0xaa, 0xbd, 0xda, 0xae, 0x40, 0xb0, 0x56, 0xb7, 0xac, 0x17, 0xf8, 0x20, 0xd1, 0x1c, + 0x0d, 0xec, 0xba, 0x14, 0xf2, 0x57, 0xa6, 0xcf, 0x09, 0x18, 0x19, 0x8f, 0x38, 0x9c, + 0xdb, 0x29, 0x55, 0x77, 0x25, 0x96, 0x92, 0x7c, 0xbf, 0x55, 0x88, 0x56, 0x13, 0x35, + 0xe7, 0xd6, 0x2e, 0x6a, 0x8a, 0xf7, 0xbc, 0x33, 0xb9, 0x9a, 0x55, 0xaf, 0xa1, 0xb7, + 0xef, 0x20, 0xeb, 0x4e, 0xd6, 0xde, 0x89, 0x69, 0xd2, 0x9f, 0x04, 0x21, 0xcd, 0x4d, + 0x99, 0x06, 0x66, 0xfd, 0xcf, 0x1e, 0xbd, 0x09, 0x06, 0x57, 0x02, 0x13, 0x4d, 0x31, + 0xc3, 0x29, 0x26, 0xa3, 0x8b, 0x6b, 0x6b, 0x48, 0xfd, 0xc9, 0xb3, 0xc7, 0x64, 0xc3, + 0xcd, 0x95, 0xb9, 0x72, 0xe7, 0x68, 0xeb, 0xd8, 0xaa, 0xe9, 0x0d, 0x6a, 0x4a, 0x98, + 0xb2, 0xd9, 0x2f, 0xd9, 0xdf, 0xa2, 0xa2, 0x99, 0xd0, 0x60, 0xe8, 0x5e, 0xf5, 0x68, + 0x3f, 0x51, 0xd0, 0x51, 0x4a, 0x6e, 0xba, 0x72, 0x57, 0x3f, 0x7b, 0xae, 0x84, 0xa2, + 0xfd, 0x92, 0xbe, 0x64, 0x24, 0x1c, 0x27, 0xa6, 0xe5, 0xce, 0xac, 0xbf, 0x37, 0xb2, + 0xd9, 0xa9, 0x75, 0xdf, 0x7a, 0xee, 0xbb, 0xa1, 0x4d, 0x8c, 0x81, 0x15, 0x8e, 0xcf, + 0x5a, 0x0a, 0x25, 0xe1, 0x2f, 0x98, 0x5d, 0x08, 0xfb, 0xb4, 0xa1, 0xc1, 0x3f, 0x76, + 0x1f, 0x3f, 0xfe, 0xe8, 0xd5, 0x38, 0xe3, 0x93, 0xf3, 0x58, 0x0b, 0x73, 0x82, 0xcd, + 0x0b, 0xf5, 0x17, 0xce, 0x78, 0x87, 0x1c, 0x19, 0xac, 0xf8, 0xca, 0x06, 0x5d, 0x7c, + 0x83, 0x87, 0xce, 0xcd, 0x0d, 0x37, 0xae, 0x21, 0x7f, 0x44, 0x06, 0x94, 0x77, 0x2a, + 0xbd, 0x4b, 0x36, 0x55, 0x56, 0x85, 0x4b, 0xaa, 0x8b, 0xcc, 0xa9, 0xc4, 0xfe, 0xf7, + 0x18, 0x99, 0x12, 0xf9, 0x8a, 0x25, 0x27, 0x68, 0x92, 0x76, 0xa4, 0x00, 0x8c, 0x83, + 0x8f, 0xe7, 0x4f, 0x7c, 0x2b, 0x75, 0x9f, 0xc2, 0xab, 0x7a, 0xfe, 0x37, 0x82, 0x80, + 0x6e, 0x31, 0xb1, 0xc5, 0x30, 0xcc, 0x46, 0x20, 0x3b, 0xb3, 0xa5, 0x66, 0xca, 0xf4, + 0xd1, 0x5b, 0x99, 0x40, 0xb4, 0x3f, 0x33, 0xa8, 0x6a, 0x65, 0xd4, 0x9d, 0xa8, 0xb6, + 0x78, 0x7d, 0xe0, 0x96, 0x38, 0xb4, 0x81, 0xf3, 0xa8, 0x10, 0x8a, 0x96, 0x9e, 0xca, + 0xdf, 0x90, 0x98, 0xbf, 0xf2, 0x14, 0x0c, 0x4b, 0x42, 0xe2, 0xb0, 0xfb, 0x10, 0xb9, + 0x02, 0x89, 0xb0, 0xc6, 0xdb, 0x8b, 0xc0, 0x85, 0xe8, 0xaf, 0xe9, 0x5d, 0xd3, 0x6a, + 0x45, 0x36, 0xea, 0xd7, 0xe9, 0x5c, 0x99, 0x66, 0x2c, 0xd9, 0x28, 0xc2, 0x2c, 0x3e, + 0xbf, 0x39, 0x79, 0x15, 0x78, 0xbc, 0x66, 0xfe, 0xa3, 0x01, 0x4d, 0x22, 0x92, 0x94, + 0x30, 0x83, 0xe7, 0x46, 0x81, 0x24, 0x52, 0xb0, 0x0b, 0xc2, 0xf3, 0xe4, 0x7c, 0x49, + 0x47, 0x46, 0xce, 0xd5, 0x57, 0xb1, 0x3a, 0xe3, 0x03, 0x0d, 0x8a, 0x95, 0x78, 0x10, + 0x2b, 0xba, 0xd2, 0xfc, 0x3b, 0x84, 0x5f, 0x31, 0xae, 0x16, 0xf8, 0xd8, 0x0b, 0x77, + 0xf8, 0x43, 0x15, 0x84, 0xa3, 0x7e, 0x8f, 0x30, 0xb0, 0xb9, 0x5c, 0xc4, 0x55, 0x5a, + 0xbc, 0x05, 0x3a, 0x0b, 0x4f, 0xf9, 0x13, 0xb0, 0x03, 0x69, 0xf1, 0x74, 0x7b, 0x1f, + 0x1c, 0x0a, 0xc8, 0x75, 0x4f, 0x01, 0x7e, 0x99, 0x47, 0xca, 0x63, 0x25, 0x5b, 0x3c, + 0x23, 0xf4, 0x56, 0xe2, 0x3f, 0x96, 0x76, 0x13, 0x99, 0x60, 0x1f, 0xd8, 0xda, 0xdb, + 0x5e, 0x3f, 0x90, 0xab, 0x1b, 0x20, 0x13, 0x81, 0x80, 0xed, 0x69, 0x73, 0x22, 0x39, + 0xc8, 0xc2, 0x15, 0xd9, 0xcc, 0x8a, 0xc8, 0x05, 0x9b, 0xde, 0x81, 0x63, 0x27, 0xd2, + 0x20, 0xb9, 0xa8, 0xec, 0xba, 0x5d, ], ock: [ - 0xec, 0xa3, 0x70, 0x7a, 0x74, 0x5d, 0x5d, 0x58, 0x65, 0x86, 0xb2, 0x35, 0xf2, 0x92, - 0xad, 0x20, 0x48, 0x93, 0x14, 0xc4, 0x58, 0x80, 0xd9, 0x83, 0x2b, 0x7f, 0x47, 0xee, - 0xbb, 0xd4, 0x5c, 0xfe, + 0xe6, 0xb7, 0x05, 0x50, 0xe1, 0xd7, 0xa2, 0xbe, 0x73, 0x04, 0x39, 0x64, 0x41, 0xec, + 0x6a, 0xc0, 0x47, 0x45, 0x99, 0xf9, 0xea, 0xd7, 0x55, 0xc2, 0xcf, 0x27, 0x6b, 0x87, + 0x50, 0xc5, 0xcf, 0x2d, ], op: [ 0x3b, 0x3e, 0x88, 0x3e, 0x95, 0x8c, 0xd6, 0xe0, 0x75, 0x4d, 0x74, 0xca, 0xae, 0x1e, 0x5a, 0x43, 0x98, 0xab, 0xeb, 0x7d, 0x10, 0xee, 0x5f, 0x75, 0xa4, 0xab, 0x8e, 0xf7, - 0x03, 0x8e, 0x3d, 0xb3, 0x0f, 0xba, 0x68, 0x76, 0xb3, 0x76, 0x5d, 0xff, 0x4f, 0x4c, - 0x40, 0xaf, 0x89, 0x3e, 0x4b, 0xd1, 0x34, 0x3a, 0x53, 0x4c, 0xdf, 0x50, 0x20, 0x15, - 0x6b, 0x5e, 0xd1, 0xf6, 0xbf, 0x62, 0xbe, 0x3c, + 0x03, 0x8e, 0x3d, 0xb3, 0x85, 0x7b, 0xa2, 0x47, 0xd4, 0x68, 0xe1, 0x8d, 0xfe, 0x96, + 0x73, 0xe9, 0x05, 0x99, 0x23, 0xc2, 0x2e, 0x9b, 0x70, 0x0d, 0x56, 0x3d, 0xf8, 0xa9, + 0x89, 0xcc, 0x63, 0x00, 0x06, 0x15, 0xb2, 0x0d, ], c_out: [ - 0xd0, 0x65, 0x9a, 0x03, 0xc5, 0x3e, 0x15, 0xdc, 0x11, 0x01, 0xa6, 0x6e, 0xa8, 0x0d, - 0xf4, 0x14, 0x4d, 0x5e, 0xe0, 0x1c, 0x3d, 0xbf, 0x20, 0x2c, 0xe6, 0x08, 0x7e, 0x96, - 0xa8, 0x5a, 0xe1, 0x39, 0xdd, 0x46, 0xfc, 0x82, 0xa1, 0xc3, 0x7d, 0x06, 0x05, 0xf8, - 0x49, 0x98, 0x53, 0x13, 0x16, 0xf1, 0xf0, 0xcb, 0xc0, 0x4e, 0xa2, 0x0a, 0xa4, 0x04, - 0xb3, 0xd5, 0xb0, 0x42, 0x96, 0x01, 0x49, 0x81, 0x6d, 0x9b, 0x8f, 0x06, 0x2a, 0xfc, - 0xc1, 0x93, 0x89, 0x43, 0x82, 0x7a, 0x1b, 0x43, 0xfc, 0xbd, + 0x02, 0xb1, 0x37, 0x3e, 0xb1, 0x89, 0x56, 0x32, 0x2b, 0x47, 0xa1, 0x70, 0x0d, 0xb7, + 0x43, 0x31, 0x6e, 0xde, 0x46, 0x44, 0xd6, 0x59, 0x3c, 0xd7, 0x94, 0x22, 0xd7, 0x51, + 0x3d, 0x1b, 0x80, 0xe6, 0x85, 0x05, 0xdf, 0xe9, 0xd6, 0x86, 0x2e, 0x79, 0x4e, 0x30, + 0x28, 0x8b, 0xae, 0xa8, 0xb0, 0xbc, 0xb3, 0x8b, 0x35, 0x49, 0x77, 0xaa, 0xee, 0x57, + 0x2e, 0xe8, 0x86, 0x8b, 0x2d, 0xa0, 0x7d, 0xa2, 0x99, 0x2c, 0x6d, 0x9f, 0xb8, 0xbd, + 0x59, 0x0b, 0x8d, 0xa0, 0x28, 0x11, 0xb5, 0x09, 0xe8, 0xc6, ], }, TestVector { @@ -1146,36 +1141,35 @@ pub(crate) fn test_vectors() -> Vec { 0x6e, 0x62, 0xe4, 0xed, 0xc7, 0x86, 0xd9, 0xe0, 0xb2, 0x7d, 0x26, 0x62, 0x8b, 0x79, 0xda, 0x6b, 0x15, 0x14, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0xe5, 0xd0, 0x8c, 0x40, 0x26, 0x3e, 0x4a, 0x2a, 0x56, 0x96, 0xda, 0x21, 0x0d, 0x8e, - 0x9a, 0x77, 0xf0, 0xaf, 0xc4, 0xc6, 0x8a, 0x6d, 0xda, 0x38, 0xe2, 0x85, 0xf4, 0xe3, - 0xef, 0x13, 0xb8, 0x17, + 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, + 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, + 0x21, 0x38, 0xab, 0x29, ], cmx: [ - 0xad, 0xc2, 0x44, 0x3a, 0xf9, 0x57, 0x67, 0x47, 0xca, 0x4f, 0x10, 0x4b, 0x1f, 0x5a, - 0x7a, 0xdc, 0x80, 0x5a, 0xc5, 0x5a, 0xcc, 0x56, 0x33, 0xa0, 0xb3, 0xc2, 0xdc, 0x7a, - 0xad, 0xff, 0x21, 0x26, + 0x18, 0xfc, 0xbd, 0x40, 0xac, 0xf1, 0xa7, 0xf4, 0xd6, 0x09, 0x87, 0x9a, 0x5f, 0x5e, + 0x3b, 0x39, 0x70, 0x09, 0x4f, 0xf8, 0xbe, 0x84, 0x18, 0x60, 0x70, 0x16, 0xc6, 0xa6, + 0x97, 0xf8, 0x9c, 0x20, ], esk: [ - 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, 0x82, 0x35, 0x16, 0x58, - 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, 0xb0, 0x52, 0xd5, 0xb4, - 0x20, 0x41, 0xd8, 0x1c, + 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, 0x6b, 0x8d, 0x6f, 0xea, + 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, 0xd5, 0xcb, 0xab, 0x1a, + 0xcc, 0xd5, 0x4e, 0x3a, ], ephemeral_key: [ - 0x00, 0x5d, 0x31, 0x5b, 0xd1, 0x80, 0xa2, 0x94, 0x0b, 0xd7, 0xfb, 0x34, 0xa7, 0x0e, - 0x90, 0xe8, 0x32, 0x6c, 0xb1, 0x34, 0x30, 0x66, 0x05, 0x46, 0x53, 0xd2, 0x64, 0x4d, - 0x20, 0x45, 0xe3, 0x0f, + 0xcf, 0xe0, 0x3e, 0xb2, 0xd3, 0x36, 0x76, 0xb7, 0x73, 0x83, 0x7d, 0xa8, 0x39, 0x17, + 0x2d, 0x33, 0x33, 0x31, 0x88, 0xc9, 0xdf, 0xef, 0x05, 0xc8, 0x32, 0xa2, 0x5c, 0x86, + 0xd3, 0xbf, 0x0e, 0x8f, ], shared_secret: [ - 0x8e, 0x59, 0x0d, 0x06, 0x3f, 0x7e, 0xc3, 0x8e, 0xb2, 0x00, 0x84, 0x70, 0xf9, 0xbb, - 0x42, 0x29, 0x04, 0xfc, 0x0b, 0xaf, 0x97, 0x80, 0xf8, 0xfd, 0x1f, 0x54, 0x22, 0xea, - 0x30, 0x8c, 0x47, 0xba, + 0xd2, 0xc2, 0x88, 0x9e, 0x03, 0x7e, 0xac, 0x60, 0x60, 0x58, 0x68, 0x2b, 0xaa, 0x38, + 0x86, 0xa4, 0xc2, 0xdd, 0x44, 0xea, 0xdf, 0x8b, 0x2c, 0xe4, 0x39, 0x95, 0xde, 0xd7, + 0x61, 0xfd, 0xaf, 0xb5, ], k_enc: [ - 0xeb, 0xb2, 0xff, 0x9b, 0x1f, 0x29, 0x0d, 0xa5, 0x63, 0x27, 0xa9, 0x67, 0x71, 0xb2, - 0x5f, 0x71, 0x29, 0xff, 0x10, 0x2e, 0xe6, 0xd2, 0xb2, 0x0d, 0xa0, 0x9a, 0x06, 0x25, - 0xf8, 0xbb, 0x26, 0x07, + 0xfe, 0xe3, 0xe3, 0xb5, 0xfd, 0x6c, 0xd8, 0x54, 0x44, 0x2b, 0x2a, 0xc2, 0x97, 0x70, + 0xfb, 0x0e, 0x39, 0x32, 0xf4, 0x71, 0x52, 0x43, 0x26, 0xda, 0x4a, 0x57, 0xc2, 0x56, + 0x18, 0x06, 0x9e, 0x99, ], p_enc: [ 0x02, 0x1c, 0xa7, 0xb6, 0x49, 0x39, 0x9e, 0x13, 0xe4, 0x39, 0x44, 0x62, 0x91, 0x20, @@ -1221,68 +1215,68 @@ pub(crate) fn test_vectors() -> Vec { 0x34, 0x1e, 0x4e, 0x6f, ], c_enc: [ - 0x96, 0x3b, 0xe3, 0x6e, 0xdc, 0xa4, 0x8b, 0x7c, 0x4a, 0x1c, 0xd6, 0xa1, 0x37, 0x2e, - 0x84, 0xc0, 0x54, 0x54, 0x83, 0x4c, 0x5e, 0xe1, 0x92, 0x5e, 0xed, 0xeb, 0x48, 0xda, - 0x16, 0x77, 0x79, 0xe3, 0x99, 0x83, 0x58, 0xcb, 0x92, 0x7a, 0x0a, 0x0b, 0x36, 0x9c, - 0x85, 0xee, 0xb3, 0x30, 0xf7, 0x00, 0x5c, 0x26, 0x9d, 0x0b, 0xe4, 0xf2, 0x38, 0x09, - 0x57, 0xb1, 0x62, 0x97, 0x7c, 0xae, 0x7a, 0x7b, 0x1d, 0x0b, 0xe5, 0xd0, 0xb7, 0x03, - 0xd3, 0x92, 0xac, 0xae, 0xd2, 0x4f, 0x52, 0x5b, 0x83, 0xcf, 0xdd, 0x7f, 0x35, 0xc1, - 0xf1, 0x74, 0xbf, 0x06, 0x6b, 0x7a, 0xfd, 0xb7, 0x45, 0xed, 0xbe, 0xdc, 0x0b, 0x46, - 0xa5, 0x91, 0x36, 0x21, 0x47, 0x61, 0x9d, 0x6b, 0xd3, 0xf3, 0xce, 0x6b, 0x45, 0x23, - 0xf0, 0x64, 0x9a, 0x7c, 0x65, 0x32, 0x2d, 0x05, 0xfa, 0xe2, 0x22, 0x70, 0x1a, 0x8c, - 0xd6, 0xca, 0xbf, 0x8d, 0xc3, 0x2f, 0x05, 0x5f, 0xeb, 0x14, 0x1e, 0x55, 0x6d, 0xdf, - 0xb1, 0x98, 0x30, 0xb7, 0x20, 0x4c, 0x30, 0x98, 0x4e, 0xdd, 0xf4, 0x34, 0xec, 0xc5, - 0xf0, 0xea, 0x82, 0x5c, 0xf8, 0xd9, 0xd5, 0x03, 0x8f, 0x28, 0xe2, 0x3e, 0xf3, 0x6b, - 0xa9, 0x38, 0x52, 0xe5, 0x8e, 0x85, 0xf8, 0x90, 0xb1, 0x77, 0x5c, 0x6d, 0x4c, 0x13, - 0x5b, 0xef, 0x0e, 0x2a, 0x19, 0x33, 0x02, 0xd9, 0x0a, 0x80, 0x4c, 0x85, 0x31, 0x25, - 0xaa, 0x5b, 0x11, 0x6f, 0x8c, 0x58, 0x0e, 0xb6, 0x54, 0xfe, 0x35, 0xe6, 0x73, 0x79, - 0x9e, 0x93, 0xcf, 0x58, 0xfe, 0x1e, 0x70, 0xcd, 0xe1, 0x19, 0xab, 0x58, 0x6c, 0x12, - 0xc4, 0x95, 0x75, 0xe6, 0x1a, 0xc4, 0xb7, 0x71, 0xfa, 0x8e, 0xbf, 0x76, 0xca, 0x95, - 0xd6, 0x51, 0xa4, 0xba, 0x87, 0x3b, 0x24, 0xcf, 0x97, 0xff, 0x75, 0x5b, 0xc7, 0x49, - 0xf4, 0x09, 0x6d, 0x2d, 0xa1, 0x5c, 0xf8, 0x30, 0x36, 0xcc, 0x22, 0x0f, 0x0a, 0x68, - 0x93, 0x43, 0x21, 0xc9, 0xae, 0x33, 0x4e, 0x2d, 0x99, 0xa9, 0x95, 0xe9, 0x29, 0x04, - 0xc1, 0x45, 0x23, 0x33, 0x19, 0x00, 0xcb, 0xca, 0x20, 0x4a, 0xdc, 0xb6, 0x93, 0x9d, - 0xc1, 0x71, 0x87, 0x53, 0x53, 0xa1, 0x1e, 0x12, 0xba, 0xcb, 0x2a, 0xab, 0x0f, 0x57, - 0x17, 0x9f, 0x1b, 0x67, 0xea, 0xcc, 0x7e, 0x7b, 0x6c, 0x5c, 0xc8, 0xa3, 0x78, 0x64, - 0x9b, 0x62, 0xb8, 0x52, 0xfa, 0x47, 0x6f, 0x93, 0x37, 0x88, 0x59, 0xd0, 0xd9, 0xa3, - 0x03, 0x3d, 0xa1, 0x31, 0x28, 0x17, 0x57, 0xad, 0x98, 0x5c, 0x86, 0xfe, 0x03, 0x7a, - 0x4e, 0xdd, 0x0a, 0x4a, 0x49, 0xee, 0x5c, 0x4f, 0x48, 0x15, 0xf0, 0x14, 0x73, 0xb9, - 0x60, 0xa1, 0x8a, 0x3b, 0x7f, 0x75, 0x07, 0xee, 0x3d, 0x8b, 0x39, 0x5a, 0x76, 0x68, - 0x40, 0x95, 0x5b, 0xaa, 0xdd, 0x0a, 0xbb, 0xf4, 0xf5, 0x91, 0x4e, 0x92, 0x10, 0xf5, - 0x9e, 0x4c, 0xd1, 0x3c, 0x82, 0xe0, 0xac, 0xf8, 0x79, 0x51, 0x78, 0x02, 0x91, 0xd0, - 0xa9, 0xa7, 0x0f, 0x6b, 0x4f, 0xf5, 0x0d, 0x81, 0x0d, 0x50, 0x90, 0x20, 0x45, 0x30, - 0xad, 0x69, 0x44, 0xb1, 0x3d, 0x23, 0x83, 0xab, 0xca, 0x42, 0x0c, 0xb6, 0xd9, 0xfc, - 0xd8, 0xfd, 0xcb, 0xe9, 0xb3, 0xb5, 0xf4, 0x2f, 0x0a, 0xf5, 0xdf, 0x36, 0x37, 0x8c, - 0xe7, 0x3d, 0xc9, 0x06, 0x16, 0x7d, 0xd4, 0xb3, 0x80, 0x41, 0x8f, 0x17, 0xe4, 0x50, - 0x61, 0x18, 0x57, 0x23, 0xda, 0xbb, 0x6f, 0xfd, 0xbb, 0xd5, 0xa4, 0x18, 0xc3, 0xc6, - 0xfd, 0x33, 0x70, 0x34, 0x09, 0x94, 0x27, 0x7b, 0x88, 0x8e, 0xe4, 0x9b, 0x08, 0x91, - 0xbb, 0xb9, 0x4b, 0x6b, 0x8b, 0x06, 0x5f, 0xd1, 0x92, 0x00, 0xdc, 0x3a, 0x68, 0x1c, - 0xa5, 0xff, 0x2a, 0x98, 0x8f, 0xa6, 0x6d, 0x02, 0x9d, 0xdd, 0xf9, 0xb0, 0x3a, 0x5e, - 0x6c, 0x6e, 0x99, 0xb6, 0x35, 0x41, 0x15, 0x6a, 0x09, 0x51, 0xd9, 0x08, 0x7d, 0xd8, - 0x83, 0xd5, 0x13, 0x9e, 0xe6, 0x7a, 0x8c, 0xe5, 0xdd, 0x6e, 0xf1, 0x4c, 0x9a, 0x10, - 0xdb, 0x81, 0x8b, 0x93, 0x69, 0x02, 0xc7, 0x99, 0x93, 0x90, 0xf9, 0x72, 0xba, 0xfa, - 0x5a, 0x57, 0x2f, 0xc8, 0x73, 0x42, 0xe2, 0xc5, 0x1c, 0xeb, 0x80, 0x30, 0xe0, 0x6b, - 0x72, 0x40, 0x95, 0xf9, 0x8d, 0x7b, + 0xbe, 0x1d, 0xff, 0xd3, 0x37, 0x0c, 0x67, 0x56, 0x69, 0xcc, 0x9a, 0xe1, 0xd0, 0x30, + 0x2d, 0x7f, 0x90, 0x6d, 0x25, 0x23, 0x09, 0x3c, 0x24, 0xf4, 0x25, 0x7a, 0x83, 0xbc, + 0x4f, 0x36, 0x62, 0x3a, 0x08, 0x2c, 0xe6, 0xeb, 0x45, 0x21, 0x95, 0x71, 0x91, 0xd5, + 0x7e, 0x14, 0x11, 0xed, 0xe7, 0x1d, 0x44, 0xb5, 0x6c, 0x57, 0xcb, 0x22, 0x81, 0x4a, + 0x04, 0x69, 0x39, 0xd2, 0xff, 0xf9, 0x2b, 0x46, 0x62, 0x76, 0x2d, 0x4f, 0x21, 0xc0, + 0x78, 0x42, 0x74, 0x72, 0xb9, 0x18, 0x10, 0x10, 0x55, 0x56, 0xf4, 0xde, 0x0a, 0x27, + 0xe7, 0x70, 0x08, 0x47, 0x72, 0xcb, 0xfe, 0xbf, 0x87, 0xdb, 0x33, 0x14, 0xab, 0x70, + 0xf2, 0x6d, 0x11, 0xea, 0x5d, 0xe2, 0x67, 0xc3, 0xa9, 0xa8, 0xf4, 0x6b, 0xad, 0x13, + 0xc7, 0x36, 0x26, 0x10, 0xbd, 0xba, 0x81, 0x02, 0xd4, 0xb7, 0x26, 0xef, 0x26, 0xec, + 0x79, 0x4a, 0x15, 0x66, 0x57, 0x1b, 0xfd, 0xc1, 0x02, 0x47, 0x7d, 0xa5, 0xb4, 0x9b, + 0xbf, 0x9f, 0xe4, 0xb1, 0xa4, 0x4e, 0xd0, 0xb3, 0xbc, 0xed, 0x99, 0xba, 0x81, 0x9a, + 0x4f, 0x30, 0x22, 0x65, 0x49, 0x44, 0x5b, 0xc6, 0x1c, 0xff, 0x5c, 0x33, 0x16, 0x33, + 0x5f, 0x6b, 0xd4, 0xa9, 0xa4, 0x24, 0xc9, 0x4a, 0xe0, 0xb5, 0xcb, 0xe4, 0x8a, 0xfb, + 0x2b, 0x94, 0xd0, 0xc7, 0xe4, 0x4e, 0x32, 0x30, 0x95, 0xa7, 0x2e, 0x42, 0x64, 0xe9, + 0x1c, 0x48, 0x94, 0xb9, 0xe8, 0x45, 0xaf, 0x32, 0x35, 0x02, 0xda, 0xe8, 0xc1, 0x86, + 0x78, 0xa4, 0xf7, 0x40, 0xe5, 0xa6, 0x3a, 0x4c, 0x70, 0x29, 0x92, 0xfa, 0xcd, 0xd3, + 0x57, 0x35, 0xb1, 0xd1, 0x34, 0x8b, 0x91, 0x9c, 0x70, 0x0c, 0x42, 0xd3, 0x30, 0xd3, + 0x86, 0xaf, 0xb8, 0x73, 0xfa, 0xba, 0xd8, 0xcb, 0x32, 0x18, 0x15, 0x1b, 0x40, 0x18, + 0x01, 0xe3, 0x69, 0x34, 0x4f, 0xf2, 0x0a, 0xaa, 0x66, 0x73, 0x47, 0x4f, 0x4b, 0xfc, + 0x98, 0xd0, 0x7e, 0x36, 0x7b, 0xc4, 0x2e, 0xf1, 0xa0, 0x4f, 0xa1, 0xbc, 0x12, 0x52, + 0x18, 0x8d, 0xd9, 0xd3, 0xe0, 0x00, 0xe3, 0xf5, 0xe9, 0xdf, 0xc9, 0xe1, 0x3e, 0xe9, + 0xdb, 0x55, 0x04, 0x0d, 0x17, 0x22, 0x7d, 0xa4, 0x4a, 0x3e, 0x08, 0xfd, 0x5e, 0xc8, + 0x58, 0xc4, 0x9c, 0x2e, 0x6a, 0x71, 0x1f, 0x8e, 0x68, 0xd0, 0xa1, 0xdf, 0x88, 0xef, + 0x09, 0x40, 0xf7, 0x2e, 0xd7, 0x3e, 0xf4, 0x9e, 0x8a, 0x45, 0xae, 0x2e, 0x5e, 0x1b, + 0xf1, 0x37, 0xba, 0x58, 0xcf, 0xb9, 0x25, 0x79, 0xab, 0xb2, 0xa4, 0x93, 0x13, 0xa2, + 0xff, 0x3d, 0xb6, 0x16, 0x93, 0xd2, 0xb7, 0x58, 0xaf, 0x20, 0x47, 0x2a, 0xc6, 0x40, + 0x6b, 0xa3, 0x55, 0xb4, 0x8c, 0xee, 0x22, 0xe7, 0x0f, 0xb8, 0xf9, 0xd4, 0x8e, 0xa3, + 0x93, 0x4b, 0x62, 0x24, 0xac, 0xe2, 0x69, 0xb9, 0xef, 0x54, 0x6d, 0xbf, 0xc5, 0x2a, + 0xbe, 0xcf, 0xac, 0x59, 0x40, 0xf0, 0x40, 0xbd, 0x21, 0xe9, 0x0e, 0xfa, 0x82, 0x75, + 0x56, 0x1a, 0x88, 0xbc, 0x18, 0xe2, 0x6b, 0x98, 0x8d, 0x11, 0x79, 0xb7, 0xa2, 0xc3, + 0xaf, 0xd8, 0x6e, 0xf2, 0xa0, 0x90, 0x62, 0x52, 0x23, 0x23, 0x4b, 0x39, 0xc9, 0xe2, + 0x06, 0x8d, 0x94, 0x5d, 0xd7, 0x76, 0x3b, 0x01, 0x0c, 0x28, 0xc8, 0x9b, 0x72, 0xe2, + 0x55, 0x13, 0xb3, 0x9c, 0x3c, 0xe1, 0x17, 0x73, 0x42, 0x8a, 0xd3, 0x44, 0xe1, 0xd5, + 0xd5, 0x1b, 0x92, 0x00, 0x14, 0xf9, 0x17, 0x06, 0xff, 0xae, 0x3d, 0x86, 0x36, 0x14, + 0x77, 0xfd, 0x5d, 0xe0, 0x13, 0x42, 0x2c, 0x06, 0xa3, 0x32, 0xe3, 0x45, 0x79, 0x75, + 0xcf, 0x9b, 0xe9, 0xf9, 0xab, 0x3a, 0x06, 0x87, 0x2e, 0xf0, 0x71, 0x7d, 0x39, 0x08, + 0xbd, 0xeb, 0xf8, 0x41, 0x8c, 0xe5, 0x57, 0xd5, 0x2d, 0x51, 0xa2, 0x50, 0xc0, 0x8c, + 0x5b, 0x79, 0x3a, 0xd4, 0xbc, 0x0f, 0x16, 0xc6, 0x27, 0x89, 0xfe, 0xa2, 0xca, 0xb3, + 0x9c, 0xcc, 0xa4, 0x07, 0xee, 0x9e, 0x47, 0xf5, 0x6d, 0x20, 0xa7, 0x41, 0x91, 0x2c, + 0x6b, 0xad, 0xdb, 0xd7, 0xfa, 0x7b, 0x97, 0xe5, 0x46, 0x33, 0x61, 0x28, 0x74, 0x5a, + 0xe7, 0xd7, 0x30, 0xa5, 0x5a, 0x6a, 0xc7, 0xb8, 0xfc, 0xbd, 0x72, 0xce, 0x78, 0x95, + 0x9c, 0x7a, 0x79, 0x75, 0x21, 0x2c, ], ock: [ - 0x5b, 0x5b, 0x20, 0xfc, 0x46, 0xba, 0x14, 0xbd, 0x18, 0x43, 0xb6, 0xc7, 0x7e, 0xc3, - 0xf4, 0x55, 0xb7, 0x65, 0xb4, 0xd1, 0x2d, 0xb6, 0x52, 0xeb, 0x34, 0x20, 0x0c, 0x41, - 0x48, 0x88, 0x1f, 0xfc, + 0xeb, 0x3e, 0xd9, 0xfc, 0xb3, 0xaa, 0x91, 0xc4, 0xf5, 0xec, 0xfd, 0x43, 0xdb, 0xda, + 0x40, 0x33, 0x06, 0x93, 0xc3, 0xa6, 0x56, 0x75, 0x45, 0xfd, 0x23, 0x6a, 0xf1, 0x90, + 0x8e, 0x29, 0x42, 0xa3, ], op: [ 0x3f, 0xeb, 0x34, 0x5a, 0xec, 0xd3, 0x42, 0x9a, 0x16, 0xe1, 0x0f, 0x3d, 0x13, 0x20, 0xbc, 0x99, 0x71, 0xb5, 0x9e, 0x63, 0x9d, 0x62, 0xb6, 0x96, 0x1a, 0xea, 0x78, 0x15, - 0x67, 0xa8, 0x60, 0x9e, 0x24, 0x75, 0x30, 0x5c, 0x35, 0xcf, 0x37, 0xeb, 0xd2, 0x77, - 0x82, 0x35, 0x16, 0x58, 0x5a, 0xfa, 0x06, 0x05, 0x78, 0x52, 0x17, 0x1e, 0x0c, 0xe4, - 0xb0, 0x52, 0xd5, 0xb4, 0x20, 0x41, 0xd8, 0x1c, + 0x67, 0xa8, 0x60, 0x9e, 0x3b, 0xc1, 0x7a, 0x58, 0x0d, 0x53, 0x0f, 0x89, 0x30, 0xa3, + 0x6b, 0x8d, 0x6f, 0xea, 0x67, 0x85, 0x7f, 0x7b, 0x85, 0x20, 0xfd, 0x2e, 0x0a, 0xb5, + 0xd5, 0xcb, 0xab, 0x1a, 0xcc, 0xd5, 0x4e, 0x3a, ], c_out: [ - 0xe0, 0x1b, 0x5c, 0x1e, 0x01, 0x90, 0x0f, 0xf7, 0x9b, 0xf7, 0x27, 0xf5, 0x37, 0xc4, - 0xac, 0x36, 0xf8, 0x06, 0x7a, 0x0c, 0xc5, 0xc8, 0xe9, 0xc8, 0x20, 0x44, 0x28, 0x43, - 0x69, 0x35, 0x30, 0x91, 0x8a, 0xea, 0x67, 0x2c, 0x4c, 0xd8, 0xfa, 0x3f, 0x6f, 0x2c, - 0xb6, 0x8b, 0x87, 0x17, 0x22, 0xe7, 0x78, 0xf6, 0xe2, 0x5e, 0x78, 0xae, 0x00, 0xa8, - 0x43, 0x28, 0xc4, 0xc2, 0xbf, 0x1c, 0x79, 0xb2, 0xc9, 0xd8, 0x69, 0x72, 0x60, 0xcd, - 0x44, 0x7e, 0x2e, 0xff, 0x31, 0x5d, 0x74, 0xb5, 0xb1, 0xfd, + 0x60, 0xf3, 0xe8, 0x94, 0xe3, 0x86, 0x4e, 0xfb, 0x48, 0xcc, 0xae, 0x50, 0xe1, 0x0d, + 0xa7, 0x73, 0xdc, 0xcf, 0x85, 0x62, 0x45, 0x5d, 0x1b, 0x73, 0x1a, 0xad, 0x44, 0xe1, + 0x5e, 0x3e, 0x40, 0x18, 0x31, 0xce, 0x6f, 0x92, 0xf4, 0x53, 0x2d, 0x90, 0x83, 0x92, + 0x59, 0xce, 0x9c, 0xb1, 0x44, 0x62, 0x1f, 0x12, 0x01, 0x77, 0x8f, 0x61, 0x5d, 0x09, + 0x87, 0x01, 0x0c, 0x8d, 0x13, 0x5c, 0x32, 0xd5, 0x6e, 0xe2, 0x84, 0x68, 0x65, 0xa2, + 0x61, 0xde, 0x14, 0x25, 0xd2, 0x3b, 0xcc, 0x51, 0xb8, 0xa0, ], }, TestVector { @@ -1356,36 +1350,35 @@ pub(crate) fn test_vectors() -> Vec { 0x0a, 0x12, 0x01, 0x2d, 0x63, 0xc0, 0x09, 0xc6, 0x77, 0x44, 0xba, 0xe0, 0xd5, 0x83, 0x88, 0xff, 0xee, 0x2f, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0xe9, 0x16, 0x93, 0xc3, 0x7d, 0x04, 0x37, 0x5e, 0x67, 0xc5, 0x71, 0x5a, 0x39, 0xc9, - 0x79, 0x4a, 0x4e, 0xcd, 0x08, 0x38, 0xe2, 0x35, 0x1f, 0xd7, 0xcd, 0x93, 0xa1, 0x55, - 0x7f, 0x01, 0x02, 0x3e, + 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, + 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, + 0x92, 0xd7, 0xa0, 0x24, ], cmx: [ - 0xcc, 0x29, 0x41, 0xe0, 0xf6, 0x38, 0x25, 0x7f, 0xb6, 0x51, 0x6a, 0x27, 0xc3, 0x0e, - 0xaa, 0xe0, 0xb4, 0x6d, 0x2f, 0xf0, 0x6a, 0x73, 0x50, 0x70, 0x41, 0x74, 0x6c, 0xdc, - 0x23, 0x07, 0x61, 0x25, + 0x1d, 0x51, 0xea, 0x92, 0xfa, 0x43, 0x55, 0x0a, 0x0e, 0xdd, 0xea, 0x23, 0x6e, 0x17, + 0xa0, 0x16, 0x93, 0xc2, 0x2d, 0x8d, 0xd8, 0x1c, 0x9c, 0x9e, 0xc8, 0x76, 0xa2, 0x4e, + 0x67, 0xd4, 0x93, 0x0b, ], esk: [ - 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, 0xbf, 0xb7, 0x8a, 0xec, - 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, 0x77, 0xc9, 0x46, 0xe9, - 0xcd, 0x7a, 0x24, 0x23, + 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, 0x14, 0xb0, 0xdf, 0x85, + 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, 0xc4, 0x84, 0xa9, 0xf4, + 0xc7, 0xda, 0x74, 0x36, ], ephemeral_key: [ - 0xad, 0xa7, 0x60, 0x27, 0xdc, 0xae, 0xb5, 0xf1, 0x58, 0xac, 0x6c, 0x5c, 0x6d, 0x7f, - 0x05, 0x31, 0x8f, 0xec, 0x26, 0xd5, 0xc7, 0x94, 0xf2, 0xe9, 0x00, 0xcb, 0x96, 0x29, - 0x92, 0x49, 0xe0, 0xb5, + 0x8f, 0xbe, 0xb6, 0xb3, 0x03, 0x8e, 0x69, 0x49, 0x91, 0x6a, 0x2c, 0x06, 0x0e, 0xf9, + 0xa4, 0xb1, 0xfe, 0xf1, 0x3a, 0xce, 0x2f, 0xee, 0x00, 0x25, 0xda, 0x32, 0xc3, 0x6d, + 0x23, 0x1a, 0x61, 0x34, ], shared_secret: [ - 0xc2, 0x5c, 0xf1, 0xd6, 0x53, 0x2e, 0x06, 0xcb, 0x8b, 0x15, 0x22, 0x14, 0x76, 0x6e, - 0xee, 0xd7, 0x5a, 0x17, 0x8c, 0x82, 0x2a, 0x11, 0x51, 0xf6, 0x9e, 0x92, 0xe9, 0xcf, - 0xfa, 0x47, 0xcb, 0x19, + 0x67, 0xd6, 0x8a, 0x5a, 0x05, 0x93, 0xfd, 0x16, 0x7d, 0x38, 0x08, 0x2e, 0x49, 0xd2, + 0x30, 0x30, 0x86, 0xe5, 0x5a, 0x43, 0xc1, 0x24, 0xd5, 0xaa, 0xa8, 0x20, 0xab, 0x0c, + 0x3f, 0x5c, 0xc5, 0x37, ], k_enc: [ - 0xd4, 0xef, 0x89, 0xc4, 0x64, 0xbe, 0x8f, 0x42, 0xf6, 0xb7, 0xf2, 0x6d, 0x89, 0x37, - 0x8b, 0x73, 0xa3, 0x55, 0xa4, 0xfe, 0x24, 0x6c, 0x2e, 0xc8, 0xe8, 0x14, 0x6b, 0xef, - 0x7d, 0xdd, 0x14, 0x19, + 0x6b, 0x8d, 0x83, 0xf2, 0xf1, 0xfd, 0x1e, 0xad, 0x7d, 0x45, 0x42, 0xb3, 0x63, 0x09, + 0x34, 0x07, 0xc5, 0x0a, 0x20, 0xed, 0x7f, 0x0e, 0x8c, 0xf2, 0xdb, 0x53, 0x6d, 0xb1, + 0xbe, 0x25, 0xe9, 0x8d, ], p_enc: [ 0x02, 0x56, 0x4f, 0xc3, 0x81, 0xfc, 0x4d, 0xc8, 0x11, 0x8d, 0xe4, 0x7c, 0x10, 0xb8, @@ -1431,68 +1424,68 @@ pub(crate) fn test_vectors() -> Vec { 0x1a, 0x81, 0xa3, 0x59, ], c_enc: [ - 0xea, 0x86, 0x7e, 0x07, 0xac, 0xb7, 0xfa, 0x03, 0xe7, 0x36, 0xce, 0xdd, 0xed, 0x82, - 0x3d, 0x19, 0x91, 0x30, 0xfb, 0x3f, 0xef, 0x62, 0xcc, 0x3e, 0xa9, 0xa0, 0xc9, 0x35, - 0xdf, 0x05, 0xc5, 0xad, 0x5e, 0x67, 0xf7, 0x4f, 0xcb, 0xa6, 0x67, 0xe0, 0x81, 0x1c, - 0xdc, 0x0c, 0xa9, 0xf3, 0xd7, 0x81, 0x76, 0x43, 0x75, 0x56, 0x47, 0xbe, 0x59, 0xdf, - 0x09, 0x6e, 0x46, 0x5e, 0xc1, 0x11, 0x24, 0x36, 0x3c, 0x98, 0x1c, 0x55, 0xd5, 0x5f, - 0x8d, 0x8a, 0xc8, 0xb6, 0x54, 0x0a, 0x98, 0xcf, 0xcc, 0x29, 0x4a, 0xa7, 0xcc, 0x62, - 0x95, 0x50, 0x85, 0x3a, 0x25, 0xbf, 0x6b, 0x32, 0x35, 0x16, 0xe1, 0x58, 0x2b, 0x4e, - 0x8b, 0x82, 0x95, 0xe2, 0x7f, 0x6b, 0x99, 0x94, 0x80, 0x2e, 0xfe, 0xf5, 0x43, 0x1f, - 0x03, 0x7d, 0x22, 0x09, 0xa0, 0x88, 0x07, 0x34, 0x6f, 0xb3, 0x9c, 0xad, 0xd8, 0x93, - 0xd6, 0x5f, 0x64, 0xc7, 0xfe, 0x92, 0xec, 0xbc, 0xdf, 0xe5, 0x55, 0x54, 0xca, 0xff, - 0xb0, 0xcf, 0x41, 0xeb, 0x5c, 0x55, 0x72, 0xba, 0x44, 0x39, 0x90, 0x00, 0xe9, 0xfa, - 0x9a, 0xaf, 0x6e, 0xb7, 0x6c, 0x2a, 0x8a, 0x5d, 0x7b, 0x6b, 0x52, 0xb9, 0xa9, 0xef, - 0x6e, 0xc3, 0xed, 0xa6, 0x65, 0xfe, 0x8a, 0xa8, 0x07, 0x48, 0xb8, 0x1f, 0x7d, 0x55, - 0x96, 0xf1, 0x94, 0x2f, 0xf7, 0x1d, 0x29, 0xc6, 0x78, 0xa3, 0xb6, 0xc6, 0x6b, 0xa7, - 0x0f, 0x45, 0xb1, 0xfc, 0xf2, 0x22, 0x38, 0x84, 0x50, 0x68, 0xf3, 0x60, 0xb0, 0x99, - 0xae, 0xe9, 0xf2, 0xf0, 0xef, 0x22, 0x33, 0x3f, 0xd6, 0x4f, 0xf1, 0x1e, 0x48, 0x15, - 0x43, 0xa5, 0x2b, 0xb3, 0x3f, 0x52, 0x3d, 0xe2, 0xec, 0x92, 0x3a, 0xe9, 0x86, 0x58, - 0x57, 0x71, 0x7b, 0x65, 0xd4, 0x4c, 0x3d, 0x9d, 0xb7, 0xb3, 0xec, 0xb2, 0xff, 0x02, - 0x25, 0x29, 0x7d, 0xeb, 0x83, 0xdd, 0x1b, 0x9a, 0x39, 0x4d, 0x69, 0x7c, 0x09, 0xd7, - 0xfe, 0xc6, 0x1e, 0xac, 0xee, 0x39, 0xa2, 0xf1, 0xce, 0xd9, 0xe6, 0xfd, 0xa5, 0xc0, - 0xf3, 0x27, 0x71, 0xc6, 0xce, 0x3f, 0x17, 0xbe, 0x0e, 0xef, 0x81, 0x10, 0x99, 0xc1, - 0x09, 0xe4, 0xfb, 0x6a, 0xec, 0x30, 0xdf, 0x04, 0x5b, 0x43, 0xda, 0x89, 0x30, 0x8b, - 0xc8, 0x37, 0x68, 0x8b, 0xb0, 0xf4, 0xa2, 0xc6, 0x04, 0xa1, 0x54, 0xa8, 0x47, 0xc5, - 0xd7, 0x87, 0x27, 0xf0, 0xe1, 0xab, 0x11, 0xe3, 0x40, 0xcf, 0xd4, 0xc7, 0xe8, 0xc6, - 0xba, 0xff, 0xfe, 0xfc, 0x74, 0xef, 0x55, 0x3d, 0x4b, 0x29, 0x26, 0x9f, 0x38, 0xb4, - 0xb7, 0xfe, 0x6e, 0x07, 0x3a, 0x70, 0xae, 0xf2, 0x0d, 0x6c, 0x23, 0x8b, 0x9f, 0xfd, - 0x24, 0x1f, 0xf6, 0x99, 0x99, 0x92, 0x30, 0xf0, 0xb3, 0x9c, 0x96, 0x3e, 0xfa, 0x00, - 0xef, 0x7f, 0x09, 0x2d, 0x76, 0x0c, 0x40, 0x9a, 0x2b, 0x6c, 0x26, 0xb4, 0x97, 0x82, - 0x9b, 0x81, 0xcb, 0xa4, 0xc8, 0x3b, 0x11, 0x44, 0xc6, 0x5a, 0x2d, 0x31, 0x78, 0xbb, - 0x28, 0xc1, 0xd8, 0xe3, 0x30, 0xd3, 0xf4, 0xaf, 0x90, 0x10, 0xad, 0x49, 0xa5, 0xdb, - 0x70, 0xd6, 0x6a, 0xf5, 0x70, 0x19, 0x21, 0x49, 0x80, 0x5f, 0xe1, 0xca, 0x61, 0xc6, - 0xd4, 0xec, 0xaf, 0xa7, 0x97, 0x51, 0x7f, 0x33, 0x06, 0xaf, 0x2a, 0x32, 0x27, 0x3b, - 0xf3, 0xd6, 0x98, 0xaa, 0x55, 0xa5, 0x72, 0xb2, 0xdf, 0x80, 0x36, 0xd9, 0x7c, 0xf5, - 0x8c, 0x12, 0x9f, 0x82, 0x85, 0xd0, 0xd7, 0xea, 0x04, 0xc1, 0x88, 0xa8, 0x39, 0x6e, - 0x73, 0x8b, 0xd4, 0x48, 0x46, 0x5e, 0x7b, 0x9a, 0x64, 0xb7, 0x96, 0x7b, 0xcb, 0x25, - 0xf8, 0xaa, 0x85, 0x9e, 0xa5, 0xca, 0x06, 0xc3, 0xdf, 0x39, 0x0f, 0xac, 0x8a, 0xc6, - 0x06, 0x05, 0x03, 0x1a, 0x02, 0x09, 0xbb, 0x80, 0x24, 0x0d, 0x05, 0x45, 0xf4, 0x11, - 0x77, 0xea, 0xb4, 0x40, 0x2e, 0x8a, 0x42, 0x3a, 0x40, 0xcc, 0xff, 0x58, 0x6b, 0x2e, - 0xdd, 0x6a, 0xcf, 0xb8, 0xf1, 0xd8, 0x0d, 0x8c, 0x60, 0x5f, 0x49, 0x05, 0x2e, 0x7a, - 0x30, 0x82, 0x6e, 0x1f, 0x03, 0x09, 0x9c, 0x71, 0x43, 0xad, 0x0b, 0x51, 0xfc, 0x63, - 0x6f, 0x1d, 0x87, 0x05, 0x83, 0xd6, 0xed, 0xce, 0xcd, 0xe9, 0x42, 0x38, 0x9e, 0x6c, - 0x01, 0x00, 0x66, 0x78, 0xda, 0xad, + 0x77, 0xc6, 0xef, 0xc8, 0xb5, 0x42, 0xa7, 0x07, 0xc0, 0xa5, 0xcf, 0x5c, 0xe3, 0xf3, + 0xb9, 0x6d, 0xe1, 0x91, 0x95, 0x7c, 0x9f, 0xa6, 0xe9, 0xbb, 0x4b, 0x8d, 0x89, 0x9e, + 0x1f, 0x19, 0xe0, 0x20, 0xba, 0x7b, 0xb3, 0xfe, 0xf1, 0x67, 0x81, 0xc8, 0x8c, 0xc5, + 0xd4, 0x4a, 0x5e, 0xf8, 0x17, 0x31, 0x47, 0xdc, 0x3d, 0x1b, 0x51, 0x6a, 0xf6, 0xdd, + 0x77, 0xdd, 0xb6, 0xee, 0x67, 0xaa, 0xf5, 0x42, 0xce, 0xe2, 0xbe, 0xd3, 0xe4, 0xa0, + 0x7e, 0xce, 0x42, 0x8f, 0x22, 0xa8, 0x01, 0xcf, 0x01, 0xba, 0xad, 0x18, 0x27, 0xfd, + 0x42, 0x57, 0x46, 0xc5, 0x45, 0x00, 0x1c, 0x35, 0x6d, 0x0a, 0xbe, 0xaa, 0xa5, 0xa4, + 0x22, 0xdf, 0xff, 0x0e, 0xe2, 0x18, 0xac, 0x37, 0xef, 0x83, 0x97, 0xc6, 0x2c, 0xa8, + 0x6f, 0xab, 0xeb, 0xb6, 0x88, 0xb3, 0x8f, 0xb4, 0xa6, 0x54, 0x29, 0x11, 0xbe, 0x1c, + 0x5e, 0x71, 0x77, 0x8b, 0x5e, 0xb5, 0x3a, 0xf1, 0xc4, 0xcb, 0x4d, 0xd9, 0x94, 0x72, + 0x4f, 0x61, 0x0f, 0x38, 0x72, 0x4a, 0x73, 0xdf, 0x09, 0x2b, 0xea, 0xe8, 0xb8, 0x7f, + 0x7f, 0x6a, 0x2b, 0xc0, 0x9d, 0xf2, 0xaa, 0x18, 0xc2, 0xf8, 0xee, 0xba, 0x63, 0xee, + 0x0d, 0x31, 0x35, 0x3b, 0x6f, 0x28, 0x3e, 0xf5, 0x9a, 0xc1, 0x53, 0x60, 0x73, 0xda, + 0x7a, 0x6d, 0x82, 0xbf, 0xdc, 0x09, 0x74, 0x02, 0x08, 0x0f, 0xa1, 0x03, 0xcb, 0x8b, + 0x3e, 0xfb, 0x94, 0x1e, 0xe5, 0x01, 0xf6, 0x41, 0x2c, 0xfb, 0xc2, 0x50, 0xaf, 0xad, + 0xbe, 0x54, 0x4a, 0xc5, 0x1f, 0xce, 0x41, 0x5a, 0x24, 0x93, 0xba, 0x83, 0x9e, 0x38, + 0x18, 0xb0, 0xfe, 0x30, 0x18, 0xbf, 0xa4, 0x37, 0xf0, 0x6e, 0x31, 0x86, 0x14, 0x8a, + 0xa4, 0x05, 0xba, 0xb8, 0x21, 0xa2, 0x6e, 0xa0, 0x7f, 0x93, 0xcf, 0xe7, 0x56, 0x8f, + 0xe3, 0xef, 0x08, 0xfa, 0x0b, 0x80, 0xfc, 0xec, 0x5b, 0xd5, 0x91, 0x5f, 0x68, 0x8c, + 0xf5, 0x99, 0x31, 0x5e, 0x79, 0xaa, 0xea, 0x34, 0xd5, 0x18, 0xd9, 0x55, 0xfe, 0xef, + 0x30, 0x3f, 0x69, 0xb2, 0x87, 0xc6, 0xd0, 0x51, 0x6d, 0xa2, 0x39, 0xfb, 0xbd, 0xdb, + 0xaf, 0x25, 0x56, 0xeb, 0xce, 0x77, 0xa3, 0xd5, 0x97, 0x23, 0x5c, 0x22, 0xd3, 0x8c, + 0x5b, 0x5e, 0xeb, 0x98, 0xc7, 0xc0, 0x8d, 0xa8, 0xd3, 0x76, 0xbb, 0xa1, 0xb5, 0x07, + 0x85, 0xbe, 0x82, 0xbf, 0xe0, 0x9a, 0xe7, 0x1c, 0xcc, 0xaf, 0x31, 0xa2, 0xf0, 0xcf, + 0xa0, 0x76, 0xd1, 0xe4, 0xd1, 0xb5, 0x2f, 0xee, 0x45, 0xc8, 0xed, 0x23, 0xdf, 0x33, + 0xa8, 0x1c, 0xb1, 0xa8, 0xac, 0xec, 0x9f, 0x53, 0x5d, 0xa4, 0x96, 0x70, 0xf9, 0x98, + 0x6d, 0x5c, 0x92, 0xc8, 0x2b, 0x0a, 0xd2, 0x20, 0xf8, 0x5f, 0x3b, 0x38, 0x72, 0xeb, + 0xe0, 0x53, 0xcd, 0xeb, 0x96, 0x1b, 0xd2, 0xd3, 0xab, 0x3b, 0xcd, 0x67, 0x6e, 0x6f, + 0xd7, 0xcb, 0xe9, 0x79, 0x5e, 0x1f, 0x2d, 0x82, 0x87, 0x00, 0x7c, 0x91, 0x0e, 0x7b, + 0x43, 0x01, 0x69, 0xe4, 0x51, 0xf0, 0xb2, 0xd7, 0x63, 0xe5, 0x43, 0x03, 0x3b, 0xc6, + 0xc7, 0x38, 0x9f, 0xa1, 0x61, 0x5b, 0xa1, 0x9d, 0x1f, 0x27, 0x48, 0xb2, 0x17, 0xc9, + 0x60, 0xfe, 0x05, 0x04, 0x07, 0xc8, 0xf4, 0x73, 0x35, 0x6b, 0xaa, 0x6e, 0x0c, 0x7d, + 0x77, 0xfa, 0xc6, 0xc7, 0xdb, 0x45, 0x12, 0xaf, 0x57, 0x96, 0xb3, 0xbc, 0xf1, 0x23, + 0xe0, 0x90, 0xb9, 0x80, 0xeb, 0xc2, 0xd6, 0x4b, 0x86, 0xdd, 0x24, 0xcb, 0x9a, 0x6d, + 0xab, 0x1d, 0xb4, 0x13, 0x04, 0x75, 0x38, 0x90, 0x2e, 0x2e, 0x49, 0x0e, 0x4f, 0xc8, + 0x78, 0xaa, 0x04, 0xdb, 0xef, 0x66, 0x99, 0x63, 0x9c, 0x3d, 0xab, 0x17, 0xc5, 0x14, + 0x70, 0x48, 0xac, 0x6d, 0x48, 0x49, 0x0d, 0xc4, 0x88, 0x5e, 0xd9, 0x86, 0x70, 0x63, + 0x35, 0xf4, 0x1b, 0xa4, 0x15, 0x59, 0x65, 0x9e, 0x1b, 0x53, 0xda, 0x76, 0x51, 0x4c, + 0xc4, 0x0a, 0xdb, 0x66, 0xc3, 0x5c, 0xe5, 0x6f, 0x3a, 0xbe, 0x39, 0xe1, 0xae, 0xe5, + 0x84, 0x9f, 0xff, 0xcc, 0x6e, 0x1f, 0x1b, 0xf8, 0x11, 0xce, 0xb6, 0x65, 0xa6, 0xfc, + 0xf8, 0x80, 0x6b, 0xbb, 0xba, 0x4a, 0x5b, 0x87, 0x38, 0xa1, 0x17, 0xdc, 0xaf, 0xfb, + 0x4f, 0xdf, 0x10, 0x08, 0x00, 0x6f, ], ock: [ - 0xf9, 0x59, 0x87, 0xcc, 0x0c, 0x73, 0x57, 0xc7, 0x20, 0x26, 0x27, 0xa5, 0xa5, 0x50, - 0x09, 0xef, 0xd7, 0x17, 0x55, 0x3e, 0x9d, 0x34, 0xc1, 0x5f, 0xad, 0xf5, 0xc9, 0x46, - 0xa9, 0xa0, 0x72, 0x17, + 0xb4, 0xf8, 0x8a, 0x29, 0x2d, 0x09, 0xd9, 0x35, 0xb4, 0x77, 0x5a, 0x29, 0x30, 0xeb, + 0x38, 0xce, 0xbd, 0x5a, 0xf6, 0xff, 0x3f, 0x39, 0xef, 0x5b, 0xb2, 0x4c, 0xd5, 0x72, + 0x81, 0xf0, 0x8c, 0xfb, ], op: [ 0xae, 0xee, 0xa5, 0x0c, 0x6b, 0xb0, 0x2e, 0x5e, 0x22, 0x4d, 0xc2, 0x95, 0x9c, 0x22, 0x9d, 0x0e, 0x3b, 0xb8, 0x79, 0xc4, 0xab, 0x00, 0xaa, 0x0a, 0xb2, 0x5a, 0x40, 0x10, - 0x6b, 0x80, 0xbb, 0xb7, 0xec, 0x99, 0xeb, 0x6f, 0x67, 0x1d, 0x0a, 0x9e, 0x84, 0x5a, - 0xbf, 0xb7, 0x8a, 0xec, 0xe9, 0x32, 0xeb, 0x13, 0xf5, 0xae, 0xd6, 0x4f, 0x20, 0xa7, - 0x77, 0xc9, 0x46, 0xe9, 0xcd, 0x7a, 0x24, 0x23, + 0x6b, 0x80, 0xbb, 0xb7, 0x19, 0xe0, 0x26, 0x4b, 0x82, 0x88, 0xf7, 0x3e, 0xbf, 0x97, + 0x14, 0xb0, 0xdf, 0x85, 0x8e, 0xf7, 0xab, 0x39, 0xec, 0x50, 0x2c, 0xd2, 0x98, 0xf2, + 0xc4, 0x84, 0xa9, 0xf4, 0xc7, 0xda, 0x74, 0x36, ], c_out: [ - 0x28, 0x9d, 0x00, 0xd4, 0x62, 0x78, 0x0b, 0xdb, 0xb6, 0xcd, 0x6c, 0xec, 0x93, 0x6b, - 0xe6, 0x5e, 0x63, 0x0d, 0x4a, 0x3c, 0x2a, 0xf7, 0x6e, 0x10, 0x4b, 0x17, 0x4e, 0x3d, - 0x5b, 0x71, 0x66, 0x39, 0xb0, 0x68, 0xb3, 0x85, 0x00, 0xd8, 0x04, 0x00, 0xee, 0x64, - 0x2f, 0x8e, 0x08, 0xc8, 0xdb, 0x29, 0xff, 0xd5, 0xa9, 0xda, 0xde, 0x84, 0xa5, 0x49, - 0x5d, 0x57, 0x7b, 0x2f, 0x56, 0xd3, 0x2b, 0x07, 0x96, 0xca, 0x23, 0xf0, 0x0f, 0x0f, - 0x8e, 0xf9, 0x93, 0x07, 0x4f, 0x88, 0x0d, 0x6a, 0xeb, 0xcb, + 0x94, 0xe3, 0x7f, 0xd6, 0x62, 0x82, 0xc0, 0x2e, 0x90, 0xe7, 0x69, 0x91, 0x4c, 0xaf, + 0x95, 0xa4, 0x95, 0xf4, 0x89, 0x7f, 0x55, 0xa5, 0xae, 0x95, 0xad, 0xe8, 0xbf, 0x67, + 0x61, 0xe3, 0x1b, 0xa5, 0xd1, 0xcf, 0xeb, 0x30, 0x6f, 0x4e, 0x22, 0x01, 0x42, 0x51, + 0xcb, 0xe3, 0xf8, 0x72, 0x4b, 0xe7, 0x69, 0x21, 0xe2, 0xad, 0xa4, 0x6e, 0x3b, 0x14, + 0x5d, 0x1b, 0x04, 0x3e, 0xb1, 0x2a, 0x0e, 0xfa, 0xb5, 0x16, 0x09, 0x34, 0xbc, 0x75, + 0x9e, 0x02, 0x01, 0xd8, 0x66, 0xad, 0xa7, 0x44, 0x35, 0x71, ], }, TestVector { @@ -1566,36 +1559,35 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x51, 0x00, 0x89, 0x08, 0xa6, 0xcd, 0xd0, 0xaa, 0x02, 0x1b, 0x88, 0x8b, 0x98, 0xe2, 0x3c, 0x39, 0x11, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0x35, 0x6f, 0xc7, 0x2e, 0x1b, 0xf1, 0xe3, 0xa2, 0xa5, 0x9a, 0xa9, 0xe4, 0x75, 0x15, - 0x5c, 0xf7, 0x43, 0xf8, 0xfd, 0xf0, 0xd1, 0x5b, 0x4c, 0xc4, 0x02, 0x60, 0xd0, 0xd0, - 0x9a, 0xda, 0x04, 0x08, + 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, + 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, + 0x3e, 0xe8, 0xed, 0x20, ], cmx: [ - 0xca, 0xa2, 0x8a, 0x69, 0x04, 0x54, 0x66, 0x37, 0xa7, 0xd4, 0xe5, 0xfb, 0xc2, 0x65, - 0x4c, 0xbf, 0x24, 0x4d, 0x18, 0x77, 0x9d, 0x35, 0x62, 0x25, 0x6c, 0x14, 0xd5, 0xb1, - 0x00, 0x5d, 0xc6, 0x0f, + 0xbe, 0x43, 0xee, 0x84, 0x70, 0x70, 0x75, 0xac, 0x48, 0x08, 0xd0, 0x97, 0x54, 0x07, + 0xc0, 0x27, 0x36, 0xd7, 0x66, 0x64, 0xf4, 0xe7, 0xae, 0xce, 0x01, 0xd9, 0xcc, 0x68, + 0x32, 0x4a, 0xe9, 0x04, ], esk: [ - 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, 0x42, 0x0e, 0xff, 0xd7, - 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, 0x91, 0x90, 0x01, 0xf8, - 0x66, 0xa8, 0xe9, 0x2c, + 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, 0x14, 0x49, 0x72, 0x62, + 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, 0xe2, 0x63, 0xf3, 0xe3, + 0x99, 0x07, 0xea, 0x0c, ], ephemeral_key: [ - 0x00, 0x62, 0x7e, 0x29, 0xc1, 0x83, 0x3e, 0x4e, 0x8f, 0xad, 0xe0, 0x82, 0x52, 0xf3, - 0x83, 0x67, 0x78, 0xb9, 0x39, 0x4c, 0x1f, 0xfe, 0xab, 0x70, 0xbf, 0x35, 0x93, 0xd5, - 0x9a, 0x81, 0xa0, 0xa5, + 0xfa, 0x19, 0xa1, 0x52, 0x7b, 0x76, 0x04, 0x8f, 0xf3, 0x7f, 0xa4, 0xf8, 0x27, 0x89, + 0xfe, 0x80, 0xb0, 0xcd, 0xd3, 0x5d, 0x5d, 0xa9, 0xc2, 0xec, 0x3f, 0xe3, 0x04, 0x38, + 0x05, 0xc0, 0x61, 0x23, ], shared_secret: [ - 0xa9, 0x93, 0x34, 0x1f, 0x99, 0xeb, 0xa8, 0x2d, 0xb6, 0xec, 0x5e, 0x71, 0x3e, 0xe2, - 0x9c, 0x01, 0xf4, 0xce, 0x2a, 0x8b, 0xb6, 0xb5, 0xeb, 0xb6, 0x0b, 0xa6, 0xeb, 0xa9, - 0x6b, 0xa4, 0x17, 0x9b, + 0x2d, 0xb5, 0xb8, 0x92, 0xb6, 0x1b, 0x9c, 0x55, 0x3b, 0x6c, 0x9b, 0x7a, 0xcc, 0x7d, + 0x71, 0x05, 0xc1, 0xdd, 0x4c, 0x28, 0xc6, 0x7f, 0x97, 0x8b, 0x6d, 0x79, 0xc7, 0x1b, + 0x98, 0xa0, 0xd0, 0x00, ], k_enc: [ - 0x35, 0x81, 0x19, 0x19, 0x3c, 0x9d, 0x2a, 0xb6, 0xd4, 0x95, 0xe0, 0x19, 0xf9, 0x7a, - 0x1c, 0x41, 0x30, 0xae, 0xe6, 0x3d, 0xae, 0xc6, 0xbb, 0xa2, 0xf2, 0x74, 0x40, 0x0f, - 0xd3, 0x4f, 0xad, 0x28, + 0x16, 0xe3, 0xf9, 0x85, 0xc0, 0x7f, 0xef, 0xe5, 0x30, 0xd9, 0xe6, 0x94, 0x5e, 0xde, + 0xc1, 0x90, 0x3b, 0xb1, 0xca, 0x8d, 0xa5, 0xa2, 0x5b, 0xe9, 0x59, 0x78, 0x63, 0x7a, + 0x40, 0x8c, 0x2e, 0xfe, ], p_enc: [ 0x02, 0xc6, 0xe8, 0xf0, 0xd5, 0x0a, 0xe8, 0x05, 0x87, 0x91, 0xdc, 0x0e, 0x46, 0x49, @@ -1641,68 +1633,68 @@ pub(crate) fn test_vectors() -> Vec { 0x84, 0x37, 0x3f, 0x4f, ], c_enc: [ - 0x31, 0xac, 0xda, 0xa6, 0xc1, 0x76, 0xbb, 0x7a, 0x2c, 0x7d, 0x66, 0x09, 0xdc, 0x2c, - 0x5e, 0x7b, 0x2e, 0xe7, 0x1d, 0xa9, 0x3c, 0x73, 0x87, 0x52, 0x74, 0xfa, 0x6c, 0x2a, - 0xd6, 0x26, 0x13, 0xc7, 0x18, 0x9b, 0x35, 0x33, 0xec, 0xf0, 0x34, 0xd8, 0x76, 0xc7, - 0x26, 0xf1, 0xed, 0x99, 0x43, 0xd4, 0x45, 0x07, 0x87, 0x52, 0x75, 0xa8, 0xe3, 0x71, - 0x0a, 0x11, 0x8d, 0x91, 0x64, 0x72, 0x91, 0x28, 0x6c, 0xf8, 0x80, 0xa7, 0x82, 0xab, - 0xea, 0xa8, 0xa6, 0xc3, 0x2f, 0xdf, 0x6f, 0x30, 0x4b, 0x0e, 0xe5, 0xbc, 0xb1, 0x4b, - 0x82, 0x79, 0x2a, 0xa3, 0xaf, 0xd7, 0x24, 0x3f, 0x57, 0xb7, 0xdc, 0xa7, 0x93, 0x52, - 0x19, 0xdf, 0x98, 0x2c, 0xe1, 0x28, 0xae, 0xa6, 0xf6, 0xbd, 0x18, 0xe1, 0x30, 0x7e, - 0xba, 0x0e, 0x3d, 0xb0, 0x06, 0x14, 0xc2, 0x65, 0xc6, 0xf2, 0x8b, 0xfe, 0x58, 0xc1, - 0x1d, 0x4a, 0xc9, 0x6d, 0x49, 0x02, 0x96, 0x7b, 0x54, 0xbc, 0x5d, 0xd1, 0x5c, 0x14, - 0x3f, 0xf4, 0x2b, 0xbb, 0x62, 0xb9, 0x34, 0xb0, 0x9e, 0x79, 0xb6, 0x1e, 0xaf, 0xe7, - 0x9a, 0xbc, 0x86, 0x94, 0x47, 0x5b, 0x6c, 0x8e, 0x19, 0x94, 0xba, 0x05, 0x5e, 0xa3, - 0xc1, 0x82, 0x93, 0xb0, 0x3c, 0x42, 0x49, 0x50, 0x1d, 0xfd, 0xc0, 0x14, 0x60, 0xcf, - 0x78, 0xcd, 0x97, 0x51, 0x30, 0xae, 0x34, 0x05, 0xba, 0x7d, 0xdc, 0x71, 0x30, 0xcb, - 0xdb, 0xb9, 0x8c, 0x7a, 0xaf, 0x6b, 0x1d, 0x0b, 0x44, 0xa5, 0x16, 0x79, 0xaa, 0x63, - 0x0a, 0x43, 0xae, 0x23, 0xb3, 0xd2, 0x2f, 0x73, 0x4c, 0xe1, 0xdb, 0xed, 0xea, 0x17, - 0x5a, 0x00, 0x62, 0xb0, 0x6e, 0x23, 0xf4, 0xd0, 0x6d, 0x2a, 0xd0, 0x45, 0xae, 0x98, - 0x2d, 0xb4, 0x34, 0x8f, 0x20, 0xc8, 0x9b, 0xf9, 0x67, 0x0e, 0x2f, 0xda, 0x47, 0x2e, - 0x55, 0xce, 0x4c, 0x35, 0x82, 0xb7, 0x64, 0x43, 0xe0, 0xab, 0xbb, 0x77, 0x8a, 0xec, - 0xa0, 0xf3, 0x9c, 0x55, 0xb6, 0xab, 0xbe, 0xd8, 0x1f, 0xde, 0x89, 0xad, 0x2c, 0x56, - 0x7d, 0xfe, 0x27, 0x7b, 0xb2, 0x69, 0xac, 0x6a, 0xe0, 0xe1, 0x88, 0x39, 0x8d, 0xea, - 0x24, 0xad, 0xcc, 0xe1, 0x82, 0xe7, 0xfd, 0xdc, 0x80, 0xeb, 0xd7, 0x69, 0xd0, 0xf0, - 0x76, 0xf9, 0xaf, 0x2d, 0xd9, 0x83, 0x07, 0xa5, 0x27, 0xc6, 0x99, 0x42, 0xdf, 0xa3, - 0xe7, 0xf4, 0x86, 0x76, 0x10, 0x1a, 0x47, 0xeb, 0x07, 0x80, 0xb6, 0x90, 0xb1, 0xaf, - 0x10, 0xfc, 0xfb, 0x5e, 0xe2, 0xbd, 0x40, 0xd2, 0x7d, 0x10, 0x9b, 0xa1, 0x5a, 0xb0, - 0xb1, 0xe9, 0x55, 0x4f, 0xdd, 0xfa, 0x81, 0x6b, 0x99, 0xcd, 0x8f, 0xdd, 0xe6, 0x81, - 0xae, 0x6b, 0x6c, 0xbb, 0xfb, 0xf0, 0x2c, 0x36, 0x32, 0x68, 0xd0, 0xf3, 0xc6, 0xa7, - 0x26, 0x1b, 0x6d, 0x00, 0x87, 0xbc, 0xad, 0xb6, 0xfb, 0x9b, 0xf3, 0x93, 0x04, 0xfc, - 0x08, 0x41, 0x5d, 0x83, 0x6f, 0xe4, 0x09, 0xa4, 0x3f, 0xaf, 0x9e, 0x28, 0xfb, 0x48, - 0x3f, 0x4a, 0x47, 0xaa, 0xd7, 0xe1, 0xf7, 0x97, 0x30, 0xb3, 0x21, 0x53, 0x60, 0x80, - 0xdb, 0x35, 0x12, 0x48, 0xb2, 0x66, 0x9b, 0x6e, 0x74, 0x48, 0x90, 0x87, 0xae, 0x72, - 0xba, 0x15, 0xd2, 0xae, 0xdd, 0x0c, 0x1e, 0x7e, 0xb1, 0x5a, 0x2f, 0x5a, 0x77, 0x31, - 0xeb, 0x45, 0xa6, 0x17, 0x8a, 0x44, 0x87, 0x09, 0x31, 0xec, 0x8e, 0x34, 0x8c, 0x19, - 0x2b, 0xc8, 0x87, 0xc8, 0x63, 0x60, 0x56, 0x67, 0x6f, 0x58, 0xd0, 0xc6, 0x34, 0xfc, - 0x99, 0xea, 0x7b, 0x07, 0xfa, 0x1b, 0x62, 0x99, 0xae, 0x5d, 0xbf, 0xe0, 0x84, 0x45, - 0xad, 0x99, 0x9f, 0x45, 0xdf, 0x00, 0xf1, 0xa4, 0x7a, 0xa5, 0xef, 0x6f, 0x88, 0xcd, - 0xba, 0x80, 0xc8, 0x8f, 0x94, 0x01, 0xe6, 0xe9, 0x09, 0xca, 0x2c, 0x5d, 0xe2, 0xcf, - 0x8f, 0x6a, 0x98, 0x44, 0xca, 0x32, 0xfe, 0x91, 0xf7, 0x13, 0xfe, 0x10, 0xa0, 0x69, - 0x8a, 0x1b, 0x3b, 0xfd, 0xf4, 0x47, 0x43, 0x75, 0xb4, 0x79, 0x1d, 0xc8, 0x50, 0x50, - 0xc9, 0x28, 0x90, 0x0e, 0x73, 0x1f, 0x7c, 0x4a, 0x12, 0x9d, 0x8e, 0x21, 0xfc, 0xf4, - 0x17, 0x62, 0x7c, 0x47, 0xdd, 0xc9, 0xf5, 0x88, 0x40, 0x38, 0x41, 0x31, 0x7a, 0x9a, - 0xc2, 0x6e, 0xef, 0x6c, 0xda, 0x23, + 0x2d, 0x40, 0x4a, 0x68, 0x81, 0xa6, 0xee, 0x76, 0x0c, 0xb5, 0x3b, 0x9c, 0xc2, 0x71, + 0x5c, 0xa7, 0x6a, 0x3a, 0x2f, 0xc9, 0x69, 0x3b, 0x1a, 0xbb, 0xcd, 0xc7, 0x5c, 0xb6, + 0xd6, 0xc3, 0x6e, 0xcf, 0x84, 0xd6, 0x93, 0x67, 0x2c, 0x53, 0xce, 0xd8, 0x79, 0x8c, + 0xc8, 0xf1, 0xe5, 0x3b, 0x8a, 0x9d, 0xe7, 0xbb, 0xb5, 0xe8, 0xc5, 0xa4, 0x6c, 0x3a, + 0x74, 0x12, 0xdf, 0x11, 0xc5, 0xda, 0x16, 0xb4, 0xdd, 0x22, 0x90, 0x1a, 0x59, 0x2b, + 0x0e, 0x93, 0x29, 0x77, 0xba, 0x06, 0x67, 0x3d, 0x6f, 0xd0, 0x38, 0xac, 0xba, 0xa9, + 0xbf, 0x79, 0xc1, 0x5b, 0xa6, 0x2b, 0x6e, 0x30, 0x74, 0xef, 0x95, 0x3b, 0x81, 0x4c, + 0xf1, 0xbd, 0xf0, 0x15, 0x77, 0xed, 0x3e, 0x3f, 0xae, 0xf4, 0x71, 0x55, 0xc9, 0x1c, + 0x68, 0xee, 0x32, 0x88, 0x1b, 0x73, 0x74, 0x94, 0xb3, 0xb4, 0x76, 0x08, 0x3b, 0x3b, + 0xd1, 0x77, 0x93, 0xc4, 0x98, 0x93, 0x1e, 0xaa, 0x92, 0xb1, 0x7c, 0x7d, 0x10, 0x47, + 0x58, 0xfc, 0x8b, 0x34, 0x93, 0xd2, 0x47, 0x41, 0x7f, 0x5e, 0xc1, 0x97, 0x9a, 0x35, + 0x28, 0x93, 0xe9, 0x95, 0x63, 0xb6, 0xc3, 0xab, 0x95, 0xcc, 0x5a, 0xfa, 0x37, 0x32, + 0xef, 0xae, 0xce, 0x9e, 0x74, 0x32, 0xc8, 0x04, 0x15, 0xe2, 0x5f, 0x55, 0x56, 0x53, + 0xc7, 0xda, 0x5d, 0xb0, 0xcc, 0x61, 0x08, 0x74, 0x21, 0x95, 0x9b, 0xb1, 0xdf, 0x80, + 0x03, 0xb7, 0x3d, 0xa0, 0xbe, 0xf0, 0x60, 0xf3, 0xa8, 0x4c, 0x8b, 0xc2, 0x4c, 0xc7, + 0x6d, 0x0d, 0x9e, 0x9c, 0x33, 0x76, 0x5c, 0x20, 0xf0, 0x7d, 0x80, 0xe2, 0x0f, 0xdf, + 0x27, 0x81, 0x5d, 0xbd, 0x9d, 0x71, 0x7c, 0x09, 0x66, 0xf8, 0x0b, 0x94, 0xb9, 0x59, + 0x15, 0x08, 0x1e, 0xa4, 0x55, 0x37, 0xa5, 0xa0, 0x74, 0xb9, 0xc9, 0x4b, 0x43, 0xdd, + 0xf4, 0xa9, 0xcb, 0xad, 0xe9, 0x04, 0x51, 0x0e, 0xaa, 0x96, 0x9e, 0x66, 0x6c, 0x94, + 0x34, 0xb9, 0xf6, 0x3e, 0xae, 0x62, 0xad, 0x58, 0x27, 0x99, 0x62, 0xe9, 0x41, 0x33, + 0x05, 0x5c, 0xbc, 0xc4, 0xb1, 0x55, 0xc0, 0x0f, 0x1b, 0x83, 0xff, 0x41, 0x28, 0xa8, + 0xab, 0xb4, 0xce, 0x68, 0xe9, 0xf1, 0xe3, 0x08, 0xe6, 0xf9, 0x7e, 0x51, 0x3a, 0xf5, + 0x95, 0x47, 0x1a, 0x16, 0x77, 0xef, 0x78, 0xe9, 0x77, 0x0f, 0x43, 0xad, 0xde, 0x1a, + 0x64, 0x58, 0x6d, 0xe6, 0xa5, 0x87, 0xc3, 0xd6, 0x93, 0xfe, 0xa8, 0xfc, 0xc6, 0xac, + 0xc8, 0x94, 0x96, 0x1e, 0x2f, 0x47, 0xb2, 0x02, 0xe8, 0x6a, 0x57, 0x38, 0x79, 0xb5, + 0xbf, 0xd7, 0x29, 0xda, 0x2f, 0xbe, 0xfc, 0x64, 0x5c, 0xfa, 0xb1, 0x88, 0x0d, 0x51, + 0x76, 0x40, 0xdf, 0x5f, 0x53, 0xe5, 0x7c, 0x72, 0xd6, 0x5a, 0x63, 0x3a, 0xa5, 0x36, + 0xb2, 0x98, 0x34, 0xbf, 0x28, 0x16, 0xb1, 0xf7, 0x16, 0xbf, 0x43, 0x6d, 0x6b, 0x2b, + 0x6e, 0x47, 0x73, 0x28, 0xc9, 0x58, 0xa6, 0xb8, 0xcf, 0x73, 0xb9, 0x5d, 0x22, 0xf6, + 0x99, 0x3b, 0x3f, 0xc5, 0x25, 0xdb, 0x62, 0x7f, 0x6f, 0x38, 0xd0, 0x77, 0x9a, 0x1d, + 0x39, 0xaf, 0x05, 0xed, 0x74, 0xfd, 0xfe, 0xff, 0x98, 0x7a, 0x95, 0x88, 0xd8, 0x0b, + 0x7e, 0x79, 0x69, 0x4a, 0xe4, 0x55, 0x29, 0x29, 0x88, 0x1c, 0x5b, 0xfe, 0x20, 0x49, + 0x2f, 0xd6, 0xf3, 0x37, 0xca, 0x88, 0xdf, 0xb5, 0x01, 0xe5, 0x45, 0xd2, 0x36, 0x73, + 0xac, 0xac, 0xbc, 0x3d, 0x33, 0x14, 0xa8, 0xbb, 0xf5, 0xec, 0x70, 0xb7, 0x05, 0xcc, + 0x9d, 0x26, 0x57, 0xbd, 0xd5, 0xa7, 0x09, 0x15, 0xbe, 0xf6, 0xd0, 0xf0, 0x39, 0xd3, + 0xeb, 0xa6, 0xbb, 0x71, 0x5b, 0xe5, 0x1e, 0xbf, 0x6e, 0xf6, 0x59, 0xea, 0x32, 0xff, + 0x80, 0xc8, 0x2c, 0x04, 0x21, 0x67, 0x5f, 0xe3, 0x71, 0xef, 0x49, 0xf1, 0xb9, 0xe3, + 0x8f, 0x43, 0x7b, 0x4a, 0x76, 0x55, 0xdc, 0x29, 0x16, 0xaa, 0x30, 0x86, 0xde, 0x6c, + 0x62, 0xa8, 0x2b, 0x36, 0x1c, 0x05, 0x3f, 0xc6, 0x34, 0x54, 0xcc, 0xd0, 0x2c, 0x22, + 0xd4, 0x1f, 0xf5, 0xbb, 0x83, 0x62, 0xde, 0xaa, 0x70, 0x82, 0x5a, 0xd2, 0xf9, 0x93, + 0x63, 0x9f, 0xc4, 0x46, 0x06, 0x9d, 0x78, 0xa6, 0x1d, 0x33, 0x8d, 0xf5, 0x8f, 0x77, + 0x63, 0xe3, 0x55, 0xe6, 0xa9, 0xff, ], ock: [ - 0x9c, 0x10, 0x3d, 0xd5, 0xd6, 0x38, 0x6c, 0xdd, 0x67, 0x69, 0x51, 0xe6, 0x56, 0x4b, - 0x16, 0x6b, 0xc5, 0xc5, 0x72, 0x32, 0xcf, 0xc3, 0x1e, 0x0e, 0x69, 0xce, 0x84, 0xda, - 0xe8, 0x32, 0x76, 0xbe, + 0x8b, 0x0d, 0x29, 0x8e, 0xe8, 0xb4, 0x25, 0x34, 0xa4, 0x2f, 0xb9, 0x63, 0x5b, 0xa7, + 0x58, 0xea, 0x9f, 0x91, 0x8b, 0x83, 0x16, 0xc0, 0xe8, 0x94, 0xa9, 0x08, 0x48, 0x89, + 0x01, 0xd9, 0xfb, 0xa3, ], op: [ 0x8e, 0x66, 0xb7, 0x92, 0xec, 0xb1, 0x56, 0xef, 0x68, 0x5e, 0xe8, 0xea, 0x35, 0xd3, 0x82, 0x75, 0x8b, 0xa4, 0x15, 0x97, 0xa3, 0x3a, 0x93, 0xba, 0xf3, 0x81, 0xd6, 0x3c, - 0x17, 0x5b, 0xa9, 0x8b, 0x01, 0xa3, 0x66, 0x1e, 0xa9, 0xaa, 0xb8, 0xf4, 0x32, 0x53, - 0x42, 0x0e, 0xff, 0xd7, 0xa4, 0x83, 0xc2, 0x79, 0xd4, 0x18, 0x18, 0xbc, 0xb3, 0xee, - 0x91, 0x90, 0x01, 0xf8, 0x66, 0xa8, 0xe9, 0x2c, + 0x17, 0x5b, 0xa9, 0x8b, 0xf9, 0xf7, 0xa0, 0x10, 0x5e, 0xa9, 0xf4, 0x45, 0xfb, 0x7a, + 0x14, 0x49, 0x72, 0x62, 0xc6, 0xe4, 0xd7, 0x32, 0x89, 0x32, 0x7b, 0x8a, 0x2d, 0xf5, + 0xe2, 0x63, 0xf3, 0xe3, 0x99, 0x07, 0xea, 0x0c, ], c_out: [ - 0xdf, 0x6b, 0xb6, 0x2e, 0x3b, 0x64, 0xf7, 0xe9, 0x37, 0xc1, 0xde, 0x38, 0xaa, 0xc5, - 0xe6, 0xb1, 0x61, 0x35, 0xba, 0x2f, 0x9d, 0xbe, 0xed, 0xb0, 0x7a, 0x45, 0xb6, 0xf0, - 0x9d, 0xf3, 0xeb, 0xec, 0xac, 0x04, 0x6c, 0x61, 0x92, 0xfb, 0xe8, 0x95, 0xd2, 0x31, - 0x02, 0x77, 0xb3, 0xe0, 0x3a, 0x90, 0xfd, 0xc8, 0x53, 0x48, 0x4a, 0x01, 0x5c, 0x88, - 0xd6, 0x63, 0x2e, 0x97, 0xba, 0x98, 0xad, 0xca, 0x9e, 0x49, 0xf5, 0x38, 0xc3, 0xa7, - 0xcb, 0x6d, 0x77, 0x23, 0xbd, 0xcc, 0x9c, 0x03, 0xae, 0x88, + 0xf3, 0xbf, 0x90, 0x76, 0xf3, 0xdb, 0x66, 0x32, 0x6d, 0xa6, 0x0c, 0xc7, 0x94, 0x3c, + 0x85, 0x4d, 0x8d, 0xe9, 0x9f, 0x57, 0x53, 0xf7, 0x0c, 0x32, 0xed, 0x01, 0xfb, 0x2e, + 0x84, 0x9c, 0x9d, 0xc7, 0x3f, 0x80, 0xb5, 0xcb, 0xaa, 0xb4, 0x99, 0x2d, 0xd7, 0xe7, + 0x38, 0xb9, 0x61, 0xfd, 0x75, 0x3f, 0x7c, 0x5b, 0x29, 0x24, 0xd1, 0xd9, 0x63, 0x06, + 0x61, 0x33, 0x92, 0x59, 0x28, 0x3e, 0x3a, 0x95, 0x3c, 0x57, 0xdf, 0x3a, 0x48, 0xca, + 0x82, 0x71, 0xfc, 0x5f, 0x26, 0x4d, 0x6f, 0x15, 0xb6, 0xb3, ], }, TestVector { @@ -1776,36 +1768,35 @@ pub(crate) fn test_vectors() -> Vec { 0x7e, 0xed, 0xd2, 0xa7, 0x06, 0x44, 0x07, 0x34, 0x78, 0x41, 0x01, 0xae, 0x2d, 0x8e, 0x87, 0xe5, 0x05, 0xad, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0x32, 0x91, 0x87, 0x35, 0x66, 0x3f, 0x34, 0xad, 0xa0, 0x22, 0x8a, 0xea, 0x4a, 0xcc, - 0x19, 0x2a, 0x12, 0x3f, 0xcf, 0xa0, 0x60, 0x46, 0x89, 0xf9, 0x1a, 0xcb, 0xe9, 0x38, - 0x31, 0xe4, 0x8c, 0x0c, + 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, + 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, + 0x45, 0x89, 0x35, 0x14, ], cmx: [ - 0xde, 0x7b, 0xf1, 0x55, 0x08, 0x29, 0x51, 0x96, 0x0a, 0x10, 0xbb, 0x8b, 0x75, 0x41, - 0x02, 0x43, 0x0f, 0x89, 0xf5, 0x32, 0x67, 0x24, 0x04, 0x36, 0x81, 0xf5, 0x06, 0xf7, - 0x48, 0xe2, 0x6f, 0x07, + 0x6d, 0x29, 0x97, 0xd1, 0xce, 0x0a, 0x94, 0x9a, 0x63, 0x70, 0x0f, 0x46, 0x1b, 0x57, + 0x12, 0xae, 0xeb, 0x43, 0xd4, 0x55, 0x04, 0xe3, 0x5b, 0xda, 0x16, 0x52, 0x97, 0x77, + 0xc7, 0x4d, 0x19, 0x1b, ], esk: [ - 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, 0x59, 0xa1, 0x33, 0xf3, - 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, 0xdd, 0x63, 0xe0, 0x62, - 0x83, 0x05, 0x47, 0x08, + 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, 0x6b, 0xa0, 0x02, 0x0c, + 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, 0x57, 0x32, 0x63, 0xf4, + 0x99, 0xbd, 0x4c, 0x13, ], ephemeral_key: [ - 0x18, 0x20, 0x84, 0x5b, 0x2d, 0x90, 0xe5, 0x45, 0x76, 0x0f, 0xca, 0x4d, 0xab, 0x30, - 0xa6, 0x78, 0x3e, 0x03, 0x1c, 0x0e, 0x54, 0x28, 0xcc, 0x22, 0x6f, 0x3f, 0x40, 0x1d, - 0xec, 0x20, 0x0b, 0x11, + 0xe4, 0x76, 0x95, 0x86, 0x30, 0x4a, 0x6a, 0x9b, 0x3a, 0x2a, 0xef, 0x3a, 0xf5, 0x8b, + 0x97, 0xda, 0xc2, 0xcc, 0x4a, 0xeb, 0x38, 0x9f, 0x68, 0xc1, 0x28, 0x87, 0x73, 0x1e, + 0x0e, 0x12, 0xbc, 0x1e, ], shared_secret: [ - 0x79, 0x38, 0x77, 0xa1, 0xae, 0xda, 0xe9, 0xac, 0x6d, 0xa3, 0xd7, 0xe8, 0x02, 0xb5, - 0xbc, 0x77, 0x3c, 0x0d, 0x93, 0x1c, 0x79, 0x6d, 0x17, 0x0c, 0x59, 0x7f, 0x22, 0xba, - 0x6f, 0xcc, 0xa2, 0x06, + 0xf6, 0xba, 0x4b, 0x1f, 0xbe, 0x01, 0xfa, 0x2f, 0x1d, 0xd4, 0x09, 0x3c, 0x5c, 0xc4, + 0x85, 0xa9, 0xbf, 0xd9, 0xef, 0x0f, 0x57, 0x89, 0x49, 0xd6, 0xe1, 0x00, 0xb0, 0x05, + 0x5c, 0xb8, 0xf3, 0x31, ], k_enc: [ - 0x28, 0x20, 0xb9, 0x38, 0xd6, 0xfc, 0xea, 0x99, 0xa7, 0x23, 0x37, 0x50, 0xa0, 0xf0, - 0x9a, 0x32, 0x10, 0xad, 0x91, 0x73, 0x46, 0x16, 0x6a, 0xea, 0xdc, 0x89, 0xbb, 0x50, - 0xf4, 0x54, 0x50, 0xa3, + 0xd3, 0xc2, 0x20, 0x51, 0x00, 0x3e, 0x88, 0x2a, 0x5d, 0xdd, 0xfb, 0x48, 0x23, 0xd6, + 0x77, 0x26, 0x96, 0xa7, 0xe9, 0x9f, 0x26, 0xb1, 0xa6, 0xac, 0xd2, 0x4b, 0xee, 0xd5, + 0xf2, 0x2f, 0x9f, 0xf8, ], p_enc: [ 0x02, 0x81, 0xf2, 0x75, 0x7c, 0x53, 0x2e, 0xd3, 0xb6, 0x2e, 0x89, 0x01, 0x22, 0x92, @@ -1851,68 +1842,68 @@ pub(crate) fn test_vectors() -> Vec { 0x3e, 0xcc, 0xc6, 0x23, ], c_enc: [ - 0xd9, 0x6a, 0xe8, 0x2f, 0xba, 0xff, 0xb9, 0xe4, 0xbd, 0x36, 0x47, 0x57, 0x96, 0x33, - 0xbc, 0x8a, 0x89, 0x66, 0xae, 0x4e, 0x18, 0x85, 0x99, 0xdc, 0x3c, 0xf0, 0x30, 0x41, - 0xd2, 0x64, 0x4f, 0x60, 0x3c, 0xe5, 0x56, 0x2e, 0x7f, 0xa1, 0xd3, 0x83, 0x12, 0x79, - 0xb6, 0x32, 0x60, 0x4d, 0x06, 0x5e, 0xd2, 0x46, 0xad, 0x2d, 0x4f, 0x73, 0xf3, 0xa4, - 0x1b, 0x2a, 0x27, 0x99, 0xe5, 0xba, 0xf8, 0x6e, 0x7d, 0x9f, 0xcc, 0x64, 0xd5, 0x6b, - 0xde, 0x56, 0xcb, 0xb0, 0x01, 0xeb, 0x7c, 0x7c, 0x0c, 0xf1, 0xe2, 0xae, 0xc3, 0xce, - 0xb1, 0x49, 0x2d, 0xdf, 0x4e, 0x35, 0x20, 0x76, 0x1f, 0x70, 0xf6, 0xa9, 0x5c, 0x9e, - 0xde, 0xed, 0x51, 0x43, 0x6d, 0xca, 0xcf, 0x71, 0x1e, 0xb5, 0x53, 0x24, 0xd3, 0xf0, - 0x1d, 0xcc, 0xa0, 0x1b, 0xca, 0x15, 0xba, 0xf2, 0x8f, 0xed, 0x81, 0x4c, 0xc3, 0x3a, - 0x43, 0x6b, 0xbc, 0x08, 0x60, 0x56, 0x78, 0x55, 0xa4, 0x9f, 0x5e, 0xfd, 0x49, 0xea, - 0x78, 0x30, 0xc2, 0xf6, 0x00, 0x61, 0xd8, 0x13, 0xa8, 0x49, 0xb4, 0x40, 0xb1, 0x2e, - 0x8f, 0x31, 0xe2, 0xdc, 0x0c, 0x39, 0x4c, 0xeb, 0x92, 0x4f, 0x0d, 0xc6, 0xd5, 0x7b, - 0xcc, 0x39, 0x1d, 0x4a, 0x5f, 0x56, 0x9f, 0x34, 0x74, 0x6b, 0x9d, 0x92, 0x08, 0x82, - 0x25, 0xb1, 0xaa, 0x3e, 0x90, 0x6f, 0x6d, 0xe4, 0xa7, 0x92, 0x2a, 0xc1, 0x16, 0xac, - 0xb2, 0x78, 0xe8, 0xef, 0xbb, 0xf6, 0xf1, 0xe3, 0xe0, 0x8d, 0x66, 0xb3, 0x4d, 0x6e, - 0xde, 0x34, 0xae, 0x78, 0x40, 0xa8, 0x80, 0x2b, 0x7c, 0x10, 0x0f, 0xa7, 0x98, 0x46, - 0x4d, 0xb5, 0x29, 0x45, 0xdb, 0xbe, 0x35, 0xe7, 0x7a, 0x77, 0x21, 0xb2, 0xe0, 0xf8, - 0xb9, 0xa1, 0x0f, 0x6b, 0xf9, 0xa2, 0x80, 0x8f, 0xa5, 0x85, 0xff, 0x21, 0xb0, 0xa3, - 0xaf, 0xfd, 0x5f, 0x3c, 0xb2, 0x30, 0x63, 0x4e, 0x2e, 0x43, 0xff, 0xde, 0x6d, 0x09, - 0x0a, 0xfc, 0xc6, 0x70, 0x4d, 0x7b, 0x3f, 0xc6, 0x15, 0x44, 0x85, 0x3b, 0xcd, 0xa7, - 0xa1, 0x06, 0xd8, 0x5b, 0xd8, 0xd8, 0x6c, 0x6f, 0x8c, 0xe0, 0x34, 0x01, 0x6e, 0xd9, - 0xa3, 0x69, 0x46, 0xf8, 0x52, 0x8b, 0x6f, 0x1e, 0x1a, 0x19, 0x82, 0xd6, 0x8d, 0x38, - 0x86, 0xe5, 0xea, 0xe6, 0xc1, 0xe3, 0x88, 0xf3, 0xde, 0xad, 0x0d, 0x35, 0x3b, 0x6c, - 0x0c, 0xbf, 0x57, 0xc2, 0xe4, 0x7d, 0x30, 0x72, 0x3e, 0xac, 0x95, 0x7b, 0x4a, 0xec, - 0x82, 0xc8, 0xa1, 0x00, 0x9e, 0x3d, 0x71, 0x96, 0x92, 0xb2, 0xfc, 0xbd, 0xda, 0xae, - 0x62, 0x5a, 0x89, 0x6a, 0x47, 0x29, 0x85, 0xb7, 0x9e, 0xb6, 0x2b, 0x1f, 0xe3, 0x3d, - 0x6e, 0x27, 0xbc, 0x1f, 0x10, 0xe4, 0xfe, 0x5c, 0x06, 0xb2, 0x4c, 0x59, 0x7f, 0x72, - 0x3c, 0x67, 0x13, 0x36, 0x13, 0xae, 0x8e, 0x15, 0x4d, 0x81, 0x69, 0x78, 0xb8, 0xfc, - 0xa6, 0x50, 0xc0, 0x1d, 0x77, 0x1a, 0x62, 0x69, 0x2a, 0x84, 0x82, 0x94, 0x2e, 0x28, - 0xfe, 0xf0, 0x45, 0x19, 0x9e, 0xd1, 0xa6, 0x64, 0x99, 0xeb, 0xa1, 0xee, 0xc1, 0x9a, - 0xc8, 0x4a, 0x12, 0xe4, 0x10, 0x29, 0xd2, 0x2f, 0x21, 0x87, 0x6e, 0xd7, 0x4a, 0x76, - 0xef, 0x39, 0xa0, 0x57, 0xce, 0x0a, 0x15, 0x8e, 0x68, 0x51, 0xec, 0x35, 0x6d, 0x97, - 0x7b, 0x1a, 0xa6, 0x8d, 0xcf, 0x70, 0x88, 0xa9, 0xf0, 0xf9, 0xe4, 0x75, 0xa2, 0xbb, - 0xc1, 0xc4, 0x49, 0x5b, 0x54, 0x6f, 0xff, 0xed, 0xaa, 0x66, 0xc4, 0xf9, 0x51, 0x74, - 0xc6, 0x2f, 0x56, 0x5a, 0x3c, 0xc0, 0xac, 0xaf, 0x85, 0x4a, 0xde, 0xd4, 0xb4, 0x25, - 0xa0, 0xc7, 0xdb, 0xcd, 0x37, 0x42, 0xa7, 0xe0, 0x59, 0x2e, 0x83, 0x73, 0x41, 0xf8, - 0x95, 0x32, 0x90, 0x99, 0xe1, 0x70, 0xb6, 0xff, 0xb1, 0x05, 0xfd, 0xbc, 0x77, 0x29, - 0x8e, 0x8c, 0x0f, 0x5e, 0xeb, 0x9e, 0x99, 0xc6, 0x58, 0x4b, 0xcf, 0xf1, 0x20, 0x20, - 0x9d, 0x69, 0x22, 0xb5, 0x34, 0xbe, 0xc9, 0xfa, 0xc1, 0xd7, 0xd2, 0x74, 0xdb, 0xcb, - 0x4a, 0x12, 0xea, 0x5a, 0x99, 0x21, 0x39, 0x2f, 0x00, 0x96, 0x60, 0x29, 0xff, 0x26, - 0x0e, 0xd2, 0x4c, 0x32, 0x78, 0x58, 0xe0, 0x34, 0x64, 0x0a, 0x8c, 0xfb, 0x28, 0xad, - 0x97, 0xe5, 0x3d, 0x80, 0xe1, 0xc9, + 0x72, 0x29, 0xa0, 0xa5, 0x6a, 0x14, 0x4b, 0x04, 0x2c, 0x1e, 0xad, 0x91, 0x80, 0xac, + 0x54, 0xda, 0xc6, 0xc5, 0x5c, 0xf4, 0xc2, 0x2f, 0xbe, 0x7c, 0xde, 0x99, 0x96, 0x0b, + 0xc6, 0x20, 0xd4, 0xdd, 0x60, 0xe4, 0xbf, 0x18, 0xa0, 0xea, 0x7a, 0xd9, 0x09, 0x3b, + 0xcd, 0x3f, 0xf6, 0xd1, 0x61, 0x1c, 0x56, 0x5f, 0x88, 0xe7, 0x35, 0xef, 0x4c, 0x51, + 0x8c, 0x77, 0xd6, 0x22, 0x28, 0xe1, 0xe4, 0xa1, 0x35, 0xca, 0x6c, 0xb4, 0xed, 0x5a, + 0xbb, 0xdf, 0x3e, 0x81, 0xd0, 0x96, 0x50, 0xa8, 0xfa, 0x9b, 0x5c, 0x3d, 0x05, 0xb6, + 0xda, 0xcf, 0x3c, 0x3d, 0xb3, 0xb3, 0x63, 0xe4, 0x10, 0x57, 0x23, 0x70, 0x0c, 0x69, + 0x13, 0x9f, 0x81, 0xec, 0xc4, 0x8d, 0x88, 0x3d, 0xa0, 0x39, 0xdd, 0xed, 0x5e, 0xf6, + 0x04, 0x0a, 0xb2, 0x12, 0x0e, 0x53, 0x3b, 0x1f, 0xfd, 0x06, 0x74, 0xdb, 0x5b, 0x92, + 0x6e, 0x58, 0x7f, 0x16, 0xe7, 0xe8, 0x96, 0x2b, 0x12, 0x48, 0x35, 0xbd, 0x56, 0xcf, + 0xd8, 0xe7, 0x5b, 0xf6, 0xaa, 0x4d, 0xcd, 0x4d, 0x6f, 0x0b, 0x55, 0x61, 0x71, 0x9c, + 0x80, 0xaa, 0x82, 0xb3, 0xbc, 0xea, 0x16, 0x7a, 0x31, 0xc6, 0x69, 0x87, 0x61, 0xe2, + 0xd2, 0x6c, 0xb5, 0x6d, 0xd3, 0x04, 0x16, 0x72, 0x1c, 0x93, 0x37, 0x32, 0x92, 0x85, + 0x33, 0x58, 0xfa, 0xfe, 0x74, 0x95, 0x55, 0x8d, 0xb9, 0x9e, 0x47, 0xa3, 0xa1, 0x6e, + 0xd2, 0x2c, 0xdb, 0x9d, 0x7d, 0x16, 0xcf, 0xd9, 0xa7, 0xbb, 0x55, 0x9c, 0x72, 0x86, + 0xed, 0x84, 0xf8, 0x89, 0x9c, 0xb0, 0x52, 0x2e, 0x8a, 0x49, 0x7f, 0x3e, 0x14, 0x45, + 0x2b, 0xa8, 0xa9, 0x4a, 0x7f, 0x58, 0xe5, 0xde, 0x37, 0x1d, 0x76, 0xec, 0xc9, 0xef, + 0xe2, 0x0a, 0xe7, 0x9b, 0xee, 0x12, 0xbc, 0xe4, 0xe4, 0xb6, 0xf2, 0x35, 0x35, 0xe5, + 0xc3, 0xc4, 0x3a, 0x4c, 0xa2, 0x07, 0x6f, 0xd6, 0x73, 0xf0, 0x80, 0x6f, 0xa9, 0x85, + 0xc5, 0x88, 0xd1, 0x14, 0xc0, 0x7d, 0x8c, 0xe3, 0xa2, 0x33, 0xe5, 0x4d, 0x77, 0x11, + 0x6c, 0x8a, 0x2a, 0x56, 0xa6, 0x82, 0xe7, 0xa4, 0x85, 0xdf, 0x71, 0xb3, 0x02, 0xa0, + 0x36, 0xdd, 0xab, 0x21, 0x4d, 0xee, 0x77, 0x62, 0x19, 0xcc, 0x24, 0x25, 0x94, 0xf7, + 0x5b, 0x8e, 0xbd, 0x56, 0x6d, 0x74, 0xb1, 0x6c, 0x9e, 0xc0, 0x05, 0x8b, 0xca, 0x28, + 0x81, 0xb7, 0x9b, 0x10, 0xe8, 0xa8, 0x01, 0x08, 0x20, 0x61, 0x8a, 0xc6, 0x52, 0x6c, + 0xf9, 0x4b, 0x13, 0xd9, 0x75, 0x9f, 0x37, 0x33, 0x93, 0x34, 0xe8, 0xb2, 0xc6, 0xbd, + 0xd1, 0xd0, 0xf5, 0xe2, 0x46, 0x3c, 0xff, 0x2b, 0x8d, 0xa6, 0xd2, 0xc6, 0x86, 0xaa, + 0x98, 0x7c, 0xd1, 0xf0, 0x7e, 0x9a, 0xa2, 0x60, 0xdd, 0x04, 0x28, 0xa4, 0xff, 0x78, + 0xaa, 0x8f, 0xda, 0x47, 0x7a, 0xb3, 0x8a, 0xcf, 0xcc, 0xb1, 0x90, 0x91, 0x77, 0xb5, + 0x27, 0xe9, 0x38, 0xf1, 0xf9, 0xdc, 0xf3, 0x1f, 0x4f, 0x40, 0xa9, 0x62, 0x89, 0x51, + 0xfc, 0x2a, 0x7a, 0xbc, 0x04, 0x1e, 0x8c, 0x93, 0x36, 0x08, 0xbb, 0x47, 0xb4, 0x50, + 0xb2, 0x8f, 0xee, 0xe0, 0x41, 0x58, 0xa8, 0x17, 0x4b, 0xff, 0xe4, 0x97, 0x06, 0x02, + 0x48, 0x86, 0x42, 0xc1, 0x9e, 0x61, 0xd4, 0x73, 0xf3, 0xde, 0x0c, 0xb0, 0xb6, 0x4a, + 0x30, 0xd6, 0xf1, 0x46, 0x68, 0xd1, 0xb0, 0x17, 0x77, 0x56, 0x6f, 0xb5, 0xac, 0xc2, + 0xe9, 0x2e, 0x64, 0xd9, 0x75, 0x7f, 0xba, 0x13, 0xc1, 0xee, 0x9c, 0xd0, 0x3a, 0xbe, + 0x98, 0xbd, 0x7e, 0x8a, 0xd7, 0x04, 0x1c, 0x3f, 0xea, 0xe7, 0xc1, 0xa7, 0x24, 0x3a, + 0xe3, 0x61, 0x0a, 0xac, 0x64, 0xfe, 0xc6, 0xc9, 0xfc, 0x94, 0x3d, 0x6a, 0xbc, 0xe9, + 0x10, 0xad, 0xbe, 0x23, 0xb5, 0x46, 0xb4, 0xc2, 0x4a, 0xa9, 0xf2, 0xce, 0x5d, 0x97, + 0x06, 0x2e, 0xe0, 0xd1, 0xcc, 0xc4, 0x8c, 0xfd, 0x1f, 0xdb, 0xa7, 0xfd, 0xac, 0x0b, + 0x04, 0xd1, 0xb3, 0xdc, 0x7a, 0x70, 0x78, 0x1c, 0xdd, 0xa2, 0xa2, 0x70, 0x3d, 0xe0, + 0x03, 0xcd, 0x01, 0x51, 0xec, 0x65, 0xbf, 0x7d, 0x1a, 0xc6, 0x3b, 0xb7, 0x35, 0xbc, + 0x2b, 0xb6, 0x7a, 0xd2, 0xb0, 0x1e, 0xd6, 0xb9, 0xae, 0x2e, 0xbb, 0xd3, 0x7a, 0x8f, + 0x8e, 0xc1, 0xa6, 0x53, 0xa8, 0x7e, ], ock: [ - 0x28, 0xcf, 0x3b, 0xea, 0xc3, 0xbd, 0xe2, 0xe9, 0x63, 0xaa, 0x60, 0x91, 0x3f, 0x10, - 0x5d, 0x25, 0x67, 0xcd, 0xaf, 0xbb, 0x66, 0x09, 0x08, 0x5a, 0x84, 0x3f, 0x75, 0x68, - 0xe4, 0x92, 0xd4, 0x4e, + 0x1b, 0xa4, 0xac, 0xd7, 0x75, 0x10, 0xc4, 0xf0, 0xc7, 0x66, 0xad, 0xf7, 0xc7, 0xdf, + 0x1d, 0x1c, 0x54, 0xd5, 0xbc, 0xe3, 0xd6, 0x0a, 0xf3, 0x5e, 0x8d, 0xd4, 0x8f, 0xdd, + 0x04, 0xa7, 0x8c, 0x0b, ], op: [ 0x55, 0xdb, 0x72, 0x90, 0x07, 0x3b, 0xa0, 0x06, 0x66, 0xe8, 0x7d, 0x25, 0x61, 0xb8, 0x88, 0x3c, 0x66, 0x2c, 0x56, 0x78, 0xff, 0x27, 0x30, 0x2a, 0x82, 0xe2, 0x0a, 0x72, - 0x01, 0x70, 0x89, 0x1a, 0x1d, 0xb6, 0x79, 0x07, 0x9a, 0xcd, 0xef, 0xe9, 0xfc, 0x1e, - 0x59, 0xa1, 0x33, 0xf3, 0x7b, 0x6d, 0x1f, 0xfb, 0xed, 0x78, 0x8c, 0xce, 0x3b, 0x0c, - 0xdd, 0x63, 0xe0, 0x62, 0x83, 0x05, 0x47, 0x08, + 0x01, 0x70, 0x89, 0x1a, 0x9d, 0xc4, 0xc8, 0xc0, 0x32, 0xd3, 0xbe, 0x66, 0xd2, 0x63, + 0x6b, 0xa0, 0x02, 0x0c, 0x63, 0xf4, 0x26, 0x53, 0x29, 0xff, 0xac, 0x2a, 0xe6, 0x35, + 0x57, 0x32, 0x63, 0xf4, 0x99, 0xbd, 0x4c, 0x13, ], c_out: [ - 0x0b, 0x2c, 0xc0, 0xa2, 0x2d, 0x06, 0xfc, 0x36, 0xa0, 0x8a, 0x7d, 0x82, 0x33, 0x8d, - 0x4a, 0xd0, 0x95, 0xa3, 0x93, 0xa1, 0xc2, 0x4a, 0x78, 0x8d, 0x45, 0x24, 0x35, 0x94, - 0x4a, 0xcc, 0xe6, 0x38, 0x1e, 0xcc, 0x69, 0x37, 0xf2, 0xc3, 0x8c, 0x89, 0xa5, 0xf5, - 0x1a, 0xa6, 0x0c, 0xa6, 0x58, 0xfe, 0x71, 0x37, 0x1c, 0x2a, 0x83, 0xf4, 0x96, 0xca, - 0x2e, 0x62, 0x49, 0x79, 0x2e, 0x09, 0xeb, 0x79, 0xea, 0x3a, 0x13, 0x80, 0x32, 0x18, - 0xff, 0x20, 0x88, 0x9d, 0x8c, 0x59, 0xc8, 0x5e, 0x90, 0x99, + 0x43, 0x0d, 0xaa, 0x6b, 0x75, 0x63, 0x22, 0x80, 0xd5, 0xe6, 0xda, 0xcb, 0xd2, 0xa0, + 0xff, 0xe2, 0xaf, 0x98, 0x60, 0xc8, 0x3a, 0x3d, 0x2a, 0x87, 0xf1, 0x79, 0x62, 0x88, + 0xeb, 0xed, 0x64, 0xd0, 0xcd, 0xc4, 0x60, 0xe2, 0xc8, 0x61, 0xc4, 0xf9, 0x38, 0x7d, + 0x92, 0x59, 0xfc, 0x60, 0x01, 0xac, 0xd0, 0xe7, 0x6f, 0x3b, 0x0f, 0xdb, 0x5d, 0xac, + 0x97, 0x4c, 0x26, 0xb5, 0x1b, 0x85, 0x9f, 0xab, 0xe0, 0x2e, 0xab, 0xae, 0x96, 0x8a, + 0xab, 0x2e, 0x5e, 0x61, 0xef, 0xc2, 0xd4, 0x46, 0x2c, 0x1e, ], }, TestVector { @@ -1986,36 +1977,35 @@ pub(crate) fn test_vectors() -> Vec { 0xbd, 0xb9, 0x6f, 0x1c, 0xe0, 0x57, 0xc3, 0x30, 0xd1, 0xcc, 0xba, 0x2f, 0x7d, 0xa8, 0x71, 0x55, 0x00, 0xb5, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ - 0x3b, 0x37, 0x96, 0x78, 0x0c, 0x0a, 0xec, 0x14, 0xed, 0x28, 0x74, 0xb5, 0x23, 0x06, - 0xe1, 0xc3, 0xd5, 0xde, 0x45, 0x93, 0xc6, 0x69, 0xaf, 0x1c, 0xaf, 0x11, 0xbc, 0xb4, - 0xd3, 0x5c, 0x60, 0x12, + 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, + 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, + 0xa3, 0x18, 0x53, 0x3e, ], cmx: [ - 0x4d, 0xa9, 0xdf, 0xdc, 0x70, 0x8c, 0xe8, 0xa0, 0x77, 0xa0, 0x6e, 0xc0, 0x67, 0x79, - 0x24, 0xcf, 0x37, 0x70, 0xed, 0xc2, 0x07, 0xfd, 0x5e, 0x7d, 0x69, 0x5f, 0x71, 0xb0, - 0x15, 0xbb, 0x03, 0x05, + 0x6a, 0xba, 0x28, 0x10, 0x5b, 0xc0, 0x72, 0xc5, 0x2a, 0xb8, 0xa3, 0x14, 0x79, 0x7f, + 0xf8, 0x66, 0x66, 0xdf, 0xb7, 0xcd, 0x8a, 0x2a, 0xe1, 0x7c, 0x58, 0x5f, 0xb7, 0xb6, + 0x51, 0x5b, 0x97, 0x1c, ], esk: [ - 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, 0x52, 0x6d, 0x66, 0x54, - 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, 0xfb, 0xee, 0x5d, 0xe3, - 0x99, 0xca, 0x31, 0x26, + 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, 0xd5, 0x64, 0x6b, 0xc4, + 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, 0x15, 0x5b, 0xef, 0x4d, + 0x46, 0x1e, 0xec, 0x29, ], ephemeral_key: [ - 0x2d, 0xa0, 0x59, 0x4c, 0xd8, 0x74, 0x91, 0x46, 0x52, 0x67, 0xe7, 0x2c, 0x61, 0x89, - 0x07, 0x91, 0xfe, 0xb4, 0x25, 0xa2, 0xbb, 0xcd, 0xda, 0xcf, 0xe4, 0x5a, 0x66, 0x62, - 0x2f, 0x49, 0xef, 0x35, + 0x95, 0x9b, 0xea, 0x8e, 0x11, 0x96, 0x8b, 0x0f, 0x34, 0x3c, 0x04, 0xcd, 0x6d, 0x50, + 0x16, 0xfc, 0xd4, 0x33, 0x90, 0x75, 0x36, 0xa2, 0x46, 0xba, 0x1c, 0x5d, 0x3e, 0x88, + 0x97, 0xf3, 0x23, 0x1c, ], shared_secret: [ - 0xe0, 0xb1, 0x52, 0x67, 0xfd, 0x21, 0x08, 0xeb, 0xbd, 0xd4, 0x16, 0x3f, 0x83, 0xad, - 0xef, 0xb6, 0x1c, 0x3e, 0xdf, 0x56, 0x6d, 0x94, 0x6f, 0xa1, 0xc1, 0x5e, 0x96, 0x46, - 0x43, 0xb1, 0x9c, 0x8e, + 0xe2, 0x69, 0x19, 0xb4, 0x0c, 0x70, 0xaf, 0x74, 0x1d, 0xf9, 0x04, 0x51, 0x72, 0x55, + 0x03, 0x58, 0x89, 0xee, 0x5a, 0x44, 0x42, 0x6d, 0x6a, 0xb8, 0x5c, 0x07, 0x4b, 0x86, + 0x2b, 0xa0, 0x63, 0x08, ], k_enc: [ - 0x28, 0x48, 0xae, 0x53, 0xaa, 0xce, 0xbe, 0x7c, 0xab, 0x58, 0x73, 0x1d, 0xc2, 0x21, - 0x88, 0x1b, 0x60, 0x2c, 0xc5, 0xa5, 0x3b, 0xcc, 0x1f, 0x76, 0xc8, 0x20, 0xb0, 0xea, - 0x13, 0x55, 0x68, 0x8e, + 0x09, 0xda, 0xc6, 0x51, 0x1c, 0x38, 0x44, 0x58, 0x7f, 0x82, 0x9c, 0x2f, 0x1e, 0xa0, + 0x37, 0xa8, 0x1a, 0x8d, 0x54, 0x85, 0xed, 0x04, 0xea, 0xf2, 0x75, 0x80, 0x05, 0xb3, + 0x2a, 0x20, 0x47, 0x0b, ], p_enc: [ 0x02, 0xdd, 0xb7, 0xc5, 0xbc, 0x4d, 0xe9, 0xdf, 0x52, 0x1b, 0xb0, 0x4b, 0xad, 0x95, @@ -2061,68 +2051,68 @@ pub(crate) fn test_vectors() -> Vec { 0xf5, 0xc6, 0x38, 0xbf, ], c_enc: [ - 0xf1, 0x42, 0xc4, 0xe5, 0x0e, 0xef, 0x2c, 0x64, 0x44, 0xcc, 0xd4, 0x0b, 0x8c, 0x99, - 0xe5, 0x6a, 0x72, 0xec, 0x4e, 0x30, 0xcf, 0x73, 0x68, 0x75, 0xf0, 0xaa, 0x6b, 0x8e, - 0x6d, 0x9c, 0xc3, 0x67, 0x73, 0x2d, 0xbc, 0x9a, 0xf0, 0xb3, 0x7d, 0x1f, 0xca, 0x6d, - 0x5b, 0xdd, 0x1d, 0xc1, 0x23, 0x79, 0x29, 0x66, 0x99, 0x9d, 0x62, 0xea, 0xf8, 0xc5, - 0xfe, 0x8d, 0x99, 0x91, 0x84, 0xf2, 0x8b, 0x99, 0xec, 0xef, 0xcc, 0x8f, 0x14, 0x8d, - 0xbd, 0x52, 0x02, 0x6f, 0xdb, 0x48, 0xdf, 0xda, 0x7b, 0xad, 0xb6, 0xd1, 0xfc, 0xd2, - 0x9a, 0xd2, 0x19, 0xea, 0xbf, 0xbb, 0x44, 0x3f, 0x5d, 0x0f, 0x98, 0xb6, 0x6a, 0x3a, - 0x25, 0x73, 0x1b, 0x52, 0xd7, 0xf2, 0xdf, 0x70, 0x01, 0x4b, 0x4a, 0xc6, 0x99, 0x34, - 0x32, 0xf8, 0x98, 0x1e, 0x9c, 0xbf, 0xe1, 0x69, 0x13, 0xf6, 0x8a, 0x93, 0x5d, 0x2d, - 0xd0, 0x06, 0xd4, 0x28, 0xf1, 0x45, 0x53, 0xe7, 0x29, 0x86, 0xc7, 0x0f, 0xb4, 0x43, - 0x18, 0xd2, 0x7c, 0x4d, 0x6f, 0x6f, 0xd3, 0x92, 0x3a, 0xb0, 0xf6, 0x28, 0x9a, 0x02, - 0x48, 0x5e, 0x87, 0x17, 0xe5, 0x7d, 0xa0, 0x24, 0xeb, 0xe1, 0x6e, 0x9c, 0xf8, 0x35, - 0xcf, 0x53, 0xd2, 0x19, 0x4f, 0xd4, 0x25, 0x50, 0x06, 0xb8, 0x1b, 0xfd, 0x51, 0xd1, - 0xef, 0x5a, 0xe9, 0xf9, 0xef, 0x6a, 0xf6, 0x57, 0x41, 0x81, 0xe2, 0xe2, 0x26, 0x50, - 0xcb, 0x91, 0x2a, 0x6b, 0x89, 0x88, 0xa0, 0x28, 0x86, 0x32, 0xbc, 0x73, 0x62, 0xbb, - 0xe1, 0x87, 0x23, 0xd8, 0x27, 0xf7, 0x94, 0x58, 0x62, 0x26, 0x0d, 0xf7, 0x8e, 0x95, - 0xd7, 0xd5, 0xe3, 0x31, 0x3f, 0x5a, 0xff, 0x72, 0xe2, 0x1c, 0xe2, 0xdf, 0x00, 0xee, - 0x7e, 0x81, 0x5a, 0xba, 0x17, 0xcc, 0xde, 0x15, 0xc2, 0x7e, 0xee, 0x08, 0x5f, 0x52, - 0xf3, 0x6c, 0x02, 0xec, 0xd6, 0x6c, 0xe1, 0x8b, 0x40, 0x15, 0xbe, 0xb6, 0x09, 0x23, - 0x3f, 0x6e, 0xb2, 0x8e, 0x4a, 0xd5, 0xcd, 0xbe, 0x6f, 0xdc, 0xab, 0x68, 0xbf, 0xbb, - 0x6f, 0xfd, 0x87, 0xd3, 0x86, 0xd8, 0x7e, 0xb1, 0xfe, 0x00, 0x34, 0x27, 0x0f, 0x41, - 0x27, 0x1e, 0xa0, 0x1f, 0x9e, 0xae, 0xa9, 0xe8, 0x9f, 0x78, 0x35, 0x9e, 0x41, 0x73, - 0x94, 0xbb, 0x9d, 0xf5, 0xb6, 0x1c, 0x36, 0xe3, 0x0b, 0xc1, 0xce, 0x4a, 0xb1, 0xbd, - 0xd7, 0x9f, 0xa4, 0x08, 0x3e, 0x82, 0x8d, 0xd1, 0x04, 0xe4, 0x73, 0x80, 0xcd, 0x83, - 0xcd, 0x65, 0x9d, 0xf4, 0x4d, 0xb9, 0x43, 0xdc, 0x07, 0xbc, 0xc8, 0x07, 0x05, 0x04, - 0xa1, 0xc6, 0x55, 0x23, 0x02, 0xe7, 0x4b, 0xe4, 0xb9, 0xc4, 0x32, 0x75, 0xec, 0xc2, - 0x88, 0xce, 0xda, 0x41, 0x59, 0xa9, 0xcc, 0x55, 0x7c, 0x18, 0x19, 0x5c, 0xec, 0x92, - 0x62, 0x24, 0xd8, 0xd6, 0x9e, 0x98, 0xe1, 0x83, 0x5a, 0x2e, 0x29, 0x05, 0x63, 0xef, - 0x20, 0xd0, 0x83, 0xd1, 0x4e, 0x93, 0xcc, 0x1f, 0x3f, 0x76, 0x3e, 0xf5, 0x58, 0x0e, - 0x13, 0x5f, 0xae, 0x1b, 0xb8, 0x54, 0x4a, 0x0c, 0x5c, 0x6d, 0x88, 0x17, 0x41, 0xe4, - 0x51, 0x34, 0x47, 0xac, 0xeb, 0x09, 0x33, 0xe6, 0xeb, 0xaf, 0x0c, 0xe3, 0x13, 0xc1, - 0x8c, 0x9a, 0xf9, 0x5b, 0xa5, 0x61, 0x31, 0xf7, 0x8f, 0x42, 0x72, 0x41, 0x22, 0x65, - 0xbc, 0xf4, 0xc5, 0xf6, 0x80, 0x89, 0x3c, 0xcd, 0xa5, 0x73, 0x7d, 0xa8, 0x23, 0xb7, - 0x63, 0x6e, 0x98, 0xdb, 0xa5, 0x62, 0x44, 0xf2, 0xb9, 0x6a, 0x10, 0x90, 0xa6, 0x60, - 0x38, 0x15, 0xc0, 0xef, 0x54, 0x97, 0x50, 0xf2, 0x47, 0x06, 0x19, 0x0b, 0x55, 0x76, - 0x6e, 0x8a, 0x62, 0x09, 0xa1, 0xc2, 0x2f, 0x67, 0xe8, 0x77, 0x62, 0x66, 0xb6, 0xfa, - 0xe4, 0x5b, 0xf7, 0x94, 0x90, 0x7f, 0x64, 0x71, 0x4f, 0xbe, 0x26, 0xc3, 0x0a, 0xc4, - 0x04, 0x11, 0xf5, 0xe6, 0x4f, 0xc1, 0x66, 0xc8, 0x4f, 0x28, 0xb8, 0x23, 0xfd, 0xaa, - 0x68, 0x32, 0xa3, 0x25, 0x63, 0x31, 0x7d, 0x25, 0x4c, 0x53, 0x16, 0x9b, 0x9f, 0xfb, - 0x24, 0x53, 0xa1, 0x12, 0x2f, 0xa4, 0x4c, 0x7f, 0x17, 0xc1, 0x36, 0xb5, 0x7e, 0x20, - 0xad, 0x17, 0x7a, 0x7e, 0xee, 0xbf, 0x9f, 0x56, 0xfb, 0x0b, 0x55, 0xcc, 0xcf, 0x68, - 0x2b, 0x8a, 0x5b, 0xd8, 0xa7, 0x45, + 0x7b, 0x59, 0x87, 0x78, 0xa7, 0x28, 0x4d, 0x52, 0xa7, 0x47, 0x77, 0x4c, 0x54, 0xbd, + 0x92, 0x57, 0xb3, 0xf1, 0x7a, 0xf1, 0x3e, 0xcc, 0x72, 0xc0, 0xe3, 0xcd, 0x95, 0xeb, + 0xfa, 0xfa, 0xa3, 0x7d, 0x16, 0x65, 0x15, 0x53, 0xdd, 0x27, 0xf0, 0x1c, 0x9c, 0xf2, + 0x4b, 0x62, 0xd7, 0xdc, 0xfd, 0x52, 0xfa, 0x4b, 0x2b, 0x3b, 0x4a, 0x8c, 0xa9, 0xeb, + 0xfc, 0xe7, 0xf4, 0xfc, 0xec, 0x27, 0xe6, 0x05, 0x8e, 0x44, 0x68, 0xc1, 0x50, 0x10, + 0xd0, 0x17, 0xcb, 0x90, 0x1a, 0xbf, 0xb2, 0x2e, 0xad, 0x86, 0x99, 0x83, 0xf6, 0x9a, + 0xed, 0xf2, 0xda, 0x7d, 0x6a, 0xaf, 0xd1, 0x30, 0x6e, 0xe7, 0x36, 0xf2, 0xdb, 0x33, + 0xbc, 0xe4, 0xb0, 0x9f, 0xca, 0x74, 0x69, 0x2a, 0x52, 0x09, 0xa7, 0x39, 0x2b, 0x7e, + 0xa9, 0x68, 0x5b, 0xe9, 0xec, 0x43, 0x1f, 0xfe, 0x50, 0xf7, 0x0f, 0x90, 0x22, 0x74, + 0x05, 0x03, 0x45, 0x2a, 0xb5, 0x14, 0x92, 0xb1, 0xf7, 0x47, 0x7e, 0xda, 0x42, 0x7b, + 0x42, 0x3a, 0x93, 0x1b, 0x26, 0x38, 0x6c, 0x56, 0xe4, 0x27, 0x86, 0x3d, 0x46, 0xb1, + 0x99, 0xff, 0xa0, 0x8c, 0x52, 0x9f, 0xa5, 0x72, 0x1f, 0x68, 0xe9, 0x14, 0xf6, 0xea, + 0x6a, 0x8a, 0xe6, 0xae, 0xcb, 0xf7, 0x37, 0x47, 0x1e, 0xbd, 0x83, 0xdb, 0xa9, 0xa7, + 0xcd, 0x89, 0x75, 0x66, 0x20, 0x4e, 0x2b, 0xae, 0x63, 0xe3, 0x4e, 0x70, 0x32, 0x51, + 0x02, 0x96, 0x92, 0x0d, 0x7e, 0x7a, 0x7c, 0xcf, 0x0f, 0xeb, 0xe7, 0xa8, 0x33, 0x69, + 0x6a, 0x4b, 0x67, 0x41, 0x88, 0x5e, 0x9b, 0x94, 0x0c, 0x61, 0xdd, 0x8d, 0x44, 0x38, + 0x54, 0x74, 0x15, 0x31, 0x0b, 0x15, 0xcf, 0x18, 0xdc, 0x19, 0x90, 0x07, 0x8c, 0x70, + 0x8b, 0xea, 0xc3, 0x32, 0xa8, 0xe0, 0x81, 0x46, 0xa6, 0x95, 0x8e, 0xa6, 0xf4, 0x3f, + 0xd0, 0xc2, 0xc8, 0xe9, 0x99, 0xaa, 0x4f, 0xdf, 0x1e, 0x77, 0xef, 0xde, 0x54, 0xfd, + 0x65, 0xc6, 0x7a, 0x3f, 0x07, 0xda, 0xf5, 0xf6, 0x04, 0x49, 0x60, 0xa0, 0xb6, 0xdd, + 0x84, 0x1f, 0xf8, 0xb8, 0xa5, 0x92, 0xc7, 0xb1, 0x09, 0x34, 0x2c, 0x73, 0x5c, 0x2a, + 0x0e, 0x37, 0xb3, 0x0b, 0x8b, 0xaa, 0x5c, 0x77, 0x01, 0xeb, 0xc7, 0xa8, 0xf8, 0x20, + 0xc0, 0x22, 0x7c, 0xa5, 0x00, 0x3f, 0x36, 0xee, 0x68, 0xf7, 0xb2, 0x89, 0x81, 0xc2, + 0x73, 0x32, 0x03, 0x9d, 0xd6, 0xa4, 0x94, 0xf0, 0xcd, 0x02, 0xbd, 0xd2, 0x8f, 0x68, + 0x3e, 0xca, 0x1b, 0x03, 0x2a, 0xfc, 0x09, 0xdd, 0x0c, 0xd8, 0x56, 0xcb, 0xc1, 0xa3, + 0x5e, 0x74, 0xd4, 0x0c, 0x24, 0x53, 0xdf, 0xe2, 0x42, 0xc8, 0x6a, 0x7a, 0x60, 0xbc, + 0xbd, 0xdb, 0x17, 0x96, 0x6c, 0x7d, 0xba, 0x76, 0x9e, 0xab, 0xd1, 0xc1, 0x67, 0xb7, + 0xe8, 0x19, 0x78, 0xf9, 0x12, 0x8b, 0xac, 0x26, 0xa2, 0x8d, 0x77, 0x21, 0x30, 0x79, + 0xcb, 0x56, 0xc0, 0x95, 0xa7, 0xc0, 0x60, 0xde, 0x0e, 0x77, 0x5c, 0xa8, 0xac, 0x8e, + 0x6c, 0xa9, 0x4d, 0x19, 0xc6, 0x16, 0x2e, 0x44, 0xf7, 0xa8, 0xf0, 0x14, 0x9d, 0x31, + 0xd3, 0x46, 0x3d, 0x01, 0xb6, 0x1a, 0x14, 0x63, 0xa9, 0xde, 0x3d, 0x8a, 0xb7, 0x40, + 0x04, 0x0a, 0x76, 0xe0, 0x5b, 0x37, 0x64, 0x28, 0x86, 0x29, 0x87, 0x59, 0x5b, 0x87, + 0xce, 0xa6, 0x94, 0xfe, 0x92, 0x0a, 0x06, 0x7e, 0x81, 0x6b, 0x4f, 0x29, 0xa3, 0xa2, + 0x24, 0x50, 0x14, 0x0f, 0x13, 0x5d, 0x71, 0x9a, 0x97, 0x1b, 0x81, 0xfc, 0x19, 0x16, + 0x98, 0x0a, 0x55, 0xdd, 0xf8, 0xd9, 0x87, 0x30, 0x57, 0x36, 0x35, 0xa0, 0x70, 0x85, + 0xc4, 0xe7, 0x7c, 0x7e, 0x1c, 0xdb, 0xb6, 0x85, 0x42, 0x6e, 0xe4, 0x62, 0xcc, 0x30, + 0x83, 0xa3, 0xf5, 0xa3, 0xb9, 0x17, 0xc0, 0x6f, 0x9a, 0x96, 0xf9, 0xf7, 0xbd, 0x81, + 0xac, 0xa4, 0x9b, 0xef, 0x95, 0xb9, 0x28, 0x06, 0xc4, 0x2d, 0x09, 0x12, 0x01, 0x31, + 0x42, 0xb2, 0x2a, 0x7b, 0xad, 0x72, 0x12, 0x11, 0x46, 0x91, 0xf1, 0xdc, 0x72, 0x64, + 0xc6, 0x7e, 0x76, 0x34, 0xf5, 0xd7, 0x95, 0xc9, 0x75, 0x30, 0x62, 0xe3, 0x06, 0xc0, + 0x6b, 0xc1, 0x03, 0xaa, 0x01, 0xc1, 0x0d, 0x1f, 0x5d, 0xd4, 0xcd, 0x59, 0xf6, 0x53, + 0x2c, 0xb7, 0x23, 0xe3, 0xa0, 0x26, ], ock: [ - 0x06, 0x3c, 0x83, 0xa4, 0x95, 0x74, 0xe7, 0x80, 0x35, 0x89, 0xcc, 0x3d, 0x34, 0xb4, - 0x38, 0x90, 0xf3, 0xd7, 0x63, 0x87, 0x35, 0xe7, 0xbd, 0x5e, 0xbd, 0xd1, 0xa5, 0xea, - 0xb9, 0xd9, 0xc5, 0xd6, + 0x4a, 0x25, 0x25, 0x4c, 0xcc, 0x44, 0x4e, 0xc6, 0x1c, 0x2b, 0xac, 0xeb, 0x2e, 0xe3, + 0x97, 0x7a, 0x63, 0x32, 0x44, 0x9a, 0x3a, 0x53, 0xad, 0xd2, 0x31, 0xab, 0xf3, 0xd1, + 0x8b, 0xb3, 0x29, 0x3d, ], op: [ 0x65, 0x3d, 0x07, 0xc9, 0x07, 0x94, 0x6a, 0xc3, 0x02, 0x0e, 0xbd, 0xe1, 0xb4, 0xf6, 0x10, 0x21, 0x0c, 0x30, 0xc4, 0x50, 0xe4, 0x27, 0x12, 0x65, 0xa0, 0x5d, 0x6e, 0xce, - 0x44, 0x6d, 0xf4, 0x39, 0xae, 0xec, 0x0d, 0xb9, 0x0e, 0x55, 0x83, 0x3c, 0x8b, 0xaf, - 0x52, 0x6d, 0x66, 0x54, 0xa1, 0x74, 0x5b, 0xa4, 0x4c, 0xad, 0x3c, 0xf9, 0xa6, 0x2c, - 0xfb, 0xee, 0x5d, 0xe3, 0x99, 0xca, 0x31, 0x26, + 0x44, 0x6d, 0xf4, 0x39, 0x03, 0xfb, 0x79, 0x43, 0x75, 0x27, 0x5d, 0x23, 0xd1, 0x58, + 0xd5, 0x64, 0x6b, 0xc4, 0x63, 0xa8, 0xb7, 0x38, 0xbc, 0x79, 0x38, 0xf6, 0x0d, 0xfb, + 0x15, 0x5b, 0xef, 0x4d, 0x46, 0x1e, 0xec, 0x29, ], c_out: [ - 0xca, 0xb7, 0x8d, 0xd1, 0x83, 0xf3, 0xe1, 0x6a, 0xf7, 0x6e, 0x9a, 0x90, 0x3d, 0xd4, - 0x2a, 0x96, 0x67, 0xbf, 0xe7, 0x08, 0xce, 0x88, 0x79, 0xb8, 0x38, 0x6e, 0x62, 0xac, - 0x9f, 0x66, 0x74, 0xf4, 0x93, 0x59, 0x5d, 0xa5, 0x06, 0xe9, 0xef, 0x06, 0xbb, 0xa2, - 0x4a, 0x93, 0x80, 0x60, 0xe5, 0xd3, 0x82, 0xcc, 0x75, 0xdf, 0xab, 0x97, 0xe0, 0xf8, - 0x49, 0x4b, 0x47, 0x6a, 0xdf, 0x4f, 0xfd, 0x96, 0xff, 0x7f, 0x1b, 0x4f, 0x16, 0xf8, - 0x59, 0x4b, 0x7c, 0x5a, 0x21, 0x9c, 0x7a, 0x00, 0xad, 0x15, + 0x7b, 0xf4, 0x12, 0x7d, 0x22, 0xcc, 0x57, 0x35, 0x87, 0x51, 0x2f, 0xf8, 0x1e, 0x55, + 0x3e, 0x3c, 0x98, 0x23, 0x5f, 0x51, 0xc7, 0x23, 0x7e, 0x9e, 0x76, 0x1a, 0x08, 0xf2, + 0xe1, 0xe8, 0x0d, 0x04, 0x26, 0x98, 0xfc, 0x3b, 0x1d, 0x03, 0x18, 0xf1, 0xfd, 0xca, + 0x8e, 0x41, 0xa3, 0x16, 0xd6, 0xaf, 0x3a, 0xc0, 0xc4, 0x0c, 0xe1, 0x99, 0x47, 0xa2, + 0xba, 0xfe, 0x80, 0x4d, 0x46, 0x6e, 0xd0, 0x79, 0x82, 0x7f, 0xc1, 0x41, 0x91, 0xeb, + 0xb5, 0x99, 0x17, 0x87, 0x49, 0xe9, 0xc4, 0x06, 0xaf, 0x26, ], }, ] diff --git a/src/test_vectors/note_encryption_zsa.rs b/src/test_vectors/note_encryption_zsa.rs index 25cd361fa..534e24407 100644 --- a/src/test_vectors/note_encryption_zsa.rs +++ b/src/test_vectors/note_encryption_zsa.rs @@ -101,7 +101,6 @@ pub(crate) fn test_vectors() -> Vec { 0x42, 0xc2, 0x38, 0x51, 0x38, 0x15, 0x30, 0x2d, 0xf0, 0xf4, 0x83, 0x04, 0x21, 0xa6, 0xc1, 0x3e, 0x71, 0x01, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xca, 0x1f, 0xeb, 0x30, 0xca, 0x11, 0x17, 0x76, 0xc0, 0x41, 0x74, 0x66, 0xbd, 0x69, 0xb3, 0xd2, 0x13, 0x88, 0x2e, 0xef, 0x55, 0xe6, 0x0b, 0x6d, 0x9e, 0x2a, 0x98, 0xe7, @@ -320,7 +319,6 @@ pub(crate) fn test_vectors() -> Vec { 0xa2, 0x17, 0x64, 0x10, 0x4a, 0x23, 0xea, 0xf6, 0xba, 0x49, 0x6c, 0xb9, 0xb8, 0xe8, 0x25, 0x7a, 0xd8, 0xb3, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xc1, 0xe1, 0x59, 0x5b, 0x8d, 0xe7, 0x55, 0x97, 0x66, 0xe5, 0xa6, 0x72, 0x5f, 0x5b, 0xe5, 0x74, 0x2f, 0x43, 0xbf, 0x40, 0x62, 0x3b, 0x71, 0x49, 0xca, 0xe2, 0x67, 0x5c, @@ -539,7 +537,6 @@ pub(crate) fn test_vectors() -> Vec { 0x9d, 0x5e, 0x64, 0x07, 0x19, 0xbc, 0xa5, 0xc8, 0xed, 0x49, 0x99, 0x97, 0x34, 0xe6, 0xc5, 0xb3, 0x73, 0x3e, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xc8, 0x8d, 0x00, 0x84, 0x84, 0xc5, 0xd7, 0x98, 0x20, 0xab, 0x68, 0xc6, 0x7d, 0x08, 0x36, 0x72, 0xb0, 0x7f, 0x72, 0x7d, 0x44, 0xd0, 0xcd, 0x14, 0x73, 0x88, 0x00, 0xf8, @@ -758,7 +755,6 @@ pub(crate) fn test_vectors() -> Vec { 0xfa, 0xde, 0x94, 0xfa, 0x0b, 0x46, 0xe3, 0xb1, 0xa5, 0x73, 0x34, 0x99, 0x34, 0xe2, 0x32, 0xb5, 0x0e, 0x96, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xa9, 0x0a, 0x9b, 0x8a, 0xb1, 0x35, 0x9d, 0xc9, 0x6b, 0xda, 0xe9, 0x0e, 0x52, 0x74, 0x78, 0x8c, 0xb0, 0xc4, 0x26, 0xef, 0xf2, 0x60, 0x43, 0x61, 0x85, 0x39, 0x8b, 0xff, @@ -977,7 +973,6 @@ pub(crate) fn test_vectors() -> Vec { 0x72, 0x95, 0x89, 0xbe, 0x69, 0xd8, 0x28, 0xbe, 0x54, 0x30, 0x69, 0x16, 0x41, 0x3c, 0xd2, 0x50, 0x21, 0x17, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x8d, 0x67, 0xe3, 0xba, 0x4d, 0xbc, 0x9d, 0xa5, 0xe8, 0x38, 0x23, 0xa1, 0x23, 0x11, 0x63, 0x96, 0x51, 0xa4, 0xff, 0xa9, 0x5f, 0x27, 0xc1, 0x83, 0x0d, 0x91, 0xd8, 0xb7, @@ -1196,7 +1191,6 @@ pub(crate) fn test_vectors() -> Vec { 0x6e, 0x62, 0xe4, 0xed, 0xc7, 0x86, 0xd9, 0xe0, 0xb2, 0x7d, 0x26, 0x62, 0x8b, 0x79, 0xda, 0x6b, 0x15, 0x14, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x9a, 0x09, 0xe4, 0x72, 0xe8, 0xe9, 0x96, 0xfc, 0xc3, 0x0e, 0xd5, 0x23, 0x72, 0x08, 0xdb, 0xb0, 0x01, 0x71, 0x32, 0x0e, 0x6b, 0xea, 0x43, 0x91, 0x86, 0x00, 0x9d, 0xad, @@ -1415,7 +1409,6 @@ pub(crate) fn test_vectors() -> Vec { 0x0a, 0x12, 0x01, 0x2d, 0x63, 0xc0, 0x09, 0xc6, 0x77, 0x44, 0xba, 0xe0, 0xd5, 0x83, 0x88, 0xff, 0xee, 0x2f, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x54, 0x3e, 0xa7, 0x11, 0x56, 0xc9, 0xa6, 0xf8, 0x04, 0x1f, 0xa7, 0x7e, 0xc1, 0xc5, 0xaf, 0x90, 0x28, 0x8f, 0x27, 0x20, 0xf1, 0x3f, 0xf0, 0x93, 0xc6, 0x86, 0x26, 0x6b, @@ -1634,7 +1627,6 @@ pub(crate) fn test_vectors() -> Vec { 0xcd, 0x51, 0x00, 0x89, 0x08, 0xa6, 0xcd, 0xd0, 0xaa, 0x02, 0x1b, 0x88, 0x8b, 0x98, 0xe2, 0x3c, 0x39, 0x11, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xbd, 0xda, 0xe8, 0xdf, 0xf1, 0x20, 0x5e, 0x04, 0x96, 0x8f, 0xae, 0x1f, 0xd9, 0xbe, 0x51, 0xd8, 0x25, 0xf5, 0xd8, 0x78, 0x1d, 0x93, 0x3d, 0x0f, 0x5b, 0xce, 0x9c, 0xa8, @@ -1853,7 +1845,6 @@ pub(crate) fn test_vectors() -> Vec { 0x7e, 0xed, 0xd2, 0xa7, 0x06, 0x44, 0x07, 0x34, 0x78, 0x41, 0x01, 0xae, 0x2d, 0x8e, 0x87, 0xe5, 0x05, 0xad, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xc2, 0x79, 0xfa, 0x9d, 0x1c, 0x84, 0x11, 0x93, 0xd3, 0x32, 0xf8, 0xcc, 0xf4, 0xd0, 0xb1, 0xe4, 0x56, 0x01, 0xa8, 0xaf, 0x66, 0x76, 0xd7, 0x62, 0xfb, 0xa7, 0x31, 0x33, @@ -2072,7 +2063,6 @@ pub(crate) fn test_vectors() -> Vec { 0xbd, 0xb9, 0x6f, 0x1c, 0xe0, 0x57, 0xc3, 0x30, 0xd1, 0xcc, 0xba, 0x2f, 0x7d, 0xa8, 0x71, 0x55, 0x00, 0xb5, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xea, 0x38, 0x44, 0x75, 0x9a, 0x9a, 0x1c, 0xc5, 0x28, 0xb2, 0x95, 0xce, 0x70, 0x13, 0x7a, 0x85, 0xf9, 0xf0, 0x8e, 0x41, 0xa5, 0xc7, 0xc1, 0xca, 0xc1, 0x55, 0xa6, 0x69, @@ -2291,7 +2281,6 @@ pub(crate) fn test_vectors() -> Vec { 0x2c, 0x3b, 0x94, 0x21, 0x3e, 0x86, 0x47, 0x3b, 0x5e, 0x2f, 0xdd, 0x70, 0x97, 0x80, 0xbc, 0xca, 0x68, 0xb4, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xf6, 0x5d, 0x22, 0x96, 0x09, 0x58, 0xd7, 0x28, 0x59, 0x60, 0x9c, 0x99, 0x46, 0xd8, 0xa9, 0x4a, 0x06, 0x04, 0xb8, 0x00, 0x6c, 0xc7, 0x94, 0xbc, 0xab, 0x57, 0x73, 0x49, @@ -2510,7 +2499,6 @@ pub(crate) fn test_vectors() -> Vec { 0x87, 0x2e, 0xf2, 0x17, 0x35, 0x43, 0xac, 0x81, 0x4c, 0x32, 0xb4, 0xb6, 0x9c, 0x9c, 0x34, 0x5e, 0x46, 0x98, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x27, 0x3c, 0x68, 0xd1, 0x9c, 0xda, 0xa8, 0x62, 0x8b, 0xac, 0x37, 0xa2, 0xd4, 0x2c, 0x51, 0x1c, 0x9b, 0xab, 0x65, 0xb6, 0xd8, 0xd5, 0xc5, 0xbd, 0x1e, 0x32, 0x77, 0x1a, @@ -2729,7 +2717,6 @@ pub(crate) fn test_vectors() -> Vec { 0xce, 0xe7, 0x81, 0xe4, 0x00, 0x28, 0x5c, 0xc6, 0x66, 0xbc, 0x6c, 0x41, 0x89, 0xdb, 0x2d, 0xda, 0x71, 0x92, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xea, 0x1d, 0x9d, 0x26, 0x5e, 0xf4, 0x8a, 0x18, 0x97, 0x89, 0x70, 0xb1, 0x76, 0x7b, 0xe0, 0xe8, 0x14, 0x11, 0x94, 0x7e, 0x9e, 0x69, 0xb7, 0x19, 0xfa, 0xb7, 0x41, 0x72, @@ -2948,7 +2935,6 @@ pub(crate) fn test_vectors() -> Vec { 0x80, 0x2d, 0x65, 0x00, 0x74, 0xdb, 0xd7, 0xe0, 0x6a, 0x48, 0x98, 0x03, 0x15, 0x30, 0x78, 0xe9, 0x97, 0x0b, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x9a, 0xd0, 0x7f, 0x1c, 0x28, 0x7b, 0xdd, 0x53, 0x4f, 0x6f, 0x7e, 0xae, 0x08, 0xf7, 0x85, 0x72, 0xa3, 0x05, 0xfa, 0x3b, 0x70, 0x68, 0xa3, 0x78, 0x38, 0x27, 0xaf, 0xe2, @@ -3167,7 +3153,6 @@ pub(crate) fn test_vectors() -> Vec { 0x34, 0xda, 0xf4, 0xe5, 0x98, 0x34, 0xcd, 0x65, 0xd7, 0x9f, 0xfc, 0x41, 0xdd, 0xf0, 0x68, 0x2d, 0xc2, 0xab, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x31, 0x70, 0x5e, 0xfb, 0xf8, 0x0c, 0x7a, 0x7a, 0xb7, 0x81, 0xdf, 0x53, 0x77, 0xf8, 0x4d, 0x4b, 0x32, 0x36, 0xdb, 0x1f, 0x32, 0xac, 0xa7, 0x94, 0x5c, 0xf2, 0x6e, 0xc8, @@ -3386,7 +3371,6 @@ pub(crate) fn test_vectors() -> Vec { 0xd7, 0xda, 0xfb, 0xbe, 0x53, 0xb0, 0xa9, 0x6b, 0x08, 0x1c, 0x90, 0xba, 0xde, 0xd9, 0xbe, 0x4b, 0x4f, 0x87, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x56, 0xbc, 0x48, 0x21, 0xa5, 0x3d, 0x5e, 0x9e, 0x6d, 0x7a, 0x04, 0x44, 0x44, 0x45, 0x4f, 0xfb, 0xc2, 0x36, 0x9c, 0xb1, 0x48, 0xeb, 0x76, 0xf1, 0xed, 0xf1, 0xb5, 0xc7, @@ -3605,7 +3589,6 @@ pub(crate) fn test_vectors() -> Vec { 0x73, 0x07, 0x93, 0xf4, 0x36, 0x33, 0x1f, 0xfe, 0x66, 0x30, 0xc7, 0xca, 0x2d, 0x9b, 0x23, 0x2a, 0xe1, 0x98, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0xd6, 0xff, 0xc4, 0x74, 0x88, 0xad, 0x05, 0x93, 0x89, 0x70, 0xc4, 0xb1, 0x56, 0xd0, 0x53, 0xb9, 0x3b, 0xcb, 0xb4, 0x37, 0x57, 0x1c, 0x62, 0xf3, 0x75, 0x60, 0x7e, 0x90, @@ -3824,7 +3807,6 @@ pub(crate) fn test_vectors() -> Vec { 0x95, 0x26, 0xa6, 0xe9, 0x4a, 0x49, 0x70, 0x10, 0xe3, 0x2a, 0x8a, 0x76, 0xbc, 0xdf, 0xa7, 0x20, 0xb8, 0xa6, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x85, 0x2f, 0x5c, 0x39, 0xd3, 0xf3, 0x55, 0xa3, 0x85, 0xe2, 0xab, 0xd2, 0x54, 0x3a, 0xa5, 0xed, 0x09, 0xc6, 0xee, 0x3b, 0x7f, 0x39, 0x34, 0x14, 0xe1, 0x1c, 0xd4, 0x20, @@ -4043,7 +4025,6 @@ pub(crate) fn test_vectors() -> Vec { 0x3a, 0x2a, 0xf5, 0x46, 0x32, 0xf8, 0x30, 0x08, 0x14, 0x68, 0x29, 0x65, 0x94, 0x5e, 0x7e, 0x33, 0x2a, 0x0d, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x09, 0x1d, 0x83, 0x73, 0x3a, 0x9f, 0xfb, 0x18, 0xc1, 0x7a, 0xd1, 0x93, 0x8d, 0xd2, 0x67, 0x93, 0xc3, 0xfe, 0xfa, 0xda, 0xee, 0xa8, 0xe2, 0x3c, 0x44, 0xd5, 0xe0, 0x18, @@ -4262,7 +4243,6 @@ pub(crate) fn test_vectors() -> Vec { 0xd3, 0x7d, 0x17, 0x17, 0xa4, 0x8d, 0x8f, 0x00, 0x6c, 0x1f, 0xf5, 0x86, 0x21, 0x46, 0x29, 0x55, 0x39, 0x1c, ], - // FIXME: used instead of rho, which was possibly modified in zsa1 version nf_old: [ 0x57, 0x87, 0x18, 0x97, 0x6d, 0xa3, 0xdc, 0xb4, 0x30, 0x32, 0x71, 0x52, 0x20, 0x72, 0xd0, 0x28, 0x44, 0x22, 0x13, 0x50, 0x86, 0x4e, 0xed, 0x56, 0x3d, 0xab, 0x30, 0x22, From dd69425b20ace58425cd557f1db5c47e65a9ae13 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 10 Oct 2024 17:35:18 +0200 Subject: [PATCH 74/92] Remove ZSA dummy notes For actions made with ZSA assets, it is important not to use dummy spend notes to ensure that the asset has been properly issued. --- src/builder.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index fa532275a..fff4de8c3 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -147,6 +147,8 @@ pub enum BuildError { BurnZero, /// The asset to be burned is duplicated. BurnDuplicateAsset, + /// There is no available split note for this asset. + NoSplitNoteAvailable, } impl Display for BuildError { @@ -169,6 +171,7 @@ impl Display for BuildError { BurnNative => f.write_str("Burning is only possible for non-native assets"), BurnZero => f.write_str("Burning is not possible for zero values"), BurnDuplicateAsset => f.write_str("Duplicate assets are not allowed when burning"), + NoSplitNoteAvailable => f.write_str("No split note has been provided for this asset"), } } } @@ -696,11 +699,13 @@ fn partition_by_asset( } if hm.is_empty() { - let dummy_spend = pad_spend(None, AssetBase::native(), rng); // dummy_spend should not be included in the indexing and marked as None. hm.insert( - dummy_spend.note.asset(), - (vec![(dummy_spend, None)], vec![]), + AssetBase::native(), + ( + vec![(SpendInfo::dummy(AssetBase::native(), rng), None)], + vec![], + ), ); } @@ -708,16 +713,20 @@ fn partition_by_asset( } /// Returns the appropriate SpendInfo for padding. -fn pad_spend(spend: Option<&SpendInfo>, asset: AssetBase, mut rng: impl RngCore) -> SpendInfo { +fn pad_spend( + spend: Option<&SpendInfo>, + asset: AssetBase, + mut rng: impl RngCore, +) -> Result { if asset.is_native().into() { // For native asset, extends with dummy notes - SpendInfo::dummy(asset, &mut rng) + Ok(SpendInfo::dummy(AssetBase::native(), &mut rng)) } else { - // For ZSA asset, extends with - // - dummy note if SpendInfo is None - // - split notes otherwise. - let dummy = SpendInfo::dummy(asset, &mut rng); - spend.map_or_else(|| dummy, |s| s.create_split_spend(&mut rng)) + // For ZSA asset, extends with split_notes. + // If SpendInfo is none, return an error (no split note are available for this asset) + spend + .map(|s| s.create_split_spend(&mut rng)) + .ok_or(BuildError::NoSplitNoteAvailable) } } @@ -770,7 +779,11 @@ pub fn bundle, FL: OrchardFlavor>( let mut indexed_spends = spends .into_iter() .chain(iter::repeat_with(|| { - (pad_spend(first_spend.as_ref(), asset, &mut rng), None) + ( + pad_spend(first_spend.as_ref(), asset, &mut rng) + .unwrap_or_else(|err| panic!("{:?}", err)), + None, + ) })) .take(num_asset_pre_actions) .collect::>(); @@ -798,7 +811,7 @@ pub fn bundle, FL: OrchardFlavor>( indexed_spends_outputs.extend( iter::repeat_with(|| { ( - (pad_spend(None, AssetBase::native(), &mut rng), None), + (SpendInfo::dummy(AssetBase::native(), &mut rng), None), (OutputInfo::dummy(&mut rng, AssetBase::native()), None), ) }) From 410037df38ec60eed49c157d4d430f0eb06604be Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:50:46 +0530 Subject: [PATCH 75/92] Changing the type of the asset description from String to Vec (#113) This switches the asset description to be the Vec type. This is so that orchard doesn't check whether the asset description string is UTF-8 encoded, and just works with the bytes. The UTF-8 recommended check will be performed closer to the top of the stack instead. --------- Co-authored-by: Paul <3682187+PaulLaux@users.noreply.github.com> Co-authored-by: Paul --- src/bundle/burn_validation.rs | 24 +-- src/bundle/commitments.rs | 4 +- src/issuance.rs | 287 +++++++++++++++++++--------------- src/note/asset_base.rs | 28 ++-- src/supply_info.rs | 12 +- tests/zsa.rs | 16 +- 6 files changed, 199 insertions(+), 172 deletions(-) diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs index d8ef0ce81..d05c43294 100644 --- a/src/bundle/burn_validation.rs +++ b/src/bundle/burn_validation.rs @@ -80,7 +80,7 @@ mod tests { /// /// A tuple `(AssetBase, Amount)` representing the burn list item. /// - pub fn get_burn_tuple(asset_desc: &str, value: i64) -> (AssetBase, i64) { + pub fn get_burn_tuple(asset_desc: &[u8], value: i64) -> (AssetBase, i64) { use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); @@ -94,9 +94,9 @@ mod tests { #[test] fn validate_bundle_burn_success() { let bundle_burn = vec![ - get_burn_tuple("Asset 1", 10), - get_burn_tuple("Asset 2", 20), - get_burn_tuple("Asset 3", 10), + get_burn_tuple(b"Asset 1", 10), + get_burn_tuple(b"Asset 2", 20), + get_burn_tuple(b"Asset 3", 10), ]; let result = validate_bundle_burn(&bundle_burn); @@ -107,9 +107,9 @@ mod tests { #[test] fn validate_bundle_burn_duplicate_asset() { let bundle_burn = vec![ - get_burn_tuple("Asset 1", 10), - get_burn_tuple("Asset 1", 20), - get_burn_tuple("Asset 3", 10), + get_burn_tuple(b"Asset 1", 10), + get_burn_tuple(b"Asset 1", 20), + get_burn_tuple(b"Asset 3", 10), ]; let result = validate_bundle_burn(&bundle_burn); @@ -120,9 +120,9 @@ mod tests { #[test] fn validate_bundle_burn_native_asset() { let bundle_burn = vec![ - get_burn_tuple("Asset 1", 10), + get_burn_tuple(b"Asset 1", 10), (AssetBase::native(), 20), - get_burn_tuple("Asset 3", 10), + get_burn_tuple(b"Asset 3", 10), ]; let result = validate_bundle_burn(&bundle_burn); @@ -133,9 +133,9 @@ mod tests { #[test] fn validate_bundle_burn_zero_value() { let bundle_burn = vec![ - get_burn_tuple("Asset 1", 10), - get_burn_tuple("Asset 2", 0), - get_burn_tuple("Asset 3", 10), + get_burn_tuple(b"Asset 1", 10), + get_burn_tuple(b"Asset 2", 0), + get_burn_tuple(b"Asset 3", 10), ]; let result = validate_bundle_burn(&bundle_burn); diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 1572987bd..b4931d4cc 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -162,7 +162,7 @@ pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) let mut h = hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION); let mut ia = hasher(ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION); - for action in bundle.actions().iter() { + for action in bundle.actions() { let mut ind = hasher(ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION); for note in action.notes().iter() { ind.update(¬e.recipient().to_raw_address_bytes()); @@ -172,7 +172,7 @@ pub(crate) fn hash_issue_bundle_txid_data(bundle: &IssueBundle) ind.update(note.rseed().as_bytes()); } ia.update(ind.finalize().as_bytes()); - ia.update(action.asset_desc().as_bytes()); + ia.update(action.asset_desc()); ia.update(&[u8::from(action.is_finalized())]); } h.update(ia.finalize().as_bytes()); diff --git a/src/issuance.rs b/src/issuance.rs index 4ba3b8feb..0b1cf568d 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -39,7 +39,7 @@ pub struct IssueBundle { #[derive(Debug, Clone, PartialEq, Eq)] pub struct IssueAction { /// Asset description for verification. - asset_desc: String, + asset_desc: Vec, /// The newly issued notes. notes: Vec, /// `finalize` will prevent further issuance of the same asset type. @@ -57,7 +57,7 @@ pub struct IssueInfo { impl IssueAction { /// Constructs a new `IssueAction`. - pub fn new_with_flags(asset_desc: String, notes: Vec, flags: u8) -> Option { + pub fn new_with_flags(asset_desc: Vec, notes: Vec, flags: u8) -> Option { let finalize = match flags { 0b0000_0000 => false, 0b0000_0001 => true, @@ -71,7 +71,7 @@ impl IssueAction { } /// Constructs an `IssueAction` from its constituent parts. - pub fn from_parts(asset_desc: String, notes: Vec, finalize: bool) -> Self { + pub fn from_parts(asset_desc: Vec, notes: Vec, finalize: bool) -> Self { IssueAction { asset_desc, notes, @@ -80,12 +80,12 @@ impl IssueAction { } /// Returns the asset description for the note being created. - pub fn asset_desc(&self) -> &str { + pub fn asset_desc(&self) -> &[u8] { &self.asset_desc } /// Returns the issued notes. - pub fn notes(&self) -> &Vec { + pub fn notes(&self) -> &[Note] { &self.notes } @@ -211,11 +211,8 @@ impl IssueBundle { &self.actions } /// Return the notes from all actions for a given `IssueBundle`. - pub fn get_all_notes(&self) -> Vec { - self.actions - .iter() - .flat_map(|action| action.notes.clone().into_iter()) - .collect() + pub fn get_all_notes(&self) -> Vec<&Note> { + self.actions.iter().flat_map(|a| a.notes.iter()).collect() } /// Returns the authorization for this action. @@ -223,18 +220,20 @@ impl IssueBundle { &self.authorization } - /// Find an action by `ik` and `asset_desc` for a given `IssueBundle`. - pub fn get_action(&self, asset_desc: String) -> Option<&IssueAction> { - self.actions.iter().find(|a| a.asset_desc.eq(&asset_desc)) + /// Find the actions corresponding to the `asset_desc` for a given `IssueBundle`. + pub fn get_actions_by_desc(&self, asset_desc: &[u8]) -> Vec<&IssueAction> { + self.actions + .iter() + .filter(|a| a.asset_desc.eq(asset_desc)) + .collect() } - /// Find an action by `asset` for a given `IssueBundle`. - pub fn get_action_by_type(&self, asset: AssetBase) -> Option<&IssueAction> { - let action = self - .actions + /// Find the actions corresponding to an Asset Base `asset` for a given `IssueBundle`. + pub fn get_actions_by_asset(&self, asset: &AssetBase) -> Vec<&IssueAction> { + self.actions .iter() - .find(|a| AssetBase::derive(&self.ik, &a.asset_desc).eq(&asset)); - action + .filter(|a| AssetBase::derive(&self.ik, &a.asset_desc).eq(asset)) + .collect() } /// Computes a commitment to the effects of this bundle, suitable for inclusion within @@ -286,7 +285,7 @@ impl IssueBundle { /// * `WrongAssetDescSize`: If `asset_desc` is empty or longer than 512 bytes. pub fn new( ik: IssuanceValidatingKey, - asset_desc: String, + asset_desc: Vec, issue_info: Option, mut rng: impl RngCore, ) -> Result<(IssueBundle, AssetBase), Error> { @@ -340,16 +339,16 @@ impl IssueBundle { /// * `WrongAssetDescSize`: If `asset_desc` is empty or longer than 512 bytes. pub fn add_recipient( &mut self, - asset_desc: String, + asset_desc: &[u8], recipient: Address, value: NoteValue, mut rng: impl RngCore, ) -> Result { - if !is_asset_desc_of_valid_size(&asset_desc) { + if !is_asset_desc_of_valid_size(asset_desc) { return Err(WrongAssetDescSize); } - let asset = AssetBase::derive(&self.ik, &asset_desc); + let asset = AssetBase::derive(&self.ik, asset_desc); let note = Note::new( recipient, @@ -362,7 +361,7 @@ impl IssueBundle { let action = self .actions .iter_mut() - .find(|issue_action| issue_action.asset_desc.eq(&asset_desc)); + .find(|issue_action| issue_action.asset_desc.eq(asset_desc)); match action { Some(action) => { @@ -372,7 +371,7 @@ impl IssueBundle { None => { // Insert a new IssueAction. self.actions.push(IssueAction { - asset_desc, + asset_desc: Vec::from(asset_desc), notes: vec![note], finalize: false, }); @@ -387,15 +386,15 @@ impl IssueBundle { /// # Panics /// /// Panics if `asset_desc` is empty or longer than 512 bytes. - pub fn finalize_action(&mut self, asset_desc: String) -> Result<(), Error> { - if !is_asset_desc_of_valid_size(&asset_desc) { + pub fn finalize_action(&mut self, asset_desc: &[u8]) -> Result<(), Error> { + if !is_asset_desc_of_valid_size(asset_desc) { return Err(WrongAssetDescSize); } match self .actions .iter_mut() - .find(|issue_action| issue_action.asset_desc.eq(&asset_desc)) + .find(|issue_action| issue_action.asset_desc.eq(asset_desc)) { Some(issue_action) => { issue_action.finalize = true; @@ -422,7 +421,7 @@ impl IssueBundle { /// Sign the `IssueBundle`. /// The call makes sure that the provided `isk` matches the `ik` and the derived `asset` for each note in the bundle. pub fn sign(self, isk: &IssuanceAuthorizingKey) -> Result, Error> { - let expected_ik: IssuanceValidatingKey = (isk).into(); + let expected_ik: IssuanceValidatingKey = isk.into(); // Make sure the `expected_ik` matches the `asset` for all notes. self.actions.iter().try_for_each(|action| { @@ -648,11 +647,15 @@ mod tests { (rng, isk, ik, recipient, sighash) } - fn setup_verify_supply_test_params( + /// Sets up test parameters for supply tests. + /// + /// This function generates two notes with the specified values and asset descriptions, + /// and returns the issuance validating key, the asset base, and the issue action. + fn supply_test_params( note1_value: u64, note2_value: u64, - note1_asset_desc: &str, - note2_asset_desc: Option<&str>, // if None, both notes use the same asset + note1_asset_desc: &[u8], + note2_asset_desc: Option<&[u8]>, // if None, both notes use the same asset finalize: bool, ) -> (IssuanceValidatingKey, AssetBase, IssueAction) { let (mut rng, _, ik, recipient, _) = setup_params(); @@ -679,16 +682,21 @@ mod tests { ( ik, asset, - IssueAction::from_parts(note1_asset_desc.into(), vec![note1, note2], finalize), + IssueAction::from_parts(note1_asset_desc.to_vec(), vec![note1, note2], finalize), ) } - // This function computes the identity point on the Pallas curve and returns an Asset Base with that value. + /// This function computes the identity point on the Pallas curve and returns an Asset Base with that value. fn identity_point() -> AssetBase { let identity_point = (Point::generator() * -Scalar::one()) + Point::generator(); AssetBase::from_bytes(&identity_point.to_bytes()).unwrap() } + /// Sets up test parameters for identity point tests. + /// + /// This function generates two notes with the identity point as their asset base, + /// and returns the issuance authorizing key, an unauthorized issue bundle containing + /// the notes, and a sighash fn identity_point_test_params( note1_value: u64, note2_value: u64, @@ -721,8 +729,7 @@ mod tests { #[test] fn verify_supply_valid() { - let (ik, test_asset, action) = - setup_verify_supply_test_params(10, 20, "Asset 1", None, false); + let (ik, test_asset, action) = supply_test_params(10, 20, b"Asset 1", None, false); let result = action.verify_supply(&ik); @@ -747,8 +754,7 @@ mod tests { #[test] fn verify_supply_finalized() { - let (ik, test_asset, action) = - setup_verify_supply_test_params(10, 20, "Asset 1", None, true); + let (ik, test_asset, action) = supply_test_params(10, 20, b"Asset 1", None, true); let result = action.verify_supply(&ik); @@ -763,8 +769,7 @@ mod tests { #[test] fn verify_supply_incorrect_asset_base() { - let (ik, _, action) = - setup_verify_supply_test_params(10, 20, "Asset 1", Some("Asset 2"), false); + let (ik, _, action) = supply_test_params(10, 20, b"Asset 1", Some(b"Asset 2"), false); assert_eq!( action.verify_supply(&ik), @@ -774,7 +779,7 @@ mod tests { #[test] fn verify_supply_ik_mismatch_asset_base() { - let (_, _, action) = setup_verify_supply_test_params(10, 20, "Asset 1", None, false); + let (_, _, action) = supply_test_params(10, 20, b"Asset 1", None, false); let (_, _, ik, _, _) = setup_params(); assert_eq!( @@ -787,13 +792,13 @@ mod tests { fn issue_bundle_basic() { let (rng, _, ik, recipient, _) = setup_params(); - let str = String::from("Halo"); - let str2 = String::from("Halo2"); + let str = "Halo".to_string(); + let str2 = "Halo2".to_string(); assert_eq!( IssueBundle::new( ik.clone(), - String::from_utf8(vec![b'X'; 513]).unwrap(), + vec![b'X'; 513], Some(IssueInfo { recipient, value: NoteValue::unsplittable() @@ -807,7 +812,7 @@ mod tests { assert_eq!( IssueBundle::new( ik.clone(), - "".to_string(), + b"".to_vec(), Some(IssueInfo { recipient, value: NoteValue::unsplittable() @@ -820,7 +825,7 @@ mod tests { let (mut bundle, asset) = IssueBundle::new( ik, - str.clone(), + str.clone().into_bytes(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -830,19 +835,21 @@ mod tests { .unwrap(); let another_asset = bundle - .add_recipient(str, recipient, NoteValue::from_raw(10), rng) + .add_recipient(&str.into_bytes(), recipient, NoteValue::from_raw(10), rng) .unwrap(); assert_eq!(asset, another_asset); let third_asset = bundle - .add_recipient(str2.clone(), recipient, NoteValue::from_raw(15), rng) + .add_recipient(str2.as_bytes(), recipient, NoteValue::from_raw(15), rng) .unwrap(); assert_ne!(asset, third_asset); let actions = bundle.actions(); assert_eq!(actions.len(), 2); - let action = bundle.get_action_by_type(asset).unwrap(); + let actions_vec = bundle.get_actions_by_asset(&asset); + assert_eq!(actions_vec.len(), 1); + let action = actions_vec[0]; assert_eq!(action.notes.len(), 2); assert_eq!(action.notes.first().unwrap().value().inner(), 5); assert_eq!(action.notes.first().unwrap().asset(), asset); @@ -852,7 +859,9 @@ mod tests { assert_eq!(action.notes.get(1).unwrap().asset(), asset); assert_eq!(action.notes.get(1).unwrap().recipient(), recipient); - let action2 = bundle.get_action(str2).unwrap(); + let action2_vec = bundle.get_actions_by_desc(str2.as_bytes()); + assert_eq!(action2_vec.len(), 1); + let action2 = action2_vec[0]; assert_eq!(action2.notes.len(), 1); assert_eq!(action2.notes().first().unwrap().value().inner(), 15); assert_eq!(action2.notes().first().unwrap().asset(), third_asset); @@ -864,7 +873,7 @@ mod tests { let (mut bundle, _) = IssueBundle::new( ik, - String::from("NFT"), + b"NFT".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(u64::MIN), @@ -874,27 +883,20 @@ mod tests { .expect("Should properly add recipient"); bundle - .finalize_action(String::from("NFT")) + .finalize_action(b"NFT") .expect("Should finalize properly"); assert_eq!( - bundle - .finalize_action(String::from("Another NFT")) - .unwrap_err(), + bundle.finalize_action(b"Another NFT").unwrap_err(), IssueActionNotFound ); assert_eq!( - bundle - .finalize_action(String::from_utf8(vec![b'X'; 513]).unwrap()) - .unwrap_err(), + bundle.finalize_action(&vec![b'X'; 513]).unwrap_err(), WrongAssetDescSize ); - assert_eq!( - bundle.finalize_action("".to_string()).unwrap_err(), - WrongAssetDescSize - ); + assert_eq!(bundle.finalize_action(b"").unwrap_err(), WrongAssetDescSize); } #[test] @@ -903,7 +905,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - String::from("Frost"), + b"Frost".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -922,7 +924,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik.clone(), - String::from("Sign"), + b"Sign".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -943,7 +945,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - String::from("IssueBundle"), + b"IssueBundle".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -969,7 +971,7 @@ mod tests { // Create a bundle with "normal" note let (mut bundle, _) = IssueBundle::new( ik, - String::from("IssueBundle"), + b"IssueBundle".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -982,7 +984,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - AssetBase::derive(bundle.ik(), "zsa_asset"), + AssetBase::derive(bundle.ik(), b"zsa_asset"), Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -1002,7 +1004,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - String::from("Verify"), + b"Verify".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1027,7 +1029,7 @@ mod tests { let (mut bundle, _) = IssueBundle::new( ik.clone(), - String::from("Verify with finalize"), + b"Verify with finalize".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(7), @@ -1036,9 +1038,7 @@ mod tests { ) .unwrap(); - bundle - .finalize_action(String::from("Verify with finalize")) - .unwrap(); + bundle.finalize_action(b"Verify with finalize").unwrap(); let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &mut HashSet::new(); @@ -1048,24 +1048,24 @@ mod tests { supply_info.update_finalization_set(prev_finalized); assert_eq!(prev_finalized.len(), 1); - assert!(prev_finalized.contains(&AssetBase::derive(&ik, "Verify with finalize"))); + assert!(prev_finalized.contains(&AssetBase::derive(&ik, b"Verify with finalize"))); } #[test] fn issue_bundle_verify_with_supply_info() { let (rng, isk, ik, recipient, sighash) = setup_params(); - let asset1_desc = "Verify with supply info 1"; - let asset2_desc = "Verify with supply info 2"; - let asset3_desc = "Verify with supply info 3"; + let asset1_desc = b"Verify with supply info 1".to_vec(); + let asset2_desc = b"Verify with supply info 2".to_vec(); + let asset3_desc = b"Verify with supply info 3".to_vec(); - let asset1_base = AssetBase::derive(&ik, &String::from(asset1_desc)); - let asset2_base = AssetBase::derive(&ik, &String::from(asset2_desc)); - let asset3_base = AssetBase::derive(&ik, &String::from(asset3_desc)); + let asset1_base = AssetBase::derive(&ik, &asset1_desc); + let asset2_base = AssetBase::derive(&ik, &asset2_desc); + let asset3_base = AssetBase::derive(&ik, &asset3_desc); let (mut bundle, _) = IssueBundle::new( ik, - String::from(asset1_desc), + asset1_desc.clone(), Some(IssueInfo { recipient, value: NoteValue::from_raw(7), @@ -1075,34 +1075,19 @@ mod tests { .unwrap(); bundle - .add_recipient( - String::from(asset1_desc), - recipient, - NoteValue::from_raw(8), - rng, - ) + .add_recipient(&asset1_desc, recipient, NoteValue::from_raw(8), rng) .unwrap(); - bundle.finalize_action(String::from(asset1_desc)).unwrap(); + bundle.finalize_action(&asset1_desc).unwrap(); bundle - .add_recipient( - String::from(asset2_desc), - recipient, - NoteValue::from_raw(10), - rng, - ) + .add_recipient(&asset2_desc, recipient, NoteValue::from_raw(10), rng) .unwrap(); - bundle.finalize_action(String::from(asset2_desc)).unwrap(); + bundle.finalize_action(&asset2_desc).unwrap(); bundle - .add_recipient( - String::from(asset3_desc), - recipient, - NoteValue::from_raw(5), - rng, - ) + .add_recipient(&asset3_desc, recipient, NoteValue::from_raw(5), rng) .unwrap(); let signed = bundle.prepare(sighash).sign(&isk).unwrap(); @@ -1140,7 +1125,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik.clone(), - String::from("already final"), + b"already final".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1152,7 +1137,7 @@ mod tests { let signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = &mut HashSet::new(); - let final_type = AssetBase::derive(&ik, &String::from("already final")); + let final_type = AssetBase::derive(&ik, b"already final"); prev_finalized.insert(final_type); @@ -1175,7 +1160,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - String::from("bad sig"), + b"bad sig".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1205,7 +1190,7 @@ mod tests { let (rng, isk, ik, recipient, random_sighash) = setup_params(); let (bundle, _) = IssueBundle::new( ik, - String::from("Asset description"), + b"Asset description".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1230,7 +1215,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - String::from("Asset description"), + b"Asset description".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1245,7 +1230,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(5), - AssetBase::derive(signed.ik(), "zsa_asset"), + AssetBase::derive(signed.ik(), b"zsa_asset"), Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -1262,13 +1247,13 @@ mod tests { #[test] fn issue_bundle_verify_fail_incorrect_ik() { - let asset_description = "Asset"; + let asset_description = b"Asset".to_vec(); let (mut rng, isk, ik, recipient, sighash) = setup_params(); let (bundle, _) = IssueBundle::new( ik, - String::from(asset_description), + asset_description.clone(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1286,7 +1271,7 @@ mod tests { let note = Note::new( recipient, NoteValue::from_raw(55), - AssetBase::derive(&incorrect_ik, asset_description), + AssetBase::derive(&incorrect_ik, &asset_description), Rho::from_nf_old(Nullifier::dummy(&mut rng)), &mut rng, ); @@ -1303,9 +1288,9 @@ mod tests { #[test] fn issue_bundle_verify_fail_wrong_asset_descr_size() { - // we want to inject "bad" description for test purposes. + // we want to inject a "malformed" description for test purposes. impl IssueAction { - pub fn modify_descr(&mut self, new_descr: String) { + pub fn modify_descr(&mut self, new_descr: Vec) { self.asset_desc = new_descr; } } @@ -1314,7 +1299,7 @@ mod tests { let (bundle, _) = IssueBundle::new( ik, - String::from("Asset description"), + b"Asset description".to_vec(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), @@ -1326,19 +1311,16 @@ mod tests { let mut signed = bundle.prepare(sighash).sign(&isk).unwrap(); let prev_finalized = HashSet::new(); - // 1. Try too long description - signed - .actions - .first_mut() - .modify_descr(String::from_utf8(vec![b'X'; 513]).unwrap()); + // 1. Try a description that is too long + signed.actions.first_mut().modify_descr(vec![b'X'; 513]); assert_eq!( verify_issue_bundle(&signed, sighash, &prev_finalized).unwrap_err(), WrongAssetDescSize ); - // 2. Try empty description - signed.actions.first_mut().modify_descr("".to_string()); + // 2. Try a description that is empty + signed.actions.first_mut().modify_descr(b"".to_vec()); assert_eq!( verify_issue_bundle(&signed, sighash, &prev_finalized).unwrap_err(), @@ -1380,19 +1362,66 @@ mod tests { let (_, _, note) = Note::dummy(&mut rng, None, AssetBase::native()); let action = - IssueAction::new_with_flags(String::from("Asset description"), vec![note], 0u8) - .unwrap(); + IssueAction::new_with_flags(b"Asset description".to_vec(), vec![note], 0u8).unwrap(); assert_eq!(action.flags(), 0b0000_0000); let action = - IssueAction::new_with_flags(String::from("Asset description"), vec![note], 1u8) - .unwrap(); + IssueAction::new_with_flags(b"Asset description".to_vec(), vec![note], 1u8).unwrap(); assert_eq!(action.flags(), 0b0000_0001); - let action = - IssueAction::new_with_flags(String::from("Asset description"), vec![note], 2u8); + let action = IssueAction::new_with_flags(b"Asset description".to_vec(), vec![note], 2u8); assert!(action.is_none()); } + + #[test] + fn issue_bundle_asset_desc_roundtrip() { + let (rng, _, ik, recipient, _) = setup_params(); + + // Generated using https://onlinetools.com/utf8/generate-random-utf8 + let asset_desc_1 = "󅞞 򬪗YV8𱈇m0{둛򙎠[㷊V֤]9Ծ̖l󾓨2닯򗏟iȰ䣄˃Oߺ񗗼🦄" + .to_string() + .as_bytes() + .to_vec(); + + // Not well-formed as per Unicode 15.0 specification, Section 3.9, D92 + let asset_desc_2: Vec = vec![0xc0, 0xaf]; + + // Confirm not valid UTF-8 + assert!(String::from_utf8(asset_desc_2.clone()).is_err()); + + let (mut bundle, asset_base_1) = IssueBundle::new( + ik, + asset_desc_1.clone(), + Some(IssueInfo { + recipient, + value: NoteValue::from_raw(5), + }), + rng, + ) + .unwrap(); + + let asset_base_2 = bundle + .add_recipient(&asset_desc_2, recipient, NoteValue::from_raw(10), rng) + .unwrap(); + + // Checks for the case of UTF-8 encoded asset description. + let actions_vec = bundle.get_actions_by_asset(&asset_base_1); + assert_eq!(actions_vec.len(), 1); + + let action = actions_vec[0]; + assert_eq!(action.asset_desc(), &asset_desc_1); + assert_eq!(action.notes.first().unwrap().value().inner(), 5); + assert_eq!(bundle.get_actions_by_desc(&asset_desc_1), actions_vec); + + // Checks for the case on non-UTF-8 encoded asset description. + let action2_vec = bundle.get_actions_by_asset(&asset_base_2); + assert_eq!(action2_vec.len(), 1); + + let action2 = action2_vec[0]; + assert_eq!(action2.asset_desc(), &asset_desc_2); + assert_eq!(action2.notes.first().unwrap().value().inner(), 10); + assert_eq!(bundle.get_actions_by_desc(&asset_desc_2), action2_vec); + } } /// Generators for property testing. @@ -1420,7 +1449,7 @@ pub mod testing { prop_compose! { /// Generate an issue action - pub fn arb_issue_action(asset_desc: String) + pub fn arb_issue_action(asset_desc: Vec) ( asset in zsa_asset_base(asset_desc.clone()), ) @@ -1439,7 +1468,7 @@ pub mod testing { /// Generate an arbitrary issue bundle with fake authorization data. pub fn arb_unathorized_issue_bundle(n_actions: usize) ( - actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), + actions in vec(arb_issue_action(b"asset_desc".to_vec()), n_actions), ik in arb_issuance_validating_key() ) -> IssueBundle { let actions = NonEmpty::from_vec(actions).unwrap(); @@ -1456,7 +1485,7 @@ pub mod testing { /// necessarily respect consensus rules pub fn arb_prepared_issue_bundle(n_actions: usize) ( - actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), + actions in vec(arb_issue_action(b"asset_desc".to_vec()), n_actions), ik in arb_issuance_validating_key(), fake_sighash in prop::array::uniform32(prop::num::u8::ANY) ) -> IssueBundle { @@ -1474,7 +1503,7 @@ pub mod testing { /// necessarily respect consensus rules pub fn arb_signed_issue_bundle(n_actions: usize) ( - actions in vec(arb_issue_action("asset_desc".to_string()), n_actions), + actions in vec(arb_issue_action(b"asset_desc".to_vec()), n_actions), ik in arb_issuance_validating_key(), fake_sig in arb_signature(), ) -> IssueBundle { diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index 6856bee74..e0ee796f8 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -55,7 +55,7 @@ impl AssetBase { /// /// Panics if `asset_desc` is empty or greater than `MAX_ASSET_DESCRIPTION_SIZE` or if the derived Asset Base is the identity point. #[allow(non_snake_case)] - pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &str) -> Self { + pub fn derive(ik: &IssuanceValidatingKey, asset_desc: &[u8]) -> Self { assert!( is_asset_desc_of_valid_size(asset_desc), "The asset_desc string is not of valid size" @@ -63,7 +63,7 @@ impl AssetBase { // EncodeAssetId(ik, asset_desc) = version_byte || ik || asset_desc let version_byte = [0x00]; - let encode_asset_id = [&version_byte[..], &ik.to_bytes(), asset_desc.as_bytes()].concat(); + let encode_asset_id = [&version_byte[..], &ik.to_bytes(), asset_desc].concat(); let asset_digest = asset_digest(encode_asset_id); @@ -103,8 +103,8 @@ impl AssetBase { pub(crate) fn random() -> Self { let isk = IssuanceAuthorizingKey::random(); let ik = IssuanceValidatingKey::from(&isk); - let asset_descr = "zsa_asset"; - AssetBase::derive(&ik, asset_descr) + let asset_descr = b"zsa_asset".to_vec(); + AssetBase::derive(&ik, &asset_descr) } } @@ -116,8 +116,8 @@ impl Hash for AssetBase { } /// Check that `asset_desc` is of valid size. -pub fn is_asset_desc_of_valid_size(asset_desc: &str) -> bool { - !asset_desc.is_empty() && asset_desc.bytes().len() <= MAX_ASSET_DESCRIPTION_SIZE +pub fn is_asset_desc_of_valid_size(asset_desc: &[u8]) -> bool { + !asset_desc.is_empty() && asset_desc.len() <= MAX_ASSET_DESCRIPTION_SIZE } impl PartialEq for AssetBase { @@ -141,19 +141,19 @@ pub mod testing { pub fn arb_asset_base()( is_native in prop::bool::ANY, isk in arb_issuance_authorizing_key(), - str in "[A-Za-z]{255}", + asset_desc in prop::collection::vec(any::(), 1..=511), ) -> AssetBase { if is_native { AssetBase::native() } else { - AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) } } } prop_compose! { /// Generate the native note type - pub fn native_asset_base()(_i in 0..10) -> AssetBase { + pub fn native_asset_base()(_i in 0..1) -> AssetBase { // TODO: remove _i AssetBase::native() } @@ -163,15 +163,15 @@ pub mod testing { /// Generate an asset ID pub fn arb_zsa_asset_base()( isk in arb_issuance_authorizing_key(), - str in "[A-Za-z]{255}" + asset_desc in prop::collection::vec(any::(), 1..=511), ) -> AssetBase { - AssetBase::derive(&IssuanceValidatingKey::from(&isk), &str) + AssetBase::derive(&IssuanceValidatingKey::from(&isk), &asset_desc) } } prop_compose! { /// Generate an asset ID using a specific description - pub fn zsa_asset_base(asset_desc: String)( + pub fn zsa_asset_base(asset_desc: Vec)( isk in arb_issuance_authorizing_key(), ) -> AssetBase { assert!(super::is_asset_desc_of_valid_size(&asset_desc)); @@ -184,11 +184,9 @@ pub mod testing { let test_vectors = crate::test_vectors::asset_base::test_vectors(); for tv in test_vectors { - let description = std::str::from_utf8(&tv.description).unwrap(); - let calculated_asset_base = AssetBase::derive( &IssuanceValidatingKey::from_bytes(&tv.key).unwrap(), - description, + &tv.description, ); let test_vector_asset_base = AssetBase::from_bytes(&tv.asset_base).unwrap(); diff --git a/src/supply_info.rs b/src/supply_info.rs index 1e3c8d28f..6fb69d516 100644 --- a/src/supply_info.rs +++ b/src/supply_info.rs @@ -79,7 +79,7 @@ impl Default for SupplyInfo { mod tests { use super::*; - fn create_test_asset(asset_desc: &str) -> AssetBase { + fn create_test_asset(asset_desc: &[u8]) -> AssetBase { use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); @@ -98,8 +98,8 @@ mod tests { fn test_add_supply_valid() { let mut supply_info = SupplyInfo::new(); - let asset1 = create_test_asset("Asset 1"); - let asset2 = create_test_asset("Asset 2"); + let asset1 = create_test_asset(b"Asset 1"); + let asset2 = create_test_asset(b"Asset 2"); let supply1 = AssetSupply::new(ValueSum::from_raw(20), false); let supply2 = AssetSupply::new(ValueSum::from_raw(30), true); @@ -167,9 +167,9 @@ mod tests { fn test_update_finalization_set() { let mut supply_info = SupplyInfo::new(); - let asset1 = create_test_asset("Asset 1"); - let asset2 = create_test_asset("Asset 2"); - let asset3 = create_test_asset("Asset 3"); + let asset1 = create_test_asset(b"Asset 1"); + let asset2 = create_test_asset(b"Asset 2"); + let asset3 = create_test_asset(b"Asset 3"); let supply1 = AssetSupply::new(ValueSum::from_raw(10), false); let supply2 = AssetSupply::new(ValueSum::from_raw(20), true); diff --git a/tests/zsa.rs b/tests/zsa.rs index fced143a0..befc65e91 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -136,12 +136,12 @@ pub fn build_merkle_path_with_two_leaves( (merkle_path1, merkle_path2, anchor) } -fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { +fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note) { let mut rng = OsRng; // Create a issuance bundle let unauthorized_asset = IssueBundle::new( keys.ik().clone(), - asset_descr.to_string(), + asset_descr.to_owned(), Some(IssueInfo { recipient: keys.recipient, value: NoteValue::from_raw(40), @@ -155,7 +155,7 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { assert!(unauthorized .add_recipient( - asset_descr.to_string(), + asset_descr, keys.recipient, NoteValue::from_raw(2), &mut rng, @@ -166,8 +166,8 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) { // Take notes from first action let notes = issue_bundle.get_all_notes(); - let note1 = notes.get(0).unwrap(); - let note2 = notes.get(1).unwrap(); + let note1 = notes[0]; + let note2 = notes[1]; assert!(verify_issue_bundle( &issue_bundle, @@ -290,10 +290,10 @@ fn zsa_issue_and_transfer() { // --------------------------- Setup ----------------------------------------- let keys = prepare_keys(); - let asset_descr = "zsa_asset"; + let asset_descr = b"zsa_asset".to_vec(); // Prepare ZSA - let (zsa_note_1, zsa_note_2) = issue_zsa_notes(asset_descr, &keys); + let (zsa_note_1, zsa_note_2) = issue_zsa_notes(&asset_descr, &keys); let (merkle_path1, merkle_path2, anchor) = build_merkle_path_with_two_leaves(&zsa_note_1, &zsa_note_2); @@ -446,7 +446,7 @@ fn zsa_issue_and_transfer() { .unwrap(); // 7. Spend ZSA notes of different asset types - let (zsa_note_t7, _) = issue_zsa_notes("zsa_asset2", &keys); + let (zsa_note_t7, _) = issue_zsa_notes(b"zsa_asset2", &keys); let (merkle_path_t7_1, merkle_path_t7_2, anchor_t7) = build_merkle_path_with_two_leaves(&zsa_note_t7, &zsa_note_2); let zsa_spend_t7_1: TestSpendInfo = TestSpendInfo { From a7c02d22a1e2f4310130ae2e7b9813136071bc75 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Tue, 15 Oct 2024 11:01:14 +0200 Subject: [PATCH 76/92] Provide compatibility with librustzcash/zcash_client_backend: derive Clone for CompactAction (#118) This PR updates the crate to ensure compatibility with the `zcash_client_backend` crate in `librustzcash` repository. Specifically, it derives the `Clone` trait for the `CompactAction` struct to resolve compilation errors when the `orchard` feature is enabled for `zcash_client_backend` crate (`BatchRunner` struct there requires that). --- src/note_encryption/compact_action.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/note_encryption/compact_action.rs b/src/note_encryption/compact_action.rs index 8ed04d983..b1a3a6664 100644 --- a/src/note_encryption/compact_action.rs +++ b/src/note_encryption/compact_action.rs @@ -33,6 +33,7 @@ impl ShieldedOutput> for Action { nullifier: Nullifier, cmx: ExtractedNoteCommitment, From 25020f857fd40125b3872ece1c0a2e2059145a17 Mon Sep 17 00:00:00 2001 From: Alexey <2365507+alexeykoren@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:44:22 +0100 Subject: [PATCH 77/92] Exclude non-native assets from value_balance (#120) Exclude non-native assets from value_balance --- src/builder.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index fff4de8c3..7e3b8fee4 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -619,7 +619,7 @@ impl Builder { &self.outputs } - /// The net value of the bundle to be built. The value of all spends, + /// The net native (ZEC) value of the bundle to be built. The value of all spends, /// minus the value of all outputs. /// /// Useful for balancing a transaction, as the value balance of an individual bundle @@ -633,10 +633,12 @@ impl Builder { let value_balance = self .spends .iter() + .filter(|spend| spend.note.asset().is_native().into()) .map(|spend| spend.note.value() - NoteValue::zero()) .chain( self.outputs .iter() + .filter(|output| output.asset.is_native().into()) .map(|output| NoteValue::zero() - output.value), ) .try_fold(ValueSum::zero(), |acc, note_value| acc + note_value) From 8a2a8de879ed2efdcadd7ee13269f2f7db34f567 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 28 Nov 2024 14:44:21 +0100 Subject: [PATCH 78/92] Simplify Unproven struct We would like to remove the generic circuit parameter from Unproven structure. To do that, we create a Witnesses structure which contains the witnesses of the circuit but not the circuit type (OrchardZSA or OrchardVanilla). Key changes: - Updated `src/builder.rs` to replace `Circuit` with `Witnesses` in several function signatures and type definitions. - Adjusted `src/circuit.rs` to define and use the new `Witnesses` structure instead of `Circuit`. --- src/builder.rs | 54 +++++++--- src/circuit.rs | 21 ++-- src/circuit/circuit_vanilla.rs | 80 ++++++--------- src/circuit/circuit_zsa.rs | 182 ++++++++++++++++----------------- src/orchard_flavor.rs | 24 ++++- 5 files changed, 195 insertions(+), 166 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 7e3b8fee4..c45afa1eb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -13,18 +13,19 @@ use rand::{prelude::SliceRandom, CryptoRng, RngCore}; use zcash_note_encryption_zsa::NoteEncryption; use crate::builder::BuildError::{BurnNative, BurnZero}; +use crate::orchard_flavor::{OrchardVanilla, OrchardZSA}; use crate::{ action::Action, address::Address, bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags}, - circuit::{Circuit, Instance, OrchardCircuit, Proof, ProvingKey}, + circuit::{Circuit, Instance, Proof, ProvingKey, Witnesses}, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, }, note::{AssetBase, Note, Rho, TransmittedNoteCiphertext}, note_encryption::{OrchardDomain, OrchardDomainCommon}, - orchard_flavor::OrchardFlavor, + orchard_flavor::{Flavor, OrchardFlavor}, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, value::{self, NoteValue, OverflowError, ValueCommitTrapdoor, ValueCommitment, ValueSum}, @@ -397,7 +398,7 @@ impl ActionInfo { fn build( self, mut rng: impl RngCore, - ) -> (Action, Circuit) { + ) -> (Action, Witnesses) { assert_eq!( self.spend.note.asset(), self.output.asset, @@ -445,7 +446,7 @@ impl ActionInfo { parts: SigningParts { ak, alpha }, }, ), - Circuit::::from_action_context_unchecked(self.spend, note, alpha, self.rcv), + Witnesses::from_action_context_unchecked(self.spend, note, alpha, self.rcv), ) } } @@ -453,7 +454,7 @@ impl ActionInfo { /// Type alias for an in-progress bundle that has no proofs or signatures. /// /// This is returned by [`Builder::build`]. -pub type UnauthorizedBundle = Bundle, Unauthorized>, V, D>; +pub type UnauthorizedBundle = Bundle, V, D>; /// Metadata about a bundle created by [`bundle`] or [`Builder::build`] that is not /// necessarily recoverable from the bundle itself. @@ -863,7 +864,7 @@ pub fn bundle, FL: OrchardFlavor>( .into_bsk(); // Create the actions. - let (actions, circuits): (Vec<_>, Vec<_>) = + let (actions, witnesses): (Vec<_>, Vec<_>) = pre_actions.into_iter().map(|a| a.build(&mut rng)).unzip(); let burn = burn @@ -892,7 +893,10 @@ pub fn bundle, FL: OrchardFlavor>( burn, anchor, InProgress { - proof: Unproven { circuits }, + proof: Unproven { + witnesses, + circuit_flavor: FL::FLAVOR, + }, sigs: Unauthorized { bsk }, }, ), @@ -935,11 +939,12 @@ impl Authorization for InProgress /// /// This struct contains the private data needed to create a [`Proof`] for a [`Bundle`]. #[derive(Clone, Debug)] -pub struct Unproven { - circuits: Vec>, +pub struct Unproven { + witnesses: Vec, + circuit_flavor: Flavor, } -impl InProgress, S> { +impl InProgress { /// Creates the proof for this bundle. pub fn create_proof( &self, @@ -947,11 +952,36 @@ impl InProgress, S> { instances: &[Instance], rng: impl RngCore, ) -> Result { - Proof::create(pk, &self.proof.circuits, instances, rng) + match self.proof.circuit_flavor { + Flavor::OrchardVanillaFlavor => { + let circuits = self + .proof + .witnesses + .iter() + .map(|witnesses| Circuit:: { + witnesses: witnesses.clone(), + phantom: std::marker::PhantomData, + }) + .collect::>>(); + Proof::create(pk, &circuits, instances, rng) + } + Flavor::OrchardZSAFlavor => { + let circuits = self + .proof + .witnesses + .iter() + .map(|witnesses| Circuit:: { + witnesses: witnesses.clone(), + phantom: std::marker::PhantomData, + }) + .collect::>>(); + Proof::create(pk, &circuits, instances, rng) + } + } } } -impl Bundle, S>, V, FL> { +impl Bundle, V, FL> { /// Creates the proof for this bundle. pub fn create_proof( self, diff --git a/src/circuit.rs b/src/circuit.rs index b0be32ce7..65ce158ef 100644 --- a/src/circuit.rs +++ b/src/circuit.rs @@ -105,7 +105,7 @@ pub trait OrchardCircuit: Sized + Default { /// Wrapper for configure function of plonk::Circuit trait fn synthesize( - circuit: &Circuit, + circuit: &Witnesses, config: Self::Config, layouter: impl Layouter, ) -> Result<(), plonk::Error>; @@ -128,13 +128,20 @@ impl plonk::Circuit for Circuit { config: Self::Config, layouter: impl Layouter, ) -> Result<(), plonk::Error> { - C::synthesize(self, config, layouter) + C::synthesize(&self.witnesses, config, layouter) } } /// The Orchard Action circuit. #[derive(Clone, Debug, Default)] pub struct Circuit { + pub(crate) witnesses: Witnesses, + pub(crate) phantom: std::marker::PhantomData, +} + +/// The Orchard Action witnesses +#[derive(Clone, Debug, Default)] +pub struct Witnesses { pub(crate) path: Value<[MerkleHashOrchard; MERKLE_DEPTH_ORCHARD]>, pub(crate) pos: Value, pub(crate) g_d_old: Value, @@ -157,10 +164,9 @@ pub struct Circuit { pub(crate) rcv: Value, pub(crate) asset: Value, pub(crate) split_flag: Value, - phantom: std::marker::PhantomData, } -impl Circuit { +impl Witnesses { /// This constructor is public to enable creation of custom builders. /// If you are not creating a custom builder, use [`Builder`] to compose /// and authorize a transaction. @@ -181,7 +187,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Option> { + ) -> Option { (Rho::from_nf_old(spend.note.nullifier(&spend.fvk)) == output_note.rho()) .then(|| Self::from_action_context_unchecked(spend, output_note, alpha, rcv)) } @@ -191,7 +197,7 @@ impl Circuit { output_note: Note, alpha: pallas::Scalar, rcv: ValueCommitTrapdoor, - ) -> Circuit { + ) -> Self { let sender_address = spend.note.recipient(); let rho_old = spend.note.rho(); let psi_old = spend.note.rseed().psi(&rho_old); @@ -204,7 +210,7 @@ impl Circuit { let psi_new = output_note.rseed().psi(&rho_new); let rcm_new = output_note.rseed().rcm(&rho_new); - Circuit { + Witnesses { path: Value::known(spend.merkle_path.auth_path()), pos: Value::known(spend.merkle_path.position()), g_d_old: Value::known(sender_address.g_d()), @@ -227,7 +233,6 @@ impl Circuit { rcv: Value::known(rcv), asset: Value::known(spend.note.asset()), split_flag: Value::known(spend.split_flag), - phantom: std::marker::PhantomData, } } } diff --git a/src/circuit/circuit_vanilla.rs b/src/circuit/circuit_vanilla.rs index 7f756e322..4fcb95ce2 100644 --- a/src/circuit/circuit_vanilla.rs +++ b/src/circuit/circuit_vanilla.rs @@ -28,7 +28,7 @@ use crate::{ circuit::derive_nullifier::gadgets::derive_nullifier, circuit::note_commit::gadgets::note_commit, circuit::value_commit_orchard::gadgets::value_commit_orchard, - circuit::Config, + circuit::{Config, Witnesses}, constants::{OrchardFixedBases, OrchardFixedBasesFull, OrchardHashDomains}, orchard_flavor::OrchardVanilla, }; @@ -37,8 +37,8 @@ use super::{ commit_ivk::CommitIvkChip, gadget::{add_chip::AddChip, assign_free_advice}, note_commit::NoteCommitChip, - Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, - RK_X, RK_Y, + OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, NF_OLD, RK_X, + RK_Y, }; impl OrchardCircuit for OrchardVanilla { @@ -235,7 +235,7 @@ impl OrchardCircuit for OrchardVanilla { #[allow(non_snake_case)] fn synthesize( - circuit: &Circuit, + circuit: &Witnesses, config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), plonk::Error> { @@ -620,6 +620,7 @@ mod tests { use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; + use crate::circuit::Witnesses; use crate::{ bundle::Flags, circuit::{Circuit, Instance, Proof, ProvingKey, VerifyingKey, K}, @@ -658,29 +659,31 @@ mod tests { ( OrchardCircuitVanilla { - path: Value::known(path.auth_path()), - pos: Value::known(path.position()), - g_d_old: Value::known(sender_address.g_d()), - pk_d_old: Value::known(*sender_address.pk_d()), - v_old: Value::known(spent_note.value()), - rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), - rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Value::known(spent_note.commitment()), - // For non split note, psi_nf is equal to psi_old - psi_nf: Value::known(psi_old), - alpha: Value::known(alpha), - ak: Value::known(ak), - nk: Value::known(nk), - rivk: Value::known(rivk), - g_d_new: Value::known(output_note.recipient().g_d()), - pk_d_new: Value::known(*output_note.recipient().pk_d()), - v_new: Value::known(output_note.value()), - psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), - rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - rcv: Value::known(rcv), - asset: Value::known(spent_note.asset()), - split_flag: Value::known(false), + witnesses: Witnesses { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(spent_note.rseed().psi(&spent_note.rho())), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + }, phantom: std::marker::PhantomData, }, Instance { @@ -858,28 +861,7 @@ mod tests { .unwrap(); let circuit = OrchardCircuitVanilla { - path: Value::unknown(), - pos: Value::unknown(), - g_d_old: Value::unknown(), - pk_d_old: Value::unknown(), - v_old: Value::unknown(), - rho_old: Value::unknown(), - psi_old: Value::unknown(), - rcm_old: Value::unknown(), - cm_old: Value::unknown(), - psi_nf: Value::unknown(), - alpha: Value::unknown(), - ak: Value::unknown(), - nk: Value::unknown(), - rivk: Value::unknown(), - g_d_new: Value::unknown(), - pk_d_new: Value::unknown(), - v_new: Value::unknown(), - psi_new: Value::unknown(), - rcm_new: Value::unknown(), - rcv: Value::unknown(), - asset: Value::unknown(), - split_flag: Value::unknown(), + witnesses: Witnesses::default(), phantom: std::marker::PhantomData, }; halo2_proofs::dev::CircuitLayout::default() diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs index f4985137c..34f9c120e 100644 --- a/src/circuit/circuit_zsa.rs +++ b/src/circuit/circuit_zsa.rs @@ -33,15 +33,15 @@ use super::{ gadget::{add_chip::AddChip, assign_free_advice, assign_is_native_asset, assign_split_flag}, note_commit::NoteCommitChip, value_commit_orchard::ZsaValueCommitParams, - Circuit, OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, - ENABLE_ZSA, NF_OLD, RK_X, RK_Y, + OrchardCircuit, ANCHOR, CMX, CV_NET_X, CV_NET_Y, ENABLE_OUTPUT, ENABLE_SPEND, ENABLE_ZSA, + NF_OLD, RK_X, RK_Y, }; use crate::{ circuit::commit_ivk::gadgets::commit_ivk, circuit::derive_nullifier::gadgets::derive_nullifier, circuit::note_commit::{gadgets::note_commit, ZsaNoteCommitParams}, circuit::value_commit_orchard::gadgets::value_commit_orchard, - circuit::Config, + circuit::{Config, Witnesses}, constants::OrchardFixedBasesFull, constants::{OrchardFixedBases, OrchardHashDomains}, note::AssetBase, @@ -322,7 +322,7 @@ impl OrchardCircuit for OrchardZSA { #[allow(non_snake_case)] fn synthesize( - circuit: &Circuit, + circuit: &Witnesses, config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), plonk::Error> { @@ -843,6 +843,7 @@ mod tests { use pasta_curves::pallas; use rand::{rngs::OsRng, RngCore}; + use crate::circuit::Witnesses; use crate::{ builder::SpendInfo, bundle::Flags, @@ -883,29 +884,31 @@ mod tests { ( OrchardCircuitZSA { - path: Value::known(path.auth_path()), - pos: Value::known(path.position()), - g_d_old: Value::known(sender_address.g_d()), - pk_d_old: Value::known(*sender_address.pk_d()), - v_old: Value::known(spent_note.value()), - rho_old: Value::known(spent_note.rho()), - psi_old: Value::known(psi_old), - rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), - cm_old: Value::known(spent_note.commitment()), - // For non split note, psi_nf is equal to psi_old - psi_nf: Value::known(psi_old), - alpha: Value::known(alpha), - ak: Value::known(ak), - nk: Value::known(nk), - rivk: Value::known(rivk), - g_d_new: Value::known(output_note.recipient().g_d()), - pk_d_new: Value::known(*output_note.recipient().pk_d()), - v_new: Value::known(output_note.value()), - psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), - rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), - rcv: Value::known(rcv), - asset: Value::known(spent_note.asset()), - split_flag: Value::known(false), + witnesses: Witnesses { + path: Value::known(path.auth_path()), + pos: Value::known(path.position()), + g_d_old: Value::known(sender_address.g_d()), + pk_d_old: Value::known(*sender_address.pk_d()), + v_old: Value::known(spent_note.value()), + rho_old: Value::known(spent_note.rho()), + psi_old: Value::known(psi_old), + rcm_old: Value::known(spent_note.rseed().rcm(&spent_note.rho())), + cm_old: Value::known(spent_note.commitment()), + // For non split note, psi_nf is equal to psi_old + psi_nf: Value::known(psi_old), + alpha: Value::known(alpha), + ak: Value::known(ak), + nk: Value::known(nk), + rivk: Value::known(rivk), + g_d_new: Value::known(output_note.recipient().g_d()), + pk_d_new: Value::known(*output_note.recipient().pk_d()), + v_new: Value::known(output_note.value()), + psi_new: Value::known(output_note.rseed().psi(&output_note.rho())), + rcm_new: Value::known(output_note.rseed().rcm(&output_note.rho())), + rcv: Value::known(rcv), + asset: Value::known(spent_note.asset()), + split_flag: Value::known(false), + }, phantom: std::marker::PhantomData, }, Instance { @@ -1084,28 +1087,7 @@ mod tests { .unwrap(); let circuit = OrchardCircuitZSA { - path: Value::unknown(), - pos: Value::unknown(), - g_d_old: Value::unknown(), - pk_d_old: Value::unknown(), - v_old: Value::unknown(), - rho_old: Value::unknown(), - psi_old: Value::unknown(), - rcm_old: Value::unknown(), - cm_old: Value::unknown(), - psi_nf: Value::unknown(), - alpha: Value::unknown(), - ak: Value::unknown(), - nk: Value::unknown(), - rivk: Value::unknown(), - g_d_new: Value::unknown(), - pk_d_new: Value::unknown(), - v_new: Value::unknown(), - psi_new: Value::unknown(), - rcm_new: Value::unknown(), - rcv: Value::unknown(), - asset: Value::unknown(), - split_flag: Value::unknown(), + witnesses: Witnesses::default(), phantom: std::marker::PhantomData, }; halo2_proofs::dev::CircuitLayout::default() @@ -1222,7 +1204,15 @@ mod tests { }; ( - OrchardCircuitZSA::from_action_context_unchecked(spend_info, output_note, alpha, rcv), + OrchardCircuitZSA { + witnesses: Witnesses::from_action_context_unchecked( + spend_info, + output_note, + alpha, + rcv, + ), + phantom: std::marker::PhantomData, + }, Instance { anchor, cv_net, @@ -1293,28 +1283,30 @@ mod tests { // Set cm_old to be a random NoteCommitment // The proof should fail let circuit_wrong_cm_old = OrchardCircuitZSA { - path: circuit.path, - pos: circuit.pos, - g_d_old: circuit.g_d_old, - pk_d_old: circuit.pk_d_old, - v_old: circuit.v_old, - rho_old: circuit.rho_old, - psi_old: circuit.psi_old, - rcm_old: circuit.rcm_old.clone(), - cm_old: Value::known(random_note_commitment(&mut rng)), - psi_nf: circuit.psi_nf, - alpha: circuit.alpha, - ak: circuit.ak.clone(), - nk: circuit.nk, - rivk: circuit.rivk, - g_d_new: circuit.g_d_new, - pk_d_new: circuit.pk_d_new, - v_new: circuit.v_new, - psi_new: circuit.psi_new, - rcm_new: circuit.rcm_new.clone(), - rcv: circuit.rcv, - asset: circuit.asset, - split_flag: circuit.split_flag, + witnesses: Witnesses { + path: circuit.witnesses.path, + pos: circuit.witnesses.pos, + g_d_old: circuit.witnesses.g_d_old, + pk_d_old: circuit.witnesses.pk_d_old, + v_old: circuit.witnesses.v_old, + rho_old: circuit.witnesses.rho_old, + psi_old: circuit.witnesses.psi_old, + rcm_old: circuit.witnesses.rcm_old.clone(), + cm_old: Value::known(random_note_commitment(&mut rng)), + psi_nf: circuit.witnesses.psi_nf, + alpha: circuit.witnesses.alpha, + ak: circuit.witnesses.ak.clone(), + nk: circuit.witnesses.nk, + rivk: circuit.witnesses.rivk, + g_d_new: circuit.witnesses.g_d_new, + pk_d_new: circuit.witnesses.pk_d_new, + v_new: circuit.witnesses.v_new, + psi_new: circuit.witnesses.psi_new, + rcm_new: circuit.witnesses.rcm_new.clone(), + rcv: circuit.witnesses.rcv, + asset: circuit.witnesses.asset, + split_flag: circuit.witnesses.split_flag, + }, phantom: std::marker::PhantomData, }; check_proof_of_orchard_circuit(&circuit_wrong_cm_old, &instance, false); @@ -1351,28 +1343,30 @@ mod tests { // The proof should fail if !split_flag { let circuit_wrong_psi_nf = OrchardCircuitZSA { - path: circuit.path, - pos: circuit.pos, - g_d_old: circuit.g_d_old, - pk_d_old: circuit.pk_d_old, - v_old: circuit.v_old, - rho_old: circuit.rho_old, - psi_old: circuit.psi_old, - rcm_old: circuit.rcm_old.clone(), - cm_old: circuit.cm_old.clone(), - psi_nf: Value::known(pallas::Base::random(&mut rng)), - alpha: circuit.alpha, - ak: circuit.ak.clone(), - nk: circuit.nk, - rivk: circuit.rivk, - g_d_new: circuit.g_d_new, - pk_d_new: circuit.pk_d_new, - v_new: circuit.v_new, - psi_new: circuit.psi_new, - rcm_new: circuit.rcm_new.clone(), - rcv: circuit.rcv, - asset: circuit.asset, - split_flag: circuit.split_flag, + witnesses: Witnesses { + path: circuit.witnesses.path, + pos: circuit.witnesses.pos, + g_d_old: circuit.witnesses.g_d_old, + pk_d_old: circuit.witnesses.pk_d_old, + v_old: circuit.witnesses.v_old, + rho_old: circuit.witnesses.rho_old, + psi_old: circuit.witnesses.psi_old, + rcm_old: circuit.witnesses.rcm_old.clone(), + cm_old: circuit.witnesses.cm_old.clone(), + psi_nf: Value::known(pallas::Base::random(&mut rng)), + alpha: circuit.witnesses.alpha, + ak: circuit.witnesses.ak.clone(), + nk: circuit.witnesses.nk, + rivk: circuit.witnesses.rivk, + g_d_new: circuit.witnesses.g_d_new, + pk_d_new: circuit.witnesses.pk_d_new, + v_new: circuit.witnesses.v_new, + psi_new: circuit.witnesses.psi_new, + rcm_new: circuit.witnesses.rcm_new.clone(), + rcv: circuit.witnesses.rcv, + asset: circuit.witnesses.asset, + split_flag: circuit.witnesses.split_flag, + }, phantom: std::marker::PhantomData, }; check_proof_of_orchard_circuit(&circuit_wrong_psi_nf, &instance, false); diff --git a/src/orchard_flavor.rs b/src/orchard_flavor.rs index 481aba5c1..7ec0ffdc9 100644 --- a/src/orchard_flavor.rs +++ b/src/orchard_flavor.rs @@ -10,8 +10,26 @@ pub struct OrchardVanilla; #[derive(Debug, Clone, Default)] pub struct OrchardZSA; +/// Represents the flavor of the Orchard protocol. +/// +/// This enables conditional execution during runtime based on the flavor of the Orchard protocol. +#[derive(Clone, Debug)] +pub enum Flavor { + /// The "Vanilla" flavor of the Orchard protocol. + OrchardVanillaFlavor, + /// The "ZSA" flavor of the Orchard protocol. + OrchardZSAFlavor, +} + /// A trait binding the common functionality between different Orchard protocol flavors. -pub trait OrchardFlavor: OrchardDomainCommon + OrchardCircuit + OrchardHash {} +pub trait OrchardFlavor: OrchardDomainCommon + OrchardCircuit + OrchardHash { + /// Flavor of the Orchard protocol. + const FLAVOR: Flavor; +} -impl OrchardFlavor for OrchardVanilla {} -impl OrchardFlavor for OrchardZSA {} +impl OrchardFlavor for OrchardVanilla { + const FLAVOR: Flavor = Flavor::OrchardVanillaFlavor; +} +impl OrchardFlavor for OrchardZSA { + const FLAVOR: Flavor = Flavor::OrchardZSAFlavor; +} From adc69955b9201576d62cb92cffb0f0af401ba119 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 9 Dec 2024 09:22:40 +0100 Subject: [PATCH 79/92] Update SIGHASH according to OrchardDomain For Vanilla transactions, we would like to use the SIGHASH defined in ZIP 244. For ZSA transactions, we would like to use the SIGHASH defined in ZIP 226. --- benches/note_decryption.rs | 2 +- src/action.rs | 4 +- src/builder.rs | 6 +- src/bundle.rs | 24 ++- src/bundle/commitments.rs | 168 +++++++++--------- src/{note_encryption.rs => domain.rs} | 4 +- .../compact_action.rs | 2 +- src/domain/orchard_domain.rs | 148 +++++++++++++++ .../orchard_domain_vanilla.rs | 34 +++- .../orchard_domain_zsa.rs | 49 ++++- .../zcash_note_encryption_domain.rs} | 0 src/lib.rs | 2 +- src/note.rs | 4 +- src/note_encryption/orchard_domain.rs | 79 -------- src/orchard_flavor.rs | 4 +- tests/builder.rs | 2 +- tests/zsa.rs | 2 +- 17 files changed, 344 insertions(+), 190 deletions(-) rename src/{note_encryption.rs => domain.rs} (92%) rename src/{note_encryption => domain}/compact_action.rs (98%) create mode 100644 src/domain/orchard_domain.rs rename src/{note_encryption => domain}/orchard_domain_vanilla.rs (87%) rename src/{note_encryption => domain}/orchard_domain_zsa.rs (82%) rename src/{note_encryption/domain.rs => domain/zcash_note_encryption_domain.rs} (100%) delete mode 100644 src/note_encryption/orchard_domain.rs diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index d17b01e41..44aefcab1 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -2,9 +2,9 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use orchard::{ builder::{Builder, BundleType}, circuit::ProvingKey, + domain::{CompactAction, OrchardDomain}, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendingKey}, note::AssetBase, - note_encryption::{CompactAction, OrchardDomain}, orchard_flavor::{OrchardVanilla, OrchardZSA}, value::NoteValue, Anchor, Bundle, diff --git a/src/action.rs b/src/action.rs index cb51e32e7..d21d2baae 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,8 +1,8 @@ use memuse::DynamicUsage; use crate::{ + domain::OrchardDomainCommon, note::{ExtractedNoteCommitment, Nullifier, Rho, TransmittedNoteCiphertext}, - note_encryption::OrchardDomainCommon, primitives::redpallas::{self, SpendAuth}, value::ValueCommitment, }; @@ -131,11 +131,11 @@ pub(crate) mod testing { use zcash_note_encryption_zsa::NoteEncryption; use crate::{ + domain::{OrchardDomain, OrchardDomainCommon}, note::{ asset_base::testing::arb_asset_base, commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier, testing::arb_note, Note, TransmittedNoteCiphertext, }, - note_encryption::{OrchardDomain, OrchardDomainCommon}, primitives::redpallas::{ self, testing::{arb_spendauth_signing_key, arb_spendauth_verification_key}, diff --git a/src/builder.rs b/src/builder.rs index c45afa1eb..e5cc965c7 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -19,12 +19,12 @@ use crate::{ address::Address, bundle::{derive_bvk, Authorization, Authorized, Bundle, Flags}, circuit::{Circuit, Instance, Proof, ProvingKey, Witnesses}, + domain::{OrchardDomain, OrchardDomainCommon}, keys::{ FullViewingKey, OutgoingViewingKey, Scope, SpendAuthorizingKey, SpendValidatingKey, SpendingKey, }, note::{AssetBase, Note, Rho, TransmittedNoteCiphertext}, - note_encryption::{OrchardDomain, OrchardDomainCommon}, orchard_flavor::{Flavor, OrchardFlavor}, primitives::redpallas::{self, Binding, SpendAuth}, tree::{Anchor, MerklePath}, @@ -542,7 +542,7 @@ impl Builder { /// Returns an error if the given Merkle path does not have the required anchor for /// the given note. /// - /// [`OrchardDomain`]: crate::note_encryption::OrchardDomain + /// [`OrchardDomain`]: crate::domain::OrchardDomain /// [`MerkleHashOrchard`]: crate::tree::MerkleHashOrchard pub fn add_spend( &mut self, @@ -1249,9 +1249,9 @@ pub mod testing { address::testing::arb_address, bundle::{Authorized, Bundle}, circuit::ProvingKey, + domain::OrchardDomainCommon, keys::{testing::arb_spending_key, FullViewingKey, SpendAuthorizingKey, SpendingKey}, note::testing::arb_note, - note_encryption::OrchardDomainCommon, orchard_flavor::OrchardFlavor, tree::{Anchor, MerkleHashOrchard, MerklePath}, value::{testing::arb_positive_note_value, NoteValue, MAX_NOTE_VALUE}, diff --git a/src/bundle.rs b/src/bundle.rs index de69c3613..5b02ea5a4 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -18,17 +18,15 @@ use crate::{ address::Address, bundle::commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, circuit::{Instance, Proof, VerifyingKey}, + domain::{OrchardDomain, OrchardDomainCommon}, keys::{IncomingViewingKey, OutgoingViewingKey, PreparedIncomingViewingKey}, note::{AssetBase, Note}, - note_encryption::{OrchardDomain, OrchardDomainCommon}, orchard_flavor::OrchardFlavor, primitives::redpallas::{self, Binding, SpendAuth}, tree::Anchor, value::{NoteValue, ValueCommitTrapdoor, ValueCommitment, ValueSum}, }; -pub(crate) use commitments::OrchardHash; - impl Action { /// Prepares the public instance for this action, for creating and verifying the /// bundle proof. @@ -207,6 +205,11 @@ pub struct Bundle { burn: Vec<(AssetBase, NoteValue)>, /// The root of the Orchard commitment tree that this bundle commits to. anchor: Anchor, + /// Block height after which this Bundle's Actions are invalid by consensus. + /// + /// For the OrchardZSA protocol, `expiry_height` is set to 0, indicating no expiry. + /// This field is reserved for future use. + expiry_height: u32, /// The authorization for this bundle. authorization: A, } @@ -247,6 +250,7 @@ impl Bundle { value_balance, burn, anchor, + expiry_height: 0, authorization, } } @@ -278,6 +282,11 @@ impl Bundle { &self.anchor } + /// Returns the expiry height for this bundle. + pub fn expiry_height(&self) -> u32 { + self.expiry_height + } + /// Returns the authorization for this bundle. /// /// In the case of a `Bundle`, this is the proof and binding signature. @@ -297,6 +306,7 @@ impl Bundle { value_balance: f(self.value_balance)?, burn: self.burn, anchor: self.anchor, + expiry_height: self.expiry_height, authorization: self.authorization, }) } @@ -315,9 +325,10 @@ impl Bundle { .map(|a| a.map(|a_auth| spend_auth(context, &authorization, a_auth))), flags: self.flags, value_balance: self.value_balance, + burn: self.burn, anchor: self.anchor, + expiry_height: self.expiry_height, authorization: step(context, authorization), - burn: self.burn, } } @@ -339,9 +350,10 @@ impl Bundle { actions: NonEmpty::from_vec(new_actions).unwrap(), flags: self.flags, value_balance: self.value_balance, + burn: self.burn, anchor: self.anchor, + expiry_height: self.expiry_height, authorization: step(context, authorization)?, - burn: self.burn, }) } @@ -592,9 +604,9 @@ pub mod testing { use super::{Action, Authorization, Authorized, Bundle, Flags}; pub use crate::action::testing::ActionArb; + use crate::domain::OrchardDomainCommon; use crate::note::asset_base::testing::arb_zsa_asset_base; use crate::note::AssetBase; - use crate::note_encryption::OrchardDomainCommon; use crate::value::testing::arb_note_value; /// Marker for an unauthorized bundle with no proofs or signatures. diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index b4931d4cc..7d09b2801 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -4,106 +4,44 @@ use blake2b_simd::{Hash as Blake2bHash, Params, State}; use crate::{ bundle::{Authorization, Authorized, Bundle}, + domain::OrchardDomainCommon, issuance::{IssueAuth, IssueBundle, Signed}, - note::AssetBase, - note_encryption::{OrchardDomainCommon, MEMO_SIZE}, - orchard_flavor::{OrchardVanilla, OrchardZSA}, - value::NoteValue, }; -const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; -const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActCHash"; -const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; -const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; +pub(crate) const ZCASH_ORCHARD_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrchardHash"; +pub(crate) const ZCASH_ORCHARD_ACTION_GROUPS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActGHash"; +pub(crate) const ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION: &[u8; 16] = + b"ZTxIdOrcActCHash"; +pub(crate) const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActMHash"; +pub(crate) const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = + b"ZTxIdOrcActNHash"; +pub(crate) const ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcBurnHash"; const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; -const ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcBurnHash"; const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdSAIssueHash"; const ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION: &[u8; 16] = b"ZTxIdIssuActHash"; const ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION: &[u8; 16] = b"ZTxIdIAcNoteHash"; const ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION: &[u8; 16] = b"ZTxAuthZSAOrHash"; -fn hasher(personal: &[u8; 16]) -> State { +pub(crate) fn hasher(personal: &[u8; 16]) -> State { Params::new().hash_length(32).personal(personal).to_state() } -/// Manages the hashing of ZSA burn-related data in transactions. -pub trait OrchardHash { - /// Incorporates the hash of burn items into the main transaction hash. - fn update_hash_with_burn(main_hasher: &mut State, burn_items: &[(AssetBase, NoteValue)]); -} - -impl OrchardHash for OrchardVanilla { - fn update_hash_with_burn(_main_hasher: &mut State, _burn_items: &[(AssetBase, NoteValue)]) {} -} - -impl OrchardHash for OrchardZSA { - fn update_hash_with_burn(main_hasher: &mut State, burn_items: &[(AssetBase, NoteValue)]) { - let mut burn_hasher = hasher(ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION); - for burn_item in burn_items { - burn_hasher.update(&burn_item.0.to_bytes()); - burn_hasher.update(&burn_item.1.to_bytes()); - } - main_hasher.update(burn_hasher.finalize().as_bytes()); - } -} - -/// Write disjoint parts of each Orchard shielded action as 3 separate hashes: -/// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized -/// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION -/// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized -/// with ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION -/// * \[(cv, rk, enc_ciphertext\[564..\], out_ciphertext)*\] personalized -/// with ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION -/// as defined in [ZIP-244: Transaction Identifier Non-Malleability][zip244] -/// -/// Then, hash these together along with (flags, value_balance_orchard, anchor_orchard), -/// and potentially the burn fields, if it is an OrchardZSA action. -/// -/// The final hash is personalized with ZCASH_ORCHARD_HASH_PERSONALIZATION. +/// Evaluate `orchard_digest` for the bundle as defined in +/// [ZIP-244: Transaction Identifier Non-Malleability][zip244] +/// for OrchardVanilla and as defined in +/// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] +/// for OrchardZSA /// /// [zip244]: https://zips.z.cash/zip-0244 -/// [zip226]: https://zips.z.cash/zip-0226 (for ZSA burn field hashing) +/// [zip226]: https://zips.z.cash/zip-0226 pub(crate) fn hash_bundle_txid_data< A: Authorization, V: Copy + Into, - D: OrchardDomainCommon + OrchardHash, + D: OrchardDomainCommon, >( bundle: &Bundle, ) -> Blake2bHash { - let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); - let mut ch = hasher(ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION); - let mut mh = hasher(ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION); - let mut nh = hasher(ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION); - - for action in bundle.actions().iter() { - ch.update(&action.nullifier().to_bytes()); - ch.update(&action.cmx().to_bytes()); - ch.update(&action.encrypted_note().epk_bytes); - ch.update(&action.encrypted_note().enc_ciphertext.as_ref()[..D::COMPACT_NOTE_SIZE]); - - mh.update( - &action.encrypted_note().enc_ciphertext.as_ref() - [D::COMPACT_NOTE_SIZE..D::COMPACT_NOTE_SIZE + MEMO_SIZE], - ); - - nh.update(&action.cv_net().to_bytes()); - nh.update(&<[u8; 32]>::from(action.rk())); - nh.update( - &action.encrypted_note().enc_ciphertext.as_ref()[D::COMPACT_NOTE_SIZE + MEMO_SIZE..], - ); - nh.update(&action.encrypted_note().out_ciphertext); - } - - h.update(ch.finalize().as_bytes()); - h.update(mh.finalize().as_bytes()); - h.update(nh.finalize().as_bytes()); - - D::update_hash_with_burn(&mut h, &bundle.burn); - - h.update(&[bundle.flags().to_byte()]); - h.update(&(*bundle.value_balance()).into().to_le_bytes()); - h.update(&bundle.anchor().to_bytes()); - h.finalize() + D::hash_bundle_txid_data(bundle) } /// Construct the commitment for the absent bundle as defined in @@ -187,3 +125,73 @@ pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake h.update(&<[u8; 64]>::from(bundle.authorization().signature())); h.finalize() } + +#[cfg(test)] +mod tests { + use crate::{ + builder::{Builder, BundleType, UnauthorizedBundle}, + bundle::commitments::hash_bundle_txid_data, + keys::{FullViewingKey, Scope, SpendingKey}, + note::AssetBase, + orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, + value::NoteValue, + Anchor, + }; + use rand::{rngs::StdRng, SeedableRng}; + + fn generate_bundle(bundle_type: BundleType) -> UnauthorizedBundle { + let rng = StdRng::seed_from_u64(5); + + let sk = SpendingKey::from_bytes([7; 32]).unwrap(); + let recipient = FullViewingKey::from(&sk).address_at(0u32, Scope::External); + + let mut builder = Builder::new(bundle_type, Anchor::from_bytes([0; 32]).unwrap()); + builder + .add_output( + None, + recipient, + NoteValue::from_raw(10), + AssetBase::native(), + None, + ) + .unwrap(); + + builder + .add_output( + None, + recipient, + NoteValue::from_raw(20), + AssetBase::native(), + None, + ) + .unwrap(); + + builder.build::(rng).unwrap().unwrap().0 + } + + /// Verify that the hash for an Orchard Vanilla bundle matches a fixed reference value + /// to ensure consistency. + #[test] + fn test_hash_bundle_txid_data_for_orchard_vanilla() { + let bundle = generate_bundle::(BundleType::DEFAULT_VANILLA); + let sighash = hash_bundle_txid_data(&bundle); + assert_eq!( + sighash.to_hex().as_str(), + // Bundle hash for Orchard (vanilla) generated using + // Zcash/Orchard commit: 23a167e3972632586dc628ddbdd69d156dfd607b + "cd6f8156a54473d411c738e781b4d601363990688a926a3335145575003bf4b8" + ); + } + + /// Verify that the hash for an OrchardZSA bundle matches a fixed reference value + /// to ensure consistency. + #[test] + fn test_hash_bundle_txid_data_for_orchard_zsa() { + let bundle = generate_bundle::(BundleType::DEFAULT_ZSA); + let sighash = hash_bundle_txid_data(&bundle); + assert_eq!( + sighash.to_hex().as_str(), + "43cfaab1ffcd8d4752e5e7479fd619c769e3ab459b6f10bbba80533608f546b0" + ); + } +} diff --git a/src/note_encryption.rs b/src/domain.rs similarity index 92% rename from src/note_encryption.rs rename to src/domain.rs index 26d293209..1632480c7 100644 --- a/src/note_encryption.rs +++ b/src/domain.rs @@ -6,12 +6,10 @@ //! organized into separate submodules. mod compact_action; -mod domain; mod orchard_domain; mod orchard_domain_vanilla; mod orchard_domain_zsa; - -pub(crate) use domain::MEMO_SIZE; +mod zcash_note_encryption_domain; pub use { compact_action::CompactAction, diff --git a/src/note_encryption/compact_action.rs b/src/domain/compact_action.rs similarity index 98% rename from src/note_encryption/compact_action.rs rename to src/domain/compact_action.rs index b1a3a6664..dcf2854a0 100644 --- a/src/note_encryption/compact_action.rs +++ b/src/domain/compact_action.rs @@ -120,9 +120,9 @@ pub mod testing { use crate::{ address::Address, + domain::zcash_note_encryption_domain::MEMO_SIZE, keys::OutgoingViewingKey, note::{AssetBase, ExtractedNoteCommitment, Note, Nullifier, RandomSeed, Rho}, - note_encryption::MEMO_SIZE, value::NoteValue, }; diff --git a/src/domain/orchard_domain.rs b/src/domain/orchard_domain.rs new file mode 100644 index 000000000..17d8a2f8c --- /dev/null +++ b/src/domain/orchard_domain.rs @@ -0,0 +1,148 @@ +//! The OrchardDomain trait represents the difference between the `OrchardVanilla` and the +//! `OrchardZSA` commitment, encryption and decryption procedures. + +use core::fmt; + +use blake2b_simd::{Hash as Blake2bHash, State}; +use zcash_note_encryption_zsa::{note_bytes::NoteBytes, AEAD_TAG_SIZE}; + +use crate::{ + action::Action, + bundle::{ + commitments::{ + hasher, ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION, + ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION, + ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION, + }, + Authorization, + }, + domain::{ + compact_action::CompactAction, + zcash_note_encryption_domain::{Memo, MEMO_SIZE}, + }, + note::{AssetBase, Rho}, + Bundle, Note, +}; + +/// Represents the Orchard protocol domain specifics required for note encryption and decryption. +pub trait OrchardDomainCommon: fmt::Debug + Clone { + /// The size of a compact note, specific to the Orchard protocol. + const COMPACT_NOTE_SIZE: usize; + + /// The size of a note plaintext, including memo and other metadata. + const NOTE_PLAINTEXT_SIZE: usize = Self::COMPACT_NOTE_SIZE + MEMO_SIZE; + + /// The size of an encrypted note ciphertext, accounting for additional AEAD tag space. + const ENC_CIPHERTEXT_SIZE: usize = Self::NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE; + + /// The raw bytes of a note plaintext. + type NotePlaintextBytes: NoteBytes; + /// The raw bytes of an encrypted note plaintext. + type NoteCiphertextBytes: NoteBytes; + /// The raw bytes of a compact note. + type CompactNotePlaintextBytes: NoteBytes; + /// The raw bytes of an encrypted compact note. + type CompactNoteCiphertextBytes: NoteBytes; + + /// Builds NotePlaintextBytes from Note and Memo. + fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes; + + /// Extracts the asset from the note plaintext. + fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option; + + /// Evaluate `orchard_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// for OrchardVanilla and as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// for OrchardZSA + /// + /// [zip244]: https://zips.z.cash/zip-0244 + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_txid_data>( + bundle: &Bundle, + ) -> Blake2bHash; + + /// Incorporates the hash of: + /// orchard_actions_compact_digest, + /// orchard_actions_memos_digest, + /// orchard_actions_noncompact_digest + /// into the hasher. + /// + /// More precisely, write disjoint parts of each Orchard shielded action as 3 separate hashes: + /// * \[(nullifier, cmx, ephemeral_key, enc_ciphertext\[..52\])*\] personalized + /// with ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION + /// * \[enc_ciphertext\[52..564\]*\] (memo ciphertexts) personalized + /// with ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION + /// * \[(cv, rk, enc_ciphertext\[564..\], out_ciphertext)*\] personalized + /// with ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION + /// as defined in [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// + /// [zip244]: https://zips.z.cash/zip-0244 + fn update_hash_with_actions>( + main_hasher: &mut State, + bundle: &Bundle, + ) { + let mut ch = hasher(ZCASH_ORCHARD_ACTIONS_COMPACT_HASH_PERSONALIZATION); + let mut mh = hasher(ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION); + let mut nh = hasher(ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION); + + for action in bundle.actions().iter() { + ch.update(&action.nullifier().to_bytes()); + ch.update(&action.cmx().to_bytes()); + ch.update(&action.encrypted_note().epk_bytes); + ch.update(&action.encrypted_note().enc_ciphertext.as_ref()[..Self::COMPACT_NOTE_SIZE]); + + mh.update( + &action.encrypted_note().enc_ciphertext.as_ref() + [Self::COMPACT_NOTE_SIZE..Self::COMPACT_NOTE_SIZE + MEMO_SIZE], + ); + + nh.update(&action.cv_net().to_bytes()); + nh.update(&<[u8; 32]>::from(action.rk())); + nh.update( + &action.encrypted_note().enc_ciphertext.as_ref() + [Self::COMPACT_NOTE_SIZE + MEMO_SIZE..], + ); + nh.update(&action.encrypted_note().out_ciphertext); + } + + main_hasher.update(ch.finalize().as_bytes()); + main_hasher.update(mh.finalize().as_bytes()); + main_hasher.update(nh.finalize().as_bytes()); + } +} + +/// Orchard-specific note encryption logic. +#[derive(Debug, Clone)] +pub struct OrchardDomain { + /// A parameter needed to generate the nullifier. + pub rho: Rho, + phantom: std::marker::PhantomData, +} + +impl OrchardDomain { + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_action(act: &Action) -> Self { + Self { + rho: act.rho(), + phantom: Default::default(), + } + } + + /// Constructs a domain that can be used to trial-decrypt this action's output note. + pub fn for_compact_action(act: &CompactAction) -> Self { + Self { + rho: act.rho(), + phantom: Default::default(), + } + } + + /// Constructs a domain from a rho. + #[cfg(test)] + pub fn for_rho(rho: Rho) -> Self { + Self { + rho, + phantom: Default::default(), + } + } +} diff --git a/src/note_encryption/orchard_domain_vanilla.rs b/src/domain/orchard_domain_vanilla.rs similarity index 87% rename from src/note_encryption/orchard_domain_vanilla.rs rename to src/domain/orchard_domain_vanilla.rs index 187e12289..1a3bea45c 100644 --- a/src/note_encryption/orchard_domain_vanilla.rs +++ b/src/domain/orchard_domain_vanilla.rs @@ -1,17 +1,24 @@ -//! This module implements the note encryption logic specific for the `OrchardVanilla` flavor. +//! This module implements the note encryption and commitment logic specific for the +//! `OrchardVanilla` flavor. +use blake2b_simd::Hash as Blake2bHash; use zcash_note_encryption_zsa::note_bytes::NoteBytesData; use crate::{ + bundle::{ + commitments::{hasher, ZCASH_ORCHARD_HASH_PERSONALIZATION}, + Authorization, + }, note::{AssetBase, Note}, orchard_flavor::OrchardVanilla, + Bundle, }; use super::{ - domain::{ + orchard_domain::OrchardDomainCommon, + zcash_note_encryption_domain::{ build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, NOTE_VERSION_BYTE_V2, }, - orchard_domain::OrchardDomainCommon, }; impl OrchardDomainCommon for OrchardVanilla { @@ -33,6 +40,23 @@ impl OrchardDomainCommon for OrchardVanilla { fn extract_asset(_plaintext: &Self::CompactNotePlaintextBytes) -> Option { Some(AssetBase::native()) } + + /// Evaluate `orchard_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// + /// [zip244]: https://zips.z.cash/zip-0244 + fn hash_bundle_txid_data>( + bundle: &Bundle, + ) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); + + Self::update_hash_with_actions(&mut h, bundle); + + h.update(&[bundle.flags().to_byte()]); + h.update(&(*bundle.value_balance()).into().to_le_bytes()); + h.update(&bundle.anchor().to_bytes()); + h.finalize() + } } #[cfg(test)] @@ -64,8 +88,10 @@ mod tests { use super::super::{ compact_action::CompactAction, - domain::{parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard}, orchard_domain::OrchardDomain, + zcash_note_encryption_domain::{ + parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard, + }, }; type OrchardDomainVanilla = OrchardDomain; diff --git a/src/note_encryption/orchard_domain_zsa.rs b/src/domain/orchard_domain_zsa.rs similarity index 82% rename from src/note_encryption/orchard_domain_zsa.rs rename to src/domain/orchard_domain_zsa.rs index 52a23bbe1..c2e685f5e 100644 --- a/src/note_encryption/orchard_domain_zsa.rs +++ b/src/domain/orchard_domain_zsa.rs @@ -1,18 +1,28 @@ -//! This module implements the note encryption logic specific for the `OrchardZSA` flavor. +//! This module implements the note encryption and commitment logic specific for the `OrchardZSA` +//! flavor. +use blake2b_simd::Hash as Blake2bHash; use zcash_note_encryption_zsa::note_bytes::NoteBytesData; use crate::{ + bundle::{ + commitments::{ + hasher, ZCASH_ORCHARD_ACTION_GROUPS_HASH_PERSONALIZATION, + ZCASH_ORCHARD_HASH_PERSONALIZATION, ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION, + }, + Authorization, + }, note::{AssetBase, Note}, orchard_flavor::OrchardZSA, + Bundle, }; use super::{ - domain::{ + orchard_domain::OrchardDomainCommon, + zcash_note_encryption_domain::{ build_base_note_plaintext_bytes, Memo, COMPACT_NOTE_SIZE_VANILLA, COMPACT_NOTE_SIZE_ZSA, NOTE_VERSION_BYTE_V3, }, - orchard_domain::OrchardDomainCommon, }; impl OrchardDomainCommon for OrchardZSA { @@ -40,6 +50,35 @@ impl OrchardDomainCommon for OrchardZSA { AssetBase::from_bytes(bytes).into() } + + /// Evaluate `orchard_digest` for the bundle as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_txid_data>( + bundle: &Bundle, + ) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_HASH_PERSONALIZATION); + let mut agh = hasher(ZCASH_ORCHARD_ACTION_GROUPS_HASH_PERSONALIZATION); + + Self::update_hash_with_actions(&mut agh, bundle); + + agh.update(&[bundle.flags().to_byte()]); + agh.update(&bundle.anchor().to_bytes()); + agh.update(&bundle.expiry_height().to_le_bytes()); + + h.update(agh.finalize().as_bytes()); + + let mut burn_hasher = hasher(ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION); + for burn_item in bundle.burn() { + burn_hasher.update(&burn_item.0.to_bytes()); + burn_hasher.update(&burn_item.1.to_bytes()); + } + h.update(burn_hasher.finalize().as_bytes()); + + h.update(&(*bundle.value_balance()).into().to_le_bytes()); + h.finalize() + } } #[cfg(test)] @@ -71,8 +110,10 @@ mod tests { use super::super::{ compact_action::CompactAction, - domain::{parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard}, orchard_domain::OrchardDomain, + zcash_note_encryption_domain::{ + parse_note_plaintext_without_memo, parse_note_version, prf_ock_orchard, + }, }; type OrchardDomainZSA = OrchardDomain; diff --git a/src/note_encryption/domain.rs b/src/domain/zcash_note_encryption_domain.rs similarity index 100% rename from src/note_encryption/domain.rs rename to src/domain/zcash_note_encryption_domain.rs diff --git a/src/lib.rs b/src/lib.rs index 96a3c3a2d..544ba22eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ pub mod keys; pub mod note; pub mod supply_info; -pub mod note_encryption; +pub mod domain; pub mod orchard_flavor; diff --git a/src/note.rs b/src/note.rs index 77cd1b2b8..42b55552f 100644 --- a/src/note.rs +++ b/src/note.rs @@ -9,8 +9,8 @@ use rand::RngCore; use subtle::{Choice, ConditionallySelectable, CtOption}; use crate::{ + domain::OrchardDomainCommon, keys::{EphemeralSecretKey, FullViewingKey, Scope, SpendingKey}, - note_encryption::OrchardDomainCommon, spec::{to_base, to_scalar, NonZeroPallasScalar, PrfExpand}, value::NoteValue, Address, @@ -37,7 +37,7 @@ impl Rho { /// value otherwise. /// /// [`Action::rho`]: crate::action::Action::rho - /// [`CompactAction::rho`]: crate::note_encryption::CompactAction::rho + /// [`CompactAction::rho`]: crate::domain::CompactAction::rho pub fn from_bytes(bytes: &[u8; 32]) -> CtOption { pallas::Base::from_repr(*bytes).map(Rho) } diff --git a/src/note_encryption/orchard_domain.rs b/src/note_encryption/orchard_domain.rs deleted file mode 100644 index e56f15cd1..000000000 --- a/src/note_encryption/orchard_domain.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! The OrchardDomain trait represents the difference between the `OrchardVanilla` and the `OrchardZSA` -//! encryption and decryption procedures. - -use core::fmt; - -use zcash_note_encryption_zsa::{note_bytes::NoteBytes, AEAD_TAG_SIZE}; - -use crate::{ - action::Action, - note::{AssetBase, Rho}, - Note, -}; - -use super::{ - compact_action::CompactAction, - domain::{Memo, MEMO_SIZE}, -}; - -/// Represents the Orchard protocol domain specifics required for note encryption and decryption. -pub trait OrchardDomainCommon: fmt::Debug + Clone { - /// The size of a compact note, specific to the Orchard protocol. - const COMPACT_NOTE_SIZE: usize; - - /// The size of a note plaintext, including memo and other metadata. - const NOTE_PLAINTEXT_SIZE: usize = Self::COMPACT_NOTE_SIZE + MEMO_SIZE; - - /// The size of an encrypted note ciphertext, accounting for additional AEAD tag space. - const ENC_CIPHERTEXT_SIZE: usize = Self::NOTE_PLAINTEXT_SIZE + AEAD_TAG_SIZE; - - /// The raw bytes of a note plaintext. - type NotePlaintextBytes: NoteBytes; - /// The raw bytes of an encrypted note plaintext. - type NoteCiphertextBytes: NoteBytes; - /// The raw bytes of a compact note. - type CompactNotePlaintextBytes: NoteBytes; - /// The raw bytes of an encrypted compact note. - type CompactNoteCiphertextBytes: NoteBytes; - - /// Builds NotePlaintextBytes from Note and Memo. - fn build_note_plaintext_bytes(note: &Note, memo: &Memo) -> Self::NotePlaintextBytes; - - /// Extracts the asset from the note plaintext. - fn extract_asset(plaintext: &Self::CompactNotePlaintextBytes) -> Option; -} - -/// Orchard-specific note encryption logic. -#[derive(Debug, Clone)] -pub struct OrchardDomain { - /// A parameter needed to generate the nullifier. - pub rho: Rho, - phantom: std::marker::PhantomData, -} - -impl OrchardDomain { - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_action(act: &Action) -> Self { - Self { - rho: act.rho(), - phantom: Default::default(), - } - } - - /// Constructs a domain that can be used to trial-decrypt this action's output note. - pub fn for_compact_action(act: &CompactAction) -> Self { - Self { - rho: act.rho(), - phantom: Default::default(), - } - } - - /// Constructs a domain from a rho. - #[cfg(test)] - pub fn for_rho(rho: Rho) -> Self { - Self { - rho, - phantom: Default::default(), - } - } -} diff --git a/src/orchard_flavor.rs b/src/orchard_flavor.rs index 7ec0ffdc9..a9cc257ae 100644 --- a/src/orchard_flavor.rs +++ b/src/orchard_flavor.rs @@ -1,6 +1,6 @@ //! Defines types and traits for the variations ("flavors") of the Orchard protocol (Vanilla and ZSA). -use crate::{bundle::OrchardHash, circuit::OrchardCircuit, note_encryption::OrchardDomainCommon}; +use crate::{circuit::OrchardCircuit, domain::OrchardDomainCommon}; /// Represents the "Vanilla" variation ("flavor") of the Orchard protocol. #[derive(Debug, Clone, Default)] @@ -22,7 +22,7 @@ pub enum Flavor { } /// A trait binding the common functionality between different Orchard protocol flavors. -pub trait OrchardFlavor: OrchardDomainCommon + OrchardCircuit + OrchardHash { +pub trait OrchardFlavor: OrchardDomainCommon + OrchardCircuit { /// Flavor of the Orchard protocol. const FLAVOR: Flavor; } diff --git a/tests/builder.rs b/tests/builder.rs index d1e50de64..d5f2fa83f 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -4,9 +4,9 @@ use orchard::{ builder::{Builder, BundleType}, bundle::{Authorized, Flags}, circuit::{ProvingKey, VerifyingKey}, + domain::OrchardDomain, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, note::{AssetBase, ExtractedNoteCommitment}, - note_encryption::OrchardDomain, orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, tree::{MerkleHashOrchard, MerklePath}, value::NoteValue, diff --git a/tests/zsa.rs b/tests/zsa.rs index befc65e91..25d1673e7 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -12,8 +12,8 @@ use orchard::tree::{MerkleHashOrchard, MerklePath}; use orchard::{ builder::{Builder, BundleType}, circuit::{ProvingKey, VerifyingKey}, + domain::OrchardDomain, keys::{FullViewingKey, PreparedIncomingViewingKey, Scope, SpendAuthorizingKey, SpendingKey}, - note_encryption::OrchardDomain, orchard_flavor::OrchardZSA, value::NoteValue, Address, Anchor, Bundle, Note, From 97cf5a30eb18a3e20cec1eee34cd10113ae4787b Mon Sep 17 00:00:00 2001 From: Alexey <2365507+alexeykoren@users.noreply.github.com> Date: Thu, 12 Dec 2024 20:39:23 +0100 Subject: [PATCH 80/92] Add Clone trait to auth-related structures (#125) Add Clone trait to auth-related structures --- src/builder.rs | 4 ++-- src/bundle.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index e5cc965c7..3c2830bb4 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -908,7 +908,7 @@ pub fn bundle, FL: OrchardFlavor>( /// Marker trait representing bundle signatures in the process of being created. pub trait InProgressSignatures: fmt::Debug { /// The authorization type of an Orchard action in the process of being authorized. - type SpendAuth: fmt::Debug; + type SpendAuth: fmt::Debug + Clone; } /// Marker for a bundle in the process of being built. @@ -1053,7 +1053,7 @@ impl InProgressSignatures for PartiallyAuthorized { /// A heisen[`Signature`] for a particular [`Action`]. /// /// [`Signature`]: redpallas::Signature -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum MaybeSigned { /// The information needed to sign this [`Action`]. SigningMetadata(SigningParts), diff --git a/src/bundle.rs b/src/bundle.rs index 5b02ea5a4..90e90bbdb 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -187,7 +187,7 @@ impl Flags { /// Defines the authorization type of an Orchard bundle. pub trait Authorization: fmt::Debug { /// The authorization type of an Orchard action. - type SpendAuth: fmt::Debug; + type SpendAuth: fmt::Debug + Clone; } /// A bundle of actions to be applied to the ledger. From 8b89888ab98b807ecc50fb888c6b8640d31c4a42 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Mon, 16 Dec 2024 13:25:54 +0100 Subject: [PATCH 81/92] Unify unique AssetBase concept in IssueAction Update get_actions_by_asset/desc to return an Option<&IssueAction> instead of a Vec<&IssueAction> Rename get_actions_by_asset/desc into get_action_by_asset/desc --- src/issuance.rs | 66 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/src/issuance.rs b/src/issuance.rs index 0b1cf568d..1d3f6c2cd 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -220,20 +220,50 @@ impl IssueBundle { &self.authorization } - /// Find the actions corresponding to the `asset_desc` for a given `IssueBundle`. - pub fn get_actions_by_desc(&self, asset_desc: &[u8]) -> Vec<&IssueAction> { - self.actions + /// Find the action corresponding to the `asset_desc` for a given `IssueBundle`. + /// + /// # Returns + /// + /// If a single matching action is found, it is returned as `Some(&IssueAction)`. + /// If no action matches the given `asset_desc`, it returns `None`. + /// + /// # Panics + /// + /// Panics if multiple matching actions are found. + pub fn get_action_by_desc(&self, asset_desc: &[u8]) -> Option<&IssueAction> { + let issue_actions: Vec<&IssueAction> = self + .actions .iter() .filter(|a| a.asset_desc.eq(asset_desc)) - .collect() + .collect(); + match issue_actions.len() { + 0 => None, + 1 => Some(issue_actions[0]), + _ => panic!("Multiple IssueActions with the same asset_desc"), + } } /// Find the actions corresponding to an Asset Base `asset` for a given `IssueBundle`. - pub fn get_actions_by_asset(&self, asset: &AssetBase) -> Vec<&IssueAction> { - self.actions + /// + /// # Returns + /// + /// If a single matching action is found, it is returned as `Some(&IssueAction)`. + /// If no action matches the given Asset Base `asset`, it returns `None`. + /// + /// # Panics + /// + /// Panics if multiple matching actions are found. + pub fn get_action_by_asset(&self, asset: &AssetBase) -> Option<&IssueAction> { + let issue_actions: Vec<&IssueAction> = self + .actions .iter() .filter(|a| AssetBase::derive(&self.ik, &a.asset_desc).eq(asset)) - .collect() + .collect(); + match issue_actions.len() { + 0 => None, + 1 => Some(issue_actions[0]), + _ => panic!("Multiple IssueActions with the same AssetBase"), + } } /// Computes a commitment to the effects of this bundle, suitable for inclusion within @@ -847,9 +877,7 @@ mod tests { let actions = bundle.actions(); assert_eq!(actions.len(), 2); - let actions_vec = bundle.get_actions_by_asset(&asset); - assert_eq!(actions_vec.len(), 1); - let action = actions_vec[0]; + let action = bundle.get_action_by_asset(&asset).unwrap(); assert_eq!(action.notes.len(), 2); assert_eq!(action.notes.first().unwrap().value().inner(), 5); assert_eq!(action.notes.first().unwrap().asset(), asset); @@ -859,9 +887,7 @@ mod tests { assert_eq!(action.notes.get(1).unwrap().asset(), asset); assert_eq!(action.notes.get(1).unwrap().recipient(), recipient); - let action2_vec = bundle.get_actions_by_desc(str2.as_bytes()); - assert_eq!(action2_vec.len(), 1); - let action2 = action2_vec[0]; + let action2 = bundle.get_action_by_desc(str2.as_bytes()).unwrap(); assert_eq!(action2.notes.len(), 1); assert_eq!(action2.notes().first().unwrap().value().inner(), 15); assert_eq!(action2.notes().first().unwrap().asset(), third_asset); @@ -1405,22 +1431,16 @@ mod tests { .unwrap(); // Checks for the case of UTF-8 encoded asset description. - let actions_vec = bundle.get_actions_by_asset(&asset_base_1); - assert_eq!(actions_vec.len(), 1); - - let action = actions_vec[0]; + let action = bundle.get_action_by_asset(&asset_base_1).unwrap(); assert_eq!(action.asset_desc(), &asset_desc_1); assert_eq!(action.notes.first().unwrap().value().inner(), 5); - assert_eq!(bundle.get_actions_by_desc(&asset_desc_1), actions_vec); + assert_eq!(bundle.get_action_by_desc(&asset_desc_1).unwrap(), action); // Checks for the case on non-UTF-8 encoded asset description. - let action2_vec = bundle.get_actions_by_asset(&asset_base_2); - assert_eq!(action2_vec.len(), 1); - - let action2 = action2_vec[0]; + let action2 = bundle.get_action_by_asset(&asset_base_2).unwrap(); assert_eq!(action2.asset_desc(), &asset_desc_2); assert_eq!(action2.notes.first().unwrap().value().inner(), 10); - assert_eq!(bundle.get_actions_by_desc(&asset_desc_2), action2_vec); + assert_eq!(bundle.get_action_by_desc(&asset_desc_2).unwrap(), action2); } } From fe150764065d224884fb1783f836ebc5a758ba3f Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Tue, 17 Dec 2024 09:48:06 +0100 Subject: [PATCH 82/92] Add a reference note for each first issuance When an asset is issue for the first time, we create a reference note which is a note with a value equal to zero and a recipient address equal to the reference recipient address. --- src/constants.rs | 1 + src/constants/reference_keys.rs | 54 +++++++++++ src/issuance.rs | 157 +++++++++++++++++++++++++++----- src/lib.rs | 8 +- tests/zsa.rs | 37 ++++++-- 5 files changed, 221 insertions(+), 36 deletions(-) create mode 100644 src/constants/reference_keys.rs diff --git a/src/constants.rs b/src/constants.rs index b64d114f5..d1cadc4bf 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,5 +1,6 @@ //! Constants used in the Orchard protocol. pub mod fixed_bases; +pub mod reference_keys; pub mod sinsemilla; pub mod util; diff --git a/src/constants/reference_keys.rs b/src/constants/reference_keys.rs new file mode 100644 index 000000000..535528000 --- /dev/null +++ b/src/constants/reference_keys.rs @@ -0,0 +1,54 @@ +//! Orchard reference keys, including the spending key and recipient address, used for reference notes. +//! +//! The reference SpendingKey is a placeholder key with all bytes set to zero. +//! Using this SpendingKey, we derive the FullViewingKey, and the recipient address. +//! To avoid repeating the derivation process whenever the recipient address is required, we store +//! its raw encoding. + +use crate::{ + address::Address, + keys::{FullViewingKey, SpendingKey}, +}; + +/// Raw bytes representation of the reference recipient address. +pub const RAW_REFERENCE_RECIPIENT: [u8; 43] = [ + 204, 54, 96, 25, 89, 33, 59, 107, 12, 219, 150, 167, 92, 23, 195, 166, 104, 169, 127, 13, 106, + 140, 92, 225, 100, 165, 24, 234, 155, 169, 165, 14, 167, 81, 145, 253, 134, 27, 15, 241, 14, + 98, 176, +]; + +/// Reference keys (spending key and recipient address) are used for reference notes. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct ReferenceKeys; + +impl ReferenceKeys { + /// Returns the spending key for reference notes. + pub fn sk() -> SpendingKey { + SpendingKey::from_bytes([0; 32]).unwrap() + } + + /// Returns the recipient address for reference notes. + pub fn recipient() -> Address { + Address::from_raw_address_bytes(&RAW_REFERENCE_RECIPIENT).unwrap() + } + + /// Returns the full viewing key for reference notes. + pub fn fvk() -> FullViewingKey { + FullViewingKey::from(&Self::sk()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::keys::{FullViewingKey, Scope}; + + #[test] + fn recipient() { + let sk = SpendingKey::from_bytes([0; 32]).unwrap(); + let fvk = FullViewingKey::from(&sk); + let recipient = fvk.address_at(0u32, Scope::External); + + assert_eq!(recipient, ReferenceKeys::recipient()); + } +} diff --git a/src/issuance.rs b/src/issuance.rs index 1d3f6c2cd..d2d2b2aaf 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -4,10 +4,11 @@ use group::Group; use k256::schnorr; use nonempty::NonEmpty; use rand::RngCore; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::fmt; use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; +use crate::constants::reference_keys::ReferenceKeys; use crate::issuance::Error::{ AssetBaseCannotBeIdentityPoint, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueActionWithoutNoteNotFinalized, IssueBundleIkMismatchAssetBase, @@ -308,6 +309,9 @@ impl IssueBundle { /// issue_info values and with `finalize` set to false. In this created note, rho will be /// randomly sampled, similar to dummy note generation. /// + /// If `first_issuance` is true, the `IssueBundle` will contain a reference note for the asset + /// defined by (`asset_desc`, `ik`). + /// /// # Errors /// /// This function may return an error in any of the following cases: @@ -317,6 +321,7 @@ impl IssueBundle { ik: IssuanceValidatingKey, asset_desc: Vec, issue_info: Option, + first_issuance: bool, mut rng: impl RngCore, ) -> Result<(IssueBundle, AssetBase), Error> { if !is_asset_desc_of_valid_size(&asset_desc) { @@ -325,10 +330,15 @@ impl IssueBundle { let asset = AssetBase::derive(&ik, &asset_desc); + let mut notes = vec![]; + if first_issuance { + notes.push(create_reference_note(asset, &mut rng)); + }; + let action = match issue_info { None => IssueAction { asset_desc, - notes: vec![], + notes, finalize: true, }, Some(issue_info) => { @@ -340,9 +350,11 @@ impl IssueBundle { &mut rng, ); + notes.push(note); + IssueAction { asset_desc, - notes: vec![note], + notes, finalize: false, } } @@ -361,6 +373,8 @@ impl IssueBundle { /// Add a new note to the `IssueBundle`. /// /// Rho will be randomly sampled, similar to dummy note generation. + /// If `first_issuance` is true, we will also add a reference note for the asset defined by + /// (`asset_desc`, `ik`). /// /// # Errors /// @@ -372,6 +386,7 @@ impl IssueBundle { asset_desc: &[u8], recipient: Address, value: NoteValue, + first_issuance: bool, mut rng: impl RngCore, ) -> Result { if !is_asset_desc_of_valid_size(asset_desc) { @@ -388,6 +403,12 @@ impl IssueBundle { &mut rng, ); + let notes = if first_issuance { + vec![create_reference_note(asset, &mut rng), note] + } else { + vec![note] + }; + let action = self .actions .iter_mut() @@ -396,13 +417,13 @@ impl IssueBundle { match action { Some(action) => { // Append to an existing IssueAction. - action.notes.push(note); + action.notes.extend(notes); } None => { // Insert a new IssueAction. self.actions.push(IssueAction { asset_desc: Vec::from(asset_desc), - notes: vec![note], + notes, finalize: false, }); } @@ -447,6 +468,33 @@ impl IssueBundle { } } +impl IssueBundle { + /// Returns the reference notes for the `IssueBundle`. + pub fn get_reference_notes(self) -> HashMap { + let mut reference_notes = HashMap::new(); + self.actions.iter().for_each(|action| { + action.notes.iter().for_each(|note| { + if (note.recipient() == ReferenceKeys::recipient()) + && (note.value() == NoteValue::zero()) + { + reference_notes.insert(note.asset(), *note); + } + }) + }); + reference_notes + } +} + +fn create_reference_note(asset: AssetBase, mut rng: impl RngCore) -> Note { + Note::new( + ReferenceKeys::recipient(), + NoteValue::zero(), + asset, + Rho::from_nf_old(Nullifier::dummy(&mut rng)), + &mut rng, + ) +} + impl IssueBundle { /// Sign the `IssueBundle`. /// The call makes sure that the provided `isk` matches the `ik` and the derived `asset` for each note in the bundle. @@ -637,6 +685,7 @@ impl fmt::Display for Error { #[cfg(test)] mod tests { use super::{AssetSupply, IssueBundle, IssueInfo}; + use crate::constants::reference_keys::ReferenceKeys; use crate::issuance::Error::{ AssetBaseCannotBeIdentityPoint, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, @@ -656,6 +705,18 @@ mod tests { use rand::RngCore; use std::collections::HashSet; + /// Validation for reference note + /// + /// The following checks are performed: + /// - the note value of the reference note is equal to 0 + /// - the asset of the reference note is equal to the provided asset + /// - the recipient of the reference note is equal to the reference recipient + fn verify_reference_note(note: &Note, asset: AssetBase) { + assert_eq!(note.value(), NoteValue::from_raw(0)); + assert_eq!(note.asset(), asset); + assert_eq!(note.recipient(), ReferenceKeys::recipient()); + } + fn setup_params() -> ( OsRng, IssuanceAuthorizingKey, @@ -833,6 +894,7 @@ mod tests { recipient, value: NoteValue::unsplittable() }), + true, rng, ) .unwrap_err(), @@ -847,6 +909,7 @@ mod tests { recipient, value: NoteValue::unsplittable() }), + true, rng, ) .unwrap_err(), @@ -854,23 +917,36 @@ mod tests { ); let (mut bundle, asset) = IssueBundle::new( - ik, + ik.clone(), str.clone().into_bytes(), Some(IssueInfo { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); let another_asset = bundle - .add_recipient(&str.into_bytes(), recipient, NoteValue::from_raw(10), rng) + .add_recipient( + &str.into_bytes(), + recipient, + NoteValue::from_raw(10), + false, + rng, + ) .unwrap(); assert_eq!(asset, another_asset); let third_asset = bundle - .add_recipient(str2.as_bytes(), recipient, NoteValue::from_raw(15), rng) + .add_recipient( + str2.as_bytes(), + recipient, + NoteValue::from_raw(15), + true, + rng, + ) .unwrap(); assert_ne!(asset, third_asset); @@ -878,19 +954,31 @@ mod tests { assert_eq!(actions.len(), 2); let action = bundle.get_action_by_asset(&asset).unwrap(); - assert_eq!(action.notes.len(), 2); - assert_eq!(action.notes.first().unwrap().value().inner(), 5); - assert_eq!(action.notes.first().unwrap().asset(), asset); - assert_eq!(action.notes.first().unwrap().recipient(), recipient); - - assert_eq!(action.notes.get(1).unwrap().value().inner(), 10); - assert_eq!(action.notes.get(1).unwrap().asset(), asset); - assert_eq!(action.notes.get(1).unwrap().recipient(), recipient); + assert_eq!(action.notes.len(), 3); + let reference_note = action.notes.get(0).unwrap(); + verify_reference_note(reference_note, asset); + let first_note = action.notes.get(1).unwrap(); + assert_eq!(first_note.value().inner(), 5); + assert_eq!(first_note.asset(), asset); + assert_eq!(first_note.recipient(), recipient); + + let second_note = action.notes.get(2).unwrap(); + assert_eq!(second_note.value().inner(), 10); + assert_eq!(second_note.asset(), asset); + assert_eq!(second_note.recipient(), recipient); let action2 = bundle.get_action_by_desc(str2.as_bytes()).unwrap(); - assert_eq!(action2.notes.len(), 1); - assert_eq!(action2.notes().first().unwrap().value().inner(), 15); - assert_eq!(action2.notes().first().unwrap().asset(), third_asset); + assert_eq!(action2.notes.len(), 2); + let reference_note = action2.notes.get(0).unwrap(); + verify_reference_note(reference_note, AssetBase::derive(&ik, str2.as_bytes())); + let first_note = action2.notes().get(1).unwrap(); + assert_eq!(first_note.value().inner(), 15); + assert_eq!(first_note.asset(), third_asset); + + let reference_notes = bundle.get_reference_notes(); + assert_eq!(reference_notes.len(), 2); + verify_reference_note(reference_notes.get(&asset).unwrap(), asset); + verify_reference_note(reference_notes.get(&third_asset).unwrap(), third_asset); } #[test] @@ -904,6 +992,7 @@ mod tests { recipient, value: NoteValue::from_raw(u64::MIN), }), + true, rng, ) .expect("Should properly add recipient"); @@ -936,6 +1025,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -955,6 +1045,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -976,6 +1067,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1002,6 +1094,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1035,6 +1128,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1060,6 +1154,7 @@ mod tests { recipient, value: NoteValue::from_raw(7), }), + true, rng, ) .unwrap(); @@ -1096,24 +1191,25 @@ mod tests { recipient, value: NoteValue::from_raw(7), }), + true, rng, ) .unwrap(); bundle - .add_recipient(&asset1_desc, recipient, NoteValue::from_raw(8), rng) + .add_recipient(&asset1_desc, recipient, NoteValue::from_raw(8), false, rng) .unwrap(); bundle.finalize_action(&asset1_desc).unwrap(); bundle - .add_recipient(&asset2_desc, recipient, NoteValue::from_raw(10), rng) + .add_recipient(&asset2_desc, recipient, NoteValue::from_raw(10), true, rng) .unwrap(); bundle.finalize_action(&asset2_desc).unwrap(); bundle - .add_recipient(&asset3_desc, recipient, NoteValue::from_raw(5), rng) + .add_recipient(&asset3_desc, recipient, NoteValue::from_raw(5), true, rng) .unwrap(); let signed = bundle.prepare(sighash).sign(&isk).unwrap(); @@ -1156,6 +1252,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1191,6 +1288,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1221,6 +1319,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1246,6 +1345,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1284,6 +1384,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1330,6 +1431,7 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); @@ -1422,24 +1524,29 @@ mod tests { recipient, value: NoteValue::from_raw(5), }), + true, rng, ) .unwrap(); let asset_base_2 = bundle - .add_recipient(&asset_desc_2, recipient, NoteValue::from_raw(10), rng) + .add_recipient(&asset_desc_2, recipient, NoteValue::from_raw(10), true, rng) .unwrap(); // Checks for the case of UTF-8 encoded asset description. let action = bundle.get_action_by_asset(&asset_base_1).unwrap(); assert_eq!(action.asset_desc(), &asset_desc_1); - assert_eq!(action.notes.first().unwrap().value().inner(), 5); + let reference_note = action.notes.get(0).unwrap(); + verify_reference_note(reference_note, asset_base_1); + assert_eq!(action.notes.get(1).unwrap().value().inner(), 5); assert_eq!(bundle.get_action_by_desc(&asset_desc_1).unwrap(), action); // Checks for the case on non-UTF-8 encoded asset description. let action2 = bundle.get_action_by_asset(&asset_base_2).unwrap(); assert_eq!(action2.asset_desc(), &asset_desc_2); - assert_eq!(action2.notes.first().unwrap().value().inner(), 10); + let reference_note = action2.notes.get(0).unwrap(); + verify_reference_note(reference_note, asset_base_2); + assert_eq!(action2.notes.get(1).unwrap().value().inner(), 10); assert_eq!(bundle.get_action_by_desc(&asset_desc_2).unwrap(), action2); } } diff --git a/src/lib.rs b/src/lib.rs index 544ba22eb..543c91825 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,17 +22,14 @@ pub mod builder; pub mod bundle; pub mod circuit; mod constants; +pub mod domain; pub mod issuance; pub mod keys; pub mod note; -pub mod supply_info; - -pub mod domain; - pub mod orchard_flavor; - pub mod primitives; mod spec; +pub mod supply_info; pub mod tree; pub mod value; pub mod zip32; @@ -44,6 +41,7 @@ pub use action::Action; pub use address::Address; pub use bundle::Bundle; pub use circuit::Proof; +pub use constants::reference_keys::ReferenceKeys; pub use constants::MERKLE_DEPTH_ORCHARD as NOTE_COMMITMENT_TREE_DEPTH; pub use note::Note; pub use tree::Anchor; diff --git a/tests/zsa.rs b/tests/zsa.rs index 25d1673e7..3a1e04cdb 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -136,7 +136,7 @@ pub fn build_merkle_path_with_two_leaves( (merkle_path1, merkle_path2, anchor) } -fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note) { +fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note, Note) { let mut rng = OsRng; // Create a issuance bundle let unauthorized_asset = IssueBundle::new( @@ -146,6 +146,7 @@ fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note) { recipient: keys.recipient, value: NoteValue::from_raw(40), }), + true, &mut rng, ); @@ -158,6 +159,7 @@ fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note) { asset_descr, keys.recipient, NoteValue::from_raw(2), + false, &mut rng, ) .is_ok()); @@ -166,8 +168,14 @@ fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note) { // Take notes from first action let notes = issue_bundle.get_all_notes(); - let note1 = notes[0]; - let note2 = notes[1]; + let reference_note = notes[0]; + let note1 = notes[1]; + let note2 = notes[2]; + + verify_reference_note( + reference_note, + AssetBase::derive(&keys.ik().clone(), asset_descr), + ); assert!(verify_issue_bundle( &issue_bundle, @@ -176,7 +184,7 @@ fn issue_zsa_notes(asset_descr: &[u8], keys: &Keychain) -> (Note, Note) { ) .is_ok()); - (*note1, *note2) + (*reference_note, *note1, *note2) } fn create_native_note(keys: &Keychain) -> Note { @@ -284,6 +292,21 @@ fn verify_unique_spent_nullifiers(bundle: &Bundle) }) } +/// Validation for reference note +/// +/// The following checks are performed: +/// - the note value of the reference note is equal to 0 +/// - the asset of the reference note is equal to the provided asset +/// - the recipient of the reference note is equal to the reference recipient +fn verify_reference_note(note: &Note, asset: AssetBase) { + let reference_sk = SpendingKey::from_bytes([0; 32]).unwrap(); + let reference_fvk = FullViewingKey::from(&reference_sk); + let reference_recipient = reference_fvk.address_at(0u32, Scope::External); + assert_eq!(note.value(), NoteValue::from_raw(0)); + assert_eq!(note.asset(), asset); + assert_eq!(note.recipient(), reference_recipient); +} + /// Issue several ZSA and native notes and spend them in different combinations, e.g. split and join #[test] fn zsa_issue_and_transfer() { @@ -293,7 +316,8 @@ fn zsa_issue_and_transfer() { let asset_descr = b"zsa_asset".to_vec(); // Prepare ZSA - let (zsa_note_1, zsa_note_2) = issue_zsa_notes(&asset_descr, &keys); + let (reference_note, zsa_note_1, zsa_note_2) = issue_zsa_notes(&asset_descr, &keys); + verify_reference_note(&reference_note, zsa_note_1.asset()); let (merkle_path1, merkle_path2, anchor) = build_merkle_path_with_two_leaves(&zsa_note_1, &zsa_note_2); @@ -446,7 +470,8 @@ fn zsa_issue_and_transfer() { .unwrap(); // 7. Spend ZSA notes of different asset types - let (zsa_note_t7, _) = issue_zsa_notes(b"zsa_asset2", &keys); + let (reference_note, zsa_note_t7, _) = issue_zsa_notes(b"zsa_asset2", &keys); + verify_reference_note(&reference_note, zsa_note_t7.asset()); let (merkle_path_t7_1, merkle_path_t7_2, anchor_t7) = build_merkle_path_with_two_leaves(&zsa_note_t7, &zsa_note_2); let zsa_spend_t7_1: TestSpendInfo = TestSpendInfo { From 9eb97f02906cdc99ed423f9d345aa73d8ad5473f Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Fri, 20 Dec 2024 17:43:45 +0100 Subject: [PATCH 83/92] Simplify bundle build function return type (#129) Previously, the bundle function returns a `Result>, BuildError>` but the `Option` was never `None` because the actions vector could not be empty. Now, the bundle function returns a `Result, BuildError>`. --- benches/circuit.rs | 2 +- benches/note_decryption.rs | 2 +- src/builder.rs | 41 ++++++++++++++++++-------------------- src/bundle/commitments.rs | 2 +- tests/builder.rs | 4 ++-- tests/zsa.rs | 4 ++-- 6 files changed, 26 insertions(+), 29 deletions(-) diff --git a/benches/circuit.rs b/benches/circuit.rs index 668965c4d..029f80b55 100644 --- a/benches/circuit.rs +++ b/benches/circuit.rs @@ -46,7 +46,7 @@ fn criterion_benchmark(c: &mut Criterion) { ) .unwrap(); } - let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().0; let instances: Vec<_> = bundle .actions() diff --git a/benches/note_decryption.rs b/benches/note_decryption.rs index 44aefcab1..5bf072c50 100644 --- a/benches/note_decryption.rs +++ b/benches/note_decryption.rs @@ -74,7 +74,7 @@ fn bench_note_decryption(c: &mut Criterion) { None, ) .unwrap(); - let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().unwrap().0; + let bundle: Bundle<_, i64, FL> = builder.build(rng).unwrap().0; bundle .create_proof(&pk, rng) .unwrap() diff --git a/src/builder.rs b/src/builder.rs index 3c2830bb4..14df505e9 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -654,7 +654,7 @@ impl Builder { pub fn build, FL: OrchardFlavor>( self, rng: impl RngCore, - ) -> Result>, BuildError> { + ) -> Result, BuildError> { bundle( rng, self.anchor, @@ -745,7 +745,7 @@ pub fn bundle, FL: OrchardFlavor>( spends: Vec, outputs: Vec, burn: HashMap, -) -> Result>, BuildError> { +) -> Result, BuildError> { let flags = bundle_type.flags(); let num_requested_spends = spends.len(); @@ -884,25 +884,24 @@ pub fn bundle, FL: OrchardFlavor>( let bvk = derive_bvk(&actions, native_value_balance, burn.iter().cloned()); assert_eq!(redpallas::VerificationKey::from(&bsk), bvk); - Ok(NonEmpty::from_vec(actions).map(|actions| { - ( - Bundle::from_parts( - actions, - flags, - result_value_balance, - burn, - anchor, - InProgress { - proof: Unproven { - witnesses, - circuit_flavor: FL::FLAVOR, - }, - sigs: Unauthorized { bsk }, + Ok(( + Bundle::from_parts( + // `actions` is never empty. It contains at least MIN_ACTIONS=2 actions. + NonEmpty::from_vec(actions).unwrap(), + flags, + result_value_balance, + burn, + anchor, + InProgress { + proof: Unproven { + witnesses, + circuit_flavor: FL::FLAVOR, }, - ), - bundle_meta, - ) - })) + sigs: Unauthorized { bsk }, + }, + ), + bundle_meta, + )) } /// Marker trait representing bundle signatures in the process of being created. @@ -1302,7 +1301,6 @@ pub mod testing { builder .build(&mut self.rng) .unwrap() - .unwrap() .0 .create_proof(&pk, &mut self.rng) .unwrap() @@ -1434,7 +1432,6 @@ mod tests { let bundle: Bundle = builder .build(&mut rng) .unwrap() - .unwrap() .0 .create_proof(&pk, &mut rng) .unwrap() diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 7d09b2801..a3d28d6c8 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -166,7 +166,7 @@ mod tests { ) .unwrap(); - builder.build::(rng).unwrap().unwrap().0 + builder.build::(rng).unwrap().0 } /// Verify that the hash for an Orchard Vanilla bundle matches a fixed reference value diff --git a/tests/builder.rs b/tests/builder.rs index d5f2fa83f..56d2e5107 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -93,7 +93,7 @@ fn bundle_chain() { builder.add_output(None, recipient, note_value, AssetBase::native(), None), Ok(()) ); - let (unauthorized, bundle_meta) = builder.build(&mut rng).unwrap().unwrap(); + let (unauthorized, bundle_meta) = builder.build(&mut rng).unwrap(); assert_eq!( unauthorized @@ -163,7 +163,7 @@ fn bundle_chain() { ), Ok(()) ); - let (unauthorized, _) = builder.build(&mut rng).unwrap().unwrap(); + let (unauthorized, _) = builder.build(&mut rng).unwrap(); let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(&pk, &mut rng).unwrap(); proven diff --git a/tests/zsa.rs b/tests/zsa.rs index 3a1e04cdb..1efbeda38 100644 --- a/tests/zsa.rs +++ b/tests/zsa.rs @@ -88,7 +88,7 @@ fn build_and_sign_bundle( pk: &ProvingKey, sk: &SpendingKey, ) -> Bundle { - let unauthorized = builder.build(&mut rng).unwrap().unwrap().0; + let unauthorized = builder.build(&mut rng).unwrap().0; let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(pk, &mut rng).unwrap(); proven @@ -205,7 +205,7 @@ fn create_native_note(keys: &Keychain) -> Note { ), Ok(()) ); - let unauthorized = builder.build(&mut rng).unwrap().unwrap().0; + let unauthorized = builder.build(&mut rng).unwrap().0; let sighash = unauthorized.commitment().into(); let proven = unauthorized.create_proof(keys.pk(), &mut rng).unwrap(); proven.apply_signatures(rng, sighash, &[]).unwrap() From 3d2515b3b52b2df47c0778050379e6588061fb95 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Wed, 25 Dec 2024 18:17:54 +0100 Subject: [PATCH 84/92] Fix some links and typo (#127) --- src/builder.rs | 2 +- src/bundle.rs | 1 - src/bundle/commitments.rs | 4 +-- src/circuit/circuit_zsa.rs | 40 +++++++++++++++++++++-------- src/circuit/note_commit.rs | 8 ++---- src/circuit/value_commit_orchard.rs | 4 +-- src/issuance.rs | 2 +- src/keys.rs | 4 +-- src/note/asset_base.rs | 8 +++--- src/note/commitment.rs | 4 +-- 10 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 14df505e9..88890e5cb 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -290,7 +290,7 @@ impl SpendInfo { /// /// Defined in [Transfer and Burn of Zcash Shielded Assets ZIP-0226 § Split Notes (DRAFT PR)][TransferZSA]. /// - /// [TransferZSA]: https://qed-it.github.io/zips/zip-0226.html#split-notes + /// [TransferZSA]: https://zips.z.cash/zip-0226#split-notes fn create_split_spend(&self, rng: &mut impl RngCore) -> Self { SpendInfo { dummy_sk: None, diff --git a/src/bundle.rs b/src/bundle.rs index 90e90bbdb..4f67591a8 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -457,7 +457,6 @@ pub(crate) fn derive_bvk<'a, A: 'a, V: Clone + Into, FL: 'a + OrchardFlavor value_balance: V, burn: impl Iterator, ) -> redpallas::VerificationKey { - // https://p.z.cash/TCR:bad-txns-orchard-binding-signature-invalid?partial (actions .into_iter() .map(|a| a.cv_net()) diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index a3d28d6c8..3f3745b71 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -82,7 +82,7 @@ pub fn hash_bundle_auth_empty() -> Blake2bHash { /// Construct the commitment for an absent issue bundle as defined in /// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] /// -/// [zip227]: https://qed-it.github.io/zips/zip-0227 +/// [zip227]: https://zips.z.cash/zip-0227 pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { hasher(ZCASH_ORCHARD_ZSA_ISSUE_SIG_PERSONALIZATION).finalize() } @@ -90,7 +90,7 @@ pub fn hash_issue_bundle_auth_empty() -> Blake2bHash { /// Construct the commitment for an absent issue bundle as defined in /// [ZIP-227: Issuance of Zcash Shielded Assets][zip227] /// -/// [zip227]: https://qed-it.github.io/zips/zip-0227 +/// [zip227]: https://zips.z.cash/zip-0227 pub fn hash_issue_bundle_txid_empty() -> Blake2bHash { hasher(ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION).finalize() } diff --git a/src/circuit/circuit_zsa.rs b/src/circuit/circuit_zsa.rs index 34f9c120e..d87180a60 100644 --- a/src/circuit/circuit_zsa.rs +++ b/src/circuit/circuit_zsa.rs @@ -66,16 +66,22 @@ impl OrchardCircuit for OrchardZSA { meta.advice_column(), ]; + // The new or updated constraints for OrchardZSA are explained in + // [ZIP-226: Transfer and Burn of Zcash Shielded Assets][circuitstatement]. + // + // All OrchardZSA constraints: // Constrain split_flag to be boolean - // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign (https://p.z.cash/ZKS:action-cv-net-integrity?partial). - // Constrain (v_old = 0 and is_native_asset = 1) or (calculated root = anchor) (https://p.z.cash/ZKS:action-merkle-path-validity?partial). - // Constrain v_old = 0 or enable_spends = 1 (https://p.z.cash/ZKS:action-enable-spend). - // Constrain v_new = 0 or enable_outputs = 1 (https://p.z.cash/ZKS:action-enable-output). + // Constrain v_old * (1 - split_flag) - v_new = magnitude * sign + // Constrain (v_old = 0 and is_native_asset = 1) or (calculated root = anchor) + // Constrain v_old = 0 or enable_spends = 1 + // Constrain v_new = 0 or enable_outputs = 1 // Constrain is_native_asset to be boolean // Constraint if is_native_asset = 1 then asset = native_asset else asset != native_asset // Constraint if split_flag = 0 then psi_old = psi_nf // Constraint if split_flag = 1, then is_native_asset = 0 // Constraint if enable_zsa = 0, then is_native_asset = 1 + // + // [circuitstatement]: https://zips.z.cash/zip-0226#circuit-statement let q_orchard = meta.selector(); meta.create_gate("Orchard circuit checks", |meta| { let q_orchard = meta.query_selector(q_orchard); @@ -426,7 +432,7 @@ impl OrchardCircuit for OrchardZSA { circuit.asset, )?; - // Merkle path validity check (https://p.z.cash/ZKS:action-merkle-path-validity?partial). + // Merkle path validity check. let root = { let path = circuit .path @@ -441,7 +447,10 @@ impl OrchardCircuit for OrchardZSA { merkle_inputs.calculate_root(layouter.namespace(|| "Merkle path"), leaf)? }; - // Value commitment integrity (https://p.z.cash/ZKS:action-cv-net-integrity?partial). + // Value commitment integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][valuecommitcorrectness] for more details. + // + // [valuecommitcorrectness]: https://zips.z.cash/zip-0226#value-commitment-correctness let v_net_magnitude_sign = { // Witness the magnitude and sign of v_net = v_old - v_new let v_net_magnitude_sign = { @@ -508,7 +517,10 @@ impl OrchardCircuit for OrchardZSA { v_net_magnitude_sign }; - // Nullifier integrity (https://p.z.cash/ZKS:action-nullifier-integrity). + // Nullifier integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] for more details. + // + // [zip226]: https://zips.z.cash/zip-0226 let nf_old = { let nf_old = derive_nullifier( &mut layouter.namespace(|| "nf_old = DeriveNullifier_nk(rho_old, psi_nf, cm_old)"), @@ -531,7 +543,7 @@ impl OrchardCircuit for OrchardZSA { nf_old }; - // Spend authority (https://p.z.cash/ZKS:action-spend-authority) + // Spend authority { let alpha = ScalarFixed::new( ecc_chip.clone(), @@ -554,7 +566,7 @@ impl OrchardCircuit for OrchardZSA { layouter.constrain_instance(rk.inner().y().cell(), config.primary, RK_Y)?; } - // Diversified address integrity (https://p.z.cash/ZKS:action-addr-integrity?partial). + // Diversified address integrity. let pk_d_old = { let ivk = { let ak = ak_P.extract_p().inner().clone(); @@ -602,7 +614,10 @@ impl OrchardCircuit for OrchardZSA { pk_d_old }; - // Old note commitment integrity (https://p.z.cash/ZKS:action-cm-old-integrity?partial). + // Old note commitment integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit] for more details. + // + // [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment. { let rcm_old = ScalarFixed::new( ecc_chip.clone(), @@ -635,7 +650,10 @@ impl OrchardCircuit for OrchardZSA { derived_cm_old.constrain_equal(layouter.namespace(|| "cm_old equality"), &cm_old)?; } - // New note commitment integrity (https://p.z.cash/ZKS:action-cmx-new-integrity?partial). + // New note commitment integrity. + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit] for more details. + // + // [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment. { // Witness g_d_new let g_d_new = { diff --git a/src/circuit/note_commit.rs b/src/circuit/note_commit.rs index ba2e1fd44..849ffc378 100644 --- a/src/circuit/note_commit.rs +++ b/src/circuit/note_commit.rs @@ -718,8 +718,6 @@ impl DecomposeHVanilla { /// -------------------------------------------- /// | h_zec | h_0 | h_1 | 1 | /// | h_zsa | h_2_zsa | | 0 | -/// -/// #[derive(Clone, Debug)] struct DecomposeHZsa { q_notecommit_h: Selector, @@ -879,8 +877,6 @@ impl DecomposeHZsa { /// | A_6 | A_7 | A_8 | q_notecommit_j | /// ------------------------------------ /// | j | j_0 | j_1 | 1 | -/// -/// https://p.z.cash/orchard-0.1:note-commit-decomposition-j?partial #[derive(Clone, Debug)] struct DecomposeJ { q_notecommit_j: Selector, @@ -2099,8 +2095,8 @@ pub(in crate::circuit) mod gadgets { // constraints allows ⊥ to occur, and then during synthesis it detects these edge // cases and raises an error (aborting proof creation). // - // https://p.z.cash/ZKS:action-cm-old-integrity?partial - // https://p.z.cash/ZKS:action-cmx-new-integrity?partial + // See [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] for more details. + // [zip226]: https://zips.z.cash/zip-0226#note-structure-commitment. let message_common_prefix = Message::from_pieces( chip.clone(), vec![ diff --git a/src/circuit/value_commit_orchard.rs b/src/circuit/value_commit_orchard.rs index 7d051013a..ae8b4ea31 100644 --- a/src/circuit/value_commit_orchard.rs +++ b/src/circuit/value_commit_orchard.rs @@ -32,9 +32,9 @@ pub(in crate::circuit) mod gadgets { plonk, }; - /// `ValueCommit^Orchard` from [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]. + /// `ValueCommit^Orchard` from [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226]. /// - /// [Section 5.4.8.3 Homomorphic Pedersen commitments (Sapling and Orchard)]: https://zips.z.cash/protocol/protocol.pdf#concretehomomorphiccommit + /// [zip226]: https://zips.z.cash/zip-0226#value-commitment-correctness pub(in crate::circuit) fn value_commit_orchard( mut layouter: impl Layouter, ecc_chip: EccChip, diff --git a/src/issuance.rs b/src/issuance.rs index d2d2b2aaf..08ea749e7 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -556,7 +556,7 @@ impl IssueBundle { /// * For the `IssueBundle`: /// * the Signature on top of the provided `sighash` verifies correctly. /// * For each `IssueAction`: -/// * Asset description size is collect. +/// * Asset description size is correct. /// * `AssetBase` for the `IssueAction` has not been previously finalized. /// * For each `Note` inside an `IssueAction`: /// * All notes have the same, correct `AssetBase`. diff --git a/src/keys.rs b/src/keys.rs index 3c76a73f6..d1ba3bb6e 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -240,7 +240,7 @@ fn check_structural_validity( /// /// $\mathsf{isk}$ as defined in [ZIP 227][issuancekeycomponents]. /// -/// [issuancekeycomponents]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation +/// [issuancekeycomponents]: https://zips.z.cash/zip-0227#issuance-key-derivation #[derive(Copy, Clone)] pub struct IssuanceAuthorizingKey(NonZeroScalar); @@ -311,7 +311,7 @@ impl Debug for IssuanceAuthorizingKey { /// /// Defined in [ZIP 227: Issuance of Zcash Shielded Assets § Issuance Key Generation][IssuanceZSA]. /// -/// [IssuanceZSA]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation +/// [IssuanceZSA]: https://zips.z.cash/zip-0227#issuance-key-derivation #[derive(Debug, Clone)] pub struct IssuanceValidatingKey(schnorr::VerifyingKey); diff --git a/src/note/asset_base.rs b/src/note/asset_base.rs index e0ee796f8..dc00b873a 100644 --- a/src/note/asset_base.rs +++ b/src/note/asset_base.rs @@ -22,9 +22,9 @@ pub const ZSA_ASSET_DIGEST_PERSONALIZATION: &[u8; 16] = b"ZSA-Asset-Digest"; /// AssetDigest for the ZSA asset /// -/// Defined in [Transfer and Burn of Zcash Shielded Assets][AssetDigest]. +/// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][assetdigest]. /// -/// [assetdigest]: https://qed-it.github.io/zips/zip-0226.html#asset-identifiers +/// [assetdigest]: https://zips.z.cash/zip-0226.html#asset-identifiers pub fn asset_digest(asset_id: Vec) -> Blake2bHash { Params::new() .hash_length(64) @@ -47,9 +47,9 @@ impl AssetBase { /// Note type derivation$. /// - /// Defined in [Transfer and Burn of Zcash Shielded Assets][AssetBase]. + /// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][assetbase]. /// - /// [notetypes]: https://qed-it.github.io/zips/zip-0226.html#asset-identifiers + /// [assetbase]: https://zips.z.cash/zip-0226.html#asset-identifiers /// /// # Panics /// diff --git a/src/note/commitment.rs b/src/note/commitment.rs index 09a7d45f4..87169049e 100644 --- a/src/note/commitment.rs +++ b/src/note/commitment.rs @@ -38,9 +38,9 @@ impl NoteCommitment { impl NoteCommitment { /// $NoteCommit^Orchard$. /// - /// Defined in [Zcash Protocol Spec § 5.4.8.4: Sinsemilla commitments][concretesinsemillacommit]. + /// Defined in [ZIP-226: Transfer and Burn of Zcash Shielded Assets][notecommit]. /// - /// [concretesinsemillacommit]: https://zips.z.cash/protocol/nu5.pdf#concretesinsemillacommit + /// [notecommit]: https://zips.z.cash/zip-0226#note-structure-commitment pub(crate) fn derive( g_d: [u8; 32], pk_d: [u8; 32], From 0d2f439f1786021c6c599a023d0575dacbdaba08 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Mon, 6 Jan 2025 15:12:46 +0300 Subject: [PATCH 85/92] Install libfontconfig1-dev to fix CI build on updated Ubuntu runner (#132) GitHub updated ubuntu-latest from Ubuntu 22.04 to 24.04, which looks like it no longer includes fontconfig by default. This PR adds installation of libfontconfig1-dev so the yeslogic-fontconfig-sys crate (a transitive dependency) can build successfully again. --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e6a6c3ae..8099ff630 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,9 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] steps: + - name: Install dependencies (needed for yeslogic-fontconfig-sys crate) + if: runner.os == 'Linux' + run: sudo apt update && sudo apt install -y libfontconfig1-dev - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable id: toolchain @@ -91,6 +94,9 @@ jobs: name: Intra-doc links runs-on: ubuntu-latest steps: + - name: Install dependencies (needed for yeslogic-fontconfig-sys crate) + if: runner.os == 'Linux' + run: sudo apt update && sudo apt install -y libfontconfig1-dev - uses: actions/checkout@v4 - run: cargo fetch # Requires #![deny(rustdoc::broken_intra_doc_links)] in crates. From 69f92a3dc118d43f40201a1ffccfe52255dfd476 Mon Sep 17 00:00:00 2001 From: Dmitry Demin Date: Wed, 8 Jan 2025 16:10:04 +0300 Subject: [PATCH 86/92] Update AssetSuply and SupplyInfo (new) (#133) This PR is an updated copy of #128: > The amount in AssetSupply must be a NoteValue (u64) and not a ValueSum (i128). > We add reference_notes into SupplyInfo. It is a hashmap of asset bases to their respective reference note The code was updated, `get_reference_note` method of `IssueAction` was added and used, `get_reference_notes` was removed. Also, instead of a separate new `reference_notes` `HashMap` in `SupplyInfo` a new field `reference_note` was added to `AssetSupply` struct. Unit tests were fixed accordingly. --------- Co-authored-by: Constance Beguier Co-authored-by: Paul <3682187+PaulLaux@users.noreply.github.com> --- src/bundle/burn_validation.rs | 48 ++++++++------- src/issuance.rs | 112 ++++++++++++++++++++-------------- src/supply_info.rs | 62 +++++++++++-------- src/value.rs | 8 +++ 4 files changed, 137 insertions(+), 93 deletions(-) diff --git a/src/bundle/burn_validation.rs b/src/bundle/burn_validation.rs index d05c43294..d6388f10c 100644 --- a/src/bundle/burn_validation.rs +++ b/src/bundle/burn_validation.rs @@ -2,9 +2,9 @@ //! //! The module provides a function `validate_bundle_burn` that can be used to validate the burn values for the bundle. //! -use std::fmt; +use std::{collections::HashSet, fmt}; -use crate::note::AssetBase; +use crate::{note::AssetBase, value::NoteValue}; /// Possible errors that can occur during bundle burn validation. #[derive(Debug)] @@ -14,36 +14,36 @@ pub enum BurnError { DuplicateAsset, /// Cannot burn a native asset. NativeAsset, - /// Cannot burn an asset with a non-positive value. - NonPositiveAmount, + /// Cannot burn an asset with a zero value. + ZeroAmount, } -/// Validates burn for a bundle by ensuring each asset is unique, non-native, and has a positive value. +/// Validates burn for a bundle by ensuring each asset is unique, non-native, and has a non-zero value. /// -/// Each burn element is represented as a tuple of `AssetBase` and `i64` (value for the burn). +/// Each burn element is represented as a tuple of `AssetBase` and `NoteValue` (value for the burn). /// /// # Arguments /// -/// * `burn` - A vector of assets, where each asset is represented as a tuple of `AssetBase` and `i64` (value the burn). +/// * `burn` - A vector of assets, where each asset is represented as a tuple of `AssetBase` and `NoteValue` (value the burn). /// /// # Errors /// /// Returns a `BurnError` if: -/// * Any asset in the `burn` vector is not unique (`BurnError::DuplicateAsset`). /// * Any asset in the `burn` vector is native (`BurnError::NativeAsset`). -/// * Any asset in the `burn` vector has a non-positive value (`BurnError::NonPositiveAmount`). -pub fn validate_bundle_burn(bundle_burn: &Vec<(AssetBase, i64)>) -> Result<(), BurnError> { - let mut asset_set = std::collections::HashSet::<&AssetBase>::new(); +/// * Any asset in the `burn` vector has a zero value (`BurnError::ZeroAmount`). +/// * Any asset in the `burn` vector is not unique (`BurnError::DuplicateAsset`). +pub fn validate_bundle_burn(burn: &[(AssetBase, NoteValue)]) -> Result<(), BurnError> { + let mut burn_set = HashSet::new(); - for (asset, value) in bundle_burn { - if !asset_set.insert(asset) { - return Err(BurnError::DuplicateAsset); - } + for (asset, value) in burn { if asset.is_native().into() { return Err(BurnError::NativeAsset); } - if *value <= 0 { - return Err(BurnError::NonPositiveAmount); + if value.inner() == 0 { + return Err(BurnError::ZeroAmount); + } + if !burn_set.insert(*asset) { + return Err(BurnError::DuplicateAsset); } } @@ -55,8 +55,8 @@ impl fmt::Display for BurnError { match *self { BurnError::DuplicateAsset => write!(f, "Encountered a duplicate asset to burn."), BurnError::NativeAsset => write!(f, "Cannot burn a native asset."), - BurnError::NonPositiveAmount => { - write!(f, "Cannot burn an asset with a non-positive value.") + BurnError::ZeroAmount => { + write!(f, "Cannot burn an asset with a zero value.") } } } @@ -64,6 +64,8 @@ impl fmt::Display for BurnError { #[cfg(test)] mod tests { + use crate::value::NoteValue; + use super::*; /// Creates an item of bundle burn list for a given asset description and value. @@ -80,14 +82,14 @@ mod tests { /// /// A tuple `(AssetBase, Amount)` representing the burn list item. /// - pub fn get_burn_tuple(asset_desc: &[u8], value: i64) -> (AssetBase, i64) { + pub fn get_burn_tuple(asset_desc: &[u8], value: u64) -> (AssetBase, NoteValue) { use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap(); ( AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc), - value, + NoteValue::from_raw(value), ) } @@ -121,7 +123,7 @@ mod tests { fn validate_bundle_burn_native_asset() { let bundle_burn = vec![ get_burn_tuple(b"Asset 1", 10), - (AssetBase::native(), 20), + (AssetBase::native(), NoteValue::from_raw(20)), get_burn_tuple(b"Asset 3", 10), ]; @@ -140,6 +142,6 @@ mod tests { let result = validate_bundle_burn(&bundle_burn); - assert_eq!(result, Err(BurnError::NonPositiveAmount)); + assert_eq!(result, Err(BurnError::ZeroAmount)); } } diff --git a/src/issuance.rs b/src/issuance.rs index 08ea749e7..78832fe7c 100644 --- a/src/issuance.rs +++ b/src/issuance.rs @@ -4,7 +4,7 @@ use group::Group; use k256::schnorr; use nonempty::NonEmpty; use rand::RngCore; -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::fmt; use crate::bundle::commitments::{hash_issue_bundle_auth_data, hash_issue_bundle_txid_data}; @@ -12,17 +12,26 @@ use crate::constants::reference_keys::ReferenceKeys; use crate::issuance::Error::{ AssetBaseCannotBeIdentityPoint, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueActionWithoutNoteNotFinalized, IssueBundleIkMismatchAssetBase, - IssueBundleInvalidSignature, ValueSumOverflow, WrongAssetDescSize, + IssueBundleInvalidSignature, ValueOverflow, WrongAssetDescSize, }; use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey}; use crate::note::asset_base::is_asset_desc_of_valid_size; use crate::note::{AssetBase, Nullifier, Rho}; -use crate::value::{NoteValue, ValueSum}; +use crate::value::NoteValue; use crate::{Address, Note}; use crate::supply_info::{AssetSupply, SupplyInfo}; +/// Checks if a given note is a reference note. +/// +/// A reference note satisfies the following conditions: +/// - The note's value is zero. +/// - The note's recipient matches the reference recipient. +fn is_reference_note(note: &Note) -> bool { + note.value() == NoteValue::zero() && note.recipient() == ReferenceKeys::recipient() +} + /// A bundle of actions to be applied to the ledger. #[derive(Debug, Clone, PartialEq, Eq)] pub struct IssueBundle { @@ -114,7 +123,7 @@ impl IssueAction { /// /// This function may return an error in any of the following cases: /// - /// * `ValueSumOverflow`: If the total amount value of all notes in the `IssueAction` overflows. + /// * `ValueOverflow`: If the total amount value of all notes in the `IssueAction` overflows. /// /// * `IssueBundleIkMismatchAssetBase`: If the provided `ik` is not used to derive the /// `AssetBase` for **all** internal notes. @@ -132,7 +141,7 @@ impl IssueAction { let value_sum = self .notes .iter() - .try_fold(ValueSum::zero(), |value_sum, ¬e| { + .try_fold(NoteValue::zero(), |value_sum, ¬e| { //The asset base should not be the identity point of the Pallas curve. if bool::from(note.asset().cv_base().is_identity()) { return Err(AssetBaseCannotBeIdentityPoint); @@ -145,12 +154,16 @@ impl IssueAction { .ok_or(IssueBundleIkMismatchAssetBase)?; // The total amount should not overflow - (value_sum + note.value()).ok_or(ValueSumOverflow) + (value_sum + note.value()).ok_or(ValueOverflow) })?; Ok(( issue_asset, - AssetSupply::new(value_sum, self.is_finalized()), + AssetSupply::new( + value_sum, + self.is_finalized(), + self.get_reference_note().cloned(), + ), )) } @@ -163,6 +176,15 @@ impl IssueAction { 0b0000_0000 } } + + /// Returns the reference note if the first note matches the reference note criteria. + /// + /// A reference note must be the first note in the `notes` vector and satisfy the following: + /// - The note's value is zero. + /// - The note's recipient matches the reference recipient. + pub fn get_reference_note(&self) -> Option<&Note> { + self.notes.first().filter(|note| is_reference_note(note)) + } } /// Defines the authorization type of an Issue bundle. @@ -468,23 +490,6 @@ impl IssueBundle { } } -impl IssueBundle { - /// Returns the reference notes for the `IssueBundle`. - pub fn get_reference_notes(self) -> HashMap { - let mut reference_notes = HashMap::new(); - self.actions.iter().for_each(|action| { - action.notes.iter().for_each(|note| { - if (note.recipient() == ReferenceKeys::recipient()) - && (note.value() == NoteValue::zero()) - { - reference_notes.insert(note.asset(), *note); - } - }) - }); - reference_notes - } -} - fn create_reference_note(asset: AssetBase, mut rng: impl RngCore) -> Note { Note::new( ReferenceKeys::recipient(), @@ -561,12 +566,13 @@ impl IssueBundle { /// * For each `Note` inside an `IssueAction`: /// * All notes have the same, correct `AssetBase`. /// -// # Returns +/// # Returns /// /// A Result containing a SupplyInfo struct, which stores supply information in a HashMap. -/// The HashMap uses AssetBase as the key, and an AssetSupply struct as the value. The -/// AssetSupply contains a ValueSum (representing the total value of all notes for the asset) -/// and a bool indicating whether the asset is finalized. +/// The HashMap `assets` uses AssetBase as the key, and an AssetSupply struct as the +/// value. The AssetSupply contains a NoteValue (representing the total value of all notes for +/// the asset), a bool indicating whether the asset is finalized and a Note (the reference note +/// for this asset). /// /// # Errors /// @@ -576,7 +582,7 @@ impl IssueBundle { /// asset in the bundle is incorrect. /// * `IssueActionPreviouslyFinalizedAssetBase`: This error occurs if the asset has already been /// finalized (inserted into the `finalized` collection). -/// * `ValueSumOverflow`: This error occurs if an overflow happens during the calculation of +/// * `ValueOverflow`: This error occurs if an overflow happens during the calculation of /// the value sum for the notes in the asset. /// * `IssueBundleIkMismatchAssetBase`: This error is raised if the `AssetBase` derived from /// the `ik` (Issuance Validating Key) and the `asset_desc` (Asset Description) does not match @@ -636,7 +642,7 @@ pub enum Error { IssueActionPreviouslyFinalizedAssetBase(AssetBase), /// Overflow error occurred while calculating the value of the asset - ValueSumOverflow, + ValueOverflow, } impl fmt::Display for Error { @@ -672,7 +678,7 @@ impl fmt::Display for Error { IssueActionPreviouslyFinalizedAssetBase(_) => { write!(f, "the provided `AssetBase` has been previously finalized") } - ValueSumOverflow => { + ValueOverflow => { write!( f, "overflow error occurred while calculating the value of the asset" @@ -685,18 +691,19 @@ impl fmt::Display for Error { #[cfg(test)] mod tests { use super::{AssetSupply, IssueBundle, IssueInfo}; - use crate::constants::reference_keys::ReferenceKeys; use crate::issuance::Error::{ AssetBaseCannotBeIdentityPoint, IssueActionNotFound, IssueActionPreviouslyFinalizedAssetBase, IssueBundleIkMismatchAssetBase, IssueBundleInvalidSignature, WrongAssetDescSize, }; - use crate::issuance::{verify_issue_bundle, IssueAction, Signed, Unauthorized}; + use crate::issuance::{ + is_reference_note, verify_issue_bundle, IssueAction, Signed, Unauthorized, + }; use crate::keys::{ FullViewingKey, IssuanceAuthorizingKey, IssuanceValidatingKey, Scope, SpendingKey, }; use crate::note::{AssetBase, Nullifier, Rho}; - use crate::value::{NoteValue, ValueSum}; + use crate::value::NoteValue; use crate::{Address, Note}; use group::{Group, GroupEncoding}; use nonempty::NonEmpty; @@ -709,12 +716,11 @@ mod tests { /// /// The following checks are performed: /// - the note value of the reference note is equal to 0 - /// - the asset of the reference note is equal to the provided asset /// - the recipient of the reference note is equal to the reference recipient + /// - the asset of the reference note is equal to the provided asset fn verify_reference_note(note: &Note, asset: AssetBase) { - assert_eq!(note.value(), NoteValue::from_raw(0)); + assert!(is_reference_note(note)); assert_eq!(note.asset(), asset); - assert_eq!(note.recipient(), ReferenceKeys::recipient()); } fn setup_params() -> ( @@ -829,7 +835,7 @@ mod tests { let (asset, supply) = result.unwrap(); assert_eq!(asset, test_asset); - assert_eq!(supply.amount, ValueSum::from_raw(30)); + assert_eq!(supply.amount, NoteValue::from_raw(30)); assert!(!supply.is_finalized); } @@ -854,7 +860,7 @@ mod tests { let (asset, supply) = result.unwrap(); assert_eq!(asset, test_asset); - assert_eq!(supply.amount, ValueSum::from_raw(30)); + assert_eq!(supply.amount, NoteValue::from_raw(30)); assert!(supply.is_finalized); } @@ -975,10 +981,8 @@ mod tests { assert_eq!(first_note.value().inner(), 15); assert_eq!(first_note.asset(), third_asset); - let reference_notes = bundle.get_reference_notes(); - assert_eq!(reference_notes.len(), 2); - verify_reference_note(reference_notes.get(&asset).unwrap(), asset); - verify_reference_note(reference_notes.get(&third_asset).unwrap(), third_asset); + verify_reference_note(action.get_reference_note().unwrap(), asset); + verify_reference_note(action2.get_reference_note().unwrap(), third_asset); } #[test] @@ -1227,17 +1231,33 @@ mod tests { assert_eq!(supply_info.assets.len(), 3); + let reference_note1 = signed.actions()[0].notes()[0]; + let reference_note2 = signed.actions()[1].notes()[0]; + let reference_note3 = signed.actions()[2].notes()[0]; + assert_eq!( supply_info.assets.get(&asset1_base), - Some(&AssetSupply::new(ValueSum::from_raw(15), true)) + Some(&AssetSupply::new( + NoteValue::from_raw(15), + true, + Some(reference_note1) + )) ); assert_eq!( supply_info.assets.get(&asset2_base), - Some(&AssetSupply::new(ValueSum::from_raw(10), true)) + Some(&AssetSupply::new( + NoteValue::from_raw(10), + true, + Some(reference_note2) + )) ); assert_eq!( supply_info.assets.get(&asset3_base), - Some(&AssetSupply::new(ValueSum::from_raw(5), false)) + Some(&AssetSupply::new( + NoteValue::from_raw(5), + false, + Some(reference_note3) + )) ); } diff --git a/src/supply_info.rs b/src/supply_info.rs index 6fb69d516..6444201ec 100644 --- a/src/supply_info.rs +++ b/src/supply_info.rs @@ -2,24 +2,31 @@ use std::collections::{hash_map, HashMap, HashSet}; -use crate::{issuance::Error, note::AssetBase, value::ValueSum}; +use crate::{issuance::Error, note::AssetBase, value::NoteValue, Note}; -/// Represents the amount of an asset and its finalization status. +/// Represents the amount of an asset, its finalization status and reference note. #[derive(Debug, Clone, Copy)] #[cfg_attr(test, derive(PartialEq, Eq))] pub struct AssetSupply { /// The amount of the asset. - pub amount: ValueSum, + pub amount: NoteValue, + /// Whether or not the asset is finalized. pub is_finalized: bool, + + /// The reference note, `None` if this `AssetSupply` instance is created from an issue bundle that does not include + /// a reference note (a non-first issuance) + pub reference_note: Option, } impl AssetSupply { - /// Creates a new AssetSupply instance with the given amount and finalization status. - pub fn new(amount: ValueSum, is_finalized: bool) -> Self { + /// Creates a new AssetSupply instance with the given amount, finalization status and reference + /// note. + pub fn new(amount: NoteValue, is_finalized: bool, reference_note: Option) -> Self { Self { amount, is_finalized, + reference_note, } } } @@ -46,9 +53,9 @@ impl SupplyInfo { match self.assets.entry(asset) { hash_map::Entry::Occupied(entry) => { let supply = entry.into_mut(); - supply.amount = - (supply.amount + new_supply.amount).ok_or(Error::ValueSumOverflow)?; + supply.amount = (supply.amount + new_supply.amount).ok_or(Error::ValueOverflow)?; supply.is_finalized |= new_supply.is_finalized; + supply.reference_note = supply.reference_note.or(new_supply.reference_note); } hash_map::Entry::Vacant(entry) => { entry.insert(new_supply); @@ -87,11 +94,11 @@ mod tests { AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc) } - fn sum<'a, T: IntoIterator>(supplies: T) -> Option { + fn sum<'a, T: IntoIterator>(supplies: T) -> Option { supplies .into_iter() .map(|supply| supply.amount) - .try_fold(ValueSum::from_raw(0), |sum, value| sum + value) + .try_fold(NoteValue::from_raw(0), |sum, value| sum + value) } #[test] @@ -101,11 +108,11 @@ mod tests { let asset1 = create_test_asset(b"Asset 1"); let asset2 = create_test_asset(b"Asset 2"); - let supply1 = AssetSupply::new(ValueSum::from_raw(20), false); - let supply2 = AssetSupply::new(ValueSum::from_raw(30), true); - let supply3 = AssetSupply::new(ValueSum::from_raw(10), false); - let supply4 = AssetSupply::new(ValueSum::from_raw(10), true); - let supply5 = AssetSupply::new(ValueSum::from_raw(50), false); + let supply1 = AssetSupply::new(NoteValue::from_raw(20), false, None); + let supply2 = AssetSupply::new(NoteValue::from_raw(30), true, None); + let supply3 = AssetSupply::new(NoteValue::from_raw(10), false, None); + let supply4 = AssetSupply::new(NoteValue::from_raw(10), true, None); + let supply5 = AssetSupply::new(NoteValue::from_raw(50), false, None); assert_eq!(supply_info.assets.len(), 0); @@ -114,7 +121,7 @@ mod tests { assert_eq!(supply_info.assets.len(), 1); assert_eq!( supply_info.assets.get(&asset1), - Some(&AssetSupply::new(sum([&supply1]).unwrap(), false)) + Some(&AssetSupply::new(sum([&supply1]).unwrap(), false, None)) ); // Add supply2 @@ -122,7 +129,11 @@ mod tests { assert_eq!(supply_info.assets.len(), 1); assert_eq!( supply_info.assets.get(&asset1), - Some(&AssetSupply::new(sum([&supply1, &supply2]).unwrap(), true)) + Some(&AssetSupply::new( + sum([&supply1, &supply2]).unwrap(), + true, + None + )) ); // Add supply3 @@ -132,7 +143,8 @@ mod tests { supply_info.assets.get(&asset1), Some(&AssetSupply::new( sum([&supply1, &supply2, &supply3]).unwrap(), - true + true, + None )) ); @@ -143,7 +155,8 @@ mod tests { supply_info.assets.get(&asset1), Some(&AssetSupply::new( sum([&supply1, &supply2, &supply3, &supply4]).unwrap(), - true + true, + None )) ); @@ -154,12 +167,13 @@ mod tests { supply_info.assets.get(&asset1), Some(&AssetSupply::new( sum([&supply1, &supply2, &supply3, &supply4]).unwrap(), - true + true, + None )) ); assert_eq!( supply_info.assets.get(&asset2), - Some(&AssetSupply::new(sum([&supply5]).unwrap(), false)) + Some(&AssetSupply::new(sum([&supply5]).unwrap(), false, None)) ); } @@ -171,10 +185,10 @@ mod tests { let asset2 = create_test_asset(b"Asset 2"); let asset3 = create_test_asset(b"Asset 3"); - let supply1 = AssetSupply::new(ValueSum::from_raw(10), false); - let supply2 = AssetSupply::new(ValueSum::from_raw(20), true); - let supply3 = AssetSupply::new(ValueSum::from_raw(40), false); - let supply4 = AssetSupply::new(ValueSum::from_raw(50), true); + let supply1 = AssetSupply::new(NoteValue::from_raw(10), false, None); + let supply2 = AssetSupply::new(NoteValue::from_raw(20), true, None); + let supply3 = AssetSupply::new(NoteValue::from_raw(40), false, None); + let supply4 = AssetSupply::new(NoteValue::from_raw(50), true, None); assert!(supply_info.add_supply(asset1, supply1).is_ok()); assert!(supply_info.add_supply(asset1, supply2).is_ok()); diff --git a/src/value.rs b/src/value.rs index a9cb843d0..e8ab3365b 100644 --- a/src/value.rs +++ b/src/value.rs @@ -153,6 +153,14 @@ impl Sub for NoteValue { } } +impl Add for NoteValue { + type Output = Option; + + fn add(self, rhs: Self) -> Self::Output { + self.0.checked_add(rhs.0).map(NoteValue) + } +} + pub(crate) enum Sign { Positive, Negative, From 3dbdbc52c6e2ffeca015ae6eb80ad7f1c870384d Mon Sep 17 00:00:00 2001 From: Vivek Arte <46618816+vivek-arte@users.noreply.github.com> Date: Sat, 18 Jan 2025 19:19:37 +0530 Subject: [PATCH 87/92] Update to orchard_auth_digest computation (#134) This updates the code to perform the computation differently for OrchardVanilla and OrchardZSA, similar to the txid_data changes --- src/bundle/commitments.rs | 59 ++++++++++++++++++++++------ src/domain/orchard_domain.rs | 12 +++++- src/domain/orchard_domain_vanilla.rs | 22 ++++++++++- src/domain/orchard_domain_zsa.rs | 22 +++++++++++ 4 files changed, 101 insertions(+), 14 deletions(-) diff --git a/src/bundle/commitments.rs b/src/bundle/commitments.rs index 3f3745b71..b25aa375d 100644 --- a/src/bundle/commitments.rs +++ b/src/bundle/commitments.rs @@ -16,7 +16,10 @@ pub(crate) const ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION: &[u8; 16] = b pub(crate) const ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcActNHash"; pub(crate) const ZCASH_ORCHARD_ZSA_BURN_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxIdOrcBurnHash"; -const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; +pub(crate) const ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION: &[u8; 16] = b"ZTxAuthOrchaHash"; +pub(crate) const ZCASH_ORCHARD_ACTION_GROUPS_SIGS_HASH_PERSONALIZATION: &[u8; 16] = + b"ZTxAuthOrcAGHash"; + const ZCASH_ORCHARD_ZSA_ISSUE_PERSONALIZATION: &[u8; 16] = b"ZTxIdSAIssueHash"; const ZCASH_ORCHARD_ZSA_ISSUE_ACTION_PERSONALIZATION: &[u8; 16] = b"ZTxIdIssuActHash"; const ZCASH_ORCHARD_ZSA_ISSUE_NOTE_PERSONALIZATION: &[u8; 16] = b"ZTxIdIAcNoteHash"; @@ -60,15 +63,7 @@ pub fn hash_bundle_txid_empty() -> Blake2bHash { pub(crate) fn hash_bundle_auth_data( bundle: &Bundle, ) -> Blake2bHash { - let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); - h.update(bundle.authorization().proof().as_ref()); - for action in bundle.actions().iter() { - h.update(&<[u8; 64]>::from(action.authorization())); - } - h.update(&<[u8; 64]>::from( - bundle.authorization().binding_signature(), - )); - h.finalize() + D::hash_bundle_auth_data(bundle) } /// Construct the commitment for an absent bundle as defined in @@ -130,7 +125,11 @@ pub(crate) fn hash_issue_bundle_auth_data(bundle: &IssueBundle) -> Blake mod tests { use crate::{ builder::{Builder, BundleType, UnauthorizedBundle}, - bundle::commitments::hash_bundle_txid_data, + bundle::{ + commitments::{hash_bundle_auth_data, hash_bundle_txid_data}, + Authorized, Bundle, + }, + circuit::ProvingKey, keys::{FullViewingKey, Scope, SpendingKey}, note::AssetBase, orchard_flavor::{OrchardFlavor, OrchardVanilla, OrchardZSA}, @@ -194,4 +193,42 @@ mod tests { "43cfaab1ffcd8d4752e5e7479fd619c769e3ab459b6f10bbba80533608f546b0" ); } + + fn generate_auth_bundle( + bundle_type: BundleType, + ) -> Bundle { + let mut rng = StdRng::seed_from_u64(6); + let pk = ProvingKey::build::(); + let bundle = generate_bundle(bundle_type) + .create_proof(&pk, &mut rng) + .unwrap(); + let sighash = bundle.commitment().into(); + bundle.prepare(rng, sighash).finalize().unwrap() + } + + /// Verify that the authorizing data commitment for an Orchard Vanilla bundle matches a fixed + /// reference value to ensure consistency. + #[test] + fn test_hash_bundle_auth_data_for_orchard_vanilla() { + let bundle = generate_auth_bundle::(BundleType::DEFAULT_VANILLA); + let orchard_auth_digest = hash_bundle_auth_data(&bundle); + assert_eq!( + orchard_auth_digest.to_hex().as_str(), + // Bundle hash for Orchard (vanilla) generated using + // Zcash/Orchard commit: 23a167e3972632586dc628ddbdd69d156dfd607b + "2cd424654d8cb770c8dbdf253b6829e25fc70b40157048fd7c6c19f9a9c61f76" + ); + } + + /// Verify that the authorizing data commitment for an OrchardZSA bundle matches a fixed + /// reference value to ensure consistency. + #[test] + fn test_hash_bundle_auth_data_for_orchard_zsa() { + let bundle = generate_auth_bundle::(BundleType::DEFAULT_ZSA); + let orchard_auth_digest = hash_bundle_auth_data(&bundle); + assert_eq!( + orchard_auth_digest.to_hex().as_str(), + "c765769582c598930b2825224d5d9246196954fe7cbd3a2be9afa3c542c06387" + ); + } } diff --git a/src/domain/orchard_domain.rs b/src/domain/orchard_domain.rs index 17d8a2f8c..5249a918d 100644 --- a/src/domain/orchard_domain.rs +++ b/src/domain/orchard_domain.rs @@ -14,7 +14,7 @@ use crate::{ ZCASH_ORCHARD_ACTIONS_MEMOS_HASH_PERSONALIZATION, ZCASH_ORCHARD_ACTIONS_NONCOMPACT_HASH_PERSONALIZATION, }, - Authorization, + Authorization, Authorized, }, domain::{ compact_action::CompactAction, @@ -110,6 +110,16 @@ pub trait OrchardDomainCommon: fmt::Debug + Clone { main_hasher.update(mh.finalize().as_bytes()); main_hasher.update(nh.finalize().as_bytes()); } + + /// Evaluate `orchard_auth_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// for OrchardVanilla and as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// for OrchardZSA + /// + /// [zip244]: https://zips.z.cash/zip-0244 + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash; } /// Orchard-specific note encryption logic. diff --git a/src/domain/orchard_domain_vanilla.rs b/src/domain/orchard_domain_vanilla.rs index 1a3bea45c..69cd9a54c 100644 --- a/src/domain/orchard_domain_vanilla.rs +++ b/src/domain/orchard_domain_vanilla.rs @@ -6,8 +6,10 @@ use zcash_note_encryption_zsa::note_bytes::NoteBytesData; use crate::{ bundle::{ - commitments::{hasher, ZCASH_ORCHARD_HASH_PERSONALIZATION}, - Authorization, + commitments::{ + hasher, ZCASH_ORCHARD_HASH_PERSONALIZATION, ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION, + }, + Authorization, Authorized, }, note::{AssetBase, Note}, orchard_flavor::OrchardVanilla, @@ -57,6 +59,22 @@ impl OrchardDomainCommon for OrchardVanilla { h.update(&bundle.anchor().to_bytes()); h.finalize() } + + /// Evaluate `orchard_auth_digest` for the bundle as defined in + /// [ZIP-244: Transaction Identifier Non-Malleability][zip244] + /// + /// [zip244]: https://zips.z.cash/zip-0244 + fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); + h.update(bundle.authorization().proof().as_ref()); + for action in bundle.actions().iter() { + h.update(&<[u8; 64]>::from(action.authorization())); + } + h.update(&<[u8; 64]>::from( + bundle.authorization().binding_signature(), + )); + h.finalize() + } } #[cfg(test)] diff --git a/src/domain/orchard_domain_zsa.rs b/src/domain/orchard_domain_zsa.rs index c2e685f5e..0c003de6c 100644 --- a/src/domain/orchard_domain_zsa.rs +++ b/src/domain/orchard_domain_zsa.rs @@ -4,6 +4,10 @@ use blake2b_simd::Hash as Blake2bHash; use zcash_note_encryption_zsa::note_bytes::NoteBytesData; +use crate::bundle::commitments::{ + ZCASH_ORCHARD_ACTION_GROUPS_SIGS_HASH_PERSONALIZATION, ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION, +}; +use crate::bundle::Authorized; use crate::{ bundle::{ commitments::{ @@ -79,6 +83,24 @@ impl OrchardDomainCommon for OrchardZSA { h.update(&(*bundle.value_balance()).into().to_le_bytes()); h.finalize() } + + /// Evaluate `orchard_auth_digest` for the bundle as defined in + /// [ZIP-226: Transfer and Burn of Zcash Shielded Assets][zip226] + /// + /// [zip226]: https://zips.z.cash/zip-0226 + fn hash_bundle_auth_data(bundle: &Bundle) -> Blake2bHash { + let mut h = hasher(ZCASH_ORCHARD_SIGS_HASH_PERSONALIZATION); + let mut agh = hasher(ZCASH_ORCHARD_ACTION_GROUPS_SIGS_HASH_PERSONALIZATION); + agh.update(bundle.authorization().proof().as_ref()); + for action in bundle.actions().iter() { + agh.update(&<[u8; 64]>::from(action.authorization())); + } + h.update(agh.finalize().as_bytes()); + h.update(&<[u8; 64]>::from( + bundle.authorization().binding_signature(), + )); + h.finalize() + } } #[cfg(test)] From 70daf8bf1accb0eaa1a5a0b865e2c7b89af05ec3 Mon Sep 17 00:00:00 2001 From: Constance Beguier Date: Thu, 23 Jan 2025 10:32:25 +0100 Subject: [PATCH 88/92] [book] Update book with ZSA changes Updated pages - Actions by adding dummy and split notes - Nullifiers by adding nullifier equation for split notes - Commitments by adding ZSA value commitment New pages - ZSA NoteCommit --- book/src/SUMMARY.md | 3 +- book/src/design/actions.md | 32 +- book/src/design/circuit/note-commit.md | 2 +- book/src/design/circuit/zsa-note-commit.md | 359 ++++++++++++++++++++ book/src/design/circuit/zsa-note-commit.png | Bin 0 -> 1487216 bytes book/src/design/commitments.md | 10 +- book/src/design/nullifiers.md | 25 ++ 7 files changed, 427 insertions(+), 4 deletions(-) create mode 100644 book/src/design/circuit/zsa-note-commit.md create mode 100644 book/src/design/circuit/zsa-note-commit.png diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 83ad1b4fd..19a8f77fd 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -18,4 +18,5 @@ - [Circuit](design/circuit.md) - [Gadgets](design/circuit/gadgets.md) - [CommitIvk](design/circuit/commit-ivk.md) - - [NoteCommit](design/circuit/note-commit.md) + - [Orchard NoteCommit](design/circuit/note-commit.md) + - [OrchardZSA NoteCommit](design/circuit/zsa-note-commit.md) diff --git a/book/src/design/actions.md b/book/src/design/actions.md index 5bbcec988..73c81a1af 100644 --- a/book/src/design/actions.md +++ b/book/src/design/actions.md @@ -13,14 +13,44 @@ proof per output note, which greatly improved the performance of generating outp removed any arity-hiding from the proofs (instead having the transaction builder pad transactions to 1-in, 2-out). -For Orchard, we take a combined approach: we define an Orchard transaction as containing a +For Orchard(ZSA), we take a combined approach: we define an Orchard transaction as containing a bundle of actions, where each action is both a spend and an output. This provides the same inherent arity-hiding as multi-JoinSplit Sprout, but using Sapling value commitments to balance the transaction without doubling its size. +## Dummy notes for Orchard + +For Orchard, a transaction is a bundle of actions. Each action is composed of one spend and one output. +This means we have the same amount of "spends" and "outputs" in one transaction. +If we would like to create a transaction with a different number of spends and outputs, +we need to add "dummy" spends or outputs to balance their count. +A dummy spend or output is a note with a value of zero and a random recipient address. +In the ZK proof, when the value of the spent note is zero, +we do not verify that the corresponding spent note commitment is part of the Merkle tree. + +## Split notes for OrchardZSA + +For OrchardZSA, if the number of inputs exceeds the number of outputs, +we use dummy output notes (as in Orchard) to fill all actions. +Conversely, if the number of outputs exceeds the number of inputs, we use split notes to fill the actions. +In OrchardZSA, ensuring that the AssetBase is correctly created is crucial. +For this reason, split notes are used instead of dummy spent notes. +Split notes are essentially duplicates of actual spent notes, +but with the following differences: +- The nullifier is randomized to prevent it from being treated as double-spending. +- Its value is excluded from the transaction's or bundle's value balance. + +Within the ZK proof, we verify that the commitment of each spent note (including split notes) +is part of the Merkle tree. This ensures that the AssetBase is constructed properly, +a note associated with this AssetBase exists within the Merkle tree. + +For further details about split notes, refer to +[ZIP226](https://github.com/zcash/zips/blob/main/zips/zip-0226.rst). + ## Memo fields Each Orchard action has a memo field for its corresponding output, as with Sprout and Sapling. We did at one point consider having a single Orchard memo field per transaction, and/or having a mechanism for enabling multiple recipients to decrypt the same memo, but these were decided against in order to keep the overall design simpler. + diff --git a/book/src/design/circuit/note-commit.md b/book/src/design/circuit/note-commit.md index 57494aacc..66cf6bf8e 100644 --- a/book/src/design/circuit/note-commit.md +++ b/book/src/design/circuit/note-commit.md @@ -1,4 +1,4 @@ -# NoteCommit +# Orchard NoteCommit ## Message decomposition diff --git a/book/src/design/circuit/zsa-note-commit.md b/book/src/design/circuit/zsa-note-commit.md new file mode 100644 index 000000000..64be86046 --- /dev/null +++ b/book/src/design/circuit/zsa-note-commit.md @@ -0,0 +1,359 @@ +# OrchardZSA NoteCommit + +In the OrchardZSA protocol, the $\NoteCommit$ function is defined as follows: +$$ +\begin{align} +&\mathsf{NoteCommit^{OrchardZSA}_{rcm}}( +\DiversifiedTransmitBaseRepr, +\DiversifiedTransmitPublicRepr, +\ItoLEBSP{64}(\mathsf{v}), +\ItoLEBSP{\BaseLength{Orchard}}(\rho), +\ItoLEBSP{\BaseLength{Orchard}}(\psi), +\mathsf{AssetBase}) = \\ +&\;\;\;\;\; +\begin{cases} +\mathsf{h_{ZEC}} + [\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"}, \texttt{""}) &\text{ if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ +\mathsf{h_{ZSA}} + [\mathsf{rcm}]\,\mathsf{GroupHash}^{\mathbb{P}}(\texttt{"z.cash:Orchard-NoteCommit-r"}, \texttt{""}) &\text{otherwise} +\end{cases} +\end{align} +$$ +where +$$ +\begin{align} +\mathsf{h_{ZEC}} =&\;\;\mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:Orchard-NoteCommit-M"}, \\ +&\;\;\;\;\; +\DiversifiedTransmitBaseRepr \bconcat +\DiversifiedTransmitPublicRepr \bconcat +\ItoLEBSP{64}(\mathsf{v}) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\rho) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\psi)) +\end{align} +$$ +and +$$ +\begin{align} +\mathsf{h_{ZSA}} =&\;\;\mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:ZSA-NoteCommit-M"}, \\ +&\;\;\;\;\; +\DiversifiedTransmitBaseRepr \bconcat +\DiversifiedTransmitPublicRepr \bconcat +\ItoLEBSP{64}(\mathsf{v}) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\rho) \bconcat +\ItoLEBSP{\BaseLength{Orchard}}(\psi) \bconcat +\mathsf{AssetBase}) +\end{align} +$$ +where: +- $\DiversifiedTransmitBaseRepr, \DiversifiedTransmitPublicRepr, \mathsf{AssetBase}$ are representations of + Pallas curve points, with $255$ bits used for the $x$-coordinate and $1$ bit used for + the $y$-coordinate. +- $\rho, \psi$ are Pallas base field elements. +- $\mathsf{v}$ is a $64$-bit value. +- $\BaseLength{Orchard} = 255.$ + +We will only present the updates and additions compared to +[Orchard $\NoteCommit$](./note-commit.md). + +## Message decomposition + +Sinsemilla operates on multiples of 10 bits, so we start by decomposing the message into +chunks: + +$$ +\begin{aligned} +\DiversifiedTransmitBaseRepr &= a \bconcat b_0 \bconcat b_1 \bconcat b_2 \\ + &= (\text{bits 0..=249 of } x(\mathsf{g_d})) \bconcat + (\text{bits 250..=253 of } x(\mathsf{g_d})) \bconcat + (\text{bit 254 of } x(\mathsf{g_d})) \bconcat + (ỹ \text{ bit of } \mathsf{g_d}) \\ +\DiversifiedTransmitPublicRepr &= b_3 \bconcat c \bconcat d_0 \bconcat d_1 \\ + &= (\text{bits 0..=3 of } x(\mathsf{pk_d})) \bconcat + (\text{bits 4..=253 of } x(\mathsf{pk_d})) \bconcat + (\text{bit 254 of } x(\mathsf{pk_d})) \bconcat + (ỹ \text{ bit of } \mathsf{pk_d}) \\ +\ItoLEBSP{64}(v) &= d_2 \bconcat d_3 \bconcat e_0 \\ + &= (\text{bits 0..=7 of } v) \bconcat + (\text{bits 8..=57 of } v) \bconcat + (\text{bits 58..=63 of } v) \\ +\ItoLEBSP{\BaseLength{Orchard}}(\rho) &= e_1 \bconcat f \bconcat g_0 \\ + &= (\text{bits 0..=3 of } \rho) \bconcat + (\text{bits 4..=253 of } \rho) \bconcat + (\text{bit 254 of } \rho) \\ +\ItoLEBSP{\BaseLength{Orchard}}(\psi) &= g_1 \bconcat g_2 \bconcat h_0 \bconcat h_1 \\ + &= (\text{bits 0..=8 of } \psi) \bconcat + (\text{bits 9..=248 of } \psi) \bconcat + (\text{bits 249..=253 of } \psi) \bconcat + (\text{bit 254 of } \psi) \\ +\mathsf{AssetBase} &= h_2^{ZSA} \bconcat i \bconcat j_0 \bconcat j_1 \\ + &= (\text{bits 0..=3 of } x(\mathsf{AssetBase})) \bconcat + (\text{bits 4..=253 of } x(\mathsf{AssetBase})) \bconcat + (\text{bit 254 of } x(\mathsf{AssetBase})) \bconcat + (ỹ \text{ bit of } \mathsf{AssetBase}) \\ +\end{aligned} +$$ + +Then we recompose the chunks into message pieces: + +$$ +\begin{array}{|c|l|} +\hline +\text{Length (bits)} & \text{Piece} \\\hline +250 & a \\ + 10 & b = b_0 \bconcat b_1 \bconcat b_2 \bconcat b_3 \\ +250 & c \\ + 60 & d = d_0 \bconcat d_1 \bconcat d_2 \bconcat d_3 \\ + 10 & e = e_0 \bconcat e_1 \\ +250 & f \\ +250 & g = g_0 \bconcat g_1 \bconcat g_2 \\ + 10 & h = h_0 \bconcat h_1 \bconcat h_2^{ZSA} \\ +250 & i \\ + 10 & j_0 \bconcat j_1 \bconcat j_2 \\ + \hline +\end{array} +$$ + +where $j_2$ is 8 zero bits (corresponding to the padding applied by the Sinsemilla +[$\mathsf{pad}$ function](https://zips.z.cash/protocol/protocol.pdf#concretesinsemillahash)). + +## Message piece decomposition + +In this section, we will only present the updates and additions compared to +[Message piece decomposition for Orchard](./note-commit.md#message-piece-decomposition). + +As $a$, $c$ and $f$, $i$ is also witnessed and constrained outside the gate. + +### $h$ decomposition + +$$\begin{cases} +h^{ZEC} = h_0 \bconcat h_1 \bconcat 0000 \\ +h^{ZSA} = h_0 \bconcat h_1 \bconcat h_2^{ZSA} +\end{cases}$$ +$h^{ZEC}$ and $h^{ZSA}$ have been constrained to be $10$ bits each by the Sinsemilla hash. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|} +\hline + A_6 & A_7 & A_8 & q_{\NoteCommit,h} \\\hline + h^{ZEC} & h_0 & h_1 & 1 \\\hline + h^{ZSA} & h_2^{ZSA} & & 0 \\\hline +\end{array} +$$ + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline + 3 & q_{\NoteCommit,h} \cdot \BoolCheck{h_1} = 0 \\\hline + 2 & q_{\NoteCommit,h} \cdot (h^{ZEC} - (h_0 + h_1 \cdot 2^5)) = 0 \\\hline + 2 & q_{\NoteCommit,h} \cdot (h^{ZSA} - (h_0 + h_1 \cdot 2^5 + h_2^{ZSA} \cdot 2^6)) = 0 \\\hline +\end{array} +$$ + +Outside this gate, we have constrained: +- $\ShortLookupRangeCheck{h_0, 5}$ +- $\ShortLookupRangeCheck{h_2^{ZSA}, 4}$ + +### $j$ decomposition + +$$j = j_0 \bconcat j_1 \bconcat j_2$$ +with $j_2$ is 8 zero bits. + +$j$ has been constrained to be $10$ bits by the $\SinsemillaHash$. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|} +\hline + A_6 & A_7 & A_8 & q_{\NoteCommit,j} \\\hline + j & j_0 & j_1 & 1 \\\hline +\end{array} +$$ + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline + 3 & q_{\NoteCommit,j} \cdot \BoolCheck{j_0} = 0 \\\hline + 3 & q_{\NoteCommit,j} \cdot \BoolCheck{j_1} = 0 \\\hline +2 & q_{\NoteCommit,j} \cdot (j - (j_0 + j_1 \cdot 2)) = 0 \\\hline +\end{array} +$$ + +## Field element checks + +In addition to [field element checks for Orchard NoteCommit](./note-commit.md#field-element-checks), +we have to +- constrain $\ItoLEBSP{\BaseLength{Orchard}}(x(\mathsf{AssetBase}))$ + to be 255-bit value, with top bit $j_0$. +- constrain $\ItoLEBSP{\BaseLength{Orchard}}(x(\mathsf{AssetBase})) = x(\mathsf{AssetBase}) \pmod{q_\mathbb{P}}$ +where $q_\mathbb{P}$ is the Pallas base field modulus. +- check that $\mathsf{AssetBase}$ is indeed canonically-encoded field elements, i.e. +$$\ItoLEBSP{\BaseLength{Orchard}}(x(\mathsf{AssetBase})) < q_\mathbb{P}$$ + +$\mathsf{pk_d}$ and $\mathsf{AssetBase}$ have a similar message piece decomposition. +Thus, we will reuse the $\mathsf{pk_d}$ gates to check those constraints on $\mathsf{AssetBase}$. + +### $x(\mathsf{AssetBase})$ is a Pallas base field element +Recall that $x(\mathsf{AssetBase}) = h_2^{ZSA} + 2^4 \cdot i + 2^{254} \cdot j_0$. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|c|} +\hline + A_6 & A_7 & A_8 & A_9 & q_{\NoteCommit,x(\mathsf{pk_d})} \\\hline +x(\mathsf{AssetBase}) & h_2^{ZSA} & i & z_{i,13} & 1 \\\hline + & j_0 & h_2i' & z_{h_2i',14} & 0 \\\hline +\end{array} +$$ + +where +- $z_{i,13}$ is the index-13 running sum output by $\SinsemillaHash(i)$, +- $h_2i' = h_2^{ZSA} + 2^4 \cdot i + 2^{140} - t_\mathbb{P}$, and +- $z_{h_2i',14}$ is the index-14 running sum output by $\SinsemillaHash(h_2i')$, + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +2 & q_{\NoteCommit,x(\mathsf{AssetBast})} \cdot \left(h_2^{ZSA} + i \cdot 2^4 + j_0 \cdot 2^{254} - x(\mathsf{AssetBase}) \right) = 0 \\\hline +3 & q_{\NoteCommit,x(\mathsf{AssetBase})} \cdot j_0 \cdot z_{i,13} = 0 \\\hline +2 & q_{\NoteCommit,x(\mathsf{AssetBase})} \cdot (h_2^{ZSA} + i \cdot 2^4 + 2^{140} - t_\mathbb{P} - {h_2}i') = 0 \\\hline +3 & q_{\NoteCommit,x(\mathsf{AssetBase})} \cdot j_0 \cdot z_{{h_2}i',14} = 0 \\\hline +\end{array} +$$ + +### Decomposition of $y(\mathsf{AssetBase})$ + +We would like to verify that the following decomposition of $y(\mathsf{AssetBase})$ is correct +$$ +\begin{align} +y &= \textsf{LSB} \bconcat k_0 \bconcat k_1 \bconcat k_2 \bconcat k_3\\ + &= \textsf{LSB} + \bconcat \text{ (bits $1..=9$ of $y$) } + \bconcat \text{ (bits $10..=249$ of $y$) } + \bconcat \text{ (bits $250..=253$ of $y$) } + \bconcat \text{ (bit $254$ of $y$) }, +\end{align} +$$ +where $\textsf{LSB}=j_1$. + +To achieve this, we will use the same gate that is utilized to verify the correctness +of the decompositions of $y(\mathsf{g_d})$ and $y(\mathsf{pk_d})$. + +Let $j = \textsf{LSB} + 2 \cdot k_0 + 2^{10} \cdot k_1$. +We decompose $j$ to be $250$ bits using a strict $25-$word +[ten-bit lookup](../decomposition.md#lookup-decomposition). +The running sum outputs allow us to susbstitute $k_1 = z_{j, 1}.$ + +Recall that $\textsf{LSB} = ỹ(\mathsf{AssetBase})$ was piece input to the +Sinsemilla hash and have already been boolean-constrained. +$k_0$ and $k_2$ are constrained outside this gate to $9$ and $4$ bits respectively. +To constrain the remaining chunks, we use the following constraints: + +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +3 & q_{\NoteCommit,y} \cdot \BoolCheck{k_3} = 0 \\\hline +\end{array} +$$ + +Then, to check that the decomposition was correct: +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +2 & q_{\NoteCommit,y} \cdot \left(j - (\textsf{LSB} + k_0 \cdot 2 + k_1 \cdot 2^{10}) \right) = 0 \\\hline +2 & q_{\NoteCommit,y} \cdot \left(y - (j + k_2 \cdot 2^{250} + k_3 \cdot 2^{254}) \right) = 0 \\\hline +\end{array} +$$ + +### $y(\mathsf{AssetBase})$ is a Pallas base field element +Recall that +$$ +\begin{align} +y &= ỹ \bconcat k_0 \bconcat k_1 \bconcat k_2 \bconcat k_3\\ + &= ỹ + \bconcat \text{ (bits $1..=9$ of $y$) } + \bconcat \text{ (bits $10..=249$ of $y$) } + \bconcat \text{ (bits $250..=253$ of $y$) } + \bconcat \text{ (bit $254$ of $y$) }, +\end{align} +$$ +Let $\begin{cases} +j = \textsf{LSB} + 2 \cdot k_0 + 2^{10} \cdot k_1 \\ +j' = j + 2^{130} - t_\mathbb{P} +\end{cases}$. + +#### Region layout +$$ +\begin{array}{|c|c|c|c|c|c|} +\hline +A_5 & A_6 & A_7 & A_8 & A_9 & q_{\NoteCommit,y} \\\hline + y & ỹ & k_0 & k_2 & k_3 & 1 \\\hline + j & k_1 & z_{j,13} & j' & z_{j',13} & 0 \\\hline +\end{array} +$$ +where $z_{j,13}$ (resp. $z_{j', 13}$) is the index-13 running sum output by the $10$-bit lookup +decomposition of $j$ (resp. $j'$). + +#### Constraints +$$ +\begin{array}{|c|l|} +\hline +\text{Degree} & \text{Constraint} \\\hline +3 & q_{\NoteCommit,y} \cdot k_3 \cdot k_2 = 0 \\\hline +3 & q_{\NoteCommit,y} \cdot k_3 \cdot z_{j,13} = 0 \\\hline +2 & q_{\NoteCommit,y} \cdot (j + 2^{130} - t_\mathbb{P} - j') = 0 \\\hline +3 & q_{\NoteCommit,y} \cdot k_3 \cdot z_{j',13} = 0 \\\hline +\end{array} +$$ + +Outside this gate, we have constrained: +- $\ShortLookupRangeCheck{k_0, 9}$ +- $\ShortLookupRangeCheck{k_2, 4}$ + +## $\mathsf{SinsemillaHashToPoint}$ evaluations +To evaluate our OrchardZSA $\NoteCommit$, we must evalute +$\mathsf{h} = \begin{cases} \mathsf{h_{ZEC}} &\text{ if } \mathsf{AssetBase} = \mathcal{V}^{\mathsf{Orchard}} \\ +\mathsf{h_{ZSA}} &\text{ otherwise} \end{cases}$. + +We observe that the messages to hash in $\mathsf{h_{ZEC}}$ and $\mathsf{h_{ZSA}}$ have a similar prefix +$$\begin{cases} +\mathsf{h_{ZEC}} = \mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:Orchard-NoteCommit-M"}, +\mathsf{prefix} \bconcat \mathsf{suffix_{ZEC}}) \\ +\mathsf{h_{ZSA}} = \mathsf{SinsemillaHashToPoint}(\texttt{"z.cash:ZSA-NoteCommit-M"}, +\mathsf{prefix} \bconcat \mathsf{suffix_{ZSA}}) +\end{cases}$$ +where +$$\begin{cases} +\mathsf{prefix} = a \bconcat b \bconcat c \bconcat d \bconcat e \bconcat f \bconcat g \\ +\mathsf{suffix_{ZEC}} = h_0 \bconcat h_1 \bconcat 0000 \\ +\mathsf{suffix_{ZSA}} = h_0 \bconcat h_1 \bconcat h_2^{ZSA} \bconcat i \bconcat j +\end{cases}$$ + +We will optimize the circuit by leveraging the fact that their respective messages share +a common prefix. More precisely, the circuit will contain the following steps: +1. Evaluate $Q_{init}$ the initial state of the hash function thanks to a multiplexer gate +$$ \mathcal{Q}_{init} = MUX(\mathcal{Q}_{ZSA}, \mathcal{Q}_{ZEC}, \mathsf{AssetBase} == \mathcal{V}^{\mathsf{Orchard}})$$ +where +$$\begin{cases} +\mathcal{Q}_{ZEC} = \mathcal{Q}(\texttt{"z.cash:Orchard-NoteCommit-M"}) \\ +\mathcal{Q}_{ZSA} = \mathcal{Q}(\texttt{"z.cash:ZSA-NoteCommit-M"}) +\end{cases}$$ +2. Evaluate $\mathsf{h_{common}}$ which is equal to the Sinsemilla hash evaluation from the inital +point $\mathcal{Q}_{init}$ with the message $\mathsf{prefix}$ +$$\mathsf{h_{common}} = \mathsf{SinsemillaHash}(\mathcal{Q}_{init}, \mathsf{prefix})$$ +3. Evaluate $\mathsf{h_{ZSA}}$ and $\mathsf{h_{ZEC}}$ which are equal to the Sinsemilla hash evaluations from the initial point $h_{common}$ with the message $\mathsf{suffix_{ZSA}}$ and $\mathsf{suffix_{ZEC}}$ respectively +$$\begin{cases} +\mathsf{h_{ZEC}} = \mathsf{SinsemillaHash}(\mathsf{h_{common}}, \mathsf{suffix_{ZEC}}) \\ +\mathsf{h_{ZSA}} = \mathsf{SinsemillaHash}(\mathsf{h_{common}}, \mathsf{suffix_{ZSA}}) +\end{cases}$$ +4. Select the desired hash thanks to a multiplexer gate +$$ \mathsf{h} = MUX(\mathsf{h_{ZSA}}, \mathsf{h_{ZEC}}, \mathsf{AssetBase} == \mathcal{V}^{\mathsf{Orchard}})$$ + +![](./zsa-note-commit.png) + diff --git a/book/src/design/circuit/zsa-note-commit.png b/book/src/design/circuit/zsa-note-commit.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfea04d7f38182740e2a9197c178ec8f7789f6 GIT binary patch literal 1487216 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%0AyufCvO%P1l;}Ec>C?w>UAUN)990$9%`i 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

-7}-w!FjjP2h2N|2zH z+2PWsv>5~8BkM?j%p+V)wXR|M)VYTjPRum|uNs25N9gy~Mb#$shlUAQx0@H4fm?b- z^5RCnV@(OK+nRmO9}_sTjff{wHc>baEA&;uctwyrz_3_Aik4gavG#+iwOp!bc+A%H zy{WHHH{WVHCaC!osYX6LG!zX`9uT(pMpv_U;V#+1cL#lYu~YfjU(H(H95c3qc~(Z1r;}vljrh_gLcgDM}oaO^K!Q zdS(h~77}Rr5Q1dDh7_O<$>3B#H9CPR+9A6S6NNIt!Zk{(3j`G{fiv-xU z04+Go%Fxu*)ID})a&op<5yAyXrU`UQfpKC3)33^w9^3t`dj-}qibKv{B4eS)y?K3) z4XG>vy!=JLd6BFe_myAlesuC)Wu~Q@Wi-FKX}7@EvgAag$V85{uL4;3r(r2Yv=m?$ zqr_S8LRJ{9>H|_B+xJMPn`Hv;;L5vrAe798s&VJ_h8u%d6)d1`L;MV-W`fiO)PV{s zcIJF~_oqDxkta4EFa+q2IZRRy zun9%+`;Kf3s=TNBaO{v<%RWOwQ>)>E#)LvS)-?K=92WqwTHRy)U27%^8w%gLS`5e> zND6ZZoM>wnf}&AQ&OdY6#jXd=U85HZIgd~RdU5KicH!wQpuQkT|#9k#*|H-w|d|EepB*m z@yR3Hr&C7tWl$Y6#xmx=tMYC#vW*eAOUwTcL#6#Q(H4QgLIp#4*h9(i=OxInTi2c>y<Oj1QYst3@S^h1 zIb$bF_fmG51AeW)s;HC({?A<~(ex2IJ-{tt2e_VWLloOG<_&@!S~&C?+nr`(M~%br zxPyTgU_Ld^b?k!j2xFjaISW}tDClJg!0W)f=~K^b$`o~(dqT^VY!*6tuyTD(YL>_> z2U8-{@`FijtXBFEHbtRbh&guMBcN?#`qP9D*@K0F@!;l%TRkn2rvx2F7%s

uZw7F+WxC5I$Lg0e1$qY=~r4?mRoCtvu2lFT{ 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čIUj?eyO(9D$~*+irYbvQ5993qUbDF`)d0y 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

tc%QjEF-?_aMxd8Qr#f ziT#-sncY4u7S4$pLphl5-xTi$BQ zOXoU4?v9wv^Bswa6|M;kxjYm8(^#6L6+2MhZ2Uxe1*tig_Axqozb<0TCFp44#2KZF zyl?~=c19#br!gFg-@Qf&J*L^r#_dpZ^iJy*I9@FlbyAd@*}0rK(v9179h)y^=ZB3& z2gPDi%rifqHOjeV5fY6+sfZ<-(%AEkaR)=XG5soI7u@Zx8=av$Y6jZ>W556I*l?AJ z+uA|JGnZNM%MXnkB8$>ettBZ{A+f^6N4ElW{J3pR1-H+1;FEhKXE?*f3vXvwD`N@ zUpPt?S}&%{oZX{bn^PVRmo$@5TSZohp5M*7Y)Ue^U4e3{Lo9A|BJ)6nThxYzmX;z4 z`@ScdIQE%aH&w+bdsnULDcW*W(qH~R?7ew7o7>($Y@cDbdv`#0TdIalX`9wit)W_y zbI>Y^ma2+rm#UJ6nn?^jPZc$`rnJU~3PnQ=NlcOMZ7L~BNDz`5gGhpqAQJDb``P>S zoU`}!?DwDdy{_M{_jQqVujF3C=l-tmTHj%P7YH2;pE|RM^1Nv7lw;A@d?A|I)Oo_~ z;@YUGsl8j#ls$+rlqwEUDhVF(v%OiB3YUTI)2&yBV9 zpjRZ-14Ysk(wzQQWIU4P<%ORO2fvpg9}jOke;?5UiYw0^X~ZoVCO2^cc_aq{RJ<

TX61fET}mVf>MNc-vA3Jg;W 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 z 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 K`JAS@Rylfke?k7? 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

Wo+*vqTyD`EKGj$|f$t<4=2XG6 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�xUiuw^ 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⪙xuCMJLs~HCZT=Ya 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

+Rr5Ms$ltX{=H?fE3@O6YoYag{d36u_ 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%0A4nigmEc>VzvOoAX>#cE{yAU6(cZ9X7+) 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%0A3~!>SfPTa{&1jRuf~ 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