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
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
//! Node-bound proof of possession — the Rust side of the standard the Go oracle
//! froze in `luxfi/conformance/vectors/pop.json`.
//!
//! A registrant proves it holds the key it registers AND that the key names the
//! node it registers it for. The pubkey-only IETF proof binds nothing but the
//! key, so it travels: an honest validator's published key and proof re-register
//! under a second identity. Binding the node closes that — a proof is valid only
//! for the one (node, key) pair it was made for.
//!
//! THE MESSAGE, byte for byte, identical in Go, Rust and C++:
//!
//! ```text
//! offset 0 .. 19 node — the 20-byte NodeID
//! offset 20 .. 67 key — compressed G1 pubkey, 48 bytes
//! total 68 bytes
//! ```
//!
//! No separator, no length prefix — both fields are fixed width. The node is the
//! raw 20-byte identity a Lux validator carries, never the 32-byte block id.
//!
//! THE CIPHERSUITE is BLS12-381 `min_pk` under the proof-of-possession domain
//! `BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_` — the `_POP_` tag, never the
//! vote's `..._NUL_`, so a vote is not a proof and a proof is not a vote. Verify
//! order: encoding, then possession.
use ;
use BLST_ERROR;
/// The 20-byte validator identity — the same value Go's `ids.NodeID` and C++'s
/// NodeID carry. Distinct from the 32-byte block [`crate::finality::Id`].
pub type NodeId = ;
/// The proof-of-possession domain. Distinct from the vote domain by `_POP_`.
pub const POP_DST: & = b"BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_";
/// Width of the node identity in the message.
pub const NODE_LEN: usize = 20;
/// Width of a compressed BLS12-381 min_pk public key (G1).
pub const KEY_LEN: usize = 48;
/// Width of a compressed BLS12-381 min_pk signature (G2) — the proof.
pub const PROOF_LEN: usize = 96;
/// The whole preimage: node ‖ key.
pub const MESSAGE_LEN: usize = NODE_LEN + KEY_LEN;
/// Why a proof was refused — the same three classes the Go oracle names, so a
/// conforming implementation rejects for the same reason, not merely rejects.
/// The exact bytes a node-bound proof signs: node ‖ key, 68 bytes.
/// Verify a node-bound proof of possession, in the order the standard fixes:
/// encoding, then possession. A port of the Go oracle's `pop.Verify`.
/// Produce a node-bound proof for `node` under `secret`. The signing side of
/// [`verify`]; used by registrants and by tests.