ckb_pow/
lib.rs

1//! TODO(doc): @quake
2use byteorder::{ByteOrder, LittleEndian};
3use ckb_types::{
4    packed::{Byte32, Header},
5    prelude::*,
6};
7use serde::{Deserialize, Serialize};
8use std::any::Any;
9use std::fmt;
10use std::sync::Arc;
11
12mod dummy;
13mod eaglesong;
14mod eaglesong_blake2b;
15
16#[cfg(test)]
17mod tests;
18
19pub use crate::dummy::DummyPowEngine;
20pub use crate::eaglesong::EaglesongPowEngine;
21pub use crate::eaglesong_blake2b::EaglesongBlake2bPowEngine;
22
23/// The PoW engine traits bundled
24#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Hash, Debug)]
25#[serde(tag = "func", content = "params")]
26pub enum Pow {
27    /// Mocking dummy PoW engine
28    Dummy,
29    /// The Eaglesong PoW engine
30    /// Check details of Eaglesong from: <https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0010-eaglesong/0010-eaglesong.md>
31    Eaglesong,
32    /// The Eaglesong PoW engine, similar to `Eaglesong`, but using `blake2b` hash as the final output.
33    /// Check details of blake2b from: <https://tools.ietf.org/html/rfc7693> and blake2b-rs from: <https://github.com/nervosnetwork/blake2b-rs>
34    EaglesongBlake2b,
35}
36
37impl fmt::Display for Pow {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        match self {
40            Pow::Dummy => write!(f, "Dummy"),
41            Pow::Eaglesong => write!(f, "Eaglesong"),
42            Pow::EaglesongBlake2b => write!(f, "EaglesongBlake2b"),
43        }
44    }
45}
46
47impl Pow {
48    /// Allocates a new engine instance
49    pub fn engine(&self) -> Arc<dyn PowEngine> {
50        match *self {
51            Pow::Dummy => Arc::new(DummyPowEngine),
52            Pow::Eaglesong => Arc::new(EaglesongPowEngine),
53            Pow::EaglesongBlake2b => Arc::new(EaglesongBlake2bPowEngine),
54        }
55    }
56
57    /// Determine whether this engine is dummy(mocking)
58    pub fn is_dummy(&self) -> bool {
59        *self == Pow::Dummy
60    }
61}
62
63/// Combine pow_hash and nonce to a message, in little endian
64pub fn pow_message(pow_hash: &Byte32, nonce: u128) -> [u8; 48] {
65    let mut message = [0; 48];
66    message[0..32].copy_from_slice(pow_hash.as_slice());
67    LittleEndian::write_u128(&mut message[32..48], nonce);
68    message
69}
70
71/// A trait for PoW engine, which is used to verify PoW
72pub trait PowEngine: Send + Sync + AsAny {
73    /// Verify header
74    fn verify(&self, header: &Header) -> bool;
75}
76
77/// A trait for casting to trait `Any`
78pub trait AsAny {
79    /// Cast to trait `Any`
80    fn as_any(&self) -> &dyn Any;
81}
82
83impl<T: Any> AsAny for T {
84    fn as_any(&self) -> &dyn Any {
85        self
86    }
87}