polkadot_subsystem_bench/mock/
chain_api.rs1use futures::FutureExt;
20use itertools::Itertools;
21use polkadot_node_subsystem::{
22 messages::ChainApiMessage, overseer, SpawnedSubsystem, SubsystemError,
23};
24use polkadot_node_subsystem_types::OverseerSignal;
25use polkadot_primitives::Header;
26use sp_core::H256;
27use std::collections::HashMap;
28
29const LOG_TARGET: &str = "subsystem-bench::chain-api-mock";
30
31pub struct ChainApiState {
33 pub block_headers: HashMap<H256, Header>,
34}
35
36pub struct MockChainApi {
37 state: ChainApiState,
38}
39
40impl ChainApiState {
41 fn get_header_by_number(&self, requested_number: u32) -> Option<&Header> {
42 self.block_headers.values().find(|header| header.number == requested_number)
43 }
44}
45
46impl MockChainApi {
47 pub fn new(state: ChainApiState) -> MockChainApi {
48 Self { state }
49 }
50}
51
52#[overseer::subsystem(ChainApi, error=SubsystemError, prefix=self::overseer)]
53impl<Context> MockChainApi {
54 fn start(self, ctx: Context) -> SpawnedSubsystem {
55 let future = self.run(ctx).map(|_| Ok(())).boxed();
56
57 SpawnedSubsystem { name: "test-environment", future }
58 }
59}
60
61#[overseer::contextbounds(ChainApi, prefix = self::overseer)]
62impl MockChainApi {
63 async fn run<Context>(self, mut ctx: Context) {
64 loop {
65 let msg = ctx.recv().await.expect("Overseer never fails us");
66
67 match msg {
68 orchestra::FromOrchestra::Signal(signal) =>
69 if signal == OverseerSignal::Conclude {
70 return
71 },
72 orchestra::FromOrchestra::Communication { msg } => {
73 gum::debug!(target: LOG_TARGET, msg=?msg, "recv message");
74
75 match msg {
76 ChainApiMessage::BlockHeader(hash, response_channel) => {
77 let _ = response_channel.send(Ok(Some(
78 self.state
79 .block_headers
80 .get(&hash)
81 .cloned()
82 .expect("Relay chain block hashes are known"),
83 )));
84 },
85 ChainApiMessage::FinalizedBlockNumber(val) => {
86 val.send(Ok(0)).unwrap();
87 },
88 ChainApiMessage::FinalizedBlockHash(requested_number, sender) => {
89 let hash = self
90 .state
91 .get_header_by_number(requested_number)
92 .expect("Unknown block number")
93 .hash();
94 sender.send(Ok(Some(hash))).unwrap();
95 },
96 ChainApiMessage::BlockNumber(requested_hash, sender) => {
97 sender
98 .send(Ok(Some(
99 self.state
100 .block_headers
101 .get(&requested_hash)
102 .expect("Unknown block hash")
103 .number,
104 )))
105 .unwrap();
106 },
107 ChainApiMessage::Ancestors { hash, k: _, response_channel } => {
108 let block_number = self
109 .state
110 .block_headers
111 .get(&hash)
112 .expect("Unknown block hash")
113 .number;
114 let ancestors = self
115 .state
116 .block_headers
117 .iter()
118 .filter(|(_, header)| header.number < block_number)
119 .sorted_by(|a, b| a.1.number.cmp(&b.1.number))
120 .map(|(hash, _)| *hash)
121 .collect_vec();
122 response_channel.send(Ok(ancestors)).unwrap();
123 },
124 _ => {
125 unimplemented!("Unexpected chain-api message")
126 },
127 }
128 },
129 }
130 }
131 }
132}