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

pow: add access to pre-digest for algorithm verifiers #6900

Merged
merged 5 commits into from
Aug 17, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 34 additions & 7 deletions client/consensus/pow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,13 @@ pub enum Error<B: BlockT> {
CreateInherents(sp_inherents::Error),
#[display(fmt = "Checking inherents failed: {}", _0)]
CheckInherents(String),
#[display(fmt = "Multiple pre-runtime digests")]
MultiplePreRuntimeDigests,
Client(sp_blockchain::Error),
Codec(codec::Error),
Environment(String),
Runtime(RuntimeString)
Runtime(RuntimeString),
Other(String),
}

impl<B: BlockT> std::convert::From<Error<B>> for String {
Expand Down Expand Up @@ -172,6 +175,7 @@ pub trait PowAlgorithm<B: BlockT> {
&self,
parent: &BlockId<B>,
pre_hash: &B::Hash,
pre_digest: Option<&[u8]>,
seal: &Seal,
difficulty: Self::Difficulty,
) -> Result<bool, Error<B>>;
Expand All @@ -180,6 +184,7 @@ pub trait PowAlgorithm<B: BlockT> {
&self,
parent: &BlockId<B>,
pre_hash: &B::Hash,
pre_digest: Option<&[u8]>,
difficulty: Self::Difficulty,
round: u32,
) -> Result<Option<Seal>, Error<B>>;
Expand Down Expand Up @@ -368,9 +373,11 @@ impl<B, I, C, S, Algorithm, CAW> BlockImport<B> for PowBlockImport<B, I, C, S, A
};

let pre_hash = block.header.hash();
let pre_digest = find_pre_digest::<B>(&block.header)?;
if !self.algorithm.verify(
&BlockId::hash(parent_hash),
&pre_hash,
pre_digest.as_ref().map(|v| &v[..]),
&inner_seal,
difficulty,
)? {
Expand Down Expand Up @@ -519,7 +526,7 @@ pub fn import_queue<B, Transaction, Algorithm>(
/// However, it's not recommended to use background threads in the rest of the
/// codebase.
///
/// `preruntime` is a parameter that allows a custom additional pre-runtime
/// `pre_runtime` is a parameter that allows a custom additional pre-runtime
/// digest to be inserted for blocks being built. This can encode authorship
/// information, or just be a graffiti. `round` is for number of rounds the
/// CPU miner runs each time. This parameter should be tweaked so that each
Expand All @@ -529,7 +536,7 @@ pub fn start_mine<B: BlockT, C, Algorithm, E, SO, S, CAW>(
client: Arc<C>,
algorithm: Algorithm,
mut env: E,
preruntime: Option<Vec<u8>>,
pre_runtime: Option<Vec<u8>>,
sorpaas marked this conversation as resolved.
Show resolved Hide resolved
round: u32,
mut sync_oracle: SO,
build_time: std::time::Duration,
Expand Down Expand Up @@ -557,7 +564,7 @@ pub fn start_mine<B: BlockT, C, Algorithm, E, SO, S, CAW>(
client.as_ref(),
&algorithm,
&mut env,
preruntime.as_ref(),
pre_runtime.as_ref(),
round,
&mut sync_oracle,
build_time.clone(),
Expand All @@ -581,7 +588,7 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
client: &C,
algorithm: &Algorithm,
env: &mut E,
preruntime: Option<&Vec<u8>>,
pre_runtime: Option<&Vec<u8>>,
round: u32,
sync_oracle: &mut SO,
build_time: std::time::Duration,
Expand Down Expand Up @@ -640,8 +647,8 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
let inherent_data = inherent_data_providers
.create_inherent_data().map_err(Error::CreateInherents)?;
let mut inherent_digest = Digest::default();
if let Some(preruntime) = &preruntime {
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec()));
if let Some(pre_runtime) = &pre_runtime {
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, pre_runtime.to_vec()));
}
let proposal = futures::executor::block_on(proposer.propose(
inherent_data,
Expand All @@ -658,6 +665,7 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
let seal = algorithm.mine(
&BlockId::Hash(best_hash),
&header.hash(),
pre_runtime.map(|v| &v[..]),
difficulty,
round,
)?;
Expand Down Expand Up @@ -702,3 +710,22 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
.map_err(|e| Error::BlockBuiltError(best_hash, e))?;
}
}

/// Find PoW pre-runtime.
fn find_pre_digest<B: BlockT>(header: &B::Header) -> Result<Option<Vec<u8>>, Error<B>> {
let mut pre_digest: Option<_> = None;
for log in header.digest().logs() {
trace!(target: "pow", "Checking log {:?}, looking for pre runtime digest", log);
match (log, pre_digest.is_some()) {
(DigestItem::PreRuntime(POW_ENGINE_ID, _), true) => {
return Err(Error::MultiplePreRuntimeDigests)
},
(DigestItem::PreRuntime(POW_ENGINE_ID, v), false) => {
pre_digest = Some(v.clone());
},
(_, _) => trace!(target: "pow", "Ignoring digest not meant for us"),
}
}

Ok(pre_digest)
}