Skip to main content

molpha_verifier/
selection.rs

1//! Deterministic selection-bitmap derivation for a `(feed_id, registry_version, timestamp)` round.
2
3use solana_keccak_hasher::hashv;
4
5use crate::bitmap::{derive_group_bitmap, effective_selection_size};
6use crate::error::DataUpdateError;
7
8/// `bytes32(keccak256("MOLPHA_SELECTION_V1"))` — EVM `Validator` selection seed prefix.
9///
10/// Value: `keccak256(bytes("MOLPHA_SELECTION_V1"))`, verified by the unit test below.
11pub const SELECTION_SEED_PREFIX: [u8; 32] = [
12    0x1d, 0xef, 0x81, 0x59, 0xcb, 0xcf, 0xcd, 0xfd, 0x72, 0x8d, 0x41, 0x97, 0x51, 0x9a, 0x57, 0xc0,
13    0x6e, 0x24, 0x3f, 0x0d, 0x94, 0x68, 0xb4, 0xc1, 0xe5, 0xc4, 0xa2, 0x33, 0xfc, 0x56, 0x53, 0xc3,
14];
15
16/// Derive the deterministic selection bitmap for a round.
17///
18/// `seed = keccak(SELECTION_SEED_PREFIX, feed_id, registry_version_be, canonical_timestamp_be)`,
19/// then `derive_group_bitmap(seed, node_count, effective_selection_size(...))`.
20pub fn derive_selection_bitmap(
21    feed_id: &[u8; 32],
22    registry_version: u32,
23    canonical_timestamp: i64,
24    node_count: u32,
25    signatures_required: u8,
26    redundancy_buffer: u8,
27) -> Result<[u8; 32], DataUpdateError> {
28    let canonical_timestamp_bytes = (canonical_timestamp as u64).to_be_bytes();
29    let selection_seed = hashv(&[
30        SELECTION_SEED_PREFIX.as_slice(),
31        feed_id.as_ref(),
32        registry_version.to_be_bytes().as_ref(),
33        canonical_timestamp_bytes.as_ref(),
34    ])
35    .to_bytes();
36    let selection_size =
37        effective_selection_size(signatures_required, redundancy_buffer, node_count);
38    derive_group_bitmap(&selection_seed, node_count, selection_size)
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn selection_seed_prefix_is_keccak_of_domain() {
47        let expected = hashv(&[b"MOLPHA_SELECTION_V1"]).to_bytes();
48        assert_eq!(SELECTION_SEED_PREFIX, expected);
49    }
50}