cfxcore/
genesis_block.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use 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    // FIXME: Decide the genesis initialization for mainnet.
60    let balance = U256::from_dec_str("5000000000000000000000000000000000")
61        .expect("Not overflow"); // 5*10^33
62    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                // Insert balance for native space only
99                accounts.insert(
100                    keypair.address().with_native_space(),
101                    balance.clone(),
102                );
103            }
104            Space::Ethereum => {
105                // Insert balance for EVM space only
106                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
118/// ` test_net_version` is used to update the genesis author so that after
119/// resetting, the chain of the older version will be discarded
120pub 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        /*
302        const TWO_YEAR_UNLOCK_TX_INDEX: usize = 2;
303        const FOUR_YEAR_UNLOCK_TX_INDEX: usize = 3;
304        const INVESTOR_FUND_TX_INDEX: usize = 4;
305        const TEAM_FUND_TX_INDEX: usize = 5;
306        const ECO_FUND_TX_INDEX: usize = 6;
307        const COMMUNITY_FUND_TX_INDEX: usize = 7;
308        */
309        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            // TODO(lpl): Pass in signed tx so they can be retired.
350            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 = */ 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 = */ 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    /// TODO: test this function with new internal contracts.
428    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(&params.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}