diff --git a/polkadot/node/core/chain-api/src/lib.rs b/polkadot/node/core/chain-api/src/lib.rs
index 9a272e7d1d..b41c017cda 100644
--- a/polkadot/node/core/chain-api/src/lib.rs
+++ b/polkadot/node/core/chain-api/src/lib.rs
@@ -22,6 +22,7 @@
//!
//! Supported requests:
//! * Block hash to number
+//! * Block hash to header
//! * Finalized block number to hash
//! * Last finalized block number
//! * Ancestors
@@ -85,6 +86,13 @@ where
subsystem.metrics.on_request(result.is_ok());
let _ = response_channel.send(result);
},
+ ChainApiMessage::BlockHeader(hash, response_channel) => {
+ let result = subsystem.client
+ .header(BlockId::Hash(hash))
+ .map_err(|e| e.to_string().into());
+ subsystem.metrics.on_request(result.is_ok());
+ let _ = response_channel.send(result);
+ },
ChainApiMessage::FinalizedBlockHash(number, response_channel) => {
// Note: we don't verify it's finalized
let result = subsystem.client.hash(number).map_err(|e| e.to_string().into());
@@ -319,6 +327,30 @@ mod tests {
})
}
+ #[test]
+ fn request_block_header() {
+ test_harness(|client, mut sender| {
+ async move {
+ const NOT_HERE: Hash = Hash::repeat_byte(0x5);
+ let test_cases = [
+ (TWO, client.header(BlockId::Hash(TWO)).unwrap()),
+ (NOT_HERE, client.header(BlockId::Hash(NOT_HERE)).unwrap()),
+ ];
+ for (hash, expected) in &test_cases {
+ let (tx, rx) = oneshot::channel();
+
+ sender.send(FromOverseer::Communication {
+ msg: ChainApiMessage::BlockHeader(*hash, tx),
+ }).await;
+
+ assert_eq!(rx.await.unwrap().unwrap(), *expected);
+ }
+
+ sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
+ }.boxed()
+ })
+ }
+
#[test]
fn request_finalized_hash() {
test_harness(|client, mut sender| {
diff --git a/polkadot/node/subsystem/src/messages.rs b/polkadot/node/subsystem/src/messages.rs
index 35f92eca8a..22e9f097ff 100644
--- a/polkadot/node/subsystem/src/messages.rs
+++ b/polkadot/node/subsystem/src/messages.rs
@@ -31,12 +31,13 @@ use polkadot_node_primitives::{
CollationGenerationConfig, MisbehaviorReport, SignedFullStatement, ValidationResult,
};
use polkadot_primitives::v1::{
- AuthorityDiscoveryId, AvailableData, BackedCandidate, BlockNumber, CandidateDescriptor,
- CandidateEvent, CandidateReceipt, CollatorId, CommittedCandidateReceipt,
- CoreState, ErasureChunk, GroupRotationInfo, Hash, Id as ParaId,
- OccupiedCoreAssumption, PersistedValidationData, PoV, SessionIndex, SignedAvailabilityBitfield,
- TransientValidationData, ValidationCode, ValidatorId, ValidationData, ValidatorIndex,
- ValidatorSignature,
+ AuthorityDiscoveryId, AvailableData, BackedCandidate, BlockNumber,
+ Header as BlockHeader, CandidateDescriptor, CandidateEvent, CandidateReceipt,
+ CollatorId, CommittedCandidateReceipt, CoreState, ErasureChunk,
+ GroupRotationInfo, Hash, Id as ParaId, OccupiedCoreAssumption,
+ PersistedValidationData, PoV, SessionIndex, SignedAvailabilityBitfield,
+ TransientValidationData, ValidationCode, ValidatorId, ValidationData,
+ ValidatorIndex, ValidatorSignature,
};
use std::sync::Arc;
@@ -336,6 +337,9 @@ pub enum ChainApiMessage {
/// Request the block number by hash.
/// Returns `None` if a block with the given hash is not present in the db.
BlockNumber(Hash, ChainApiResponseChannel