ckb_pow/
eaglesong.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use super::PowEngine;
use ckb_types::{packed::Header, prelude::*, utilities::compact_to_target, U256};
use eaglesong::eaglesong;
use log::Level::Debug;
use log::{debug, log_enabled};

/// PoW verifier using [Eaglesong hash](https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0010-eaglesong/0010-eaglesong.md)
pub struct EaglesongPowEngine;

impl PowEngine for EaglesongPowEngine {
    fn verify(&self, header: &Header) -> bool {
        let input =
            crate::pow_message(&header.as_reader().calc_pow_hash(), header.nonce().unpack());
        let mut output = [0u8; 32];
        eaglesong(&input, &mut output);

        let (block_target, overflow) = compact_to_target(header.raw().compact_target().unpack());

        if block_target.is_zero() || overflow {
            debug!(
                "compact_target is invalid: {:#x}",
                header.raw().compact_target()
            );
            return false;
        }

        if U256::from_big_endian(&output[..]).expect("bound checked") > block_target {
            if log_enabled!(Debug) {
                use ckb_types::bytes::Bytes;
                debug!(
                    "PowEngine::verify error: expected target {:#x}, got {:#x}",
                    block_target,
                    U256::from_big_endian(&output[..]).unwrap()
                );

                debug!(
                    "PowEngine::verify error: header raw 0x{:x}",
                    &header.raw().as_bytes()
                );
                debug!(
                    "PowEngine::verify error: pow hash {:#x}",
                    &header.as_reader().calc_pow_hash()
                );
                debug!(
                    "PowEngine::verify error: nonce {:#x}",
                    header.nonce().unpack()
                );
                debug!(
                    "PowEngine::verify error: pow input: 0x{:x}",
                    Bytes::from(input.to_vec())
                );
                debug!(
                    "PowEngine::verify error: pow output: 0x{:x}",
                    Bytes::from(output.to_vec())
                );
            }
            return false;
        }

        true
    }
}