Skip to content

Commit 95a744f

Browse files
committed
check babe block signature prior to blocking verification in aura import queue
1 parent 839ed65 commit 95a744f

File tree

1 file changed

+43
-31
lines changed

1 file changed

+43
-31
lines changed

node/src/consensus/aura_wrapped_import_queue.rs

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use sc_consensus_slots::InherentDataProviderExt;
1414
use sc_telemetry::TelemetryHandle;
1515
use sp_api::ApiExt;
1616
use sp_api::ProvideRuntimeApi;
17+
use sp_application_crypto::Ss58Codec as _;
1718
use sp_block_builder::BlockBuilder as BlockBuilderApi;
1819
use sp_blockchain::HeaderBackend;
1920
use sp_blockchain::HeaderMetadata;
@@ -24,7 +25,6 @@ use sp_consensus_aura::sr25519::AuthorityPair as AuraAuthorityPair;
2425
use sp_consensus_babe::AuthorityId as BabeAuthorityId;
2526
use sp_consensus_babe::AuthorityPair as BabeAuthorityPair;
2627
use sp_consensus_babe::BABE_ENGINE_ID;
27-
use sp_consensus_babe::BabeApi;
2828
use sp_core::Pair;
2929
use sp_inherents::CreateInherentDataProviders;
3030
use sp_runtime::Digest;
@@ -51,7 +51,7 @@ where
5151
CIDP: CreateInherentDataProviders<B, ()> + Send + Sync,
5252
CIDP::InherentDataProviders: InherentDataProviderExt + Send + Sync,
5353
C: ProvideRuntimeApi<B> + Send + Sync + sc_client_api::backend::AuxStore,
54-
C::Api: BlockBuilderApi<B> + AuraApi<B, AuraAuthorityId> + ApiExt<B> + BabeApi<B>,
54+
C::Api: BlockBuilderApi<B> + AuraApi<B, AuraAuthorityId> + ApiExt<B>,
5555
C: HeaderBackend<B> + HeaderMetadata<B>,
5656
{
5757
pub fn new(
@@ -86,52 +86,64 @@ where
8686
///
8787
/// The Babe block will be verified in full after the node spins back up as a Babe service.
8888
async fn check_babe_block(&self, block: BlockImportParams<B>) -> Result<(), String> {
89-
use sp_core::crypto::Ss58Codec;
90-
89+
log::info!(
90+
"Checking Babe block {:?} is legitimate",
91+
block.post_header().hash()
92+
);
9193
let mut header = block.header.clone();
92-
93-
let _parent_header = self
94-
.client
95-
.header(*block.post_header().parent_hash())
96-
.map_err(|e| format!("Failed to get parent header: {}", e))?
97-
.ok_or("Parent header not found".to_string())?;
98-
99-
let _pre_digest = sc_consensus_babe::find_pre_digest::<B>(&block.header)?
100-
.ok_or("No predigest".to_string())?;
101-
10294
let seal = header
10395
.digest_mut()
10496
.pop()
10597
.ok_or_else(|| "Header Unsealed".to_string())?;
106-
10798
let sig = seal
10899
.as_babe_seal()
109100
.ok_or_else(|| "Header bad seal".to_string())?;
110101

111-
// the pre-hash of the header doesn't include the seal
112-
// and that's what we sign
113-
let pre_hash = header.hash();
114-
115-
// Alice pub key
116-
// TODO: Make this based on last Aura authorities, not just Alice.
117-
let public =
118-
BabeAuthorityId::from_ss58check("5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY")
119-
.unwrap();
120-
if !BabeAuthorityPair::verify(&sig, pre_hash, &public) {
121-
return Ok(());
122-
// TODO: Return Err
123-
// return Err("Bad Sig".to_string());
102+
let authorities = self.get_last_aura_authorities(block.header)?;
103+
if let Some(a) = authorities.into_iter().find(|a| {
104+
let babe_key = BabeAuthorityId::from(a.clone().into_inner());
105+
BabeAuthorityPair::verify(&sig, header.hash(), &babe_key)
106+
}) {
107+
log::info!(
108+
"Babe block has a valid signature by author: {}",
109+
a.to_ss58check()
110+
);
111+
Ok(())
112+
} else {
113+
Err("Babe block has a bad signature. Rejecting.".to_string())
124114
}
115+
}
116+
117+
/// Given the hash of the first Babe block mined, get the Aura authorities that existed prior to
118+
/// the runtime upgrade.
119+
///
120+
/// Note: We need get the Aura authorities from grandparent rather than the parent,
121+
/// because the runtime upgrade clearing the Aura authorities occurs in the parent.
122+
fn get_last_aura_authorities(
123+
&self,
124+
first_babe_block_header: B::Header,
125+
) -> Result<Vec<AuraAuthorityId>, String> {
126+
let parent_header = self
127+
.client
128+
.header(*first_babe_block_header.parent_hash())
129+
.map_err(|e| format!("Failed to get parent header: {}", e))?
130+
.ok_or("Parent header not found".to_string())?;
131+
let grandparent_hash = parent_header.parent_hash();
132+
133+
let runtime_api = self.client.runtime_api();
134+
let authorities = runtime_api
135+
.authorities(*grandparent_hash)
136+
.map_err(|e| format!("Failed to get Aura authorities: {}", e))?;
125137

126-
Ok(())
138+
Ok(authorities)
127139
}
128140
}
129141

130142
#[async_trait::async_trait]
131143
impl<B: BlockT, C, CIDP> Verifier<B> for AuraWrappedVerifier<B, C, CIDP, NumberFor<B>>
132144
where
133145
C: ProvideRuntimeApi<B> + Send + Sync + sc_client_api::backend::AuxStore,
134-
C::Api: BlockBuilderApi<B> + AuraApi<B, AuraAuthorityId> + ApiExt<B> + BabeApi<B>,
146+
C::Api: BlockBuilderApi<B> + AuraApi<B, AuraAuthorityId> + ApiExt<B>,
135147
C: HeaderBackend<B> + HeaderMetadata<B>,
136148
CIDP: CreateInherentDataProviders<B, ()> + Send + Sync,
137149
CIDP::InherentDataProviders: InherentDataProviderExt + Send + Sync,
@@ -158,7 +170,7 @@ pub fn import_queue<B, I, C, S, CIDP>(
158170
) -> Result<DefaultImportQueue<B>, sp_consensus::Error>
159171
where
160172
B: BlockT,
161-
C::Api: BlockBuilderApi<B> + AuraApi<B, AuraAuthorityId> + ApiExt<B> + BabeApi<B>,
173+
C::Api: BlockBuilderApi<B> + AuraApi<B, AuraAuthorityId> + ApiExt<B>,
162174
C: 'static
163175
+ ProvideRuntimeApi<B>
164176
+ BlockOf

0 commit comments

Comments
 (0)