amadeus_runtime/consensus/bic/
epoch.rs

1use crate::consensus::consensus_apply::ApplyEnv;
2use crate::consensus::consensus_kv::{kv_exists, kv_get, kv_get_prev_or_exact, kv_increment, kv_put, kv_set_bit};
3use crate::{bcat, consensus};
4use amadeus_utils::constants::{CF_CONTRACTSTATE, DST_MOTION};
5use amadeus_utils::{Hash, PublicKey, Signature};
6use amadeus_utils::{blake3, bls12_381};
7use bitvec::order::Msb0;
8use bitvec::prelude::BitVec;
9
10pub const EPOCH_EMISSION_BASE: i128 = 1_000_000_000_000_000;
11pub const EPOCH_INTERVAL: i128 = 100_000;
12
13pub const TREASURY_DONATION_ADDRESS: &[u8; 48] = &[
14    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,
15    254, 87, 139, 252, 148, 176, 113, 6, 207, 153, 51, 25, 202, 45, 48, 153, 223, 248, 219, 210, 80, 254,
16];
17
18pub fn epoch_emission(epoch: u64) -> i128 {
19    epoch_emission_1(epoch, EPOCH_EMISSION_BASE)
20}
21
22fn epoch_emission_1(epoch: u64, acc: i128) -> i128 {
23    if epoch == 0 {
24        acc
25    } else {
26        let sub = acc.saturating_mul(333) / 1_000_000;
27        let emitted = acc.saturating_sub(sub);
28        epoch_emission_1(epoch - 1, emitted)
29    }
30}
31
32pub fn circulating_without_burn(epoch: u64) -> i128 {
33    fn rec(n: u64, acc: i128) -> i128 {
34        if n == 0 { acc } else { rec(n - 1, acc + epoch_emission(n)) }
35    }
36    rec(epoch, 0)
37}
38
39pub const PEDDLEBIKE67: &[PublicKey; 67] = &[
40    PublicKey::new([
41        0x95, 0xD8, 0x37, 0xFF, 0x1D, 0x08, 0xEF, 0xFB, 0x8B, 0x70, 0x1E, 0x1D, 0xC7, 0x39, 0x5A, 0x43, 0xC6, 0xDC,
42        0x65, 0x12, 0xE4, 0x64, 0x64, 0xF1, 0x2B, 0xD5, 0xDD, 0xE6, 0xFD, 0x3A, 0xE7, 0x01, 0x66, 0xA6, 0x36, 0x42,
43        0xF5, 0x94, 0x8C, 0x2C, 0x4E, 0x38, 0x54, 0x0C, 0xDE, 0xCD, 0x39, 0xD2,
44    ]),
45    PublicKey::new([
46        0x95, 0xD6, 0x8B, 0xD8, 0x44, 0x2D, 0xAA, 0x15, 0xF6, 0x96, 0x24, 0x5D, 0x22, 0xFD, 0x16, 0x5C, 0x70, 0xBA,
47        0x03, 0x76, 0xA8, 0xEC, 0xBE, 0x28, 0xD5, 0xD6, 0x30, 0xF7, 0x8F, 0x94, 0xDD, 0x9E, 0x81, 0xB1, 0x69, 0xA2,
48        0x4A, 0xC7, 0x64, 0x24, 0x58, 0x0E, 0x58, 0x77, 0xF3, 0xC3, 0x0B, 0xB0,
49    ]),
50    PublicKey::new([
51        0x95, 0xD6, 0x95, 0x90, 0x56, 0xCC, 0x5C, 0x67, 0x7B, 0xE0, 0x50, 0x78, 0xA9, 0x15, 0x3D, 0x46, 0x49, 0x88,
52        0x60, 0x1A, 0x0D, 0x06, 0x59, 0x90, 0x2A, 0xA9, 0xC8, 0x51, 0x4E, 0x1F, 0x75, 0x02, 0xFE, 0x37, 0x83, 0x7A,
53        0xFF, 0x11, 0x54, 0x63, 0xE4, 0x0F, 0x40, 0xE0, 0xD4, 0x4A, 0x16, 0xC4,
54    ]),
55    PublicKey::new([
56        0x95, 0xD6, 0xA5, 0xAF, 0xDD, 0xE5, 0x3E, 0x9C, 0xF2, 0x18, 0xB2, 0x60, 0x33, 0xB3, 0x61, 0xEC, 0x5F, 0x82,
57        0x2D, 0x3C, 0x06, 0x41, 0x0E, 0xB1, 0x34, 0xDA, 0x57, 0xBC, 0x53, 0x11, 0x58, 0x93, 0x5B, 0x45, 0xD3, 0xAD,
58        0x2D, 0xE6, 0xAD, 0x50, 0x3B, 0xD7, 0xF4, 0x57, 0xEC, 0x4A, 0x51, 0x2F,
59    ]),
60    PublicKey::new([
61        0x95, 0xD6, 0xAB, 0x96, 0x2C, 0x7D, 0xB2, 0x01, 0xED, 0x17, 0x8E, 0x97, 0x6C, 0xCB, 0x0A, 0xD7, 0x2C, 0x88,
62        0x72, 0x84, 0xE8, 0xD0, 0xA4, 0x47, 0x92, 0xF3, 0x4F, 0xD4, 0x2E, 0x8D, 0xE3, 0xCF, 0x93, 0x75, 0x4D, 0x83,
63        0x4D, 0x18, 0x0A, 0x30, 0x4E, 0x09, 0xAB, 0x6C, 0x04, 0x37, 0x45, 0xE1,
64    ]),
65    PublicKey::new([
66        0x95, 0xD6, 0xB5, 0x21, 0x25, 0xED, 0xD6, 0x18, 0x82, 0xB4, 0x44, 0xD3, 0x2F, 0xD4, 0x7E, 0x96, 0x0F, 0x61,
67        0x63, 0x05, 0x07, 0x4E, 0xC3, 0x40, 0x19, 0x11, 0x0E, 0x56, 0xD2, 0xC7, 0x70, 0x7A, 0x59, 0x2A, 0x20, 0x50,
68        0xDE, 0xC9, 0xD7, 0xBC, 0xDF, 0xA5, 0xBB, 0x3C, 0x13, 0x16, 0x18, 0xA3,
69    ]),
70    PublicKey::new([
71        0x95, 0xD6, 0xBC, 0x60, 0xF1, 0x03, 0xC5, 0x5A, 0x81, 0xBB, 0x6B, 0x2A, 0x40, 0xAF, 0xD1, 0x03, 0xA5, 0xDB,
72        0x49, 0xDB, 0x68, 0xC4, 0xAD, 0xB5, 0x1F, 0x69, 0xCC, 0x1C, 0xA2, 0x15, 0x93, 0x9E, 0x3F, 0xC4, 0x37, 0xC2,
73        0xEE, 0x31, 0xF3, 0x51, 0xBD, 0x20, 0xDB, 0xD0, 0x5D, 0xA4, 0xB7, 0x26,
74    ]),
75    PublicKey::new([
76        0x95, 0xD6, 0xCA, 0x83, 0x2C, 0xAC, 0x1C, 0x82, 0xAC, 0x4B, 0xA8, 0xA1, 0x4B, 0x60, 0xAD, 0xB9, 0xFB, 0x15,
77        0x29, 0xBD, 0xE5, 0x00, 0xFD, 0xE0, 0xE5, 0xDE, 0x14, 0x88, 0xE1, 0x66, 0x86, 0x52, 0x96, 0xDF, 0x9B, 0xEB,
78        0x84, 0x57, 0x29, 0x11, 0x4E, 0x4B, 0xE2, 0x78, 0x19, 0xAA, 0x48, 0xE2,
79    ]),
80    PublicKey::new([
81        0x95, 0xD6, 0xD1, 0x72, 0xEC, 0x97, 0xA6, 0x70, 0x33, 0x83, 0x29, 0x6D, 0x44, 0x4E, 0x7E, 0x7F, 0xAB, 0xB0,
82        0x59, 0xB6, 0xA8, 0xEB, 0xA1, 0xB0, 0x52, 0xA7, 0x13, 0xE4, 0x75, 0x70, 0x6E, 0xF9, 0x83, 0x8A, 0xF2, 0xE3,
83        0x61, 0x59, 0x02, 0xE6, 0xC9, 0x55, 0xE3, 0xD9, 0x23, 0xF0, 0x13, 0xAE,
84    ]),
85    PublicKey::new([
86        0x95, 0xD6, 0xDC, 0xA4, 0xE7, 0xE9, 0xBD, 0xEA, 0xA8, 0xAD, 0x0D, 0xCD, 0xCE, 0x86, 0x67, 0xB8, 0x19, 0xDC,
87        0x2E, 0x69, 0x37, 0x4F, 0x3C, 0x7D, 0xC4, 0xF2, 0x96, 0xF4, 0x55, 0xE7, 0x50, 0xF5, 0xB3, 0xB2, 0x95, 0x66,
88        0xCB, 0x61, 0xEF, 0xED, 0x70, 0x50, 0xA5, 0xDD, 0x80, 0x88, 0xD5, 0x5A,
89    ]),
90    PublicKey::new([
91        0x95, 0x78, 0xC6, 0xCC, 0x1A, 0x7E, 0xBB, 0xBB, 0x64, 0xEC, 0x65, 0xC5, 0x4B, 0x25, 0x43, 0x50, 0x74, 0x10,
92        0x0E, 0xD1, 0x5A, 0x5B, 0xD6, 0xA1, 0x74, 0xBE, 0x4B, 0x61, 0x4B, 0xA0, 0xD5, 0xEB, 0x5E, 0x2A, 0xE6, 0x82,
93        0xC7, 0x58, 0xA2, 0xB1, 0x04, 0x68, 0xE9, 0x83, 0x63, 0xCC, 0xDE, 0xB4,
94    ]),
95    PublicKey::new([
96        0x95, 0x77, 0x23, 0x8C, 0x01, 0xC9, 0x30, 0xFE, 0x41, 0x7C, 0x48, 0xFC, 0x1F, 0xF8, 0xB7, 0x01, 0x18, 0x71,
97        0x45, 0xD6, 0x30, 0x5C, 0x04, 0x42, 0xD9, 0xF3, 0xC3, 0xAC, 0x31, 0x15, 0x30, 0xEF, 0x6A, 0x51, 0xE9, 0x85,
98        0xFD, 0xAF, 0x6F, 0x80, 0xAB, 0x95, 0x72, 0x6E, 0x8E, 0xE2, 0xAD, 0x7F,
99    ]),
100    PublicKey::new([
101        0x95, 0x77, 0x28, 0xB6, 0xB0, 0xBD, 0xC2, 0x6D, 0xC9, 0x81, 0x41, 0x66, 0x4C, 0x77, 0xF3, 0xDD, 0x3F, 0x31,
102        0xEE, 0x85, 0x85, 0xDF, 0x38, 0x63, 0x4D, 0xFA, 0x8A, 0x52, 0xC3, 0xED, 0x9F, 0xAC, 0xE8, 0x32, 0xBA, 0x65,
103        0x16, 0x64, 0xA4, 0xA8, 0x47, 0xB9, 0x66, 0xA3, 0x61, 0xFB, 0x58, 0x35,
104    ]),
105    PublicKey::new([
106        0x95, 0x77, 0x30, 0x96, 0x49, 0x20, 0xA0, 0x0D, 0xE3, 0xA8, 0xFA, 0x02, 0xEA, 0x89, 0x65, 0x09, 0x3D, 0xE3,
107        0x0B, 0x8E, 0xD4, 0x23, 0x65, 0x5B, 0xCB, 0x98, 0x29, 0x25, 0xAB, 0x95, 0x79, 0x7B, 0xBB, 0x5A, 0x55, 0x4E,
108        0xCB, 0x50, 0xD1, 0xB6, 0xCE, 0x25, 0x77, 0x6C, 0xAF, 0x5D, 0x74, 0x8C,
109    ]),
110    PublicKey::new([
111        0x95, 0x77, 0x3C, 0x10, 0x56, 0x5C, 0x56, 0xD2, 0x27, 0x09, 0x85, 0x97, 0x97, 0x9B, 0x75, 0x1A, 0x3E, 0xD5,
112        0xF9, 0x9C, 0x28, 0xFA, 0xBC, 0x12, 0xF0, 0x76, 0xED, 0xC6, 0x7A, 0x7B, 0x19, 0xD6, 0x67, 0x59, 0x67, 0x99,
113        0xC7, 0x67, 0xDE, 0x05, 0x31, 0x12, 0x0A, 0x81, 0x97, 0xC3, 0xF1, 0x4E,
114    ]),
115    PublicKey::new([
116        0x95, 0x77, 0x4A, 0x57, 0x62, 0xD2, 0x60, 0x73, 0x0E, 0x16, 0x4E, 0x8E, 0x0B, 0x22, 0xD5, 0x83, 0x5D, 0xD7,
117        0x8D, 0xE8, 0xD7, 0xC6, 0x39, 0x4B, 0xA1, 0x47, 0x3D, 0x8D, 0xAF, 0x4A, 0x3C, 0x20, 0xB7, 0x3A, 0xB9, 0x07,
118        0x28, 0x00, 0x87, 0xE3, 0xE6, 0xB6, 0x2C, 0x7C, 0x35, 0xE9, 0x35, 0xCD,
119    ]),
120    PublicKey::new([
121        0x95, 0x77, 0x53, 0x14, 0x4F, 0x94, 0xF0, 0x6E, 0x3B, 0x47, 0x81, 0xD3, 0x37, 0xB7, 0xF7, 0xB2, 0xB7, 0x92,
122        0x6B, 0xF7, 0xB4, 0x9E, 0xC7, 0xDF, 0x22, 0x14, 0xF8, 0x59, 0xAC, 0x23, 0xF2, 0x79, 0xB3, 0xEC, 0x47, 0xA4,
123        0xD9, 0x3D, 0x45, 0x74, 0x12, 0xEE, 0x17, 0x59, 0xE6, 0xF9, 0x0A, 0x5C,
124    ]),
125    PublicKey::new([
126        0x95, 0x77, 0x5B, 0x46, 0x7A, 0xCB, 0x18, 0x7D, 0x32, 0x81, 0x96, 0x1A, 0x67, 0x8B, 0x34, 0x7A, 0xCE, 0xD9,
127        0x97, 0x7D, 0xB4, 0x9A, 0xB8, 0xA1, 0xAB, 0x12, 0xE7, 0x6A, 0xE2, 0x72, 0xA7, 0x32, 0xFB, 0x0D, 0xB8, 0xDE,
128        0x2D, 0x9D, 0x31, 0x2A, 0xF4, 0x48, 0x7B, 0xAF, 0x9C, 0xCB, 0xAE, 0x91,
129    ]),
130    PublicKey::new([
131        0x95, 0x77, 0x5F, 0x9D, 0xAD, 0x81, 0x45, 0x9A, 0x72, 0x95, 0xF1, 0x58, 0x08, 0xE5, 0x13, 0x09, 0x59, 0x4C,
132        0xF3, 0x16, 0xDC, 0xF9, 0x0B, 0x4D, 0x92, 0x0B, 0xBF, 0x39, 0x25, 0xF8, 0x74, 0x47, 0x27, 0xBA, 0xC5, 0x5C,
133        0xDB, 0xF9, 0x96, 0x24, 0xDD, 0x32, 0x61, 0xE1, 0xEE, 0xF6, 0x03, 0xA9,
134    ]),
135    PublicKey::new([
136        0x95, 0x77, 0x6B, 0x3E, 0x7F, 0x1B, 0x4A, 0x0D, 0x46, 0x4E, 0x8D, 0x09, 0x06, 0x6E, 0x9D, 0xAA, 0xF6, 0x8C,
137        0x8C, 0x1B, 0xAF, 0xD0, 0x8E, 0xF2, 0xB7, 0xD6, 0xF4, 0xBC, 0xA0, 0x4D, 0xB1, 0x3D, 0x68, 0x0A, 0x4B, 0xAE,
138        0x95, 0xC9, 0xA0, 0x94, 0xD2, 0x6E, 0x44, 0x0A, 0x8F, 0xDB, 0x69, 0x6B,
139    ]),
140    PublicKey::new([
141        0x95, 0x7A, 0xDC, 0xA8, 0x5B, 0x47, 0x06, 0x63, 0x7D, 0x2F, 0x80, 0x04, 0x54, 0x97, 0x82, 0xC0, 0x70, 0x4B,
142        0x7F, 0x7D, 0x87, 0x8D, 0x0D, 0x61, 0xC7, 0xBA, 0xD5, 0x79, 0x67, 0x57, 0x81, 0xD0, 0x57, 0x93, 0xA8, 0xD6,
143        0x27, 0x17, 0x01, 0xC7, 0xAE, 0xDD, 0x7C, 0xB3, 0x71, 0xA7, 0x6A, 0x4C,
144    ]),
145    PublicKey::new([
146        0x95, 0x79, 0x36, 0x85, 0x52, 0x08, 0x74, 0x33, 0xC9, 0xDF, 0xF4, 0xEA, 0x44, 0x52, 0x2D, 0xC3, 0x80, 0xD1,
147        0x63, 0xF0, 0x7F, 0x17, 0xE3, 0x1A, 0x74, 0x93, 0x39, 0xF1, 0x78, 0xB2, 0xB7, 0x54, 0xD9, 0xF0, 0x55, 0x41,
148        0xD0, 0x60, 0x4F, 0xD3, 0xC7, 0x56, 0xE9, 0x1D, 0xB1, 0xCA, 0x44, 0xD0,
149    ]),
150    PublicKey::new([
151        0x95, 0x79, 0x3F, 0xED, 0xDA, 0x1A, 0x40, 0xCC, 0xC5, 0x16, 0xA7, 0xED, 0x3F, 0x05, 0x11, 0x8A, 0x9F, 0x94,
152        0x3B, 0x1E, 0x0F, 0xCC, 0xFE, 0x7D, 0x2B, 0x51, 0xA2, 0x70, 0x37, 0xE6, 0x8A, 0x57, 0xE0, 0xC2, 0x3E, 0xC6,
153        0x31, 0x6F, 0xBB, 0xA0, 0x9E, 0xB4, 0x0A, 0x68, 0xEC, 0xBF, 0x1C, 0x39,
154    ]),
155    PublicKey::new([
156        0x95, 0x79, 0x45, 0xE9, 0x73, 0x74, 0xE2, 0x4B, 0xB5, 0x2E, 0xD3, 0xF6, 0xB7, 0x16, 0x94, 0x5B, 0x85, 0x91,
157        0x49, 0x6B, 0xEC, 0x39, 0x2F, 0x0F, 0xE7, 0x27, 0xED, 0xE3, 0x88, 0x0A, 0xB1, 0x19, 0xB1, 0x11, 0x92, 0x3D,
158        0xC4, 0x09, 0x69, 0x2C, 0x9F, 0x0F, 0x4D, 0xED, 0xD6, 0xA0, 0x30, 0x33,
159    ]),
160    PublicKey::new([
161        0x95, 0x79, 0x51, 0xA5, 0x24, 0xC0, 0x87, 0x9F, 0x9B, 0xAA, 0x49, 0xC5, 0xCA, 0x48, 0x78, 0x06, 0xAD, 0x3E,
162        0x49, 0xC4, 0xFB, 0x7B, 0x9B, 0x41, 0xDB, 0xC4, 0x51, 0x4A, 0x0B, 0x1B, 0x12, 0x3F, 0x32, 0x94, 0x9C, 0xE5,
163        0x77, 0x39, 0xD0, 0x1B, 0xEC, 0x94, 0xC2, 0x7F, 0xBB, 0xC6, 0x5B, 0x1C,
164    ]),
165    PublicKey::new([
166        0x95, 0x79, 0x5B, 0x63, 0x5D, 0xA0, 0x66, 0xB1, 0x03, 0x4E, 0x12, 0xA6, 0xF7, 0x33, 0xFF, 0xEC, 0x5C, 0x23,
167        0x61, 0x6F, 0x47, 0x81, 0xF9, 0xF1, 0x8D, 0x43, 0x43, 0x72, 0x08, 0x8B, 0xDC, 0x1B, 0x24, 0x1E, 0x73, 0xA8,
168        0xD7, 0x78, 0x96, 0xA1, 0xE0, 0x2A, 0x4B, 0x84, 0xF1, 0xAF, 0x6A, 0x34,
169    ]),
170    PublicKey::new([
171        0x95, 0x79, 0x60, 0xC1, 0xE1, 0x8D, 0x2A, 0x24, 0xDD, 0xAD, 0x36, 0x2D, 0xFF, 0x7A, 0x13, 0x13, 0x86, 0x24,
172        0x32, 0x54, 0xEF, 0x0C, 0x80, 0x89, 0xFE, 0x3A, 0x00, 0x6C, 0xF7, 0x82, 0x0B, 0xFE, 0x02, 0xE3, 0xA1, 0x94,
173        0x7E, 0x25, 0xEE, 0xAF, 0xB9, 0xAD, 0x3E, 0xFD, 0x1A, 0xD6, 0xC4, 0xD2,
174    ]),
175    PublicKey::new([
176        0x95, 0x79, 0x6F, 0xAB, 0x71, 0xC1, 0x05, 0x8F, 0x49, 0x76, 0x90, 0xA1, 0x68, 0x3E, 0x4D, 0x7F, 0x04, 0x79,
177        0x73, 0x40, 0x1D, 0xB7, 0xF4, 0xDD, 0xE4, 0x91, 0x42, 0x11, 0x37, 0xFE, 0x04, 0xC6, 0xE2, 0xAF, 0xA1, 0xF5,
178        0xFF, 0x35, 0x8D, 0xF5, 0x62, 0x6B, 0xE5, 0xB5, 0x3E, 0x8F, 0x99, 0x3D,
179    ]),
180    PublicKey::new([
181        0x95, 0x79, 0x70, 0x5F, 0xD4, 0x00, 0xB0, 0xF2, 0xB2, 0x6B, 0x77, 0x0F, 0x36, 0x07, 0xA6, 0x5B, 0x5C, 0x30,
182        0xD1, 0xF2, 0xB1, 0x3C, 0xC8, 0xE9, 0x98, 0xB6, 0xD2, 0xC2, 0x48, 0x54, 0x40, 0x21, 0x5F, 0x2E, 0x3A, 0x9A,
183        0xD4, 0x98, 0x2F, 0x4A, 0xE3, 0x6A, 0x39, 0x0D, 0xC7, 0x69, 0xD3, 0xBA,
184    ]),
185    PublicKey::new([
186        0x95, 0x79, 0x7E, 0xDA, 0xD1, 0xB9, 0xA4, 0x00, 0x15, 0x95, 0xFE, 0x88, 0x6B, 0x88, 0x64, 0x97, 0xF3, 0xF5,
187        0x83, 0xFD, 0xEA, 0x41, 0x66, 0xA0, 0xC4, 0x09, 0x5B, 0xE5, 0xAB, 0x84, 0x5F, 0x0D, 0x12, 0x2B, 0xD7, 0x28,
188        0xA3, 0x17, 0x5A, 0xBE, 0x0B, 0x18, 0x5C, 0xB7, 0xCD, 0x34, 0xEA, 0x25,
189    ]),
190    PublicKey::new([
191        0x95, 0x7C, 0xE9, 0x53, 0xCE, 0x70, 0x05, 0x4E, 0xF6, 0x1F, 0x67, 0xFA, 0xEF, 0x51, 0x81, 0x74, 0x0C, 0xCE,
192        0xC7, 0x3F, 0xC5, 0x11, 0x41, 0x22, 0x74, 0x8C, 0x4E, 0x63, 0x54, 0x75, 0x6F, 0xD9, 0x94, 0xFE, 0x13, 0xBD,
193        0x88, 0xC0, 0xEB, 0x5D, 0x59, 0x31, 0x7F, 0xC1, 0xE0, 0xFD, 0xF1, 0x92,
194    ]),
195    PublicKey::new([
196        0x95, 0x7B, 0x44, 0xA3, 0x5A, 0x9E, 0x65, 0x1B, 0x62, 0x64, 0xB3, 0xA1, 0xE2, 0x2A, 0x20, 0x2C, 0xDA, 0x1F,
197        0x0A, 0xA1, 0x5D, 0x99, 0x40, 0x58, 0x43, 0x7B, 0x19, 0xA3, 0x7C, 0xEF, 0x6E, 0xA5, 0x47, 0x1D, 0x1D, 0x9B,
198        0xD8, 0x62, 0x3E, 0x04, 0x5B, 0x6E, 0x9D, 0xD7, 0x28, 0xF1, 0x62, 0xAD,
199    ]),
200    PublicKey::new([
201        0x95, 0x7B, 0x4F, 0x13, 0x17, 0x20, 0x70, 0xAA, 0xB0, 0xE1, 0x1D, 0x8B, 0xF0, 0xC8, 0x35, 0x8F, 0xD9, 0x60,
202        0xB4, 0xBD, 0x7A, 0xC8, 0x81, 0x48, 0x15, 0x8C, 0xF4, 0x97, 0x72, 0x76, 0xF3, 0x01, 0xBC, 0x61, 0x1D, 0xF4,
203        0xDA, 0x41, 0x6D, 0x26, 0x9B, 0x79, 0x96, 0x09, 0xDA, 0xF2, 0x0C, 0xF6,
204    ]),
205    PublicKey::new([
206        0x95, 0x7B, 0x5C, 0x7B, 0x2D, 0x3B, 0x1B, 0x64, 0xB0, 0xE1, 0x3E, 0x56, 0x96, 0x7F, 0xD3, 0x71, 0xB9, 0xB5,
207        0xC3, 0xF8, 0x77, 0xE7, 0x11, 0xF4, 0x5C, 0xA3, 0xA5, 0x9A, 0x9D, 0x6D, 0xB3, 0x96, 0x11, 0x8B, 0xDF, 0x34,
208        0x09, 0x2D, 0x11, 0x3B, 0xF9, 0x64, 0x31, 0xA7, 0x66, 0xEA, 0x2C, 0xDE,
209    ]),
210    PublicKey::new([
211        0x95, 0x7B, 0x5F, 0x6C, 0x26, 0xF9, 0x29, 0x31, 0x89, 0xB2, 0xCB, 0x33, 0x57, 0xD9, 0x32, 0x88, 0x9D, 0xC0,
212        0x23, 0xE3, 0x36, 0xA5, 0x34, 0x0C, 0x48, 0xC4, 0xD6, 0x79, 0x69, 0x57, 0x26, 0x70, 0x9D, 0x9C, 0x64, 0x0B,
213        0xC3, 0x0B, 0x1D, 0x71, 0x46, 0xE4, 0xE8, 0x12, 0x1F, 0xA2, 0x36, 0xE5,
214    ]),
215    PublicKey::new([
216        0x95, 0x7B, 0x6C, 0x3B, 0x53, 0x8B, 0xF0, 0x85, 0x22, 0x07, 0x23, 0x27, 0xF1, 0x71, 0xE1, 0x3C, 0xBC, 0x47,
217        0xE3, 0x95, 0x5C, 0x73, 0x31, 0xDA, 0x43, 0x87, 0xEF, 0x71, 0x5D, 0x7E, 0x97, 0x76, 0x8A, 0x41, 0x7E, 0x76,
218        0x31, 0xF0, 0xC9, 0x67, 0x2A, 0xCD, 0xC2, 0x7C, 0x88, 0x2C, 0xBC, 0x11,
219    ]),
220    PublicKey::new([
221        0x95, 0x7B, 0x74, 0x5C, 0x1A, 0x4C, 0x57, 0x98, 0x94, 0x81, 0xA1, 0xB5, 0x90, 0x2A, 0xC9, 0x01, 0x75, 0xCC,
222        0xE7, 0x79, 0x55, 0xA9, 0x9F, 0x5B, 0x53, 0x00, 0x96, 0x93, 0xB7, 0x47, 0xE1, 0xC0, 0x04, 0x09, 0xDC, 0xEF,
223        0x8B, 0x6D, 0x32, 0xFF, 0xA5, 0x0B, 0x35, 0x41, 0x8F, 0xD0, 0xE9, 0x89,
224    ]),
225    PublicKey::new([
226        0x95, 0x7B, 0x7B, 0x07, 0x56, 0x2B, 0x10, 0x35, 0x73, 0xCE, 0x97, 0x74, 0x7D, 0xB2, 0xD7, 0x67, 0x3A, 0x04,
227        0x00, 0x84, 0xE2, 0xA6, 0x7B, 0x19, 0xB7, 0x71, 0x2B, 0xF1, 0xD5, 0xDB, 0xDC, 0xE1, 0x9B, 0xE6, 0xEB, 0xFB,
228        0xDB, 0x6E, 0xCC, 0x17, 0x36, 0x62, 0x55, 0x26, 0x1A, 0x27, 0x49, 0x60,
229    ]),
230    PublicKey::new([
231        0x95, 0x7B, 0x87, 0xF8, 0xE4, 0x11, 0x4D, 0x09, 0xDB, 0x5A, 0x31, 0x20, 0x56, 0x83, 0x1F, 0x6B, 0xA9, 0xA0,
232        0x82, 0xEC, 0x16, 0x4E, 0x04, 0x46, 0x6D, 0xC6, 0x1C, 0x7B, 0x5A, 0xDC, 0xBB, 0xFC, 0xCA, 0x2D, 0x89, 0x6B,
233        0x96, 0x70, 0xEB, 0xA2, 0x92, 0x6B, 0xA2, 0x29, 0xEB, 0xCA, 0x42, 0x3E,
234    ]),
235    PublicKey::new([
236        0x95, 0x7B, 0x92, 0x64, 0x58, 0xCB, 0x87, 0x1B, 0xA8, 0x82, 0x2D, 0x39, 0x8F, 0xC8, 0x25, 0xD8, 0x96, 0x4B,
237        0x25, 0xCA, 0xA7, 0x13, 0xFE, 0x19, 0x02, 0xEF, 0xB8, 0xDF, 0x19, 0x2D, 0xCD, 0xE3, 0xF6, 0xCE, 0x74, 0x78,
238        0x67, 0x27, 0x3D, 0xF8, 0x4A, 0xFB, 0x60, 0xBB, 0x95, 0x03, 0xB6, 0x16,
239    ]),
240    PublicKey::new([
241        0x95, 0x7F, 0x01, 0xD5, 0x03, 0x64, 0x70, 0x14, 0xC3, 0xB7, 0x9B, 0x0A, 0x3E, 0xCB, 0x49, 0x18, 0xF3, 0x84,
242        0x32, 0x87, 0xE0, 0xBB, 0xFE, 0xDC, 0x3A, 0x41, 0x91, 0x84, 0x04, 0xC8, 0x35, 0xEA, 0xC9, 0x47, 0xB4, 0x76,
243        0x2F, 0xBA, 0x05, 0x21, 0x80, 0xC3, 0xC2, 0x00, 0x6C, 0x1B, 0x15, 0x03,
244    ]),
245    PublicKey::new([
246        0x95, 0x7D, 0x5A, 0x0F, 0xBB, 0x34, 0x83, 0x05, 0x81, 0xD4, 0xC7, 0xCA, 0x1C, 0x83, 0xAF, 0xCB, 0xB2, 0xB0,
247        0x35, 0x21, 0x80, 0x18, 0x65, 0x72, 0x06, 0x87, 0x51, 0x72, 0xAC, 0xF3, 0x89, 0xC5, 0xA2, 0xC6, 0x84, 0xAF,
248        0x4D, 0x46, 0x96, 0xAE, 0x23, 0x0A, 0xCA, 0x43, 0x6C, 0x59, 0x0D, 0x45,
249    ]),
250    PublicKey::new([
251        0x95, 0x7D, 0x68, 0x1A, 0x52, 0xD2, 0xF6, 0x9C, 0x2E, 0xFD, 0x07, 0x1E, 0x6A, 0xCE, 0xAC, 0x36, 0x6E, 0x72,
252        0x3A, 0xFA, 0xC5, 0x22, 0x36, 0xC3, 0xA8, 0xA8, 0x6D, 0x42, 0x22, 0x00, 0x18, 0x04, 0x40, 0xE7, 0xEA, 0x7E,
253        0xDE, 0x71, 0xB9, 0x5D, 0x01, 0xD2, 0x83, 0x0C, 0xB7, 0x0F, 0xC0, 0x21,
254    ]),
255    PublicKey::new([
256        0x95, 0x7D, 0x6D, 0x07, 0x33, 0x88, 0x37, 0x07, 0x73, 0xF4, 0xFD, 0x7D, 0xAC, 0x5A, 0xA6, 0xD6, 0xC9, 0x8E,
257        0x7F, 0x69, 0x40, 0x5F, 0x8F, 0x14, 0x52, 0x76, 0x7F, 0xA2, 0xC8, 0x17, 0x9B, 0x0B, 0x23, 0x6B, 0xB2, 0x63,
258        0xCA, 0x76, 0x23, 0xEF, 0xC7, 0x70, 0x9B, 0xCF, 0xEE, 0x27, 0xA2, 0x1E,
259    ]),
260    PublicKey::new([
261        0x95, 0x7D, 0x79, 0x1A, 0x6D, 0xB9, 0xBD, 0x07, 0xB9, 0x9E, 0x3E, 0x6B, 0xD5, 0xF0, 0x9B, 0x2F, 0x8E, 0xE5,
262        0x27, 0xDB, 0x92, 0xFE, 0x83, 0x49, 0x15, 0xBE, 0x1D, 0x5E, 0xA4, 0x57, 0xDA, 0xE5, 0x5E, 0xC9, 0x64, 0x41,
263        0x6A, 0x17, 0x42, 0x83, 0x5B, 0x5A, 0x78, 0x56, 0xE2, 0xE1, 0x6D, 0x5D,
264    ]),
265    PublicKey::new([
266        0x95, 0x7D, 0x80, 0x31, 0x73, 0x85, 0x76, 0x17, 0x18, 0x10, 0xA0, 0xAC, 0x00, 0x28, 0x79, 0x42, 0xE5, 0x5B,
267        0x18, 0x2B, 0xD2, 0x75, 0x9F, 0xD0, 0x86, 0x48, 0x95, 0xA1, 0x21, 0xB3, 0x9A, 0xE0, 0x8D, 0xB6, 0x85, 0x6B,
268        0xC1, 0xF4, 0x2C, 0x88, 0x73, 0x6D, 0xE1, 0xEE, 0xFF, 0x9D, 0xD0, 0x28,
269    ]),
270    PublicKey::new([
271        0x95, 0x7D, 0x8D, 0x30, 0x56, 0xFB, 0x29, 0x0F, 0x45, 0x2F, 0xC3, 0xF6, 0x2B, 0x3A, 0xAF, 0xFD, 0xAB, 0x48,
272        0x35, 0xC5, 0xDE, 0x3A, 0x7B, 0xDD, 0x01, 0x30, 0x2F, 0x9F, 0xEB, 0xD2, 0x36, 0xDC, 0xFD, 0x1E, 0x6B, 0xA6,
273        0xF1, 0xF4, 0xEC, 0xF8, 0x82, 0x32, 0xFA, 0x14, 0x17, 0x8A, 0x81, 0xCD,
274    ]),
275    PublicKey::new([
276        0x95, 0x7D, 0x90, 0x5B, 0xDB, 0x26, 0xCB, 0x87, 0xD9, 0x80, 0x39, 0x03, 0xBF, 0x49, 0x39, 0x30, 0xCA, 0x21,
277        0x42, 0xCE, 0xC6, 0xEB, 0xED, 0x9D, 0x22, 0x5D, 0xD4, 0xF4, 0x6D, 0x90, 0x63, 0x18, 0xB4, 0xE8, 0x45, 0xDD,
278        0xA7, 0xA9, 0x2E, 0x62, 0xF2, 0xD4, 0xB1, 0x59, 0xD4, 0xCD, 0x9B, 0x66,
279    ]),
280    PublicKey::new([
281        0x95, 0x7D, 0x9D, 0x0E, 0x22, 0x5F, 0x2B, 0x3B, 0xFE, 0xDC, 0x80, 0xDD, 0xBF, 0x09, 0x73, 0x7F, 0xED, 0x21,
282        0xDC, 0x4D, 0x94, 0xD3, 0x4C, 0x40, 0xCE, 0xC1, 0x0E, 0x2F, 0x54, 0x02, 0xA5, 0x42, 0xBA, 0xB7, 0x98, 0xEC,
283        0x89, 0x79, 0xD8, 0xEE, 0x97, 0x0D, 0x9F, 0x51, 0xB5, 0x0D, 0xFE, 0xAA,
284    ]),
285    PublicKey::new([
286        0x95, 0x7D, 0xA7, 0xF8, 0xC6, 0xB6, 0xAE, 0x33, 0x22, 0x25, 0x93, 0x1D, 0x85, 0x6D, 0x59, 0xB4, 0xF7, 0x6B,
287        0xF5, 0x8E, 0x51, 0x33, 0x7A, 0x10, 0x19, 0xCC, 0xB4, 0x86, 0x91, 0x30, 0x90, 0x96, 0x30, 0xC1, 0x7A, 0xD1,
288        0x04, 0x19, 0x5B, 0x3C, 0xED, 0x37, 0xC6, 0xF2, 0xA4, 0x82, 0xB0, 0x32,
289    ]),
290    PublicKey::new([
291        0x95, 0x81, 0x0F, 0x01, 0xD9, 0x42, 0x31, 0xA0, 0xD1, 0xCA, 0x47, 0xB6, 0x54, 0x73, 0x7A, 0x5C, 0x12, 0x9E,
292        0x05, 0x70, 0xA4, 0x3C, 0x10, 0x2C, 0xFE, 0x6F, 0x4F, 0x14, 0x08, 0x01, 0x6E, 0x1A, 0x67, 0xEB, 0xD4, 0x44,
293        0x16, 0x86, 0x06, 0x5B, 0x4F, 0x5A, 0x5F, 0xF8, 0x1D, 0xC5, 0x0D, 0x15,
294    ]),
295    PublicKey::new([
296        0x95, 0x7F, 0x71, 0x5D, 0x5A, 0x80, 0x47, 0x4F, 0x48, 0xC9, 0x3C, 0x7C, 0x96, 0x33, 0x25, 0x18, 0xFD, 0x66,
297        0x33, 0x3B, 0x88, 0x11, 0xD9, 0x62, 0x60, 0xDC, 0xFF, 0xA8, 0xD3, 0xEA, 0xD9, 0x96, 0xDC, 0x07, 0xAA, 0x37,
298        0x83, 0xD0, 0xD6, 0x9E, 0x6A, 0x1E, 0x2F, 0x76, 0xAB, 0x56, 0x4E, 0x5D,
299    ]),
300    PublicKey::new([
301        0x95, 0x7F, 0x78, 0x77, 0xD6, 0x6F, 0x92, 0x7F, 0x27, 0x5E, 0xD9, 0x0D, 0x10, 0x92, 0xEC, 0xE2, 0xF4, 0x51,
302        0xE0, 0xFE, 0xA7, 0x82, 0x56, 0x30, 0xEF, 0x6A, 0x70, 0x1C, 0x77, 0xCF, 0x00, 0xD6, 0x4B, 0xC0, 0x52, 0x98,
303        0x76, 0xCF, 0x2F, 0x24, 0xFC, 0xE8, 0x19, 0xA5, 0xC1, 0x9C, 0xE3, 0xC4,
304    ]),
305    PublicKey::new([
306        0x95, 0x7F, 0x82, 0xD6, 0x2B, 0xA1, 0xC1, 0xB1, 0x44, 0xFB, 0x91, 0x3A, 0x08, 0x22, 0xB8, 0xA5, 0x50, 0x6C,
307        0x8F, 0xBC, 0xDA, 0xD7, 0x2F, 0x08, 0xE0, 0x6C, 0x64, 0x2D, 0x62, 0xB8, 0xE9, 0x64, 0xE5, 0xD4, 0xA2, 0x97,
308        0xAC, 0x19, 0xF9, 0x3A, 0x4A, 0xAA, 0x0E, 0xFD, 0xE9, 0xAD, 0x1C, 0x10,
309    ]),
310    PublicKey::new([
311        0x95, 0x7F, 0x88, 0x8A, 0xD9, 0x02, 0x17, 0x03, 0x4D, 0x82, 0x4E, 0xF1, 0xB3, 0x15, 0x97, 0xB2, 0x2D, 0xA5,
312        0xC9, 0x16, 0x8D, 0x6A, 0x84, 0x03, 0x1B, 0xB8, 0x45, 0x3F, 0xAF, 0x68, 0xC4, 0x7C, 0x9B, 0x61, 0x39, 0x6B,
313        0x17, 0x9B, 0xD9, 0xA1, 0xB4, 0x24, 0xB3, 0x6C, 0x40, 0xD6, 0xCE, 0xD2,
314    ]),
315    PublicKey::new([
316        0x95, 0x7F, 0x90, 0x81, 0x23, 0x3F, 0x67, 0x0E, 0x75, 0x0D, 0xA6, 0xA5, 0x2E, 0x67, 0x77, 0x68, 0xBB, 0x7B,
317        0xEC, 0x29, 0x65, 0x95, 0x2F, 0x2A, 0xC7, 0x7B, 0xB6, 0x99, 0x90, 0xA6, 0xBF, 0xC5, 0x04, 0xF9, 0x9B, 0x53,
318        0xB7, 0x13, 0x02, 0x2B, 0xE2, 0x39, 0xE7, 0xCF, 0xB6, 0xEB, 0xBC, 0x99,
319    ]),
320    PublicKey::new([
321        0x95, 0x7F, 0x9B, 0xF2, 0xBF, 0xA1, 0x49, 0x97, 0x1C, 0x38, 0xA1, 0x9C, 0x30, 0x0D, 0xC1, 0x83, 0x48, 0xC2,
322        0x5F, 0x37, 0xBA, 0xF9, 0xED, 0x41, 0x42, 0xD1, 0x76, 0x19, 0xCB, 0xBF, 0x10, 0x7A, 0x6C, 0x9B, 0xF3, 0x3D,
323        0xB6, 0x50, 0xB9, 0x9E, 0x79, 0x34, 0x0C, 0xEC, 0xE5, 0xE3, 0x34, 0x62,
324    ]),
325    PublicKey::new([
326        0x95, 0x7F, 0xA8, 0xB2, 0x6F, 0x63, 0xB8, 0x50, 0x88, 0x78, 0x55, 0xF6, 0xF3, 0xD7, 0x16, 0xA5, 0xD4, 0x75,
327        0x78, 0xB0, 0x4A, 0x85, 0x00, 0xB2, 0x6D, 0x1D, 0x87, 0x11, 0xE6, 0x45, 0xB9, 0xBD, 0xF7, 0x2B, 0xD4, 0x5E,
328        0x2E, 0x6C, 0x51, 0x4B, 0xA0, 0xF8, 0x8B, 0x22, 0x52, 0x52, 0xB4, 0x05,
329    ]),
330    PublicKey::new([
331        0x95, 0x7F, 0xAA, 0xBA, 0xDE, 0x3F, 0x91, 0x59, 0xFA, 0x2B, 0x17, 0xCB, 0x94, 0x70, 0xE4, 0xBE, 0xAD, 0x8C,
332        0xE5, 0xE8, 0x8C, 0x3B, 0x63, 0x9C, 0x7E, 0x86, 0x17, 0xDA, 0x81, 0x40, 0xB8, 0x63, 0x4E, 0x1A, 0xA2, 0xE4,
333        0xDC, 0x32, 0x5D, 0x13, 0x14, 0x07, 0x44, 0xB8, 0x9F, 0xC6, 0xD3, 0xA0,
334    ]),
335    PublicKey::new([
336        0x95, 0x7F, 0xB2, 0xF3, 0x59, 0x75, 0xF4, 0x3A, 0xF8, 0xCD, 0xC9, 0xCB, 0x85, 0x3D, 0xEF, 0x7C, 0x8F, 0x7F,
337        0x62, 0x64, 0x19, 0xBB, 0x5A, 0xE5, 0xEC, 0xF3, 0x20, 0xA3, 0xB2, 0xC0, 0xC3, 0x5F, 0x78, 0x15, 0x0C, 0x84,
338        0x08, 0x50, 0x91, 0x85, 0x98, 0x74, 0x94, 0x19, 0x10, 0x09, 0x03, 0x68,
339    ]),
340    PublicKey::new([
341        0x95, 0x83, 0x23, 0xC2, 0x76, 0x16, 0xC6, 0x32, 0x14, 0x57, 0xA1, 0x14, 0x53, 0x81, 0xA3, 0x5C, 0x1F, 0xC7,
342        0xD1, 0x1C, 0xDB, 0xC7, 0xFA, 0xD0, 0x0B, 0x92, 0x91, 0x40, 0xCA, 0xA9, 0xBF, 0x9A, 0x3D, 0x02, 0xE6, 0xA4,
343        0x75, 0x61, 0xCB, 0xA3, 0xD9, 0x9E, 0x7E, 0x1F, 0x78, 0x89, 0x51, 0xB5,
344    ]),
345    PublicKey::new([
346        0x95, 0x81, 0x84, 0xAF, 0x90, 0xEC, 0x9E, 0x53, 0x6E, 0xD5, 0xA7, 0x60, 0xF0, 0x03, 0xCC, 0xE6, 0x61, 0x6F,
347        0x7E, 0xED, 0x9E, 0x3F, 0x9C, 0x29, 0xC3, 0x0E, 0x98, 0xCA, 0x29, 0xE6, 0x08, 0x93, 0xEF, 0x57, 0xCE, 0x2F,
348        0xF0, 0xC9, 0x95, 0xFB, 0x94, 0x56, 0x6A, 0xC7, 0x71, 0x2D, 0xCF, 0x79,
349    ]),
350    PublicKey::new([
351        0x95, 0x81, 0x8C, 0x8C, 0x69, 0xEA, 0x6C, 0x8B, 0x54, 0xE2, 0xDC, 0xA3, 0xC9, 0x96, 0xB5, 0x56, 0xF3, 0xED,
352        0xC3, 0x00, 0x69, 0x43, 0x6D, 0xF2, 0x49, 0x09, 0x6F, 0xBF, 0x13, 0xE2, 0x71, 0x23, 0xAD, 0xB7, 0x7D, 0x39,
353        0x65, 0x44, 0x51, 0x83, 0xAA, 0xDA, 0xD2, 0x7A, 0x29, 0x25, 0x3E, 0xE7,
354    ]),
355    PublicKey::new([
356        0x95, 0x81, 0x92, 0xF8, 0x69, 0x66, 0xE8, 0x73, 0xE2, 0xB4, 0x29, 0xEF, 0x7A, 0xA1, 0x33, 0x70, 0x75, 0x71,
357        0x96, 0xBF, 0xBB, 0x6A, 0xED, 0xFF, 0x1D, 0x11, 0x24, 0x26, 0x49, 0x47, 0x7A, 0x04, 0x07, 0xBE, 0x47, 0x32,
358        0x57, 0xB9, 0xDE, 0xBE, 0x80, 0x8B, 0xC0, 0xB5, 0x24, 0x63, 0xBA, 0x8F,
359    ]),
360    PublicKey::new([
361        0x95, 0x81, 0x99, 0x07, 0x4D, 0x30, 0x9A, 0xB2, 0x13, 0x66, 0x7C, 0xB6, 0x3C, 0x7C, 0x50, 0xD3, 0x38, 0x5E,
362        0x55, 0x36, 0xBA, 0xA1, 0x3F, 0xE1, 0xAA, 0xAC, 0xED, 0xAB, 0x0C, 0x93, 0x89, 0x34, 0xFC, 0x6E, 0x44, 0xBA,
363        0xD0, 0x5C, 0x17, 0x32, 0x8D, 0xE4, 0x5F, 0x87, 0x92, 0xAA, 0x63, 0x92,
364    ]),
365    PublicKey::new([
366        0x95, 0x81, 0xA4, 0xE2, 0x84, 0x71, 0xA4, 0xD2, 0x6C, 0x39, 0x2B, 0x2A, 0x03, 0x19, 0xE0, 0x9A, 0x41, 0x27,
367        0x08, 0xED, 0xC2, 0x93, 0x7B, 0x49, 0x51, 0x27, 0x4A, 0x3A, 0xF5, 0x54, 0x6E, 0x35, 0x97, 0x83, 0x6B, 0x71,
368        0xE2, 0xAF, 0x51, 0x24, 0xEC, 0xE5, 0x46, 0x23, 0xFA, 0x82, 0x38, 0x1D,
369    ]),
370    PublicKey::new([
371        0x95, 0x81, 0xAB, 0x66, 0x9D, 0xDE, 0x3B, 0xDE, 0xDE, 0x43, 0xCE, 0x68, 0x14, 0xD1, 0xEE, 0x3B, 0x54, 0x9A,
372        0x48, 0x6B, 0x01, 0xD5, 0x96, 0xD8, 0xC2, 0x09, 0xF7, 0x8F, 0x87, 0xBE, 0x0A, 0x3F, 0x6A, 0x66, 0x8E, 0x62,
373        0xE1, 0x5A, 0x8F, 0x31, 0xCE, 0xD9, 0xBF, 0x86, 0xA3, 0x61, 0x37, 0x5D,
374    ]),
375];
376
377pub fn call_set_emission_address(env: &mut ApplyEnv, args: Vec<Vec<u8>>) -> Result<(), &'static str> {
378    if args.len() != 1 {
379        return Err("invalid_args");
380    }
381    let address = args[0].as_slice();
382    if address.len() != 48 {
383        return Err("invalid_address_pk");
384    }
385    kv_put(env, &bcat(&[b"bic:epoch:emission_address:", env.caller_env.account_caller.as_slice()]), address)?;
386    Ok(())
387}
388
389pub fn call_submit_sol(env: &mut ApplyEnv, args: Vec<Vec<u8>>) -> Result<(), &'static str> {
390    if args.len() != 1 {
391        return Err("invalid_args");
392    }
393    let sol = args[0].as_slice();
394    if sol.len() != consensus::bic::sol::SOL_SIZE {
395        return Err("invalid_sol_seed_size");
396    }
397    let sol: [u8; consensus::bic::sol::SOL_SIZE] = sol.try_into().map_err(|_| "invalid_sol_size")?;
398
399    let hash = blake3::hash(&sol);
400    let mut flips = 0;
401    for seg in consensus::bic::sol_bloom::segs_from_digest(&hash) {
402        let key = format!("bic:epoch:solbloom:{}", seg.page).into_bytes();
403        if kv_set_bit(env, &key, seg.bit_offset)? {
404            flips += 1
405        }
406    }
407    if flips == 0 {
408        return Err("sol_exists");
409    }
410
411    let usol = consensus::bic::sol::unpack(&sol)?;
412    if env.caller_env.entry_epoch != usol.epoch {
413        return Err("invalid_epoch");
414    }
415
416    let segment_vr_hash = kv_get(env, b"bic:epoch:segment_vr_hash")?.ok_or("missing_segment_vr_hash")?;
417    let diff_bits = kv_get(env, b"bic:epoch:diff_bits")?.ok_or("missing_diff_bits")?;
418    let diff_bits_int =
419        std::str::from_utf8(&diff_bits).ok().and_then(|s| s.parse::<u64>().ok()).ok_or("invalid_diff_bits")?;
420
421    let hash_bytes: Hash = hash.into();
422    if !consensus::bic::sol::verify(
423        &sol,
424        &hash_bytes[..],
425        &segment_vr_hash,
426        env.caller_env.entry_vr_b3.as_ref(),
427        diff_bits_int,
428    )
429    .unwrap_or(false)
430    {
431        return Err("invalid_sol");
432    }
433
434    if !kv_exists(env, &bcat(&[b"bic:epoch:pop:", usol.pk.as_ref()]))? {
435        match bls12_381::verify(&usol.pk, &usol.pop, usol.pk.as_ref(), amadeus_utils::constants::DST_POP) {
436            Ok(()) => kv_put(env, &bcat(&[b"bic:epoch:pop:", usol.pk.as_ref()]), usol.pop.as_ref())?,
437            Err(_) => return Err("invalid_pop"),
438        }
439    }
440    kv_increment(env, &bcat(&[b"bic:epoch:solutions_count:", usol.pk.as_ref()]), 1)?;
441    Ok(())
442}
443
444pub fn kv_get_epoch_trainers(env: &ApplyEnv, key: &[u8]) -> Result<Vec<Vec<u8>>, &'static str> {
445    use amadeus_utils::vecpak::{decode, Term};
446    match kv_get(env, key)? {
447        None => Ok(Vec::new()),
448        Some(trainer_list) => {
449            let term = decode(trainer_list.as_slice()).map_err(|_| "invalid_vecpak")?;
450            match term {
451                Term::List(term_list) => {
452                    let mut out = Vec::with_capacity(term_list.len());
453                    for el in term_list {
454                        if let Term::Binary(b) = el {
455                            out.push(b);
456                        } else {
457                            return Err("invalid_trainer_list_term");
458                        }
459                    }
460                    Ok(out)
461                }
462                _ => Err("invalid_trainer_list_term"),
463            }
464        }
465    }
466}
467
468pub fn kv_get_height_trainers(env: &ApplyEnv, prefix: &[u8], key: &[u8]) -> Vec<Vec<u8>> {
469    use amadeus_utils::vecpak::{decode, Term};
470    match kv_get_prev_or_exact(env, prefix, key) {
471        None => Vec::new(),
472        Some((_key_suffix, trainer_list)) => {
473            let term = match decode(trainer_list.as_slice()) {
474                Ok(t) => t,
475                Err(_) => return Vec::new(),
476            };
477            match term {
478                Term::List(term_list) => {
479                    let mut out = Vec::with_capacity(term_list.len());
480                    for el in term_list {
481                        if let Term::Binary(b) = el {
482                            out.push(b);
483                        }
484                    }
485                    out
486                }
487                _ => Vec::new(),
488            }
489        }
490    }
491}
492
493pub fn call_slash_trainer(env: &mut ApplyEnv, args: Vec<Vec<u8>>) -> Result<(), &'static str> {
494    if args.len() != 5 {
495        return Err("invalid_args");
496    }
497    let epoch = args[0].as_slice();
498    let epoch = std::str::from_utf8(&epoch).ok().and_then(|s| s.parse::<u64>().ok()).ok_or("invalid_epoch")?;
499    let malicious_pk = args[1].as_slice();
500    let signature = args[2].as_slice();
501    let mask_size = args[3].as_slice();
502    let mask_size =
503        std::str::from_utf8(&mask_size).ok().and_then(|s| s.parse::<u64>().ok()).ok_or("invalid_mask_size")?;
504    let mask = args[4].to_vec();
505
506    if epoch != env.caller_env.entry_epoch {
507        return Err("invalid_epoch");
508    }
509
510    let mut trainers = kv_get_epoch_trainers(env, &bcat(&[b"bic:epoch:trainers:", epoch.to_string().as_bytes()]))?;
511    if !trainers.iter().any(|v| v.as_slice() == malicious_pk) {
512        return Err("invalid_trainer_pk");
513    }
514
515    let trainers_48: Vec<PublicKey> = trainers
516        .iter()
517        .filter_map(|pk| {
518            if pk.len() == 48 {
519                let mut arr = [0u8; 48];
520                arr.copy_from_slice(pk);
521                Some(PublicKey::new(arr))
522            } else {
523                None
524            }
525        })
526        .collect();
527
528    let mask_bitvec = BitVec::from_vec(mask);
529    let signers = unmask_trainers(&mask_bitvec, &trainers_48);
530    let consensus_pct = signers.len() as f64 / trainers.len() as f64;
531    if consensus_pct < 0.67 {
532        return Err("invalid_amount_of_signatures");
533    }
534
535    let apk = bls12_381::aggregate_public_keys(signers).map_err(|_| "invalid_aggregation")?;
536    let msg = bcat(&[b"slash_trainer", (epoch as u32).to_le_bytes().as_slice(), malicious_pk]);
537    let signature_valid = match bls12_381::verify(&apk, signature, msg.as_slice(), DST_MOTION) {
538        Ok(()) => true,
539        _ => false,
540    };
541    if !signature_valid {
542        return Err("invalid_signature");
543    }
544
545    let mut trainers_removed =
546        kv_get_epoch_trainers(env, &bcat(&[b"bic:epoch:trainers:removed:", epoch.to_string().as_bytes()]))?;
547    trainers_removed.push(malicious_pk.to_vec());
548    let term_trainers_removed = amadeus_utils::misc::list_of_binaries_to_vecpak(trainers_removed);
549    kv_put(
550        env,
551        &bcat(&[b"bic:epoch:trainers:removed:", epoch.to_string().as_bytes()]),
552        term_trainers_removed.as_slice(),
553    )?;
554
555    trainers.retain(|pk| pk.as_slice() != malicious_pk);
556    let term_trainers = amadeus_utils::misc::list_of_binaries_to_vecpak(trainers);
557    kv_put(env, &bcat(&[b"bic:epoch:trainers:", epoch.to_string().as_bytes()]), term_trainers.as_slice())?;
558
559    let height = format!("{:012}", env.caller_env.entry_height.saturating_add(1)).into_bytes();
560    kv_put(env, &bcat(&[b"bic:epoch:trainers:height:", &height]), term_trainers.as_slice())?;
561    Ok(())
562}
563
564pub fn next(env: &mut ApplyEnv) {
565    let epoch_cur = env.caller_env.entry_epoch;
566
567    if epoch_cur >= 295 && epoch_cur < 420 {
568        next_420(env);
569    } else {
570        next_pre_420(env);
571    }
572}
573
574fn next_420(env: &mut ApplyEnv) {
575    let epoch_cur = env.caller_env.entry_epoch;
576    let epoch_next = epoch_cur + 1;
577
578    let leaders = get_sorted_leaders_excluding_removed(env, epoch_cur);
579
580    let trainers_key = bcat(&[b"bic:epoch:trainers:", &epoch_cur.to_string().as_bytes()]);
581    let trainers: Vec<Vec<u8>> = kv_get_epoch_trainers(env, &trainers_key).unwrap_or_default();
582
583    let trainers_to_recv_emissions: Vec<_> = leaders
584        .iter()
585        .filter(|(pk, _)| {
586            trainers.iter().any(|t| t == pk) && !PEDDLEBIKE67.iter().any(|p| p.as_slice() == pk.as_slice())
587        })
588        .take(99)
589        .collect();
590
591    let epoch_total_emission = epoch_emission(epoch_cur);
592    let epoch_early_adopter_emission = epoch_total_emission / 7;
593    let epoch_communityfund_emission = epoch_total_emission - epoch_early_adopter_emission;
594
595    distribute_peddlebike67_community_fund(env, epoch_communityfund_emission);
596
597    let total_sols: i128 = trainers_to_recv_emissions.iter().map(|(_, count)| count).sum();
598    distribute_emissions_to_trainers(env, &trainers_to_recv_emissions, epoch_early_adopter_emission, total_sols);
599
600    let new_validators = build_and_shuffle_new_validators(env, &leaders);
601    store_new_trainers_for_next_epoch(env, epoch_next, new_validators);
602
603    update_difficulty_and_log_sols(env, epoch_cur, epoch_next, total_sols);
604    clear_epoch_data(env);
605}
606
607fn next_pre_420(env: &mut ApplyEnv) {
608    let epoch_cur = env.caller_env.entry_epoch;
609    let epoch_next = epoch_cur + 1;
610
611    let leaders = get_sorted_leaders_excluding_removed(env, epoch_cur);
612
613    let trainers_key = bcat(&[b"bic:epoch:trainers:", &epoch_cur.to_string().as_bytes()]);
614    let trainers: Vec<Vec<u8>> = kv_get_epoch_trainers(env, &trainers_key).unwrap_or_default();
615
616    let trainers_to_recv_emissions: Vec<_> =
617        leaders.iter().filter(|(pk, _)| trainers.iter().any(|t| t == pk)).take(99).collect();
618
619    let epoch_total_emission = epoch_emission(epoch_cur);
620    let total_sols: i128 = trainers_to_recv_emissions.iter().map(|(_, count)| count).sum();
621
622    distribute_emissions_to_trainers(env, &trainers_to_recv_emissions, epoch_total_emission, total_sols);
623
624    let new_validators = build_and_shuffle_new_validators(env, &leaders);
625    store_new_trainers_for_next_epoch(env, epoch_next, new_validators);
626    clear_epoch_data(env);
627}
628
629fn get_sorted_leaders_excluding_removed(env: &ApplyEnv, epoch: u64) -> Vec<(Vec<u8>, i128)> {
630    use crate::consensus::consensus_kv::kv_get_prefix;
631    use amadeus_utils::vecpak::{decode, VecpakExt};
632
633    let removed_key = bcat(&[b"bic:epoch:trainers:removed:", &epoch.to_string().as_bytes()]);
634    let removed_trainers: Vec<Vec<u8>> = kv_get(env, &removed_key)
635        .ok()
636        .flatten()
637        .and_then(|bytes| {
638            let term = decode(&bytes[..]).ok()?;
639            let list = term.get_list()?;
640            Some(list.iter().filter_map(|t| t.get_binary()).map(|b| b.to_vec()).collect())
641        })
642        .unwrap_or_default();
643
644    let leaders_raw = kv_get_prefix(env, b"bic:epoch:solutions_count:");
645    let mut leaders: Vec<(Vec<u8>, i128)> = leaders_raw
646        .into_iter()
647        .filter_map(|(pk_bytes, value_bytes)| {
648            if removed_trainers.contains(&pk_bytes) {
649                return None;
650            }
651            atoi::atoi::<i128>(&value_bytes).map(|count| (pk_bytes, count))
652        })
653        .collect();
654
655    leaders.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| b.0.cmp(&a.0)));
656    leaders
657}
658
659fn distribute_emissions_to_trainers(
660    env: &mut ApplyEnv,
661    trainers_to_recv: &[&(Vec<u8>, i128)],
662    total_emission: i128,
663    total_sols: i128,
664) {
665    if total_sols == 0 {
666        return;
667    }
668
669    for (trainer, trainer_sols) in trainers_to_recv {
670        let coins = (trainer_sols * total_emission) / total_sols;
671        let emission_addr_key = bcat(&[b"bic:epoch:emission_address:", trainer]);
672        let emission_address = kv_get(env, &emission_addr_key).ok().flatten();
673
674        let balance_key = if let Some(addr) = emission_address {
675            bcat(&[b"account:", &addr, b":balance:AMA"])
676        } else {
677            bcat(&[b"account:", trainer, b":balance:AMA"])
678        };
679
680        let _ = kv_increment(env, &balance_key, coins);
681    }
682}
683
684fn build_and_shuffle_new_validators(env: &ApplyEnv, leaders: &[(Vec<u8>, i128)]) -> Vec<Vec<u8>> {
685    use amadeus_utils::exsss::Exsss;
686
687    let leader_pks: Vec<Vec<u8>> = leaders.iter().map(|(pk, _)| pk.clone()).collect();
688    let filtered_leaders: Vec<Vec<u8>> =
689        leader_pks.into_iter().filter(|pk| !PEDDLEBIKE67.iter().any(|p| p.as_slice() == pk.as_slice())).collect();
690
691    let mut new_validators: Vec<Vec<u8>> = PEDDLEBIKE67.iter().map(|p| p.to_vec()).collect();
692    new_validators.extend(filtered_leaders);
693    new_validators.truncate(99);
694
695    let seed_bytes = &env.caller_env.seed;
696    let seed_array: Hash =
697        seed_bytes.get(..32).and_then(|s| s.try_into().ok()).map(Hash::new).unwrap_or(Hash::new([0u8; 32]));
698    let mut rng = Exsss::from_seed(&seed_array);
699    rng.shuffle(&mut new_validators);
700
701    new_validators
702}
703
704fn store_new_trainers_for_next_epoch(env: &mut ApplyEnv, epoch_next: u64, new_validators: Vec<Vec<u8>>) {
705    use crate::consensus::consensus_kv::kv_put;
706    let term = amadeus_utils::misc::list_of_binaries_to_vecpak(new_validators);
707
708    let trainers_next_key = bcat(&[b"bic:epoch:trainers:", &epoch_next.to_string().as_bytes()]);
709    let _ = kv_put(env, &trainers_next_key, &term);
710
711    let height = format!("{:012}", env.caller_env.entry_height + 1);
712    let trainers_height_key = bcat(&[b"bic:epoch:trainers:height:", height.as_bytes()]);
713    let _ = kv_put(env, &trainers_height_key, &term);
714}
715
716fn clear_epoch_data(env: &mut ApplyEnv) {
717    use crate::consensus::consensus_kv::kv_clear_prefix;
718    let _ = kv_clear_prefix(env, b"bic:epoch:solbloom:");
719    let _ = kv_clear_prefix(env, b"bic:epoch:solutions_count:");
720}
721
722fn distribute_peddlebike67_community_fund(env: &mut ApplyEnv, total_emission: i128) {
723    let n_count = PEDDLEBIKE67.len() as i128;
724    let q = total_emission / n_count;
725    let r = total_emission % n_count;
726
727    for (i, peddle_pk) in PEDDLEBIKE67.iter().enumerate() {
728        let coins = if (i as i128) < r { q + 1 } else { q };
729        let emission_addr_key = bcat(&[b"bic:epoch:emission_address:", peddle_pk.as_slice()]);
730        let emission_address = kv_get(env, &emission_addr_key).ok().flatten();
731
732        let balance_key = if let Some(addr) = emission_address {
733            bcat(&[b"account:", &addr, b":balance:AMA"])
734        } else {
735            bcat(&[b"account:", peddle_pk.as_slice(), b":balance:AMA"])
736        };
737
738        let _ = kv_increment(env, &balance_key, coins);
739    }
740}
741
742fn update_difficulty_and_log_sols(env: &mut ApplyEnv, epoch_cur: u64, epoch_next: u64, total_sols: i128) {
743    use crate::consensus::consensus_kv::kv_put;
744    let old_diff_bits =
745        kv_get(env, b"bic:epoch:diff_bits").ok().flatten().and_then(|bytes| atoi::atoi::<u32>(&bytes)).unwrap_or(24);
746
747    let next_diff_bits = crate::consensus::bic::sol_difficulty::next(old_diff_bits, total_sols as u64);
748    let _ = kv_put(env, b"bic:epoch:diff_bits", next_diff_bits.to_string().as_bytes());
749
750    let diff_key = format!("bic:epoch:diff_bits:{}", epoch_next);
751    let _ = kv_put(env, diff_key.as_bytes(), next_diff_bits.to_string().as_bytes());
752
753    let sols_key = format!("bic:epoch:total_sols:{}", epoch_cur);
754    let _ = kv_put(env, sols_key.as_bytes(), total_sols.to_string().as_bytes());
755}
756
757// Compatibility wrappers for amadeus-node
758#[derive(Debug, Clone, PartialEq, Eq)]
759pub enum EpochCall {
760    SubmitSol {
761        sol: Vec<u8>,
762    },
763    SetEmissionAddress {
764        address: PublicKey,
765    },
766    SlashTrainer {
767        epoch: u64,
768        malicious_pk: PublicKey,
769        signature: Vec<u8>,
770        mask: bitvec::vec::BitVec<u8, bitvec::order::Msb0>,
771        trainers: Option<Vec<PublicKey>>,
772    },
773}
774
775#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)]
776pub enum EpochError {
777    #[error("sol_exists")]
778    SolExists,
779    #[error("invalid_sol")]
780    InvalidSol,
781    #[error("invalid_epoch")]
782    InvalidEpoch,
783    #[error("invalid_pop")]
784    InvalidPop,
785    #[error("invalid_address_pk")]
786    InvalidAddressPk,
787}
788
789pub struct Epoch;
790
791impl Epoch {
792    pub fn call(&self, env: &mut ApplyEnv, op: EpochCall) -> Result<(), EpochError> {
793        match op {
794            EpochCall::SubmitSol { sol } => call_submit_sol(env, vec![sol]).map_err(|e| match e {
795                "sol_exists" => EpochError::SolExists,
796                "invalid_sol" | "invalid_sol_seed_size" | "invalid_sol_size" => EpochError::InvalidSol,
797                "invalid_epoch" => EpochError::InvalidEpoch,
798                "invalid_pop" => EpochError::InvalidPop,
799                _ => EpochError::InvalidSol,
800            }),
801            EpochCall::SetEmissionAddress { address } => call_set_emission_address(env, vec![address.to_vec()])
802                .map_err(|e| match e {
803                    "invalid_address_pk" => EpochError::InvalidAddressPk,
804                    _ => EpochError::InvalidAddressPk,
805                }),
806            EpochCall::SlashTrainer { epoch, malicious_pk, signature, mask, trainers } => {
807                let mut args = vec![epoch.to_le_bytes().to_vec(), malicious_pk.to_vec(), signature];
808                let mask_bytes = mask.into_vec();
809                args.push(mask_bytes);
810                if let Some(t) = trainers {
811                    args.push(
812                        amadeus_utils::misc::list_of_binaries_to_vecpak(t.into_iter().map(|pk| pk.to_vec()).collect()),
813                    );
814                }
815                call_slash_trainer(env, args).map_err(|_| EpochError::InvalidEpoch)
816            }
817        }
818    }
819
820    pub fn next(&self, env: &mut ApplyEnv) {
821        next(env);
822    }
823}
824
825pub fn trainers_for_height(db: &amadeus_utils::rocksdb::RocksDb, height: u64) -> Option<Vec<PublicKey>> {
826    use amadeus_utils::vecpak::{decode, VecpakExt};
827
828    let value: Option<Vec<u8>> = if (3_195_570..=3_195_575).contains(&height) {
829        match db.get(CF_CONTRACTSTATE, b"bic:epoch:trainers:height:000000319557") {
830            Ok(v) => v,
831            Err(_) => return None,
832        }
833    } else {
834        let key_suffix = format!("{:012}", height);
835        match db.get_prev_or_first(CF_CONTRACTSTATE, "bic:epoch:trainers:height:", &key_suffix) {
836            Ok(Some((_k, v))) => Some(v),
837            Ok(None) => None,
838            Err(_) => return None,
839        }
840    };
841
842    let bytes = value?;
843    let term = decode(&bytes[..]).ok()?;
844    let list = term.get_list()?;
845    let mut out = Vec::with_capacity(list.len());
846    for t in list {
847        let pk = t.get_binary()?;
848        if pk.len() != 48 {
849            return None;
850        }
851        let mut arr = [0u8; 48];
852        arr.copy_from_slice(pk);
853        out.push(PublicKey::new(arr));
854    }
855
856    Some(out)
857}
858
859pub fn unmask_trainers(mask: &BitVec<u8, Msb0>, trainers: &[PublicKey]) -> Vec<PublicKey> {
860    mask.iter().zip(trainers.iter()).filter_map(|(bit, pk)| if *bit { Some(*pk) } else { None }).collect()
861}