/* * 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 << "embed_genesis: 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 << "embed_genesis: 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 << "embed_genesis: 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 << "embed_genesis: parsing tmplsub parameter \"" << src_dest << "\"\n"; size_t pos = src_dest.find( "---" ); if( pos == std::string::npos ) { std::cerr << "embed_genesis: 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; }