1use std::{
6 collections::HashMap,
7 fs::File,
8 io::{BufRead, BufReader, Read},
9 sync::Arc,
10};
11
12use rustc_hex::FromHex;
13use serde::{Deserialize, Serialize};
14use toml::Value;
15
16use crate::keylib::KeyPair;
17use cfx_executor::internal_contract::initialize_internal_contract_accounts;
18use cfx_internal_common::debug::ComputeEpochDebugRecord;
19use cfx_parameters::{
20 consensus::{GENESIS_GAS_LIMIT, ONE_CFX_IN_DRIP},
21 consensus_internal::{
22 GENESIS_TOKEN_COUNT_IN_CFX, TWO_YEAR_UNLOCK_TOKEN_COUNT_IN_CFX,
23 },
24 genesis::*,
25 staking::POS_VOTE_PRICE,
26};
27use cfx_statedb::StateDb;
28use cfx_storage::{StorageManager, StorageManagerTrait};
29use cfx_types::{
30 address_util::AddressUtil, cal_contract_address_with_space, Address,
31 AddressSpaceUtil, AddressWithSpace, CreateContractAddressType, Space, H256,
32 U256,
33};
34use diem_crypto::{
35 bls::BLSPrivateKey, ec_vrf::EcVrfPublicKey, PrivateKey, ValidCryptoMaterial,
36};
37use diem_types::validator_config::{ConsensusPublicKey, ConsensusVRFPublicKey};
38use primitives::{
39 Action, Block, BlockHeaderBuilder, BlockReceipts, SignedTransaction,
40};
41use secret_store::SecretStore;
42
43use crate::verification::{compute_receipts_root, compute_transaction_root};
44use cfx_executor::{
45 executive::{ExecutionOutcome, ExecutiveContext, TransactOptions},
46 machine::Machine,
47 state::State,
48};
49use cfx_vm_types::Env;
50use diem_types::account_address::AccountAddress;
51use primitives::transaction::native_transaction::NativeTransaction;
52
53pub fn default(dev_or_test_mode: bool) -> HashMap<AddressWithSpace, U256> {
54 if !dev_or_test_mode {
55 return HashMap::new();
56 }
57 let mut accounts: HashMap<AddressWithSpace, U256> = HashMap::new();
58 let balance = U256::from_dec_str("5000000000000000000000000000000000")
60 .expect("Not overflow"); accounts
62 .insert(DEV_GENESIS_KEY_PAIR.address().with_native_space(), balance);
63 accounts.insert(
64 DEV_GENESIS_KEY_PAIR_2.address().with_native_space(),
65 balance,
66 );
67 accounts
68 .insert(DEV_GENESIS_KEY_PAIR.evm_address().with_evm_space(), balance);
69 accounts.insert(
70 DEV_GENESIS_KEY_PAIR_2.evm_address().with_evm_space(),
71 balance,
72 );
73 accounts
74}
75
76pub fn load_secrets_file(
77 path: &String, secret_store: &SecretStore, space: Space,
78) -> Result<HashMap<AddressWithSpace, U256>, String> {
79 let file = File::open(path)
80 .map_err(|e| format!("failed to open file: {:?}", e))?;
81 let buffered = BufReader::new(file);
82
83 let mut accounts: HashMap<AddressWithSpace, U256> = HashMap::new();
84 let balance =
85 U256::from_dec_str("10000000000000000000000").map_err(|e| {
86 format!(
87 "failed to parse balance: value = {}, error = {:?}",
88 "10000000000000000000000", e
89 )
90 })?;
91 for line in buffered.lines() {
92 let keypair =
93 KeyPair::from_secret(line.unwrap().parse().unwrap()).unwrap();
94
95 match space {
96 Space::Native => {
97 accounts.insert(
99 keypair.address().with_native_space(),
100 balance.clone(),
101 );
102 }
103 Space::Ethereum => {
104 accounts.insert(
106 keypair.evm_address().with_evm_space(),
107 balance.clone(),
108 );
109 }
110 }
111
112 secret_store.insert(keypair);
113 }
114 Ok(accounts)
115}
116
117pub fn genesis_block(
120 storage_manager: &Arc<StorageManager>,
121 genesis_accounts: HashMap<AddressWithSpace, U256>,
122 test_net_version: Address, initial_difficulty: U256, machine: Arc<Machine>,
123 need_to_execute: bool, genesis_chain_id: Option<u32>,
124 initial_nodes: &Option<GenesisPosState>,
125) -> Block {
126 let mut state =
127 State::new(StateDb::new(storage_manager.get_state_for_genesis_write()))
128 .expect("Failed to initialize state");
129
130 let mut genesis_block_author = test_net_version;
131 genesis_block_author.set_user_account_type_bits();
132
133 initialize_internal_contract_accounts(
134 &mut state,
135 machine.internal_contracts().initialized_at_genesis(),
136 )
137 .expect("no db error");
138 trace!("genesis_accounts: {:?}", genesis_accounts);
139 for (addr, balance) in genesis_accounts {
140 state.add_balance(&addr, &balance).unwrap();
141 state.add_total_issued(balance);
142 if addr.space == Space::Ethereum {
143 state.add_total_evm_tokens(balance);
144 }
145 }
146 let genesis_account_address = GENESIS_ACCOUNT_ADDRESS.with_native_space();
147
148 let genesis_token_count =
149 U256::from(GENESIS_TOKEN_COUNT_IN_CFX) * U256::from(ONE_CFX_IN_DRIP);
150 state.add_total_issued(genesis_token_count);
151 let two_year_unlock_token_count =
152 U256::from(TWO_YEAR_UNLOCK_TOKEN_COUNT_IN_CFX)
153 * U256::from(ONE_CFX_IN_DRIP);
154 let four_year_unlock_token_count =
155 genesis_token_count - two_year_unlock_token_count;
156
157 let genesis_account_init_balance =
158 U256::from(ONE_CFX_IN_DRIP) * 100 + genesis_token_count;
159 state
160 .add_balance(&genesis_account_address, &genesis_account_init_balance)
161 .unwrap();
162 state.commit_cache(false);
163
164 let mut debug_record = Some(ComputeEpochDebugRecord::default());
165
166 let genesis_chain_id = genesis_chain_id.unwrap_or(0);
167 let mut genesis_transaction = NativeTransaction::default();
168 genesis_transaction.data = GENESIS_TRANSACTION_DATA_STR.as_bytes().into();
169 genesis_transaction.action = Action::Call(Default::default());
170 genesis_transaction.chain_id = genesis_chain_id;
171
172 let mut create_create2factory_transaction = NativeTransaction::default();
173 create_create2factory_transaction.nonce = 0.into();
174 create_create2factory_transaction.data =
175 GENESIS_TRANSACTION_CREATE_CREATE2FACTORY
176 .from_hex()
177 .unwrap();
178 create_create2factory_transaction.action = Action::Create;
179 create_create2factory_transaction.chain_id = genesis_chain_id;
180 create_create2factory_transaction.gas = 300000.into();
181 create_create2factory_transaction.gas_price = 1.into();
182 create_create2factory_transaction.storage_limit = 512;
183
184 let mut create_genesis_token_manager_two_year_unlock_transaction =
185 NativeTransaction::default();
186 create_genesis_token_manager_two_year_unlock_transaction.nonce = 1.into();
187 create_genesis_token_manager_two_year_unlock_transaction.data =
188 GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_TWO_YEAR_UNLOCK
189 .from_hex()
190 .unwrap();
191 create_genesis_token_manager_two_year_unlock_transaction.value =
192 two_year_unlock_token_count;
193 create_genesis_token_manager_two_year_unlock_transaction.action =
194 Action::Create;
195 create_genesis_token_manager_two_year_unlock_transaction.chain_id =
196 genesis_chain_id;
197 create_genesis_token_manager_two_year_unlock_transaction.gas =
198 2800000.into();
199 create_genesis_token_manager_two_year_unlock_transaction.gas_price =
200 1.into();
201 create_genesis_token_manager_two_year_unlock_transaction.storage_limit =
202 16000;
203
204 let mut create_genesis_token_manager_four_year_unlock_transaction =
205 NativeTransaction::default();
206 create_genesis_token_manager_four_year_unlock_transaction.nonce = 2.into();
207 create_genesis_token_manager_four_year_unlock_transaction.data =
208 GENESIS_TRANSACTION_CREATE_GENESIS_TOKEN_MANAGER_FOUR_YEAR_UNLOCK
209 .from_hex()
210 .unwrap();
211 create_genesis_token_manager_four_year_unlock_transaction.value =
212 four_year_unlock_token_count;
213 create_genesis_token_manager_four_year_unlock_transaction.action =
214 Action::Create;
215 create_genesis_token_manager_four_year_unlock_transaction.chain_id =
216 genesis_chain_id;
217 create_genesis_token_manager_four_year_unlock_transaction.gas =
218 5000000.into();
219 create_genesis_token_manager_four_year_unlock_transaction.gas_price =
220 1.into();
221 create_genesis_token_manager_four_year_unlock_transaction.storage_limit =
222 32000;
223
224 let mut create_genesis_investor_fund_transaction =
225 NativeTransaction::default();
226 create_genesis_investor_fund_transaction.nonce = 3.into();
227 create_genesis_investor_fund_transaction.data =
228 GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
229 create_genesis_investor_fund_transaction.action = Action::Create;
230 create_genesis_investor_fund_transaction.chain_id = genesis_chain_id;
231 create_genesis_investor_fund_transaction.gas = 400000.into();
232 create_genesis_investor_fund_transaction.gas_price = 1.into();
233 create_genesis_investor_fund_transaction.storage_limit = 1000;
234
235 let mut create_genesis_team_fund_transaction = NativeTransaction::default();
236 create_genesis_team_fund_transaction.nonce = 4.into();
237 create_genesis_team_fund_transaction.data =
238 GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
239 create_genesis_team_fund_transaction.action = Action::Create;
240 create_genesis_team_fund_transaction.chain_id = genesis_chain_id;
241 create_genesis_team_fund_transaction.gas = 400000.into();
242 create_genesis_team_fund_transaction.gas_price = 1.into();
243 create_genesis_team_fund_transaction.storage_limit = 1000;
244
245 let mut create_genesis_eco_fund_transaction = NativeTransaction::default();
246 create_genesis_eco_fund_transaction.nonce = 5.into();
247 create_genesis_eco_fund_transaction.data =
248 GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
249 create_genesis_eco_fund_transaction.action = Action::Create;
250 create_genesis_eco_fund_transaction.chain_id = genesis_chain_id;
251 create_genesis_eco_fund_transaction.gas = 400000.into();
252 create_genesis_eco_fund_transaction.gas_price = 1.into();
253 create_genesis_eco_fund_transaction.storage_limit = 1000;
254
255 let mut create_genesis_community_fund_transaction =
256 NativeTransaction::default();
257 create_genesis_community_fund_transaction.nonce = 6.into();
258 create_genesis_community_fund_transaction.data =
259 GENESIS_TRANSACTION_CREATE_FUND_POOL.from_hex().unwrap();
260 create_genesis_community_fund_transaction.action = Action::Create;
261 create_genesis_community_fund_transaction.chain_id = genesis_chain_id;
262 create_genesis_community_fund_transaction.gas = 400000.into();
263 create_genesis_community_fund_transaction.gas_price = 1.into();
264 create_genesis_community_fund_transaction.storage_limit = 1000;
265
266 let genesis_transactions = vec![
267 Arc::new(genesis_transaction.fake_sign(Default::default())),
268 Arc::new(
269 create_create2factory_transaction
270 .fake_sign(genesis_account_address),
271 ),
272 Arc::new(
273 create_genesis_token_manager_two_year_unlock_transaction
274 .fake_sign(genesis_account_address),
275 ),
276 Arc::new(
277 create_genesis_token_manager_four_year_unlock_transaction
278 .fake_sign(genesis_account_address),
279 ),
280 Arc::new(
281 create_genesis_investor_fund_transaction
282 .fake_sign(genesis_account_address),
283 ),
284 Arc::new(
285 create_genesis_team_fund_transaction
286 .fake_sign(genesis_account_address),
287 ),
288 Arc::new(
289 create_genesis_eco_fund_transaction
290 .fake_sign(genesis_account_address),
291 ),
292 Arc::new(
293 create_genesis_community_fund_transaction
294 .fake_sign(genesis_account_address),
295 ),
296 ];
297
298 if need_to_execute {
299 const CREATE2FACTORY_TX_INDEX: usize = 1;
300 let contract_name_list = vec![
309 "CREATE2FACTORY",
310 "TWO_YEAR_UNLOCK",
311 "FOUR_YEAR_UNLOCK",
312 "INVESTOR_FUND",
313 "TEAM_FUND",
314 "ECO_FUND",
315 "COMMUNITY_FUND",
316 ];
317
318 for i in CREATE2FACTORY_TX_INDEX..=contract_name_list.len() {
319 execute_genesis_transaction(
320 genesis_transactions[i].as_ref(),
321 &mut state,
322 machine.clone(),
323 );
324
325 let (contract_address, _) = cal_contract_address_with_space(
326 CreateContractAddressType::FromSenderNonceAndCodeHash,
327 &genesis_account_address,
328 &(i - 1).into(),
329 genesis_transactions[i].as_ref().data(),
330 );
331
332 state
333 .set_admin(&contract_address.address, &Address::zero())
334 .expect("");
335 info!(
336 "Genesis {:?} addresses: {:?}",
337 contract_name_list[i - 1],
338 contract_address
339 );
340 state.commit_cache(false);
341 }
342 }
343
344 if let Some(initial_nodes) = initial_nodes {
345 for node in &initial_nodes.initial_nodes {
346 let stake_balance = U256::from(node.voting_power) * *POS_VOTE_PRICE;
347 state
349 .add_balance(
350 &node.address.with_native_space(),
351 &(stake_balance
352 + U256::from(ONE_CFX_IN_DRIP) * U256::from(20)),
353 )
354 .unwrap();
355 state
356 .deposit(&node.address, &stake_balance, 0, false)
357 .unwrap();
358 state.commit_cache(false);
359 let signed_tx = node
360 .register_tx
361 .clone()
362 .fake_sign(node.address.with_native_space());
363 execute_genesis_transaction(
364 &signed_tx,
365 &mut state,
366 machine.clone(),
367 );
368 }
369 }
370
371 state
372 .genesis_special_remove_account(&genesis_account_address.address)
373 .expect("Clean account failed");
374
375 let state_root = state
376 .compute_state_root_for_genesis(
377 debug_record.as_mut(),
378 )
379 .unwrap();
380 let receipt_root = compute_receipts_root(&vec![Arc::new(BlockReceipts {
381 receipts: vec![],
382 block_number: 0,
383 secondary_reward: U256::zero(),
384 tx_execution_error_messages: vec![],
385 })]);
386
387 let mut genesis = Block::new(
388 BlockHeaderBuilder::new()
389 .with_deferred_state_root(state_root.aux_info.state_root_hash)
390 .with_deferred_receipts_root(receipt_root)
391 .with_gas_limit(GENESIS_GAS_LIMIT.into())
392 .with_author(genesis_block_author)
393 .with_difficulty(initial_difficulty)
394 .with_transactions_root(compute_transaction_root(
395 &genesis_transactions,
396 ))
397 .build(),
398 genesis_transactions,
399 );
400 genesis.block_header.compute_hash();
401 debug!(
402 "Initialize genesis_block={:?} hash={:?}",
403 genesis,
404 genesis.hash()
405 );
406
407 state
408 .commit(
409 genesis.block_header.hash(),
410 debug_record.as_mut(),
411 )
412 .unwrap();
413 genesis.block_header.pow_hash = Some(Default::default());
414 debug!(
415 "genesis debug_record {}",
416 serde_json::to_string(&debug_record).unwrap()
417 );
418 genesis
419}
420
421pub fn register_transaction(
422 bls_priv_key: BLSPrivateKey, vrf_pub_key: EcVrfPublicKey, power: u64,
423 genesis_chain_id: u32, legacy: bool,
424) -> NativeTransaction {
425 use bls_signatures::{
427 sigma_protocol, PrivateKey as BlsPrivKey, PublicKey as BlsPubKey,
428 Serialize,
429 };
430 use cfx_parameters::internal_contract_addresses::POS_REGISTER_CONTRACT_ADDRESS;
431 use rand_08::rngs::OsRng;
432 use solidity_abi::ABIEncodable;
433 use tiny_keccak::{Hasher, Keccak};
434
435 let bls_pub_key = bls_priv_key.public_key();
436 let (commit, answer) =
437 sigma_protocol::prove(bls_priv_key.raw_key(), &mut OsRng, legacy);
438
439 let mut encoded_commit = Vec::<u8>::new();
440 BlsPubKey::from(commit)
441 .write_bytes(&mut encoded_commit)
442 .expect("write to Vec<u8> never fails");
443
444 let mut encoded_answer = Vec::<u8>::new();
445 BlsPrivKey::from(answer)
446 .write_bytes(&mut encoded_answer)
447 .expect("write to Vec<u8> never fails");
448
449 let encoded_bls_pub_key = bls_pub_key.to_bytes();
450
451 let encoded_vrf_pub_key = vrf_pub_key.to_bytes();
452
453 let mut hasher = Keccak::v256();
454 hasher.update(encoded_bls_pub_key.as_slice());
455 hasher.update(encoded_vrf_pub_key.as_slice());
456 let mut computed_identifier = H256::default();
457 hasher.finalize(computed_identifier.as_bytes_mut());
458
459 let params = (
460 computed_identifier,
461 power,
462 encoded_bls_pub_key,
463 encoded_vrf_pub_key,
464 [encoded_commit, encoded_answer],
465 );
466
467 let mut call_data: Vec<u8> = "e335b451".from_hex().unwrap();
468 call_data.extend_from_slice(¶ms.abi_encode());
469
470 let mut tx = NativeTransaction::default();
471 tx.nonce = 0.into();
472 tx.data = call_data;
473 tx.value = U256::zero();
474 tx.action = Action::Call(POS_REGISTER_CONTRACT_ADDRESS);
475 tx.chain_id = genesis_chain_id;
476 tx.gas = 200000.into();
477 tx.gas_price = 1.into();
478 tx.storage_limit = 16000;
479 tx
480}
481
482fn execute_genesis_transaction(
483 transaction: &SignedTransaction, state: &mut State, machine: Arc<Machine>,
484) {
485 let mut env = Env::default();
486 env.transaction_hash = transaction.hash();
487
488 let options = TransactOptions::default();
489 let r = {
490 ExecutiveContext::new(
491 state,
492 &env,
493 machine.as_ref(),
494 &machine.spec(env.number, env.epoch_height),
495 )
496 .transact(transaction, options)
497 .unwrap()
498 };
499 state.update_state_post_tx_execution(false);
500
501 match &r {
502 ExecutionOutcome::Finished(_executed) => {}
503 _ => {
504 panic!("genesis transaction should not fail! err={:?}", r);
505 }
506 }
507}
508
509pub fn load_file(
510 path: &String, address_parser: impl Fn(&str) -> Result<Address, String>,
511) -> Result<HashMap<AddressWithSpace, U256>, String> {
512 let mut content = String::new();
513 let mut file = File::open(path)
514 .map_err(|e| format!("failed to open file: {:?}", e))?;
515 file.read_to_string(&mut content)
516 .map_err(|e| format!("failed to read file content: {:?}", e))?;
517 let account_values = content
518 .parse::<toml::Value>()
519 .map_err(|e| format!("failed to parse toml file: {:?}", e))?;
520
521 let mut accounts: HashMap<AddressWithSpace, U256> = HashMap::new();
522 match account_values {
523 Value::Table(table) => {
524 for (key, value) in table {
525 let addr = address_parser(&key).map_err(|e| {
526 format!(
527 "failed to parse address: value = {}, error = {:?}",
528 key, e
529 )
530 })?;
531
532 match value {
533 Value::String(balance) => {
534 let balance = U256::from_dec_str(&balance).map_err(|e| format!("failed to parse balance: value = {}, error = {:?}", balance, e))?;
535 accounts.insert(addr.with_native_space(), balance);
536 }
537 _ => {
538 return Err(
539 "balance in toml file requires String type".into(),
540 );
541 }
542 }
543 }
544 }
545 _ => {
546 return Err(format!(
547 "invalid root value type {:?} in toml file",
548 account_values.type_str()
549 ));
550 }
551 }
552
553 Ok(accounts)
554}
555
556#[derive(Serialize, Deserialize, Clone)]
557pub struct GenesisPosNodeInfo {
558 pub address: Address,
559 pub bls_key: ConsensusPublicKey,
560 pub vrf_key: ConsensusVRFPublicKey,
561 pub voting_power: u64,
562 pub register_tx: NativeTransaction,
563}
564
565#[derive(Serialize, Deserialize)]
566pub struct GenesisPosState {
567 pub initial_nodes: Vec<GenesisPosNodeInfo>,
568 pub initial_committee: Vec<(AccountAddress, u64)>,
569 pub initial_seed: H256,
570}