state: fill in RFC5-style Request, Response enums

The test transcripts need to be rewritten, so they are removed for now.
This commit is contained in:
Henry de Valence 2020-09-09 17:59:58 -07:00
parent 98d5351206
commit 070013439e
5 changed files with 157 additions and 189 deletions

View File

@ -23,7 +23,7 @@ use memory_state::MemoryState;
use sled_state::SledState;
pub use config::Config;
pub use request::Request;
pub use request::{HashOrHeight, Request};
pub use response::Response;
pub use service::init;

View File

@ -1,32 +1,110 @@
use std::sync::Arc;
use zebra_chain::block::{self, Block};
use zebra_chain::{
block::{self, Block},
transaction,
};
// Allow *only* this unused import, so that rustdoc link resolution
// will work with inline links.
#[allow(unused_imports)]
use crate::Response;
/// Identify a block by hash or height.
///
/// This enum implements `From` for [`block::Hash`] and [`block::Height`],
/// so it can be created using `hash.into()` or `height.into()`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum HashOrHeight {
/// A block identified by hash.
Hash(block::Hash),
/// A block identified by height.
Height(block::Height),
}
impl From<block::Hash> for HashOrHeight {
fn from(hash: block::Hash) -> Self {
Self::Hash(hash)
}
}
impl From<block::Height> for HashOrHeight {
fn from(hash: block::Height) -> Self {
Self::Height(hash)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
/// A query about or modification to the chain state.
///
/// TODO: replace these variants with the ones in RFC5.
pub enum Request {
// TODO(jlusby): deprecate in the future based on our validation story
/// Add a block to the zebra-state
AddBlock {
/// The block to be added to the state
/// Performs contextual validation of the given block, committing it to the
/// state if successful.
///
/// Returns [`Response::Committed`] with the hash of the newly
/// committed block, or an error.
///
/// This request can be made out-of-order; the state service will buffer it
/// until its parent is ready.
CommitBlock {
/// The block to commit to the state.
block: Arc<Block>,
// TODO: add these parameters when we can compute anchors.
// sprout_anchor: sprout::tree::Root,
// sapling_anchor: sapling::tree::Root,
},
/// Get a block from the zebra-state
GetBlock {
/// The hash used to identify the block
hash: block::Hash,
},
/// Get a block locator list for the current best chain
GetBlockLocator {
/// The genesis block of the current best chain
genesis: block::Hash,
},
/// Get the block that is the tip of the current chain
GetTip,
/// Ask the state if the given hash is part of the current best chain
GetDepth {
/// The hash to check against the current chain
hash: block::Hash,
/// Commit a finalized block to the state, skipping contextual validation.
/// This is exposed for use in checkpointing, which produces finalized
/// blocks.
///
/// Returns [`Response::Committed`] with the hash of the newly
/// committed block, or an error.
///
/// This request can be made out-of-order; the state service will buffer it
/// until its parent is ready.
CommitFinalizedBlock {
/// The block to commit to the state.
block: Arc<Block>,
// TODO: add these parameters when we can compute anchors.
// sprout_anchor: sprout::tree::Root,
// sapling_anchor: sapling::tree::Root,
},
/// Computes the depth in the best chain of the block identified by the given hash.
///
/// Returns
///
/// * [`Response::Depth(Some(depth))`](Response::Depth) if the block is in the main chain;
/// * [`Response::Depth(None)`](Response::Depth) otherwise.
Depth(block::Hash),
/// Returns [`Response::Tip`] with the current best chain tip.
Tip,
/// Computes a block locator object based on the current chain state.
///
/// Returns [`Response::BlockLocator`] with hashes starting
/// from the current chain tip and reaching backwards towards the genesis
/// block. The first hash is the current chain tip. The last hash is the tip
/// of the finalized portion of the state. If the state is empty, the block
/// locator is also empty.
BlockLocator,
/// Looks up a transaction by hash.
///
/// Returns
///
/// * [`Response::Transaction(Some(Arc<Transaction>))`](Response::Transaction) if the transaction is known;
/// * [`Response::Transaction(None)`](Response::Transaction) otherwise.
Transaction(transaction::Hash),
/// Looks up a block by hash or height.
///
/// Returns
///
/// * [`Response::Block(Some(Arc<Block>))`](Response::Block) if the block is known;
/// * [`Response::Block(None)`](Response::Transaction) otherwise.
///
/// Note: the [`HashOrHeight`] can be constructed from a [`block::Hash`] or
/// [`block::Height`] using `.into()`.
Block(HashOrHeight),
}

View File

@ -1,34 +1,33 @@
use std::sync::Arc;
use zebra_chain::block::{self, Block};
use zebra_chain::{
block::{self, Block},
transaction::Transaction,
};
// Allow *only* this unused import, so that rustdoc link resolution
// will work with inline links.
#[allow(unused_imports)]
use crate::Request;
#[derive(Clone, Debug, PartialEq, Eq)]
/// A response to a state [`Request`](super::Request).
/// A response to a state [`Request`].
pub enum Response {
/// The response to a `AddBlock` request indicating a block was successfully
/// added to the state
Added {
/// The hash of the block that was added
hash: block::Hash,
},
/// The response to a `GetBlock` request by hash
Block {
/// The block that was requested
block: Arc<Block>,
},
/// The response to a `GetBlockLocator` request
BlockLocator {
/// The set of blocks that make up the block locator
block_locator: Vec<block::Hash>,
},
/// The response to a `GetTip` request
Tip {
/// The hash of the block at the tip of the current chain
hash: block::Hash,
},
/// The response to a `Contains` request indicating that the given has is in
/// the current best chain
Depth(
/// The number of blocks above the given block in the current best chain
Option<u32>,
),
/// Response to [`Request::CommitBlock`] indicating that a block was
/// successfully committed to the state.
Committed(block::Hash),
/// Response to [`Request::Depth`] with the depth of the specified block.
Depth(Option<block::Height>),
/// Response to [`Request::Tip`] with the current best chain tip.
Tip(Option<block::Hash>),
/// Response to [`Request::BlockLocator`] with a block locator object.
BlockLocator(Vec<block::Hash>),
/// Response to [`Request::Transaction`] with the specified transaction.
Transaction(Option<Arc<Transaction>>),
/// Response to [`Request::Block`] with the specified block.
Block(Option<Arc<Block>>),
}

View File

@ -6,7 +6,7 @@ use std::{
use tower::{buffer::Buffer, util::BoxService, Service};
use zebra_chain::parameters::Network;
use crate::{BoxError, Config, MemoryState, Request, Response, SledState};
use crate::{BoxError, Config, HashOrHeight, MemoryState, Request, Response, SledState};
struct StateService {
/// Holds data relating to finalized chain state.
@ -35,11 +35,14 @@ impl Service<Request> for StateService {
fn call(&mut self, req: Request) -> Self::Future {
match req {
Request::AddBlock { block } => unimplemented!(),
Request::GetBlock { hash } => unimplemented!(),
Request::GetTip => unimplemented!(),
Request::GetDepth { hash } => unimplemented!(),
Request::GetBlockLocator { genesis } => unimplemented!(),
Request::CommitBlock { block } => unimplemented!(),
Request::CommitFinalizedBlock { block } => unimplemented!(),
Request::Depth(hash) => unimplemented!(),
Request::Tip => unimplemented!(),
Request::BlockLocator => unimplemented!(),
Request::Transaction(hash) => unimplemented!(),
Request::Block(HashOrHeight::Hash(hash)) => unimplemented!(),
Request::Block(HashOrHeight::Height(height)) => unimplemented!(),
}
}
}

View File

@ -7,145 +7,43 @@ use zebra_test::transcript::{TransError, Transcript};
use zebra_state::*;
static ADD_BLOCK_TRANSCRIPT_MAINNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
static COMMIT_FINALIZED_BLOCK_MAINNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
Lazy::new(|| {
let block: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
.unwrap()
.into();
let hash = block.as_ref().into();
let block2 = block.clone();
let hash = block.hash();
vec![
(
Request::AddBlock {
block: block.clone(),
},
Ok(Response::Added { hash }),
Request::CommitFinalizedBlock { block },
Ok(Response::Committed(hash)),
),
(
Request::Block(hash.into()),
Ok(Response::Block(Some(block2))),
),
(Request::GetBlock { hash }, Ok(Response::Block { block })),
]
});
static ADD_BLOCK_TRANSCRIPT_TESTNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
static COMMIT_FINALIZED_BLOCK_TESTNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
Lazy::new(|| {
let block: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
.unwrap()
.into();
let hash = block.as_ref().into();
let block2 = block.clone();
let hash = block.hash();
vec![
(
Request::AddBlock {
block: block.clone(),
},
Ok(Response::Added { hash }),
),
(Request::GetBlock { hash }, Ok(Response::Block { block })),
]
});
static GET_TIP_ADD_ORDERED_TRANSCRIPT_MAINNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
Lazy::new(|| {
let block0: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
.unwrap()
.into();
let block1: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])
.unwrap()
.into();
let hash0 = block0.as_ref().into();
let hash1 = block1.as_ref().into();
vec![
// Insert the blocks in order
(
Request::AddBlock { block: block0 },
Ok(Response::Added { hash: hash0 }),
Request::CommitFinalizedBlock { block },
Ok(Response::Committed(hash)),
),
(
Request::AddBlock { block: block1 },
Ok(Response::Added { hash: hash1 }),
Request::Block(hash.into()),
Ok(Response::Block(Some(block2))),
),
(Request::GetTip, Ok(Response::Tip { hash: hash1 })),
]
});
static GET_TIP_ADD_ORDERED_TRANSCRIPT_TESTNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
Lazy::new(|| {
let block0: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
.unwrap()
.into();
let block1: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_1_BYTES[..])
.unwrap()
.into();
let hash0 = block0.as_ref().into();
let hash1 = block1.as_ref().into();
vec![
// Insert the blocks in order
(
Request::AddBlock { block: block0 },
Ok(Response::Added { hash: hash0 }),
),
(
Request::AddBlock { block: block1 },
Ok(Response::Added { hash: hash1 }),
),
(Request::GetTip, Ok(Response::Tip { hash: hash1 })),
]
});
#[allow(dead_code)]
static GET_TIP_ADD_REVERSED_TRANSCRIPT_MAINNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
Lazy::new(|| {
let block0: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
.unwrap()
.into();
let block1: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_1_BYTES[..])
.unwrap()
.into();
let hash0 = block0.as_ref().into();
let hash1 = block1.as_ref().into();
vec![
// Insert the blocks in reverse order
(
Request::AddBlock { block: block1 },
Ok(Response::Added { hash: hash1 }),
),
(
Request::AddBlock { block: block0 },
Ok(Response::Added { hash: hash0 }),
),
(Request::GetTip, Ok(Response::Tip { hash: hash1 })),
]
});
#[allow(dead_code)]
static GET_TIP_ADD_REVERSED_TRANSCRIPT_TESTNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
Lazy::new(|| {
let block0: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
.unwrap()
.into();
let block1: Arc<_> =
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_1_BYTES[..])
.unwrap()
.into();
let hash0 = block0.as_ref().into();
let hash1 = block1.as_ref().into();
vec![
// Insert the blocks in reverse order
(
Request::AddBlock { block: block1 },
Ok(Response::Added { hash: hash1 }),
),
(
Request::AddBlock { block: block0 },
Ok(Response::Added { hash: hash0 }),
),
(Request::GetTip, Ok(Response::Tip { hash: hash1 })),
]
});
@ -163,18 +61,8 @@ async fn check_transcripts_testnet() -> Result<(), Report> {
async fn check_transcripts(network: Network) -> Result<(), Report> {
zebra_test::init();
let mainnet_transcript = &[
&ADD_BLOCK_TRANSCRIPT_MAINNET,
&GET_TIP_ADD_ORDERED_TRANSCRIPT_MAINNET,
// Temporarily disabled, until the state accepts out-of-order blocks
//&GET_TIP_ADD_REVERSED_TRANSCRIPT_MAINNET,
];
let testnet_transcript = &[
&ADD_BLOCK_TRANSCRIPT_TESTNET,
&GET_TIP_ADD_ORDERED_TRANSCRIPT_TESTNET,
// Temporarily disabled, until the state accepts out-of-order blocks
//&GET_TIP_ADD_REVERSED_TRANSCRIPT_TESTNET,
];
let mainnet_transcript = &[&COMMIT_FINALIZED_BLOCK_MAINNET];
let testnet_transcript = &[&COMMIT_FINALIZED_BLOCK_TESTNET];
for transcript_data in match network {
Network::Mainnet => mainnet_transcript,