2020-06-22 21:31:44 -07:00
|
|
|
use color_eyre::eyre::Report;
|
|
|
|
use once_cell::sync::Lazy;
|
2020-06-24 11:30:20 -07:00
|
|
|
use std::sync::Arc;
|
2020-06-22 21:31:44 -07:00
|
|
|
use tempdir::TempDir;
|
2020-08-15 15:45:37 -07:00
|
|
|
use zebra_chain::{block::Block, parameters::Network, serialization::ZcashDeserialize};
|
2020-07-31 11:54:18 -07:00
|
|
|
use zebra_test::transcript::{TransError, Transcript};
|
2020-06-22 21:31:44 -07:00
|
|
|
|
|
|
|
use zebra_state::*;
|
|
|
|
|
2020-08-04 13:39:32 -07:00
|
|
|
static ADD_BLOCK_TRANSCRIPT_MAINNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
|
|
|
|
Lazy::new(|| {
|
|
|
|
let block: Arc<_> =
|
2020-09-04 02:34:40 -07:00
|
|
|
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_MAINNET_GENESIS_BYTES[..])
|
2020-08-04 13:39:32 -07:00
|
|
|
.unwrap()
|
|
|
|
.into();
|
|
|
|
let hash = block.as_ref().into();
|
|
|
|
vec![
|
|
|
|
(
|
|
|
|
Request::AddBlock {
|
|
|
|
block: block.clone(),
|
|
|
|
},
|
|
|
|
Ok(Response::Added { hash }),
|
|
|
|
),
|
|
|
|
(Request::GetBlock { hash }, Ok(Response::Block { block })),
|
|
|
|
]
|
|
|
|
});
|
|
|
|
|
|
|
|
static ADD_BLOCK_TRANSCRIPT_TESTNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
|
|
|
|
Lazy::new(|| {
|
|
|
|
let block: Arc<_> =
|
2020-09-04 02:34:40 -07:00
|
|
|
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
|
2020-08-04 13:39:32 -07:00
|
|
|
.unwrap()
|
|
|
|
.into();
|
|
|
|
let hash = block.as_ref().into();
|
|
|
|
vec![
|
|
|
|
(
|
|
|
|
Request::AddBlock {
|
|
|
|
block: block.clone(),
|
|
|
|
},
|
|
|
|
Ok(Response::Added { hash }),
|
|
|
|
),
|
|
|
|
(Request::GetBlock { hash }, Ok(Response::Block { block })),
|
|
|
|
]
|
|
|
|
});
|
2020-06-22 21:31:44 -07:00
|
|
|
|
2020-09-04 02:50:25 -07:00
|
|
|
static GET_TIP_ADD_ORDERED_TRANSCRIPT_MAINNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
|
2020-08-04 13:39:32 -07:00
|
|
|
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![
|
2020-09-04 02:50:25 -07:00
|
|
|
// 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 })),
|
|
|
|
]
|
|
|
|
});
|
|
|
|
|
|
|
|
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 })),
|
|
|
|
]
|
|
|
|
});
|
|
|
|
|
2020-09-04 02:50:25 -07:00
|
|
|
#[allow(dead_code)]
|
2020-09-04 02:50:25 -07:00
|
|
|
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
|
2020-08-04 13:39:32 -07:00
|
|
|
(
|
|
|
|
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 })),
|
|
|
|
]
|
|
|
|
});
|
|
|
|
|
2020-09-04 02:50:25 -07:00
|
|
|
#[allow(dead_code)]
|
2020-09-04 02:50:25 -07:00
|
|
|
static GET_TIP_ADD_REVERSED_TRANSCRIPT_TESTNET: Lazy<Vec<(Request, Result<Response, TransError>)>> =
|
2020-08-04 13:39:32 -07:00
|
|
|
Lazy::new(|| {
|
|
|
|
let block0: Arc<_> =
|
|
|
|
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_GENESIS_BYTES[..])
|
|
|
|
.unwrap()
|
|
|
|
.into();
|
|
|
|
let block1: Arc<_> =
|
2020-09-04 02:34:40 -07:00
|
|
|
Block::zcash_deserialize(&zebra_test::vectors::BLOCK_TESTNET_1_BYTES[..])
|
2020-08-04 13:39:32 -07:00
|
|
|
.unwrap()
|
|
|
|
.into();
|
|
|
|
let hash0 = block0.as_ref().into();
|
|
|
|
let hash1 = block1.as_ref().into();
|
|
|
|
vec![
|
2020-09-04 02:50:25 -07:00
|
|
|
// Insert the blocks in reverse order
|
2020-08-04 13:39:32 -07:00
|
|
|
(
|
|
|
|
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 })),
|
|
|
|
]
|
|
|
|
});
|
2020-06-22 21:31:44 -07:00
|
|
|
|
|
|
|
#[tokio::test]
|
2020-07-26 16:57:18 -07:00
|
|
|
async fn check_transcripts_mainnet() -> Result<(), Report> {
|
2020-08-15 15:45:37 -07:00
|
|
|
check_transcripts(Network::Mainnet).await
|
2020-07-26 16:57:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn check_transcripts_testnet() -> Result<(), Report> {
|
2020-08-15 15:45:37 -07:00
|
|
|
check_transcripts(Network::Testnet).await
|
2020-07-23 04:12:20 -07:00
|
|
|
}
|
|
|
|
|
2020-07-17 15:19:00 -07:00
|
|
|
#[spandoc::spandoc]
|
2020-07-26 16:57:18 -07:00
|
|
|
async fn check_transcripts(network: Network) -> Result<(), Report> {
|
2020-06-24 11:30:20 -07:00
|
|
|
zebra_test::init();
|
2020-06-22 21:31:44 -07:00
|
|
|
|
2020-09-04 02:50:25 -07:00
|
|
|
let mainnet_transcript = &[
|
|
|
|
&ADD_BLOCK_TRANSCRIPT_MAINNET,
|
|
|
|
&GET_TIP_ADD_ORDERED_TRANSCRIPT_MAINNET,
|
2020-09-04 02:50:25 -07:00
|
|
|
// Temporarily disabled, until the state accepts out-of-order blocks
|
|
|
|
//&GET_TIP_ADD_REVERSED_TRANSCRIPT_MAINNET,
|
2020-09-04 02:50:25 -07:00
|
|
|
];
|
|
|
|
let testnet_transcript = &[
|
|
|
|
&ADD_BLOCK_TRANSCRIPT_TESTNET,
|
|
|
|
&GET_TIP_ADD_ORDERED_TRANSCRIPT_TESTNET,
|
2020-09-04 02:50:25 -07:00
|
|
|
// Temporarily disabled, until the state accepts out-of-order blocks
|
|
|
|
//&GET_TIP_ADD_REVERSED_TRANSCRIPT_TESTNET,
|
2020-09-04 02:50:25 -07:00
|
|
|
];
|
2020-08-04 13:39:32 -07:00
|
|
|
|
|
|
|
for transcript_data in match network {
|
2020-09-04 02:50:25 -07:00
|
|
|
Network::Mainnet => mainnet_transcript,
|
2020-08-04 13:39:32 -07:00
|
|
|
Network::Testnet => testnet_transcript,
|
|
|
|
} {
|
2020-06-22 21:31:44 -07:00
|
|
|
let storage_guard = TempDir::new("")?;
|
2020-08-05 11:48:08 -07:00
|
|
|
let cache_dir = storage_guard.path().to_owned();
|
2020-09-01 12:39:04 -07:00
|
|
|
let service = zebra_state::init(
|
Fix sync algorithm. (#887)
* checkpoint: reject older of duplicate verification requests.
If we get a duplicate block verification request, we should drop the older one
in favor of the newer one, because the older request is likely to have been
canceled. Previously, this code would accept up to four duplicate verification
requests, then fail all subsequent ones.
* sync: add a timeout layer to block requests.
Note that if this timeout is too short, we'll bring down the peer set in a
retry storm.
* sync: restart syncing on error
Restart the syncing process when an error occurs, rather than ignoring it.
Restarting means we discard all tips and start over with a new block locator,
so we can have another chance to "unstuck" ourselves.
* sync: additional debug info
* sync: handle lookahead limit correctly.
Instead of extracting all the completed task results, the previous code pulled
results out until there were fewer tasks than the lookahead limit, then
stopped. This meant that completed tasks could be left until the limit was
exceeded again. Instead, extract all completed results, and use the number of
pending tasks to decide whether to extend the tip or wait for blocks to finish.
* network: add debug instrumentation to retry policy
* sync: instrument the spawned task
* sync: streamline ObtainTips/ExtendTips logic & tracing
This change does three things:
1. It aligns the implementation of ObtainTips and ExtendTips so that they use
the same deduplication method. This means that when debugging we only have one
deduplication algorithm to focus on.
2. It streamlines the tracing output to not include information already
included in spans. Both obtain_tips and extend_tips have their own spans
attached to the events, so it's not necessary to add Scope: prefixes in
messages.
3. It changes the messages to be focused on reporting the actual
events rather than the interpretation of the events (e.g., "got genesis hash in
response" rather than "peer could not extend tip"). The motivation for this
change is that when debugging, the interpretation of events is already known to
be incorrect, in the sense that the mental model of the code (no bug) does not
match its behavior (has bug), so presenting minimally-interpreted events forces
interpretation relative to the actual code.
* sync: hack to work around zcashd behavior
* sync: localize debug statement in extend_tips
* sync: change algorithm to define tips as pairs of hashes.
This is different enough from the existing description that its comments no
longer apply, so I removed them. A further chunk of work is to change the sync
RFC to document this algorithm.
* sync: reduce block timeout
* state: add resource limits for sled
Closes #888
* sync: add a restart timeout constant
* sync: de-pub constants
2020-08-12 16:48:01 -07:00
|
|
|
Config {
|
|
|
|
cache_dir,
|
|
|
|
..Config::default()
|
|
|
|
},
|
|
|
|
network,
|
|
|
|
);
|
2020-06-22 21:31:44 -07:00
|
|
|
let transcript = Transcript::from(transcript_data.iter().cloned());
|
2020-07-17 15:19:00 -07:00
|
|
|
/// SPANDOC: check the on disk service against the transcript
|
2020-06-22 21:31:44 -07:00
|
|
|
transcript.check(service).await?;
|
|
|
|
// Delete the contents of the temp directory before going to the next case.
|
|
|
|
std::mem::drop(storage_guard);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|