2025-09-25 15:38:18 +00:00
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2012-2013 The Boolberry developers
2025-09-25 18:18:41 +01:00
// Copyright (c) 2017-2025 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// You may obtain a copy of the licence at:
//
// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl
//
// The EUPL is a copyleft licence that is compatible with the MIT/X11
// licence used by the original projects; the MIT terms are therefore
// considered “grandfathered” under the EUPL for this code.
//
// SPDX‑ License‑ Identifier: EUPL-1.2
//
2025-09-25 15:38:18 +00:00
# include "misc_log_ex.h"
# include "currency_core/currency_format_utils.h"
# include "common/command_line.h"
# include <boost/multiprecision/integer.hpp>
namespace po = boost : : program_options ;
bool generate_test_genesis ( std : : string address , std : : string proof , std : : string out_dir )
{
using namespace std ;
currency : : block bl = boost : : value_initialized < currency : : block > ( ) ;
# ifndef TESTNET
constexpr auto posfix = " " ;
# else
constexpr auto posfix = " _tn " ;
# endif
vector < currency : : tx_destination_entry > destinations ;
currency : : tx_destination_entry de = AUTO_VAL_INIT ( de ) ;
de . addr . resize ( 1 ) ;
bool r = get_account_address_from_str ( de . addr . back ( ) , address ) ;
CHECK_AND_ASSERT_MES ( r , false , " wrong address string: " < < address ) ;
de . amount = PREMINE_AMOUNT ;
destinations . push_back ( de ) ;
//make sure it initialized with zeros
uint64_t summary_premine_coins = de . amount ;
const currency : : account_public_address dummy_address = AUTO_VAL_INIT ( dummy_address ) ;
uint64_t block_reward_without_fee = 0 ;
uint64_t block_reward = 0 ;
construct_miner_tx ( 0 , 0 , 0 , 0 , 0 ,
dummy_address , dummy_address , bl . miner_tx , block_reward_without_fee , block_reward ,
TRANSACTION_VERSION_PRE_HF4 , 0 , proof , CURRENCY_MINER_TX_MAX_OUTS , false , currency : : pos_entry ( ) ,
nullptr , nullptr , destinations ) ;
currency : : blobdata txb = tx_to_blob ( bl . miner_tx ) ;
//self validate block
if ( currency : : get_outs_money_amount ( bl . miner_tx ) ! = summary_premine_coins )
{
LOG_ERROR ( " Internal error: total_this = " < < summary_premine_coins < < " didn't match with miner_tx total = " < < currency : : get_outs_money_amount ( bl . miner_tx ) ) ;
}
string hex_tx_represent = epee : : string_tools : : buff_to_hex_nodelimer ( txb ) ;
auto ret = epee : : file_io_utils : : save_string_to_file ( out_dir + " .genesis.txt " , hex_tx_represent ) ;
CHECK_AND_ASSERT_MES_NO_RET ( ret , " failed to create " < < out_dir < < " .genesis.txt " ) ;
uint64_t * parray = ( uint64_t * ) txb . data ( ) ;
size_t count = txb . size ( ) / sizeof ( uint64_t ) ;
size_t rest_bytes = txb . size ( ) - count * sizeof ( uint64_t ) ;
basic_stringstream < char > genesis_h_stream ;
basic_stringstream < char > genesis_cpp_stream ;
genesis_h_stream < < " struct genesis_tx_raw_data " < < ENDL
< < " { " < < ENDL
< < " uint64_t const v[ " < < count < < " ]; " < < ENDL
< < " uint8_t const r[ " < < rest_bytes < < " ]; " < < ENDL
< < " }; " < < ENDL ;
genesis_cpp_stream < < " const genesis_tx_raw_data ggenesis_tx_raw = {{ " < < ENDL ;
for ( size_t i = 0 ; i ! = count ; i + + )
{
genesis_cpp_stream < < ( i = = 0 ? " 0x " : " ,0x " ) < < hex < < setw ( 16 ) < < setfill ( ' 0 ' ) < < parray [ i ] ;
}
genesis_cpp_stream < < " }, " < < ENDL < < " { " ;
uint8_t * ptail_array = ( uint8_t * ) & parray [ count ] ;
for ( size_t i = 0 ; i ! = rest_bytes ; i + + )
{
genesis_cpp_stream < < ( i = = 0 ? " 0x " : " ,0x " ) < < hex < < setw ( 2 ) < < setfill ( ' 0 ' ) < < + ptail_array [ i ] ;
}
genesis_cpp_stream < < " }}; " < < ENDL ;
// Generate _genesis.cpp.gen
// Generate _genesis.h.gen
ret = epee : : file_io_utils : : save_string_to_file ( out_dir + " _genesis " + posfix + " .h.gen " , genesis_h_stream . str ( ) ) ;
CHECK_AND_ASSERT_MES_NO_RET ( ret , " failed to create " < < out_dir < < " _genesis.h.gen " ) ;
ret = epee : : file_io_utils : : save_string_to_file ( out_dir + " _genesis " + posfix + " .cpp.gen " , genesis_cpp_stream . str ( ) ) ;
CHECK_AND_ASSERT_MES_NO_RET ( ret , " failed to create " < < out_dir < < " _genesis.cpp.gen " ) ;
// Single address for now
uint64_t key = currency : : get_string_uint64_hash ( address ) ;
// Generate _genesis_acc.cpp.gen
basic_stringstream < char > genesis_acc_stream ;
genesis_acc_stream < < " const std::string ggenesis_tx_pub_key_str = \" " < <
epee : : string_tools : : pod_to_hex ( get_tx_pub_key_from_extra ( bl . miner_tx ) ) < < " \" ; " < < ENDL ;
genesis_acc_stream < < " const crypto::public_key ggenesis_tx_pub_key = epee::string_tools::parse_tpod_from_hex_string<crypto::public_key>(ggenesis_tx_pub_key_str); " < < ENDL
< < " extern const genesis_tx_dictionary_entry ggenesis_dict[ " < < 1 < < " ]; " < < ENDL
< < " const genesis_tx_dictionary_entry ggenesis_dict[ " < < 1 < < " ] = { " ;
genesis_acc_stream < < " " < < ENDL < < " { " < < key < < " ULL, " < < 0 < < " } " ;
genesis_acc_stream < < ENDL < < " }; " < < ENDL ;
ret = epee : : file_io_utils : : save_string_to_file ( out_dir + " _genesis_acc " + posfix + " .cpp.gen " , genesis_acc_stream . str ( ) ) ;
CHECK_AND_ASSERT_MES_NO_RET ( ret , " failed to create " < < out_dir < < " .genesis.dictionary.txt " ) ;
return ret ;
}
const command_line : : arg_descriptor < std : : string > arg_target_address ( " address " , " Premine wallet address " ) ;
const command_line : : arg_descriptor < std : : string > arg_proof ( " proof " , " Genesis proof string " ) ;
const command_line : : arg_descriptor < std : : string > arg_dir ( " output " , " Direcory output for generated files " ) ;
po : : options_description desc_cmd ( " Command line options " ) ;
int main ( int argc , char * * argv ) {
command_line : : add_arg ( desc_cmd , arg_target_address ) ;
command_line : : add_arg ( desc_cmd , arg_proof ) ;
command_line : : add_arg ( desc_cmd , arg_dir ) ;
epee : : log_space : : log_singletone : : add_logger ( LOGGER_CONSOLE , NULL , NULL ) ;
po : : variables_map vm ;
bool r = command_line : : handle_error_helper ( desc_cmd , [ & ] ( )
{
po : : store ( po : : parse_command_line ( argc , argv , desc_cmd ) , vm ) ;
po : : notify ( vm ) ;
return true ;
} ) ;
if ( ! r ) {
LOG_ERROR ( " Param parsing failed! " ) ;
return 1 ;
}
std : : string premine_address = command_line : : get_arg ( vm , arg_target_address ) ;
std : : string proof = command_line : : get_arg ( vm , arg_proof ) ;
std : : string dir = command_line : : get_arg ( vm , arg_dir ) ;
LOG_PRINT_L0 ( " addr: " < < premine_address < < " proof: " < < proof < < " amount: " < < PREMINE_AMOUNT ) ;
generate_test_genesis ( premine_address , proof , dir ) ;
return 0 ;
}