diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 47c88128..6af806f9 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory( fc ) add_subdirectory( db ) add_subdirectory( deterministic_openssl_rand ) add_subdirectory( chain ) +add_subdirectory( egenesis ) add_subdirectory( net ) add_subdirectory( time ) add_subdirectory( utilities ) diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index 33fca309..a2b95a23 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -18,6 +18,7 @@ add_library( graphene_chain # db_witness_schedule.cpp protocol/types.cpp + protocol/chain_id.cpp protocol/address.cpp protocol/authority.cpp protocol/asset.cpp @@ -40,6 +41,8 @@ add_library( graphene_chain protocol/confidential.cpp protocol/vote.cpp + genesis_state.cpp + pts_address.cpp evaluator.cpp diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 4d2218dc..2ab28d9f 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -303,7 +303,7 @@ void database::init_genesis(const genesis_state_type& genesis_state) // Create global properties create([&](global_property_object& p) { - p.chain_id = fc::digest(genesis_state); + p.chain_id = genesis_state.compute_chain_id(); p.parameters = genesis_state.initial_parameters; // Set fees to zero initially, so that genesis initialization needs not pay them // We'll fix it at the end of the function diff --git a/libraries/chain/genesis_state.cpp b/libraries/chain/genesis_state.cpp new file mode 100644 index 00000000..a8af8b56 --- /dev/null +++ b/libraries/chain/genesis_state.cpp @@ -0,0 +1,15 @@ + +#include + +// these are required to serialize a genesis_state +#include // required for gcc in release mode +#include + +namespace graphene { namespace chain { + +chain_id_type genesis_state_type::compute_chain_id() const +{ + return fc::sha256::hash( *this ); +} + +} } // graphene::chain diff --git a/libraries/chain/include/graphene/chain/genesis_state.hpp b/libraries/chain/include/graphene/chain/genesis_state.hpp index 2f30b8fc..b2594f5a 100644 --- a/libraries/chain/include/graphene/chain/genesis_state.hpp +++ b/libraries/chain/include/graphene/chain/genesis_state.hpp @@ -1,8 +1,11 @@ #pragma once #include +#include #include +#include + #include #include @@ -84,7 +87,15 @@ struct genesis_state_type { vector initial_witness_candidates; vector initial_committee_candidates; vector initial_worker_candidates; + + /** + * Get the chain_id corresponding to this genesis state. + * + * This is the SHA256 serialization of the genesis_state. + */ + chain_id_type compute_chain_id() const; }; + } } // namespace graphene::chain FC_REFLECT(graphene::chain::genesis_state_type::initial_account_type, (name)(owner_key)(active_key)(is_lifetime_member)) diff --git a/libraries/chain/include/graphene/chain/global_property_object.hpp b/libraries/chain/include/graphene/chain/global_property_object.hpp index addad7f9..7ad166f2 100644 --- a/libraries/chain/include/graphene/chain/global_property_object.hpp +++ b/libraries/chain/include/graphene/chain/global_property_object.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/libraries/chain/include/graphene/chain/protocol/chain_id.hpp b/libraries/chain/include/graphene/chain/protocol/chain_id.hpp new file mode 100644 index 00000000..05dc0cc5 --- /dev/null +++ b/libraries/chain/include/graphene/chain/protocol/chain_id.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#pragma once + +#include +#include + +namespace graphene { namespace chain { + +typedef fc::sha256 chain_id_type; + +/** + * Get the current chain ID. The chain ID is stored in a global + * variable. Accessing multiple Graphene-based chains from a single + * process is not supported. Returns the last chain ID set with + * set_current_chain_id(), or an invalid optional if never set. + */ +fc::optional get_current_chain_id(); + +/** + * Set the global chain ID. The chain ID is stored in a global + * variable. Accessing multiple Graphene-based chains from a single + * process is not supported. + */ +void set_current_chain_id( const fc::optional& chain_id ); + +} } diff --git a/libraries/chain/protocol/chain_id.cpp b/libraries/chain/protocol/chain_id.cpp new file mode 100644 index 00000000..41df6224 --- /dev/null +++ b/libraries/chain/protocol/chain_id.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +namespace graphene { namespace chain { + +chain_id_type the_chain_id; +bool the_chain_id_initialized = false; + +fc::optional< chain_id_type > get_current_chain_id() +{ + optional< chain_id_type > result; + if( the_chain_id_initialized ) + result = the_chain_id; + return result; +} + +void set_current_chain_id( const fc::optional& chain_id ) +{ + bool valid = chain_id.valid(); + the_chain_id_initialized = valid; + if( valid ) + the_chain_id = *chain_id; + return; +} + +} } // graphene::chain diff --git a/libraries/egenesis/CMakeLists.txt b/libraries/egenesis/CMakeLists.txt new file mode 100644 index 00000000..357d3599 --- /dev/null +++ b/libraries/egenesis/CMakeLists.txt @@ -0,0 +1,59 @@ + +add_library( graphene_egenesis_none + egenesis_none.cpp + include/graphene/egenesis/egenesis.hpp + ) + +target_link_libraries( graphene_egenesis_none graphene_chain fc ) +target_include_directories( graphene_egenesis_none + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +add_executable( embed_genesis + embed_genesis.cpp + ) + +target_link_libraries( embed_genesis graphene_chain graphene_egenesis_none graphene_app fc ) + +set( embed_genesis_args + -t "${CMAKE_CURRENT_SOURCE_DIR}/egenesis_brief.cpp.tmpl---${CMAKE_CURRENT_BINARY_DIR}/egenesis_brief.cpp" + -t "${CMAKE_CURRENT_SOURCE_DIR}/egenesis_full.cpp.tmpl---${CMAKE_CURRENT_BINARY_DIR}/egenesis_full.cpp" + ) + +MESSAGE( STATUS "egenesis: " ${GRAPHENE_EGENESIS_JSON} ) + +if( GRAPHENE_EGENESIS_JSON ) + list( APPEND embed_genesis_args --genesis-json "${GRAPHENE_EGENESIS_JSON}" ) +endif( GRAPHENE_EGENESIS_JSON ) + +MESSAGE( STATUS "embed_genesis_args: " ${embed_genesis_args} ) + +add_custom_command( + OUTPUT + "${CMAKE_CURRENT_BINARY_DIR}/egenesis_brief.cpp" + "${CMAKE_CURRENT_BINARY_DIR}/egenesis_full.cpp" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND "${CMAKE_CURRENT_BINARY_DIR}/embed_genesis" ${embed_genesis_args} + DEPENDS + "${GRAPHENE_EGENESIS_JSON}" + "${CMAKE_CURRENT_SOURCE_DIR}/egenesis_brief.cpp.tmpl" + "${CMAKE_CURRENT_SOURCE_DIR}/egenesis_full.cpp.tmpl" + embed_genesis ) + +add_library( graphene_egenesis_brief "${CMAKE_CURRENT_BINARY_DIR}/egenesis_brief.cpp" include/graphene/egenesis/egenesis.hpp ) +add_library( graphene_egenesis_full "${CMAKE_CURRENT_BINARY_DIR}/egenesis_full.cpp" include/graphene/egenesis/egenesis.hpp ) + +target_link_libraries( graphene_egenesis_brief graphene_chain fc ) +target_link_libraries( graphene_egenesis_full graphene_chain fc ) + +target_include_directories( graphene_egenesis_brief + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) +target_include_directories( graphene_egenesis_full + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) + +INSTALL( TARGETS + embed_genesis graphene_egenesis_none graphene_egenesis_brief graphene_egenesis_full + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/libraries/egenesis/egenesis_brief.cpp.tmpl b/libraries/egenesis/egenesis_brief.cpp.tmpl new file mode 100644 index 00000000..03d00a9b --- /dev/null +++ b/libraries/egenesis/egenesis_brief.cpp.tmpl @@ -0,0 +1,42 @@ +${generated_file_banner} +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace graphene { namespace chain { + +using namespace graphene::chain; + +chain_id_type get_egenesis_chain_id() +{ + return chain_id_type( "${chain_id}$" ); +} + +void compute_egenesis_json( std::string& result ) +{ + result = ""; +} + +fc::sha256 get_egenesis_json_hash() +{ + return fc::sha256( "${genesis_json_hash}" ); +} + +} } diff --git a/libraries/egenesis/egenesis_full.cpp.tmpl b/libraries/egenesis/egenesis_full.cpp.tmpl new file mode 100644 index 00000000..a5c41e8b --- /dev/null +++ b/libraries/egenesis/egenesis_full.cpp.tmpl @@ -0,0 +1,54 @@ +${generated_file_banner} +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace graphene { namespace egenesis { + +using namespace graphene::chain; + +static const char genesis_json_array[${genesis_json_array_height}$][${genesis_json_array_width}$+1] = +{ +${genesis_json_array}$ +}; + +chain_id_type get_egenesis_chain_id() +{ + return chain_id_type( "${chain_id}$" ); +} + +void compute_egenesis_json( std::string& result ) +{ + result.reserve( ${genesis_json_length}$ ); + result.resize(0); + for( size_t i=0; i<${genesis_json_array_height}$-1; i++ ) + { + result.append( genesis_json_array[i], ${genesis_json_array_width}$ ); + } + result.append( std::string( genesis_json_array[ ${genesis_json_array_height}$-1 ] ) ); + return; +} + +fc::sha256 get_egenesis_json_hash() +{ + return fc::sha256( "${genesis_json_hash}" ); +} + +} } diff --git a/libraries/egenesis/egenesis_none.cpp b/libraries/egenesis/egenesis_none.cpp new file mode 100644 index 00000000..3f293b64 --- /dev/null +++ b/libraries/egenesis/egenesis_none.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace graphene { namespace egenesis { + +using namespace graphene::chain; + +chain_id_type get_egenesis_chain_id() +{ + return chain_id_type(); +} + +void compute_egenesis_json( std::string& result ) +{ + result = ""; +} + +fc::sha256 get_egenesis_json_hash() +{ + return fc::sha256::hash( "" ); +} + +} } diff --git a/libraries/egenesis/embed_genesis.cpp b/libraries/egenesis/embed_genesis.cpp new file mode 100644 index 00000000..f3d1edd5 --- /dev/null +++ b/libraries/egenesis/embed_genesis.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015, Cryptonomex, Inc. + * All rights reserved. + * + * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and + * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, + * are permitted until September 8, 2015, provided that the following conditions are met: + * + * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include // required for gcc in release mode +#include +#include +#include +#include +#include + +// we need to include the world in order to serialize fee_parameters +#include + +using namespace graphene::chain; + +static const char generated_file_banner[] = +"// _ _ __ _ _ //\n" +"// | | | | / _(_) | //\n" +"// __ _ ___ _ __ ___ _ __ __ _| |_ ___ __| | | |_ _| | ___ //\n" +"// / _` |/ _ \\ '_ \\ / _ \\ '__/ _` | __/ _ \\/ _` | | _| | |/ _ \\ //\n" +"// | (_| | __/ | | | __/ | | (_| | || __/ (_| | | | | | | __/ //\n" +"// \\__, |\\___|_| |_|\\___|_| \\__,_|\\__\\___|\\__,_| |_| |_|_|\\___| //\n" +"// __/ | //\n" +"// |___/ //\n" +"// //\n" +"// Generated by: libraries/chain_id/identify_chain.cpp //\n" +"// //\n" +"// Warning: This is a generated file, any changes made here will be //\n" +"// overwritten by the build process. If you need to change what //\n" +"// is generated here, you should use the CMake variable //\n" +"// GRAPHENE_EGENESIS_JSON to specify an embedded genesis state. //\n" +"// //\n" +; + +// hack: import create_example_genesis() even though it's a way, way +// specific internal detail +namespace graphene { namespace app { namespace detail { +genesis_state_type create_example_genesis(); +} } } // graphene::app::detail + +fc::path get_path( + const boost::program_options::variables_map& options, + const std::string& name ) +{ + fc::path result = options[name].as(); + if( result.is_relative() ) + result = fc::current_path() / result; + return result; +} + +void convert_to_c_array( + const std::string& src, + std::string& dest, + int width = 40 ) +{ + dest.reserve( src.length() * 6 / 5 ); + bool needs_comma = false; + int row = 0; + for( std::string::size_type i=0; i': case '@': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '[': case ']': case '^': case '_': case '`': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case '{': case '|': case '}': case '~': + dest.append(&c, 1); + break; + + // use shortest octal escape for everything else + default: + dest.append("\\"); + char dg[3]; + dg[0] = '0' + ((c >> 6) & 3); + dg[1] = '0' + ((c >> 3) & 7); + dg[2] = '0' + ((c ) & 7); + int start = (dg[0] == '0' ? (dg[1] == '0' ? 2 : 1) : 0); + dest.append( dg+start, 3-start ); + } + } + dest.append("\""); + needs_comma = true; + row++; + } + std::cerr << "\n"; + return; +} + +struct egenesis_info +{ + fc::optional< genesis_state_type > genesis; + fc::optional< chain_id_type > chain_id; + fc::optional< std::string > genesis_json; + fc::optional< fc::sha256 > genesis_json_hash; + fc::optional< std::string > genesis_json_array; + int genesis_json_array_width, + genesis_json_array_height; + + void fillin() + { + // must specify either genesis_json or genesis + if( genesis.valid() ) + { + if( !genesis_json.valid() ) + // If genesis_json not exist, generate from genesis + genesis_json = fc::json::to_string( *genesis ); + } + else if( genesis_json.valid() ) + { + // If genesis not exist, generate from genesis_json + genesis = fc::json::from_string( *genesis_json ).as< genesis_state_type >(); + } + else + { + // Neither genesis nor genesis_json exists, crippled + std::cerr << "embed_genesis: Need genesis or genesis_json\n"; + exit(1); + } + // init chain_id from genesis + if( !chain_id.valid() ) + chain_id = genesis->compute_chain_id(); + // init genesis_json_hash from genesis_json + if( !genesis_json_hash.valid() ) + genesis_json_hash = fc::sha256::hash( *genesis_json ); + // init genesis_json_array from genesis_json + if( !genesis_json_array.valid() ) + { + genesis_json_array = std::string(); + // TODO: gzip + int width = 40; + convert_to_c_array( *genesis_json, *genesis_json_array, width ); + int height = (genesis_json->length() + width-1) / width; + genesis_json_array_width = width; + genesis_json_array_height = height; + } + } +}; + +void load_genesis( + const boost::program_options::variables_map& options, + egenesis_info& info + ) +{ + if( options.count("genesis-json") ) + { + fc::path genesis_json_filename = get_path( options, "genesis-json" ); + std::cerr << "chain_identifier: Reading genesis from file " << genesis_json_filename.preferred_string() << "\n"; + info.genesis_json = std::string(); + read_file_contents( genesis_json_filename, *info.genesis_json ); + } + else + info.genesis = graphene::app::detail::create_example_genesis(); + + if( options.count("chain-id") ) + { + std::string chain_id_str = options["chain-id"].as(); + std::cerr << "chain_identifier: Genesis ID from argument is " << chain_id_str << "\n"; + info.chain_id = chain_id_str; + } + return; +} + +int main( int argc, char** argv ) +{ + int main_return = 0; + boost::program_options::options_description cli_options("Graphene Chain Identifier"); + cli_options.add_options() + ("help,h", "Print this help message and exit.") + ("genesis-json,g", boost::program_options::value(), "File to read genesis state from") + ("tmplsub,t", boost::program_options::value >()->composing(), + "Given argument of form src.cpp.tmpl---dest.cpp, write dest.cpp expanding template invocations in src") + ; + + boost::program_options::variables_map options; + try + { + boost::program_options::store( boost::program_options::parse_command_line(argc, argv, cli_options), options ); + } + catch (const boost::program_options::error& e) + { + std::cerr << "chain_identifier: error parsing command line: " << e.what() << "\n"; + return 1; + } + + if( options.count("help") ) + { + std::cout << cli_options << "\n"; + return 0; + } + + egenesis_info info; + + load_genesis( options, info ); + info.fillin(); + + fc::mutable_variant_object template_context = fc::mutable_variant_object() + ( "generated_file_banner", generated_file_banner ) + ( "chain_id", (*info.chain_id).str() ) + ; + if( info.genesis_json.valid() ) + { + template_context["genesis_json_length"] = info.genesis_json->length(); + template_context["genesis_json_array"] = (*info.genesis_json_array); + template_context["genesis_json_hash"] = (*info.genesis_json_hash).str(); + template_context["genesis_json_array_width"] = info.genesis_json_array_width; + template_context["genesis_json_array_height"] = info.genesis_json_array_height; + } + + for( const std::string& src_dest : options["tmplsub"].as< std::vector< std::string > >() ) + { + std::cerr << "chain_identifier: parsing tmplsub parameter \"" << src_dest << "\"\n"; + size_t pos = src_dest.find( "---" ); + if( pos == std::string::npos ) + { + std::cerr << "chain_identifier: could not parse tmplsub parameter: '---' not found\n"; + main_return = 1; + continue; + } + std::string src = src_dest.substr( 0, pos ); + std::string dest = src_dest.substr( pos+3 ); + + std::string tmpl; + read_file_contents( fc::path( src ), tmpl ); + std::string out_str = fc::format_string( tmpl, template_context ); + fc::path dest_filename = fc::path( dest ); + fc::ofstream outfile( dest_filename ); + outfile.write( out_str.c_str(), out_str.size() ); + outfile.close(); + } + + return main_return; +} diff --git a/libraries/egenesis/include/graphene/egenesis/egenesis.hpp b/libraries/egenesis/include/graphene/egenesis/egenesis.hpp new file mode 100644 index 00000000..2e471de3 --- /dev/null +++ b/libraries/egenesis/include/graphene/egenesis/egenesis.hpp @@ -0,0 +1,28 @@ + +#pragma once + +#include + +#include +#include +#include + +namespace graphene { namespace egenesis { + +/** + * Get the chain ID of the built-in egenesis, or chain_id_type() + * if none was compiled in. + */ +graphene::chain::chain_id_type get_egenesis_chain_id(); + +/** + * Get the egenesis JSON, or the empty string if none was compiled in. + */ +void compute_egenesis_json( std::string& result ); + +/** + * The file returned by compute_egenesis_json() should have this hash. + */ +fc::sha256 get_egenesis_json_hash(); + +} } // graphene::egenesis diff --git a/programs/cli_full_wallet/CMakeLists.txt b/programs/cli_full_wallet/CMakeLists.txt index 098aa92d..3f7c72f1 100644 --- a/programs/cli_full_wallet/CMakeLists.txt +++ b/programs/cli_full_wallet/CMakeLists.txt @@ -10,7 +10,7 @@ if( GPERFTOOLS_FOUND ) endif() target_link_libraries( cli_full_wallet - PRIVATE graphene_witness graphene_account_history graphene_market_history graphene_app graphene_net graphene_chain graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_witness graphene_account_history graphene_market_history graphene_app graphene_net graphene_chain graphene_egenesis_full graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) if(MSVC) set_source_files_properties( main.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) diff --git a/programs/cli_wallet/CMakeLists.txt b/programs/cli_wallet/CMakeLists.txt index 0c5d580b..140bdce3 100644 --- a/programs/cli_wallet/CMakeLists.txt +++ b/programs/cli_wallet/CMakeLists.txt @@ -10,7 +10,7 @@ if( GPERFTOOLS_FOUND ) endif() target_link_libraries( cli_wallet - PRIVATE graphene_app graphene_net graphene_chain graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_app graphene_net graphene_chain graphene_egenesis_brief graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) if(MSVC) set_source_files_properties( main.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) diff --git a/programs/js_operation_serializer/CMakeLists.txt b/programs/js_operation_serializer/CMakeLists.txt index 40084608..dad8ded2 100644 --- a/programs/js_operation_serializer/CMakeLists.txt +++ b/programs/js_operation_serializer/CMakeLists.txt @@ -4,7 +4,7 @@ if( UNIX AND NOT APPLE ) endif() target_link_libraries( js_operation_serializer - PRIVATE graphene_app graphene_net graphene_chain graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_app graphene_net graphene_chain graphene_egenesis_none graphene_utilities graphene_wallet fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) install( TARGETS js_operation_serializer diff --git a/programs/light_client/CMakeLists.txt b/programs/light_client/CMakeLists.txt index c9bca410..eac86b39 100644 --- a/programs/light_client/CMakeLists.txt +++ b/programs/light_client/CMakeLists.txt @@ -34,7 +34,7 @@ if (CMAKE_VERSION VERSION_LESS 3.0) add_dependencies(light_client gen_qrc) endif() -target_link_libraries(light_client PRIVATE Qt5::Core Qt5::Widgets Qt5::Quick graphene_chain graphene_utilities fc graphene_app ) +target_link_libraries(light_client PRIVATE Qt5::Core Qt5::Widgets Qt5::Quick graphene_chain graphene_egenesis_brief graphene_utilities fc graphene_app ) install( TARGETS light_client diff --git a/programs/size_checker/CMakeLists.txt b/programs/size_checker/CMakeLists.txt index 0025afc3..5e0a167c 100644 --- a/programs/size_checker/CMakeLists.txt +++ b/programs/size_checker/CMakeLists.txt @@ -4,7 +4,7 @@ if( UNIX AND NOT APPLE ) endif() target_link_libraries( size_checker - PRIVATE graphene_chain fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_chain graphene_egenesis_none fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) install( TARGETS size_checker diff --git a/programs/witness_node/CMakeLists.txt b/programs/witness_node/CMakeLists.txt index c0f6a7c1..41bd784d 100644 --- a/programs/witness_node/CMakeLists.txt +++ b/programs/witness_node/CMakeLists.txt @@ -10,7 +10,7 @@ if( GPERFTOOLS_FOUND ) endif() target_link_libraries( witness_node - PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_chain fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) + PRIVATE graphene_app graphene_account_history graphene_market_history graphene_witness graphene_chain graphene_egenesis_full fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} ) install( TARGETS witness_node