diff --git a/toolkit/pallets/block-production-log/src/lib.rs b/toolkit/pallets/block-production-log/src/lib.rs index 3f76bd88d..892335523 100644 --- a/toolkit/pallets/block-production-log/src/lib.rs +++ b/toolkit/pallets/block-production-log/src/lib.rs @@ -35,6 +35,10 @@ pub mod pallet { #[pallet::unbounded] pub type Log = StorageValue<_, Vec<(Slot, T::BlockProducerId)>, ValueQuery>; + /// Temporary storage of the current block's producer, to be appended to the log on block finalization. + #[pallet::storage] + pub type CurrentProducer = StorageValue<_, T::BlockProducerId, OptionQuery>; + /// This storage is used to prevent calling `append` multiple times for the same block or for past blocks. #[pallet::storage] pub type LatestBlock = StorageValue<_, BlockNumberFor, OptionQuery>; @@ -70,7 +74,7 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// Appends an entry to the log. Log has to be ordered by slots and writing the same slot twice is forbidden. + /// Schedules an entry to be appended to the log. Log has to be ordered by slots and writing the same slot twice is forbidden. #[pallet::call_index(0)] #[pallet::weight((T::WeightInfo::append(), DispatchClass::Mandatory))] pub fn append( @@ -86,7 +90,19 @@ pub mod pallet { }?; LatestBlock::::put(current_block); - Ok(Log::::append((T::current_slot(), block_producer_id))) + Ok(CurrentProducer::::put(block_producer_id)) + } + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_finalize(block: BlockNumberFor) { + let block_producer_id = + CurrentProducer::::take().expect("Author is set before on_finalize; qed"); + + log::info!("👷 Block {block:?} producer is {block_producer_id:?}"); + + Log::::append((T::current_slot(), block_producer_id)) } } @@ -96,5 +112,15 @@ pub mod pallet { Log::::put(to_retain); to_return } + + pub fn peek_prefix<'a>(slot: Slot) -> impl Iterator { + Log::::get().into_iter().filter(move |(s, _)| s <= &slot) + } + + pub fn drop_prefix<'a>(slot: Slot) { + let entries_left: Vec<_> = + Log::::get().into_iter().filter(move |(s, _)| s > &slot).collect(); + Log::::put(entries_left); + } } } diff --git a/toolkit/pallets/block-production-log/src/test.rs b/toolkit/pallets/block-production-log/src/test.rs index e8a154f18..de544e84b 100644 --- a/toolkit/pallets/block-production-log/src/test.rs +++ b/toolkit/pallets/block-production-log/src/test.rs @@ -1,5 +1,8 @@ use super::*; -use frame_support::{assert_err, assert_ok, traits::UnfilteredDispatchable}; +use frame_support::{ + assert_err, assert_ok, + traits::{Hooks, UnfilteredDispatchable}, +}; use mock::*; use sp_consensus_slots::Slot; @@ -15,6 +18,13 @@ fn first_append_should_succeed() { let call = Call::::append { block_producer_id: make_id(1) }; assert_ok!(call.dispatch_bypass_filter(RuntimeOrigin::none())); + assert_eq!(CurrentProducer::::get(), Some(make_id(1))); + + // Log should not be appended to until block finalization + assert!(Log::::get().is_empty()); + + Pallet::::on_finalize(System::block_number()); + assert_eq!(Log::::get().to_vec(), vec![(Slot::from(1001000), make_id(1))]); }) } @@ -29,6 +39,10 @@ fn append_to_end_of_log() { let call = Call::::append { block_producer_id: make_id(2) }; assert_ok!(call.dispatch_bypass_filter(RuntimeOrigin::none())); assert_eq!(LatestBlock::::get(), Some(1001)); + assert_eq!(CurrentProducer::::get(), Some(make_id(2))); + + Pallet::::on_finalize(System::block_number()); + assert_eq!( Log::::get().to_vec(), vec![(Slot::from(100), make_id(1)), (Slot::from(1001000), make_id(2))]