use crate::consensus::consensus_apply::ApplyEnv;
use crate::consensus::consensus_kv::{kv_exists, kv_get, kv_get_prev_or_exact, kv_increment, kv_put, kv_set_bit};
use crate::{bcat, consensus};
use amadeus_utils::constants::{CF_CONTRACTSTATE, DST_MOTION};
use amadeus_utils::{Hash, PublicKey, Signature};
use amadeus_utils::{blake3, bls12_381};
use bitvec::order::Msb0;
use bitvec::prelude::BitVec;
pub const EPOCH_EMISSION_BASE: i128 = 1_000_000_000_000_000;
pub const EPOCH_INTERVAL: i128 = 100_000;
pub const TREASURY_DONATION_ADDRESS: &[u8; 48] = &[
140, 71, 6, 83, 31, 185, 171, 240, 47, 5, 14, 246, 98, 23, 105, 24, 183, 118, 193, 92, 66, 82, 64, 5, 239, 255,
254, 87, 139, 252, 148, 176, 113, 6, 207, 153, 51, 25, 202, 45, 48, 153, 223, 248, 219, 210, 80, 254,
];
pub fn epoch_emission(epoch: u64) -> i128 {
epoch_emission_1(epoch, EPOCH_EMISSION_BASE)
}
fn epoch_emission_1(epoch: u64, acc: i128) -> i128 {
if epoch == 0 {
acc
} else {
let sub = acc.saturating_mul(333) / 1_000_000;
let emitted = acc.saturating_sub(sub);
epoch_emission_1(epoch - 1, emitted)
}
}
pub fn circulating_without_burn(epoch: u64) -> i128 {
fn rec(n: u64, acc: i128) -> i128 {
if n == 0 { acc } else { rec(n - 1, acc + epoch_emission(n)) }
}
rec(epoch, 0)
}
pub const PEDDLEBIKE67: &[PublicKey; 67] = &[
PublicKey::new([
0x95, 0xD8, 0x37, 0xFF, 0x1D, 0x08, 0xEF, 0xFB, 0x8B, 0x70, 0x1E, 0x1D, 0xC7, 0x39, 0x5A, 0x43, 0xC6, 0xDC,
0x65, 0x12, 0xE4, 0x64, 0x64, 0xF1, 0x2B, 0xD5, 0xDD, 0xE6, 0xFD, 0x3A, 0xE7, 0x01, 0x66, 0xA6, 0x36, 0x42,
0xF5, 0x94, 0x8C, 0x2C, 0x4E, 0x38, 0x54, 0x0C, 0xDE, 0xCD, 0x39, 0xD2,
]),
PublicKey::new([
0x95, 0xD6, 0x8B, 0xD8, 0x44, 0x2D, 0xAA, 0x15, 0xF6, 0x96, 0x24, 0x5D, 0x22, 0xFD, 0x16, 0x5C, 0x70, 0xBA,
0x03, 0x76, 0xA8, 0xEC, 0xBE, 0x28, 0xD5, 0xD6, 0x30, 0xF7, 0x8F, 0x94, 0xDD, 0x9E, 0x81, 0xB1, 0x69, 0xA2,
0x4A, 0xC7, 0x64, 0x24, 0x58, 0x0E, 0x58, 0x77, 0xF3, 0xC3, 0x0B, 0xB0,
]),
PublicKey::new([
0x95, 0xD6, 0x95, 0x90, 0x56, 0xCC, 0x5C, 0x67, 0x7B, 0xE0, 0x50, 0x78, 0xA9, 0x15, 0x3D, 0x46, 0x49, 0x88,
0x60, 0x1A, 0x0D, 0x06, 0x59, 0x90, 0x2A, 0xA9, 0xC8, 0x51, 0x4E, 0x1F, 0x75, 0x02, 0xFE, 0x37, 0x83, 0x7A,
0xFF, 0x11, 0x54, 0x63, 0xE4, 0x0F, 0x40, 0xE0, 0xD4, 0x4A, 0x16, 0xC4,
]),
PublicKey::new([
0x95, 0xD6, 0xA5, 0xAF, 0xDD, 0xE5, 0x3E, 0x9C, 0xF2, 0x18, 0xB2, 0x60, 0x33, 0xB3, 0x61, 0xEC, 0x5F, 0x82,
0x2D, 0x3C, 0x06, 0x41, 0x0E, 0xB1, 0x34, 0xDA, 0x57, 0xBC, 0x53, 0x11, 0x58, 0x93, 0x5B, 0x45, 0xD3, 0xAD,
0x2D, 0xE6, 0xAD, 0x50, 0x3B, 0xD7, 0xF4, 0x57, 0xEC, 0x4A, 0x51, 0x2F,
]),
PublicKey::new([
0x95, 0xD6, 0xAB, 0x96, 0x2C, 0x7D, 0xB2, 0x01, 0xED, 0x17, 0x8E, 0x97, 0x6C, 0xCB, 0x0A, 0xD7, 0x2C, 0x88,
0x72, 0x84, 0xE8, 0xD0, 0xA4, 0x47, 0x92, 0xF3, 0x4F, 0xD4, 0x2E, 0x8D, 0xE3, 0xCF, 0x93, 0x75, 0x4D, 0x83,
0x4D, 0x18, 0x0A, 0x30, 0x4E, 0x09, 0xAB, 0x6C, 0x04, 0x37, 0x45, 0xE1,
]),
PublicKey::new([
0x95, 0xD6, 0xB5, 0x21, 0x25, 0xED, 0xD6, 0x18, 0x82, 0xB4, 0x44, 0xD3, 0x2F, 0xD4, 0x7E, 0x96, 0x0F, 0x61,
0x63, 0x05, 0x07, 0x4E, 0xC3, 0x40, 0x19, 0x11, 0x0E, 0x56, 0xD2, 0xC7, 0x70, 0x7A, 0x59, 0x2A, 0x20, 0x50,
0xDE, 0xC9, 0xD7, 0xBC, 0xDF, 0xA5, 0xBB, 0x3C, 0x13, 0x16, 0x18, 0xA3,
]),
PublicKey::new([
0x95, 0xD6, 0xBC, 0x60, 0xF1, 0x03, 0xC5, 0x5A, 0x81, 0xBB, 0x6B, 0x2A, 0x40, 0xAF, 0xD1, 0x03, 0xA5, 0xDB,
0x49, 0xDB, 0x68, 0xC4, 0xAD, 0xB5, 0x1F, 0x69, 0xCC, 0x1C, 0xA2, 0x15, 0x93, 0x9E, 0x3F, 0xC4, 0x37, 0xC2,
0xEE, 0x31, 0xF3, 0x51, 0xBD, 0x20, 0xDB, 0xD0, 0x5D, 0xA4, 0xB7, 0x26,
]),
PublicKey::new([
0x95, 0xD6, 0xCA, 0x83, 0x2C, 0xAC, 0x1C, 0x82, 0xAC, 0x4B, 0xA8, 0xA1, 0x4B, 0x60, 0xAD, 0xB9, 0xFB, 0x15,
0x29, 0xBD, 0xE5, 0x00, 0xFD, 0xE0, 0xE5, 0xDE, 0x14, 0x88, 0xE1, 0x66, 0x86, 0x52, 0x96, 0xDF, 0x9B, 0xEB,
0x84, 0x57, 0x29, 0x11, 0x4E, 0x4B, 0xE2, 0x78, 0x19, 0xAA, 0x48, 0xE2,
]),
PublicKey::new([
0x95, 0xD6, 0xD1, 0x72, 0xEC, 0x97, 0xA6, 0x70, 0x33, 0x83, 0x29, 0x6D, 0x44, 0x4E, 0x7E, 0x7F, 0xAB, 0xB0,
0x59, 0xB6, 0xA8, 0xEB, 0xA1, 0xB0, 0x52, 0xA7, 0x13, 0xE4, 0x75, 0x70, 0x6E, 0xF9, 0x83, 0x8A, 0xF2, 0xE3,
0x61, 0x59, 0x02, 0xE6, 0xC9, 0x55, 0xE3, 0xD9, 0x23, 0xF0, 0x13, 0xAE,
]),
PublicKey::new([
0x95, 0xD6, 0xDC, 0xA4, 0xE7, 0xE9, 0xBD, 0xEA, 0xA8, 0xAD, 0x0D, 0xCD, 0xCE, 0x86, 0x67, 0xB8, 0x19, 0xDC,
0x2E, 0x69, 0x37, 0x4F, 0x3C, 0x7D, 0xC4, 0xF2, 0x96, 0xF4, 0x55, 0xE7, 0x50, 0xF5, 0xB3, 0xB2, 0x95, 0x66,
0xCB, 0x61, 0xEF, 0xED, 0x70, 0x50, 0xA5, 0xDD, 0x80, 0x88, 0xD5, 0x5A,
]),
PublicKey::new([
0x95, 0x78, 0xC6, 0xCC, 0x1A, 0x7E, 0xBB, 0xBB, 0x64, 0xEC, 0x65, 0xC5, 0x4B, 0x25, 0x43, 0x50, 0x74, 0x10,
0x0E, 0xD1, 0x5A, 0x5B, 0xD6, 0xA1, 0x74, 0xBE, 0x4B, 0x61, 0x4B, 0xA0, 0xD5, 0xEB, 0x5E, 0x2A, 0xE6, 0x82,
0xC7, 0x58, 0xA2, 0xB1, 0x04, 0x68, 0xE9, 0x83, 0x63, 0xCC, 0xDE, 0xB4,
]),
PublicKey::new([
0x95, 0x77, 0x23, 0x8C, 0x01, 0xC9, 0x30, 0xFE, 0x41, 0x7C, 0x48, 0xFC, 0x1F, 0xF8, 0xB7, 0x01, 0x18, 0x71,
0x45, 0xD6, 0x30, 0x5C, 0x04, 0x42, 0xD9, 0xF3, 0xC3, 0xAC, 0x31, 0x15, 0x30, 0xEF, 0x6A, 0x51, 0xE9, 0x85,
0xFD, 0xAF, 0x6F, 0x80, 0xAB, 0x95, 0x72, 0x6E, 0x8E, 0xE2, 0xAD, 0x7F,
]),
PublicKey::new([
0x95, 0x77, 0x28, 0xB6, 0xB0, 0xBD, 0xC2, 0x6D, 0xC9, 0x81, 0x41, 0x66, 0x4C, 0x77, 0xF3, 0xDD, 0x3F, 0x31,
0xEE, 0x85, 0x85, 0xDF, 0x38, 0x63, 0x4D, 0xFA, 0x8A, 0x52, 0xC3, 0xED, 0x9F, 0xAC, 0xE8, 0x32, 0xBA, 0x65,
0x16, 0x64, 0xA4, 0xA8, 0x47, 0xB9, 0x66, 0xA3, 0x61, 0xFB, 0x58, 0x35,
]),
PublicKey::new([
0x95, 0x77, 0x30, 0x96, 0x49, 0x20, 0xA0, 0x0D, 0xE3, 0xA8, 0xFA, 0x02, 0xEA, 0x89, 0x65, 0x09, 0x3D, 0xE3,
0x0B, 0x8E, 0xD4, 0x23, 0x65, 0x5B, 0xCB, 0x98, 0x29, 0x25, 0xAB, 0x95, 0x79, 0x7B, 0xBB, 0x5A, 0x55, 0x4E,
0xCB, 0x50, 0xD1, 0xB6, 0xCE, 0x25, 0x77, 0x6C, 0xAF, 0x5D, 0x74, 0x8C,
]),
PublicKey::new([
0x95, 0x77, 0x3C, 0x10, 0x56, 0x5C, 0x56, 0xD2, 0x27, 0x09, 0x85, 0x97, 0x97, 0x9B, 0x75, 0x1A, 0x3E, 0xD5,
0xF9, 0x9C, 0x28, 0xFA, 0xBC, 0x12, 0xF0, 0x76, 0xED, 0xC6, 0x7A, 0x7B, 0x19, 0xD6, 0x67, 0x59, 0x67, 0x99,
0xC7, 0x67, 0xDE, 0x05, 0x31, 0x12, 0x0A, 0x81, 0x97, 0xC3, 0xF1, 0x4E,
]),
PublicKey::new([
0x95, 0x77, 0x4A, 0x57, 0x62, 0xD2, 0x60, 0x73, 0x0E, 0x16, 0x4E, 0x8E, 0x0B, 0x22, 0xD5, 0x83, 0x5D, 0xD7,
0x8D, 0xE8, 0xD7, 0xC6, 0x39, 0x4B, 0xA1, 0x47, 0x3D, 0x8D, 0xAF, 0x4A, 0x3C, 0x20, 0xB7, 0x3A, 0xB9, 0x07,
0x28, 0x00, 0x87, 0xE3, 0xE6, 0xB6, 0x2C, 0x7C, 0x35, 0xE9, 0x35, 0xCD,
]),
PublicKey::new([
0x95, 0x77, 0x53, 0x14, 0x4F, 0x94, 0xF0, 0x6E, 0x3B, 0x47, 0x81, 0xD3, 0x37, 0xB7, 0xF7, 0xB2, 0xB7, 0x92,
0x6B, 0xF7, 0xB4, 0x9E, 0xC7, 0xDF, 0x22, 0x14, 0xF8, 0x59, 0xAC, 0x23, 0xF2, 0x79, 0xB3, 0xEC, 0x47, 0xA4,
0xD9, 0x3D, 0x45, 0x74, 0x12, 0xEE, 0x17, 0x59, 0xE6, 0xF9, 0x0A, 0x5C,
]),
PublicKey::new([
0x95, 0x77, 0x5B, 0x46, 0x7A, 0xCB, 0x18, 0x7D, 0x32, 0x81, 0x96, 0x1A, 0x67, 0x8B, 0x34, 0x7A, 0xCE, 0xD9,
0x97, 0x7D, 0xB4, 0x9A, 0xB8, 0xA1, 0xAB, 0x12, 0xE7, 0x6A, 0xE2, 0x72, 0xA7, 0x32, 0xFB, 0x0D, 0xB8, 0xDE,
0x2D, 0x9D, 0x31, 0x2A, 0xF4, 0x48, 0x7B, 0xAF, 0x9C, 0xCB, 0xAE, 0x91,
]),
PublicKey::new([
0x95, 0x77, 0x5F, 0x9D, 0xAD, 0x81, 0x45, 0x9A, 0x72, 0x95, 0xF1, 0x58, 0x08, 0xE5, 0x13, 0x09, 0x59, 0x4C,
0xF3, 0x16, 0xDC, 0xF9, 0x0B, 0x4D, 0x92, 0x0B, 0xBF, 0x39, 0x25, 0xF8, 0x74, 0x47, 0x27, 0xBA, 0xC5, 0x5C,
0xDB, 0xF9, 0x96, 0x24, 0xDD, 0x32, 0x61, 0xE1, 0xEE, 0xF6, 0x03, 0xA9,
]),
PublicKey::new([
0x95, 0x77, 0x6B, 0x3E, 0x7F, 0x1B, 0x4A, 0x0D, 0x46, 0x4E, 0x8D, 0x09, 0x06, 0x6E, 0x9D, 0xAA, 0xF6, 0x8C,
0x8C, 0x1B, 0xAF, 0xD0, 0x8E, 0xF2, 0xB7, 0xD6, 0xF4, 0xBC, 0xA0, 0x4D, 0xB1, 0x3D, 0x68, 0x0A, 0x4B, 0xAE,
0x95, 0xC9, 0xA0, 0x94, 0xD2, 0x6E, 0x44, 0x0A, 0x8F, 0xDB, 0x69, 0x6B,
]),
PublicKey::new([
0x95, 0x7A, 0xDC, 0xA8, 0x5B, 0x47, 0x06, 0x63, 0x7D, 0x2F, 0x80, 0x04, 0x54, 0x97, 0x82, 0xC0, 0x70, 0x4B,
0x7F, 0x7D, 0x87, 0x8D, 0x0D, 0x61, 0xC7, 0xBA, 0xD5, 0x79, 0x67, 0x57, 0x81, 0xD0, 0x57, 0x93, 0xA8, 0xD6,
0x27, 0x17, 0x01, 0xC7, 0xAE, 0xDD, 0x7C, 0xB3, 0x71, 0xA7, 0x6A, 0x4C,
]),
PublicKey::new([
0x95, 0x79, 0x36, 0x85, 0x52, 0x08, 0x74, 0x33, 0xC9, 0xDF, 0xF4, 0xEA, 0x44, 0x52, 0x2D, 0xC3, 0x80, 0xD1,
0x63, 0xF0, 0x7F, 0x17, 0xE3, 0x1A, 0x74, 0x93, 0x39, 0xF1, 0x78, 0xB2, 0xB7, 0x54, 0xD9, 0xF0, 0x55, 0x41,
0xD0, 0x60, 0x4F, 0xD3, 0xC7, 0x56, 0xE9, 0x1D, 0xB1, 0xCA, 0x44, 0xD0,
]),
PublicKey::new([
0x95, 0x79, 0x3F, 0xED, 0xDA, 0x1A, 0x40, 0xCC, 0xC5, 0x16, 0xA7, 0xED, 0x3F, 0x05, 0x11, 0x8A, 0x9F, 0x94,
0x3B, 0x1E, 0x0F, 0xCC, 0xFE, 0x7D, 0x2B, 0x51, 0xA2, 0x70, 0x37, 0xE6, 0x8A, 0x57, 0xE0, 0xC2, 0x3E, 0xC6,
0x31, 0x6F, 0xBB, 0xA0, 0x9E, 0xB4, 0x0A, 0x68, 0xEC, 0xBF, 0x1C, 0x39,
]),
PublicKey::new([
0x95, 0x79, 0x45, 0xE9, 0x73, 0x74, 0xE2, 0x4B, 0xB5, 0x2E, 0xD3, 0xF6, 0xB7, 0x16, 0x94, 0x5B, 0x85, 0x91,
0x49, 0x6B, 0xEC, 0x39, 0x2F, 0x0F, 0xE7, 0x27, 0xED, 0xE3, 0x88, 0x0A, 0xB1, 0x19, 0xB1, 0x11, 0x92, 0x3D,
0xC4, 0x09, 0x69, 0x2C, 0x9F, 0x0F, 0x4D, 0xED, 0xD6, 0xA0, 0x30, 0x33,
]),
PublicKey::new([
0x95, 0x79, 0x51, 0xA5, 0x24, 0xC0, 0x87, 0x9F, 0x9B, 0xAA, 0x49, 0xC5, 0xCA, 0x48, 0x78, 0x06, 0xAD, 0x3E,
0x49, 0xC4, 0xFB, 0x7B, 0x9B, 0x41, 0xDB, 0xC4, 0x51, 0x4A, 0x0B, 0x1B, 0x12, 0x3F, 0x32, 0x94, 0x9C, 0xE5,
0x77, 0x39, 0xD0, 0x1B, 0xEC, 0x94, 0xC2, 0x7F, 0xBB, 0xC6, 0x5B, 0x1C,
]),
PublicKey::new([
0x95, 0x79, 0x5B, 0x63, 0x5D, 0xA0, 0x66, 0xB1, 0x03, 0x4E, 0x12, 0xA6, 0xF7, 0x33, 0xFF, 0xEC, 0x5C, 0x23,
0x61, 0x6F, 0x47, 0x81, 0xF9, 0xF1, 0x8D, 0x43, 0x43, 0x72, 0x08, 0x8B, 0xDC, 0x1B, 0x24, 0x1E, 0x73, 0xA8,
0xD7, 0x78, 0x96, 0xA1, 0xE0, 0x2A, 0x4B, 0x84, 0xF1, 0xAF, 0x6A, 0x34,
]),
PublicKey::new([
0x95, 0x79, 0x60, 0xC1, 0xE1, 0x8D, 0x2A, 0x24, 0xDD, 0xAD, 0x36, 0x2D, 0xFF, 0x7A, 0x13, 0x13, 0x86, 0x24,
0x32, 0x54, 0xEF, 0x0C, 0x80, 0x89, 0xFE, 0x3A, 0x00, 0x6C, 0xF7, 0x82, 0x0B, 0xFE, 0x02, 0xE3, 0xA1, 0x94,
0x7E, 0x25, 0xEE, 0xAF, 0xB9, 0xAD, 0x3E, 0xFD, 0x1A, 0xD6, 0xC4, 0xD2,
]),
PublicKey::new([
0x95, 0x79, 0x6F, 0xAB, 0x71, 0xC1, 0x05, 0x8F, 0x49, 0x76, 0x90, 0xA1, 0x68, 0x3E, 0x4D, 0x7F, 0x04, 0x79,
0x73, 0x40, 0x1D, 0xB7, 0xF4, 0xDD, 0xE4, 0x91, 0x42, 0x11, 0x37, 0xFE, 0x04, 0xC6, 0xE2, 0xAF, 0xA1, 0xF5,
0xFF, 0x35, 0x8D, 0xF5, 0x62, 0x6B, 0xE5, 0xB5, 0x3E, 0x8F, 0x99, 0x3D,
]),
PublicKey::new([
0x95, 0x79, 0x70, 0x5F, 0xD4, 0x00, 0xB0, 0xF2, 0xB2, 0x6B, 0x77, 0x0F, 0x36, 0x07, 0xA6, 0x5B, 0x5C, 0x30,
0xD1, 0xF2, 0xB1, 0x3C, 0xC8, 0xE9, 0x98, 0xB6, 0xD2, 0xC2, 0x48, 0x54, 0x40, 0x21, 0x5F, 0x2E, 0x3A, 0x9A,
0xD4, 0x98, 0x2F, 0x4A, 0xE3, 0x6A, 0x39, 0x0D, 0xC7, 0x69, 0xD3, 0xBA,
]),
PublicKey::new([
0x95, 0x79, 0x7E, 0xDA, 0xD1, 0xB9, 0xA4, 0x00, 0x15, 0x95, 0xFE, 0x88, 0x6B, 0x88, 0x64, 0x97, 0xF3, 0xF5,
0x83, 0xFD, 0xEA, 0x41, 0x66, 0xA0, 0xC4, 0x09, 0x5B, 0xE5, 0xAB, 0x84, 0x5F, 0x0D, 0x12, 0x2B, 0xD7, 0x28,
0xA3, 0x17, 0x5A, 0xBE, 0x0B, 0x18, 0x5C, 0xB7, 0xCD, 0x34, 0xEA, 0x25,
]),
PublicKey::new([
0x95, 0x7C, 0xE9, 0x53, 0xCE, 0x70, 0x05, 0x4E, 0xF6, 0x1F, 0x67, 0xFA, 0xEF, 0x51, 0x81, 0x74, 0x0C, 0xCE,
0xC7, 0x3F, 0xC5, 0x11, 0x41, 0x22, 0x74, 0x8C, 0x4E, 0x63, 0x54, 0x75, 0x6F, 0xD9, 0x94, 0xFE, 0x13, 0xBD,
0x88, 0xC0, 0xEB, 0x5D, 0x59, 0x31, 0x7F, 0xC1, 0xE0, 0xFD, 0xF1, 0x92,
]),
PublicKey::new([
0x95, 0x7B, 0x44, 0xA3, 0x5A, 0x9E, 0x65, 0x1B, 0x62, 0x64, 0xB3, 0xA1, 0xE2, 0x2A, 0x20, 0x2C, 0xDA, 0x1F,
0x0A, 0xA1, 0x5D, 0x99, 0x40, 0x58, 0x43, 0x7B, 0x19, 0xA3, 0x7C, 0xEF, 0x6E, 0xA5, 0x47, 0x1D, 0x1D, 0x9B,
0xD8, 0x62, 0x3E, 0x04, 0x5B, 0x6E, 0x9D, 0xD7, 0x28, 0xF1, 0x62, 0xAD,
]),
PublicKey::new([
0x95, 0x7B, 0x4F, 0x13, 0x17, 0x20, 0x70, 0xAA, 0xB0, 0xE1, 0x1D, 0x8B, 0xF0, 0xC8, 0x35, 0x8F, 0xD9, 0x60,
0xB4, 0xBD, 0x7A, 0xC8, 0x81, 0x48, 0x15, 0x8C, 0xF4, 0x97, 0x72, 0x76, 0xF3, 0x01, 0xBC, 0x61, 0x1D, 0xF4,
0xDA, 0x41, 0x6D, 0x26, 0x9B, 0x79, 0x96, 0x09, 0xDA, 0xF2, 0x0C, 0xF6,
]),
PublicKey::new([
0x95, 0x7B, 0x5C, 0x7B, 0x2D, 0x3B, 0x1B, 0x64, 0xB0, 0xE1, 0x3E, 0x56, 0x96, 0x7F, 0xD3, 0x71, 0xB9, 0xB5,
0xC3, 0xF8, 0x77, 0xE7, 0x11, 0xF4, 0x5C, 0xA3, 0xA5, 0x9A, 0x9D, 0x6D, 0xB3, 0x96, 0x11, 0x8B, 0xDF, 0x34,
0x09, 0x2D, 0x11, 0x3B, 0xF9, 0x64, 0x31, 0xA7, 0x66, 0xEA, 0x2C, 0xDE,
]),
PublicKey::new([
0x95, 0x7B, 0x5F, 0x6C, 0x26, 0xF9, 0x29, 0x31, 0x89, 0xB2, 0xCB, 0x33, 0x57, 0xD9, 0x32, 0x88, 0x9D, 0xC0,
0x23, 0xE3, 0x36, 0xA5, 0x34, 0x0C, 0x48, 0xC4, 0xD6, 0x79, 0x69, 0x57, 0x26, 0x70, 0x9D, 0x9C, 0x64, 0x0B,
0xC3, 0x0B, 0x1D, 0x71, 0x46, 0xE4, 0xE8, 0x12, 0x1F, 0xA2, 0x36, 0xE5,
]),
PublicKey::new([
0x95, 0x7B, 0x6C, 0x3B, 0x53, 0x8B, 0xF0, 0x85, 0x22, 0x07, 0x23, 0x27, 0xF1, 0x71, 0xE1, 0x3C, 0xBC, 0x47,
0xE3, 0x95, 0x5C, 0x73, 0x31, 0xDA, 0x43, 0x87, 0xEF, 0x71, 0x5D, 0x7E, 0x97, 0x76, 0x8A, 0x41, 0x7E, 0x76,
0x31, 0xF0, 0xC9, 0x67, 0x2A, 0xCD, 0xC2, 0x7C, 0x88, 0x2C, 0xBC, 0x11,
]),
PublicKey::new([
0x95, 0x7B, 0x74, 0x5C, 0x1A, 0x4C, 0x57, 0x98, 0x94, 0x81, 0xA1, 0xB5, 0x90, 0x2A, 0xC9, 0x01, 0x75, 0xCC,
0xE7, 0x79, 0x55, 0xA9, 0x9F, 0x5B, 0x53, 0x00, 0x96, 0x93, 0xB7, 0x47, 0xE1, 0xC0, 0x04, 0x09, 0xDC, 0xEF,
0x8B, 0x6D, 0x32, 0xFF, 0xA5, 0x0B, 0x35, 0x41, 0x8F, 0xD0, 0xE9, 0x89,
]),
PublicKey::new([
0x95, 0x7B, 0x7B, 0x07, 0x56, 0x2B, 0x10, 0x35, 0x73, 0xCE, 0x97, 0x74, 0x7D, 0xB2, 0xD7, 0x67, 0x3A, 0x04,
0x00, 0x84, 0xE2, 0xA6, 0x7B, 0x19, 0xB7, 0x71, 0x2B, 0xF1, 0xD5, 0xDB, 0xDC, 0xE1, 0x9B, 0xE6, 0xEB, 0xFB,
0xDB, 0x6E, 0xCC, 0x17, 0x36, 0x62, 0x55, 0x26, 0x1A, 0x27, 0x49, 0x60,
]),
PublicKey::new([
0x95, 0x7B, 0x87, 0xF8, 0xE4, 0x11, 0x4D, 0x09, 0xDB, 0x5A, 0x31, 0x20, 0x56, 0x83, 0x1F, 0x6B, 0xA9, 0xA0,
0x82, 0xEC, 0x16, 0x4E, 0x04, 0x46, 0x6D, 0xC6, 0x1C, 0x7B, 0x5A, 0xDC, 0xBB, 0xFC, 0xCA, 0x2D, 0x89, 0x6B,
0x96, 0x70, 0xEB, 0xA2, 0x92, 0x6B, 0xA2, 0x29, 0xEB, 0xCA, 0x42, 0x3E,
]),
PublicKey::new([
0x95, 0x7B, 0x92, 0x64, 0x58, 0xCB, 0x87, 0x1B, 0xA8, 0x82, 0x2D, 0x39, 0x8F, 0xC8, 0x25, 0xD8, 0x96, 0x4B,
0x25, 0xCA, 0xA7, 0x13, 0xFE, 0x19, 0x02, 0xEF, 0xB8, 0xDF, 0x19, 0x2D, 0xCD, 0xE3, 0xF6, 0xCE, 0x74, 0x78,
0x67, 0x27, 0x3D, 0xF8, 0x4A, 0xFB, 0x60, 0xBB, 0x95, 0x03, 0xB6, 0x16,
]),
PublicKey::new([
0x95, 0x7F, 0x01, 0xD5, 0x03, 0x64, 0x70, 0x14, 0xC3, 0xB7, 0x9B, 0x0A, 0x3E, 0xCB, 0x49, 0x18, 0xF3, 0x84,
0x32, 0x87, 0xE0, 0xBB, 0xFE, 0xDC, 0x3A, 0x41, 0x91, 0x84, 0x04, 0xC8, 0x35, 0xEA, 0xC9, 0x47, 0xB4, 0x76,
0x2F, 0xBA, 0x05, 0x21, 0x80, 0xC3, 0xC2, 0x00, 0x6C, 0x1B, 0x15, 0x03,
]),
PublicKey::new([
0x95, 0x7D, 0x5A, 0x0F, 0xBB, 0x34, 0x83, 0x05, 0x81, 0xD4, 0xC7, 0xCA, 0x1C, 0x83, 0xAF, 0xCB, 0xB2, 0xB0,
0x35, 0x21, 0x80, 0x18, 0x65, 0x72, 0x06, 0x87, 0x51, 0x72, 0xAC, 0xF3, 0x89, 0xC5, 0xA2, 0xC6, 0x84, 0xAF,
0x4D, 0x46, 0x96, 0xAE, 0x23, 0x0A, 0xCA, 0x43, 0x6C, 0x59, 0x0D, 0x45,
]),
PublicKey::new([
0x95, 0x7D, 0x68, 0x1A, 0x52, 0xD2, 0xF6, 0x9C, 0x2E, 0xFD, 0x07, 0x1E, 0x6A, 0xCE, 0xAC, 0x36, 0x6E, 0x72,
0x3A, 0xFA, 0xC5, 0x22, 0x36, 0xC3, 0xA8, 0xA8, 0x6D, 0x42, 0x22, 0x00, 0x18, 0x04, 0x40, 0xE7, 0xEA, 0x7E,
0xDE, 0x71, 0xB9, 0x5D, 0x01, 0xD2, 0x83, 0x0C, 0xB7, 0x0F, 0xC0, 0x21,
]),
PublicKey::new([
0x95, 0x7D, 0x6D, 0x07, 0x33, 0x88, 0x37, 0x07, 0x73, 0xF4, 0xFD, 0x7D, 0xAC, 0x5A, 0xA6, 0xD6, 0xC9, 0x8E,
0x7F, 0x69, 0x40, 0x5F, 0x8F, 0x14, 0x52, 0x76, 0x7F, 0xA2, 0xC8, 0x17, 0x9B, 0x0B, 0x23, 0x6B, 0xB2, 0x63,
0xCA, 0x76, 0x23, 0xEF, 0xC7, 0x70, 0x9B, 0xCF, 0xEE, 0x27, 0xA2, 0x1E,
]),
PublicKey::new([
0x95, 0x7D, 0x79, 0x1A, 0x6D, 0xB9, 0xBD, 0x07, 0xB9, 0x9E, 0x3E, 0x6B, 0xD5, 0xF0, 0x9B, 0x2F, 0x8E, 0xE5,
0x27, 0xDB, 0x92, 0xFE, 0x83, 0x49, 0x15, 0xBE, 0x1D, 0x5E, 0xA4, 0x57, 0xDA, 0xE5, 0x5E, 0xC9, 0x64, 0x41,
0x6A, 0x17, 0x42, 0x83, 0x5B, 0x5A, 0x78, 0x56, 0xE2, 0xE1, 0x6D, 0x5D,
]),
PublicKey::new([
0x95, 0x7D, 0x80, 0x31, 0x73, 0x85, 0x76, 0x17, 0x18, 0x10, 0xA0, 0xAC, 0x00, 0x28, 0x79, 0x42, 0xE5, 0x5B,
0x18, 0x2B, 0xD2, 0x75, 0x9F, 0xD0, 0x86, 0x48, 0x95, 0xA1, 0x21, 0xB3, 0x9A, 0xE0, 0x8D, 0xB6, 0x85, 0x6B,
0xC1, 0xF4, 0x2C, 0x88, 0x73, 0x6D, 0xE1, 0xEE, 0xFF, 0x9D, 0xD0, 0x28,
]),
PublicKey::new([
0x95, 0x7D, 0x8D, 0x30, 0x56, 0xFB, 0x29, 0x0F, 0x45, 0x2F, 0xC3, 0xF6, 0x2B, 0x3A, 0xAF, 0xFD, 0xAB, 0x48,
0x35, 0xC5, 0xDE, 0x3A, 0x7B, 0xDD, 0x01, 0x30, 0x2F, 0x9F, 0xEB, 0xD2, 0x36, 0xDC, 0xFD, 0x1E, 0x6B, 0xA6,
0xF1, 0xF4, 0xEC, 0xF8, 0x82, 0x32, 0xFA, 0x14, 0x17, 0x8A, 0x81, 0xCD,
]),
PublicKey::new([
0x95, 0x7D, 0x90, 0x5B, 0xDB, 0x26, 0xCB, 0x87, 0xD9, 0x80, 0x39, 0x03, 0xBF, 0x49, 0x39, 0x30, 0xCA, 0x21,
0x42, 0xCE, 0xC6, 0xEB, 0xED, 0x9D, 0x22, 0x5D, 0xD4, 0xF4, 0x6D, 0x90, 0x63, 0x18, 0xB4, 0xE8, 0x45, 0xDD,
0xA7, 0xA9, 0x2E, 0x62, 0xF2, 0xD4, 0xB1, 0x59, 0xD4, 0xCD, 0x9B, 0x66,
]),
PublicKey::new([
0x95, 0x7D, 0x9D, 0x0E, 0x22, 0x5F, 0x2B, 0x3B, 0xFE, 0xDC, 0x80, 0xDD, 0xBF, 0x09, 0x73, 0x7F, 0xED, 0x21,
0xDC, 0x4D, 0x94, 0xD3, 0x4C, 0x40, 0xCE, 0xC1, 0x0E, 0x2F, 0x54, 0x02, 0xA5, 0x42, 0xBA, 0xB7, 0x98, 0xEC,
0x89, 0x79, 0xD8, 0xEE, 0x97, 0x0D, 0x9F, 0x51, 0xB5, 0x0D, 0xFE, 0xAA,
]),
PublicKey::new([
0x95, 0x7D, 0xA7, 0xF8, 0xC6, 0xB6, 0xAE, 0x33, 0x22, 0x25, 0x93, 0x1D, 0x85, 0x6D, 0x59, 0xB4, 0xF7, 0x6B,
0xF5, 0x8E, 0x51, 0x33, 0x7A, 0x10, 0x19, 0xCC, 0xB4, 0x86, 0x91, 0x30, 0x90, 0x96, 0x30, 0xC1, 0x7A, 0xD1,
0x04, 0x19, 0x5B, 0x3C, 0xED, 0x37, 0xC6, 0xF2, 0xA4, 0x82, 0xB0, 0x32,
]),
PublicKey::new([
0x95, 0x81, 0x0F, 0x01, 0xD9, 0x42, 0x31, 0xA0, 0xD1, 0xCA, 0x47, 0xB6, 0x54, 0x73, 0x7A, 0x5C, 0x12, 0x9E,
0x05, 0x70, 0xA4, 0x3C, 0x10, 0x2C, 0xFE, 0x6F, 0x4F, 0x14, 0x08, 0x01, 0x6E, 0x1A, 0x67, 0xEB, 0xD4, 0x44,
0x16, 0x86, 0x06, 0x5B, 0x4F, 0x5A, 0x5F, 0xF8, 0x1D, 0xC5, 0x0D, 0x15,
]),
PublicKey::new([
0x95, 0x7F, 0x71, 0x5D, 0x5A, 0x80, 0x47, 0x4F, 0x48, 0xC9, 0x3C, 0x7C, 0x96, 0x33, 0x25, 0x18, 0xFD, 0x66,
0x33, 0x3B, 0x88, 0x11, 0xD9, 0x62, 0x60, 0xDC, 0xFF, 0xA8, 0xD3, 0xEA, 0xD9, 0x96, 0xDC, 0x07, 0xAA, 0x37,
0x83, 0xD0, 0xD6, 0x9E, 0x6A, 0x1E, 0x2F, 0x76, 0xAB, 0x56, 0x4E, 0x5D,
]),
PublicKey::new([
0x95, 0x7F, 0x78, 0x77, 0xD6, 0x6F, 0x92, 0x7F, 0x27, 0x5E, 0xD9, 0x0D, 0x10, 0x92, 0xEC, 0xE2, 0xF4, 0x51,
0xE0, 0xFE, 0xA7, 0x82, 0x56, 0x30, 0xEF, 0x6A, 0x70, 0x1C, 0x77, 0xCF, 0x00, 0xD6, 0x4B, 0xC0, 0x52, 0x98,
0x76, 0xCF, 0x2F, 0x24, 0xFC, 0xE8, 0x19, 0xA5, 0xC1, 0x9C, 0xE3, 0xC4,
]),
PublicKey::new([
0x95, 0x7F, 0x82, 0xD6, 0x2B, 0xA1, 0xC1, 0xB1, 0x44, 0xFB, 0x91, 0x3A, 0x08, 0x22, 0xB8, 0xA5, 0x50, 0x6C,
0x8F, 0xBC, 0xDA, 0xD7, 0x2F, 0x08, 0xE0, 0x6C, 0x64, 0x2D, 0x62, 0xB8, 0xE9, 0x64, 0xE5, 0xD4, 0xA2, 0x97,
0xAC, 0x19, 0xF9, 0x3A, 0x4A, 0xAA, 0x0E, 0xFD, 0xE9, 0xAD, 0x1C, 0x10,
]),
PublicKey::new([
0x95, 0x7F, 0x88, 0x8A, 0xD9, 0x02, 0x17, 0x03, 0x4D, 0x82, 0x4E, 0xF1, 0xB3, 0x15, 0x97, 0xB2, 0x2D, 0xA5,
0xC9, 0x16, 0x8D, 0x6A, 0x84, 0x03, 0x1B, 0xB8, 0x45, 0x3F, 0xAF, 0x68, 0xC4, 0x7C, 0x9B, 0x61, 0x39, 0x6B,
0x17, 0x9B, 0xD9, 0xA1, 0xB4, 0x24, 0xB3, 0x6C, 0x40, 0xD6, 0xCE, 0xD2,
]),
PublicKey::new([
0x95, 0x7F, 0x90, 0x81, 0x23, 0x3F, 0x67, 0x0E, 0x75, 0x0D, 0xA6, 0xA5, 0x2E, 0x67, 0x77, 0x68, 0xBB, 0x7B,
0xEC, 0x29, 0x65, 0x95, 0x2F, 0x2A, 0xC7, 0x7B, 0xB6, 0x99, 0x90, 0xA6, 0xBF, 0xC5, 0x04, 0xF9, 0x9B, 0x53,
0xB7, 0x13, 0x02, 0x2B, 0xE2, 0x39, 0xE7, 0xCF, 0xB6, 0xEB, 0xBC, 0x99,
]),
PublicKey::new([
0x95, 0x7F, 0x9B, 0xF2, 0xBF, 0xA1, 0x49, 0x97, 0x1C, 0x38, 0xA1, 0x9C, 0x30, 0x0D, 0xC1, 0x83, 0x48, 0xC2,
0x5F, 0x37, 0xBA, 0xF9, 0xED, 0x41, 0x42, 0xD1, 0x76, 0x19, 0xCB, 0xBF, 0x10, 0x7A, 0x6C, 0x9B, 0xF3, 0x3D,
0xB6, 0x50, 0xB9, 0x9E, 0x79, 0x34, 0x0C, 0xEC, 0xE5, 0xE3, 0x34, 0x62,
]),
PublicKey::new([
0x95, 0x7F, 0xA8, 0xB2, 0x6F, 0x63, 0xB8, 0x50, 0x88, 0x78, 0x55, 0xF6, 0xF3, 0xD7, 0x16, 0xA5, 0xD4, 0x75,
0x78, 0xB0, 0x4A, 0x85, 0x00, 0xB2, 0x6D, 0x1D, 0x87, 0x11, 0xE6, 0x45, 0xB9, 0xBD, 0xF7, 0x2B, 0xD4, 0x5E,
0x2E, 0x6C, 0x51, 0x4B, 0xA0, 0xF8, 0x8B, 0x22, 0x52, 0x52, 0xB4, 0x05,
]),
PublicKey::new([
0x95, 0x7F, 0xAA, 0xBA, 0xDE, 0x3F, 0x91, 0x59, 0xFA, 0x2B, 0x17, 0xCB, 0x94, 0x70, 0xE4, 0xBE, 0xAD, 0x8C,
0xE5, 0xE8, 0x8C, 0x3B, 0x63, 0x9C, 0x7E, 0x86, 0x17, 0xDA, 0x81, 0x40, 0xB8, 0x63, 0x4E, 0x1A, 0xA2, 0xE4,
0xDC, 0x32, 0x5D, 0x13, 0x14, 0x07, 0x44, 0xB8, 0x9F, 0xC6, 0xD3, 0xA0,
]),
PublicKey::new([
0x95, 0x7F, 0xB2, 0xF3, 0x59, 0x75, 0xF4, 0x3A, 0xF8, 0xCD, 0xC9, 0xCB, 0x85, 0x3D, 0xEF, 0x7C, 0x8F, 0x7F,
0x62, 0x64, 0x19, 0xBB, 0x5A, 0xE5, 0xEC, 0xF3, 0x20, 0xA3, 0xB2, 0xC0, 0xC3, 0x5F, 0x78, 0x15, 0x0C, 0x84,
0x08, 0x50, 0x91, 0x85, 0x98, 0x74, 0x94, 0x19, 0x10, 0x09, 0x03, 0x68,
]),
PublicKey::new([
0x95, 0x83, 0x23, 0xC2, 0x76, 0x16, 0xC6, 0x32, 0x14, 0x57, 0xA1, 0x14, 0x53, 0x81, 0xA3, 0x5C, 0x1F, 0xC7,
0xD1, 0x1C, 0xDB, 0xC7, 0xFA, 0xD0, 0x0B, 0x92, 0x91, 0x40, 0xCA, 0xA9, 0xBF, 0x9A, 0x3D, 0x02, 0xE6, 0xA4,
0x75, 0x61, 0xCB, 0xA3, 0xD9, 0x9E, 0x7E, 0x1F, 0x78, 0x89, 0x51, 0xB5,
]),
PublicKey::new([
0x95, 0x81, 0x84, 0xAF, 0x90, 0xEC, 0x9E, 0x53, 0x6E, 0xD5, 0xA7, 0x60, 0xF0, 0x03, 0xCC, 0xE6, 0x61, 0x6F,
0x7E, 0xED, 0x9E, 0x3F, 0x9C, 0x29, 0xC3, 0x0E, 0x98, 0xCA, 0x29, 0xE6, 0x08, 0x93, 0xEF, 0x57, 0xCE, 0x2F,
0xF0, 0xC9, 0x95, 0xFB, 0x94, 0x56, 0x6A, 0xC7, 0x71, 0x2D, 0xCF, 0x79,
]),
PublicKey::new([
0x95, 0x81, 0x8C, 0x8C, 0x69, 0xEA, 0x6C, 0x8B, 0x54, 0xE2, 0xDC, 0xA3, 0xC9, 0x96, 0xB5, 0x56, 0xF3, 0xED,
0xC3, 0x00, 0x69, 0x43, 0x6D, 0xF2, 0x49, 0x09, 0x6F, 0xBF, 0x13, 0xE2, 0x71, 0x23, 0xAD, 0xB7, 0x7D, 0x39,
0x65, 0x44, 0x51, 0x83, 0xAA, 0xDA, 0xD2, 0x7A, 0x29, 0x25, 0x3E, 0xE7,
]),
PublicKey::new([
0x95, 0x81, 0x92, 0xF8, 0x69, 0x66, 0xE8, 0x73, 0xE2, 0xB4, 0x29, 0xEF, 0x7A, 0xA1, 0x33, 0x70, 0x75, 0x71,
0x96, 0xBF, 0xBB, 0x6A, 0xED, 0xFF, 0x1D, 0x11, 0x24, 0x26, 0x49, 0x47, 0x7A, 0x04, 0x07, 0xBE, 0x47, 0x32,
0x57, 0xB9, 0xDE, 0xBE, 0x80, 0x8B, 0xC0, 0xB5, 0x24, 0x63, 0xBA, 0x8F,
]),
PublicKey::new([
0x95, 0x81, 0x99, 0x07, 0x4D, 0x30, 0x9A, 0xB2, 0x13, 0x66, 0x7C, 0xB6, 0x3C, 0x7C, 0x50, 0xD3, 0x38, 0x5E,
0x55, 0x36, 0xBA, 0xA1, 0x3F, 0xE1, 0xAA, 0xAC, 0xED, 0xAB, 0x0C, 0x93, 0x89, 0x34, 0xFC, 0x6E, 0x44, 0xBA,
0xD0, 0x5C, 0x17, 0x32, 0x8D, 0xE4, 0x5F, 0x87, 0x92, 0xAA, 0x63, 0x92,
]),
PublicKey::new([
0x95, 0x81, 0xA4, 0xE2, 0x84, 0x71, 0xA4, 0xD2, 0x6C, 0x39, 0x2B, 0x2A, 0x03, 0x19, 0xE0, 0x9A, 0x41, 0x27,
0x08, 0xED, 0xC2, 0x93, 0x7B, 0x49, 0x51, 0x27, 0x4A, 0x3A, 0xF5, 0x54, 0x6E, 0x35, 0x97, 0x83, 0x6B, 0x71,
0xE2, 0xAF, 0x51, 0x24, 0xEC, 0xE5, 0x46, 0x23, 0xFA, 0x82, 0x38, 0x1D,
]),
PublicKey::new([
0x95, 0x81, 0xAB, 0x66, 0x9D, 0xDE, 0x3B, 0xDE, 0xDE, 0x43, 0xCE, 0x68, 0x14, 0xD1, 0xEE, 0x3B, 0x54, 0x9A,
0x48, 0x6B, 0x01, 0xD5, 0x96, 0xD8, 0xC2, 0x09, 0xF7, 0x8F, 0x87, 0xBE, 0x0A, 0x3F, 0x6A, 0x66, 0x8E, 0x62,
0xE1, 0x5A, 0x8F, 0x31, 0xCE, 0xD9, 0xBF, 0x86, 0xA3, 0x61, 0x37, 0x5D,
]),
];
pub fn call_set_emission_address(env: &mut ApplyEnv, args: Vec<Vec<u8>>) -> Result<(), &'static str> {
if args.len() != 1 {
return Err("invalid_args");
}
let address = args[0].as_slice();
if address.len() != 48 {
return Err("invalid_address_pk");
}
kv_put(env, &bcat(&[b"bic:epoch:emission_address:", env.caller_env.account_caller.as_slice()]), address)?;
Ok(())
}
pub fn call_submit_sol(env: &mut ApplyEnv, args: Vec<Vec<u8>>) -> Result<(), &'static str> {
if args.len() != 1 {
return Err("invalid_args");
}
let sol = args[0].as_slice();
if sol.len() != consensus::bic::sol::SOL_SIZE {
return Err("invalid_sol_seed_size");
}
let sol: [u8; consensus::bic::sol::SOL_SIZE] = sol.try_into().map_err(|_| "invalid_sol_size")?;
let hash = blake3::hash(&sol);
let mut flips = 0;
for seg in consensus::bic::sol_bloom::segs_from_digest(&hash) {
let key = format!("bic:epoch:solbloom:{}", seg.page).into_bytes();
if kv_set_bit(env, &key, seg.bit_offset)? {
flips += 1
}
}
if flips == 0 {
return Err("sol_exists");
}
let usol = consensus::bic::sol::unpack(&sol)?;
if env.caller_env.entry_epoch != usol.epoch {
return Err("invalid_epoch");
}
let segment_vr_hash = kv_get(env, b"bic:epoch:segment_vr_hash")?.ok_or("missing_segment_vr_hash")?;
let diff_bits = kv_get(env, b"bic:epoch:diff_bits")?.ok_or("missing_diff_bits")?;
let diff_bits_int =
std::str::from_utf8(&diff_bits).ok().and_then(|s| s.parse::<u64>().ok()).ok_or("invalid_diff_bits")?;
let hash_bytes: Hash = hash.into();
if !consensus::bic::sol::verify(
&sol,
&hash_bytes[..],
&segment_vr_hash,
env.caller_env.entry_vr_b3.as_ref(),
diff_bits_int,
)
.unwrap_or(false)
{
return Err("invalid_sol");
}
if !kv_exists(env, &bcat(&[b"bic:epoch:pop:", usol.pk.as_ref()]))? {
match bls12_381::verify(&usol.pk, &usol.pop, usol.pk.as_ref(), amadeus_utils::constants::DST_POP) {
Ok(()) => kv_put(env, &bcat(&[b"bic:epoch:pop:", usol.pk.as_ref()]), usol.pop.as_ref())?,
Err(_) => return Err("invalid_pop"),
}
}
kv_increment(env, &bcat(&[b"bic:epoch:solutions_count:", usol.pk.as_ref()]), 1)?;
Ok(())
}
pub fn kv_get_epoch_trainers(env: &ApplyEnv, key: &[u8]) -> Result<Vec<Vec<u8>>, &'static str> {
use amadeus_utils::vecpak::{decode, Term};
match kv_get(env, key)? {
None => Ok(Vec::new()),
Some(trainer_list) => {
let term = decode(trainer_list.as_slice()).map_err(|_| "invalid_vecpak")?;
match term {
Term::List(term_list) => {
let mut out = Vec::with_capacity(term_list.len());
for el in term_list {
if let Term::Binary(b) = el {
out.push(b);
} else {
return Err("invalid_trainer_list_term");
}
}
Ok(out)
}
_ => Err("invalid_trainer_list_term"),
}
}
}
}
pub fn kv_get_height_trainers(env: &ApplyEnv, prefix: &[u8], key: &[u8]) -> Vec<Vec<u8>> {
use amadeus_utils::vecpak::{decode, Term};
match kv_get_prev_or_exact(env, prefix, key) {
None => Vec::new(),
Some((_key_suffix, trainer_list)) => {
let term = match decode(trainer_list.as_slice()) {
Ok(t) => t,
Err(_) => return Vec::new(),
};
match term {
Term::List(term_list) => {
let mut out = Vec::with_capacity(term_list.len());
for el in term_list {
if let Term::Binary(b) = el {
out.push(b);
}
}
out
}
_ => Vec::new(),
}
}
}
}
pub fn call_slash_trainer(env: &mut ApplyEnv, args: Vec<Vec<u8>>) -> Result<(), &'static str> {
if args.len() != 5 {
return Err("invalid_args");
}
let epoch = args[0].as_slice();
let epoch = std::str::from_utf8(&epoch).ok().and_then(|s| s.parse::<u64>().ok()).ok_or("invalid_epoch")?;
let malicious_pk = args[1].as_slice();
let signature = args[2].as_slice();
let mask_size = args[3].as_slice();
let mask_size =
std::str::from_utf8(&mask_size).ok().and_then(|s| s.parse::<u64>().ok()).ok_or("invalid_mask_size")?;
let mask = args[4].to_vec();
if epoch != env.caller_env.entry_epoch {
return Err("invalid_epoch");
}
let mut trainers = kv_get_epoch_trainers(env, &bcat(&[b"bic:epoch:trainers:", epoch.to_string().as_bytes()]))?;
if !trainers.iter().any(|v| v.as_slice() == malicious_pk) {
return Err("invalid_trainer_pk");
}
let trainers_48: Vec<PublicKey> = trainers
.iter()
.filter_map(|pk| {
if pk.len() == 48 {
let mut arr = [0u8; 48];
arr.copy_from_slice(pk);
Some(PublicKey::new(arr))
} else {
None
}
})
.collect();
let mask_bitvec = BitVec::from_vec(mask);
let signers = unmask_trainers(&mask_bitvec, &trainers_48);
let consensus_pct = signers.len() as f64 / trainers.len() as f64;
if consensus_pct < 0.67 {
return Err("invalid_amount_of_signatures");
}
let apk = bls12_381::aggregate_public_keys(signers).map_err(|_| "invalid_aggregation")?;
let msg = bcat(&[b"slash_trainer", (epoch as u32).to_le_bytes().as_slice(), malicious_pk]);
let signature_valid = match bls12_381::verify(&apk, signature, msg.as_slice(), DST_MOTION) {
Ok(()) => true,
_ => false,
};
if !signature_valid {
return Err("invalid_signature");
}
let mut trainers_removed =
kv_get_epoch_trainers(env, &bcat(&[b"bic:epoch:trainers:removed:", epoch.to_string().as_bytes()]))?;
trainers_removed.push(malicious_pk.to_vec());
let term_trainers_removed = amadeus_utils::misc::list_of_binaries_to_vecpak(trainers_removed);
kv_put(
env,
&bcat(&[b"bic:epoch:trainers:removed:", epoch.to_string().as_bytes()]),
term_trainers_removed.as_slice(),
)?;
trainers.retain(|pk| pk.as_slice() != malicious_pk);
let term_trainers = amadeus_utils::misc::list_of_binaries_to_vecpak(trainers);
kv_put(env, &bcat(&[b"bic:epoch:trainers:", epoch.to_string().as_bytes()]), term_trainers.as_slice())?;
let height = format!("{:012}", env.caller_env.entry_height.saturating_add(1)).into_bytes();
kv_put(env, &bcat(&[b"bic:epoch:trainers:height:", &height]), term_trainers.as_slice())?;
Ok(())
}
pub fn next(env: &mut ApplyEnv) {
let epoch_cur = env.caller_env.entry_epoch;
if epoch_cur >= 295 && epoch_cur < 420 {
next_420(env);
} else {
next_pre_420(env);
}
}
fn next_420(env: &mut ApplyEnv) {
let epoch_cur = env.caller_env.entry_epoch;
let epoch_next = epoch_cur + 1;
let leaders = get_sorted_leaders_excluding_removed(env, epoch_cur);
let trainers_key = bcat(&[b"bic:epoch:trainers:", &epoch_cur.to_string().as_bytes()]);
let trainers: Vec<Vec<u8>> = kv_get_epoch_trainers(env, &trainers_key).unwrap_or_default();
let trainers_to_recv_emissions: Vec<_> = leaders
.iter()
.filter(|(pk, _)| {
trainers.iter().any(|t| t == pk) && !PEDDLEBIKE67.iter().any(|p| p.as_slice() == pk.as_slice())
})
.take(99)
.collect();
let epoch_total_emission = epoch_emission(epoch_cur);
let epoch_early_adopter_emission = epoch_total_emission / 7;
let epoch_communityfund_emission = epoch_total_emission - epoch_early_adopter_emission;
distribute_peddlebike67_community_fund(env, epoch_communityfund_emission);
let total_sols: i128 = trainers_to_recv_emissions.iter().map(|(_, count)| count).sum();
distribute_emissions_to_trainers(env, &trainers_to_recv_emissions, epoch_early_adopter_emission, total_sols);
let new_validators = build_and_shuffle_new_validators(env, &leaders);
store_new_trainers_for_next_epoch(env, epoch_next, new_validators);
update_difficulty_and_log_sols(env, epoch_cur, epoch_next, total_sols);
clear_epoch_data(env);
}
fn next_pre_420(env: &mut ApplyEnv) {
let epoch_cur = env.caller_env.entry_epoch;
let epoch_next = epoch_cur + 1;
let leaders = get_sorted_leaders_excluding_removed(env, epoch_cur);
let trainers_key = bcat(&[b"bic:epoch:trainers:", &epoch_cur.to_string().as_bytes()]);
let trainers: Vec<Vec<u8>> = kv_get_epoch_trainers(env, &trainers_key).unwrap_or_default();
let trainers_to_recv_emissions: Vec<_> =
leaders.iter().filter(|(pk, _)| trainers.iter().any(|t| t == pk)).take(99).collect();
let epoch_total_emission = epoch_emission(epoch_cur);
let total_sols: i128 = trainers_to_recv_emissions.iter().map(|(_, count)| count).sum();
distribute_emissions_to_trainers(env, &trainers_to_recv_emissions, epoch_total_emission, total_sols);
let new_validators = build_and_shuffle_new_validators(env, &leaders);
store_new_trainers_for_next_epoch(env, epoch_next, new_validators);
clear_epoch_data(env);
}
fn get_sorted_leaders_excluding_removed(env: &ApplyEnv, epoch: u64) -> Vec<(Vec<u8>, i128)> {
use crate::consensus::consensus_kv::kv_get_prefix;
use amadeus_utils::vecpak::{decode, VecpakExt};
let removed_key = bcat(&[b"bic:epoch:trainers:removed:", &epoch.to_string().as_bytes()]);
let removed_trainers: Vec<Vec<u8>> = kv_get(env, &removed_key)
.ok()
.flatten()
.and_then(|bytes| {
let term = decode(&bytes[..]).ok()?;
let list = term.get_list()?;
Some(list.iter().filter_map(|t| t.get_binary()).map(|b| b.to_vec()).collect())
})
.unwrap_or_default();
let leaders_raw = kv_get_prefix(env, b"bic:epoch:solutions_count:");
let mut leaders: Vec<(Vec<u8>, i128)> = leaders_raw
.into_iter()
.filter_map(|(pk_bytes, value_bytes)| {
if removed_trainers.contains(&pk_bytes) {
return None;
}
atoi::atoi::<i128>(&value_bytes).map(|count| (pk_bytes, count))
})
.collect();
leaders.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| b.0.cmp(&a.0)));
leaders
}
fn distribute_emissions_to_trainers(
env: &mut ApplyEnv,
trainers_to_recv: &[&(Vec<u8>, i128)],
total_emission: i128,
total_sols: i128,
) {
if total_sols == 0 {
return;
}
for (trainer, trainer_sols) in trainers_to_recv {
let coins = (trainer_sols * total_emission) / total_sols;
let emission_addr_key = bcat(&[b"bic:epoch:emission_address:", trainer]);
let emission_address = kv_get(env, &emission_addr_key).ok().flatten();
let balance_key = if let Some(addr) = emission_address {
bcat(&[b"account:", &addr, b":balance:AMA"])
} else {
bcat(&[b"account:", trainer, b":balance:AMA"])
};
let _ = kv_increment(env, &balance_key, coins);
}
}
fn build_and_shuffle_new_validators(env: &ApplyEnv, leaders: &[(Vec<u8>, i128)]) -> Vec<Vec<u8>> {
use amadeus_utils::exsss::Exsss;
let leader_pks: Vec<Vec<u8>> = leaders.iter().map(|(pk, _)| pk.clone()).collect();
let filtered_leaders: Vec<Vec<u8>> =
leader_pks.into_iter().filter(|pk| !PEDDLEBIKE67.iter().any(|p| p.as_slice() == pk.as_slice())).collect();
let mut new_validators: Vec<Vec<u8>> = PEDDLEBIKE67.iter().map(|p| p.to_vec()).collect();
new_validators.extend(filtered_leaders);
new_validators.truncate(99);
let seed_bytes = &env.caller_env.seed;
let seed_array: Hash =
seed_bytes.get(..32).and_then(|s| s.try_into().ok()).map(Hash::new).unwrap_or(Hash::new([0u8; 32]));
let mut rng = Exsss::from_seed(&seed_array);
rng.shuffle(&mut new_validators);
new_validators
}
fn store_new_trainers_for_next_epoch(env: &mut ApplyEnv, epoch_next: u64, new_validators: Vec<Vec<u8>>) {
use crate::consensus::consensus_kv::kv_put;
let term = amadeus_utils::misc::list_of_binaries_to_vecpak(new_validators);
let trainers_next_key = bcat(&[b"bic:epoch:trainers:", &epoch_next.to_string().as_bytes()]);
let _ = kv_put(env, &trainers_next_key, &term);
let height = format!("{:012}", env.caller_env.entry_height + 1);
let trainers_height_key = bcat(&[b"bic:epoch:trainers:height:", height.as_bytes()]);
let _ = kv_put(env, &trainers_height_key, &term);
}
fn clear_epoch_data(env: &mut ApplyEnv) {
use crate::consensus::consensus_kv::kv_clear_prefix;
let _ = kv_clear_prefix(env, b"bic:epoch:solbloom:");
let _ = kv_clear_prefix(env, b"bic:epoch:solutions_count:");
}
fn distribute_peddlebike67_community_fund(env: &mut ApplyEnv, total_emission: i128) {
let n_count = PEDDLEBIKE67.len() as i128;
let q = total_emission / n_count;
let r = total_emission % n_count;
for (i, peddle_pk) in PEDDLEBIKE67.iter().enumerate() {
let coins = if (i as i128) < r { q + 1 } else { q };
let emission_addr_key = bcat(&[b"bic:epoch:emission_address:", peddle_pk.as_slice()]);
let emission_address = kv_get(env, &emission_addr_key).ok().flatten();
let balance_key = if let Some(addr) = emission_address {
bcat(&[b"account:", &addr, b":balance:AMA"])
} else {
bcat(&[b"account:", peddle_pk.as_slice(), b":balance:AMA"])
};
let _ = kv_increment(env, &balance_key, coins);
}
}
fn update_difficulty_and_log_sols(env: &mut ApplyEnv, epoch_cur: u64, epoch_next: u64, total_sols: i128) {
use crate::consensus::consensus_kv::kv_put;
let old_diff_bits =
kv_get(env, b"bic:epoch:diff_bits").ok().flatten().and_then(|bytes| atoi::atoi::<u32>(&bytes)).unwrap_or(24);
let next_diff_bits = crate::consensus::bic::sol_difficulty::next(old_diff_bits, total_sols as u64);
let _ = kv_put(env, b"bic:epoch:diff_bits", next_diff_bits.to_string().as_bytes());
let diff_key = format!("bic:epoch:diff_bits:{}", epoch_next);
let _ = kv_put(env, diff_key.as_bytes(), next_diff_bits.to_string().as_bytes());
let sols_key = format!("bic:epoch:total_sols:{}", epoch_cur);
let _ = kv_put(env, sols_key.as_bytes(), total_sols.to_string().as_bytes());
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EpochCall {
SubmitSol {
sol: Vec<u8>,
},
SetEmissionAddress {
address: PublicKey,
},
SlashTrainer {
epoch: u64,
malicious_pk: PublicKey,
signature: Vec<u8>,
mask: bitvec::vec::BitVec<u8, bitvec::order::Msb0>,
trainers: Option<Vec<PublicKey>>,
},
}
#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
pub enum EpochError {
#[error("sol_exists")]
SolExists,
#[error("invalid_sol")]
InvalidSol,
#[error("invalid_epoch")]
InvalidEpoch,
#[error("invalid_pop")]
InvalidPop,
#[error("invalid_address_pk")]
InvalidAddressPk,
}
pub struct Epoch;
impl Epoch {
pub fn call(&self, env: &mut ApplyEnv, op: EpochCall) -> Result<(), EpochError> {
match op {
EpochCall::SubmitSol { sol } => call_submit_sol(env, vec![sol]).map_err(|e| match e {
"sol_exists" => EpochError::SolExists,
"invalid_sol" | "invalid_sol_seed_size" | "invalid_sol_size" => EpochError::InvalidSol,
"invalid_epoch" => EpochError::InvalidEpoch,
"invalid_pop" => EpochError::InvalidPop,
_ => EpochError::InvalidSol,
}),
EpochCall::SetEmissionAddress { address } => call_set_emission_address(env, vec![address.to_vec()])
.map_err(|e| match e {
"invalid_address_pk" => EpochError::InvalidAddressPk,
_ => EpochError::InvalidAddressPk,
}),
EpochCall::SlashTrainer { epoch, malicious_pk, signature, mask, trainers } => {
let mut args = vec![epoch.to_le_bytes().to_vec(), malicious_pk.to_vec(), signature];
let mask_bytes = mask.into_vec();
args.push(mask_bytes);
if let Some(t) = trainers {
args.push(
amadeus_utils::misc::list_of_binaries_to_vecpak(t.into_iter().map(|pk| pk.to_vec()).collect()),
);
}
call_slash_trainer(env, args).map_err(|_| EpochError::InvalidEpoch)
}
}
}
pub fn next(&self, env: &mut ApplyEnv) {
next(env);
}
}
pub fn trainers_for_height(db: &amadeus_utils::rocksdb::RocksDb, height: u64) -> Option<Vec<PublicKey>> {
use amadeus_utils::vecpak::{decode, VecpakExt};
let value: Option<Vec<u8>> = if (3_195_570..=3_195_575).contains(&height) {
match db.get(CF_CONTRACTSTATE, b"bic:epoch:trainers:height:000000319557") {
Ok(v) => v,
Err(_) => return None,
}
} else {
let key_suffix = format!("{:012}", height);
match db.get_prev_or_first(CF_CONTRACTSTATE, "bic:epoch:trainers:height:", &key_suffix) {
Ok(Some((_k, v))) => Some(v),
Ok(None) => None,
Err(_) => return None,
}
};
let bytes = value?;
let term = decode(&bytes[..]).ok()?;
let list = term.get_list()?;
let mut out = Vec::with_capacity(list.len());
for t in list {
let pk = t.get_binary()?;
if pk.len() != 48 {
return None;
}
let mut arr = [0u8; 48];
arr.copy_from_slice(pk);
out.push(PublicKey::new(arr));
}
Some(out)
}
pub fn unmask_trainers(mask: &BitVec<u8, Msb0>, trainers: &[PublicKey]) -> Vec<PublicKey> {
mask.iter().zip(trainers.iter()).filter_map(|(bit, pk)| if *bit { Some(*pk) } else { None }).collect()
}