diff --git a/client/finality-grandpa/src/aux_schema.rs b/client/finality-grandpa/src/aux_schema.rs index cac8e566d2636..beb2103ec4272 100644 --- a/client/finality-grandpa/src/aux_schema.rs +++ b/client/finality-grandpa/src/aux_schema.rs @@ -36,6 +36,7 @@ use crate::NewAuthoritySet; const VERSION_KEY: &[u8] = b"grandpa_schema_version"; const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; +const CONCLUDED_ROUNDS: &[u8] = b"grandpa_concluded_rounds"; const AUTHORITY_SET_KEY: &[u8] = b"grandpa_voters"; const CONSENSUS_CHANGES_KEY: &[u8] = b"grandpa_consensus_changes"; @@ -405,6 +406,18 @@ pub(crate) fn write_voter_set_state( ) } +/// Write concluded round. +pub(crate) fn write_concluded_round( + backend: &B, + round_data: &CompletedRound, +) -> ClientResult<()> { + let mut key = CONCLUDED_ROUNDS.to_vec(); + let round_number = round_data.number; + round_number.using_encoded(|n| key.extend(n)); + + backend.insert_aux(&[(&key[..], round_data.encode().as_slice())], &[]) +} + /// Update the consensus changes. pub(crate) fn update_consensus_changes( set: &ConsensusChanges, @@ -608,4 +621,29 @@ mod test { }, ); } + + #[test] + fn write_read_concluded_rounds() { + let client = test_client::new(); + let hash = H256::random(); + let round_state = RoundState::genesis((hash, 0)); + + let completed_round = CompletedRound:: { + number: 42, + state: round_state.clone(), + base: round_state.prevote_ghost.unwrap(), + votes: vec![], + }; + + assert!(write_concluded_round(&client, &completed_round).is_ok()); + + let round_number = completed_round.number; + let mut key = CONCLUDED_ROUNDS.to_vec(); + round_number.using_encoded(|n| key.extend(n)); + + assert_eq!( + load_decode::<_, CompletedRound::>(&client, &key).unwrap(), + Some(completed_round), + ); + } } diff --git a/client/finality-grandpa/src/environment.rs b/client/finality-grandpa/src/environment.rs index af6e03743a42d..bc04ecef043f5 100644 --- a/client/finality-grandpa/src/environment.rs +++ b/client/finality-grandpa/src/environment.rs @@ -865,6 +865,7 @@ where historical_votes.seen().iter().skip(n_existing_votes).cloned() ); already_completed.state = state; + crate::aux_schema::write_concluded_round(&*self.client, &already_completed); } let set_state = VoterSetState::::Live {