diff --git a/primitives/src/rotate.rs b/primitives/src/rotate.rs index 2bafde3..7466e30 100644 --- a/primitives/src/rotate.rs +++ b/primitives/src/rotate.rs @@ -62,7 +62,7 @@ fn verify_encoding_epoch_end_header( decode_scale_compact_int(header_bytes[cursor..cursor + 5].to_vec()); cursor += decoded_byte_length; - // Verify the next byte after encoded scheduled change message is scheduled change enum flags. + // Verify the next byte after encoded scheduled change message is the ScheduledChange enum flag. assert_eq!(header_bytes[cursor], 1u8); cursor += 1; diff --git a/script/bin/test.rs b/script/bin/test.rs index c10499c..67761c4 100644 --- a/script/bin/test.rs +++ b/script/bin/test.rs @@ -16,11 +16,11 @@ async fn main() -> anyhow::Result<()> { setup_logger(); // Supply an initial authority set id, trusted block, and target block. - let authority_set_id = 64u64; + let authority_set_id = 282u64; let trusted_block = 305130; let target_block = 305160; - let proof_type = ProofType::HeaderRangeProof; + let proof_type = ProofType::RotateProof; let fetcher = RpcDataFetcher::new().await; let mut stdin: SP1Stdin = SP1Stdin::new(); diff --git a/services/src/input.rs b/services/src/input.rs index 22ece9e..c38af92 100644 --- a/services/src/input.rs +++ b/services/src/input.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use avail_subxt::primitives::grandpa::{AuthorityId, ConsensusLog}; +use log::info; use sp1_vector_primitives::types::{ CircuitJustification, HeaderRangeInputs, HeaderRotateData, Precommit, RotateInputs, }; @@ -454,6 +456,39 @@ impl RpcDataFetcher { .await } + /// Filter the authority set changes from the header at the end of the epoch associated with the + /// given authority set id. + /// Source: https://github.com/Rahul8869/avail-light/blob/1ee54e10c037474d2ee99a0762e6ffee43f0df1c/src/utils.rs#L78 + pub async fn filter_auth_set_changes( + &self, + authority_set_id: u64, + ) -> Vec> { + let epoch_end_block = self.last_justified_block(authority_set_id).await; + if epoch_end_block == 0 { + panic!("Current authority set is still active!"); + } + + let header = self.get_header(epoch_end_block).await; + + let new_auths = header + .digest + .logs + .iter() + .filter_map(|e| match &e { + avail_subxt::config::substrate::DigestItem::Consensus( + [b'F', b'R', b'N', b'K'], + data, + ) => match ConsensusLog::::decode(&mut data.as_slice()) { + Ok(ConsensusLog::ScheduledChange(x)) => Some(x.next_authorities), + Ok(ConsensusLog::ForcedChange(_, x)) => Some(x.next_authorities), + _ => None, + }, + _ => None, + }) + .collect::>(); + new_auths + } + /// This function takes in a block_number as input, and fetches the new authority set specified /// in the epoch end block. It returns the data necessary to prove the new authority set, which /// specifies the new authority set hash, the number of authorities, and the start and end @@ -484,10 +519,21 @@ impl RpcDataFetcher { // Note: Two bytes are skipped between the consensus id and value. if let DigestItem::Consensus(consensus_id, value) = log { if consensus_id == [70, 82, 78, 75] { - found_correct_log = true; - - // Denotes that this is a `ScheduledChange` log. - assert_eq!(value[0], 1); + // Decode the consensus log. Only if this is the correct log, will we continue. + match ConsensusLog::::decode(&mut value.as_slice()) { + Ok(ConsensusLog::ScheduledChange(x)) => { + println!("Found ScheduledChange log!"); + found_correct_log = true; + } + Ok(ConsensusLog::ForcedChange(_, x)) => { + println!("Found ForcedChange log!"); + found_correct_log = true; + } + _ => { + position += encoded_log.len(); + continue; + } + } // The bytes after the prefix are the compact encoded number of authorities. // Follows the encoding format: https://docs.substrate.io/reference/scale-codec/#fn-1