From e2ee6a2b90a80e9197bdf4283075c2ab5be85d87 Mon Sep 17 00:00:00 2001
From: Robert Habermeier <rphmeier@gmail.com>
Date: Mon, 29 Oct 2018 02:31:51 +0100
Subject: [PATCH] read authority set from DB on startup

---
 .../finality-grandpa/primitives/src/lib.rs    |  6 ++--
 .../core/finality-grandpa/src/authorities.rs  | 10 -------
 substrate/core/finality-grandpa/src/lib.rs    | 28 +++++++++++++++----
 3 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/substrate/core/finality-grandpa/primitives/src/lib.rs b/substrate/core/finality-grandpa/primitives/src/lib.rs
index 047c37632a8..ddf924cc2e0 100644
--- a/substrate/core/finality-grandpa/primitives/src/lib.rs
+++ b/substrate/core/finality-grandpa/primitives/src/lib.rs
@@ -44,7 +44,7 @@ pub struct ScheduledChange<N> {
 /// WASM function call to check for pending changes.
 pub const PENDING_CHANGE_CALL: &str = "grandpa_pending_change";
 /// WASM function call to get current GRANDPA authorities.
-pub const AUTHORITIES_CALL: &str = "grandpa_pending_change";
+pub const AUTHORITIES_CALL: &str = "grandpa_authorities";
 
 decl_apis! {
 	/// APIs for integrating the GRANDPA finality gadget into runtimes.
@@ -66,8 +66,8 @@ decl_apis! {
 		/// passed completely.
 		fn grandpa_pending_change(digest: DigestFor<B>) -> Option<ScheduledChange<NumberFor<B>>>;
 
-		/// Get the current GRANDPA authorities. This should not change except
+		/// Get the current GRANDPA authorities and weights. This should not change except
 		/// for when changes are scheduled and the corresponding delay has passed.
-		fn grandpa_authorities() -> Vec<AuthorityId>;
+		fn grandpa_authorities() -> Vec<(AuthorityId, u64)>;
 	}
 }
diff --git a/substrate/core/finality-grandpa/src/authorities.rs b/substrate/core/finality-grandpa/src/authorities.rs
index 7896c084950..6a32e3ddb7c 100644
--- a/substrate/core/finality-grandpa/src/authorities.rs
+++ b/substrate/core/finality-grandpa/src/authorities.rs
@@ -56,11 +56,6 @@ impl<H, N> SharedAuthoritySet<H, N> {
 impl<H: Eq, N> SharedAuthoritySet<H, N>
 	where N: Add<Output=N> + Ord + Clone + Debug
 {
-	/// Note an upcoming pending transition.
-	pub(crate) fn add_pending_change(&self, pending: PendingChange<H, N>) {
-		self.inner.write().add_pending_change(pending)
-	}
-
 	/// Get the earliest limit-block number, if any.
 	pub(crate) fn current_limit(&self) -> Option<N> {
 		self.inner.read().current_limit()
@@ -96,11 +91,6 @@ pub(crate) struct AuthoritySet<H, N> {
 }
 
 impl<H, N> AuthoritySet<H, N> {
-	/// Get the set identifier.
-	pub(crate) fn set_id(&self) -> u64 {
-		self.set_id
-	}
-
 	/// Get the current set id and a reference to the current authority set.
 	pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) {
 		(self.set_id, &self.current_authorities[..])
diff --git a/substrate/core/finality-grandpa/src/lib.rs b/substrate/core/finality-grandpa/src/lib.rs
index 58de2553b3f..2291c0c8237 100644
--- a/substrate/core/finality-grandpa/src/lib.rs
+++ b/substrate/core/finality-grandpa/src/lib.rs
@@ -712,7 +712,6 @@ impl<B, E, Block: BlockT> BlockImport<Block> for GrandpaBlockImport<B, E, Block>
 	fn import_block(&self, mut block: ImportBlock<Block>, new_authorities: Option<Vec<AuthorityId>>)
 		-> Result<ImportResult, Self::Error>
 	{
-		use runtime_primitives::traits::Digest;
 		use authorities::PendingChange;
 
 		let maybe_change: Option<ScheduledChange<NumberFor<Block>>> = self.inner.call_api_at(
@@ -779,10 +778,29 @@ pub fn run_grandpa<B, E, Block: BlockT, N>(
 	let chain_info = client.info()?;
 	let genesis_hash = chain_info.chain.genesis_hash;
 
-	// TODO [now]: attempt to load from disk.
-	let authority_set = SharedAuthoritySet::genesis(
-		voters.iter().map(|(&id, &weight)| (id, weight)).collect(),
-	);
+	let authority_set = match client.backend().get_aux(AUTHORITY_SET_KEY)? {
+		None => {
+			info!(target: "afg", "Loading GRANDPA authorities \
+				from genesis on what appears to be first startup.");
+
+			// no authority set on disk: fetch authorities from genesis state.
+			// if genesis state is not available, we may be a light client, but these
+			// are unsupported for following GRANDPA directly.
+			let genesis_authorities: Vec<(AuthorityId, u64)> = client
+				.call_api_at(&BlockId::Number(NumberFor::<Block>::zero()), fg_primitives::AUTHORITIES_CALL, &())?;
+
+			let authority_set = SharedAuthoritySet::genesis(genesis_authorities);
+			let encoded = authority_set.inner().read().encode();
+			client.backend().insert_aux(&[(AUTHORITY_SET_KEY, &encoded[..])], &[])?;
+
+			authority_set
+		}
+		Some(raw) => ::authorities::AuthoritySet::decode(&mut &raw[..])
+			.ok_or_else(|| ::client::error::ErrorKind::Backend(
+				format!("GRANDPA authority set kept in invalid format")
+			))?
+			.into(),
+	};
 
 	let block_import = GrandpaBlockImport {
 		inner: client.clone(),
-- 
GitLab