change(ci): Run block proposal tests in CI (#5963)

* Revert "Temporarily fix the code for a disabled test"

This reverts commit d915624417cc946e53aac76449e0b5b719e03d2a.

* Check every valid time source in the proposal tests

* Activate block proposal tests in CI

* Repeats block proposal test a few times at an interval to sample different mempool contents

* Increase the number of templates tested to 10

Co-authored-by: Arya <aryasolhi@gmail.com>

---------

Co-authored-by: arya2 <aryasolhi@gmail.com>
This commit is contained in:
teor 2023-02-01 09:02:22 +10:00 committed by GitHub
parent 8390e4e0cd
commit 14fdd3002b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 31 deletions

View File

@ -131,6 +131,13 @@ impl TimeSource {
Raw(_) | RawNow => false,
}
}
/// Returns an iterator of time sources that are valid according to the consensus rules.
pub fn valid_sources() -> impl IntoIterator<Item = TimeSource> {
use TimeSource::*;
[CurTime, MinTime, MaxTime, ClampedNow].into_iter()
}
}
impl FromStr for TimeSource {
@ -160,7 +167,7 @@ impl FromStr for TimeSource {
///
/// If `time_source` is not supplied, uses the current time from the template.
pub fn proposal_block_from_template(
template: GetBlockTemplate,
template: &GetBlockTemplate,
time_source: impl Into<Option<TimeSource>>,
) -> Result<Block, SerializationError> {
let GetBlockTemplate {
@ -177,7 +184,7 @@ pub fn proposal_block_from_template(
ref coinbase_txn,
transactions: ref tx_templates,
..
} = template;
} = *template;
if Height(height) > Height::MAX {
Err(SerializationError::Parse(
@ -188,7 +195,7 @@ pub fn proposal_block_from_template(
let time = time_source
.into()
.unwrap_or_default()
.time_from_template(&template);
.time_from_template(template);
let mut transactions = vec![coinbase_txn.data.as_ref().zcash_deserialize_into()?];

View File

@ -96,7 +96,7 @@ fn main() -> Result<()> {
let template: GetBlockTemplate = serde_json::from_value(template)?;
// generate proposal according to arguments
let proposal = proposal_block_from_template(template, time_source)?;
let proposal = proposal_block_from_template(&template, time_source)?;
eprintln!("{proposal:#?}");
let proposal = proposal

View File

@ -27,6 +27,10 @@ use crate::common::{
/// We've seen it take anywhere from 1-45 seconds for the mempool to have some transactions in it.
pub const EXPECTED_MEMPOOL_TRANSACTION_TIME: Duration = Duration::from_secs(45);
/// Number of times we want to try submitting a block template as a block proposal at an interval
/// that allows testing the varying mempool contents.
const NUM_SUCCESSFUL_BLOCK_PROPOSALS_REQUIRED: usize = 10;
/// Launch Zebra, wait for it to sync, and check the getblocktemplate RPC returns without errors.
pub(crate) async fn run() -> Result<()> {
let _init_guard = zebra_test::init();
@ -86,25 +90,24 @@ pub(crate) async fn run() -> Result<()> {
assert!(is_response_success);
tracing::info!(
"waiting {EXPECTED_MEMPOOL_TRANSACTION_TIME:?} for the mempool \
to download and verify some transactions...",
);
for _ in 0..NUM_SUCCESSFUL_BLOCK_PROPOSALS_REQUIRED {
tracing::info!(
"waiting {EXPECTED_MEMPOOL_TRANSACTION_TIME:?} for the mempool \
to download and verify some transactions...",
);
tokio::time::sleep(EXPECTED_MEMPOOL_TRANSACTION_TIME).await;
tokio::time::sleep(EXPECTED_MEMPOOL_TRANSACTION_TIME).await;
/* TODO: activate this test after #5925 and #5953 have merged,
and we've checked for any other bugs using #5944.
tracing::info!(
"calling getblocktemplate RPC method at {rpc_address}, \
with a mempool that likely has transactions and attempting \
to validate response result as a block proposal",
);
tracing::info!(
"calling getblocktemplate RPC method at {rpc_address}, \
with a mempool that likely has transactions and attempting \
to validate response result as a block proposal",
);
try_validate_block_template(&client)
.await
.expect("block proposal validation failed");
*/
try_validate_block_template(&client)
.await
.expect("block proposal validation failed");
}
zebrad.kill(false)?;
@ -130,7 +133,6 @@ pub(crate) async fn run() -> Result<()> {
/// If an RPC call returns a failure
/// If the response result cannot be deserialized to `GetBlockTemplate` in 'template' mode
/// or `ProposalResponse` in 'proposal' mode.
#[allow(dead_code)]
async fn try_validate_block_template(client: &RPCRequestClient) -> Result<()> {
let response_json_result = client
.json_result_from_call("getblocktemplate", "[]".to_string())
@ -142,16 +144,16 @@ async fn try_validate_block_template(client: &RPCRequestClient) -> Result<()> {
"got getblocktemplate response, hopefully with transactions"
);
// Propose a new block with an empty solution and nonce field
tracing::info!("calling getblocktemplate with a block proposal...",);
for time_source in TimeSource::valid_sources() {
// Propose a new block with an empty solution and nonce field
tracing::info!(
"calling getblocktemplate with a block proposal and time source {time_source:?}...",
);
// TODO: update this to use all valid time sources in the next PR
#[allow(clippy::single_element_loop)]
for proposal_block in [proposal_block_from_template(
response_json_result,
TimeSource::CurTime,
)?] {
let raw_proposal_block = hex::encode(proposal_block.zcash_serialize_to_vec()?);
let raw_proposal_block = hex::encode(
proposal_block_from_template(&response_json_result, time_source)?
.zcash_serialize_to_vec()?,
);
let json_result = client
.json_result_from_call(
@ -163,7 +165,7 @@ async fn try_validate_block_template(client: &RPCRequestClient) -> Result<()> {
tracing::info!(
?json_result,
?proposal_block.header.time,
?time_source,
"got getblocktemplate proposal response"
);