Resolve #133: allow creation of example genesis json
This commit is contained in:
parent
52fd59f0aa
commit
6ab59f63a7
4 changed files with 73 additions and 56 deletions
|
|
@ -54,6 +54,35 @@ namespace bpo = boost::program_options;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
genesis_state_type create_example_genesis() {
|
||||||
|
auto nathan_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
|
||||||
|
dlog("Allocating all stake to ${key}", ("key", utilities::key_to_wif(nathan_key)));
|
||||||
|
genesis_state_type initial_state;
|
||||||
|
fc::reflector<fee_schedule_type>::visit(
|
||||||
|
fee_schedule_type::fee_set_visitor{initial_state.initial_parameters.current_fees, 0});
|
||||||
|
secret_hash_type::encoder enc;
|
||||||
|
fc::raw::pack(enc, nathan_key);
|
||||||
|
fc::raw::pack(enc, secret_hash_type());
|
||||||
|
auto secret = secret_hash_type::hash(enc.result());
|
||||||
|
initial_state.initial_active_witnesses = 10;
|
||||||
|
for( int i = 0; i < initial_state.initial_active_witnesses; ++i )
|
||||||
|
{
|
||||||
|
auto name = "init"+fc::to_string(i);
|
||||||
|
initial_state.initial_accounts.emplace_back(name,
|
||||||
|
nathan_key.get_public_key(),
|
||||||
|
nathan_key.get_public_key(),
|
||||||
|
true);
|
||||||
|
initial_state.initial_committee_candidates.push_back({name});
|
||||||
|
initial_state.initial_witness_candidates.push_back({name, nathan_key.get_public_key(), secret});
|
||||||
|
}
|
||||||
|
|
||||||
|
initial_state.initial_accounts.emplace_back("nathan", nathan_key.get_public_key());
|
||||||
|
initial_state.initial_balances.push_back({nathan_key.get_public_key(),
|
||||||
|
GRAPHENE_SYMBOL,
|
||||||
|
GRAPHENE_MAX_SHARE_SUPPLY});
|
||||||
|
return initial_state;
|
||||||
|
}
|
||||||
|
|
||||||
class application_impl : public net::node_delegate
|
class application_impl : public net::node_delegate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -155,34 +184,12 @@ namespace detail {
|
||||||
bool clean = !fc::exists(_data_dir / "blockchain/dblock");
|
bool clean = !fc::exists(_data_dir / "blockchain/dblock");
|
||||||
fc::create_directories(_data_dir / "blockchain/dblock");
|
fc::create_directories(_data_dir / "blockchain/dblock");
|
||||||
|
|
||||||
auto nathan_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("nathan")));
|
|
||||||
genesis_state_type initial_state;
|
genesis_state_type initial_state;
|
||||||
fc::reflector<fee_schedule_type>::visit(
|
|
||||||
fee_schedule_type::fee_set_visitor{initial_state.initial_parameters.current_fees, 0});
|
|
||||||
secret_hash_type::encoder enc;
|
|
||||||
fc::raw::pack(enc, nathan_key);
|
|
||||||
fc::raw::pack(enc, secret_hash_type());
|
|
||||||
auto secret = secret_hash_type::hash(enc.result());
|
|
||||||
for( int i = 0; i < 10; ++i )
|
|
||||||
{
|
|
||||||
auto name = "init"+fc::to_string(i);
|
|
||||||
initial_state.initial_accounts.emplace_back(name,
|
|
||||||
nathan_key.get_public_key(),
|
|
||||||
nathan_key.get_public_key(),
|
|
||||||
true);
|
|
||||||
initial_state.initial_committee_candidates.push_back({name});
|
|
||||||
initial_state.initial_witness_candidates.push_back({name, nathan_key.get_public_key(), secret});
|
|
||||||
}
|
|
||||||
|
|
||||||
initial_state.initial_accounts.emplace_back("nathan", nathan_key.get_public_key());
|
|
||||||
initial_state.initial_balances.push_back({nathan_key.get_public_key(),
|
|
||||||
GRAPHENE_SYMBOL,
|
|
||||||
GRAPHENE_MAX_SHARE_SUPPLY});
|
|
||||||
if( _options->count("genesis-json") )
|
if( _options->count("genesis-json") )
|
||||||
initial_state = fc::json::from_file(_options->at("genesis-json").as<boost::filesystem::path>())
|
initial_state = fc::json::from_file(_options->at("genesis-json").as<boost::filesystem::path>())
|
||||||
.as<genesis_state_type>();
|
.as<genesis_state_type>();
|
||||||
else
|
else
|
||||||
dlog("Allocating all stake to ${key}", ("key", utilities::key_to_wif(nathan_key)));
|
initial_state = create_example_genesis();
|
||||||
|
|
||||||
if( _options->count("resync-blockchain") )
|
if( _options->count("resync-blockchain") )
|
||||||
_chain_db->wipe(_data_dir / "blockchain", true);
|
_chain_db->wipe(_data_dir / "blockchain", true);
|
||||||
|
|
@ -427,13 +434,11 @@ application::~application()
|
||||||
{
|
{
|
||||||
if( my->_p2p_network )
|
if( my->_p2p_network )
|
||||||
{
|
{
|
||||||
//ilog("Closing p2p node");
|
|
||||||
my->_p2p_network->close();
|
my->_p2p_network->close();
|
||||||
my->_p2p_network.reset();
|
my->_p2p_network.reset();
|
||||||
}
|
}
|
||||||
if( my->_chain_db )
|
if( my->_chain_db )
|
||||||
{
|
{
|
||||||
//ilog("Closing chain database");
|
|
||||||
my->_chain_db->close();
|
my->_chain_db->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -452,6 +457,10 @@ void application::set_program_options(boost::program_options::options_descriptio
|
||||||
;
|
;
|
||||||
command_line_options.add(configuration_file_options);
|
command_line_options.add(configuration_file_options);
|
||||||
command_line_options.add_options()
|
command_line_options.add_options()
|
||||||
|
("create-genesis-json", bpo::value<boost::filesystem::path>(),
|
||||||
|
"Path to create a Genesis State at. If a well-formed JSON file exists at the path, it will be parsed and any "
|
||||||
|
"missing fields in a Genesis State will be added, and any unknown fields will be removed. If no file or an "
|
||||||
|
"invalid file is found, it will be replaced with an example Genesis State.")
|
||||||
("replay-blockchain", "Rebuild object graph by replaying all blocks")
|
("replay-blockchain", "Rebuild object graph by replaying all blocks")
|
||||||
("resync-blockchain", "Delete all blocks and re-sync with network from scratch")
|
("resync-blockchain", "Delete all blocks and re-sync with network from scratch")
|
||||||
;
|
;
|
||||||
|
|
@ -463,6 +472,31 @@ void application::initialize(const fc::path& data_dir, const boost::program_opti
|
||||||
{
|
{
|
||||||
my->_data_dir = data_dir;
|
my->_data_dir = data_dir;
|
||||||
my->_options = &options;
|
my->_options = &options;
|
||||||
|
|
||||||
|
if( options.count("create-genesis-json") )
|
||||||
|
{
|
||||||
|
fc::path genesis_out = options.at("create-genesis-json").as<boost::filesystem::path>();
|
||||||
|
genesis_state_type genesis_state = detail::create_example_genesis();
|
||||||
|
if( fc::exists(genesis_out) )
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
genesis_state = fc::json::from_file(genesis_out).as<genesis_state_type>();
|
||||||
|
} catch(const fc::exception& e) {
|
||||||
|
std::cerr << "Unable to parse existing genesis file:\n" << e.to_string()
|
||||||
|
<< "\nWould you like to replace it? [y/N] ";
|
||||||
|
char response = std::cin.get();
|
||||||
|
if( toupper(response) != 'Y' )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "Updating genesis state in file " << genesis_out.generic_string() << "\n";
|
||||||
|
} else {
|
||||||
|
std::cerr << "Creating example genesis state in file " << genesis_out.generic_string() << "\n";
|
||||||
|
}
|
||||||
|
fc::json::save_to_file(genesis_state, genesis_out);
|
||||||
|
|
||||||
|
std::exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void application::startup()
|
void application::startup()
|
||||||
|
|
|
||||||
|
|
@ -251,24 +251,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
// Create initial accounts
|
// Create initial accounts
|
||||||
for( const auto& account : genesis_state.initial_accounts )
|
for( const auto& account : genesis_state.initial_accounts )
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
key_id_type key_id = apply_operation(genesis_eval_state,
|
|
||||||
key_create_operation({asset(),
|
|
||||||
GRAPHENE_TEMP_ACCOUNT,
|
|
||||||
account.owner_key})).get<object_id_type>();
|
|
||||||
*/
|
|
||||||
account_create_operation cop;
|
account_create_operation cop;
|
||||||
cop.name = account.name;
|
cop.name = account.name;
|
||||||
cop.registrar = GRAPHENE_TEMP_ACCOUNT;
|
cop.registrar = GRAPHENE_TEMP_ACCOUNT;
|
||||||
cop.owner = authority(1, account.owner_key, 1);
|
cop.owner = authority(1, account.owner_key, 1);
|
||||||
if( account.owner_key != account.active_key )
|
if( account.owner_key != account.active_key )
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
key_id = apply_operation(genesis_eval_state,
|
|
||||||
key_create_operation({asset(),
|
|
||||||
GRAPHENE_TEMP_ACCOUNT,
|
|
||||||
account.owner_key})).get<object_id_type>();
|
|
||||||
*/
|
|
||||||
cop.active = authority(1, account.owner_key, 1);
|
cop.active = authority(1, account.owner_key, 1);
|
||||||
} else {
|
} else {
|
||||||
cop.active = cop.owner;
|
cop.active = cop.owner;
|
||||||
|
|
@ -288,7 +276,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
const auto& accounts_by_name = get_index_type<account_index>().indices().get<by_name>();
|
const auto& accounts_by_name = get_index_type<account_index>().indices().get<by_name>();
|
||||||
auto get_account_id = [&accounts_by_name](const string& name) {
|
auto get_account_id = [&accounts_by_name](const string& name) {
|
||||||
auto itr = accounts_by_name.find(name);
|
auto itr = accounts_by_name.find(name);
|
||||||
FC_ASSERT(itr != accounts_by_name.end());
|
FC_ASSERT(itr != accounts_by_name.end(),
|
||||||
|
"Unable to find account '${acct}'. Did you forget to add a record for it to initial_accounts?",
|
||||||
|
("acct", name));
|
||||||
return itr->get_id();
|
return itr->get_id();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -296,7 +286,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
const auto& assets_by_symbol = get_index_type<asset_index>().indices().get<by_symbol>();
|
const auto& assets_by_symbol = get_index_type<asset_index>().indices().get<by_symbol>();
|
||||||
auto get_asset_id = [&assets_by_symbol](const string& symbol) {
|
auto get_asset_id = [&assets_by_symbol](const string& symbol) {
|
||||||
auto itr = assets_by_symbol.find(symbol);
|
auto itr = assets_by_symbol.find(symbol);
|
||||||
FC_ASSERT(itr != assets_by_symbol.end());
|
FC_ASSERT(itr != assets_by_symbol.end(),
|
||||||
|
"Unable to find asset '${sym}'. Did you forget to add a record for it to initial_assets?",
|
||||||
|
("sym", symbol));
|
||||||
return itr->get_id();
|
return itr->get_id();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -313,12 +305,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
int collateral_holder_number = 0;
|
int collateral_holder_number = 0;
|
||||||
for( const auto& collateral_rec : asset.bitasset_options->collateral_records )
|
for( const auto& collateral_rec : asset.bitasset_options->collateral_records )
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
key_id_type key_id = apply_operation(genesis_eval_state,
|
|
||||||
key_create_operation{{},
|
|
||||||
GRAPHENE_TEMP_ACCOUNT,
|
|
||||||
collateral_rec.owner}).get<object_id_type>();
|
|
||||||
*/
|
|
||||||
account_create_operation cop;
|
account_create_operation cop;
|
||||||
cop.name = asset.symbol + "-collateral-holder-" + std::to_string(collateral_holder_number);
|
cop.name = asset.symbol + "-collateral-holder-" + std::to_string(collateral_holder_number);
|
||||||
boost::algorithm::to_lower(cop.name);
|
boost::algorithm::to_lower(cop.name);
|
||||||
|
|
@ -414,11 +400,6 @@ void database::init_genesis(const genesis_state_type& genesis_state)
|
||||||
// Create initial witnesses and delegates
|
// Create initial witnesses and delegates
|
||||||
std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(),
|
std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(),
|
||||||
[&](const genesis_state_type::initial_witness_type& witness) {
|
[&](const genesis_state_type::initial_witness_type& witness) {
|
||||||
/*
|
|
||||||
const key_object& signing_key = create<key_object>([&witness](key_object& k) {
|
|
||||||
k.key_data = witness.block_signing_key;
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
witness_create_operation op;
|
witness_create_operation op;
|
||||||
op.block_signing_key = witness.block_signing_key;
|
op.block_signing_key = witness.block_signing_key;
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,11 @@ void witness_plugin::plugin_set_program_options(
|
||||||
boost::program_options::options_description& config_file_options)
|
boost::program_options::options_description& config_file_options)
|
||||||
{
|
{
|
||||||
auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
|
auto default_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(std::string("nathan")));
|
||||||
|
string witness_id_example = fc::json::to_string(chain::witness_id_type());
|
||||||
command_line_options.add_options()
|
command_line_options.add_options()
|
||||||
("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale")
|
("enable-stale-production", bpo::bool_switch()->notifier([this](bool e){_production_enabled = e;}), "Enable block production, even if the chain is stale")
|
||||||
("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
|
("witness-id,w", bpo::value<vector<string>>()->composing()->multitoken(),
|
||||||
"ID of witness controlled by this node (e.g. \"1.7.0\", quotes are required, may specify multiple times)")
|
("ID of witness controlled by this node (e.g. " + witness_id_example + ", quotes are required, may specify multiple times)").c_str())
|
||||||
("private-key", bpo::value<vector<string>>()->composing()->multitoken()->
|
("private-key", bpo::value<vector<string>>()->composing()->multitoken()->
|
||||||
DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
|
DEFAULT_VALUE_VECTOR(std::make_pair(chain::public_key_type(default_priv_key.get_public_key()), graphene::utilities::key_to_wif(default_priv_key))),
|
||||||
"Tuple of [PublicKey, WIF private key] (may specify multiple times)")
|
"Tuple of [PublicKey, WIF private key] (may specify multiple times)")
|
||||||
|
|
|
||||||
|
|
@ -981,6 +981,7 @@ BOOST_AUTO_TEST_CASE( balance_object_test )
|
||||||
fc::temp_directory td;
|
fc::temp_directory td;
|
||||||
genesis_state.initial_balances.push_back({generate_private_key("n").get_public_key(), GRAPHENE_SYMBOL, 1});
|
genesis_state.initial_balances.push_back({generate_private_key("n").get_public_key(), GRAPHENE_SYMBOL, 1});
|
||||||
genesis_state.initial_balances.push_back({generate_private_key("x").get_public_key(), GRAPHENE_SYMBOL, 1});
|
genesis_state.initial_balances.push_back({generate_private_key("x").get_public_key(), GRAPHENE_SYMBOL, 1});
|
||||||
|
// genesis_state.initial_vesting_balances.push_back({generate_private_key("v").get_public_key(), GRAPHENE_SYMBOL, 1});
|
||||||
// TODO: vesting genesis balances
|
// TODO: vesting genesis balances
|
||||||
genesis_state.initial_accounts.emplace_back("n", generate_private_key("n").get_public_key());
|
genesis_state.initial_accounts.emplace_back("n", generate_private_key("n").get_public_key());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue