diff --git a/polkadot/node/core/chain-api/src/lib.rs b/polkadot/node/core/chain-api/src/lib.rs index 350a76bb0e..15cdfef1a6 100644 --- a/polkadot/node/core/chain-api/src/lib.rs +++ b/polkadot/node/core/chain-api/src/lib.rs @@ -145,7 +145,7 @@ where Ok(None) => None, Ok(Some(header)) => { // stop at the genesis header. - if header.number == 1 { + if header.number == 0 { None } else { hash = header.parent_hash; diff --git a/polkadot/node/core/chain-api/src/tests.rs b/polkadot/node/core/chain-api/src/tests.rs index 3f28a3e269..ca89f05467 100644 --- a/polkadot/node/core/chain-api/src/tests.rs +++ b/polkadot/node/core/chain-api/src/tests.rs @@ -18,6 +18,7 @@ struct TestClient { headers: BTreeMap, } +const GENESIS: Hash = Hash::repeat_byte(0xAA); const ONE: Hash = Hash::repeat_byte(0x01); const TWO: Hash = Hash::repeat_byte(0x02); const THREE: Hash = Hash::repeat_byte(0x03); @@ -38,6 +39,7 @@ impl Default for TestClient { fn default() -> Self { Self { blocks: maplit::btreemap! { + GENESIS => 0, ONE => 1, TWO => 2, THREE => 3, @@ -54,6 +56,16 @@ impl Default for TestClient { 3 => THREE, }, headers: maplit::btreemap! { + GENESIS => Header { + parent_hash: Hash::zero(), // Dummy parent with zero hash. + number: 0, + ..default_header() + }, + ONE => Header { + parent_hash: GENESIS, + number: 1, + ..default_header() + }, TWO => Header { parent_hash: ONE, number: 2, @@ -298,8 +310,9 @@ fn request_ancestors() { msg: ChainApiMessage::Ancestors { hash: THREE, k: 4, response_channel: tx }, }) .await; - assert_eq!(rx.await.unwrap().unwrap(), vec![TWO, ONE]); + assert_eq!(rx.await.unwrap().unwrap(), vec![TWO, ONE, GENESIS]); + // Limit the number of ancestors. let (tx, rx) = oneshot::channel(); sender .send(FromOverseer::Communication { @@ -308,6 +321,24 @@ fn request_ancestors() { .await; assert_eq!(rx.await.unwrap().unwrap(), vec![ONE]); + // Ancestor of block #1 is returned. + let (tx, rx) = oneshot::channel(); + sender + .send(FromOverseer::Communication { + msg: ChainApiMessage::Ancestors { hash: ONE, k: 10, response_channel: tx }, + }) + .await; + assert_eq!(rx.await.unwrap().unwrap(), vec![GENESIS]); + + // No ancestors of genesis block. + let (tx, rx) = oneshot::channel(); + sender + .send(FromOverseer::Communication { + msg: ChainApiMessage::Ancestors { hash: GENESIS, k: 10, response_channel: tx }, + }) + .await; + assert_eq!(rx.await.unwrap().unwrap(), Vec::new()); + let (tx, rx) = oneshot::channel(); sender .send(FromOverseer::Communication { diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 6be22c2b5b..0aa6b1abb4 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -558,7 +558,8 @@ pub enum ChainApiMessage { /// Request the `k` ancestors block hashes of a block with the given hash. /// The response channel may return a `Vec` of size up to `k` /// filled with ancestors hashes with the following order: - /// `parent`, `grandparent`, ... + /// `parent`, `grandparent`, ... up to the hash of genesis block + /// with number 0, including it. Ancestors { /// The hash of the block in question. hash: Hash,