Merge pull request #538 from paritytech/always_ask_for_witness_blocks_on_core_chain
Always ask for witness when requesting b/tx on --btc chain
This commit is contained in:
commit
3ab2265a86
|
@ -64,12 +64,26 @@ impl InventoryVector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn witness_tx(hash: H256) -> Self {
|
||||||
|
InventoryVector {
|
||||||
|
inv_type: InventoryType::MessageWitnessTx,
|
||||||
|
hash: hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn block(hash: H256) -> Self {
|
pub fn block(hash: H256) -> Self {
|
||||||
InventoryVector {
|
InventoryVector {
|
||||||
inv_type: InventoryType::MessageBlock,
|
inv_type: InventoryType::MessageBlock,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn witness_block(hash: H256) -> Self {
|
||||||
|
InventoryVector {
|
||||||
|
inv_type: InventoryType::MessageWitnessBlock,
|
||||||
|
hash: hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serializable for InventoryVector {
|
impl Serializable for InventoryVector {
|
||||||
|
|
|
@ -152,6 +152,15 @@ impl ConsensusParams {
|
||||||
(height == 91842 && hash == &H256::from_reversed_str("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
|
(height == 91842 && hash == &H256::from_reversed_str("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
|
||||||
(height == 91880 && hash == &H256::from_reversed_str("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))
|
(height == 91880 && hash == &H256::from_reversed_str("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if SegWit is possible on this chain.
|
||||||
|
pub fn is_segwit_possible(&self) -> bool {
|
||||||
|
match self.fork {
|
||||||
|
// SegWit is not supported in (our?) regtests
|
||||||
|
ConsensusFork::BitcoinCore if self.network != Network::Regtest => true,
|
||||||
|
ConsensusFork::BitcoinCore | ConsensusFork::BitcoinCash(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConsensusFork {
|
impl ConsensusFork {
|
||||||
|
|
|
@ -110,7 +110,7 @@ pub fn create_local_sync_node(consensus: ConsensusParams, db: storage::SharedSto
|
||||||
let memory_pool = Arc::new(RwLock::new(MemoryPool::new()));
|
let memory_pool = Arc::new(RwLock::new(MemoryPool::new()));
|
||||||
let sync_state = SynchronizationStateRef::new(SynchronizationState::with_storage(db.clone()));
|
let sync_state = SynchronizationStateRef::new(SynchronizationState::with_storage(db.clone()));
|
||||||
let sync_chain = SyncChain::new(db.clone(), consensus.clone(), memory_pool.clone());
|
let sync_chain = SyncChain::new(db.clone(), consensus.clone(), memory_pool.clone());
|
||||||
if sync_chain.is_segwit_active() {
|
if sync_chain.is_segwit_possible() {
|
||||||
peers.require_peer_services(Services::default().with_witness(true));
|
peers.require_peer_services(Services::default().with_witness(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ use primitives::bytes::Bytes;
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
use utils::{BestHeadersChain, BestHeadersChainInformation, HashQueueChain, HashPosition};
|
use utils::{BestHeadersChain, BestHeadersChainInformation, HashQueueChain, HashPosition};
|
||||||
use types::{BlockHeight, StorageRef, MemoryPoolRef};
|
use types::{BlockHeight, StorageRef, MemoryPoolRef};
|
||||||
use verification::Deployments;
|
|
||||||
|
|
||||||
/// Index of 'verifying' queue
|
/// Index of 'verifying' queue
|
||||||
const VERIFYING_QUEUE: usize = 0;
|
const VERIFYING_QUEUE: usize = 0;
|
||||||
|
@ -106,8 +105,6 @@ pub struct Chain {
|
||||||
best_storage_block: storage::BestBlock,
|
best_storage_block: storage::BestBlock,
|
||||||
/// Local blocks storage
|
/// Local blocks storage
|
||||||
storage: StorageRef,
|
storage: StorageRef,
|
||||||
/// Consensus params.
|
|
||||||
consensus: ConsensusParams,
|
|
||||||
/// In-memory queue of blocks hashes
|
/// In-memory queue of blocks hashes
|
||||||
hash_chain: HashQueueChain,
|
hash_chain: HashQueueChain,
|
||||||
/// In-memory queue of blocks headers
|
/// In-memory queue of blocks headers
|
||||||
|
@ -118,10 +115,9 @@ pub struct Chain {
|
||||||
memory_pool: MemoryPoolRef,
|
memory_pool: MemoryPoolRef,
|
||||||
/// Blocks that have been marked as dead-ends
|
/// Blocks that have been marked as dead-ends
|
||||||
dead_end_blocks: HashSet<H256>,
|
dead_end_blocks: HashSet<H256>,
|
||||||
/// Deployments cache
|
/// Is SegWit is possible on this chain? SegWit inventory types are used when block/tx-es are
|
||||||
deployments: Deployments,
|
/// requested and this flag is true.
|
||||||
/// Is SegWit active?
|
is_segwit_possible: bool,
|
||||||
is_segwit_active: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockState {
|
impl BlockState {
|
||||||
|
@ -152,21 +148,18 @@ impl Chain {
|
||||||
.expect("storage with genesis block is required");
|
.expect("storage with genesis block is required");
|
||||||
let best_storage_block = storage.best_block();
|
let best_storage_block = storage.best_block();
|
||||||
let best_storage_block_hash = best_storage_block.hash.clone();
|
let best_storage_block_hash = best_storage_block.hash.clone();
|
||||||
let deployments = Deployments::new();
|
let is_segwit_possible = consensus.is_segwit_possible();
|
||||||
let is_segwit_active = deployments.segwit(best_storage_block.number, storage.as_block_header_provider(), &consensus);
|
|
||||||
|
|
||||||
Chain {
|
Chain {
|
||||||
genesis_block_hash: genesis_block_hash,
|
genesis_block_hash: genesis_block_hash,
|
||||||
best_storage_block: best_storage_block,
|
best_storage_block: best_storage_block,
|
||||||
storage: storage,
|
storage: storage,
|
||||||
consensus: consensus,
|
|
||||||
hash_chain: HashQueueChain::with_number_of_queues(NUMBER_OF_QUEUES),
|
hash_chain: HashQueueChain::with_number_of_queues(NUMBER_OF_QUEUES),
|
||||||
headers_chain: BestHeadersChain::new(best_storage_block_hash),
|
headers_chain: BestHeadersChain::new(best_storage_block_hash),
|
||||||
verifying_transactions: LinkedHashMap::new(),
|
verifying_transactions: LinkedHashMap::new(),
|
||||||
memory_pool: memory_pool,
|
memory_pool: memory_pool,
|
||||||
dead_end_blocks: HashSet::new(),
|
dead_end_blocks: HashSet::new(),
|
||||||
deployments: deployments,
|
is_segwit_possible,
|
||||||
is_segwit_active: is_segwit_active,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +186,8 @@ impl Chain {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is segwit active
|
/// Is segwit active
|
||||||
pub fn is_segwit_active(&self) -> bool {
|
pub fn is_segwit_possible(&self) -> bool {
|
||||||
self.is_segwit_active
|
self.is_segwit_possible
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get number of blocks in given state
|
/// Get number of blocks in given state
|
||||||
|
@ -367,7 +360,6 @@ impl Chain {
|
||||||
|
|
||||||
// remember new best block hash
|
// remember new best block hash
|
||||||
self.best_storage_block = self.storage.as_store().best_block();
|
self.best_storage_block = self.storage.as_store().best_block();
|
||||||
self.is_segwit_active = self.deployments.segwit(self.best_storage_block.number, self.storage.as_block_header_provider(), &self.consensus);
|
|
||||||
|
|
||||||
// remove inserted block + handle possible reorganization in headers chain
|
// remove inserted block + handle possible reorganization in headers chain
|
||||||
// TODO: mk, not sure if we need both of those params
|
// TODO: mk, not sure if we need both of those params
|
||||||
|
@ -403,7 +395,6 @@ impl Chain {
|
||||||
|
|
||||||
// remember new best block hash
|
// remember new best block hash
|
||||||
self.best_storage_block = self.storage.best_block();
|
self.best_storage_block = self.storage.best_block();
|
||||||
self.is_segwit_active = self.deployments.segwit(self.best_storage_block.number, self.storage.as_block_header_provider(), &self.consensus);
|
|
||||||
|
|
||||||
// remove inserted block + handle possible reorganization in headers chain
|
// remove inserted block + handle possible reorganization in headers chain
|
||||||
// TODO: mk, not sure if we need both of those params
|
// TODO: mk, not sure if we need both of those params
|
||||||
|
|
|
@ -6,7 +6,7 @@ use futures::Future;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use time::precise_time_s;
|
use time::precise_time_s;
|
||||||
use chain::{IndexedBlockHeader, IndexedTransaction, Transaction, IndexedBlock};
|
use chain::{IndexedBlockHeader, IndexedTransaction, Transaction, IndexedBlock};
|
||||||
use message::{types, Services};
|
use message::types;
|
||||||
use message::common::{InventoryType, InventoryVector};
|
use message::common::{InventoryType, InventoryVector};
|
||||||
use miner::transaction_fee_rate;
|
use miner::transaction_fee_rate;
|
||||||
use primitives::hash::H256;
|
use primitives::hash::H256;
|
||||||
|
@ -226,16 +226,16 @@ impl<T> ClientCore for SynchronizationClientCore<T> where T: TaskExecutor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// else ask for all unknown transactions and blocks
|
// else ask for all unknown transactions and blocks
|
||||||
let is_segwit_active = self.chain.is_segwit_active();
|
let is_segwit_possible = self.chain.is_segwit_possible();
|
||||||
let ask_for_witness = is_segwit_active && self.peers.is_segwit_enabled(peer_index);
|
|
||||||
let unknown_inventory: Vec<_> = message.inventory.into_iter()
|
let unknown_inventory: Vec<_> = message.inventory.into_iter()
|
||||||
.filter(|item| {
|
.filter(|item| {
|
||||||
match item.inv_type {
|
match item.inv_type {
|
||||||
// check that transaction is unknown to us
|
// check that transaction is unknown to us
|
||||||
InventoryType::MessageTx => self.chain.transaction_state(&item.hash) == TransactionState::Unknown
|
InventoryType::MessageTx| InventoryType::MessageWitnessTx =>
|
||||||
|
self.chain.transaction_state(&item.hash) == TransactionState::Unknown
|
||||||
&& !self.orphaned_transactions_pool.contains(&item.hash),
|
&& !self.orphaned_transactions_pool.contains(&item.hash),
|
||||||
// check that block is unknown to us
|
// check that block is unknown to us
|
||||||
InventoryType::MessageBlock => match self.chain.block_state(&item.hash) {
|
InventoryType::MessageBlock | InventoryType::MessageWitnessBlock => match self.chain.block_state(&item.hash) {
|
||||||
BlockState::Unknown => !self.orphaned_blocks_pool.contains_unknown_block(&item.hash),
|
BlockState::Unknown => !self.orphaned_blocks_pool.contains_unknown_block(&item.hash),
|
||||||
BlockState::DeadEnd if !self.config.close_connection_on_bad_block => true,
|
BlockState::DeadEnd if !self.config.close_connection_on_bad_block => true,
|
||||||
BlockState::DeadEnd if self.config.close_connection_on_bad_block => {
|
BlockState::DeadEnd if self.config.close_connection_on_bad_block => {
|
||||||
|
@ -246,8 +246,8 @@ impl<T> ClientCore for SynchronizationClientCore<T> where T: TaskExecutor {
|
||||||
},
|
},
|
||||||
// we never ask for merkle blocks && we never ask for compact blocks
|
// we never ask for merkle blocks && we never ask for compact blocks
|
||||||
InventoryType::MessageCompactBlock | InventoryType::MessageFilteredBlock
|
InventoryType::MessageCompactBlock | InventoryType::MessageFilteredBlock
|
||||||
| InventoryType::MessageWitnessBlock | InventoryType::MessageWitnessFilteredBlock
|
| InventoryType::MessageWitnessFilteredBlock
|
||||||
| InventoryType::MessageWitnessTx => false,
|
=> false,
|
||||||
// unknown inventory type
|
// unknown inventory type
|
||||||
InventoryType::Error => {
|
InventoryType::Error => {
|
||||||
self.peers.misbehaving(peer_index, &format!("Provided unknown inventory type {:?}", item.hash.to_reversed_str()));
|
self.peers.misbehaving(peer_index, &format!("Provided unknown inventory type {:?}", item.hash.to_reversed_str()));
|
||||||
|
@ -258,7 +258,7 @@ impl<T> ClientCore for SynchronizationClientCore<T> where T: TaskExecutor {
|
||||||
// we are not synchronizing =>
|
// we are not synchronizing =>
|
||||||
// 1) either segwit is active and we are connected to segwit-enabled nodes => we could ask for witness
|
// 1) either segwit is active and we are connected to segwit-enabled nodes => we could ask for witness
|
||||||
// 2) or segwit is inactive => we shall not ask for witness
|
// 2) or segwit is inactive => we shall not ask for witness
|
||||||
.map(|item| if !ask_for_witness {
|
.map(|item| if !is_segwit_possible {
|
||||||
item
|
item
|
||||||
} else {
|
} else {
|
||||||
match item.inv_type {
|
match item.inv_type {
|
||||||
|
@ -973,8 +973,8 @@ impl<T> SynchronizationClientCore<T> where T: TaskExecutor {
|
||||||
let chunk_size = min(limits.max_blocks_in_request, max(hashes.len() as BlockHeight, limits.min_blocks_in_request));
|
let chunk_size = min(limits.max_blocks_in_request, max(hashes.len() as BlockHeight, limits.min_blocks_in_request));
|
||||||
let last_peer_index = peers.len() - 1;
|
let last_peer_index = peers.len() - 1;
|
||||||
let mut tasks: Vec<Task> = Vec::new();
|
let mut tasks: Vec<Task> = Vec::new();
|
||||||
let is_segwit_active = self.chain.is_segwit_active();
|
let is_segwit_possible = self.chain.is_segwit_possible();
|
||||||
let inv_type = if is_segwit_active { InventoryType::MessageWitnessBlock } else { InventoryType::MessageBlock };
|
let inv_type = if is_segwit_possible { InventoryType::MessageWitnessBlock } else { InventoryType::MessageBlock };
|
||||||
for (peer_index, peer) in peers.into_iter().enumerate() {
|
for (peer_index, peer) in peers.into_iter().enumerate() {
|
||||||
// we have to request all blocks => we will request last peer for all remaining blocks
|
// we have to request all blocks => we will request last peer for all remaining blocks
|
||||||
let peer_chunk_size = if peer_index == last_peer_index { hashes.len() } else { min(hashes.len(), chunk_size as usize) };
|
let peer_chunk_size = if peer_index == last_peer_index { hashes.len() } else { min(hashes.len(), chunk_size as usize) };
|
||||||
|
@ -1073,9 +1073,6 @@ impl<T> SynchronizationClientCore<T> where T: TaskExecutor {
|
||||||
// update block processing speed
|
// update block processing speed
|
||||||
self.block_speed_meter.checkpoint();
|
self.block_speed_meter.checkpoint();
|
||||||
|
|
||||||
// remember if SegWit was active before this block
|
|
||||||
let segwit_was_active = self.chain.is_segwit_active();
|
|
||||||
|
|
||||||
// remove flags
|
// remove flags
|
||||||
let needs_relay = !self.do_not_relay.remove(block.hash());
|
let needs_relay = !self.do_not_relay.remove(block.hash());
|
||||||
|
|
||||||
|
@ -1096,13 +1093,6 @@ impl<T> SynchronizationClientCore<T> where T: TaskExecutor {
|
||||||
// update shared state
|
// update shared state
|
||||||
self.shared_state.update_best_storage_block_height(self.chain.best_storage_block().number);
|
self.shared_state.update_best_storage_block_height(self.chain.best_storage_block().number);
|
||||||
|
|
||||||
// if SegWit activated after this block insertion:
|
|
||||||
// 1) no more connections to !NODE_WITNESS nodes
|
|
||||||
// 2) disconnect from all nodes without NODE_WITNESS support
|
|
||||||
if !segwit_was_active && self.chain.is_segwit_active() {
|
|
||||||
self.peers.require_peer_services(Services::default().with_witness(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
// notify listener
|
// notify listener
|
||||||
if let Some(best_block_hash) = insert_result.canonized_blocks_hashes.last() {
|
if let Some(best_block_hash) = insert_result.canonized_blocks_hashes.last() {
|
||||||
if let Some(ref listener) = self.listener {
|
if let Some(ref listener) = self.listener {
|
||||||
|
@ -1349,7 +1339,7 @@ pub mod tests {
|
||||||
|
|
||||||
fn request_blocks(peer_index: PeerIndex, hashes: Vec<H256>) -> Task {
|
fn request_blocks(peer_index: PeerIndex, hashes: Vec<H256>) -> Task {
|
||||||
Task::GetData(peer_index, types::GetData {
|
Task::GetData(peer_index, types::GetData {
|
||||||
inventory: hashes.into_iter().map(InventoryVector::block).collect(),
|
inventory: hashes.into_iter().map(InventoryVector::witness_block).collect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1749,13 +1739,13 @@ pub mod tests {
|
||||||
|
|
||||||
sync.on_block(1, test_data::block_h2().into());
|
sync.on_block(1, test_data::block_h2().into());
|
||||||
sync.on_inventory(1, types::Inv::with_inventory(vec![
|
sync.on_inventory(1, types::Inv::with_inventory(vec![
|
||||||
InventoryVector::block(test_data::block_h1().hash()),
|
InventoryVector::witness_block(test_data::block_h1().hash()),
|
||||||
InventoryVector::block(test_data::block_h2().hash()),
|
InventoryVector::witness_block(test_data::block_h2().hash()),
|
||||||
]));
|
]));
|
||||||
|
|
||||||
let tasks = executor.take_tasks();
|
let tasks = executor.take_tasks();
|
||||||
assert_eq!(tasks, vec![Task::GetData(1, types::GetData::with_inventory(vec![
|
assert_eq!(tasks, vec![Task::GetData(1, types::GetData::with_inventory(vec![
|
||||||
InventoryVector::block(test_data::block_h1().hash())
|
InventoryVector::witness_block(test_data::block_h1().hash())
|
||||||
]))]);
|
]))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1883,11 +1873,11 @@ pub mod tests {
|
||||||
fn transaction_is_requested_when_not_synchronizing() {
|
fn transaction_is_requested_when_not_synchronizing() {
|
||||||
let (executor, core, sync) = create_sync(None, None);
|
let (executor, core, sync) = create_sync(None, None);
|
||||||
|
|
||||||
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::tx(H256::from(0))]));
|
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::witness_tx(H256::from(0))]));
|
||||||
|
|
||||||
{
|
{
|
||||||
let tasks = executor.take_tasks();
|
let tasks = executor.take_tasks();
|
||||||
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![InventoryVector::tx(H256::from(0))]))]);
|
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![InventoryVector::witness_tx(H256::from(0))]))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let b1 = test_data::block_h1();
|
let b1 = test_data::block_h1();
|
||||||
|
@ -1896,28 +1886,28 @@ pub mod tests {
|
||||||
assert!(core.lock().information().state.is_nearly_saturated());
|
assert!(core.lock().information().state.is_nearly_saturated());
|
||||||
{ executor.take_tasks(); } // forget tasks
|
{ executor.take_tasks(); } // forget tasks
|
||||||
|
|
||||||
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::tx(H256::from(1))]));
|
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::witness_tx(H256::from(1))]));
|
||||||
|
|
||||||
let tasks = executor.take_tasks();
|
let tasks = executor.take_tasks();
|
||||||
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![InventoryVector::tx(H256::from(1))]))]);
|
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![InventoryVector::witness_tx(H256::from(1))]))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn same_transaction_can_be_requested_twice() {
|
fn same_transaction_can_be_requested_twice() {
|
||||||
let (executor, _, sync) = create_sync(None, None);
|
let (executor, _, sync) = create_sync(None, None);
|
||||||
|
|
||||||
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::tx(H256::from(0))]));
|
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::witness_tx(H256::from(0))]));
|
||||||
|
|
||||||
let tasks = executor.take_tasks();
|
let tasks = executor.take_tasks();
|
||||||
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![
|
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![
|
||||||
InventoryVector::tx(H256::from(0))
|
InventoryVector::witness_tx(H256::from(0))
|
||||||
]))]);
|
]))]);
|
||||||
|
|
||||||
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::tx(H256::from(0))]));
|
sync.on_inventory(0, types::Inv::with_inventory(vec![InventoryVector::witness_tx(H256::from(0))]));
|
||||||
|
|
||||||
let tasks = executor.take_tasks();
|
let tasks = executor.take_tasks();
|
||||||
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![
|
assert_eq!(tasks, vec![Task::GetData(0, types::GetData::with_inventory(vec![
|
||||||
InventoryVector::tx(H256::from(0))
|
InventoryVector::witness_tx(H256::from(0))
|
||||||
]))]);
|
]))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1926,11 +1916,11 @@ pub mod tests {
|
||||||
let (executor, _, sync) = create_sync(None, None);
|
let (executor, _, sync) = create_sync(None, None);
|
||||||
|
|
||||||
sync.on_inventory(0, types::Inv::with_inventory(vec![
|
sync.on_inventory(0, types::Inv::with_inventory(vec![
|
||||||
InventoryVector::tx(test_data::genesis().transactions[0].hash()),
|
InventoryVector::witness_tx(test_data::genesis().transactions[0].hash()),
|
||||||
InventoryVector::tx(H256::from(0)),
|
InventoryVector::witness_tx(H256::from(0)),
|
||||||
]));
|
]));
|
||||||
assert_eq!(executor.take_tasks(), vec![Task::GetData(0, types::GetData::with_inventory(vec![
|
assert_eq!(executor.take_tasks(), vec![Task::GetData(0, types::GetData::with_inventory(vec![
|
||||||
InventoryVector::tx(H256::from(0))
|
InventoryVector::witness_tx(H256::from(0))
|
||||||
]))]);
|
]))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue