Skip to main content

amadeus_runtime/consensus/bic/
sol.rs

1use crate::Result;
2use amadeus_utils::blake3;
3use amadeus_utils::{Hash, PublicKey, Signature};
4use std::convert::TryInto;
5
6pub const PREAMBLE_SIZE: usize = 240;
7pub const MATRIX_SIZE: usize = 1024;
8pub const SOL_SIZE: usize = PREAMBLE_SIZE + MATRIX_SIZE; // 1264
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Sol {
12    pub epoch: u64,
13    pub segment_vr_hash: Hash,
14    pub pk: PublicKey,
15    pub pop: Signature,
16    pub computor: PublicKey,
17    pub nonce: [u8; 12],
18    pub tensor_c: [u8; 1024],
19}
20
21pub fn unpack(sol: &[u8; SOL_SIZE]) -> Result<Sol> {
22    let epoch = u32::from_le_bytes(sol[0..4].try_into().map_err(|_| "sol_unpack_failed")?) as u64;
23    let segment_vr_hash = Hash::new(sol[4..36].try_into().map_err(|_| "sol_unpack_failed")?);
24    let pk = PublicKey::new(sol[36..84].try_into().map_err(|_| "sol_unpack_failed")?);
25    let pop = Signature::new(sol[84..180].try_into().map_err(|_| "sol_unpack_failed")?);
26    let computor = PublicKey::new(sol[180..228].try_into().map_err(|_| "sol_unpack_failed")?);
27    let nonce: [u8; 12] = sol[228..240].try_into().map_err(|_| "sol_unpack_failed")?;
28    let tensor_c: [u8; 1024] = sol[240..(240 + 1024)].try_into().map_err(|_| "sol_unpack_failed")?;
29    Ok(Sol { epoch, segment_vr_hash, pk, pop, computor, nonce, tensor_c })
30}
31
32pub fn verify_hash_diff(_epoch: u64, hash: &[u8], diff_bits: u64) -> bool {
33    if diff_bits > 256 {
34        return false;
35    }
36    let (full, rem) = ((diff_bits / 8) as usize, (diff_bits % 8) as u8);
37    hash[..full].iter().all(|&b| b == 0) && (rem == 0 || (hash[full] & (0xFF << (8 - rem))) == 0)
38}
39
40pub fn verify(
41    sol: &[u8; SOL_SIZE],
42    solhash: &[u8],
43    segment_vr_hash: &[u8],
44    vr_b3: &[u8],
45    diff_bits: u64,
46) -> Result<bool> {
47    let usol = unpack(sol)?;
48    if segment_vr_hash != &*usol.segment_vr_hash {
49        return Err("segment_vr_hash");
50    }
51    if sol.len() != SOL_SIZE {
52        return Err("invalid_sol_seed_size");
53    }
54    Ok(verify_hash_diff(usol.epoch, solhash, diff_bits) && blake3::freivalds_e260(sol, vr_b3))
55}