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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! The hash primitives both families are built from, as thin wrappers over
//! RustCrypto: SHA-256, SHA-256d, the BIP-340 tagged hash and BLAKE2b-256.
//!
//! Nothing here is hand-rolled. The upstream kernel carries its own pure-JS
//! SHA-256 and BLAKE2b (`codec/hash.js`, `codec/pow/blake2b.js`) so that it
//! runs in a browser without dependencies; this crate takes the same
//! functions from [`sha2`] and [`blake2`] instead.
//!
//! One detail the kernel's `blake2b.js` header comment makes explicit is worth
//! repeating here: Knots hashes with `blake2b_nokey(out, 32, in, len)`, and a
//! **32-byte BLAKE2b digest is not a truncated BLAKE2b-512** — the output
//! length is mixed into the parameter block, so the IV differs.
//! [`blake2::Blake2b`] parameterised with `U32` does exactly that, which the
//! Knots vectors in this crate's tests confirm stage for stage.
use U32;
use ;
use Sha256;
/// BLAKE2b with a 32-byte digest length in its parameter block (RFC 7693
/// `blake2b(…, outlen = 32)`), the function Knots' v2 proof of work uses.
pub type Blake2b256 = ;
/// The 32-byte digest every stage of both pipelines produces.
pub type Digest32 = ;
/// SHA-256 of `data`.
///
/// ```
/// let d = sidestr_header::hash::sha256(b"abc");
/// assert_eq!(hex::encode(d), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
/// ```
/// Bitcoin's hash function, SHA-256 applied twice (`dsha256` in the kernel's
/// `codec/hash.js`). The stock family's block hash is this over the 80 bytes.
/// The BIP-340 tagged hash `SHA256(SHA256(tag) ‖ SHA256(tag) ‖ chunks…)`, as
/// `taggedHash` in the kernel's `codec/hash.js`. Every SHA-256 round of the
/// Knots v2 pipeline is one of these; `chunks` are concatenated in order.
///
/// ```
/// use sidestr_header::hash::tagged_hash;
/// // The same message in one chunk or two hashes identically.
/// assert_eq!(tagged_hash(b"BIP0340/challenge", &[b"ab", b"c"]),
/// tagged_hash(b"BIP0340/challenge", &[b"abc"]));
/// ```
/// BLAKE2b-256 over the concatenation of `chunks` (`blake2b(input, 32)` in the
/// kernel's `codec/pow/blake2b.js`; unkeyed, no salt, no personalisation).
///
/// ```
/// use sidestr_header::hash::blake2b_256;
/// // RFC 7693 does not publish a 256-bit unkeyed vector; the Knots vectors in
/// // this crate's tests pin the function. Here: determinism and chunking.
/// assert_eq!(blake2b_256(&[b"hello ", b"world"]), blake2b_256(&[b"hello world"]));
/// ```
/// Parses exactly 32 bytes of hex (64 characters, either case) without
/// allocating. Returns `None` for any other length or a non-hex character.
pub
const
/// `hex32` usable in `const` context, for the fork constants. Panics at
/// compile time on malformed input, which is the point: a typo in a constant
/// is a build failure, not a wrong chain.
pub const
/// Writes `bytes` as lowercase hex to a formatter without allocating.
pub