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

* pow: fetch pre-runtime digest to verifier

* Add Other error type

* Fix log target and change docs to refer to pre_runtime
This commit is contained in:
Wei Tang
2020-08-17 19:36:29 +02:00
committed by GitHub
parent 3f85b85e80
commit 41ca7d9127
+34 -7
View File
@@ -88,10 +88,13 @@ pub enum Error<B: BlockT> {
CreateInherents(sp_inherents::Error), CreateInherents(sp_inherents::Error),
#[display(fmt = "Checking inherents failed: {}", _0)] #[display(fmt = "Checking inherents failed: {}", _0)]
CheckInherents(String), CheckInherents(String),
#[display(fmt = "Multiple pre-runtime digests")]
MultiplePreRuntimeDigests,
Client(sp_blockchain::Error), Client(sp_blockchain::Error),
Codec(codec::Error), Codec(codec::Error),
Environment(String), Environment(String),
Runtime(RuntimeString) Runtime(RuntimeString),
Other(String),
} }
impl<B: BlockT> std::convert::From<Error<B>> for String { impl<B: BlockT> std::convert::From<Error<B>> for String {
@@ -172,6 +175,7 @@ pub trait PowAlgorithm<B: BlockT> {
&self, &self,
parent: &BlockId<B>, parent: &BlockId<B>,
pre_hash: &B::Hash, pre_hash: &B::Hash,
pre_digest: Option<&[u8]>,
seal: &Seal, seal: &Seal,
difficulty: Self::Difficulty, difficulty: Self::Difficulty,
) -> Result<bool, Error<B>>; ) -> Result<bool, Error<B>>;
@@ -180,6 +184,7 @@ pub trait PowAlgorithm<B: BlockT> {
&self, &self,
parent: &BlockId<B>, parent: &BlockId<B>,
pre_hash: &B::Hash, pre_hash: &B::Hash,
pre_digest: Option<&[u8]>,
difficulty: Self::Difficulty, difficulty: Self::Difficulty,
round: u32, round: u32,
) -> Result<Option<Seal>, Error<B>>; ) -> Result<Option<Seal>, Error<B>>;
@@ -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_hash = block.header.hash();
let pre_digest = find_pre_digest::<B>(&block.header)?;
if !self.algorithm.verify( if !self.algorithm.verify(
&BlockId::hash(parent_hash), &BlockId::hash(parent_hash),
&pre_hash, &pre_hash,
pre_digest.as_ref().map(|v| &v[..]),
&inner_seal, &inner_seal,
difficulty, difficulty,
)? { )? {
@@ -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 /// However, it's not recommended to use background threads in the rest of the
/// codebase. /// 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 /// 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 /// 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 /// CPU miner runs each time. This parameter should be tweaked so that each
@@ -529,7 +536,7 @@ pub fn start_mine<B: BlockT, C, Algorithm, E, SO, S, CAW>(
client: Arc<C>, client: Arc<C>,
algorithm: Algorithm, algorithm: Algorithm,
mut env: E, mut env: E,
preruntime: Option<Vec<u8>>, pre_runtime: Option<Vec<u8>>,
round: u32, round: u32,
mut sync_oracle: SO, mut sync_oracle: SO,
build_time: std::time::Duration, build_time: std::time::Duration,
@@ -557,7 +564,7 @@ pub fn start_mine<B: BlockT, C, Algorithm, E, SO, S, CAW>(
client.as_ref(), client.as_ref(),
&algorithm, &algorithm,
&mut env, &mut env,
preruntime.as_ref(), pre_runtime.as_ref(),
round, round,
&mut sync_oracle, &mut sync_oracle,
build_time.clone(), build_time.clone(),
@@ -581,7 +588,7 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
client: &C, client: &C,
algorithm: &Algorithm, algorithm: &Algorithm,
env: &mut E, env: &mut E,
preruntime: Option<&Vec<u8>>, pre_runtime: Option<&Vec<u8>>,
round: u32, round: u32,
sync_oracle: &mut SO, sync_oracle: &mut SO,
build_time: std::time::Duration, build_time: std::time::Duration,
@@ -640,8 +647,8 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
let inherent_data = inherent_data_providers let inherent_data = inherent_data_providers
.create_inherent_data().map_err(Error::CreateInherents)?; .create_inherent_data().map_err(Error::CreateInherents)?;
let mut inherent_digest = Digest::default(); let mut inherent_digest = Digest::default();
if let Some(preruntime) = &preruntime { if let Some(pre_runtime) = &pre_runtime {
inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, preruntime.to_vec())); inherent_digest.push(DigestItem::PreRuntime(POW_ENGINE_ID, pre_runtime.to_vec()));
} }
let proposal = futures::executor::block_on(proposer.propose( let proposal = futures::executor::block_on(proposer.propose(
inherent_data, inherent_data,
@@ -658,6 +665,7 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
let seal = algorithm.mine( let seal = algorithm.mine(
&BlockId::Hash(best_hash), &BlockId::Hash(best_hash),
&header.hash(), &header.hash(),
pre_runtime.map(|v| &v[..]),
difficulty, difficulty,
round, round,
)?; )?;
@@ -702,3 +710,22 @@ fn mine_loop<B: BlockT, C, Algorithm, E, SO, S, CAW>(
.map_err(|e| Error::BlockBuiltError(best_hash, e))?; .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)
}