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:
parent
98d5351206
commit
070013439e
|
|
@ -23,7 +23,7 @@ use memory_state::MemoryState;
|
||||||
use sled_state::SledState;
|
use sled_state::SledState;
|
||||||
|
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
pub use request::Request;
|
pub use request::{HashOrHeight, Request};
|
||||||
pub use response::Response;
|
pub use response::Response;
|
||||||
pub use service::init;
|
pub use service::init;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,110 @@
|
||||||
use std::sync::Arc;
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
/// A query about or modification to the chain state.
|
/// A query about or modification to the chain state.
|
||||||
///
|
|
||||||
/// TODO: replace these variants with the ones in RFC5.
|
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
// TODO(jlusby): deprecate in the future based on our validation story
|
/// Performs contextual validation of the given block, committing it to the
|
||||||
/// Add a block to the zebra-state
|
/// state if successful.
|
||||||
AddBlock {
|
///
|
||||||
/// The block to be added to the state
|
/// 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>,
|
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 {
|
/// Commit a finalized block to the state, skipping contextual validation.
|
||||||
/// The hash used to identify the block
|
/// This is exposed for use in checkpointing, which produces finalized
|
||||||
hash: block::Hash,
|
/// blocks.
|
||||||
},
|
///
|
||||||
/// Get a block locator list for the current best chain
|
/// Returns [`Response::Committed`] with the hash of the newly
|
||||||
GetBlockLocator {
|
/// committed block, or an error.
|
||||||
/// The genesis block of the current best chain
|
///
|
||||||
genesis: block::Hash,
|
/// This request can be made out-of-order; the state service will buffer it
|
||||||
},
|
/// until its parent is ready.
|
||||||
/// Get the block that is the tip of the current chain
|
CommitFinalizedBlock {
|
||||||
GetTip,
|
/// The block to commit to the state.
|
||||||
/// Ask the state if the given hash is part of the current best chain
|
block: Arc<Block>,
|
||||||
GetDepth {
|
// TODO: add these parameters when we can compute anchors.
|
||||||
/// The hash to check against the current chain
|
// sprout_anchor: sprout::tree::Root,
|
||||||
hash: block::Hash,
|
// 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),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,33 @@
|
||||||
use std::sync::Arc;
|
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)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
/// A response to a state [`Request`](super::Request).
|
/// A response to a state [`Request`].
|
||||||
pub enum Response {
|
pub enum Response {
|
||||||
/// The response to a `AddBlock` request indicating a block was successfully
|
/// Response to [`Request::CommitBlock`] indicating that a block was
|
||||||
/// added to the state
|
/// successfully committed to the state.
|
||||||
Added {
|
Committed(block::Hash),
|
||||||
/// The hash of the block that was added
|
|
||||||
hash: block::Hash,
|
/// Response to [`Request::Depth`] with the depth of the specified block.
|
||||||
},
|
Depth(Option<block::Height>),
|
||||||
/// The response to a `GetBlock` request by hash
|
|
||||||
Block {
|
/// Response to [`Request::Tip`] with the current best chain tip.
|
||||||
/// The block that was requested
|
Tip(Option<block::Hash>),
|
||||||
block: Arc<Block>,
|
|
||||||
},
|
/// Response to [`Request::BlockLocator`] with a block locator object.
|
||||||
/// The response to a `GetBlockLocator` request
|
BlockLocator(Vec<block::Hash>),
|
||||||
BlockLocator {
|
|
||||||
/// The set of blocks that make up the block locator
|
/// Response to [`Request::Transaction`] with the specified transaction.
|
||||||
block_locator: Vec<block::Hash>,
|
Transaction(Option<Arc<Transaction>>),
|
||||||
},
|
|
||||||
/// The response to a `GetTip` request
|
/// Response to [`Request::Block`] with the specified block.
|
||||||
Tip {
|
Block(Option<Arc<Block>>),
|
||||||
/// 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>,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
use tower::{buffer::Buffer, util::BoxService, Service};
|
use tower::{buffer::Buffer, util::BoxService, Service};
|
||||||
use zebra_chain::parameters::Network;
|
use zebra_chain::parameters::Network;
|
||||||
|
|
||||||
use crate::{BoxError, Config, MemoryState, Request, Response, SledState};
|
use crate::{BoxError, Config, HashOrHeight, MemoryState, Request, Response, SledState};
|
||||||
|
|
||||||
struct StateService {
|
struct StateService {
|
||||||
/// Holds data relating to finalized chain state.
|
/// Holds data relating to finalized chain state.
|
||||||
|
|
@ -35,11 +35,14 @@ impl Service<Request> for StateService {
|
||||||
|
|
||||||
fn call(&mut self, req: Request) -> Self::Future {
|
fn call(&mut self, req: Request) -> Self::Future {
|
||||||
match req {
|
match req {
|
||||||
Request::AddBlock { block } => unimplemented!(),
|
Request::CommitBlock { block } => unimplemented!(),
|
||||||
Request::GetBlock { hash } => unimplemented!(),
|
Request::CommitFinalizedBlock { block } => unimplemented!(),
|
||||||
Request::GetTip => unimplemented!(),
|
Request::Depth(hash) => unimplemented!(),
|
||||||
Request::GetDepth { hash } => unimplemented!(),
|
Request::Tip => unimplemented!(),
|
||||||
Request::GetBlockLocator { genesis } => unimplemented!(),
|
Request::BlockLocator => unimplemented!(),
|
||||||
|
Request::Transaction(hash) => unimplemented!(),
|
||||||
|
Request::Block(HashOrHeight::Hash(hash)) => unimplemented!(),
|
||||||
|
Request::Block(HashOrHeight::Height(height)) => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,145 +7,43 @@ use zebra_test::transcript::{TransError, Transcript};
|
||||||
|
|
||||||
use zebra_state::*;
|
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(|| {
|
Lazy::new(|| {
|
||||||
let block: Arc<_> =
|
let block: Arc<_> =
|
||||||
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
|
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
let hash = block.as_ref().into();
|
let block2 = block.clone();
|
||||||
|
let hash = block.hash();
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Request::AddBlock {
|
Request::CommitFinalizedBlock { block },
|
||||||
block: block.clone(),
|
Ok(Response::Committed(hash)),
|
||||||
},
|
),
|
||||||
Ok(Response::Added { 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(|| {
|
Lazy::new(|| {
|
||||||
let block: Arc<_> =
|
let block: Arc<_> =
|
||||||
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
|
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into();
|
.into();
|
||||||
let hash = block.as_ref().into();
|
let block2 = block.clone();
|
||||||
|
let hash = block.hash();
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Request::AddBlock {
|
Request::CommitFinalizedBlock { block },
|
||||||
block: block.clone(),
|
Ok(Response::Committed(hash)),
|
||||||
},
|
|
||||||
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::AddBlock { block: block1 },
|
Request::Block(hash.into()),
|
||||||
Ok(Response::Added { hash: hash1 }),
|
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> {
|
async fn check_transcripts(network: Network) -> Result<(), Report> {
|
||||||
zebra_test::init();
|
zebra_test::init();
|
||||||
|
|
||||||
let mainnet_transcript = &[
|
let mainnet_transcript = &[&COMMIT_FINALIZED_BLOCK_MAINNET];
|
||||||
&ADD_BLOCK_TRANSCRIPT_MAINNET,
|
let testnet_transcript = &[&COMMIT_FINALIZED_BLOCK_TESTNET];
|
||||||
&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,
|
|
||||||
];
|
|
||||||
|
|
||||||
for transcript_data in match network {
|
for transcript_data in match network {
|
||||||
Network::Mainnet => mainnet_transcript,
|
Network::Mainnet => mainnet_transcript,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue