ckb_pow/
eaglesong_blake2b.rs

1use super::PowEngine;
2use ckb_hash::blake2b_256;
3use ckb_types::{U256, packed::Header, prelude::*, utilities::compact_to_target};
4use eaglesong::eaglesong;
5use log::Level::Debug;
6use log::{debug, log_enabled};
7
8/// PoW verifier using [Eaglesong hash](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0010-eaglesong/0010-eaglesong.md), but with Blake2b as the final hash function
9pub struct EaglesongBlake2bPowEngine;
10
11impl PowEngine for EaglesongBlake2bPowEngine {
12    fn verify(&self, header: &Header) -> bool {
13        let input = crate::pow_message(&header.as_reader().calc_pow_hash(), header.nonce().into());
14        let output = {
15            let mut output_tmp = [0u8; 32];
16            eaglesong(&input, &mut output_tmp);
17            blake2b_256(output_tmp)
18        };
19
20        let (block_target, overflow) = compact_to_target(header.raw().compact_target().into());
21
22        if block_target.is_zero() || overflow {
23            debug!(
24                "compact_target is invalid: {:#x}",
25                header.raw().compact_target()
26            );
27            return false;
28        }
29
30        if U256::from_big_endian(&output[..]).expect("bound checked") > block_target {
31            if log_enabled!(Debug) {
32                use ckb_types::bytes::Bytes;
33
34                let mut output_tmp = [0u8; 32];
35                eaglesong(&input, &mut output_tmp);
36
37                debug!(
38                    "PowEngine::verify error: expected target {:#x}, got {:#x}",
39                    block_target,
40                    U256::from_big_endian(&output[..]).unwrap()
41                );
42
43                debug!(
44                    "PowEngine::verify error: header raw 0x{:x}",
45                    &header.raw().as_bytes()
46                );
47                debug!(
48                    "PowEngine::verify error: pow hash {:#x}",
49                    &header.as_reader().calc_pow_hash()
50                );
51                debug!(
52                    "PowEngine::verify error: nonce {:#x}",
53                    Into::<u128>::into(header.nonce())
54                );
55                debug!(
56                    "PowEngine::verify error: pow input: 0x{:x}",
57                    Bytes::from(input.to_vec())
58                );
59                debug!(
60                    "PowEngine::verify error: eaglesong output: 0x{:#x}",
61                    Bytes::from(output_tmp.to_vec())
62                );
63                debug!(
64                    "PowEngine::verify error: pow output: 0x{:#x}",
65                    Bytes::from(output.to_vec())
66                );
67            }
68            return false;
69        }
70
71        true
72    }
73}