diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 9079e543..76caf599 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -219,6 +219,15 @@ namespace detail { fc::remove_all(_data_dir / "blockchain/dblock"); } + void set_dbg_init_key( genesis_state_type& genesis, const std::string& init_key ) + { + flat_set< std::string > initial_witness_names; + public_key_type init_pubkey( init_key ); + for( uint64_t i=0; icount("genesis-json") ) { genesis_state_type genesis = fc::json::from_file(_options->at("genesis-json").as()).as(); + bool modified_genesis = false; if( _options->count("genesis-timestamp") ) { genesis.initial_timestamp = fc::time_point_sec( graphene::time::now() ) + genesis.initial_parameters.block_interval + _options->at("genesis-timestamp").as(); genesis.initial_timestamp -= genesis.initial_timestamp.sec_since_epoch() % genesis.initial_parameters.block_interval; + modified_genesis = true; std::cerr << "Used genesis timestamp: " << genesis.initial_timestamp.to_iso_string() << " (PLEASE RECORD THIS)\n"; } + if( _options->count("dbg-init-key") ) + { + std::string init_key = _options->at( "dbg-init-key" ).as(); + FC_ASSERT( genesis.initial_witness_candidates.size() >= genesis.initial_active_witnesses ); + set_dbg_init_key( genesis, init_key ); + modified_genesis = true; + std::cerr << "Set init witness key to " << init_key << "\n"; + } + if( modified_genesis ) + { + std::cerr << "WARNING: GENESIS WAS MODIFIED, YOUR CHAIN ID MAY BE DIFFERENT\n"; + } return genesis; } else @@ -610,6 +633,7 @@ void application::set_program_options(boost::program_options::options_descriptio ("server-pem,p", bpo::value()->implicit_value("server.pem"), "The TLS certificate file for this server") ("server-pem-password,P", bpo::value()->implicit_value(""), "Password for this certificate") ("genesis-json", bpo::value(), "File to read Genesis State from") + ("dbg-init-key", bpo::value(), "Block signing key to use for init witnesses, overrides genesis file") ("api-access", bpo::value(), "JSON file specifying API permissions") ; command_line_options.add(configuration_file_options); diff --git a/libraries/chain/block_database.cpp b/libraries/chain/block_database.cpp index c0005971..281dd387 100644 --- a/libraries/chain/block_database.cpp +++ b/libraries/chain/block_database.cpp @@ -237,4 +237,40 @@ optional block_database::last()const } return optional(); } + +optional block_database::last_id()const +{ + try + { + index_entry e; + _block_num_to_pos.seekg( 0, _block_num_to_pos.end ); + + if( _block_num_to_pos.tellp() < sizeof(index_entry) ) + return optional(); + + _block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end ); + _block_num_to_pos.read( (char*)&e, sizeof(e) ); + uint64_t pos = _block_num_to_pos.tellg(); + while( e.block_size == 0 && pos > 0 ) + { + pos -= sizeof(index_entry); + _block_num_to_pos.seekg( pos ); + _block_num_to_pos.read( (char*)&e, sizeof(e) ); + } + + if( e.block_size == 0 ) + return optional(); + + return e.block_id; + } + catch (const fc::exception&) + { + } + catch (const std::exception&) + { + } + return optional(); +} + + } } diff --git a/libraries/chain/db_management.cpp b/libraries/chain/db_management.cpp index baf4548b..c33b3ad1 100644 --- a/libraries/chain/db_management.cpp +++ b/libraries/chain/db_management.cpp @@ -58,12 +58,32 @@ void database::reindex(fc::path data_dir, const genesis_state_type& initial_allo for( uint32_t i = 1; i <= last_block_num; ++i ) { if( i % 2000 == 0 ) std::cerr << " " << double(i*100)/last_block_num << "% "< block = _block_id_to_block.fetch_by_number(i); + if( !block.valid() ) + { + wlog( "Reindexing terminated due to gap: Block ${i} does not exist!", ("i", i) ); + uint32_t dropped_count = 0; + while( true ) + { + fc::optional< block_id_type > last_id = _block_id_to_block.last_id(); + // this can trigger if we attempt to e.g. read a file that has block #2 but no block #1 + if( !last_id.valid() ) + break; + // we've caught up to the gap + if( block_header::num_from_id( *last_id ) <= i ) + break; + _block_id_to_block.remove( *last_id ); + dropped_count++; + } + wlog( "Dropped ${n} blocks from after the gap", ("n", dropped_count) ); + break; + } + apply_block(*block, skip_witness_signature | + skip_transaction_signatures | + skip_transaction_dupe_check | + skip_tapos_check | + skip_witness_schedule_check | + skip_authority_check); } _undo_db.enable(); auto end = fc::time_point::now(); diff --git a/libraries/chain/db_update.cpp b/libraries/chain/db_update.cpp index cccc3bb2..debb05a0 100644 --- a/libraries/chain/db_update.cpp +++ b/libraries/chain/db_update.cpp @@ -109,9 +109,7 @@ void database::clear_expired_transactions() //Transactions must have expired by at least two forking windows in order to be removed. auto& transaction_idx = static_cast(get_mutable_index(implementation_ids, impl_transaction_object_type)); const auto& dedupe_index = transaction_idx.indices().get(); - const auto& global_parameters = get_global_properties().parameters; - while( !dedupe_index.empty() - && head_block_time() - dedupe_index.rbegin()->trx.expiration >= fc::seconds(global_parameters.maximum_expiration) ) + while( (!dedupe_index.empty()) && (head_block_time() > dedupe_index.rbegin()->trx.expiration) ) transaction_idx.remove(*dedupe_index.rbegin()); } diff --git a/libraries/chain/get_config.cpp b/libraries/chain/get_config.cpp index 9f10ce78..1d81ecfb 100644 --- a/libraries/chain/get_config.cpp +++ b/libraries/chain/get_config.cpp @@ -45,7 +45,6 @@ fc::variant_object get_config() result[ "GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION" ] = GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION; result[ "GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL" ] = GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL; result[ "GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS" ] = GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS; - result[ "GRAPHENE_DEFAULT_MAX_EXPIRATION_SEC" ] = GRAPHENE_DEFAULT_MAX_EXPIRATION_SEC; result[ "GRAPHENE_MIN_UNDO_HISTORY" ] = GRAPHENE_MIN_UNDO_HISTORY; result[ "GRAPHENE_MAX_UNDO_HISTORY" ] = GRAPHENE_MAX_UNDO_HISTORY; result[ "GRAPHENE_MIN_BLOCK_SIZE_LIMIT" ] = GRAPHENE_MIN_BLOCK_SIZE_LIMIT; diff --git a/libraries/chain/include/graphene/chain/block_database.hpp b/libraries/chain/include/graphene/chain/block_database.hpp index 1e8a97a6..816df798 100644 --- a/libraries/chain/include/graphene/chain/block_database.hpp +++ b/libraries/chain/include/graphene/chain/block_database.hpp @@ -36,6 +36,7 @@ namespace graphene { namespace chain { optional fetch_optional( const block_id_type& id )const; optional fetch_by_number( uint32_t block_num )const; optional last()const; + optional last_id()const; private: mutable std::fstream _blocks; mutable std::fstream _block_num_to_pos; diff --git a/libraries/chain/include/graphene/chain/config.hpp b/libraries/chain/include/graphene/chain/config.hpp index 7256fbb2..3ad559ea 100644 --- a/libraries/chain/include/graphene/chain/config.hpp +++ b/libraries/chain/include/graphene/chain/config.hpp @@ -45,7 +45,6 @@ #define GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION (60*60*24) // seconds, aka: 1 day #define GRAPHENE_DEFAULT_MAINTENANCE_INTERVAL (60*60*24) // seconds, aka: 1 day #define GRAPHENE_DEFAULT_MAINTENANCE_SKIP_SLOTS 3 // number of slots to skip for maintenance interval -#define GRAPHENE_DEFAULT_MAX_EXPIRATION_SEC (60*60) // 1 hour #define GRAPHENE_MIN_UNDO_HISTORY 10 #define GRAPHENE_MAX_UNDO_HISTORY 1000 diff --git a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp index ac91d777..1f0e8d76 100644 --- a/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp +++ b/libraries/chain/include/graphene/chain/protocol/chain_parameters.hpp @@ -41,7 +41,7 @@ namespace graphene { namespace chain { uint32_t committee_proposal_review_period = GRAPHENE_DEFAULT_COMMITTEE_PROPOSAL_REVIEW_PERIOD_SEC; ///< minimum time in seconds that a proposed transaction requiring committee authority may not be signed, prior to expiration uint32_t maximum_transaction_size = GRAPHENE_DEFAULT_MAX_TRANSACTION_SIZE; ///< maximum allowable size in bytes for a transaction uint32_t maximum_block_size = GRAPHENE_DEFAULT_MAX_BLOCK_SIZE; ///< maximum allowable size in bytes for a block - uint32_t maximum_expiration = GRAPHENE_DEFAULT_MAX_EXPIRATION_SEC; ///< maximum number of seconds in the future a transaction may expire + uint32_t maximum_expiration = 0; ///< ignored, but included to ensure we don't hardfork; see #308 uint32_t maximum_time_until_expiration = GRAPHENE_DEFAULT_MAX_TIME_UNTIL_EXPIRATION; ///< maximum lifetime in seconds for transactions to be valid, before expiring uint32_t maximum_proposal_lifetime = GRAPHENE_DEFAULT_MAX_PROPOSAL_LIFETIME_SEC; ///< maximum lifetime in seconds for proposed transactions to be kept, before expiring uint8_t maximum_asset_whitelist_authorities = GRAPHENE_DEFAULT_MAX_ASSET_WHITELIST_AUTHORITIES; ///< maximum number of accounts which an asset may list as authorities for its whitelist OR blacklist