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