From 01ea87a03948e6ac0b0166be30302b30be5d3034 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Thu, 8 Jul 2021 09:36:36 -0300 Subject: [PATCH] Verify orchard spend auth (#2442) --- zebra-consensus/src/transaction.rs | 41 +++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/zebra-consensus/src/transaction.rs b/zebra-consensus/src/transaction.rs index b8e671d7..da73edab 100644 --- a/zebra-consensus/src/transaction.rs +++ b/zebra-consensus/src/transaction.rs @@ -15,7 +15,7 @@ use tower::{Service, ServiceExt}; use tracing::Instrument; use zebra_chain::{ - block, + block, orchard, parameters::{Network, NetworkUpgrade}, primitives::Groth16Proof, sapling, @@ -209,6 +209,7 @@ where Transaction::V5 { inputs, sapling_shielded_data, + orchard_shielded_data, .. } => Self::verify_v5_transaction( req, @@ -216,6 +217,7 @@ where script_verifier, inputs, sapling_shielded_data, + orchard_shielded_data, )?, }; @@ -298,12 +300,15 @@ where /// - the `network` to consider when verifying /// - the `script_verifier` to use for verifying the transparent transfers /// - the transparent `inputs` in the transaction + /// - the sapling shielded data of the transaction, if any + /// - the orchard shielded data of the transaction, if any fn verify_v5_transaction( request: Request, network: Network, script_verifier: script::Verifier, inputs: &[transparent::Input], sapling_shielded_data: &Option>, + orchard_shielded_data: &Option, ) -> Result { let transaction = request.transaction(); let upgrade = request.upgrade(network); @@ -320,6 +325,10 @@ where .and(Self::verify_sapling_shielded_data( sapling_shielded_data, &shielded_sighash, + )?) + .and(Self::verify_orchard_shielded_data( + orchard_shielded_data, + &shielded_sighash, )?); // TODO: @@ -533,6 +542,36 @@ where Ok(async_checks) } + + /// Verifies a transaction's Orchard shielded data. + fn verify_orchard_shielded_data( + orchard_shielded_data: &Option, + shielded_sighash: &blake2b_simd::Hash, + ) -> Result { + let mut async_checks = AsyncChecks::new(); + + if let Some(orchard_shielded_data) = orchard_shielded_data { + for authorized_action in orchard_shielded_data.actions.iter().cloned() { + let (action, spend_auth_sig) = authorized_action.into_parts(); + // Consensus rule: The spend authorization signature + // MUST be a valid SpendAuthSig signature over + // SigHash using rk as the validating key. + // + // Queue the validation of the RedPallas spend + // authorization signature for each Action + // description while adding the resulting future to + // our collection of async checks that (at a + // minimum) must pass for the transaction to verify. + async_checks.push( + primitives::redpallas::VERIFIER + .clone() + .oneshot((action.rk, spend_auth_sig, &shielded_sighash).into()), + ); + } + } + + Ok(async_checks) + } } /// A set of unordered asynchronous checks that should succeed.