Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Async Script Verification RFC #961

Merged
merged 12 commits into from
Oct 14, 2020
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
# Vscode detrius
.vscode/
.zebra-state/
.cargo/
2 changes: 1 addition & 1 deletion zebra-chain/src/transaction/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use super::Transaction;
///
/// TODO: I'm pretty sure this is also a SHA256d hash but I haven't
/// confirmed it yet.
#[derive(Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Copy, Clone, Eq, PartialEq, Serialize, Deserialize, Hash)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct Hash(pub [u8; 32]);

Expand Down
2 changes: 1 addition & 1 deletion zebra-chain/src/transparent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl AsRef<[u8]> for CoinbaseData {
/// OutPoint
///
/// A particular transaction output reference.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
#[cfg_attr(test, derive(Arbitrary))]
pub struct OutPoint {
/// References the transaction that contains the UTXO being spent.
Expand Down
1 change: 1 addition & 0 deletions zebra-state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ tower = "0.3.1"
tracing = "0.1"
tracing-error = "0.1.2"
thiserror = "1.0.20"
tokio = "0.2.22"

[dev-dependencies]
zebra-test = { path = "../zebra-test/" }
Expand Down
1 change: 1 addition & 0 deletions zebra-state/src/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ impl Service<Request> for InMemoryState {

async move { Ok(Response::BlockLocator { block_locator }) }.boxed()
}
Request::AwaitUtxo(_) => unimplemented!("this Service is being removed"),
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions zebra-state/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use tower::{Service, ServiceExt};
use zebra_chain::{
block::{self, Block},
parameters::Network,
transparent,
};

pub mod in_memory;
Expand Down Expand Up @@ -126,6 +127,11 @@ pub enum Request {
/// The hash to check against the current chain
hash: block::Hash,
},
/// Request a UTXO identified by the given Outpoint
AwaitUtxo(
/// The outpoint identifying with the requested UTXO
transparent::OutPoint,
),
}

#[derive(Clone, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -158,6 +164,11 @@ pub enum Response {
/// The number of blocks above the given block in the current best chain
Option<u32>,
),
/// The response to a `AwaitUtxo` request
Utxo(
/// The transparent::Output representing the requested UTXO
transparent::Output,
),
}

/// Get the heights of the blocks for constructing a block_locator list
Expand Down
3 changes: 3 additions & 0 deletions zebra-state/src/on_disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use zebra_chain::{
parameters::Network,
};

mod utxo;

/// Type alias of our wrapped service
pub type StateService = Buffer<BoxService<Request, Response, Error>, Request>;

Expand Down Expand Up @@ -211,6 +213,7 @@ impl Service<Request> for SledState {
}
.boxed()
}
Request::AwaitUtxo(_) => todo!("blocked waiting for chain state RFC implementation"),
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions zebra-state/src/on_disk/utxo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#![allow(dead_code)]
use crate::{Error, Response};
use std::collections::HashMap;
use std::future::Future;
use tokio::sync::broadcast;
use zebra_chain::transparent;

pub(super) struct PendingUtxos(
HashMap<transparent::OutPoint, broadcast::Sender<transparent::Output>>,
);

impl PendingUtxos {
pub(super) fn queue(
&mut self,
outpoint: transparent::OutPoint,
) -> impl Future<Output = Result<Response, Error>> {
let mut receiver = self
.0
.entry(outpoint)
.or_insert_with(|| {
let (sender, _) = broadcast::channel(1);
sender
})
.subscribe();

async move {
receiver
.recv()
.await
.map(Response::Utxo)
.map_err(Error::from)
}
}

pub(super) fn respond(&mut self, outpoint: transparent::OutPoint, output: transparent::Output) {
if let Some(sender) = self.0.remove(&outpoint) {
let _ = sender.send(output);
}
}

pub(super) fn prune(&mut self) {
self.0.retain(|_, chan| chan.receiver_count() > 0);
}
}