consensus: add NU plumbing to block,tx,script verifiers
Closes #1367 by propagating the network upgrade through the service requests.
This commit is contained in:
parent
2e0ed94b22
commit
61b3286085
|
@ -25,7 +25,6 @@ use tracing::Instrument;
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
block::{self, Block},
|
block::{self, Block},
|
||||||
parameters::Network,
|
parameters::Network,
|
||||||
parameters::NetworkUpgrade,
|
|
||||||
transparent,
|
transparent,
|
||||||
work::equihash,
|
work::equihash,
|
||||||
};
|
};
|
||||||
|
@ -83,9 +82,8 @@ where
|
||||||
S::Future: Send + 'static,
|
S::Future: Send + 'static,
|
||||||
{
|
{
|
||||||
pub fn new(network: Network, state_service: S) -> Self {
|
pub fn new(network: Network, state_service: S) -> Self {
|
||||||
let branch = NetworkUpgrade::Sapling.branch_id().unwrap();
|
let transaction_verifier =
|
||||||
let script_verifier = script::Verifier::new(state_service.clone(), branch);
|
transaction::Verifier::new(network, script::Verifier::new(state_service.clone()));
|
||||||
let transaction_verifier = transaction::Verifier::new(script_verifier);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
network,
|
network,
|
||||||
|
@ -176,6 +174,7 @@ where
|
||||||
.call(transaction::Request::Block {
|
.call(transaction::Request::Block {
|
||||||
transaction: transaction.clone(),
|
transaction: transaction.clone(),
|
||||||
known_utxos: known_utxos.clone(),
|
known_utxos: known_utxos.clone(),
|
||||||
|
height,
|
||||||
});
|
});
|
||||||
async_checks.push(rsp);
|
async_checks.push(rsp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{collections::HashMap, future::Future, pin::Pin, sync::Arc};
|
||||||
|
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
|
||||||
use zebra_chain::{parameters::ConsensusBranchId, transaction::Transaction, transparent};
|
use zebra_chain::{parameters::NetworkUpgrade, transaction::Transaction, transparent};
|
||||||
use zebra_state::Utxo;
|
use zebra_state::Utxo;
|
||||||
|
|
||||||
use crate::BoxError;
|
use crate::BoxError;
|
||||||
|
@ -21,27 +21,34 @@ use crate::BoxError;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Verifier<ZS> {
|
pub struct Verifier<ZS> {
|
||||||
state: ZS,
|
state: ZS,
|
||||||
branch: ConsensusBranchId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ZS> Verifier<ZS> {
|
impl<ZS> Verifier<ZS> {
|
||||||
pub fn new(state: ZS, branch: ConsensusBranchId) -> Self {
|
pub fn new(state: ZS) -> Self {
|
||||||
Self { state, branch }
|
Self { state }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A script verification request.
|
/// A script verification request.
|
||||||
///
|
|
||||||
/// Ideally, this would supply only an `Outpoint` and the unlock script,
|
|
||||||
/// rather than the entire `Transaction`, but we call a C++
|
|
||||||
/// implementation, and its FFI requires the entire transaction.
|
|
||||||
/// At some future point, we could investigate reducing the size of the
|
|
||||||
/// request.
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
|
/// Ideally, this would supply only an `Outpoint` and the unlock script,
|
||||||
|
/// rather than the entire `Transaction`, but we call a C++
|
||||||
|
/// implementation, and its FFI requires the entire transaction.
|
||||||
|
///
|
||||||
|
/// This causes quadratic script verification behavior, so
|
||||||
|
/// at some future point, we need to reform this data.
|
||||||
pub transaction: Arc<Transaction>,
|
pub transaction: Arc<Transaction>,
|
||||||
pub input_index: usize,
|
pub input_index: usize,
|
||||||
|
/// A set of additional UTXOs known in the context of this verification request.
|
||||||
|
///
|
||||||
|
/// This allows specifying additional UTXOs that are not already known to the chain state.
|
||||||
pub known_utxos: Arc<HashMap<transparent::OutPoint, Utxo>>,
|
pub known_utxos: Arc<HashMap<transparent::OutPoint, Utxo>>,
|
||||||
|
/// The network upgrade active in the context of this verification request.
|
||||||
|
///
|
||||||
|
/// Because the consensus branch ID changes with each network upgrade,
|
||||||
|
/// it has to be specified on a per-request basis.
|
||||||
|
pub upgrade: NetworkUpgrade,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ZS> tower::Service<Request> for Verifier<ZS>
|
impl<ZS> tower::Service<Request> for Verifier<ZS>
|
||||||
|
@ -68,13 +75,16 @@ where
|
||||||
transaction,
|
transaction,
|
||||||
input_index,
|
input_index,
|
||||||
known_utxos,
|
known_utxos,
|
||||||
|
upgrade,
|
||||||
} = req;
|
} = req;
|
||||||
let input = &transaction.inputs()[input_index];
|
let input = &transaction.inputs()[input_index];
|
||||||
|
let branch_id = upgrade
|
||||||
|
.branch_id()
|
||||||
|
.expect("post-Sapling NUs have a consensus branch ID");
|
||||||
|
|
||||||
match input {
|
match input {
|
||||||
transparent::Input::PrevOut { outpoint, .. } => {
|
transparent::Input::PrevOut { outpoint, .. } => {
|
||||||
let outpoint = *outpoint;
|
let outpoint = *outpoint;
|
||||||
let branch_id = self.branch;
|
|
||||||
|
|
||||||
let span = tracing::trace_span!("script", ?outpoint);
|
let span = tracing::trace_span!("script", ?outpoint);
|
||||||
let query =
|
let query =
|
||||||
|
|
|
@ -14,7 +14,8 @@ use tower::{Service, ServiceExt};
|
||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
|
||||||
use zebra_chain::{
|
use zebra_chain::{
|
||||||
parameters::NetworkUpgrade,
|
block,
|
||||||
|
parameters::{Network, NetworkUpgrade},
|
||||||
transaction::{self, HashType, Transaction},
|
transaction::{self, HashType, Transaction},
|
||||||
transparent,
|
transparent,
|
||||||
};
|
};
|
||||||
|
@ -28,6 +29,7 @@ mod check;
|
||||||
/// Asynchronous transaction verification.
|
/// Asynchronous transaction verification.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Verifier<ZS> {
|
pub struct Verifier<ZS> {
|
||||||
|
network: Network,
|
||||||
script_verifier: script::Verifier<ZS>,
|
script_verifier: script::Verifier<ZS>,
|
||||||
// spend_verifier: groth16::Verifier,
|
// spend_verifier: groth16::Verifier,
|
||||||
// output_verifier: groth16::Verifier,
|
// output_verifier: groth16::Verifier,
|
||||||
|
@ -40,8 +42,11 @@ where
|
||||||
ZS::Future: Send + 'static,
|
ZS::Future: Send + 'static,
|
||||||
{
|
{
|
||||||
// XXX: how should this struct be constructed?
|
// XXX: how should this struct be constructed?
|
||||||
pub fn new(script_verifier: script::Verifier<ZS>) -> Self {
|
pub fn new(network: Network, script_verifier: script::Verifier<ZS>) -> Self {
|
||||||
Self { script_verifier }
|
Self {
|
||||||
|
network,
|
||||||
|
script_verifier,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,15 +59,22 @@ where
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
/// Verify the supplied transaction as part of a block.
|
/// Verify the supplied transaction as part of a block.
|
||||||
Block {
|
Block {
|
||||||
|
/// The transaction itself.
|
||||||
transaction: Arc<Transaction>,
|
transaction: Arc<Transaction>,
|
||||||
/// Additional UTXOs which are known at the time of verification.
|
/// Additional UTXOs which are known at the time of verification.
|
||||||
known_utxos: Arc<HashMap<transparent::OutPoint, zs::Utxo>>,
|
known_utxos: Arc<HashMap<transparent::OutPoint, zs::Utxo>>,
|
||||||
|
/// The height of the block containing this transaction, used to
|
||||||
|
/// determine the applicable network upgrade.
|
||||||
|
height: block::Height,
|
||||||
},
|
},
|
||||||
/// Verify the supplied transaction as part of the mempool.
|
/// Verify the supplied transaction as part of the mempool.
|
||||||
Mempool {
|
Mempool {
|
||||||
|
/// The transaction itself.
|
||||||
transaction: Arc<Transaction>,
|
transaction: Arc<Transaction>,
|
||||||
/// Additional UTXOs which are known at the time of verification.
|
/// Additional UTXOs which are known at the time of verification.
|
||||||
known_utxos: Arc<HashMap<transparent::OutPoint, zs::Utxo>>,
|
known_utxos: Arc<HashMap<transparent::OutPoint, zs::Utxo>>,
|
||||||
|
/// The active NU in the context of this verification.
|
||||||
|
upgrade: NetworkUpgrade,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,15 +103,20 @@ where
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx, known_utxos) = match req {
|
let (tx, known_utxos, upgrade) = match req {
|
||||||
Request::Block {
|
Request::Block {
|
||||||
transaction,
|
transaction,
|
||||||
known_utxos,
|
known_utxos,
|
||||||
} => (transaction, known_utxos),
|
height,
|
||||||
|
} => {
|
||||||
|
let upgrade = NetworkUpgrade::current(self.network, height);
|
||||||
|
(transaction, known_utxos, upgrade)
|
||||||
|
}
|
||||||
Request::Mempool {
|
Request::Mempool {
|
||||||
transaction,
|
transaction,
|
||||||
known_utxos,
|
known_utxos,
|
||||||
} => (transaction, known_utxos),
|
upgrade,
|
||||||
|
} => (transaction, known_utxos, upgrade),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut redjubjub_verifier = crate::primitives::redjubjub::VERIFIER.clone();
|
let mut redjubjub_verifier = crate::primitives::redjubjub::VERIFIER.clone();
|
||||||
|
@ -135,6 +152,7 @@ where
|
||||||
// feed all of the inputs to the script verifier
|
// feed all of the inputs to the script verifier
|
||||||
for input_index in 0..inputs.len() {
|
for input_index in 0..inputs.len() {
|
||||||
let rsp = script_verifier.ready_and().await?.call(script::Request {
|
let rsp = script_verifier.ready_and().await?.call(script::Request {
|
||||||
|
upgrade,
|
||||||
known_utxos: known_utxos.clone(),
|
known_utxos: known_utxos.clone(),
|
||||||
transaction: tx.clone(),
|
transaction: tx.clone(),
|
||||||
input_index,
|
input_index,
|
||||||
|
@ -146,10 +164,11 @@ where
|
||||||
|
|
||||||
check::has_inputs_and_outputs(&tx)?;
|
check::has_inputs_and_outputs(&tx)?;
|
||||||
|
|
||||||
|
// TODO: rework this code
|
||||||
let sighash = tx.sighash(
|
let sighash = tx.sighash(
|
||||||
NetworkUpgrade::Sapling, // TODO: pass this in
|
upgrade,
|
||||||
HashType::ALL, // TODO: check these
|
HashType::ALL, // TODO: check these
|
||||||
None, // TODO: check these
|
None, // TODO: check these
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(joinsplit_data) = joinsplit_data {
|
if let Some(joinsplit_data) = joinsplit_data {
|
||||||
|
|
Loading…
Reference in New Issue