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#[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}