diff --git a/.gitignore b/.gitignore index 36019a50cf..e253ec412e 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,4 @@ yosemite_bios/reset_yosemite_testnet_on_local.sh yosemite_bios/reset_std_token_yosemite_testnet_on_local.sh yosemite_bios/stop_yosemite_testnet_node_local.sh yosemite_bios/start_yosemite_testnet_node_local.sh +yosemite_bios/clean_data_yosemite_testnet_on_local.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 627f5c3e73..15c2b3dcdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") if (UNIX) if (APPLE) if (LLVM_DIR STREQUAL "" OR NOT LLVM_DIR) - set(LLVM_DIR "/usr/local/opt/llvm@4/lib/cmake/llvm") + set(LLVM_DIR "/usr/local/opt/llvm@4/lib/cmake/llvm/") endif() endif() endif() @@ -37,7 +37,7 @@ set( CXX_STANDARD_REQUIRED ON) set(VERSION_MAJOR 1) set(VERSION_MINOR 6) -set(VERSION_PATCH 0) +set(VERSION_PATCH 3) if(VERSION_SUFFIX) set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}") @@ -130,6 +130,9 @@ FIND_PACKAGE(Boost 1.67 REQUIRED COMPONENTS locale iostreams) +# Some new stdlibc++s will #error on +add_definitions(-DBOOST_ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW) + if( WIN32 ) message( STATUS "Configuring EOSIO on WIN32") @@ -243,7 +246,7 @@ message( STATUS "Using S(${YOSEMITE_NATIVE_TOKEN_PRECISION},${YOSEMITE_NATIVE_TO if ("${EOSIO_ROOT_KEY}" STREQUAL "") - set(EOSIO_ROOT_KEY "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV") + set(EOSIO_ROOT_KEY "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV") endif() message( STATUS "Using '${EOSIO_ROOT_KEY}' as public key for 'yosemite' account" ) diff --git a/Docker/Dockerfile b/Docker/Dockerfile index 774aba6e21..1552635380 100644 --- a/Docker/Dockerfile +++ b/Docker/Dockerfile @@ -1,11 +1,10 @@ FROM eosio/builder as builder -ARG repository_name=yosemite-public-blockchain ARG branch=master ARG native_token_symbol=DUSD ARG native_token_precision=4 -RUN git clone -b $branch https://github.com/YosemiteLabs/$repository_name.git --recursive \ - && cd $repository_name && echo "$branch:$(git rev-parse HEAD)" > /etc/yosemite-version \ +RUN git clone -b $branch https://github.com/YosemiteLabs/yosemite-public-blockchain.git --recursive \ + && cd yosemite-public-blockchain && echo "$branch:$(git rev-parse HEAD)" > /etc/yosemite-version \ && cmake -H. -B"/tmp/build" -GNinja -DCMAKE_BUILD_TYPE=Release -DWASM_ROOT=/opt/wasm -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_C_COMPILER=clang -DCMAKE_INSTALL_PREFIX=/tmp/build -DBUILD_MONGO_DB_PLUGIN=true \ -DYOSEMITE_NATIVE_TOKEN_SYMBOL_NAME=$native_token_symbol -DYOSEMITE_NATIVE_TOKEN_PRECISION=$native_token_precision \ @@ -17,9 +16,9 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install openssl COPY --from=builder /usr/local/lib/* /usr/local/lib/ COPY --from=builder /tmp/build/bin /opt/yosemite/bin COPY --from=builder /tmp/build/contracts /contracts -COPY --from=builder /$repository_name/Docker/config.ini / +COPY --from=builder /yosemite-public-blockchain/Docker/config.ini / COPY --from=builder /etc/yosemite-version /etc -COPY --from=builder /$repository_name/Docker/yosemited.sh /opt/yosemite/bin/yosemited.sh +COPY --from=builder /yosemite-public-blockchain/Docker/yosemited.sh /opt/yosemite/bin/yosemited.sh ENV EOSIO_ROOT=/opt/yosemite ENV YOSEMITE_ROOT=/opt/yosemite RUN chmod +x /opt/yosemite/bin/yosemited.sh diff --git a/Docker/README.md b/Docker/README.md index 8772fb609d..17b431eba9 100644 --- a/Docker/README.md +++ b/Docker/README.md @@ -20,10 +20,10 @@ cd yosemite-public-blockchain/Docker docker build . -t yosemitex/yosemite ``` -The above will build off the most recent commit to the master branch by default. If you would like to target a specific branch/tag, you may use a build argument. For example, if you wished to generate a docker image based off of the 1.6.0 tag, you could do the following: +The above will build off the most recent commit to the master branch by default. If you would like to target a specific branch/tag, you may use a build argument. For example, if you wished to generate a docker image based off of the 1.6.3 tag, you could do the following: ```bash -docker build -t yosemitex/yosemite:1.6.0 --build-arg branch=1.6.0 . +docker build -t yosemitex/yosemite:v1.6.3 --build-arg branch=v1.6.3 . ``` By default, the native token symbol is set to DUSD with precision 4. You can override this using the symbol argument while building the docker image. diff --git a/LICENSE b/LICENSE index 78ccd85f29..2189948e7b 100644 --- a/LICENSE +++ b/LICENSE @@ -17,9 +17,9 @@ met: 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: "Powered by YOSEMITE" or - "This product includes software developed by the Yosemite X Inc." + "This product includes software developed by Yosemite X Inc." - 4. Neither the name of the Yosemite X Inc. nor the names of its + 4. Neither the name of Yosemite X Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index 18c8013874..9559398409 100644 --- a/README.md +++ b/README.md @@ -85,13 +85,9 @@ even if it had been advised of the possibility of damage. ## Supported Operating Systems -1. Amazon 2017.09 and higher -2. Centos 7 -3. Fedora 25 and higher (Fedora 27 recommended) -4. Mint 18 -5. Ubuntu 16.04 (Ubuntu 16.10 recommended) -6. Ubuntu 18.04 -7. MacOS Darwin 10.12 and higher (MacOS 10.13.x recommended) +1. Centos 7 +2. Ubuntu 18.04 +3. MacOS 10.13 and higher (MacOS 10.14.x recommended) diff --git a/contracts/yosemitelib/system_depository.hpp b/contracts/yosemitelib/system_depository.hpp deleted file mode 100644 index 2d4e110e85..0000000000 --- a/contracts/yosemitelib/system_depository.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file - * @copyright defined in yosemite/LICENSE.txt - */ -#pragma once - -#include -#include -#include - -namespace yosemite { - - // system depository issuing native stable token - struct sys_depository_info { - account_name owner; - bool is_authorized = false; - std::string url; - uint16_t location = 0; - - uint64_t primary_key() const { return owner; } - - // explicit serialization macro is not necessary, used here only to improve compilation time - EOSLIB_SERIALIZE( sys_depository_info, (owner)(is_authorized) - (url)(location) ) - }; - - typedef eosio::multi_index< N(sysdepos), sys_depository_info > sys_depository_table; - - bool is_authorized_sys_depository( const account_name depository ) { - sys_depository_table depositories(YOSEMITE_SYSTEM_ACCOUNT, YOSEMITE_SYSTEM_ACCOUNT); - auto depo = depositories.find( depository ); - return depo != depositories.end() && (*depo).is_authorized; - } -} diff --git a/contracts/yosemitelib/transaction_vote.h b/contracts/yosemitelib/transaction_vote.h index 9d1f625c20..ccb96cb8a0 100644 --- a/contracts/yosemitelib/transaction_vote.h +++ b/contracts/yosemitelib/transaction_vote.h @@ -23,6 +23,7 @@ extern "C" { /** + * [Deprecated] * Cast Transaction Vote * @brief Contribute transaction voting from an action in current transaction context. * The vote amount is accumulated to the vote-to(candidate) account specified in the current transaction context. @@ -36,6 +37,7 @@ extern "C" { void cast_transaction_vote( uint32_t vote_amount ); /** + * [Deprecated] * Get transaction vote data accumulated in the head block (previous block) * @brief Get transaction votes sum data for each vote-to(candidate) account, * accumulated from the transactions in the previous block right before current pending block @@ -49,6 +51,39 @@ extern "C" { */ size_t read_head_block_trx_votes_data(char *buffer, size_t size); + + /** + * Get Top Transaction Vote Receivers + * @brief Retrieve top transaction vote receiver list from blockchain core. + * Transaction votes are processed and accrued for each vote target account on blockchain core by YOSEMITE Proof-of-Transaction/Transaction-as-a-Vote protocol + * Smart contract code including system contract can retrieve the top transaction vote receiver list + * sorted by the accumulated time-decaying weighted transaction vote amount for each tx vote receiver account. + * The whole list of transaction vote receivers can be arbitrarily long, + * so the sorted list can be retrieved by multiple function call with different offset_rank and limit parameter values. + * + * @param buffer - a buffer to write the top sorted transaction vote receiver list data to, + * returned buffer memory contains array of 'yosemite_tx_vote_stat_for_account' struct + * @param size - the size of the buffer, 0 to return required size + * @param offset_rank - offset-rank of first item in the returned list. offset-rank n means the returned list starts from the rank n+1 tx vote receiver. + * e.g. if offset_rank = 0, the first item in the returned list is the top 1 vote receiver. + * @param limit - max limit of the returned item count + * + * @return the size of the sorted transaction vote receiver list data written to the buffer (array of 'yosemite_tx_vote_stat_for_account' struct), + * or number of bytes that can be copied if size==0 passed + * @pre `buffer` is a valid pointer to a range of memory at least `size` bytes long + * @post `buffer` is filled with packed transaction vote receiver list data + */ + size_t get_top_transaction_vote_receivers( char *buffer, size_t size, uint32_t offset_rank, uint32_t limit ); + + /** + * Get Total Weighted Transaction Votes + * @brief Retrieve the total weighted (time-decaying) transaction vote amount accumulated for all blockchain transactions in the blockchain history + * + * @return total weighted transaction vote amount + */ + double get_total_weighted_transaction_votes(); + + ///@ } trxvoteapi } @@ -56,3 +91,9 @@ struct yosemite_transaction_vote { uint64_t to; // account name uint32_t amount; }; + +struct yosemite_tx_vote_stat_for_account { + uint64_t account; + double tx_votes_weighted; + uint64_t tx_votes; +}; diff --git a/contracts/yx.ntoken/yx.ntoken.cpp b/contracts/yx.ntoken/yx.ntoken.cpp index 7ed9773ab9..4e5910148f 100644 --- a/contracts/yx.ntoken/yx.ntoken.cpp +++ b/contracts/yx.ntoken/yx.ntoken.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +//#include #include namespace yosemite { namespace native_token { @@ -37,8 +37,8 @@ namespace yosemite { namespace native_token { eosio_assert(static_cast(memo.size() <= 256), "memo has more than 256 bytes"); require_auth(token.issuer); - eosio_assert(static_cast(is_authorized_sys_depository(token.issuer)), - "issuer account is not system depository"); + //eosio_assert(static_cast(is_authorized_sys_depository(token.issuer)), + // "issuer account is not system depository"); stats_native stats(get_self(), token.issuer); const auto &tstats = stats.find(NTOKEN_BASIC_STATS_KEY); @@ -75,8 +75,8 @@ namespace yosemite { namespace native_token { eosio_assert(static_cast(memo.size() <= 256), "memo has more than 256 bytes"); require_auth(token.issuer); - eosio_assert(static_cast(is_authorized_sys_depository(token.issuer)), - "issuer account is not system depository"); + //eosio_assert(static_cast(is_authorized_sys_depository(token.issuer)), + // "issuer account is not system depository"); stats_native stats(get_self(), token.issuer); const auto &tstats = stats.get(NTOKEN_BASIC_STATS_KEY, "createn for the issuer is not called"); diff --git a/contracts/yx.system/yx.block_producer.cpp b/contracts/yx.system/yx.block_producer.cpp index b5da2edc32..8003a48883 100644 --- a/contracts/yx.system/yx.block_producer.cpp +++ b/contracts/yx.system/yx.block_producer.cpp @@ -6,21 +6,16 @@ #include "yx.system.hpp" -#include -#include #include #include #include #include -#include #include namespace yosemitesys { - using yosemite::yx_asset; - // const uint32_t blocks_per_year = 52*7*24*2*3600; // half seconds per year // const uint32_t seconds_per_year = 52*7*24*3600; // const uint32_t blocks_per_day = 2 * 24 * 3600; @@ -54,81 +49,85 @@ namespace yosemitesys { }); } - /// read tran transaction votes sum data for each vote-to(candidate) account, - /// accumulated from the transactions in the previous block right before current pending block - uint32_t tx_votes_packed_size = read_head_block_trx_votes_data(nullptr, 0); - - if (tx_votes_packed_size > 0) { - - int cnt = tx_votes_packed_size / sizeof(struct yosemite_transaction_vote); - - /// allocate buffer memory through memory manager - char* buf_tx_votes_data_packed = static_cast(malloc(tx_votes_packed_size)); - eosio_assert( buf_tx_votes_data_packed != nullptr, "malloc failed for tx votes packed data" ); - - read_head_block_trx_votes_data(buf_tx_votes_data_packed, tx_votes_packed_size); - yosemite_transaction_vote* votes_arr = reinterpret_cast(buf_tx_votes_data_packed); - - for (int i = 0; i < cnt; i++) { - yosemite_transaction_vote &trx_vote = votes_arr[i]; - - auto prod_vote = _producers.find( trx_vote.to ); - - if (prod_vote != _producers.end()) { - _producers.modify( prod_vote, 0, [&]( producer_info& info ){ - double trx_vote_amount = static_cast(trx_vote.amount); - info.total_votes += trx_vote_amount; - _gstate.total_producer_vote += trx_vote_amount; - double weighted_vote_amount = weighted_vote(trx_vote.amount); - info.total_votes_weight += weighted_vote_amount; - _gstate.total_producer_vote_weight += weighted_vote_amount; - }); - } - } - - free(buf_tx_votes_data_packed); - } - /// only update block producers once every minute, block_timestamp is in half seconds if( timestamp.slot - _gstate.last_producer_schedule_update.slot > 120 ) { update_elected_producers( timestamp ); } } + const uint32_t top_tx_vote_receiver_list_fetch_count = 30; + void system_contract::update_elected_producers( block_timestamp block_time ) { - _gstate.last_producer_schedule_update = block_time; + _gstate.last_producer_schedule_update = block_time; - auto idx = _producers.get_index(); + std::vector< std::pair > top_producers; + top_producers.reserve( YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT ); - std::vector< std::pair > top_producers; - top_producers.reserve(YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT); + uint32_t offset_rank = 0; + uint32_t fetched_list_packed_size = get_top_transaction_vote_receivers(nullptr, 0, offset_rank, top_tx_vote_receiver_list_fetch_count); - for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT && 0 <= it->total_votes_weight && it->active() && it->is_trusted_seed; ++it ) { - top_producers.emplace_back( std::pair({{it->owner, it->producer_key}, it->location}) ); - } + while ( fetched_list_packed_size > 0 /*&& top_producers.size() < YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT*/ ) { + uint32_t fetched_cnt = fetched_list_packed_size / sizeof(struct yosemite_tx_vote_stat_for_account); + + /// allocate buffer memory through memory manager + char *buf_top_tx_vote_receivers_data_packed = static_cast(malloc(fetched_list_packed_size)); + eosio_assert(buf_top_tx_vote_receivers_data_packed != nullptr, "malloc failed for top tx vote receiver list packed data"); + + // fetch top tx vote account list from chain core + get_top_transaction_vote_receivers(buf_top_tx_vote_receivers_data_packed, fetched_list_packed_size, offset_rank, top_tx_vote_receiver_list_fetch_count); -// if ( top_producers.size() < _gstate.last_producer_schedule_size ) { + yosemite_tx_vote_stat_for_account *tx_vote_receiver_stat_arr = reinterpret_cast(buf_top_tx_vote_receivers_data_packed); + + for (uint32_t i = 0; i < fetched_cnt; i++) { + yosemite_tx_vote_stat_for_account &tx_vote_stat_for_account = tx_vote_receiver_stat_arr[i]; + + auto producer_itr = _producers.find( tx_vote_stat_for_account.account ); + if (producer_itr != _producers.cend()) { + if ( top_producers.size() < YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT && producer_itr->active() && producer_itr->is_trusted_seed ) { + top_producers.emplace_back(std::pair({{producer_itr->owner, producer_itr->producer_key}, producer_itr->location})); + + if ( top_producers.size() == YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT ) { + break; + } + } + } + } + + /// deallocate buffer memory + free(buf_top_tx_vote_receivers_data_packed); + + if ( top_producers.size() < YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT && fetched_cnt == top_tx_vote_receiver_list_fetch_count ) { + offset_rank += fetched_cnt; + fetched_list_packed_size = get_top_transaction_vote_receivers(nullptr, 0, offset_rank, top_tx_vote_receiver_list_fetch_count); + } else { + // if the fetched item count is less than requested fetch count, there is no more transaction vote receiver list items on blockchain core, + // and if max number of block producers are already selected as top producers, then there is no need to fetch additional transaction vote receiver list. + fetched_list_packed_size = 0; + } + } + + if ( top_producers.size() < _gstate.last_producer_schedule_size ) { + return; + } + +// if (top_producers.empty()) { // return; // } - if (top_producers.empty()) { - return; - } - - /// sort by producer name - std::sort( top_producers.begin(), top_producers.end() ); + /// sort by producer name + std::sort( top_producers.begin(), top_producers.end() ); - std::vector producers; + std::vector producers; - producers.reserve(top_producers.size()); - for( const auto& item : top_producers ) - producers.push_back(item.first); + producers.reserve(top_producers.size()); + for( const auto& item : top_producers ) + producers.push_back(item.first); - bytes packed_schedule = pack(producers); + bytes packed_schedule = pack(producers); - if( set_proposed_producers( packed_schedule.data(), packed_schedule.size() ) >= 0 ) { - _gstate.last_producer_schedule_size = static_cast( top_producers.size() ); - } + if( set_proposed_producers( packed_schedule.data(), packed_schedule.size() ) >= 0 ) { + _gstate.last_producer_schedule_size = static_cast( top_producers.size() ); + } } void system_contract::regproducer( const account_name producer, const eosio::public_key& producer_key, const std::string& url, uint16_t location ) { @@ -200,30 +199,7 @@ namespace yosemitesys { eosio_assert( prod.active(), "producer does not have an active key" ); eosio_assert( prod.is_trusted_seed, "producer is not trusted seed producer" ); - int64_t tx_fee_accumulated = native_token::get_total_native_token_balance(YOSEMITE_TX_FEE_ACCOUNT); - eosio_assert( tx_fee_accumulated > 0, "no tx fee accumulated"); - - auto ct = current_time(); - - eosio_assert( ct - prod.last_claim_time > useconds_per_day, "already claimed rewards within past day" ); - - int64_t producer_per_block_pay = 0; - if( _gstate.total_unpaid_blocks > 0 ) { - producer_per_block_pay = (tx_fee_accumulated * prod.unpaid_blocks) / _gstate.total_unpaid_blocks; - } - - _gstate.total_unpaid_blocks -= prod.unpaid_blocks; - - _producers.modify( prod, 0, [&](auto& p) { - p.last_claim_time = ct; - p.unpaid_blocks = 0; - }); - - if( producer_per_block_pay > 0 ) { - INLINE_ACTION_SENDER(yosemite::native_token::ntoken, transfer) - (YOSEMITE_NATIVE_TOKEN_ACCOUNT, {YOSEMITE_SYSTEM_ACCOUNT, N(active)}, - { YOSEMITE_TX_FEE_ACCOUNT, owner, asset(producer_per_block_pay, YOSEMITE_NATIVE_TOKEN_SYMBOL), "producer pay" }); - } + eosio_assert( false, "claimrewards not yet supported"); } } //namespace yosemitesys diff --git a/contracts/yx.system/yx.sys_depository.cpp b/contracts/yx.system/yx.sys_depository.cpp deleted file mode 100644 index f9e45f5896..0000000000 --- a/contracts/yx.system/yx.sys_depository.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "yx.system.hpp" - -#include -#include -#include - -#include - -namespace yosemitesys { - - using yosemite::sys_depository_info; - using yosemite::yx_asset; - - void system_contract::regsysdepo( const account_name depository, const std::string& url, uint16_t location ) { - - eosio_assert( url.size() < 512, "url too long" ); - require_auth( depository ); - - auto depo = _sys_depositories.find( depository ); - - if ( depo != _sys_depositories.end() ) { - _sys_depositories.modify( depo, depository, [&]( sys_depository_info& info ){ - info.is_authorized = false; - info.url = url; - info.location = location; - }); - } else { - _sys_depositories.emplace( depository, [&]( sys_depository_info& info ){ - info.owner = depository; - info.is_authorized = false; - info.url = url; - info.location = location; - }); - } - } - - void system_contract::authsysdepo( const account_name depository ) { - require_auth( _self ); - - auto depo = _sys_depositories.find( depository ); - - eosio_assert( depo != _sys_depositories.end(), "not found registered system depository" ); - eosio_assert( !depo->is_authorized, "system depository is already authorized" ); - - _sys_depositories.modify( depo, 0, [&]( sys_depository_info& info ){ - info.is_authorized = true; - }); - } - - void system_contract::rmvsysdepo( const account_name depository ) { - require_auth( _self ); - - auto depo = _sys_depositories.find( depository ); - - eosio_assert( depo != _sys_depositories.end(), "not found registered system depository" ); - eosio_assert( depo->is_authorized, "system depository is already unauthorized" ); - - _sys_depositories.modify( depo, 0, [&]( sys_depository_info& info ){ - info.is_authorized = false; - }); - } - -} //namespace yosemitesys diff --git a/contracts/yx.system/yx.system.abi b/contracts/yx.system/yx.system.abi index 824472fcbe..a40b818df8 100644 --- a/contracts/yx.system/yx.system.abi +++ b/contracts/yx.system/yx.system.abi @@ -196,15 +196,6 @@ {"name":"last_claim_time", "type":"uint64"}, {"name":"location", "type":"uint16"} ] - },{ - "name": "sys_depository_info", - "base": "", - "fields": [ - {"name":"owner", "type":"account_name"}, - {"name":"is_authorized", "type":"bool"}, - {"name":"url", "type":"string"}, - {"name":"location", "type":"uint16"} - ] },{ "name": "identity_authority_info", "base": "", @@ -253,26 +244,6 @@ "fields": [ {"name":"owner", "type":"account_name"} ] - },{ - "name": "regsysdepo", - "base": "", - "fields": [ - {"name":"depository", "type":"account_name"}, - {"name":"url", "type":"string"}, - {"name":"location", "type":"uint16"} - ] - },{ - "name": "authsysdepo", - "base": "", - "fields": [ - {"name":"depository", "type":"account_name"} - ] - },{ - "name": "rmvsysdepo", - "base": "", - "fields": [ - {"name":"depository", "type":"account_name"} - ] },{ "name": "regidauth", "base": "", @@ -445,18 +416,6 @@ "name": "claimrewards", "type": "claimrewards", "ricardian_contract": "" - },{ - "name": "regsysdepo", - "type": "regsysdepo", - "ricardian_contract": "" - },{ - "name": "authsysdepo", - "type": "authsysdepo", - "ricardian_contract": "" - },{ - "name": "rmvsysdepo", - "type": "rmvsysdepo", - "ricardian_contract": "" },{ "name": "regidauth", "type": "regidauth", @@ -492,12 +451,6 @@ "index_type": "i64", "key_names" : ["owner"], "key_types" : ["uint64"] - },{ - "name": "sysdepos", - "type": "sys_depository_info", - "index_type": "i64", - "key_names" : ["owner"], - "key_types" : ["uint64"] },{ "name": "idauthority", "type": "identity_authority_info", diff --git a/contracts/yx.system/yx.system.cpp b/contracts/yx.system/yx.system.cpp index c97cb9a461..6186ffaea6 100644 --- a/contracts/yx.system/yx.system.cpp +++ b/contracts/yx.system/yx.system.cpp @@ -7,11 +7,9 @@ #include "yx.system.hpp" #include #include -#include #include #include #include "yx.block_producer.cpp" -#include "yx.sys_depository.cpp" #include "yx.identity_authority.cpp" #include "yx.system_token.cpp" #include "yx.transaction_fee.cpp" @@ -22,7 +20,6 @@ namespace yosemitesys { system_contract::system_contract( account_name s ) :native(s), _producers(_self,_self), - _sys_depositories(_self,_self), _identity_authorities(_self,_self), _global(_self,_self) { @@ -106,8 +103,6 @@ EOSIO_ABI( yosemitesys::system_contract, (setram)(setparams)(setpriv) // yx.block_producer.cpp (onblock)(regproducer)(authproducer)(unregprod)(rmvproducer)(claimrewards) - // yx.sys_depository.cpp - (regsysdepo)(authsysdepo)(rmvsysdepo) // yx.identity_authority.cpp (regidauth)(authidauth)(rmvidauth) // yx.system_token.cpp diff --git a/contracts/yx.system/yx.system.hpp b/contracts/yx.system/yx.system.hpp index e0282163ab..0fd171696b 100644 --- a/contracts/yx.system/yx.system.hpp +++ b/contracts/yx.system/yx.system.hpp @@ -8,7 +8,6 @@ #include "yx.native.hpp" #include #include -#include #include #include #include @@ -24,7 +23,6 @@ namespace yosemitesys { using eosio::indexed_by; using eosio::const_mem_fun; using eosio::block_timestamp; - using yosemite::sys_depository_table; using yosemite::identity_authority_table; static const uint32_t YOSEMITE_MAX_ELECTED_BLOCK_PRODUCER_COUNT = 5; @@ -39,8 +37,8 @@ namespace yosemitesys { block_timestamp last_producer_schedule_update; uint32_t total_unpaid_blocks = 0; /// all blocks which have been produced but not paid uint16_t last_producer_schedule_size = 0; - double total_producer_vote = 0; /// the sum of all producer votes (un-weighted sum) - double total_producer_vote_weight = 0; /// the sum of all producer votes (weighted sum for vote decay) + /* deprecated */ double total_producer_vote = 0; /// the sum of all producer votes (un-weighted sum) + /* deprecated */ double total_producer_vote_weight = 0; /// the sum of all producer votes (weighted sum for vote decay) // explicit serialization macro is not necessary, used here only to improve compilation time EOSLIB_SERIALIZE_DERIVED( yosemite_global_state, eosio::blockchain_parameters, @@ -80,7 +78,6 @@ namespace yosemitesys { class system_contract : public native { private: producers_table _producers; - sys_depository_table _sys_depositories; identity_authority_table _identity_authorities; global_state_singleton _global; @@ -112,16 +109,6 @@ namespace yosemitesys { void claimrewards( const account_name& owner ); - - // System Depositories (yx.sys_depository.cpp) - - void regsysdepo( const account_name depository, const std::string& url, uint16_t location ); - - void authsysdepo( const account_name depository ); - - void rmvsysdepo( const account_name depository ); - - // Identity Authorities (yx.identity_authority.cpp) void regidauth( const account_name identity_authority, const std::string& url, uint16_t location ); diff --git a/eosio_build.sh b/eosio_build.sh index d16f56e657..b2dcc0c364 100644 --- a/eosio_build.sh +++ b/eosio_build.sh @@ -34,10 +34,14 @@ function usage() { - printf "\\tUsage: %s \\n\\t[Build Option -o ] \\n\\t[CodeCoverage -c] \\n\\t[Doxygen -d] \\n\\t[CoreSymbolName -s <1-7 characters>] \\n\\t[Avoid Compiling -a]\\n\\n" "$0" 1>&2 + printf "\\tUsage: %s \\n\\t[Build Option -o ] \\n\\t[CodeCoverage -c] \\n\\t[Doxygen -d] \\n\\t[CoreSymbolName -s <1-7 characters>] \\n\\t[Avoid Compiling -a]\\n\\t[Noninteractive -y]\\n\\n" "$0" 1>&2 exit 1 } + is_noninteractive() { + [[ -n "${EOSIO_BUILD_NONINTERACTIVE+1}" ]] + } + ARCH=$( uname ) if [ "${SOURCE_DIR}" == "${PWD}" ]; then BUILD_DIR="${PWD}/build" @@ -66,7 +70,7 @@ txtrst=$(tput sgr0) if [ $# -ne 0 ]; then - while getopts ":cdo:s:ah" opt; do + while getopts ":cdo:s:ahy" opt; do case "${opt}" in o ) options=( "Debug" "Release" "RelWithDebInfo" "MinSizeRel" ) @@ -100,6 +104,9 @@ usage exit 1 ;; + y) + EOSIO_BUILD_NONINTERACTIVE=1 + ;; \? ) printf "\\n\\tInvalid Option: %s\\n" "-${OPTARG}" 1>&2 usage diff --git a/libraries/chain/CMakeLists.txt b/libraries/chain/CMakeLists.txt index c53943dd12..d2b550d52d 100644 --- a/libraries/chain/CMakeLists.txt +++ b/libraries/chain/CMakeLists.txt @@ -44,6 +44,8 @@ add_library( eosio_chain yosemite/standard_token_manager.cpp yosemite/transaction_fee_manager.cpp + yosemite/softfloat64.cpp + yosemite/transaction_vote_stat_manager.cpp yosemite/standard_token_action_handlers.cpp # get_config.cpp diff --git a/libraries/chain/apply_context.cpp b/libraries/chain/apply_context.cpp index 0fea2e729c..118bf84678 100644 --- a/libraries/chain/apply_context.cpp +++ b/libraries/chain/apply_context.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include using boost::container::flat_set; @@ -431,12 +432,7 @@ bool apply_context::cancel_deferred_transaction( const uint128_t& sender_id, acc ////////////////////////////////////// /// YOSEMITE Core API - Proof-of-Transaction(PoT), Transaction-as-a-Vote(TaaV) -void apply_context::cast_transaction_vote(uint32_t vote_amount) { - // only system contracts on privileged account can call transaction vote API - require_authorization(config::system_account_name); - trx_context.add_transaction_vote(vote_amount); -} - +/// Deprecated vector apply_context::get_transaction_votes_in_head_block() const { auto head_block_ptr = control.head_block_state(); if (!head_block_ptr) { @@ -445,6 +441,14 @@ vector apply_context::get_transaction_votes_in_head_block() co return head_block_ptr->trx_votes.get_tx_vote_list(); } +vector apply_context::get_top_transaction_vote_receivers( const uint32_t offset_rank, const uint32_t limit ) const { + return control.get_tx_vote_stat_manager().get_top_sorted_transaction_vote_receivers( offset_rank, limit, false ).tx_vote_receiver_list; +} + +double apply_context::get_total_weighted_transaction_votes() const { + return control.get_tx_vote_stat_manager().get_total_weighted_transaction_vote_amount(); +} + ////////////////////////////////////// /// YOSEMITE Core API - Transaction-Fee diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index ea1e073826..2171bafc8c 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace eosio { namespace chain { @@ -133,6 +134,7 @@ struct controller_impl { authorization_manager authorization; standard_token_manager token; transaction_fee_manager txfee; + transaction_vote_stat_manager tx_vote_stat; controller::config conf; chain_id_type chain_id; bool replaying= false; @@ -159,7 +161,7 @@ struct controller_impl { * are removed from this list if they are re-applied in other blocks. Producers * can query this list when scheduling new transactions into blocks. */ - map unapplied_transactions; + unapplied_transactions_type unapplied_transactions; void pop_block() { auto prev = fork_db.get_block( head->header.previous ); @@ -202,8 +204,9 @@ struct controller_impl { wasmif( cfg.wasm_runtime ), resource_limits( db ), authorization( s, db ), - token ( db ), - txfee ( db ), + token( db ), + txfee( db ), + tx_vote_stat( db ), conf( cfg ), chain_id( cfg.genesis.compute_chain_id() ), read_mode( cfg.read_mode ), @@ -211,7 +214,7 @@ struct controller_impl { { #define SET_APP_HANDLER( receiver, contract, action) \ - set_apply_handler( #receiver, #contract, #action, &BOOST_PP_CAT(apply_, BOOST_PP_CAT(eosio, BOOST_PP_CAT(_,action) ) ) ) + set_apply_handler( #receiver, #contract, #action, &BOOST_PP_CAT(apply_, BOOST_PP_CAT(contract, BOOST_PP_CAT(_,action) ) ) ) SET_APP_HANDLER( yosemite, yosemite, newaccount ); SET_APP_HANDLER( yosemite, yosemite, setcode ); @@ -453,6 +456,7 @@ struct controller_impl { token.add_indices(); txfee.add_indices(); + tx_vote_stat.add_indices(); } void clear_all_undo() { @@ -557,6 +561,7 @@ struct controller_impl { token.add_to_snapshot(snapshot); txfee.add_to_snapshot(snapshot); + tx_vote_stat.add_to_snapshot(snapshot); } void read_from_snapshot( const snapshot_reader_ptr& snapshot ) { @@ -604,6 +609,7 @@ struct controller_impl { token.read_from_snapshot(snapshot); txfee.read_from_snapshot(snapshot); + tx_vote_stat.read_from_snapshot(snapshot); db.set_revision( head->block_num ); } @@ -695,6 +701,7 @@ struct controller_impl { token.initialize_database(); txfee.initialize_database(); + tx_vote_stat.initialize_database(); authority system_auth(conf.genesis.initial_key); create_native_account( config::system_account_name, system_auth, system_auth, true ); @@ -1051,6 +1058,9 @@ struct controller_impl { transaction_trace_ptr trace; try { auto start = fc::time_point::now(); + const bool check_auth = !self.skip_auth_check() && !trx->implicit; + // call recover keys so that trx->sig_cpu_usage is set correctly + const flat_set& recovered_keys = check_auth ? trx->recover_keys( chain_id ) : flat_set(); if( !explicit_billed_cpu_time ) { fc::microseconds already_consumed_time( EOS_PERCENT(trx->sig_cpu_usage.count(), conf.sig_cpu_bill_pct) ); @@ -1083,7 +1093,7 @@ struct controller_impl { trx_context.delay = fc::seconds(trn.delay_sec); - if( !self.skip_auth_check() && !trx->implicit ) { + if( check_auth ) { // YOSEMITE Transaction Fee Payer // The submitted transaction message must contain @@ -1100,12 +1110,10 @@ struct controller_impl { authorization.check_authorization( trn.actions, permissions_to_check, - trx->recover_keys( chain_id ), + recovered_keys, {}, trx_context.delay, - [](){} - /*std::bind(&transaction_context::add_cpu_usage_and_check_time, &trx_context, - std::placeholders::_1)*/, + [&trx_context](){ trx_context.checktime(); }, false ); } @@ -1810,6 +1818,16 @@ transaction_fee_manager& controller::get_mutable_tx_fee_manager() return my->txfee; } +const transaction_vote_stat_manager& controller::get_tx_vote_stat_manager()const +{ + return my->tx_vote_stat; +} + +transaction_vote_stat_manager& controller::get_mutable_tx_vote_stat_manager() +{ + return my->tx_vote_stat; +} + controller::controller( const controller::config& cfg ) :my( new controller_impl( cfg, *this ) ) { @@ -2213,41 +2231,12 @@ const account_object& controller::get_account( account_name name )const return my->db.get(name); } FC_CAPTURE_AND_RETHROW( (name) ) } -vector controller::get_unapplied_transactions() const { - vector result; - if ( my->read_mode == db_read_mode::SPECULATIVE ) { - result.reserve(my->unapplied_transactions.size()); - for ( const auto& entry: my->unapplied_transactions ) { - result.emplace_back(entry.second); - } - } else { - EOS_ASSERT( my->unapplied_transactions.empty(), transaction_exception, "not empty unapplied_transactions in non-speculative mode" ); //should never happen - } - return result; -} - -void controller::drop_unapplied_transaction(const transaction_metadata_ptr& trx) { - my->unapplied_transactions.erase(trx->signed_id); -} - -void controller::drop_all_unapplied_transactions() { - my->unapplied_transactions.clear(); -} - -vector controller::get_scheduled_transactions() const { - const auto& idx = db().get_index(); - - vector result; - - static const size_t max_reserve = 64; - result.reserve(std::min(idx.size(), max_reserve)); - - auto itr = idx.begin(); - while( itr != idx.end() && itr->delay_until <= pending_block_time() ) { - result.emplace_back(itr->trx_id); - ++itr; +unapplied_transactions_type& controller::get_unapplied_transactions() { + if ( my->read_mode != db_read_mode::SPECULATIVE ) { + EOS_ASSERT( my->unapplied_transactions.empty(), transaction_exception, + "not empty unapplied_transactions in non-speculative mode" ); //should never happen } - return result; + return my->unapplied_transactions; } bool controller::sender_avoids_whitelist_blacklist_enforcement( account_name sender )const { diff --git a/libraries/chain/eosio_contract.cpp b/libraries/chain/eosio_contract.cpp index f3d164fec5..0a1e46579f 100644 --- a/libraries/chain/eosio_contract.cpp +++ b/libraries/chain/eosio_contract.cpp @@ -67,7 +67,7 @@ void validate_authority_precondition( const apply_context& context, const author /** * This method is called assuming precondition_system_newaccount succeeds a */ -void apply_eosio_newaccount(apply_context& context) { +void apply_yosemite_newaccount(apply_context& context) { auto create = context.act.data_as(); try { context.require_authorization(create.creator); @@ -127,7 +127,7 @@ void apply_eosio_newaccount(apply_context& context) { } FC_CAPTURE_AND_RETHROW( (create) ) } -void apply_eosio_setcode(apply_context& context) { +void apply_yosemite_setcode(apply_context& context) { const auto& cfg = context.control.get_global_properties().configuration; auto& db = context.db; @@ -174,7 +174,7 @@ void apply_eosio_setcode(apply_context& context) { } } -void apply_eosio_setabi(apply_context& context) { +void apply_yosemite_setabi(apply_context& context) { auto& db = context.db; auto act = context.act.data_as(); @@ -205,7 +205,7 @@ void apply_eosio_setabi(apply_context& context) { } } -void apply_eosio_updateauth(apply_context& context) { +void apply_yosemite_updateauth(apply_context& context) { auto update = context.act.data_as(); context.require_authorization(update.account); // only here to mark the single authority on this action as used @@ -269,7 +269,7 @@ void apply_eosio_updateauth(apply_context& context) { } } -void apply_eosio_deleteauth(apply_context& context) { +void apply_yosemite_deleteauth(apply_context& context) { // context.require_write_lock( config::eosio_auth_scope ); auto remove = context.act.data_as(); @@ -300,7 +300,7 @@ void apply_eosio_deleteauth(apply_context& context) { } -void apply_eosio_linkauth(apply_context& context) { +void apply_yosemite_linkauth(apply_context& context) { // context.require_write_lock( config::eosio_auth_scope ); auto requirement = context.act.data_as(); @@ -348,7 +348,7 @@ void apply_eosio_linkauth(apply_context& context) { } FC_CAPTURE_AND_RETHROW((requirement)) } -void apply_eosio_unlinkauth(apply_context& context) { +void apply_yosemite_unlinkauth(apply_context& context) { // context.require_write_lock( config::eosio_auth_scope ); auto& db = context.db; @@ -367,7 +367,7 @@ void apply_eosio_unlinkauth(apply_context& context) { db.remove(*link); } -void apply_eosio_canceldelay(apply_context& context) { +void apply_yosemite_canceldelay(apply_context& context) { auto cancel = context.act.data_as(); context.require_authorization(cancel.canceling_auth.actor); // only here to mark the single authority on this action as used diff --git a/libraries/chain/include/eosio/chain/apply_context.hpp b/libraries/chain/include/eosio/chain/apply_context.hpp index d3925b3455..2c7343bcdc 100644 --- a/libraries/chain/include/eosio/chain/apply_context.hpp +++ b/libraries/chain/include/eosio/chain/apply_context.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -489,13 +490,16 @@ class apply_context { /// YOSEMITE Core API - Proof-of-Transaction(PoT), Transaction-as-a-Vote(TaaV) public: - - /// contribute transaction voting from an action in current transaction - void cast_transaction_vote(uint32_t vote_amount); - + /// Deprecated /// get transaction vote data accumulated in the head block (previous block) vector get_transaction_votes_in_head_block() const; + /// get top sorted transaction vote receiver list + vector get_top_transaction_vote_receivers( const uint32_t offset_rank, const uint32_t limit ) const; + + /// get total weighted transaction vote amount summed up + double get_total_weighted_transaction_votes() const; + /// YOSEMITE Core API - Transaction-Fee public: diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 094fc6ff6a..8c98353f76 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -23,6 +23,7 @@ namespace yosemite { namespace chain { class yosemite_global_property_object; class standard_token_manager; class transaction_fee_manager; + class transaction_vote_stat_manager; } } namespace eosio { namespace chain { @@ -43,6 +44,7 @@ namespace eosio { namespace chain { class account_object; using resource_limits::resource_limits_manager; using apply_handler = std::function; + using unapplied_transactions_type = map; class fork_database; @@ -121,22 +123,9 @@ namespace eosio { namespace chain { * The caller is responsible for calling drop_unapplied_transaction on a failing transaction that * they never intend to retry * - * @return vector of transactions which have been unapplied + * @return map of transactions which have been unapplied */ - vector get_unapplied_transactions() const; - void drop_unapplied_transaction(const transaction_metadata_ptr& trx); - void drop_all_unapplied_transactions(); - - /** - * These transaction IDs represent transactions available in the head chain state as scheduled - * or otherwise generated transactions. - * - * calling push_scheduled_transaction with these IDs will remove the associated transaction from - * the chain state IFF it succeeds or objectively fails - * - * @return - */ - vector get_scheduled_transactions() const; + unapplied_transactions_type& get_unapplied_transactions(); /** * @@ -176,6 +165,9 @@ namespace eosio { namespace chain { yosemite::chain::standard_token_manager& get_mutable_token_manager(); const yosemite::chain::transaction_fee_manager& get_tx_fee_manager()const; yosemite::chain::transaction_fee_manager& get_mutable_tx_fee_manager(); + const yosemite::chain::transaction_vote_stat_manager& get_tx_vote_stat_manager()const; + yosemite::chain::transaction_vote_stat_manager& get_mutable_tx_vote_stat_manager(); + const flat_set& get_actor_whitelist() const; const flat_set& get_actor_blacklist() const; diff --git a/libraries/chain/include/eosio/chain/eosio_contract.hpp b/libraries/chain/include/eosio/chain/eosio_contract.hpp index 1bf9163827..5f5d62bede 100644 --- a/libraries/chain/include/eosio/chain/eosio_contract.hpp +++ b/libraries/chain/include/eosio/chain/eosio_contract.hpp @@ -15,22 +15,22 @@ namespace eosio { namespace chain { * @defgroup native_action_handlers Native Action Handlers */ ///@{ - void apply_eosio_newaccount(apply_context&); - void apply_eosio_updateauth(apply_context&); - void apply_eosio_deleteauth(apply_context&); - void apply_eosio_linkauth(apply_context&); - void apply_eosio_unlinkauth(apply_context&); + void apply_yosemite_newaccount(apply_context&); + void apply_yosemite_updateauth(apply_context&); + void apply_yosemite_deleteauth(apply_context&); + void apply_yosemite_linkauth(apply_context&); + void apply_yosemite_unlinkauth(apply_context&); /* - void apply_eosio_postrecovery(apply_context&); - void apply_eosio_passrecovery(apply_context&); - void apply_eosio_vetorecovery(apply_context&); + void apply_yosemite_postrecovery(apply_context&); + void apply_yosemite_passrecovery(apply_context&); + void apply_yosemite_vetorecovery(apply_context&); */ - void apply_eosio_setcode(apply_context&); - void apply_eosio_setabi(apply_context&); + void apply_yosemite_setcode(apply_context&); + void apply_yosemite_setabi(apply_context&); - void apply_eosio_canceldelay(apply_context&); + void apply_yosemite_canceldelay(apply_context&); ///@} end action handlers } } /// namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/transaction_context.hpp b/libraries/chain/include/eosio/chain/transaction_context.hpp index c8accdf356..2799f9b738 100644 --- a/libraries/chain/include/eosio/chain/transaction_context.hpp +++ b/libraries/chain/include/eosio/chain/transaction_context.hpp @@ -66,7 +66,7 @@ namespace eosio { namespace chain { public: /// YOSEMITE Proof-of-Transaction, Transaction-as-a-Vote - void add_transaction_vote(transaction_vote_amount_type vote_amount); + void cast_transaction_vote(transaction_vote_amount_type vote_amount); bool has_transaction_vote() const; const transaction_vote& get_transaction_vote() const; diff --git a/libraries/chain/include/eosio/chain/types.hpp b/libraries/chain/include/eosio/chain/types.hpp index ed8526490f..7a886db818 100644 --- a/libraries/chain/include/eosio/chain/types.hpp +++ b/libraries/chain/include/eosio/chain/types.hpp @@ -192,7 +192,8 @@ namespace eosio { namespace chain { yosemite_global_property_object_type, yosemite_token_meta_object_type, yosemite_token_balance_object_type, - yosemite_transaction_fee_object_type + yosemite_transaction_fee_object_type, + yosemite_received_transaction_votes_object_type }; class account_object; diff --git a/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp b/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp index f5ebf01c1f..a67ca9ef69 100644 --- a/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp +++ b/libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp @@ -272,7 +272,7 @@ namespace eosio { namespace chain { namespace wasm_injections { }; - struct call_depth_check { + struct call_depth_check_and_insert_checktime { static constexpr bool kills = true; static constexpr bool post = false; static int32_t global_idx; @@ -290,6 +290,7 @@ namespace eosio { namespace chain { namespace wasm_injections { injector_utils::add_import(*(arg.module), "call_depth_assert", assert_idx); wasm_ops::op_types<>::call_t call_assert; + wasm_ops::op_types<>::call_t call_checktime; wasm_ops::op_types<>::get_global_t get_global_inst; wasm_ops::op_types<>::set_global_t set_global_inst; @@ -301,6 +302,7 @@ namespace eosio { namespace chain { namespace wasm_injections { wasm_ops::op_types<>::else__t else_inst; call_assert.field = assert_idx; + call_checktime.field = checktime_injection::chktm_idx; get_global_inst.field = global_idx; set_global_inst.field = global_idx; const_inst.field = -1; @@ -334,6 +336,7 @@ namespace eosio { namespace chain { namespace wasm_injections { INSERT_INJECTED(const_inst); INSERT_INJECTED(add_inst); INSERT_INJECTED(set_global_inst); + INSERT_INJECTED(call_checktime); #undef INSERT_INJECTED } @@ -679,8 +682,8 @@ namespace eosio { namespace chain { namespace wasm_injections { }; struct pre_op_injectors : wasm_ops::op_types { - using call_t = wasm_ops::call ; - using call_indirect_t = wasm_ops::call_indirect ; + using call_t = wasm_ops::call ; + using call_indirect_t = wasm_ops::call_indirect ; // float binops using f32_add_t = wasm_ops::f32_add >; @@ -785,7 +788,7 @@ namespace eosio { namespace chain { namespace wasm_injections { // initialize static fields of injectors injector_utils::init( mod ); checktime_injection::init(); - call_depth_check::init(); + call_depth_check_and_insert_checktime::init(); } void inject() { diff --git a/libraries/chain/include/yosemite/chain/received_transaction_votes_database.hpp b/libraries/chain/include/yosemite/chain/received_transaction_votes_database.hpp new file mode 100644 index 0000000000..754940057c --- /dev/null +++ b/libraries/chain/include/yosemite/chain/received_transaction_votes_database.hpp @@ -0,0 +1,48 @@ +/** + * @file yosemite/chain/received_transaction_votes_database.hpp + * @author bezalel@yosemitex.com + * @copyright defined in yosemite/LICENSE.txt + */ +#pragma once + +#include +#include + +namespace yosemite { namespace chain { + + using namespace eosio::chain; + + using tx_votes_sum_type = uint64_t; //eosio::chain::int128_t; // share_type + using tx_votes_sum_weighted_type = double; + + /** + * @brief received transaction votes statistics for an account + */ + class received_transaction_votes_object : public chainbase::object { + OBJECT_CTOR(received_transaction_votes_object) + + id_type id; + account_name account; // transaction vote target account + tx_votes_sum_weighted_type tx_votes_weighted = 0.0; // weighted (time-decaying) sum of received transaction votes + tx_votes_sum_type tx_votes = 0; // sum of received transaction votes + uint64_t reserved = 0; + }; + + struct by_tx_votes_account; + struct by_tx_votes_weighted; + + using received_transaction_votes_multi_index = chainbase::shared_multi_index_container< + received_transaction_votes_object, + indexed_by< + ordered_unique< tag, member >, + ordered_unique< tag, member>, + ordered_non_unique< tag, member> + > + >; + +} } /// yosemite::chain + + +CHAINBASE_SET_INDEX_TYPE(yosemite::chain::received_transaction_votes_object, yosemite::chain::received_transaction_votes_multi_index) + +FC_REFLECT(yosemite::chain::received_transaction_votes_object, (account)(tx_votes)(tx_votes_weighted)(reserved)) diff --git a/libraries/chain/include/yosemite/chain/softfloat64.hpp b/libraries/chain/include/yosemite/chain/softfloat64.hpp new file mode 100644 index 0000000000..4f9b1d5b90 --- /dev/null +++ b/libraries/chain/include/yosemite/chain/softfloat64.hpp @@ -0,0 +1,61 @@ +/** + * @file yosemite/chain/received_transaction_votes_database.hpp + * @author bezalel@yosemitex.com + * @copyright defined in yosemite/LICENSE.txt + */ +#pragma once + +#include + +namespace yosemite { namespace chain { + + class softfloat64 { + public: + static double add( double a, double b ) { + float64_t ret = f64_add( to_softfloat64(a), to_softfloat64(b) ); + return from_softfloat64(ret); + } + + static double sub( double a, double b ) { + float64_t ret = f64_sub( to_softfloat64(a), to_softfloat64(b) ); + return from_softfloat64(ret); + } + + static double div( double a, double b ) { + float64_t ret = f64_div( to_softfloat64(a), to_softfloat64(b) ); + return from_softfloat64(ret); + } + + static double mul( double a, double b ) { + float64_t ret = f64_mul( to_softfloat64(a), to_softfloat64(b) ); + return from_softfloat64(ret); + } + + static float64_t fromRaw( const uint64_t a ) { float64_t x; x.v = a; return x; } + + static float64_t zero() { return softfloat64::fromRaw( 0 ); } + + static float64_t inf() { return softfloat64::fromRaw( (uint_fast64_t)(0x7FF) << 52 ); } + + static float64_t one() { return softfloat64::fromRaw( (uint_fast64_t)(1023) << 52 ); } + + static float64_t nan() { return softfloat64::fromRaw( 0x7FFFFFFFFFFFFFFFLL ); } + + static bool isInf( float64_t a ) { return (a.v & 0x7fffffffffffffff) == 0x7ff0000000000000; } + + static bool isNaN( float64_t a ) { return (a.v & 0x7fffffffffffffff) > 0x7ff0000000000000; } + + static float64_t abs( float64_t a ) { float64_t x; x.v = a.v & ((1ULL << 63) - 1); return x; } + + static float64_t negate( float64_t a ) { float64_t x; x.v = a.v ^ (1ULL << 63); return x; } + + static float64_t pow( float64_t x, float64_t y ); + + static float64_t powi( float64_t x, int y ); + + static float64_t exp( float64_t x ); + + static float64_t log( float64_t x ); + }; + +} } /// yosemite::chain \ No newline at end of file diff --git a/libraries/chain/include/yosemite/chain/transaction_as_a_vote.hpp b/libraries/chain/include/yosemite/chain/transaction_as_a_vote.hpp index 6f15462a69..ebe1e9ab30 100644 --- a/libraries/chain/include/yosemite/chain/transaction_as_a_vote.hpp +++ b/libraries/chain/include/yosemite/chain/transaction_as_a_vote.hpp @@ -145,5 +145,7 @@ namespace yosemite { namespace chain { } } /// yosemite::chain +#define YOSEMITE_MAX_TRANSACTION_FEE_AMOUNT_PER_TRANSACTION 1000000000 + FC_REFLECT(yosemite::chain::transaction_vote, (to)(amt)) FC_REFLECT(yosemite::chain::transaction_votes_in_block, (tx_votes)) \ No newline at end of file diff --git a/libraries/chain/include/yosemite/chain/transaction_vote_stat_manager.hpp b/libraries/chain/include/yosemite/chain/transaction_vote_stat_manager.hpp new file mode 100644 index 0000000000..40167eea19 --- /dev/null +++ b/libraries/chain/include/yosemite/chain/transaction_vote_stat_manager.hpp @@ -0,0 +1,63 @@ +/** + * @file yosemite/chain/received_transaction_votes_manager.hpp + * @author bezalel@yosemitex.com + * @copyright defined in yosemite/LICENSE.txt + */ +#pragma once + +#include +#include + +#include +#include +#include + +#include + +namespace yosemite { namespace chain { + + using namespace eosio::chain; + + struct tx_vote_stat_for_account { + tx_vote_stat_for_account( account_name a, tx_votes_sum_weighted_type wv, tx_votes_sum_type v ) + : account(a), tx_votes_weighted(wv), tx_votes(v) {} + + account_name account; + tx_votes_sum_weighted_type tx_votes_weighted; + tx_votes_sum_type tx_votes; + }; + + struct tx_vote_receiver_list_result { + vector tx_vote_receiver_list; + tx_votes_sum_weighted_type total_tx_votes_weighted = 0.0; + tx_votes_sum_type total_tx_votes = 0; + bool more = false; + }; + + class transaction_vote_stat_manager { + public: + explicit transaction_vote_stat_manager( chainbase::database &db ); + + void add_indices(); + void initialize_database(); + void add_to_snapshot( const snapshot_writer_ptr &snapshot ) const; + void read_from_snapshot( const snapshot_reader_ptr &snapshot ); + + void add_transaction_vote_to_target_account( transaction_context& context, const account_name vote_target_account, const transaction_vote_amount_type tx_vote_amount ); + + tx_votes_sum_weighted_type get_total_weighted_transaction_vote_amount() const; + + tx_vote_stat_for_account get_transaction_vote_stat_for_account( const transaction_vote_to_name_type vote_target_account ) const; + + tx_vote_receiver_list_result get_top_sorted_transaction_vote_receivers( const uint32_t offset_rank, const uint32_t limit, const bool retrieve_total_votes ) const; + + private: + double weighted_tx_vote_time_decayed( uint32_t curren_block_time_sec, uint32_t vote ); + + chainbase::database &_db; + }; + +} } /// yosemite::chain + +FC_REFLECT(yosemite::chain::tx_vote_stat_for_account, (account)(tx_votes_weighted)(tx_votes)) +FC_REFLECT(yosemite::chain::tx_vote_receiver_list_result, (tx_vote_receiver_list)(total_tx_votes_weighted)(total_tx_votes)(more)) diff --git a/libraries/chain/include/yosemite/chain/yosemite_global_property_database.hpp b/libraries/chain/include/yosemite/chain/yosemite_global_property_database.hpp index 4a1f113c93..ad70420ea2 100644 --- a/libraries/chain/include/yosemite/chain/yosemite_global_property_database.hpp +++ b/libraries/chain/include/yosemite/chain/yosemite_global_property_database.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace yosemite { namespace chain { @@ -18,6 +19,10 @@ namespace yosemite { namespace chain { id_type id; shared_system_token_list_type system_token_list; + tx_votes_sum_weighted_type total_tx_votes_weighted = 0.0; /// the sum of all transaction votes (weighted sum for vote decay) + tx_votes_sum_type total_tx_votes = 0; /// the sum of all transaction votes (un-weighted sum) + uint64_t reserved1 = 0; + uint64_t reserved2 = 0; }; using yosemite_global_property_multi_index = chainbase::shared_multi_index_container< @@ -31,4 +36,4 @@ namespace yosemite { namespace chain { CHAINBASE_SET_INDEX_TYPE(yosemite::chain::yosemite_global_property_object, yosemite::chain::yosemite_global_property_multi_index) -FC_REFLECT(yosemite::chain::yosemite_global_property_object, (system_token_list)) +FC_REFLECT(yosemite::chain::yosemite_global_property_object, (system_token_list)(total_tx_votes_weighted)(total_tx_votes)(reserved1)(reserved2)) diff --git a/libraries/chain/transaction_context.cpp b/libraries/chain/transaction_context.cpp index 8f9271e037..6816fcec10 100644 --- a/libraries/chain/transaction_context.cpp +++ b/libraries/chain/transaction_context.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include #pragma push_macro("N") #undef N @@ -398,7 +400,8 @@ namespace bacc = boost::accumulators; txfee_to_pay += tx_fee_for_action( txfee_manager, act_trace ); } - EOS_ASSERT( txfee_to_pay >= 0, yosemite_transaction_fee_exception, "transaction fee amount must be greater than 0" ); + EOS_ASSERT( txfee_to_pay >= 0, yosemite_transaction_fee_exception, "transaction fee amount must be greater than or equal to 0" ); + EOS_ASSERT( txfee_to_pay <= YOSEMITE_MAX_TRANSACTION_FEE_AMOUNT_PER_TRANSACTION, yosemite_transaction_fee_exception, "transaction fee amount exceeds max transaction fee amount per transaction" ); // if (txfee_to_pay == 0) { // txfee_to_pay = txfee_manager.get_default_tx_fee().value; @@ -406,8 +409,13 @@ namespace bacc = boost::accumulators; if ( txfee_to_pay > 0 ) { EOS_ASSERT( !fee_payer.empty(), invalid_trx_fee_payer_account, "transaction fee payer field is required" ); + + uint32_t tx_fee_amount = static_cast(txfee_to_pay); // dispatch 'txfee' actions to system token accounts - control.get_mutable_token_manager().pay_transaction_fee( *this, fee_payer, static_cast(txfee_to_pay) ); + control.get_mutable_token_manager().pay_transaction_fee( *this, fee_payer, tx_fee_amount ); + + // Cast Transaction Vote - YOSEMITE Proof-of-Transaction / Transaction-as-a-Vote + cast_transaction_vote( tx_fee_amount ); } } @@ -638,10 +646,13 @@ namespace bacc = boost::accumulators; return std::make_tuple(account_net_limit, account_cpu_limit, greylisted_net, greylisted_cpu); } - void transaction_context::add_transaction_vote(transaction_vote_amount_type vote_amount) { + void transaction_context::cast_transaction_vote(transaction_vote_amount_type vote_amount) { if (vote_amount > 0 && trace->trx_vote.valid() && !trace->trx_vote->to.empty()) { trace->trx_vote->amt += vote_amount; + + // update transaction vote statistics database + control.get_mutable_tx_vote_stat_manager().add_transaction_vote_to_target_account( *this, trace->trx_vote->to, vote_amount ); } } diff --git a/libraries/chain/wasm_eosio_injection.cpp b/libraries/chain/wasm_eosio_injection.cpp index a4afa44d46..2c627e13ea 100644 --- a/libraries/chain/wasm_eosio_injection.cpp +++ b/libraries/chain/wasm_eosio_injection.cpp @@ -35,7 +35,7 @@ void max_memory_injection_visitor::inject( Module& m ) { } void max_memory_injection_visitor::initializer() {} -int32_t call_depth_check::global_idx = -1; +int32_t call_depth_check_and_insert_checktime::global_idx = -1; uint32_t instruction_counter::icnt = 0; uint32_t instruction_counter::tcnt = 0; uint32_t instruction_counter::bcnt = 0; diff --git a/libraries/chain/wasm_interface.cpp b/libraries/chain/wasm_interface.cpp index ec194dccb2..c0c5f8c882 100644 --- a/libraries/chain/wasm_interface.cpp +++ b/libraries/chain/wasm_interface.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include namespace eosio { namespace chain { using namespace webassembly; @@ -906,6 +908,8 @@ class system_api : public context_aware_api { }; +constexpr size_t max_assert_message = 1024; + class context_free_system_api : public context_aware_api { public: explicit context_free_system_api( apply_context& ctx ) @@ -918,14 +922,16 @@ class context_free_system_api : public context_aware_api { // Kept as intrinsic rather than implementing on WASM side (using eosio_assert_message and strlen) because strlen is faster on native side. void eosio_assert( bool condition, null_terminated_ptr msg ) { if( BOOST_UNLIKELY( !condition ) ) { - std::string message( msg ); + const size_t sz = strnlen( msg, max_assert_message ); + std::string message( msg, sz ); EOS_THROW( eosio_assert_message_exception, "assertion failure with message: ${s}", ("s",message) ); } } void eosio_assert_message( bool condition, array_ptr msg, size_t msg_len ) { if( BOOST_UNLIKELY( !condition ) ) { - std::string message( msg, msg_len ); + const size_t sz = msg_len > max_assert_message ? max_assert_message : msg_len; + std::string message( msg, sz ); EOS_THROW( eosio_assert_message_exception, "assertion failure with message: ${s}", ("s",message) ); } } @@ -1329,11 +1335,13 @@ class transaction_api : public context_aware_api { return context.cancel_deferred_transaction( (unsigned __int128)sender_id ); } + /// Deprecated /// YOSEMITE Core API - Proof-of-Transaction(PoT), Transaction-as-a-Vote(TaaV) void cast_transaction_vote(uint32_t vote_amount) { - context.cast_transaction_vote(vote_amount); +// context.cast_transaction_vote(vote_amount); } + /// Deprecated /// YOSEMITE Core API - Proof-of-Transaction(PoT), Transaction-as-a-Vote(TaaV) int read_head_block_trx_votes_data(array_ptr memory, size_t buffer_size) { auto trx_votes = context.get_transaction_votes_in_head_block(); @@ -1347,6 +1355,24 @@ class transaction_api : public context_aware_api { return copy_size; } + /// YOSEMITE Core API - Proof-of-Transaction(PoT), Transaction-as-a-Vote(TaaV) + int get_top_transaction_vote_receivers(array_ptr memory, size_t buffer_size, uint32_t offset_rank, uint32_t limit) { + auto trx_vote_receivers = context.get_top_transaction_vote_receivers( offset_rank, limit ); + + auto s = trx_vote_receivers.size() * sizeof(struct yosemite::chain::tx_vote_stat_for_account); + if (buffer_size == 0) return s; + + auto copy_size = std::min( buffer_size, s ); + memcpy( memory, trx_vote_receivers.data(), copy_size ); + + return copy_size; + } + + /// YOSEMITE Core API - Proof-of-Transaction(PoT), Transaction-as-a-Vote(TaaV) + double get_total_weighted_transaction_votes() { + return context.get_total_weighted_transaction_votes(); + } + /// YOSEMITE Core API - Transaction-Fee-Setup void set_trx_fee_for_action( const account_name code, const action_name action, int32_t value, uint32_t fee_type ) { context.set_transaction_fee_for_action( code, action, value, fee_type ); @@ -1953,6 +1979,8 @@ REGISTER_INTRINSICS(transaction_api, (cancel_deferred, int(int) ) (cast_transaction_vote, void(int) ) (read_head_block_trx_votes_data, int(int, int) ) + (get_top_transaction_vote_receivers, int(int, int, int, int) ) + (get_total_weighted_transaction_votes, double() ) (set_trx_fee_for_action, void(int64_t, int64_t, int32_t, int) ) (unset_trx_fee_for_action, void(int64_t, int64_t) ) (get_trx_fee_for_action, int(int64_t, int64_t, int, int) ) diff --git a/libraries/chain/yosemite/softfloat64.cpp b/libraries/chain/yosemite/softfloat64.cpp new file mode 100644 index 0000000000..4087476e67 --- /dev/null +++ b/libraries/chain/yosemite/softfloat64.cpp @@ -0,0 +1,483 @@ +/** + * @file yosemite/softfloat64.cpp + * @author bezalel@yosemitex.com + * @copyright defined in yosemite/LICENSE.txt + */ + +#include +#include + +#define _expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) +#define _signF64UI( a ) (((uint64_t) (a)>>63) != 0) +#define _packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) + +#define EXPTAB_SCALE 6 +#define EXPTAB_MASK ((1 << EXPTAB_SCALE) - 1) + +#define LOGTAB_SCALE 8 + +namespace yosemite { namespace chain { + + // .9670371139572337719125840413672004409288e-2 + static const float64_t EXPPOLY_32F_A0 = softfloat64::fromRaw(0x3f83ce0f3e46f431); + + // 1 / ln(2) * (1 << EXPTAB_SCALE) == 1.4426950408889634073599246810019 * (1 << EXPTAB_SCALE) + static const float64_t exp_prescale = f64_mul( softfloat64::fromRaw(0x3ff71547652b82fe), ui32_to_f64(1 << EXPTAB_SCALE) ); + static const float64_t exp_postscale = f64_div( softfloat64::one(), ui32_to_f64(1 << EXPTAB_SCALE) ); + static const float64_t exp_max_val = ui32_to_f64(3000*(1 << EXPTAB_SCALE)); // log10(DBL_MAX) < 3000 + + // 0.69314718055994530941723212145818 + static const float64_t ln_2 = softfloat64::fromRaw(0x3fe62e42fefa39ef); + + static const uint64_t expTab[] = { + 0x3ff0000000000000, // 1.000000 + 0x3ff02c9a3e778061, // 1.010889 + 0x3ff059b0d3158574, // 1.021897 + 0x3ff0874518759bc8, // 1.033025 + 0x3ff0b5586cf9890f, // 1.044274 + 0x3ff0e3ec32d3d1a2, // 1.055645 + 0x3ff11301d0125b51, // 1.067140 + 0x3ff1429aaea92de0, // 1.078761 + 0x3ff172b83c7d517b, // 1.090508 + 0x3ff1a35beb6fcb75, // 1.102383 + 0x3ff1d4873168b9aa, // 1.114387 + 0x3ff2063b88628cd6, // 1.126522 + 0x3ff2387a6e756238, // 1.138789 + 0x3ff26b4565e27cdd, // 1.151189 + 0x3ff29e9df51fdee1, // 1.163725 + 0x3ff2d285a6e4030b, // 1.176397 + 0x3ff306fe0a31b715, // 1.189207 + 0x3ff33c08b26416ff, // 1.202157 + 0x3ff371a7373aa9cb, // 1.215247 + 0x3ff3a7db34e59ff7, // 1.228481 + 0x3ff3dea64c123422, // 1.241858 + 0x3ff4160a21f72e2a, // 1.255381 + 0x3ff44e086061892d, // 1.269051 + 0x3ff486a2b5c13cd0, // 1.282870 + 0x3ff4bfdad5362a27, // 1.296840 + 0x3ff4f9b2769d2ca7, // 1.310961 + 0x3ff5342b569d4f82, // 1.325237 + 0x3ff56f4736b527da, // 1.339668 + 0x3ff5ab07dd485429, // 1.354256 + 0x3ff5e76f15ad2148, // 1.369002 + 0x3ff6247eb03a5585, // 1.383910 + 0x3ff6623882552225, // 1.398980 + 0x3ff6a09e667f3bcd, // 1.414214 + 0x3ff6dfb23c651a2f, // 1.429613 + 0x3ff71f75e8ec5f74, // 1.445181 + 0x3ff75feb564267c9, // 1.460918 + 0x3ff7a11473eb0187, // 1.476826 + 0x3ff7e2f336cf4e62, // 1.492908 + 0x3ff82589994cce13, // 1.509164 + 0x3ff868d99b4492ed, // 1.525598 + 0x3ff8ace5422aa0db, // 1.542211 + 0x3ff8f1ae99157736, // 1.559004 + 0x3ff93737b0cdc5e5, // 1.575981 + 0x3ff97d829fde4e50, // 1.593142 + 0x3ff9c49182a3f090, // 1.610490 + 0x3ffa0c667b5de565, // 1.628027 + 0x3ffa5503b23e255d, // 1.645755 + 0x3ffa9e6b5579fdbf, // 1.663677 + 0x3ffae89f995ad3ad, // 1.681793 + 0x3ffb33a2b84f15fb, // 1.700106 + 0x3ffb7f76f2fb5e47, // 1.718619 + 0x3ffbcc1e904bc1d2, // 1.737334 + 0x3ffc199bdd85529c, // 1.756252 + 0x3ffc67f12e57d14b, // 1.775376 + 0x3ffcb720dcef9069, // 1.794709 + 0x3ffd072d4a07897c, // 1.814252 + 0x3ffd5818dcfba487, // 1.834008 + 0x3ffda9e603db3285, // 1.853979 + 0x3ffdfc97337b9b5f, // 1.874168 + 0x3ffe502ee78b3ff6, // 1.894576 + 0x3ffea4afa2a490da, // 1.915207 + 0x3ffefa1bee615a27, // 1.936062 + 0x3fff50765b6e4540, // 1.957144 + 0x3fffa7c1819e90d8, // 1.978456 + }; + + static const uint64_t __attribute__ ((aligned (16))) icvLogTab[] = { + 0, 0x3ff0000000000000, // 0.000000, 1.000000 + 0x3f6ff00aa2b10bc0, 0x3fefe01fe01fe020, // 0.003899, 0.996109 + 0x3f7fe02a6b106788, 0x3fefc07f01fc07f0, // 0.007782, 0.992248 + 0x3f87dc475f810a76, 0x3fefa11caa01fa12, // 0.011651, 0.988417 + 0x3f8fc0a8b0fc03e3, 0x3fef81f81f81f820, // 0.015504, 0.984615 + 0x3f93cea44346a574, 0x3fef6310aca0dbb5, // 0.019343, 0.980843 + 0x3f97b91b07d5b11a, 0x3fef44659e4a4271, // 0.023167, 0.977099 + 0x3f9b9fc027af9197, 0x3fef25f644230ab5, // 0.026977, 0.973384 + 0x3f9f829b0e783300, 0x3fef07c1f07c1f08, // 0.030772, 0.969697 + 0x3fa1b0d98923d97f, 0x3feee9c7f8458e02, // 0.034552, 0.966038 + 0x3fa39e87b9febd5f, 0x3feecc07b301ecc0, // 0.038319, 0.962406 + 0x3fa58a5bafc8e4d4, 0x3feeae807aba01eb, // 0.042071, 0.958801 + 0x3fa77458f632dcfc, 0x3fee9131abf0b767, // 0.045810, 0.955224 + 0x3fa95c830ec8e3eb, 0x3fee741aa59750e4, // 0.049534, 0.951673 + 0x3fab42dd711971be, 0x3fee573ac901e574, // 0.053245, 0.948148 + 0x3fad276b8adb0b52, 0x3fee3a9179dc1a73, // 0.056941, 0.944649 + 0x3faf0a30c01162a6, 0x3fee1e1e1e1e1e1e, // 0.060625, 0.941176 + 0x3fb075983598e471, 0x3fee01e01e01e01e, // 0.064294, 0.937729 + 0x3fb16536eea37ae0, 0x3fede5d6e3f8868a, // 0.067951, 0.934307 + 0x3fb253f62f0a1416, 0x3fedca01dca01dca, // 0.071594, 0.930909 + 0x3fb341d7961bd1d0, 0x3fedae6076b981db, // 0.075223, 0.927536 + 0x3fb42edcbea646f0, 0x3fed92f2231e7f8a, // 0.078840, 0.924188 + 0x3fb51b073f06183f, 0x3fed77b654b82c34, // 0.082444, 0.920863 + 0x3fb60658a93750c3, 0x3fed5cac807572b2, // 0.086034, 0.917563 + 0x3fb6f0d28ae56b4b, 0x3fed41d41d41d41d, // 0.089612, 0.914286 + 0x3fb7da766d7b12cc, 0x3fed272ca3fc5b1a, // 0.093177, 0.911032 + 0x3fb8c345d6319b20, 0x3fed0cb58f6ec074, // 0.096730, 0.907801 + 0x3fb9ab42462033ac, 0x3fecf26e5c44bfc6, // 0.100269, 0.904594 + 0x3fba926d3a4ad563, 0x3fecd85689039b0b, // 0.103797, 0.901408 + 0x3fbb78c82bb0eda1, 0x3fecbe6d9601cbe7, // 0.107312, 0.898246 + 0x3fbc5e548f5bc743, 0x3feca4b3055ee191, // 0.110814, 0.895105 + 0x3fbd4313d66cb35d, 0x3fec8b265afb8a42, // 0.114305, 0.891986 + 0x3fbe27076e2af2e5, 0x3fec71c71c71c71c, // 0.117783, 0.888889 + 0x3fbf0a30c01162a6, 0x3fec5894d10d4986, // 0.121249, 0.885813 + 0x3fbfec9131dbeaba, 0x3fec3f8f01c3f8f0, // 0.124703, 0.882759 + 0x3fc0671512ca596e, 0x3fec26b5392ea01c, // 0.128146, 0.879725 + 0x3fc0d77e7cd08e59, 0x3fec0e070381c0e0, // 0.131576, 0.876712 + 0x3fc14785846742ac, 0x3febf583ee868d8b, // 0.134995, 0.873720 + 0x3fc1b72ad52f67a0, 0x3febdd2b899406f7, // 0.138402, 0.870748 + 0x3fc2266f190a5acb, 0x3febc4fd65883e7b, // 0.141798, 0.867797 + 0x3fc29552f81ff523, 0x3febacf914c1bad0, // 0.145182, 0.864865 + 0x3fc303d718e47fd2, 0x3feb951e2b18ff23, // 0.148555, 0.861953 + 0x3fc371fc201e8f74, 0x3feb7d6c3dda338b, // 0.151916, 0.859060 + 0x3fc3dfc2b0ecc629, 0x3feb65e2e3beee05, // 0.155266, 0.856187 + 0x3fc44d2b6ccb7d1e, 0x3feb4e81b4e81b4f, // 0.158605, 0.853333 + 0x3fc4ba36f39a55e5, 0x3feb37484ad806ce, // 0.161933, 0.850498 + 0x3fc526e5e3a1b437, 0x3feb2036406c80d9, // 0.165250, 0.847682 + 0x3fc59338d9982085, 0x3feb094b31d922a4, // 0.168555, 0.844884 + 0x3fc5ff3070a793d3, 0x3feaf286bca1af28, // 0.171850, 0.842105 + 0x3fc66acd4272ad50, 0x3feadbe87f94905e, // 0.175134, 0.839344 + 0x3fc6d60fe719d21c, 0x3feac5701ac5701b, // 0.178408, 0.836601 + 0x3fc740f8f54037a4, 0x3feaaf1d2f87ebfd, // 0.181670, 0.833876 + 0x3fc7ab890210d909, 0x3fea98ef606a63be, // 0.184922, 0.831169 + 0x3fc815c0a14357ea, 0x3fea82e65130e159, // 0.188164, 0.828479 + 0x3fc87fa06520c910, 0x3fea6d01a6d01a6d, // 0.191395, 0.825806 + 0x3fc8e928de886d40, 0x3fea574107688a4a, // 0.194615, 0.823151 + 0x3fc9525a9cf456b4, 0x3fea41a41a41a41a, // 0.197826, 0.820513 + 0x3fc9bb362e7dfb83, 0x3fea2c2a87c51ca0, // 0.201026, 0.817891 + 0x3fca23bc1fe2b563, 0x3fea16d3f97a4b02, // 0.204216, 0.815287 + 0x3fca8becfc882f18, 0x3fea01a01a01a01a, // 0.207395, 0.812698 + 0x3fcaf3c94e80bff2, 0x3fe9ec8e951033d9, // 0.210565, 0.810127 + 0x3fcb5b519e8fb5a4, 0x3fe9d79f176b682d, // 0.213724, 0.807571 + 0x3fcbc286742d8cd6, 0x3fe9c2d14ee4a102, // 0.216874, 0.805031 + 0x3fcc2968558c18c0, 0x3fe9ae24ea5510da, // 0.220014, 0.802508 + 0x3fcc8ff7c79a9a21, 0x3fe999999999999a, // 0.223144, 0.800000 + 0x3fccf6354e09c5dc, 0x3fe9852f0d8ec0ff, // 0.226264, 0.797508 + 0x3fcd5c216b4fbb91, 0x3fe970e4f80cb872, // 0.229374, 0.795031 + 0x3fcdc1bca0abec7d, 0x3fe95cbb0be377ae, // 0.232475, 0.792570 + 0x3fce27076e2af2e5, 0x3fe948b0fcd6e9e0, // 0.235566, 0.790123 + 0x3fce8c0252aa5a5f, 0x3fe934c67f9b2ce6, // 0.238648, 0.787692 + 0x3fcef0adcbdc5936, 0x3fe920fb49d0e229, // 0.241720, 0.785276 + 0x3fcf550a564b7b37, 0x3fe90d4f120190d5, // 0.244783, 0.782875 + 0x3fcfb9186d5e3e2a, 0x3fe8f9c18f9c18fa, // 0.247836, 0.780488 + 0x3fd00e6c45ad501c, 0x3fe8e6527af1373f, // 0.250880, 0.778116 + 0x3fd0402594b4d040, 0x3fe8d3018d3018d3, // 0.253915, 0.775758 + 0x3fd071b85fcd590d, 0x3fe8bfce8062ff3a, // 0.256941, 0.773414 + 0x3fd0a324e27390e3, 0x3fe8acb90f6bf3aa, // 0.259958, 0.771084 + 0x3fd0d46b579ab74b, 0x3fe899c0f601899c, // 0.262965, 0.768769 + 0x3fd1058bf9ae4ad5, 0x3fe886e5f0abb04a, // 0.265964, 0.766467 + 0x3fd136870293a8b0, 0x3fe87427bcc092b9, // 0.268953, 0.764179 + 0x3fd1675cababa60e, 0x3fe8618618618618, // 0.271934, 0.761905 + 0x3fd1980d2dd4236f, 0x3fe84f00c2780614, // 0.274905, 0.759644 + 0x3fd1c898c16999fa, 0x3fe83c977ab2bedd, // 0.277868, 0.757396 + 0x3fd1f8ff9e48a2f2, 0x3fe82a4a0182a4a0, // 0.280823, 0.755162 + 0x3fd22941fbcf7965, 0x3fe8181818181818, // 0.283768, 0.752941 + 0x3fd2596010df7639, 0x3fe8060180601806, // 0.286705, 0.750733 + 0x3fd2895a13de86a3, 0x3fe7f405fd017f40, // 0.289633, 0.748538 + 0x3fd2b9303ab89d24, 0x3fe7e225515a4f1d, // 0.292553, 0.746356 + 0x3fd2e8e2bae11d30, 0x3fe7d05f417d05f4, // 0.295464, 0.744186 + 0x3fd31871c9544184, 0x3fe7beb3922e017c, // 0.298367, 0.742029 + 0x3fd347dd9a987d54, 0x3fe7ad2208e0ecc3, // 0.301261, 0.739884 + 0x3fd3772662bfd85a, 0x3fe79baa6bb6398b, // 0.304147, 0.737752 + 0x3fd3a64c556945e9, 0x3fe78a4c8178a4c8, // 0.307025, 0.735632 + 0x3fd3d54fa5c1f70f, 0x3fe77908119ac60d, // 0.309894, 0.733524 + 0x3fd404308686a7e3, 0x3fe767dce434a9b1, // 0.312756, 0.731429 + 0x3fd432ef2a04e813, 0x3fe756cac201756d, // 0.315609, 0.729345 + 0x3fd4618bc21c5ec2, 0x3fe745d1745d1746, // 0.318454, 0.727273 + 0x3fd49006804009d0, 0x3fe734f0c541fe8d, // 0.321291, 0.725212 + 0x3fd4be5f957778a0, 0x3fe724287f46debc, // 0.324119, 0.723164 + 0x3fd4ec9732600269, 0x3fe713786d9c7c09, // 0.326940, 0.721127 + 0x3fd51aad872df82d, 0x3fe702e05c0b8170, // 0.329753, 0.719101 + 0x3fd548a2c3add262, 0x3fe6f26016f26017, // 0.332558, 0.717087 + 0x3fd5767717455a6c, 0x3fe6e1f76b4337c7, // 0.335356, 0.715084 + 0x3fd5a42ab0f4cfe1, 0x3fe6d1a62681c861, // 0.338145, 0.713092 + 0x3fd5d1bdbf5809ca, 0x3fe6c16c16c16c17, // 0.340927, 0.711111 + 0x3fd5ff3070a793d3, 0x3fe6b1490aa31a3d, // 0.343701, 0.709141 + 0x3fd62c82f2b9c795, 0x3fe6a13cd1537290, // 0.346467, 0.707182 + 0x3fd659b57303e1f2, 0x3fe691473a88d0c0, // 0.349225, 0.705234 + 0x3fd686c81e9b14ae, 0x3fe6816816816817, // 0.351976, 0.703297 + 0x3fd6b3bb2235943d, 0x3fe6719f3601671a, // 0.354720, 0.701370 + 0x3fd6e08eaa2ba1e3, 0x3fe661ec6a5122f9, // 0.357456, 0.699454 + 0x3fd70d42e2789235, 0x3fe6524f853b4aa3, // 0.360184, 0.697548 + 0x3fd739d7f6bbd006, 0x3fe642c8590b2164, // 0.362905, 0.695652 + 0x3fd7664e1239dbce, 0x3fe63356b88ac0de, // 0.365619, 0.693767 + 0x3fd792a55fdd47a2, 0x3fe623fa77016240, // 0.368326, 0.691892 + 0x3fd7bede0a37afbf, 0x3fe614b36831ae94, // 0.371025, 0.690027 + 0x3fd7eaf83b82afc3, 0x3fe6058160581606, // 0.373716, 0.688172 + 0x3fd816f41da0d495, 0x3fe5f66434292dfc, // 0.376401, 0.686327 + 0x3fd842d1da1e8b17, 0x3fe5e75bb8d015e7, // 0.379078, 0.684492 + 0x3fd86e919a330ba0, 0x3fe5d867c3ece2a5, // 0.381749, 0.682667 + 0x3fd89a3386c1425a, 0x3fe5c9882b931057, // 0.384412, 0.680851 + 0x3fd8c5b7c858b48a, 0x3fe5babcc647fa91, // 0.387068, 0.679045 + 0x3fd8f11e873662c7, 0x3fe5ac056b015ac0, // 0.389717, 0.677249 + 0x3fd91c67eb45a83d, 0x3fe59d61f123ccaa, // 0.392359, 0.675462 + 0x3fd947941c2116fa, 0x3fe58ed2308158ed, // 0.394994, 0.673684 + 0x3fd972a341135158, 0x3fe5805601580560, // 0.397622, 0.671916 + 0x3fd99d958117e08a, 0x3fe571ed3c506b3a, // 0.400243, 0.670157 + 0x3fd9c86b02dc0862, 0x3fe56397ba7c52e2, // 0.402858, 0.668407 + 0x3fd9f323ecbf984b, 0x3fe5555555555555, // 0.405465, 0.666667 + 0x3fda1dc064d5b995, 0x3fe54725e6bb82fe, // 0.408066, 0.664935 + 0x3fda484090e5bb0a, 0x3fe5390948f40feb, // 0.410660, 0.663212 + 0x3fda72a4966bd9ea, 0x3fe52aff56a8054b, // 0.413247, 0.661499 + 0x3fda9cec9a9a0849, 0x3fe51d07eae2f815, // 0.415828, 0.659794 + 0x3fdac718c258b0e4, 0x3fe50f22e111c4c5, // 0.418402, 0.658098 + 0x3fdaf1293247786b, 0x3fe5015015015015, // 0.420969, 0.656410 + 0x3fdb1b1e0ebdfc5b, 0x3fe4f38f62dd4c9b, // 0.423530, 0.654731 + 0x3fdb44f77bcc8f62, 0x3fe4e5e0a72f0539, // 0.426084, 0.653061 + 0x3fdb6eb59d3cf35d, 0x3fe4d843bedc2c4c, // 0.428632, 0.651399 + 0x3fdb9858969310fb, 0x3fe4cab88725af6e, // 0.431173, 0.649746 + 0x3fdbc1e08b0dad0a, 0x3fe4bd3edda68fe1, // 0.433708, 0.648101 + 0x3fdbeb4d9da71b7b, 0x3fe4afd6a052bf5b, // 0.436237, 0.646465 + 0x3fdc149ff115f026, 0x3fe4a27fad76014a, // 0.438759, 0.644836 + 0x3fdc3dd7a7cdad4d, 0x3fe49539e3b2d067, // 0.441275, 0.643216 + 0x3fdc66f4e3ff6ff7, 0x3fe4880522014880, // 0.443784, 0.641604 + 0x3fdc8ff7c79a9a21, 0x3fe47ae147ae147b, // 0.446287, 0.640000 + 0x3fdcb8e0744d7ac9, 0x3fe46dce34596066, // 0.448784, 0.638404 + 0x3fdce1af0b85f3eb, 0x3fe460cbc7f5cf9a, // 0.451275, 0.636816 + 0x3fdd0a63ae721e64, 0x3fe453d9e2c776ca, // 0.453759, 0.635236 + 0x3fdd32fe7e00ebd5, 0x3fe446f86562d9fb, // 0.456237, 0.633663 + 0x3fdd5b7f9ae2c683, 0x3fe43a2730abee4d, // 0.458710, 0.632099 + 0x3fdd83e7258a2f3e, 0x3fe42d6625d51f87, // 0.461176, 0.630542 + 0x3fddac353e2c5954, 0x3fe420b5265e5951, // 0.463636, 0.628993 + 0x3fddd46a04c1c4a0, 0x3fe4141414141414, // 0.466090, 0.627451 + 0x3fddfc859906d5b5, 0x3fe40782d10e6566, // 0.468538, 0.625917 + 0x3fde24881a7c6c26, 0x3fe3fb013fb013fb, // 0.470980, 0.624390 + 0x3fde4c71a8687704, 0x3fe3ee8f42a5af07, // 0.473416, 0.622871 + 0x3fde744261d68787, 0x3fe3e22cbce4a902, // 0.475846, 0.621359 + 0x3fde9bfa659861f5, 0x3fe3d5d991aa75c6, // 0.478270, 0.619855 + 0x3fdec399d2468cc0, 0x3fe3c995a47babe7, // 0.480689, 0.618357 + 0x3fdeeb20c640ddf4, 0x3fe3bd60d9232955, // 0.483101, 0.616867 + 0x3fdf128f5faf06ec, 0x3fe3b13b13b13b14, // 0.485508, 0.615385 + 0x3fdf39e5bc811e5b, 0x3fe3a524387ac822, // 0.487909, 0.613909 + 0x3fdf6123fa7028ac, 0x3fe3991c2c187f63, // 0.490304, 0.612440 + 0x3fdf884a36fe9ec2, 0x3fe38d22d366088e, // 0.492693, 0.610979 + 0x3fdfaf588f78f31e, 0x3fe3813813813814, // 0.495077, 0.609524 + 0x3fdfd64f20f61571, 0x3fe3755bd1c945ee, // 0.497455, 0.608076 + 0x3fdffd2e0857f498, 0x3fe3698df3de0748, // 0.499828, 0.606635 + 0x3fe011fab125ff8a, 0x3fe35dce5f9f2af8, // 0.502195, 0.605201 + 0x3fe02552a5a5d0fe, 0x3fe3521cfb2b78c1, // 0.504556, 0.603774 + 0x3fe0389eefce633b, 0x3fe34679ace01346, // 0.506912, 0.602353 + 0x3fe04bdf9da926d2, 0x3fe33ae45b57bcb2, // 0.509262, 0.600939 + 0x3fe05f14bd26459c, 0x3fe32f5ced6a1dfa, // 0.511607, 0.599532 + 0x3fe0723e5c1cdf40, 0x3fe323e34a2b10bf, // 0.513946, 0.598131 + 0x3fe0855c884b450e, 0x3fe3187758e9ebb6, // 0.516279, 0.596737 + 0x3fe0986f4f573520, 0x3fe30d190130d190, // 0.518608, 0.595349 + 0x3fe0ab76bece14d1, 0x3fe301c82ac40260, // 0.520931, 0.593968 + 0x3fe0be72e4252a82, 0x3fe2f684bda12f68, // 0.523248, 0.592593 + 0x3fe0d163ccb9d6b7, 0x3fe2eb4ea1fed14b, // 0.525560, 0.591224 + 0x3fe0e44985d1cc8b, 0x3fe2e025c04b8097, // 0.527867, 0.589862 + 0x3fe0f7241c9b497d, 0x3fe2d50a012d50a0, // 0.530169, 0.588506 + 0x3fe109f39e2d4c96, 0x3fe2c9fb4d812ca0, // 0.532465, 0.587156 + 0x3fe11cb81787ccf8, 0x3fe2bef98e5a3711, // 0.534756, 0.585812 + 0x3fe12f719593efbc, 0x3fe2b404ad012b40, // 0.537041, 0.584475 + 0x3fe1422025243d44, 0x3fe2a91c92f3c105, // 0.539322, 0.583144 + 0x3fe154c3d2f4d5e9, 0x3fe29e4129e4129e, // 0.541597, 0.581818 + 0x3fe1675cababa60e, 0x3fe293725bb804a5, // 0.543867, 0.580499 + 0x3fe179eabbd899a0, 0x3fe288b01288b013, // 0.546132, 0.579186 + 0x3fe18c6e0ff5cf06, 0x3fe27dfa38a1ce4d, // 0.548392, 0.577878 + 0x3fe19ee6b467c96e, 0x3fe27350b8812735, // 0.550647, 0.576577 + 0x3fe1b154b57da29e, 0x3fe268b37cd60127, // 0.552897, 0.575281 + 0x3fe1c3b81f713c24, 0x3fe25e22708092f1, // 0.555142, 0.573991 + 0x3fe1d610fe677003, 0x3fe2539d7e9177b2, // 0.557381, 0.572707 + 0x3fe1e85f5e7040d0, 0x3fe2492492492492, // 0.559616, 0.571429 + 0x3fe1faa34b87094c, 0x3fe23eb79717605b, // 0.561845, 0.570156 + 0x3fe20cdcd192ab6d, 0x3fe23456789abcdf, // 0.564070, 0.568889 + 0x3fe21f0bfc65beeb, 0x3fe22a0122a0122a, // 0.566290, 0.567627 + 0x3fe23130d7bebf42, 0x3fe21fb78121fb78, // 0.568505, 0.566372 + 0x3fe2434b6f483933, 0x3fe21579804855e6, // 0.570715, 0.565121 + 0x3fe2555bce98f7cb, 0x3fe20b470c67c0d9, // 0.572920, 0.563877 + 0x3fe26762013430df, 0x3fe2012012012012, // 0.575120, 0.562637 + 0x3fe2795e1289b11a, 0x3fe1f7047dc11f70, // 0.577315, 0.561404 + 0x3fe28b500df60782, 0x3fe1ecf43c7fb84c, // 0.579506, 0.560175 + 0x3fe29d37fec2b08a, 0x3fe1e2ef3b3fb874, // 0.581692, 0.558952 + 0x3fe2af15f02640ad, 0x3fe1d8f5672e4abd, // 0.583873, 0.557734 + 0x3fe2c0e9ed448e8b, 0x3fe1cf06ada2811d, // 0.586049, 0.556522 + 0x3fe2d2b4012edc9d, 0x3fe1c522fc1ce059, // 0.588221, 0.555315 + 0x3fe2e47436e40268, 0x3fe1bb4a4046ed29, // 0.590387, 0.554113 + 0x3fe2f62a99509546, 0x3fe1b17c67f2bae3, // 0.592550, 0.552916 + 0x3fe307d7334f10be, 0x3fe1a7b9611a7b96, // 0.594707, 0.551724 + 0x3fe3197a0fa7fe6a, 0x3fe19e0119e0119e, // 0.596860, 0.550538 + 0x3fe32b1339121d71, 0x3fe19453808ca29c, // 0.599008, 0.549356 + 0x3fe33ca2ba328994, 0x3fe18ab083902bdb, // 0.601152, 0.548180 + 0x3fe34e289d9ce1d3, 0x3fe1811811811812, // 0.603291, 0.547009 + 0x3fe35fa4edd36ea0, 0x3fe1778a191bd684, // 0.605425, 0.545842 + 0x3fe37117b54747b5, 0x3fe16e0689427379, // 0.607555, 0.544681 + 0x3fe38280fe58797e, 0x3fe1648d50fc3201, // 0.609681, 0.543524 + 0x3fe393e0d3562a19, 0x3fe15b1e5f75270d, // 0.611802, 0.542373 + 0x3fe3a5373e7ebdf9, 0x3fe151b9a3fdd5c9, // 0.613918, 0.541226 + 0x3fe3b68449fffc22, 0x3fe1485f0e0acd3b, // 0.616030, 0.540084 + 0x3fe3c7c7fff73205, 0x3fe13f0e8d344724, // 0.618137, 0.538947 + 0x3fe3d9026a7156fa, 0x3fe135c81135c811, // 0.620240, 0.537815 + 0x3fe3ea33936b2f5b, 0x3fe12c8b89edc0ac, // 0.622339, 0.536688 + 0x3fe3fb5b84d16f42, 0x3fe12358e75d3033, // 0.624433, 0.535565 + 0x3fe40c7a4880dce9, 0x3fe11a3019a74826, // 0.626523, 0.534447 + 0x3fe41d8fe84672ae, 0x3fe1111111111111, // 0.628609, 0.533333 + 0x3fe42e9c6ddf80bf, 0x3fe107fbbe011080, // 0.630690, 0.532225 + 0x3fe43f9fe2f9ce67, 0x3fe0fef010fef011, // 0.632767, 0.531120 + 0x3fe4509a5133bb0a, 0x3fe0f5edfab325a2, // 0.634839, 0.530021 + 0x3fe4618bc21c5ec2, 0x3fe0ecf56be69c90, // 0.636907, 0.528926 + 0x3fe472743f33aaad, 0x3fe0e40655826011, // 0.638971, 0.527835 + 0x3fe48353d1ea88df, 0x3fe0db20a88f4696, // 0.641031, 0.526749 + 0x3fe4942a83a2fc07, 0x3fe0d24456359e3a, // 0.643087, 0.525667 + 0x3fe4a4f85db03ebb, 0x3fe0c9714fbcda3b, // 0.645138, 0.524590 + 0x3fe4b5bd6956e273, 0x3fe0c0a7868b4171, // 0.647185, 0.523517 + 0x3fe4c679afccee39, 0x3fe0b7e6ec259dc8, // 0.649228, 0.522449 + 0x3fe4d72d3a39fd00, 0x3fe0af2f722eecb5, // 0.651267, 0.521385 + 0x3fe4e7d811b75bb0, 0x3fe0a6810a6810a7, // 0.653301, 0.520325 + 0x3fe4f87a3f5026e8, 0x3fe09ddba6af8360, // 0.655332, 0.519270 + 0x3fe50913cc01686b, 0x3fe0953f39010954, // 0.657358, 0.518219 + 0x3fe519a4c0ba3446, 0x3fe08cabb37565e2, // 0.659380, 0.517172 + 0x3fe52a2d265bc5aa, 0x3fe0842108421084, // 0.661398, 0.516129 + 0x3fe53aad05b99b7c, 0x3fe07b9f29b8eae2, // 0.663413, 0.515091 + 0x3fe54b2467999497, 0x3fe073260a47f7c6, // 0.665423, 0.514056 + 0x3fe55b9354b40bcd, 0x3fe06ab59c7912fb, // 0.667429, 0.513026 + 0x3fe56bf9d5b3f399, 0x3fe0624dd2f1a9fc, // 0.669431, 0.512000 + 0x3fe57c57f336f190, 0x3fe059eea0727586, // 0.671429, 0.510978 + 0x3fe58cadb5cd7989, 0x3fe05197f7d73404, // 0.673423, 0.509960 + 0x3fe59cfb25fae87d, 0x3fe04949cc1664c5, // 0.675413, 0.508946 + 0x3fe5ad404c359f2c, 0x3fe0410410410410, // 0.677399, 0.507937 + 0x3fe5bd7d30e71c73, 0x3fe038c6b78247fc, // 0.679381, 0.506931 + 0x3fe5cdb1dc6c1764, 0x3fe03091b51f5e1a, // 0.681359, 0.505929 + 0x3fe5ddde57149923, 0x3fe02864fc7729e9, // 0.683334, 0.504931 + 0x3fe5ee02a9241675, 0x3fe0204081020408, // 0.685304, 0.503937 + 0x3fe5fe1edad18918, 0x3fe0182436517a37, // 0.687271, 0.502947 + 0x3fe60e32f44788d8, 0x3fe0101010101010, // 0.689233, 0.501961 + 0x3fe62e42fefa39ef, 0x3fe0000000000000, // 0.693147, 0.500000 + }; + + float64_t softfloat64::pow( float64_t x, float64_t y ) { + + static const float64_t zero = softfloat64::zero(), one = softfloat64::one(), inf = softfloat64::inf(), nan = softfloat64::nan(); + bool xinf = softfloat64::isInf(x), yinf = softfloat64::isInf(y), xnan = softfloat64::isNaN(x), ynan = softfloat64::isNaN(y); + float64_t ax = softfloat64::abs(x); + bool useInf = (y > zero) == (ax > one); + float64_t v; + //special cases + if(ynan) v = nan; + else if(yinf) v = (ax == one || xnan) ? nan : (useInf ? inf : zero); + else if(y == zero) v = one; + else if(y == one ) v = x; + else //here y is ok + { + if(xnan) v = nan; + else if(xinf) v = (y < zero) ? zero : inf; + else if(y == f64_roundToInt(y, 0/*softfloat_round_near_even*/, false)) v = softfloat64::powi(x, f64_to_i32(y, 0/*softfloat_round_near_even*/, false)); + else if(x < zero) v = nan; + // (0 ** 0) == 1 + else if(x == zero) v = (y < zero) ? inf : (y == zero ? one : zero); + // here x and y are ok + else v = softfloat64::exp(f64_mul( y, softfloat64::log(x) )); + } + + return v; + } + + float64_t softfloat64::powi( float64_t x, int y ) { + + float64_t v; + //special case: (0 ** 0) == 1 + if(x == softfloat64::zero()) { + v = (y < 0) ? softfloat64::inf() : (y == 0 ? softfloat64::one() : softfloat64::zero()); + // here x and y are ok + } else { + float64_t a = softfloat64::one(), b = x; + int p = std::abs(y); + if( y < 0 ) { + b = f64_div(softfloat64::one(), b); + } + while( p > 1 ) { + if( p & 1 ) { + a = f64_mul( a, b ); + } + b = f64_mul( b, b ); + p >>= 1; + } + v = f64_mul( a, b ); + } + + return v; + } + + float64_t softfloat64::exp( float64_t x ) { + + //special cases + if(softfloat64::isNaN(x)) return softfloat64::nan(); + if(softfloat64::isInf(x)) return (x == softfloat64::inf()) ? x : softfloat64::zero(); + + static const float64_t + A5 = f64_div( softfloat64::one(), EXPPOLY_32F_A0 ), + A4 = f64_div( softfloat64::fromRaw(0x3fe62e42fefa39f1), EXPPOLY_32F_A0 ), // .69314718055994546743029643825322 / EXPPOLY_32F_A0 + A3 = f64_div( softfloat64::fromRaw(0x3fcebfbdff82a45a), EXPPOLY_32F_A0 ), // .24022650695886477918181338054308 / EXPPOLY_32F_A0 + A2 = f64_div( softfloat64::fromRaw(0x3fac6b08d81fec75), EXPPOLY_32F_A0 ), // .55504108793649567998466049042729e-1 / EXPPOLY_32F_A0 + A1 = f64_div( softfloat64::fromRaw(0x3f83b2a72b4f3cd3), EXPPOLY_32F_A0 ), // .96180973140732918010002372686186e-2 / EXPPOLY_32F_A0 + A0 = f64_div( softfloat64::fromRaw(0x3f55e7aa1566c2a4), EXPPOLY_32F_A0 ); // .13369713757180123244806654839424e-2 / EXPPOLY_32F_A0 + + float64_t x0; + if(_expF64UI(x.v) > 1023 + 10) + x0 = _signF64UI(x.v) ? softfloat64::negate( exp_max_val ) : exp_max_val; + else + x0 = f64_mul(x, exp_prescale); + + int val0 = f64_to_i32(x0, 0 /*softfloat_round_near_even*/, false); + int t = (val0 >> EXPTAB_SCALE) + 1023; + t = t < 0 ? 0 : (t > 2047 ? 2047 : t); + float64_t buf; buf.v = _packToF64UI(0, t, 0); + + x0 = f64_mul( f64_sub( x0, f64_roundToInt(x0, 0 /*softfloat_round_near_even*/, false) ), exp_postscale ); + + return f64_mul( + f64_mul( f64_mul( buf, EXPPOLY_32F_A0 ), softfloat64::fromRaw(expTab[val0 & EXPTAB_MASK]) ), + f64_add( f64_mul( f64_add( f64_mul( f64_add( f64_mul( f64_add( f64_mul( f64_add( f64_mul( A0, x0 ), A1 ), x0 ), A2 ), x0 ), A3 ), x0 ), A4 ), x0 ), A5 ) + ); + } + + float64_t softfloat64::log( float64_t x ) { + + //special cases + if(softfloat64::isNaN(x) || x < softfloat64::zero()) return softfloat64::nan(); + if(x == softfloat64::zero()) return softfloat64::negate(softfloat64::inf()); + + static const float64_t + A7 = i32_to_f64(1), + A6 = f64_div( softfloat64::negate(softfloat64::one()), ui32_to_f64(2) ), + A5 = f64_div( softfloat64::one(), ui32_to_f64(3) ), + A4 = f64_div( softfloat64::negate(softfloat64::one()), ui32_to_f64(4) ), + A3 = f64_div( softfloat64::one(), ui32_to_f64(5) ), + A2 = f64_div( softfloat64::negate(softfloat64::one()), ui32_to_f64(6) ), + A1 = f64_div( softfloat64::one(), ui32_to_f64(7) ), + A0 = f64_div( softfloat64::negate(softfloat64::one()), ui32_to_f64(8) ); + + //first 8 bits of mantissa + int h0 = (x.v >> (52 - LOGTAB_SCALE)) & ((1 << LOGTAB_SCALE) - 1); + //buf == 0.00000000_the_rest_mantissa_bits + float64_t buf; buf.v = _packToF64UI(0, 1023, x.v & ((1LL << (52 - LOGTAB_SCALE)) - 1)); + buf = f64_sub( buf, softfloat64::one() ); + + float64_t tab0 = softfloat64::fromRaw(icvLogTab[2*h0]); + float64_t tab1 = softfloat64::fromRaw(icvLogTab[2*h0 + 1]); + + float64_t x0 = f64_mul( buf, tab1 ); + //if last elements of icvLogTab + if(h0 == 255) x0 = f64_add( x0, f64_div( softfloat64::negate(softfloat64::one()), ui32_to_f64(512)) ); + float64_t xq = f64_mul( x0, x0 ); + + return f64_add( + f64_add( + f64_add( f64_mul( ln_2, i32_to_f64( _expF64UI(x.v) - 1023 )), tab0 ), + f64_mul( f64_add( f64_mul( f64_add( f64_mul( f64_add( f64_mul( A0, xq ), A2 ), xq ), A4 ), xq ), A6 ), xq ) + ), + f64_mul( f64_add( f64_mul( f64_add( f64_mul( f64_add( f64_mul( A1, xq ), A3 ), xq ), A5 ), xq ), A7 ), x0 ) + ); + } + +} } /// yosemite::chain \ No newline at end of file diff --git a/libraries/chain/yosemite/standard_token_manager.cpp b/libraries/chain/yosemite/standard_token_manager.cpp index 97028b779f..6a53b8865f 100644 --- a/libraries/chain/yosemite/standard_token_manager.cpp +++ b/libraries/chain/yosemite/standard_token_manager.cpp @@ -213,9 +213,6 @@ namespace yosemite { namespace chain { } EOS_ASSERT( fee_remaining <= 0, yosemite_transaction_fee_exception, "fee payer ${payer} does not have enough system token", ("payer", fee_payer) ); - - // Cast Transaction Vote - YOSEMITE Proof-of-Transaction / Transaction-as-a-Vote - trx_context.add_transaction_vote(fee_amount); } @@ -235,7 +232,7 @@ namespace yosemite { namespace chain { int64_t version = new_sys_token_list.version; - _db.modify( ygpo, [&]( auto& ygp ) { + _db.modify( ygpo, [&]( auto& ygp ) { ygp.system_token_list = std::move(new_sys_token_list); }); return version; diff --git a/libraries/chain/yosemite/transaction_vote_stat_manager.cpp b/libraries/chain/yosemite/transaction_vote_stat_manager.cpp new file mode 100644 index 0000000000..117f84f2f8 --- /dev/null +++ b/libraries/chain/yosemite/transaction_vote_stat_manager.cpp @@ -0,0 +1,144 @@ +/** + * @file chain/yosemite/transaction_vote_stat_manager.cpp + * @author bezalel@yosemitex.com + * @copyright defined in yosemite/LICENSE.txt + */ + +#include +#include +#include +#include + +#include + +namespace yosemite { namespace chain { + + using namespace eosio::chain; + + using transaction_vote_stat_db_index_set = index_set< + received_transaction_votes_multi_index + >; + + transaction_vote_stat_manager::transaction_vote_stat_manager( chainbase::database& db ) + : _db(db) { + } + + void transaction_vote_stat_manager::add_indices() { + transaction_vote_stat_db_index_set::add_indices(_db); + } + + void transaction_vote_stat_manager::initialize_database() { + + } + + void transaction_vote_stat_manager::add_to_snapshot( const snapshot_writer_ptr& snapshot ) const { + transaction_vote_stat_db_index_set::walk_indices([this, &snapshot]( auto utils ){ + snapshot->write_section([this]( auto& section ){ + decltype(utils)::walk(_db, [this, §ion]( const auto &row ) { + section.add_row(row, _db); + }); + }); + }); + } + + void transaction_vote_stat_manager::read_from_snapshot( const snapshot_reader_ptr& snapshot ) { + transaction_vote_stat_db_index_set::walk_indices([this, &snapshot]( auto utils ){ + snapshot->read_section([this]( auto& section ) { + bool more = !section.empty(); + while(more) { + decltype(utils)::create(_db, [this, §ion, &more]( auto &row ) { + more = section.read_row(row, _db); + }); + } + }); + }); + } + + const int64_t __tx_vote_weight_timestamp_epoch__ = 1514764800ll; // 01/01/2018 @ 12:00am (UTC) + const uint32_t __seconds_per_week__ = 24 * 3600 * 7; + + double transaction_vote_stat_manager::weighted_tx_vote_time_decayed( uint32_t curren_block_time_sec, uint32_t vote ) { + float64_t weight = f64_div( i64_to_f64(int64_t( curren_block_time_sec - __tx_vote_weight_timestamp_epoch__ )), i64_to_f64( __seconds_per_week__ * 52 ) ); + return from_softfloat64( f64_mul( ui32_to_f64(vote), softfloat64::pow( ui32_to_f64(2), weight ) ) ); + } + + void transaction_vote_stat_manager::add_transaction_vote_to_target_account( transaction_context& context, const transaction_vote_to_name_type vote_target_account, const transaction_vote_amount_type tx_vote_amount ) { + + if (tx_vote_amount == 0 || tx_vote_amount > YOSEMITE_MAX_TRANSACTION_FEE_AMOUNT_PER_TRANSACTION) { + return; + } + + uint32_t curren_block_time_sec = (uint32_t)( static_cast( context.control.pending_block_time().time_since_epoch().count() ) / 1000000 ); + tx_votes_sum_weighted_type weighted_tx_vote_amount = weighted_tx_vote_time_decayed( curren_block_time_sec, tx_vote_amount ); + + auto* tx_votes_ptr = _db.find( vote_target_account ); + if ( tx_votes_ptr ) { + _db.modify( *tx_votes_ptr, [&]( received_transaction_votes_object& tx_votes_obj ) { + tx_votes_obj.tx_votes_weighted = softfloat64::add( tx_votes_obj.tx_votes_weighted, weighted_tx_vote_amount ); + tx_votes_obj.tx_votes += tx_vote_amount; + }); + } else { + _db.create( [&](received_transaction_votes_object& tx_votes_obj) { + tx_votes_obj.account = vote_target_account; + tx_votes_obj.tx_votes_weighted = weighted_tx_vote_amount; + tx_votes_obj.tx_votes = tx_vote_amount; + }); + } + + auto& ygpo = _db.get(); + _db.modify( ygpo, [&]( auto& ygp ) { + ygp.total_tx_votes += tx_vote_amount; + ygp.total_tx_votes_weighted = softfloat64::add( ygp.total_tx_votes_weighted, weighted_tx_vote_amount ); + }); + } + + tx_votes_sum_weighted_type transaction_vote_stat_manager::get_total_weighted_transaction_vote_amount() const { + return _db.get().total_tx_votes_weighted; + } + + tx_vote_stat_for_account transaction_vote_stat_manager::get_transaction_vote_stat_for_account( const transaction_vote_to_name_type vote_target_account ) const { + + auto* tx_votes_ptr = _db.find( vote_target_account ); + if ( tx_votes_ptr ) { + return tx_vote_stat_for_account( vote_target_account, (*tx_votes_ptr).tx_votes_weighted, (*tx_votes_ptr).tx_votes ); + } else { + return tx_vote_stat_for_account( vote_target_account, 0.0, 0 ); + } + } + + tx_vote_receiver_list_result transaction_vote_stat_manager::get_top_sorted_transaction_vote_receivers( const uint32_t offset_rank, const uint32_t limit, const bool retrieve_total_votes ) const { + + tx_vote_receiver_list_result result; + vector& tx_vote_receivers = result.tx_vote_receiver_list; + tx_vote_receivers.reserve( limit ); + + const auto& idx = _db.get_index(); + auto itr = idx.rbegin(); + auto itr_rend = idx.rend(); + + uint32_t skip_cnt = 0; + + while ( itr != itr_rend && tx_vote_receivers.size() < limit ) { + if ( skip_cnt == offset_rank ) { + tx_vote_receivers.emplace_back( itr->account, itr->tx_votes_weighted, itr->tx_votes ); + } else { + skip_cnt++; + } + itr++; + } + + if (itr != itr_rend) { + result.more = true; + } + + if ( retrieve_total_votes ) { + auto& ygpo = _db.get(); + result.total_tx_votes_weighted = ygpo.total_tx_votes_weighted; + result.total_tx_votes = ygpo.total_tx_votes; + } + + return result; + } + + +} } // namespace yosemite::chain diff --git a/libraries/testing/include/eosio/testing/tester.hpp b/libraries/testing/include/eosio/testing/tester.hpp index fffc787b9d..2234cd216a 100644 --- a/libraries/testing/include/eosio/testing/tester.hpp +++ b/libraries/testing/include/eosio/testing/tester.hpp @@ -102,6 +102,17 @@ namespace eosio { namespace testing { void produce_min_num_of_blocks_to_spend_time_wo_inactive_prod(const fc::microseconds target_elapsed_time = fc::microseconds()); signed_block_ptr push_block(signed_block_ptr b); + /** + * These transaction IDs represent transactions available in the head chain state as scheduled + * or otherwise generated transactions. + * + * calling push_scheduled_transaction with these IDs will remove the associated transaction from + * the chain state IFF it succeeds or objectively fails + * + * @return + */ + vector get_scheduled_transactions() const; + transaction_trace_ptr push_transaction( packed_transaction& trx, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US ); transaction_trace_ptr push_transaction( signed_transaction& trx, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US ); action_result push_action(action&& cert_act, uint64_t authorizer); // TODO/QUESTION: Is this needed? diff --git a/libraries/testing/tester.cpp b/libraries/testing/tester.cpp index bcf811434d..a632cb4064 100644 --- a/libraries/testing/tester.cpp +++ b/libraries/testing/tester.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -163,16 +164,16 @@ namespace eosio { namespace testing { } if( !skip_pending_trxs ) { - auto unapplied_trxs = control->get_unapplied_transactions(); - for (const auto& trx : unapplied_trxs ) { - auto trace = control->push_transaction(trx, fc::time_point::maximum()); + unapplied_transactions_type unapplied_trxs = control->get_unapplied_transactions(); // make copy of map + for (const auto& entry : unapplied_trxs ) { + auto trace = control->push_transaction(entry.second, fc::time_point::maximum()); if(trace->except) { trace->except->dynamic_rethrow_exception(); } } vector scheduled_trxs; - while( (scheduled_trxs = control->get_scheduled_transactions() ).size() > 0 ) { + while( (scheduled_trxs = get_scheduled_transactions() ).size() > 0 ) { for (const auto& trx : scheduled_trxs ) { auto trace = control->push_scheduled_transaction(trx, fc::time_point::maximum()); if(trace->except) { @@ -237,6 +238,18 @@ namespace eosio { namespace testing { } } + vector base_tester::get_scheduled_transactions() const { + const auto& idx = control->db().get_index(); + + vector result; + + auto itr = idx.begin(); + while( itr != idx.end() && itr->delay_until <= control->pending_block_time() ) { + result.emplace_back(itr->trx_id); + ++itr; + } + return result; + } void base_tester::produce_blocks_until_end_of_round() { uint64_t blocks_per_round; diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index eb311f7277..f66ca61da9 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -100,6 +100,8 @@ void chain_api_plugin::plugin_startup() { CHAIN_RO_CALL(get_system_token_balance, 200), CHAIN_RO_CALL(get_txfee_item, 200), CHAIN_RO_CALL(get_txfee_list, 200), + CHAIN_RO_CALL(get_tx_vote_stat_for_account, 200), + CHAIN_RO_CALL(get_top_tx_vote_receiver_list, 200), CHAIN_RO_CALL(get_yx_token_balance, 200), CHAIN_RO_CALL(get_yx_token_stats, 200), CHAIN_RO_CALL(get_native_token_balance, 200), diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index cc2957c801..508815111a 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -1387,6 +1389,16 @@ yosemite::chain::tx_fee_list_result read_only::get_txfee_list(const get_txfee_li return yosemite_tx_fee_manager.get_tx_fee_list(params.code_lower_bound, params.code_upper_bound, params.limit); } +yosemite::chain::tx_vote_stat_for_account read_only::get_tx_vote_stat_for_account(const get_tx_vote_stat_for_account_params ¶ms) const { + auto& yosemite_tx_vote_stat_manager = db.get_tx_vote_stat_manager(); + return yosemite_tx_vote_stat_manager.get_transaction_vote_stat_for_account( params.account ); +} + +yosemite::chain::tx_vote_receiver_list_result read_only::get_top_tx_vote_receiver_list(const get_top_tx_vote_receiver_list_params ¶ms) const { + auto& yosemite_tx_vote_stat_manager = db.get_tx_vote_stat_manager(); + return yosemite_tx_vote_stat_manager.get_top_sorted_transaction_vote_receivers( params.offset, params.limit, true ); +} + yx_asset read_only::get_yx_token_balance(const read_only::get_yx_token_balance_params &p) const { yx_symbol target_symbol = yx_symbol::from_string(p.ysymbol); const abi_def abi = eosio::chain_apis::get_abi(db, p.code); @@ -1554,19 +1566,53 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p boost::make_tuple(secondary_table_id->id, lower.value))); }(); + auto& tx_vote_stat_manager = db.get_tx_vote_stat_manager(); + for( ; it != secondary_index_by_secondary.end() && it->t_id == secondary_table_id->id; ++it ) { if (result.rows.size() >= p.limit || fc::time_point::now() > stopTime) { result.more = name{it->primary_key}.to_string(); break; } copy_inline_row(*kv_index.find(boost::make_tuple(table_id->id, it->primary_key)), data); - if (p.json) - result.rows.emplace_back( abis.binary_to_variant( abis.get_table_type(N(producers)), data, abi_serializer_max_time, shorten_abi_errors ) ); - else - result.rows.emplace_back(fc::variant(data)); +// if (p.json) +// result.rows.emplace_back( abis.binary_to_variant( abis.get_table_type(N(producers)), data, abi_serializer_max_time, shorten_abi_errors ) ); +// else +// result.rows.emplace_back(fc::variant(data)); + + auto producer_item = abis.binary_to_variant( abis.get_table_type(N(producers)), data, abi_serializer_max_time, shorten_abi_errors ); + +// account_name owner; +// double total_votes = 0; +// double total_votes_weight = 0; +// eosio::public_key producer_key; /// a packed public key object +// bool is_active = true; +// bool is_trusted_seed = false; // authorized flag for permissioned setup +// std::string url; +// uint32_t unpaid_blocks = 0; +// uint64_t last_claim_time = 0; +// uint16_t location = 0; + + auto owner = producer_item["owner"]; + account_name producer_account_name(owner.as_string()); + auto tx_vote_receiver_stat = tx_vote_stat_manager.get_transaction_vote_stat_for_account(producer_account_name); + + result.rows.emplace_back( + fc::mutable_variant_object("owner", owner) + ("total_votes_weight", tx_vote_receiver_stat.tx_votes_weighted) + ("total_votes", tx_vote_receiver_stat.tx_votes) + ("producer_key", producer_item["producer_key"]) + ("is_active", producer_item["is_active"]) + ("is_trusted_seed", producer_item["is_trusted_seed"]) + ("url", producer_item["url"]) + ("unpaid_blocks", producer_item["unpaid_blocks"]) + ("last_claim_time", producer_item["last_claim_time"]) + ("location", producer_item["location"]) + ); } - result.total_producer_vote_weight = get_global_row(d, abi, abis, abi_serializer_max_time, shorten_abi_errors)["total_producer_vote_weight"].as_double(); +// result.total_producer_vote_weight = get_global_row(d, abi, abis, abi_serializer_max_time, shorten_abi_errors)["total_producer_vote_weight"].as_double(); + result.total_producer_vote_weight = db.get_yosemite_global_properties().total_tx_votes_weighted; + return result; } diff --git a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp index a09d884db9..f5b3444f98 100644 --- a/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eosio/chain_plugin/chain_plugin.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -375,6 +376,19 @@ class read_only { yosemite::chain::tx_fee_list_result get_txfee_list(const get_txfee_list_params ¶ms) const; + struct get_tx_vote_stat_for_account_params { + name account; + }; + + yosemite::chain::tx_vote_stat_for_account get_tx_vote_stat_for_account(const get_tx_vote_stat_for_account_params ¶ms) const; + + struct get_top_tx_vote_receiver_list_params { + uint32_t offset = 0; + uint32_t limit = 30; + }; + + yosemite::chain::tx_vote_receiver_list_result get_top_tx_vote_receiver_list(const get_top_tx_vote_receiver_list_params ¶ms) const; + struct get_yx_token_balance_params { name code; name account; @@ -818,6 +832,8 @@ FC_REFLECT(eosio::chain_apis::read_only::get_system_token_list_params, (token_me FC_REFLECT(eosio::chain_apis::read_only::get_system_token_balance_params, (account)); FC_REFLECT(eosio::chain_apis::read_only::get_txfee_item_params, (code)(action)); FC_REFLECT(eosio::chain_apis::read_only::get_txfee_list_params, (code_lower_bound)(code_upper_bound)(limit)); +FC_REFLECT(eosio::chain_apis::read_only::get_tx_vote_stat_for_account_params, (account)); +FC_REFLECT(eosio::chain_apis::read_only::get_top_tx_vote_receiver_list_params, (offset)(limit)); FC_REFLECT(eosio::chain_apis::read_only::get_yx_token_balance_params, (code)(account)(ysymbol)); FC_REFLECT(eosio::chain_apis::read_only::get_yx_token_stats_params, (code)(ysymbol)); FC_REFLECT(eosio::chain_apis::read_only::get_yx_token_stats_result, (supply)(can_set_options)(options)(kyc_rule_types)(kyc_rule_flags)); diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 4f6f6e458b..7d6ce50800 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -283,6 +283,10 @@ namespace eosio { */ constexpr auto def_send_buffer_size_mb = 4; constexpr auto def_send_buffer_size = 1024*1024*def_send_buffer_size_mb; + constexpr auto def_max_write_queue_size = def_send_buffer_size*10; + constexpr boost::asio::chrono::milliseconds def_read_delay_for_full_write_queue{100}; + constexpr auto def_max_reads_in_flight = 1000; + constexpr auto def_max_trx_in_progress_size = 100*1024*1024; // 100 MB constexpr auto def_max_clients = 25; // 0 for unlimited clients constexpr auto def_max_nodes_per_host = 1; constexpr auto def_conn_retry_wait = 30; @@ -400,6 +404,86 @@ namespace eosio { static void populate(handshake_message &hello); }; + class queued_buffer : boost::noncopyable { + public: + void clear_write_queue() { + _write_queue.clear(); + _sync_write_queue.clear(); + _write_queue_size = 0; + } + + void clear_out_queue() { + while ( _out_queue.size() > 0 ) { + _out_queue.pop_front(); + } + } + + uint32_t write_queue_size() const { return _write_queue_size; } + + bool is_out_queue_empty() const { return _out_queue.empty(); } + + bool ready_to_send() const { + // if out_queue is not empty then async_write is in progress + return ((!_sync_write_queue.empty() || !_write_queue.empty()) && _out_queue.empty()); + } + + bool add_write_queue( const std::shared_ptr>& buff, + std::function callback, + bool to_sync_queue ) { + if( to_sync_queue ) { + _sync_write_queue.push_back( {buff, callback} ); + } else { + _write_queue.push_back( {buff, callback} ); + } + _write_queue_size += buff->size(); + if( _write_queue_size > 2 * def_max_write_queue_size ) { + return false; + } + return true; + } + + void fill_out_buffer( std::vector& bufs ) { + if( _sync_write_queue.size() > 0 ) { // always send msgs from sync_write_queue first + fill_out_buffer( bufs, _sync_write_queue ); + } else { // postpone real_time write_queue if sync queue is not empty + fill_out_buffer( bufs, _write_queue ); + EOS_ASSERT( _write_queue_size == 0, plugin_exception, "write queue size expected to be zero" ); + } + } + + void out_callback( boost::system::error_code ec, std::size_t w ) { + for( auto& m : _out_queue ) { + m.callback( ec, w ); + } + } + + private: + struct queued_write; + void fill_out_buffer( std::vector& bufs, + deque& w_queue ) { + while ( w_queue.size() > 0 ) { + auto& m = w_queue.front(); + bufs.push_back( boost::asio::buffer( *m.buff )); + _write_queue_size -= m.buff->size(); + _out_queue.emplace_back( m ); + w_queue.pop_front(); + } + } + + private: + struct queued_write { + std::shared_ptr> buff; + std::function callback; + }; + + uint32_t _write_queue_size = 0; + deque _write_queue; + deque _sync_write_queue; // sync_write_queue will be sent first + deque _out_queue; + + }; // queued_buffer + + class connection : public std::enable_shared_from_this { public: explicit connection( string endpoint ); @@ -416,12 +500,11 @@ namespace eosio { fc::message_buffer<1024*1024> pending_message_buffer; fc::optional outstanding_read_bytes; - struct queued_write { - std::shared_ptr> buff; - std::function callback; - }; - deque write_queue; - deque out_queue; + + queued_buffer buffer_queue; + + uint32_t reads_in_flight = 0; + uint32_t trx_in_progress_size = 0; fc::sha256 node_id; handshake_message last_handshake_recv; handshake_message last_handshake_sent; @@ -431,6 +514,7 @@ namespace eosio { uint16_t protocol_version = 0; string peer_addr; unique_ptr response_expected; + unique_ptr read_delay_timer; optional pending_fetch; go_away_reason no_retry = no_reason; block_id_type fork_head; @@ -497,12 +581,14 @@ namespace eosio { void txn_send(const vector& txn_lis); void blk_send_branch(); - void blk_send(const vector &txn_lis); + void blk_send(const block_id_type& blkid); void stop_send(); void enqueue( const net_message &msg, bool trigger_send = true ); - void enqueue_block( const signed_block_ptr& sb, bool trigger_send = true ); - void enqueue_buffer( const std::shared_ptr>& send_buffer, bool trigger_send, go_away_reason close_after_send ); + void enqueue_block( const signed_block_ptr& sb, bool trigger_send = true, bool to_sync_queue = false ); + void enqueue_buffer( const std::shared_ptr>& send_buffer, + bool trigger_send, go_away_reason close_after_send, + bool to_sync_queue = false); void cancel_sync(go_away_reason); void flush_queues(); bool enqueue_sync_block(); @@ -516,7 +602,8 @@ namespace eosio { void queue_write(const std::shared_ptr>& buff, bool trigger_send, - std::function callback); + std::function callback, + bool to_sync_queue = false); void do_queue_write(); /** \brief Process the next message from the pending message buffer @@ -530,7 +617,7 @@ namespace eosio { */ bool process_next_message(net_plugin_impl& impl, uint32_t message_length); - bool add_peer_block(const peer_block_state &pbs); + bool add_peer_block(const peer_block_state& pbs); fc::optional _logger_variant; const fc::variant_object& get_logger_variant() { @@ -637,6 +724,7 @@ namespace eosio { void rejected_block(const block_id_type& id); void recv_block(const connection_ptr& conn, const block_id_type& msg, uint32_t bnum); + void expire_blocks( uint32_t bnum ); void recv_transaction(const connection_ptr& conn, const transaction_id_type& id); void recv_notice(const connection_ptr& conn, const notice_message& msg, bool generated); @@ -659,6 +747,7 @@ namespace eosio { protocol_version(0), peer_addr(endpoint), response_expected(), + read_delay_timer(), pending_fetch(), no_retry(no_reason), fork_head(), @@ -683,6 +772,7 @@ namespace eosio { protocol_version(0), peer_addr(), response_expected(), + read_delay_timer(), pending_fetch(), no_retry(no_reason), fork_head(), @@ -699,6 +789,7 @@ namespace eosio { auto *rnd = node_id.data(); rnd[0] = 0; response_expected.reset(new boost::asio::steady_timer(app().get_io_service())); + read_delay_timer.reset(new boost::asio::steady_timer(app().get_io_service())); } bool connection::connected() { @@ -716,7 +807,7 @@ namespace eosio { } void connection::flush_queues() { - write_queue.clear(); + buffer_queue.clear_write_queue(); } void connection::close() { @@ -739,6 +830,7 @@ namespace eosio { my_impl->sync_master->reset_lib_num(shared_from_this()); fc_dlog(logger, "canceling wait on ${p}", ("p",peer_name())); cancel_wait(); + if( read_delay_timer ) read_delay_timer->cancel(); pending_message_buffer.reset(); } @@ -803,75 +895,43 @@ namespace eosio { catch (...) { } - vector bstack; - block_id_type null_id; - for (auto bid = head_id; bid != null_id && bid != lib_id; ) { - try { - - // if the last handshake received indicates that we are catching up on a fork - // that the peer is already partially aware of, no need to resend blocks - if (remote_head_id == bid) { - break; - } - - signed_block_ptr b = cc.fetch_block_by_id(bid); - if ( b ) { - bid = b->previous; - bstack.push_back(b); - } - else { - break; - } - } catch (...) { - break; - } - } - size_t count = 0; - if (!bstack.empty()) { - if (bstack.back()->previous == lib_id || bstack.back()->previous == remote_head_id) { - count = bstack.size(); - while (bstack.size()) { - enqueue_block( bstack.back() ); - bstack.pop_back(); - } - } - fc_ilog(logger, "Sent ${n} blocks on my fork",("n",count)); + if( !peer_requested ) { + peer_requested = sync_state( block_header::num_from_id(lib_id)+1, + block_header::num_from_id(head_id), + block_header::num_from_id(lib_id) ); } else { - fc_ilog(logger, "Nothing to send on fork request"); + uint32_t start = std::min( peer_requested->last + 1, block_header::num_from_id(lib_id)+1 ); + uint32_t end = std::max( peer_requested->end_block, block_header::num_from_id(head_id) ); + peer_requested = sync_state( start, end, start - 1 ); } + enqueue_sync_block(); + // still want to send transactions along during blk branch sync syncing = false; } - void connection::blk_send(const vector &ids) { + void connection::blk_send(const block_id_type& blkid) { controller &cc = my_impl->chain_plug->chain(); - int count = 0; - for(auto &blkid : ids) { - ++count; - try { - signed_block_ptr b = cc.fetch_block_by_id(blkid); - if(b) { - fc_dlog(logger,"found block for id at num ${n}",("n",b->block_num())); - enqueue_block( b ); - } - else { - ilog("fetch block by id returned null, id ${id} on block ${c} of ${s} for ${p}", - ("id",blkid)("c",count)("s",ids.size())("p",peer_name())); - break; - } - } - catch (const assert_exception &ex) { - elog( "caught assert on fetch_block_by_id, ${ex}, id ${id} on block ${c} of ${s} for ${p}", - ("ex",ex.to_string())("id",blkid)("c",count)("s",ids.size())("p",peer_name())); - break; - } - catch (...) { - elog( "caught othser exception fetching block id ${id} on block ${c} of ${s} for ${p}", - ("id",blkid)("c",count)("s",ids.size())("p",peer_name())); - break; + try { + signed_block_ptr b = cc.fetch_block_by_id(blkid); + if(b) { + fc_dlog(logger,"found block for id at num ${n}",("n",b->block_num())); + peer_block_state pbstate = {blkid, block_header::num_from_id(blkid), true, true, time_point()}; + add_peer_block(pbstate); + enqueue_block( b ); + } else { + ilog("fetch block by id returned null, id ${id} for ${p}", + ("id",blkid)("p",peer_name())); } } - + catch (const assert_exception &ex) { + elog( "caught assert on fetch_block_by_id, ${ex}, id ${id} for ${p}", + ("ex",ex.to_string())("id",blkid)("p",peer_name())); + } + catch (...) { + elog( "caught other exception fetching block id ${id} for ${p}", + ("id",blkid)("p",peer_name())); + } } void connection::stop_send() { @@ -905,14 +965,21 @@ namespace eosio { void connection::queue_write(const std::shared_ptr>& buff, bool trigger_send, - std::function callback) { - write_queue.push_back({buff, callback}); - if(out_queue.empty() && trigger_send) + std::function callback, + bool to_sync_queue) { + if( !buffer_queue.add_write_queue( buff, callback, to_sync_queue )) { + fc_wlog( logger, "write_queue full ${s} bytes, giving up on connection ${p}", + ("s", buffer_queue.write_queue_size())("p", peer_name()) ); + my_impl->close( shared_from_this() ); + return; + } + if( buffer_queue.is_out_queue_empty() && trigger_send) { do_queue_write(); + } } void connection::do_queue_write() { - if(write_queue.empty() || !out_queue.empty()) + if( !buffer_queue.ready_to_send() ) return; connection_wptr c(shared_from_this()); if(!socket->is_open()) { @@ -921,21 +988,14 @@ namespace eosio { return; } std::vector bufs; - while (write_queue.size() > 0) { - auto& m = write_queue.front(); - bufs.push_back(boost::asio::buffer(*m.buff)); - out_queue.push_back(m); - write_queue.pop_front(); - } + buffer_queue.fill_out_buffer( bufs ); boost::asio::async_write(*socket, bufs, [c](boost::system::error_code ec, std::size_t w) { try { auto conn = c.lock(); if(!conn) return; - for (auto& m: conn->out_queue) { - m.callback(ec, w); - } + conn->buffer_queue.out_callback( ec, w ); if(ec) { string pname = conn ? conn->peer_name() : "no connection name"; @@ -948,9 +1008,7 @@ namespace eosio { my_impl->close(conn); return; } - while (conn->out_queue.size() > 0) { - conn->out_queue.pop_front(); - } + conn->buffer_queue.clear_out_queue(); conn->enqueue_sync_block(); conn->do_queue_write(); } @@ -973,8 +1031,8 @@ namespace eosio { } void connection::cancel_sync(go_away_reason reason) { - fc_dlog(logger,"cancel sync reason = ${m}, write queue size ${o} peer ${p}", - ("m",reason_str(reason)) ("o", write_queue.size())("p", peer_name())); + fc_dlog(logger,"cancel sync reason = ${m}, write queue size ${o} bytes peer ${p}", + ("m",reason_str(reason)) ("o", buffer_queue.write_queue_size())("p", peer_name())); cancel_wait(); flush_queues(); switch (reason) { @@ -1002,7 +1060,7 @@ namespace eosio { controller& cc = my_impl->chain_plug->chain(); signed_block_ptr sb = cc.fetch_block_by_number(num); if(sb) { - enqueue_block( sb, trigger_send); + enqueue_block( sb, trigger_send, true); return true; } } catch ( ... ) { @@ -1031,7 +1089,7 @@ namespace eosio { enqueue_buffer( send_buffer, trigger_send, close_after_send ); } - void connection::enqueue_block( const signed_block_ptr& sb, bool trigger_send ) { + void connection::enqueue_block( const signed_block_ptr& sb, bool trigger_send, bool to_sync_queue ) { // this implementation is to avoid copy of signed_block to net_message int which = 7; // matches which of net_message for signed_block @@ -1048,10 +1106,13 @@ namespace eosio { fc::raw::pack( ds, unsigned_int( which )); fc::raw::pack( ds, *sb ); - enqueue_buffer( send_buffer, trigger_send, no_reason ); + enqueue_buffer( send_buffer, trigger_send, no_reason, to_sync_queue ); } - void connection::enqueue_buffer( const std::shared_ptr>& send_buffer, bool trigger_send, go_away_reason close_after_send ) { + void connection::enqueue_buffer( const std::shared_ptr>& send_buffer, bool trigger_send, + go_away_reason close_after_send, + bool to_sync_queue ) + { connection_wptr weak_this = shared_from_this(); queue_write(send_buffer,trigger_send, [weak_this, close_after_send](boost::system::error_code ec, std::size_t ) { @@ -1065,7 +1126,8 @@ namespace eosio { } else { fc_wlog(logger, "connection expired before enqueued net_message called callback!"); } - }); + }, + to_sync_queue); } void connection::cancel_wait() { @@ -1165,7 +1227,7 @@ namespace eosio { return true; } - bool connection::add_peer_block(const peer_block_state &entry) { + bool connection::add_peer_block(const peer_block_state& entry) { auto bptr = blk_state.get().find(entry.id); bool added = (bptr == blk_state.end()); if (added){ @@ -1476,11 +1538,15 @@ namespace eosio { void sync_manager::recv_notice(const connection_ptr& c, const notice_message& msg) { fc_ilog(logger, "sync_manager got ${m} block notice",("m",modes_str(msg.known_blocks.mode))); + if( msg.known_blocks.ids.size() > 1 ) { + elog( "Invalid notice_message, known_blocks.ids.size ${s}", ("s", msg.known_blocks.ids.size()) ); + my_impl->close(c); + return; + } if (msg.known_blocks.mode == catch_up) { if (msg.known_blocks.ids.size() == 0) { elog("got a catch up with ids size = 0"); - } - else { + } else { verify_catchup(c, msg.known_blocks.pending, msg.known_blocks.ids.back()); } } @@ -1591,11 +1657,23 @@ namespace eosio { } void dispatch_manager::rejected_block(const block_id_type& id) { - fc_dlog(logger,"not sending rejected transaction ${tid}",("tid",id)); + fc_dlog( logger, "rejected block ${id}", ("id", id) ); auto range = received_blocks.equal_range(id); received_blocks.erase(range.first, range.second); } + void dispatch_manager::expire_blocks( uint32_t lib_num ) { + for( auto i = received_blocks.begin(); i != received_blocks.end(); ) { + const block_id_type& blk_id = i->first; + uint32_t blk_num = block_header::num_from_id( blk_id ); + if( blk_num <= lib_num ) { + i = received_blocks.erase( i ); + } else { + ++i; + } + } + } + void dispatch_manager::bcast_transaction(const transaction_metadata_ptr& ptrx) { std::set skips; const auto& id = ptrx->id; @@ -1685,7 +1763,9 @@ namespace eosio { if (msg.known_blocks.mode == normal) { req.req_blocks.mode = normal; controller& cc = my_impl->chain_plug->chain(); - for( const auto& blkid : msg.known_blocks.ids) { + // known_blocks.ids is never > 1 + if( !msg.known_blocks.ids.empty() ) { + const block_id_type& blkid = msg.known_blocks.ids.back(); signed_block_ptr b; peer_block_state entry = {blkid,0,true,true,fc::time_point()}; try { @@ -1952,6 +2032,37 @@ namespace eosio { } }; + if( conn->buffer_queue.write_queue_size() > def_max_write_queue_size || + conn->reads_in_flight > def_max_reads_in_flight || + conn->trx_in_progress_size > def_max_trx_in_progress_size ) + { + // too much queued up, reschedule + if( conn->buffer_queue.write_queue_size() > def_max_write_queue_size ) { + peer_wlog( conn, "write_queue full ${s} bytes", ("s", conn->buffer_queue.write_queue_size()) ); + } else if( conn->reads_in_flight > def_max_reads_in_flight ) { + peer_wlog( conn, "max reads in flight ${s}", ("s", conn->reads_in_flight) ); + } else { + peer_wlog( conn, "max trx in progress ${s} bytes", ("s", conn->trx_in_progress_size) ); + } + if( conn->buffer_queue.write_queue_size() > 2*def_max_write_queue_size || + conn->reads_in_flight > 2*def_max_reads_in_flight || + conn->trx_in_progress_size > 2*def_max_trx_in_progress_size ) + { + fc_wlog( logger, "queues over full, giving up on connection ${p}", ("p", conn->peer_name()) ); + my_impl->close( conn ); + return; + } + if( !conn->read_delay_timer ) return; + conn->read_delay_timer->expires_from_now( def_read_delay_for_full_write_queue ); + conn->read_delay_timer->async_wait([this, weak_conn]( boost::system::error_code ) { + auto conn = weak_conn.lock(); + if( !conn ) return; + start_read_message( conn ); + } ); + return; + } + + ++conn->reads_in_flight; boost::asio::async_read(*conn->socket, conn->pending_message_buffer.get_buffer_sequence_for_boost_async_read(), completion_handler, [this,weak_conn]( boost::system::error_code ec, std::size_t bytes_transferred ) { @@ -1960,6 +2071,7 @@ namespace eosio { return; } + --conn->reads_in_flight; conn->outstanding_read_bytes.reset(); try { @@ -2308,6 +2420,12 @@ namespace eosio { } void net_plugin_impl::handle_message(const connection_ptr& c, const request_message& msg) { + if( msg.req_blocks.ids.size() > 1 ) { + elog( "Invalid request_message, req_blocks.ids.size ${s}", ("s", msg.req_blocks.ids.size()) ); + close(c); + return; + } + switch (msg.req_blocks.mode) { case catch_up : peer_ilog(c, "received request_message:catch_up"); @@ -2315,7 +2433,9 @@ namespace eosio { break; case normal : peer_ilog(c, "received request_message:normal"); - c->blk_send(msg.req_blocks.ids); + if( !msg.req_blocks.ids.empty() ) { + c->blk_send(msg.req_blocks.ids.back()); + } break; default:; } @@ -2347,6 +2467,13 @@ namespace eosio { } } + size_t calc_trx_size( const packed_transaction_ptr& trx ) { + // transaction is stored packed and unpacked, double packed_size and size of signed as an approximation of use + return (trx->get_packed_transaction().size() * 2 + sizeof(trx->get_signed_transaction())) * 2 + + trx->get_packed_context_free_data().size() * 4 + + trx->get_signatures().size() * sizeof(signature_type); + } + void net_plugin_impl::handle_message(const connection_ptr& c, const packed_transaction_ptr& trx) { fc_dlog(logger, "got a packed transaction, cancel wait"); peer_ilog(c, "received packed_transaction"); @@ -2369,7 +2496,9 @@ namespace eosio { return; } dispatcher->recv_transaction(c, tid); + c->trx_in_progress_size += calc_trx_size( ptrx->packed_trx ); chain_plug->accept_transaction(ptrx, [c, this, ptrx](const static_variant& result) { + c->trx_in_progress_size -= calc_trx_size( ptrx->packed_trx ); if (result.contains()) { peer_dlog(c, "bad packed_transaction : ${m}", ("m",result.get()->what())); } else { @@ -2449,6 +2578,7 @@ namespace eosio { } else { sync_master->rejected_block(c, blk_num); + dispatcher->rejected_block( blk_id ); } } @@ -2510,6 +2640,7 @@ namespace eosio { controller& cc = chain_plug->chain(); uint32_t lib = cc.last_irreversible_block_num(); + dispatcher->expire_blocks( lib ); for ( auto &c : connections ) { auto &stale_txn = c->trx_state.get(); stale_txn.erase( stale_txn.lower_bound(1), stale_txn.upper_bound(lib) ); diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 50fb078125..ea643676a8 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -1143,6 +1144,10 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { int orig_count = _persistent_transactions.size(); while(!persisted_by_expiry.empty() && persisted_by_expiry.begin()->expiry <= pbs->header.timestamp.to_time_point()) { + if (preprocess_deadline <= fc::time_point::now()) { + exhausted = true; + break; + } auto const& txid = persisted_by_expiry.begin()->trx_id; if (_pending_block_mode == pending_block_mode::producing) { fc_dlog(_trx_trace_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} is EXPIRING PERSISTED tx: ${txid}", @@ -1158,9 +1163,15 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { num_expired_persistent++; } - fc_dlog(_log, "Processed ${n} persisted transactions, Expired ${expired}", - ("n", orig_count) - ("expired", num_expired_persistent)); + if( exhausted ) { + fc_wlog( _log, "Unable to process all ${n} persisted transactions before deadline, Expired ${expired}", + ( "n", orig_count ) + ( "expired", num_expired_persistent ) ); + } else { + fc_dlog( _log, "Processed ${n} persisted transactions, Expired ${expired}", + ( "n", orig_count ) + ( "expired", num_expired_persistent ) ); + } } try { @@ -1171,13 +1182,15 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { if (_producers.empty() && persisted_by_id.empty()) { // if this node can never produce and has no persisted transactions, // there is no need for unapplied transactions they can be dropped - chain.drop_all_unapplied_transactions(); + chain.get_unapplied_transactions().clear(); } else { - std::vector apply_trxs; - { // derive appliable transactions from unapplied_transactions and drop droppable transactions - auto unapplied_trxs = chain.get_unapplied_transactions(); - apply_trxs.reserve(unapplied_trxs.size()); - + // derive appliable transactions from unapplied_transactions and drop droppable transactions + unapplied_transactions_type& unapplied_trxs = chain.get_unapplied_transactions(); + if( !unapplied_trxs.empty() ) { + auto unapplied_trxs_size = unapplied_trxs.size(); + int num_applied = 0; + int num_failed = 0; + int num_processed = 0; auto calculate_transaction_category = [&](const transaction_metadata_ptr& trx) { if (trx->packed_trx->expiration() < pbs->header.timestamp.to_time_point()) { return tx_category::EXPIRED; @@ -1188,64 +1201,65 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { } }; - for (auto& trx: unapplied_trxs) { + auto itr = unapplied_trxs.begin(); + while( itr != unapplied_trxs.end() ) { + auto itr_next = itr; // save off next since itr may be invalidated by loop + ++itr_next; + + if( preprocess_deadline <= fc::time_point::now() ) exhausted = true; + if( exhausted ) break; + const auto& trx = itr->second; auto category = calculate_transaction_category(trx); - if (category == tx_category::EXPIRED || (category == tx_category::UNEXPIRED_UNPERSISTED && _producers.empty())) { + if (category == tx_category::EXPIRED || + (category == tx_category::UNEXPIRED_UNPERSISTED && _producers.empty())) + { if (!_producers.empty()) { fc_dlog(_trx_trace_log, "[TRX_TRACE] Node with producers configured is dropping an EXPIRED transaction that was PREVIOUSLY ACCEPTED : ${txid}", ("txid", trx->id)); } - chain.drop_unapplied_transaction(trx); - } else if (category == tx_category::PERSISTED || (category == tx_category::UNEXPIRED_UNPERSISTED && _pending_block_mode == pending_block_mode::producing)) { - apply_trxs.emplace_back(std::move(trx)); - } - } - } - - if (!apply_trxs.empty()) { - int num_applied = 0; - int num_failed = 0; - int num_processed = 0; - - for (const auto& trx: apply_trxs) { - if (preprocess_deadline <= fc::time_point::now()) exhausted = true; - if (exhausted) { - break; - } - - num_processed++; - - try { - auto deadline = fc::time_point::now() + fc::milliseconds(_max_transaction_time_ms); - bool deadline_is_subjective = false; - if (_max_transaction_time_ms < 0 || (_pending_block_mode == pending_block_mode::producing && preprocess_deadline < deadline)) { - deadline_is_subjective = true; - deadline = preprocess_deadline; - } + itr = unapplied_trxs.erase( itr ); // unapplied_trxs map has not been modified, so simply erase and continue + continue; + } else if (category == tx_category::PERSISTED || + (category == tx_category::UNEXPIRED_UNPERSISTED && _pending_block_mode == pending_block_mode::producing)) + { + ++num_processed; + + try { + auto deadline = fc::time_point::now() + fc::milliseconds(_max_transaction_time_ms); + bool deadline_is_subjective = false; + if (_max_transaction_time_ms < 0 || (_pending_block_mode == pending_block_mode::producing && preprocess_deadline < deadline)) { + deadline_is_subjective = true; + deadline = preprocess_deadline; + } - auto trace = chain.push_transaction(trx, deadline); - if (trace->except) { - if (failure_is_subjective(*trace->except, deadline_is_subjective)) { - exhausted = true; + auto trace = chain.push_transaction(trx, deadline); + if (trace->except) { + if (failure_is_subjective(*trace->except, deadline_is_subjective)) { + exhausted = true; + break; + } else { + // this failed our configured maximum transaction time, we don't want to replay it + // chain.plus_transactions can modify unapplied_trxs, so erase by id + unapplied_trxs.erase( trx->signed_id ); + ++num_failed; + } } else { - // this failed our configured maximum transaction time, we don't want to replay it - chain.drop_unapplied_transaction(trx); - num_failed++; + ++num_applied; } - } else { - num_applied++; - } - } catch ( const guard_exception& e ) { - chain_plug->handle_guard_exception(e); - return start_block_result::failed; - } FC_LOG_AND_DROP(); + } catch ( const guard_exception& e ) { + chain_plug->handle_guard_exception(e); + return start_block_result::failed; + } FC_LOG_AND_DROP(); + } + + itr = itr_next; } fc_dlog(_log, "Processed ${m} of ${n} previously applied transactions, Applied ${applied}, Failed/Dropped ${failed}", - ("m", num_processed) - ("n", apply_trxs.size()) - ("applied", num_applied) - ("failed", num_failed)); + ("m", num_processed) + ("n", unapplied_trxs_size) + ("applied", num_applied) + ("failed", num_failed)); } } @@ -1258,6 +1272,7 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { int orig_count = _blacklisted_transactions.size(); while (!blacklist_by_expiry.empty() && blacklist_by_expiry.begin()->expiry <= now) { + if (preprocess_deadline <= fc::time_point::now()) break; blacklist_by_expiry.erase(blacklist_by_expiry.begin()); num_expired++; } @@ -1267,85 +1282,105 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { ("expired", num_expired)); } - auto scheduled_trxs = chain.get_scheduled_transactions(); - if (!scheduled_trxs.empty()) { - int num_applied = 0; - int num_failed = 0; - int num_processed = 0; + // scheduled transactions + int num_applied = 0; + int num_failed = 0; + int num_processed = 0; + + auto scheduled_trx_deadline = preprocess_deadline; + if (_max_scheduled_transaction_time_per_block_ms >= 0) { + scheduled_trx_deadline = std::min( + scheduled_trx_deadline, + fc::time_point::now() + fc::milliseconds(_max_scheduled_transaction_time_per_block_ms) + ); + } + time_point pending_block_time = chain.pending_block_time(); + const auto& sch_idx = chain.db().get_index(); + const auto scheduled_trxs_size = sch_idx.size(); + auto sch_itr = sch_idx.begin(); + while( sch_itr != sch_idx.end() ) { + if( sch_itr->delay_until > pending_block_time) break; // not scheduled yet + if( sch_itr->published >= pending_block_time ) { + ++sch_itr; + continue; // do not allow schedule and execute in same block + } + if( scheduled_trx_deadline <= fc::time_point::now() ) { + exhausted = true; + break; + } - auto scheduled_trx_deadline = preprocess_deadline; - if (_max_scheduled_transaction_time_per_block_ms >= 0) { - scheduled_trx_deadline = std::min( - scheduled_trx_deadline, - fc::time_point::now() + fc::milliseconds(_max_scheduled_transaction_time_per_block_ms) - ); + const transaction_id_type trx_id = sch_itr->trx_id; // make copy since reference could be invalidated + if (blacklist_by_id.find(trx_id) != blacklist_by_id.end()) { + ++sch_itr; + continue; } - for (const auto& trx : scheduled_trxs) { - if (scheduled_trx_deadline <= fc::time_point::now()) exhausted = true; - if (exhausted) { - break; - } + auto sch_itr_next = sch_itr; // save off next since sch_itr may be invalidated by loop + ++sch_itr_next; + const auto next_delay_until = sch_itr_next != sch_idx.end() ? sch_itr_next->delay_until : sch_itr->delay_until; + const auto next_id = sch_itr_next != sch_idx.end() ? sch_itr_next->id : sch_itr->id; - num_processed++; + num_processed++; - // configurable ratio of incoming txns vs deferred txns - while (_incoming_trx_weight >= 1.0 && orig_pending_txn_size && _pending_incoming_transactions.size()) { - if (scheduled_trx_deadline <= fc::time_point::now()) break; + // configurable ratio of incoming txns vs deferred txns + while (_incoming_trx_weight >= 1.0 && orig_pending_txn_size && _pending_incoming_transactions.size()) { + if (scheduled_trx_deadline <= fc::time_point::now()) break; - auto e = _pending_incoming_transactions.front(); - _pending_incoming_transactions.pop_front(); - --orig_pending_txn_size; - _incoming_trx_weight -= 1.0; - process_incoming_transaction_async(std::get<0>(e), std::get<1>(e), std::get<2>(e)); - } + auto e = _pending_incoming_transactions.front(); + _pending_incoming_transactions.pop_front(); + --orig_pending_txn_size; + _incoming_trx_weight -= 1.0; + process_incoming_transaction_async(std::get<0>(e), std::get<1>(e), std::get<2>(e)); + } - if (scheduled_trx_deadline <= fc::time_point::now()) { - exhausted = true; - break; - } + if (scheduled_trx_deadline <= fc::time_point::now()) { + exhausted = true; + break; + } - if (blacklist_by_id.find(trx) != blacklist_by_id.end()) { - continue; + try { + auto deadline = fc::time_point::now() + fc::milliseconds(_max_transaction_time_ms); + bool deadline_is_subjective = false; + if (_max_transaction_time_ms < 0 || (_pending_block_mode == pending_block_mode::producing && scheduled_trx_deadline < deadline)) { + deadline_is_subjective = true; + deadline = scheduled_trx_deadline; } - try { - auto deadline = fc::time_point::now() + fc::milliseconds(_max_transaction_time_ms); - bool deadline_is_subjective = false; - if (_max_transaction_time_ms < 0 || (_pending_block_mode == pending_block_mode::producing && scheduled_trx_deadline < deadline)) { - deadline_is_subjective = true; - deadline = scheduled_trx_deadline; - } - - auto trace = chain.push_scheduled_transaction(trx, deadline); - if (trace->except) { - if (failure_is_subjective(*trace->except, deadline_is_subjective)) { - exhausted = true; - } else { - auto expiration = fc::time_point::now() + fc::seconds(chain.get_global_properties().configuration.deferred_trx_expiration_window); - // this failed our configured maximum transaction time, we don't want to replay it add it to a blacklist - _blacklisted_transactions.insert(transaction_id_with_expiry{trx, expiration}); - num_failed++; - } + auto trace = chain.push_scheduled_transaction(trx_id, deadline); + if (trace->except) { + if (failure_is_subjective(*trace->except, deadline_is_subjective)) { + exhausted = true; + break; } else { - num_applied++; + auto expiration = fc::time_point::now() + fc::seconds(chain.get_global_properties().configuration.deferred_trx_expiration_window); + // this failed our configured maximum transaction time, we don't want to replay it add it to a blacklist + _blacklisted_transactions.insert(transaction_id_with_expiry{trx_id, expiration}); + num_failed++; } - } catch ( const guard_exception& e ) { - chain_plug->handle_guard_exception(e); - return start_block_result::failed; - } FC_LOG_AND_DROP(); + } else { + num_applied++; + } + } catch ( const guard_exception& e ) { + chain_plug->handle_guard_exception(e); + return start_block_result::failed; + } FC_LOG_AND_DROP(); - _incoming_trx_weight += _incoming_defer_ratio; - if (!orig_pending_txn_size) _incoming_trx_weight = 0.0; - } + _incoming_trx_weight += _incoming_defer_ratio; + if (!orig_pending_txn_size) _incoming_trx_weight = 0.0; - fc_dlog(_log, "Processed ${m} of ${n} scheduled transactions, Applied ${applied}, Failed/Dropped ${failed}", - ("m", num_processed) - ("n", scheduled_trxs.size()) - ("applied", num_applied) - ("failed", num_failed)); + if( sch_itr_next == sch_idx.end() ) break; + sch_itr = sch_idx.lower_bound( boost::make_tuple( next_delay_until, next_id ) ); + } + if( scheduled_trxs_size > 0 ) { + fc_dlog( _log, + "Processed ${m} of ${n} scheduled transactions, Applied ${applied}, Failed/Dropped ${failed}", + ( "m", num_processed ) + ( "n", scheduled_trxs_size ) + ( "applied", num_applied ) + ( "failed", num_failed ) ); } + } if (exhausted || preprocess_deadline <= fc::time_point::now()) { @@ -1357,11 +1392,11 @@ producer_plugin_impl::start_block_result producer_plugin_impl::start_block() { if (!_pending_incoming_transactions.empty()) { fc_dlog(_log, "Processing ${n} pending transactions"); while (orig_pending_txn_size && _pending_incoming_transactions.size()) { + if (preprocess_deadline <= fc::time_point::now()) return start_block_result::exhausted; auto e = _pending_incoming_transactions.front(); _pending_incoming_transactions.pop_front(); --orig_pending_txn_size; process_incoming_transaction_async(std::get<0>(e), std::get<1>(e), std::get<2>(e)); - if (preprocess_deadline <= fc::time_point::now()) return start_block_result::exhausted; } } return start_block_result::succeeded; diff --git a/programs/cleos/httpc.hpp b/programs/cleos/httpc.hpp index 8cd7642850..21f1304db0 100644 --- a/programs/cleos/httpc.hpp +++ b/programs/cleos/httpc.hpp @@ -102,6 +102,8 @@ namespace eosio { namespace client { namespace http { const string get_system_token_balance_func = chain_func_base + "/get_system_token_balance"; const string get_txfee_item_func = chain_func_base + "/get_txfee_item"; const string get_txfee_list_func = chain_func_base + "/get_txfee_list"; + const string get_tx_vote_stat_for_account_func = chain_func_base + "/get_tx_vote_stat_for_account"; + const string get_top_tx_vote_receiver_list_func = chain_func_base + "/get_top_tx_vote_receiver_list"; const string get_yx_token_balance_func = chain_func_base + "/get_yx_token_balance"; const string get_yx_token_stats_func = chain_func_base + "/get_yx_token_stats"; diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index ba42039901..fe7bb22ee9 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -1154,7 +1154,7 @@ struct list_producers_subcommand { row["owner"].as_string().c_str(), row["producer_key"].as_string().c_str(), row["url"].as_string().c_str(), - row["total_votes"].as_double() / weight); + row["total_votes_weight"].as_double() / weight); if ( !result.more.empty() ) std::cout << "-L " << result.more << " for more" << std::endl; }); @@ -2221,6 +2221,38 @@ int main( int argc, char** argv ) { << std::endl; }); + // YOSEMITE Proof-of-Transaction Transaction Vote Statistics + // get tx vote stats for an account + string txVoteAccountName; + auto tx_vote_stat = get->add_subcommand("txvote", localized("Retrieve YOSEMITE Proof-of-Transaction transaction vote statistics"), true); + tx_vote_stat->require_subcommand(); + + auto get_tx_vote_stat_for_account = tx_vote_stat->add_subcommand("account", localized("Retrieve the transaction vote statistics info for an action"), false); + get_tx_vote_stat_for_account->add_option("code", txVoteAccountName, localized("account name to retrieve transaction vote stats."))->required(); + get_tx_vote_stat_for_account->set_callback([&] { + auto result = call(get_tx_vote_stat_for_account_func, + fc::mutable_variant_object("account", txVoteAccountName) + ); + + std::cout << fc::json::to_pretty_string(result) + << std::endl; + }); + + // get top transaction vote receiver list + uint32_t tx_vote_receiver_list_offset = 0; + uint32_t tx_vote_receiver_list_limit = 30; + auto get_top_tx_vote_receiver_list = tx_vote_stat->add_subcommand("top", localized("Retrieve top transaction vote receiver list sorted by weighted transaction vote amount"), false); + get_top_tx_vote_receiver_list->add_option("-o,--offset", tx_vote_receiver_list_offset, localized("offset of first result item. offset n means the result list starts from the rank n+1 tx vote receiver (default = 0)")); + get_top_tx_vote_receiver_list->add_option("-l,--limit", tx_vote_receiver_list_limit, localized("max limit of result item count (default = 30)")); + get_top_tx_vote_receiver_list->set_callback([&] { + auto result = call(get_top_tx_vote_receiver_list_func, + fc::mutable_variant_object("offset", tx_vote_receiver_list_offset)("limit", tx_vote_receiver_list_limit) + ); + + std::cout << fc::json::to_pretty_string(result) + << std::endl; + }); + // yx.token accessors // get yxtoken balance string ysymbol; diff --git a/scripts/boost.rb b/scripts/boost.rb new file mode 100644 index 0000000000..a322acbdd1 --- /dev/null +++ b/scripts/boost.rb @@ -0,0 +1,131 @@ +class Boost < Formula + desc "Collection of portable C++ source libraries" + homepage "https://www.boost.org/" + revision 1 + head "https://github.com/boostorg/boost.git" + + stable do + url "https://dl.bintray.com/boostorg/release/1.67.0/source/boost_1_67_0.tar.bz2" + sha256 "2684c972994ee57fc5632e03bf044746f6eb45d4920c343937a465fd67a5adba" + + # Remove for > 1.67.0 + # Fix "error: no member named 'next' in namespace 'boost'" + # Upstream commit from 1 Dec 2017 "Add #include ; no + # longer in utility.hpp" + patch :p2 do + url "https://github.com/boostorg/lockfree/commit/12726cd.patch?full_index=1" + sha256 "f165823d961a588b622b20520668b08819eb5fdc08be7894c06edce78026ce0a" + end + end + + bottle do + cellar :any + sha256 "265ab8beaa6fa26a7c305ef2e6aec8bd26ca1db105aca0aaca028f32c5245a90" => :high_sierra + sha256 "567f3e9a294413c1701b698d666a521cfdeec846e256c6e66576d5b70eb26f08" => :sierra + sha256 "3f3f687a620f656fe2ac54f01306e00e6bbc0e9797db284a8d272648d427e640" => :el_capitan + end + + option "with-icu4c", "Build regexp engine with icu support" + option "without-single", "Disable building single-threading variant" + option "without-static", "Disable building static library variant" + + deprecated_option "with-icu" => "with-icu4c" + + depends_on "icu4c" => :optional + + def install + # Force boost to compile with the desired compiler + open("user-config.jam", "a") do |file| + file.write "using darwin : : #{ENV.cxx} ;\n" + end + + # libdir should be set by --prefix but isn't + bootstrap_args = ["--prefix=#{prefix}", "--libdir=#{lib}"] + + if build.with? "icu4c" + icu4c_prefix = Formula["icu4c"].opt_prefix + bootstrap_args << "--with-icu=#{icu4c_prefix}" + else + bootstrap_args << "--without-icu" + end + + # Handle libraries that will not be built. + without_libraries = ["python", "mpi"] + + # Boost.Log cannot be built using Apple GCC at the moment. Disabled + # on such systems. + without_libraries << "log" if ENV.compiler == :gcc + + bootstrap_args << "--without-libraries=#{without_libraries.join(",")}" + + # layout should be synchronized with boost-python and boost-mpi + args = ["--prefix=#{prefix}", + "--libdir=#{lib}", + "-d2", + "-j#{ENV.make_jobs}", + "--layout=tagged", + "--user-config=user-config.jam", + "-sNO_LZMA=1", + "install"] + + if build.with? "single" + args << "threading=multi,single" + else + args << "threading=multi" + end + + if build.with? "static" + args << "link=shared,static" + else + args << "link=shared" + end + + # Trunk starts using "clang++ -x c" to select C compiler which breaks C++11 + # handling using ENV.cxx11. Using "cxxflags" and "linkflags" still works. + args << "cxxflags=-std=c++11" + if ENV.compiler == :clang + args << "cxxflags=-stdlib=libc++" << "linkflags=-stdlib=libc++" + end + + system "./bootstrap.sh", *bootstrap_args + system "./b2", "headers" + system "./b2", *args + end + + def caveats + s = "" + # ENV.compiler doesn't exist in caveats. Check library availability + # instead. + if Dir["#{lib}/libboost_log*"].empty? + s += <<~EOS + Building of Boost.Log is disabled because it requires newer GCC or Clang. + EOS + end + + s + end + + test do + (testpath/"test.cpp").write <<~EOS + #include + #include + #include + #include + using namespace boost::algorithm; + using namespace std; + + int main() + { + string str("a,b"); + vector strVec; + split(strVec, str, is_any_of(",")); + assert(strVec.size()==2); + assert(strVec[0]=="a"); + assert(strVec[1]=="b"); + return 0; + } + EOS + system ENV.cxx, "test.cpp", "-std=c++1y", "-L#{lib}", "-lboost_system", "-o", "test" + system "./test" + end +end diff --git a/scripts/eosio_build_amazon.sh b/scripts/eosio_build_amazon.sh index 1c96024b84..73c163330d 100644 --- a/scripts/eosio_build_amazon.sh +++ b/scripts/eosio_build_amazon.sh @@ -56,11 +56,11 @@ if [[ "${OS_NAME}" == "Amazon Linux AMI" ]]; then DEP_ARRAY=( git gcc72.x86_64 gcc72-c++.x86_64 autoconf automake libtool make bzip2 \ bzip2-devel.x86_64 openssl-devel.x86_64 gmp-devel.x86_64 libstdc++72.x86_64 \ - python27.x86_64 python36-devel.x86_64 libedit-devel.x86_64 doxygen.x86_64 graphviz.x86_64) + python27.x86_64 python27-devel.x86_64 python36-devel.x86_64 libedit-devel.x86_64 doxygen.x86_64 graphviz.x86_64) else DEP_ARRAY=( git gcc gcc-c++ autoconf automake libtool make bzip2 \ bzip2-devel openssl-devel gmp-devel libstdc++ \ - python3 python3-devel libedit-devel doxygen graphviz) + python3 python3-devel python-devel libedit-devel doxygen graphviz) fi COUNT=1 DISPLAY="" @@ -87,6 +87,7 @@ printf "\\n\\tThe following dependencies are required to install EOSIO.\\n" printf "\\n\\t${DISPLAY}\\n\\n" printf "\\tDo you wish to install these dependencies?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) diff --git a/scripts/eosio_build_centos.sh b/scripts/eosio_build_centos.sh index fa5e3c6137..6c3f11ee1c 100644 --- a/scripts/eosio_build_centos.sh +++ b/scripts/eosio_build_centos.sh @@ -63,6 +63,7 @@ SCL=$( rpm -qa | grep -E 'centos-release-scl-[0-9].*' ) if [ -z "${SCL}" ]; then printf "\\t - Do you wish to install and enable this repository?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) @@ -87,6 +88,7 @@ DEVTOOLSET=$( rpm -qa | grep -E 'devtoolset-7-[0-9].*' ) if [ -z "${DEVTOOLSET}" ]; then printf "\\tDo you wish to install devtoolset-7?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) @@ -118,6 +120,7 @@ PYTHON33=$( rpm -qa | grep -E 'python33-[0-9].*' ) if [ -z "${PYTHON33}" ]; then printf "\\tDo you wish to install python33?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) @@ -170,6 +173,7 @@ printf "\\tThe following dependencies are required to install EOSIO.\\n" printf "\\t${DISPLAY}\\n\\n" printf "\\tDo you wish to install these dependencies?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) diff --git a/scripts/eosio_build_darwin.sh b/scripts/eosio_build_darwin.sh index a91e1611d4..adcae78a25 100644 --- a/scripts/eosio_build_darwin.sh +++ b/scripts/eosio_build_darwin.sh @@ -70,6 +70,7 @@ then printf "\\tHomebrew must be installed to compile EOS.IO\\n\\n" printf "\\tDo you wish to install Home Brew?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case "${yn}" in [Yy]* ) @@ -138,6 +139,7 @@ printf "\\n\\tThe following dependencies are required to install EOSIO.\\n" printf "\\n\\t${DISPLAY}\\n\\n" echo "Do you wish to install these packages?" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) @@ -159,13 +161,12 @@ printf "\\tExiting now.\\n\\n" exit 1; fi - if [[ "$DEP" == "llvm@4" ]]; then - "${BREW}" unlink ${DEP} - elif ! "${BREW}" unlink ${DEP} && "${BREW}" link --force ${DEP} - then - printf "\\tHomebrew exited with the above errors.\\n" - printf "\\tExiting now.\\n\\n" - exit 1; + if [ $PERMISSION_GETTEXT -eq 1 ]; then + if ! "${BREW}" link --force gettext; then + printf "\\tHomebrew exited with the above errors.\\n" + printf "\\tExiting now.\\n\\n" + exit 1; + fi fi break;; [Nn]* ) echo "User aborting installation of required dependencies, Exiting now."; exit;; @@ -184,6 +185,7 @@ printf "\\tFound Boost Version %s.\\n" "${BVERSION}" printf "\\tEOS.IO requires Boost version 1.67.\\n" printf "\\tWould you like to uninstall version %s and install Boost version 1.67.\\n" "${BVERSION}" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) @@ -218,7 +220,7 @@ done fi printf "\\tInstalling boost libraries.\\n" - if ! "${BREW}" install https://raw.githubusercontent.com/Homebrew/homebrew-core/f946d12e295c8a27519b73cc810d06593270a07f/Formula/boost.rb + if ! "${BREW}" install "${SOURCE_DIR}/scripts/boost.rb" then printf "\\tUnable to install boost 1.67 libraries at this time. 0\\n" printf "\\tExiting now.\\n\\n" diff --git a/scripts/eosio_build_fedora.sh b/scripts/eosio_build_fedora.sh index 661efea9fc..4492e545c1 100644 --- a/scripts/eosio_build_fedora.sh +++ b/scripts/eosio_build_fedora.sh @@ -86,6 +86,7 @@ printf "\\n\\tThe following dependencies are required to install EOSIO.\\n" printf "\\n\\t${DISPLAY}\\n\\n" printf "\\tDo you wish to install these dependencies?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) diff --git a/scripts/eosio_build_ubuntu.sh b/scripts/eosio_build_ubuntu.sh index 4c9873a60a..f87397e862 100644 --- a/scripts/eosio_build_ubuntu.sh +++ b/scripts/eosio_build_ubuntu.sh @@ -91,6 +91,7 @@ printf "\\n\\tThe following dependencies are required to install EOSIO.\\n" printf "\\n\\t${DISPLAY}\\n\\n" printf "\\tDo you wish to install these packages?\\n" + if is_noninteractive; then exec <<< "1"; fi select yn in "Yes" "No"; do case $yn in [Yy]* ) diff --git a/unittests/api_tests.cpp b/unittests/api_tests.cpp index 8325ca30e5..66dabf8717 100644 --- a/unittests/api_tests.cpp +++ b/unittests/api_tests.cpp @@ -1089,7 +1089,7 @@ BOOST_FIXTURE_TEST_CASE(deferred_transaction_tests, TESTER) { try { produce_blocks( 3 ); //check that only one deferred transaction executed - auto dtrxs = control->get_scheduled_transactions(); + auto dtrxs = get_scheduled_transactions(); BOOST_CHECK_EQUAL(dtrxs.size(), 1); for (const auto& trx: dtrxs) { control->push_scheduled_transaction(trx, fc::time_point::maximum()); @@ -1114,7 +1114,7 @@ BOOST_FIXTURE_TEST_CASE(deferred_transaction_tests, TESTER) { try { produce_blocks( 3 ); //check that only one deferred transaction executed - auto dtrxs = control->get_scheduled_transactions(); + auto dtrxs = get_scheduled_transactions(); BOOST_CHECK_EQUAL(dtrxs.size(), 1); for (const auto& trx: dtrxs) { control->push_scheduled_transaction(trx, fc::time_point::maximum()); diff --git a/unittests/delay_tests.cpp b/unittests/delay_tests.cpp index 9f14de4107..ae1a3d114b 100644 --- a/unittests/delay_tests.cpp +++ b/unittests/delay_tests.cpp @@ -72,7 +72,7 @@ BOOST_FIXTURE_TEST_CASE( delay_error_create_account, validating_tester) { try { produce_blocks(6); - auto scheduled_trxs = control->get_scheduled_transactions(); + auto scheduled_trxs = get_scheduled_transactions(); BOOST_REQUIRE_EQUAL(scheduled_trxs.size(), 1); auto dtrace = control->push_scheduled_transaction(scheduled_trxs.front(), fc::time_point::maximum()); BOOST_REQUIRE_EQUAL(dtrace->except.valid(), true); diff --git a/yosemite_bios/reset_std_token_yosemite_testnet_on_server_side.sh b/yosemite_bios/reset_std_token_yosemite_testnet_on_server_side.sh index b7d33ea96a..99cd31f7ef 100755 --- a/yosemite_bios/reset_std_token_yosemite_testnet_on_server_side.sh +++ b/yosemite_bios/reset_std_token_yosemite_testnet_on_server_side.sh @@ -53,7 +53,7 @@ set -x { set +x; } 2>/dev/null echo "${red}Really want to reset Testnet node data?${reset}" -echo "${red}[WARNING] all data including yosemite node data and mongo db data will be deleted permanately.${reset}" +echo "${red}[WARNING] all data including yosemite node data and mongo db data will be deleted permanantely.${reset}" echo "write YES to proceed reset process." read USER_CONFIRM_TO_PROCEED if [ "$USER_CONFIRM_TO_PROCEED" != "YES" ]; then