Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 93da950

Browse files
committed
grandpa: Use storage proofs for Grandpa authorities
1 parent 0eeee4d commit 93da950

File tree

16 files changed

+289
-149
lines changed

16 files changed

+289
-149
lines changed

core/finality-grandpa/primitives/src/lib.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ extern crate alloc;
2323

2424
#[cfg(feature = "std")]
2525
use serde::Serialize;
26-
use codec::{Encode, Decode, Codec};
26+
use codec::{Encode, Decode, Input, Codec};
2727
use sr_primitives::{ConsensusEngineId, RuntimeDebug};
2828
use client::decl_runtime_apis;
29+
use rstd::borrow::Cow;
2930
use rstd::vec::Vec;
3031

3132
mod app {
@@ -46,6 +47,10 @@ pub type AuthoritySignature = app::Signature;
4647
/// The `ConsensusEngineId` of GRANDPA.
4748
pub const GRANDPA_ENGINE_ID: ConsensusEngineId = *b"FRNK";
4849

50+
/// The storage key for the current set of weighted Grandpa authorities.
51+
/// The value stored is an encoded VersionedAuthorityList.
52+
pub const GRANDPA_AUTHORITIES_KEY: &'static [u8] = b":grandpa_authorities";
53+
4954
/// The weight of an authority.
5055
pub type AuthorityWeight = u64;
5156

@@ -58,12 +63,15 @@ pub type SetId = u64;
5863
/// The round indicator.
5964
pub type RoundNumber = u64;
6065

66+
/// A list of Grandpa authorities with associated weights.
67+
pub type AuthorityList = Vec<(AuthorityId, AuthorityWeight)>;
68+
6169
/// A scheduled change of authority set.
6270
#[cfg_attr(feature = "std", derive(Serialize))]
6371
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug)]
6472
pub struct ScheduledChange<N> {
6573
/// The new authorities after the change, along with their respective weights.
66-
pub next_authorities: Vec<(AuthorityId, AuthorityWeight)>,
74+
pub next_authorities: AuthorityList,
6775
/// The number of blocks to delay.
6876
pub delay: N,
6977
}
@@ -154,6 +162,55 @@ pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change";
154162
/// WASM function call to get current GRANDPA authorities.
155163
pub const AUTHORITIES_CALL: &str = "grandpa_authorities";
156164

165+
/// The current version of the stored AuthorityList type. The encoding version MUST be updated any
166+
/// time the AuthorityList type changes.
167+
const AUTHORITIES_VERISON: u8 = 1;
168+
169+
/// An AuthorityList that is encoded with a version specifier. The encoding version is updated any
170+
/// time the AuthorityList type changes. This ensures that encodings of different versions of an
171+
/// AuthorityList are differentiable. Attempting to decode an authority list with an unknown
172+
/// version will fail.
173+
#[derive(Default)]
174+
pub struct VersionedAuthorityList<'a>(Cow<'a, AuthorityList>);
175+
176+
impl<'a> From<AuthorityList> for VersionedAuthorityList<'a> {
177+
fn from(authorities: AuthorityList) -> Self {
178+
VersionedAuthorityList(Cow::Owned(authorities))
179+
}
180+
}
181+
182+
impl<'a> From<&'a AuthorityList> for VersionedAuthorityList<'a> {
183+
fn from(authorities: &'a AuthorityList) -> Self {
184+
VersionedAuthorityList(Cow::Borrowed(authorities))
185+
}
186+
}
187+
188+
impl<'a> Into<AuthorityList> for VersionedAuthorityList<'a> {
189+
fn into(self) -> AuthorityList {
190+
self.0.into_owned()
191+
}
192+
}
193+
194+
impl<'a> Encode for VersionedAuthorityList<'a> {
195+
fn size_hint(&self) -> usize {
196+
(AUTHORITIES_VERISON, self.0.as_ref()).size_hint()
197+
}
198+
199+
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
200+
(AUTHORITIES_VERISON, self.0.as_ref()).using_encoded(f)
201+
}
202+
}
203+
204+
impl<'a> Decode for VersionedAuthorityList<'a> {
205+
fn decode<I: Input>(value: &mut I) -> Result<Self, codec::Error> {
206+
let (version, authorities): (u8, AuthorityList) = Decode::decode(value)?;
207+
if version != AUTHORITIES_VERISON {
208+
return Err("unknown Grandpa authorities version".into());
209+
}
210+
Ok(authorities.into())
211+
}
212+
}
213+
157214
decl_runtime_apis! {
158215
/// APIs for integrating the GRANDPA finality gadget into runtimes.
159216
/// This should be implemented on the runtime side.
@@ -172,6 +229,6 @@ decl_runtime_apis! {
172229
/// When called at block B, it will return the set of authorities that should be
173230
/// used to finalize descendants of this block (B+1, B+2, ...). The block B itself
174231
/// is finalized by the authorities from block B-1.
175-
fn grandpa_authorities() -> Vec<(AuthorityId, AuthorityWeight)>;
232+
fn grandpa_authorities() -> AuthorityList;
176233
}
177234
}

core/finality-grandpa/src/authorities.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use grandpa::voter_set::VoterSet;
2222
use codec::{Encode, Decode};
2323
use log::{debug, info};
2424
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
25-
use fg_primitives::AuthorityId;
25+
use fg_primitives::{AuthorityId, AuthorityList};
2626

2727
use std::cmp::Ord;
2828
use std::fmt::Debug;
@@ -86,7 +86,7 @@ pub(crate) struct Status<H, N> {
8686
/// A set of authorities.
8787
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
8888
pub(crate) struct AuthoritySet<H, N> {
89-
pub(crate) current_authorities: Vec<(AuthorityId, u64)>,
89+
pub(crate) current_authorities: AuthorityList,
9090
pub(crate) set_id: u64,
9191
// Tree of pending standard changes across forks. Standard changes are
9292
// enacted on finality and must be enacted (i.e. finalized) in-order across
@@ -103,7 +103,7 @@ where H: PartialEq,
103103
N: Ord,
104104
{
105105
/// Get a genesis set with given authorities.
106-
pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self {
106+
pub(crate) fn genesis(initial: AuthorityList) -> Self {
107107
AuthoritySet {
108108
current_authorities: initial,
109109
set_id: 0,
@@ -390,7 +390,7 @@ pub(crate) enum DelayKind<N> {
390390
#[derive(Debug, Clone, Encode, PartialEq)]
391391
pub(crate) struct PendingChange<H, N> {
392392
/// The new authorities and weights to apply.
393-
pub(crate) next_authorities: Vec<(AuthorityId, u64)>,
393+
pub(crate) next_authorities: AuthorityList,
394394
/// How deep in the chain the announcing block must be
395395
/// before the change is applied.
396396
pub(crate) delay: N,

core/finality-grandpa/src/aux_schema.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use fork_tree::ForkTree;
2525
use grandpa::round::State as RoundState;
2626
use sr_primitives::traits::{Block as BlockT, NumberFor};
2727
use log::{info, warn};
28-
use fg_primitives::{AuthorityId, AuthorityWeight, SetId, RoundNumber};
28+
use fg_primitives::{AuthorityList, SetId, RoundNumber};
2929

3030
use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind};
3131
use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges};
@@ -55,15 +55,15 @@ type V0VoterSetState<H, N> = (RoundNumber, RoundState<H, N>);
5555

5656
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
5757
struct V0PendingChange<H, N> {
58-
next_authorities: Vec<(AuthorityId, AuthorityWeight)>,
58+
next_authorities: AuthorityList,
5959
delay: N,
6060
canon_height: N,
6161
canon_hash: H,
6262
}
6363

6464
#[derive(Debug, Clone, Encode, Decode, PartialEq)]
6565
struct V0AuthoritySet<H, N> {
66-
current_authorities: Vec<(AuthorityId, AuthorityWeight)>,
66+
current_authorities: AuthorityList,
6767
set_id: SetId,
6868
pending_changes: Vec<V0PendingChange<H, N>>,
6969
}
@@ -266,7 +266,7 @@ pub(crate) fn load_persistent<Block: BlockT, B, G>(
266266
-> ClientResult<PersistentData<Block>>
267267
where
268268
B: AuxStore,
269-
G: FnOnce() -> ClientResult<Vec<(AuthorityId, AuthorityWeight)>>,
269+
G: FnOnce() -> ClientResult<AuthorityList>,
270270
{
271271
let version: Option<u32> = load_decode(backend, VERSION_KEY)?;
272272
let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)?
@@ -426,6 +426,7 @@ pub(crate) fn load_authorities<B: AuxStore, H: Decode, N: Decode>(backend: &B)
426426

427427
#[cfg(test)]
428428
mod test {
429+
use fg_primitives::AuthorityId;
429430
use primitives::H256;
430431
use test_client;
431432
use super::*;

core/finality-grandpa/src/communication/tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use codec::Encode;
2828
use sr_primitives::traits::NumberFor;
2929

3030
use crate::environment::SharedVoterSetState;
31+
use fg_primitives::AuthorityList;
3132
use super::gossip::{self, GossipValidator};
3233
use super::{AuthorityId, VoterSet, Round, SetId};
3334

@@ -200,7 +201,7 @@ fn make_test_network() -> (
200201
)
201202
}
202203

203-
fn make_ids(keys: &[Ed25519Keyring]) -> Vec<(AuthorityId, u64)> {
204+
fn make_ids(keys: &[Ed25519Keyring]) -> AuthorityList {
204205
keys.iter()
205206
.map(|key| key.clone().public().into())
206207
.map(|id| (id, 1))

core/finality-grandpa/src/finality_proof.rs

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,24 @@
3434
//! finality proof (that finalizes some block C that is ancestor of the B and descendant
3535
//! of the U) could be returned.
3636
37+
use std::iter;
3738
use std::sync::Arc;
3839
use log::{trace, warn};
3940

4041
use client::{
4142
backend::Backend, blockchain::Backend as BlockchainBackend, CallExecutor, Client,
4243
error::{Error as ClientError, Result as ClientResult},
43-
light::fetcher::{FetchChecker, RemoteCallRequest, StorageProof}, ExecutionStrategy,
44+
light::fetcher::{FetchChecker, RemoteReadRequest, StorageProof},
4445
};
4546
use codec::{Encode, Decode};
4647
use grandpa::BlockNumberOps;
4748
use sr_primitives::{
4849
Justification, generic::BlockId,
4950
traits::{NumberFor, Block as BlockT, Header as HeaderT, One},
5051
};
51-
use primitives::{H256, Blake2Hasher};
52+
use primitives::{H256, Blake2Hasher, storage::StorageKey};
5253
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
53-
use fg_primitives::AuthorityId;
54+
use fg_primitives::{AuthorityId, AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY};
5455

5556
use crate::justification::GrandpaJustification;
5657

@@ -59,9 +60,9 @@ const MAX_FRAGMENTS_IN_PROOF: usize = 8;
5960

6061
/// GRANDPA authority set related methods for the finality proof provider.
6162
pub trait AuthoritySetForFinalityProver<Block: BlockT>: Send + Sync {
62-
/// Call GrandpaApi::grandpa_authorities at given block.
63-
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>>;
64-
/// Prove call of GrandpaApi::grandpa_authorities at given block.
63+
/// Read GRANDPA_AUTHORITIES_KEY from storage at given block.
64+
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList>;
65+
/// Prove storage read of GRANDPA_AUTHORITIES_KEY at given block.
6566
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof>;
6667
}
6768

@@ -72,33 +73,28 @@ impl<B, E, Block: BlockT<Hash=H256>, RA> AuthoritySetForFinalityProver<Block> fo
7273
E: CallExecutor<Block, Blake2Hasher> + 'static + Clone + Send + Sync,
7374
RA: Send + Sync,
7475
{
75-
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>> {
76-
self.executor().call(
77-
block,
78-
"GrandpaApi_grandpa_authorities",
79-
&[],
80-
ExecutionStrategy::NativeElseWasm,
81-
None,
82-
).and_then(|call_result| Decode::decode(&mut &call_result[..])
83-
.map_err(|err| ClientError::CallResultDecode(
84-
"failed to decode GRANDPA authorities set proof".into(), err
85-
)))
76+
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
77+
let storage_key = StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec());
78+
self.storage(block, &storage_key)?
79+
.and_then(|encoded| VersionedAuthorityList::decode(&mut encoded.0.as_slice()).ok())
80+
.map(|versioned| versioned.into())
81+
.ok_or(ClientError::InvalidAuthoritiesSet)
8682
}
8783

8884
fn prove_authorities(&self, block: &BlockId<Block>) -> ClientResult<StorageProof> {
89-
self.execution_proof(block, "GrandpaApi_grandpa_authorities",&[]).map(|(_, proof)| proof)
85+
self.read_proof(block, iter::once(GRANDPA_AUTHORITIES_KEY))
9086
}
9187
}
9288

9389
/// GRANDPA authority set related methods for the finality proof checker.
9490
pub trait AuthoritySetForFinalityChecker<Block: BlockT>: Send + Sync {
95-
/// Check execution proof of Grandpa::grandpa_authorities at given block.
91+
/// Check storage read proof of GRANDPA_AUTHORITIES_KEY at given block.
9692
fn check_authorities_proof(
9793
&self,
9894
hash: Block::Hash,
9995
header: Block::Header,
10096
proof: StorageProof,
101-
) -> ClientResult<Vec<(AuthorityId, u64)>>;
97+
) -> ClientResult<AuthorityList>;
10298
}
10399

104100
/// FetchChecker-based implementation of AuthoritySetForFinalityChecker.
@@ -108,22 +104,30 @@ impl<Block: BlockT> AuthoritySetForFinalityChecker<Block> for Arc<dyn FetchCheck
108104
hash: Block::Hash,
109105
header: Block::Header,
110106
proof: StorageProof,
111-
) -> ClientResult<Vec<(AuthorityId, u64)>> {
112-
let request = RemoteCallRequest {
107+
) -> ClientResult<AuthorityList> {
108+
let storage_key = GRANDPA_AUTHORITIES_KEY.to_vec();
109+
let request = RemoteReadRequest {
113110
block: hash,
114111
header,
115-
method: "GrandpaApi_grandpa_authorities".into(),
116-
call_data: vec![],
112+
keys: vec![storage_key.clone()],
117113
retry_count: None,
118114
};
119115

120-
self.check_execution_proof(&request, proof)
121-
.and_then(|authorities| {
122-
let authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &authorities[..])
123-
.map_err(|err| ClientError::CallResultDecode(
124-
"failed to decode GRANDPA authorities set proof".into(), err
125-
))?;
126-
Ok(authorities.into_iter().collect())
116+
self.check_read_proof(&request, proof)
117+
.and_then(|results| {
118+
let maybe_encoded = results.get(&storage_key)
119+
.expect(
120+
"storage_key is listed in the request keys; \
121+
check_read_proof must return a value for each requested key;
122+
qed"
123+
);
124+
maybe_encoded
125+
.as_ref()
126+
.and_then(|encoded| {
127+
VersionedAuthorityList::decode(&mut encoded.as_slice()).ok()
128+
})
129+
.map(|versioned| versioned.into())
130+
.ok_or(ClientError::InvalidAuthoritiesSet)
127131
})
128132
}
129133
}
@@ -189,7 +193,7 @@ pub struct FinalityEffects<Header: HeaderT> {
189193
/// New authorities set id that should be applied starting from block.
190194
pub new_set_id: u64,
191195
/// New authorities set that should be applied starting from block.
192-
pub new_authorities: Vec<(AuthorityId, u64)>,
196+
pub new_authorities: AuthorityList,
193197
}
194198

195199
/// Single fragment of proof-of-finality.
@@ -408,7 +412,7 @@ pub(crate) fn prove_finality<Block: BlockT<Hash=H256>, B: BlockchainBackend<Bloc
408412
pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
409413
blockchain: &B,
410414
current_set_id: u64,
411-
current_authorities: Vec<(AuthorityId, u64)>,
415+
current_authorities: AuthorityList,
412416
authorities_provider: &dyn AuthoritySetForFinalityChecker<Block>,
413417
remote_proof: Vec<u8>,
414418
) -> ClientResult<FinalityEffects<Block::Header>>
@@ -427,7 +431,7 @@ pub(crate) fn check_finality_proof<Block: BlockT<Hash=H256>, B>(
427431
fn do_check_finality_proof<Block: BlockT<Hash=H256>, B, J>(
428432
blockchain: &B,
429433
current_set_id: u64,
430-
current_authorities: Vec<(AuthorityId, u64)>,
434+
current_authorities: AuthorityList,
431435
authorities_provider: &dyn AuthoritySetForFinalityChecker<Block>,
432436
remote_proof: Vec<u8>,
433437
) -> ClientResult<FinalityEffects<Block::Header>>
@@ -522,12 +526,12 @@ fn check_finality_proof_fragment<Block: BlockT<Hash=H256>, B, J>(
522526

523527
/// Authorities set from initial authorities set or finality effects.
524528
enum AuthoritiesOrEffects<Header: HeaderT> {
525-
Authorities(u64, Vec<(AuthorityId, u64)>),
529+
Authorities(u64, AuthorityList),
526530
Effects(FinalityEffects<Header>),
527531
}
528532

529533
impl<Header: HeaderT> AuthoritiesOrEffects<Header> {
530-
pub fn extract_authorities(self) -> (u64, Vec<(AuthorityId, u64)>) {
534+
pub fn extract_authorities(self) -> (u64, AuthorityList) {
531535
match self {
532536
AuthoritiesOrEffects::Authorities(set_id, authorities) => (set_id, authorities),
533537
AuthoritiesOrEffects::Effects(effects) => (effects.new_set_id, effects.new_authorities),
@@ -581,10 +585,10 @@ pub(crate) mod tests {
581585

582586
impl<GetAuthorities, ProveAuthorities> AuthoritySetForFinalityProver<Block> for (GetAuthorities, ProveAuthorities)
583587
where
584-
GetAuthorities: Send + Sync + Fn(BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>>,
588+
GetAuthorities: Send + Sync + Fn(BlockId<Block>) -> ClientResult<AuthorityList>,
585589
ProveAuthorities: Send + Sync + Fn(BlockId<Block>) -> ClientResult<StorageProof>,
586590
{
587-
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<Vec<(AuthorityId, u64)>> {
591+
fn authorities(&self, block: &BlockId<Block>) -> ClientResult<AuthorityList> {
588592
self.0(*block)
589593
}
590594

@@ -597,14 +601,14 @@ pub(crate) mod tests {
597601

598602
impl<Closure> AuthoritySetForFinalityChecker<Block> for ClosureAuthoritySetForFinalityChecker<Closure>
599603
where
600-
Closure: Send + Sync + Fn(H256, Header, StorageProof) -> ClientResult<Vec<(AuthorityId, u64)>>,
604+
Closure: Send + Sync + Fn(H256, Header, StorageProof) -> ClientResult<AuthorityList>,
601605
{
602606
fn check_authorities_proof(
603607
&self,
604608
hash: H256,
605609
header: Header,
606-
proof: StorageProof,
607-
) -> ClientResult<Vec<(AuthorityId, u64)>> {
610+
proof: StorageProof
611+
) -> ClientResult<AuthorityList> {
608612
self.0(hash, header, proof)
609613
}
610614
}

0 commit comments

Comments
 (0)