未验证 提交 7b530751 编写于 作者: K Kevin Heifner 提交者: GitHub

Merge branch 'develop' into remoteTestFixes

......@@ -107,7 +107,7 @@ steps:
- "mongod.log"
- "build/genesis.json"
- "build/config.ini"
timeout: 60
timeout: 100
- command: |
echo "--- :arrow_down: Downloading build directory" && \
......@@ -131,7 +131,7 @@ steps:
docker#v1.4.0:
image: "eosio/ci:ubuntu"
workdir: /data/job
timeout: 60
timeout: 100
- command: |
echo "--- :arrow_down: Downloading build directory" && \
......@@ -155,7 +155,7 @@ steps:
docker#v1.4.0:
image: "eosio/ci:ubuntu18"
workdir: /data/job
timeout: 60
timeout: 100
- command: |
echo "--- :arrow_down: Downloading build directory" && \
......@@ -179,7 +179,7 @@ steps:
docker#v1.4.0:
image: "eosio/ci:fedora"
workdir: /data/job
timeout: 60
timeout: 100
- command: |
echo "--- :arrow_down: Downloading build directory" && \
......@@ -203,7 +203,7 @@ steps:
docker#v1.4.0:
image: "eosio/ci:centos"
workdir: /data/job
timeout: 60
timeout: 100
- command: |
echo "--- :arrow_down: Downloading build directory" && \
......@@ -227,4 +227,4 @@ steps:
docker#v1.4.0:
image: "eosio/ci:amazonlinux"
workdir: /data/job
timeout: 60
timeout: 100
......@@ -232,6 +232,14 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/EosioTester.cmake.in ${C
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/EosioTesterBuild.cmake.in ${CMAKE_BINARY_DIR}/lib/cmake/EosioTester.cmake @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/EosioTester.cmake DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}/cmake/)
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/)
install(FILES libraries/wabt/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.wabt)
install(FILES libraries/softfloat/COPYING.txt DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.softfloat)
install(FILES libraries/wasm-jit/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.wavm)
install(FILES libraries/fc/secp256k1/upstream/COPYING DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.secp256k1)
install(FILES externals/binaryen/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.binaryen)
install(FILES libraries/fc/src/network/LICENSE.go DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ )
include(installer)
include(doxygen)
......@@ -49,7 +49,6 @@ else()
find_library(libsecp256k1 secp256k1 @CMAKE_INSTALL_FULL_LIBDIR@)
endif()
find_library(libbinaryen binaryen @CMAKE_INSTALL_FULL_LIBDIR@)
find_library(libwasm WASM @CMAKE_INSTALL_FULL_LIBDIR@)
find_library(libwast WAST @CMAKE_INSTALL_FULL_LIBDIR@)
find_library(libwabt wabt @CMAKE_INSTALL_FULL_LIBDIR@)
......@@ -76,7 +75,6 @@ macro(add_eosio_test test_name)
${libtester}
${libchain}
${libfc}
${libbinaryen}
${libwast}
${libwasm}
${libwabt}
......
......@@ -50,7 +50,6 @@ else()
find_library(libsecp256k1 secp256k1 @CMAKE_BINARY_DIR@/libraries/fc/secp256k1)
endif()
find_library(libbinaryen binaryen @CMAKE_BINARY_DIR@/externals/binaryen/lib)
find_library(libwasm WASM @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WASM)
find_library(libwast WAST @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WAST)
find_library(libir IR @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/IR)
......@@ -77,7 +76,6 @@ macro(add_eosio_test test_name)
${libtester}
${libchain}
${libfc}
${libbinaryen}
${libwast}
${libwasm}
${libwabt}
......
......@@ -53,6 +53,28 @@
{"name":"accounts", "type":"permission_level_weight[]"},
{"name":"waits", "type":"wait_weight[]"}
]
},{
"name": "blockchain_parameters",
"base": "",
"fields": [
{"name":"max_block_net_usage", "type":"uint64"},
{"name":"target_block_net_usage_pct", "type":"uint32"},
{"name":"max_transaction_net_usage", "type":"uint32"},
{"name":"base_per_transaction_net_usage", "type":"uint32"},
{"name":"net_usage_leeway", "type":"uint32"},
{"name":"context_free_discount_net_usage_num", "type":"uint32"},
{"name":"context_free_discount_net_usage_den", "type":"uint32"},
{"name":"max_block_cpu_usage", "type":"uint32"},
{"name":"target_block_cpu_usage_pct", "type":"uint32"},
{"name":"max_transaction_cpu_usage", "type":"uint32"},
{"name":"min_transaction_cpu_usage", "type":"uint32"},
{"name":"max_transaction_lifetime", "type":"uint32"},
{"name":"deferred_trx_expiration_window", "type":"uint32"},
{"name":"max_transaction_delay", "type":"uint32"},
{"name":"max_inline_action_size", "type":"uint32"},
{"name":"max_inline_action_depth", "type":"uint16"},
{"name":"max_authority_depth", "type":"uint16"}
]
},{
"name": "newaccount",
"base": "",
......@@ -160,6 +182,12 @@
"fields": [
{"name":"schedule", "type":"producer_key[]"}
]
},{
"name": "setparams",
"base": "",
"fields": [
{"name":"params", "type":"blockchain_parameters"}
]
},{
"name": "require_auth",
"base": "",
......@@ -219,6 +247,10 @@
"name": "setprods",
"type": "set_producers",
"ricardian_contract": ""
},{
"name": "setparams",
"type": "setparams",
"ricardian_contract": ""
},{
"name": "reqauth",
"type": "require_auth",
......
#include <eosio.bios/eosio.bios.hpp>
EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(reqauth) )
EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(setparams)(reqauth) )
......@@ -34,6 +34,11 @@ namespace eosio {
set_proposed_producers(buffer, size);
}
void setparams( const eosio::blockchain_parameters& params ) {
require_auth( _self );
set_blockchain_parameters( params );
}
void reqauth( action_name from ) {
require_auth( from );
}
......
......@@ -265,7 +265,7 @@
-DCMAKE_C_COMPILER="${C_COMPILER}" -DWASM_ROOT="${WASM_ROOT}" -DCORE_SYMBOL_NAME="${CORE_SYMBOL_NAME}" \
-DOPENSSL_ROOT_DIR="${OPENSSL_ROOT_DIR}" -DBUILD_MONGO_DB_PLUGIN=true \
-DENABLE_COVERAGE_TESTING="${ENABLE_COVERAGE_TESTING}" -DBUILD_DOXYGEN="${DOXYGEN}" \
-DCMAKE_INSTALL_PREFIX="/usr/local/eosio" "${SOURCE_DIR}"
-DCMAKE_INSTALL_PREFIX="/usr/local/eosio" ${LOCAL_CMAKE_FLAGS} "${SOURCE_DIR}"
then
printf "\\n\\t>>>>>>>>>>>>>>>>>>>> CMAKE building EOSIO has exited with the above error.\\n\\n"
exit -1
......
......@@ -37,7 +37,6 @@ add_library( eosio_chain
asset.cpp
webassembly/wavm.cpp
webassembly/binaryen.cpp
webassembly/wabt.cpp
# get_config.cpp
......@@ -51,12 +50,11 @@ add_library( eosio_chain
)
target_link_libraries( eosio_chain eos_utilities fc chainbase Logging IR WAST WASM Runtime
wasm asmjs passes cfg ast emscripten-optimizer support softfloat builtins wabt
softfloat builtins wabt
)
target_include_directories( eosio_chain
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../wasm-jit/Include"
"${CMAKE_CURRENT_SOURCE_DIR}/../../externals/binaryen/src"
"${CMAKE_SOURCE_DIR}/libraries/wabt"
"${CMAKE_BINARY_DIR}/libraries/wabt"
)
......
此差异已折叠。
......@@ -272,8 +272,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
}
uint32_t trx_size = 0;
auto& d = control.db();
if ( auto ptr = d.find<generated_transaction_object,by_sender_id>(boost::make_tuple(receiver, sender_id)) ) {
if ( auto ptr = db.find<generated_transaction_object,by_sender_id>(boost::make_tuple(receiver, sender_id)) ) {
EOS_ASSERT( replace_existing, deferred_tx_duplicate, "deferred transaction with the same sender_id and payer already exists" );
// TODO: Remove the following subjective check when the deferred trx replacement RAM bug has been fixed with a hard fork.
......@@ -283,7 +282,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
// TODO: The logic of the next line needs to be incorporated into the next hard fork.
// add_ram_usage( ptr->payer, -(config::billable_size_v<generated_transaction_object> + ptr->packed_trx.size()) );
d.modify<generated_transaction_object>( *ptr, [&]( auto& gtx ) {
db.modify<generated_transaction_object>( *ptr, [&]( auto& gtx ) {
gtx.sender = receiver;
gtx.sender_id = sender_id;
gtx.payer = payer;
......@@ -294,7 +293,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
trx_size = gtx.set( trx );
});
} else {
d.create<generated_transaction_object>( [&]( auto& gtx ) {
db.create<generated_transaction_object>( [&]( auto& gtx ) {
gtx.trx_id = trx.id();
gtx.sender = receiver;
gtx.sender_id = sender_id;
......
......@@ -1400,9 +1400,11 @@ void controller::startup() {
my->init();
}
chainbase::database& controller::db()const { return my->db; }
const chainbase::database& controller::db()const { return my->db; }
fork_database& controller::fork_db()const { return my->fork_db; }
chainbase::database& controller::mutable_db()const { return my->db; }
const fork_database& controller::fork_db()const { return my->fork_db; }
void controller::start_block( block_timestamp_type when, uint16_t confirm_block_count) {
......
......@@ -453,7 +453,7 @@ class apply_context {
public:
apply_context(controller& con, transaction_context& trx_ctx, const action& a, uint32_t depth=0)
:control(con)
,db(con.db())
,db(con.mutable_db())
,trx_context(trx_ctx)
,act(a)
,receiver(act.account)
......
......@@ -93,7 +93,7 @@ const static uint32_t setcode_ram_bytes_multiplier = 10; ///< multip
const static uint32_t hashing_checktime_block_size = 10*1024; /// call checktime from hashing intrinsic once per this number of bytes
const static eosio::chain::wasm_interface::vm_type default_wasm_runtime = eosio::chain::wasm_interface::vm_type::binaryen;
const static eosio::chain::wasm_interface::vm_type default_wasm_runtime = eosio::chain::wasm_interface::vm_type::wabt;
const static uint32_t default_abi_serializer_max_time_ms = 15*1000; ///< default deadline for abi serialization methods
/**
......
......@@ -146,9 +146,9 @@ namespace eosio { namespace chain {
*/
void push_confirmation( const header_confirmation& c );
chainbase::database& db()const;
const chainbase::database& db()const;
fork_database& fork_db()const;
const fork_database& fork_db()const;
const account_object& get_account( account_name n )const;
const global_property_object& get_global_properties()const;
......@@ -286,6 +286,10 @@ namespace eosio { namespace chain {
}
private:
friend class apply_context;
friend class transaction_context;
chainbase::database& mutable_db()const;
std::unique_ptr<controller_impl> my;
......
......@@ -91,12 +91,6 @@ namespace eosio { namespace chain {
operator unsigned __int128()const { return value; }
};
inline std::vector<name> sort_names( std::vector<name>&& names ) {
fc::deduplicate(names);
return names;
}
} } // eosio::chain
namespace std {
......
......@@ -53,7 +53,6 @@ namespace eosio { namespace chain {
public:
enum class vm_type {
wavm,
binaryen,
wabt
};
......@@ -77,4 +76,4 @@ namespace eosio{ namespace chain {
std::istream& operator>>(std::istream& in, wasm_interface::vm_type& runtime);
}}
FC_REFLECT_ENUM( eosio::chain::wasm_interface::vm_type, (wavm)(binaryen)(wabt) )
FC_REFLECT_ENUM( eosio::chain::wasm_interface::vm_type, (wavm)(wabt) )
......@@ -2,7 +2,6 @@
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/webassembly/wavm.hpp>
#include <eosio/chain/webassembly/binaryen.hpp>
#include <eosio/chain/webassembly/wabt.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/wasm_eosio_injection.hpp>
......@@ -27,8 +26,6 @@ namespace eosio { namespace chain {
wasm_interface_impl(wasm_interface::vm_type vm) {
if(vm == wasm_interface::vm_type::wavm)
runtime_interface = std::make_unique<webassembly::wavm::wavm_runtime>();
else if(vm == wasm_interface::vm_type::binaryen)
runtime_interface = std::make_unique<webassembly::binaryen::binaryen_runtime>();
else if(vm == wasm_interface::vm_type::wabt)
runtime_interface = std::make_unique<webassembly::wabt_runtime::wabt_runtime>();
else
......@@ -98,7 +95,6 @@ namespace eosio { namespace chain {
#define _REGISTER_INTRINSIC_EXPLICIT(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_WAVM_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_BINARYEN_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
_REGISTER_WABT_INTRINSIC(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)
#define _REGISTER_INTRINSIC4(CLS, MOD, METHOD, WASM_SIG, NAME, SIG)\
......
......@@ -371,7 +371,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>>
size_t length = args.at((uint32_t)offset).get_i32();
T* base = array_ptr_impl<T>(vars, ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of const values" );
if(vars.ctx.control.contracts_console())
wlog( "misaligned array of const values" );
std::vector<std::remove_const_t<T> > copy(length > 0 ? length : 1);
T* copy_ptr = &copy[0];
memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) );
......@@ -387,7 +388,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>>
size_t length = args.at((uint32_t)offset).get_i32();
T* base = array_ptr_impl<T>(vars, ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of values" );
if(vars.ctx.control.contracts_console())
wlog( "misaligned array of values" );
std::vector<std::remove_const_t<T> > copy(length > 0 ? length : 1);
T* copy_ptr = &copy[0];
memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) );
......@@ -500,7 +502,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>> {
uint32_t ptr = args.at((uint32_t)offset).get_i32();
T* base = array_ptr_impl<T>(vars, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned const pointer" );
if(vars.ctx.control.contracts_console())
wlog( "misaligned const pointer" );
std::remove_const_t<T> copy;
T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)base, sizeof(T) );
......@@ -514,7 +517,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>> {
uint32_t ptr = args.at((uint32_t)offset).get_i32();
T* base = array_ptr_impl<T>(vars, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned pointer" );
if(vars.ctx.control.contracts_console())
wlog( "misaligned pointer" );
T copy;
memcpy( (void*)&copy, (void*)base, sizeof(T) );
Ret ret = Then(vars, &copy, rest..., args, (uint32_t)offset - 1);
......@@ -603,7 +607,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>> {
EOS_ASSERT(ptr != 0, binaryen_exception, "references cannot be created for null pointers");
T* base = array_ptr_impl<T>(vars, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned const reference" );
if(vars.ctx.control.contracts_console())
wlog( "misaligned const reference" );
std::remove_const_t<T> copy;
T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)base, sizeof(T) );
......@@ -619,7 +624,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>> {
EOS_ASSERT(ptr != 0, binaryen_exception, "references cannot be created for null pointers");
T* base = array_ptr_impl<T>(vars, ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned reference" );
if(vars.ctx.control.contracts_console())
wlog( "misaligned reference" );
T copy;
memcpy( (void*)&copy, (void*)base, sizeof(T) );
Ret ret = Then(vars, copy, rest..., args, (uint32_t)offset - 1);
......
......@@ -3,6 +3,7 @@
#include <eosio/chain/webassembly/common.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/webassembly/runtime_interface.hpp>
#include <eosio/chain/apply_context.hpp>
#include <softfloat.hpp>
#include "Runtime/Runtime.h"
#include "IR/Types.h"
......@@ -382,7 +383,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>,
const auto length = size_t(size);
T* base = array_ptr_impl<T>(ctx, (U32)ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of const values" );
if(ctx.apply_ctx->control.contracts_console())
wlog( "misaligned array of const values" );
std::vector<std::remove_const_t<T> > copy(length > 0 ? length : 1);
T* copy_ptr = &copy[0];
memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) );
......@@ -397,7 +399,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<array_ptr<T>, size_t, Inputs...>,
const auto length = size_t(size);
T* base = array_ptr_impl<T>(ctx, (U32)ptr, length);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned array of values" );
if(ctx.apply_ctx->control.contracts_console())
wlog( "misaligned array of values" );
std::vector<std::remove_const_t<T> > copy(length > 0 ? length : 1);
T* copy_ptr = &copy[0];
memcpy( (void*)copy_ptr, (void*)base, length * sizeof(T) );
......@@ -508,7 +511,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>, std::tuple<Transl
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<std::is_const<U>::value, Ret> {
T* base = array_ptr_impl<T>(ctx, (U32)ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned const pointer" );
if(ctx.apply_ctx->control.contracts_console())
wlog( "misaligned const pointer" );
std::remove_const_t<T> copy;
T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)base, sizeof(T) );
......@@ -521,7 +525,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T *, Inputs...>, std::tuple<Transl
static auto translate_one(running_instance_context& ctx, Inputs... rest, Translated... translated, I32 ptr) -> std::enable_if_t<!std::is_const<U>::value, Ret> {
T* base = array_ptr_impl<T>(ctx, (U32)ptr, 1);
if ( reinterpret_cast<uintptr_t>(base) % alignof(T) != 0 ) {
wlog( "misaligned pointer" );
if(ctx.apply_ctx->control.contracts_console())
wlog( "misaligned pointer" );
std::remove_const_t<T> copy;
T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)base, sizeof(T) );
......@@ -587,7 +592,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>, std::tuple<Transl
Runtime::causeException(Exception::Cause::accessViolation);
T &base = *(T*)(getMemoryBaseAddress(mem)+(U32)ptr);
if ( reinterpret_cast<uintptr_t>(&base) % alignof(T) != 0 ) {
wlog( "misaligned const reference" );
if(ctx.apply_ctx->control.contracts_console())
wlog( "misaligned const reference" );
std::remove_const_t<T> copy;
T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)&base, sizeof(T) );
......@@ -605,7 +611,8 @@ struct intrinsic_invoker_impl<Ret, std::tuple<T &, Inputs...>, std::tuple<Transl
Runtime::causeException(Exception::Cause::accessViolation);
T &base = *(T*)(getMemoryBaseAddress(mem)+(U32)ptr);
if ( reinterpret_cast<uintptr_t>(&base) % alignof(T) != 0 ) {
wlog( "misaligned reference" );
if(ctx.apply_ctx->control.contracts_console())
wlog( "misaligned reference" );
std::remove_const_t<T> copy;
T* copy_ptr = &copy;
memcpy( (void*)copy_ptr, (void*)&base, sizeof(T) );
......
......@@ -23,7 +23,7 @@ namespace eosio { namespace chain {
,pseudo_start(s)
{
if (!c.skip_db_sessions()) {
undo_session = c.db().start_undo_session(true);
undo_session = c.mutable_db().start_undo_session(true);
}
trace->id = id;
trace->block_num = c.pending_block_state()->block_num;
......@@ -451,7 +451,7 @@ namespace eosio { namespace chain {
auto first_auth = trx.first_authorizor();
uint32_t trx_size = 0;
const auto& cgto = control.db().create<generated_transaction_object>( [&]( auto& gto ) {
const auto& cgto = control.mutable_db().create<generated_transaction_object>( [&]( auto& gto ) {
gto.trx_id = id;
gto.payer = first_auth;
gto.sender = account_name(); /// delayed transactions have no sender
......@@ -467,7 +467,7 @@ namespace eosio { namespace chain {
void transaction_context::record_transaction( const transaction_id_type& id, fc::time_point_sec expire ) {
try {
control.db().create<transaction_object>([&](transaction_object& transaction) {
control.mutable_db().create<transaction_object>([&](transaction_object& transaction) {
transaction.trx_id = id;
transaction.expiration = expire;
});
......
......@@ -1911,8 +1911,6 @@ std::istream& operator>>(std::istream& in, wasm_interface::vm_type& runtime) {
in >> s;
if (s == "wavm")
runtime = eosio::chain::wasm_interface::vm_type::wavm;
else if (s == "binaryen")
runtime = eosio::chain::wasm_interface::vm_type::binaryen;
else if (s == "wabt")
runtime = eosio::chain::wasm_interface::vm_type::wabt;
else
......
#include <eosio/chain/webassembly/binaryen.hpp>
#include <eosio/chain/apply_context.hpp>
#include <wasm-binary.h>
namespace eosio { namespace chain { namespace webassembly { namespace binaryen {
class binaryen_instantiated_module : public wasm_instantiated_module_interface {
public:
binaryen_instantiated_module(linear_memory_type& shared_linear_memory,
std::vector<uint8_t> initial_memory,
call_indirect_table_type table,
import_lut_type import_lut,
unique_ptr<Module>&& module) :
_shared_linear_memory(shared_linear_memory),
_initial_memory(initial_memory),
_table(forward<decltype(table)>(table)),
_import_lut(forward<decltype(import_lut)>(import_lut)),
_module(forward<decltype(module)>(module)) {
}
void apply(apply_context& context) override {
LiteralList args = {Literal(uint64_t(context.receiver)),
Literal(uint64_t(context.act.account)),
Literal(uint64_t(context.act.name))};
call("apply", args, context);
}
private:
linear_memory_type& _shared_linear_memory;
std::vector<uint8_t> _initial_memory;
call_indirect_table_type _table;
import_lut_type _import_lut;
unique_ptr<Module> _module;
void call(const string& entry_point, LiteralList& args, apply_context& context){
const unsigned initial_memory_size = _module->memory.initial*Memory::kPageSize;
interpreter_interface local_interface(_shared_linear_memory, _table, _import_lut, initial_memory_size, context);
//zero out the initial pages
memset(_shared_linear_memory.data, 0, initial_memory_size);
//copy back in the initial data
memcpy(_shared_linear_memory.data, _initial_memory.data(), _initial_memory.size());
//be aware that construction of the ModuleInstance implictly fires the start function
ModuleInstance instance(*_module.get(), &local_interface);
instance.callExport(Name(entry_point), args);
}
};
binaryen_runtime::binaryen_runtime() {
}
std::unique_ptr<wasm_instantiated_module_interface> binaryen_runtime::instantiate_module(const char* code_bytes, size_t code_size, std::vector<uint8_t> initial_memory) {
try {
vector<char> code(code_bytes, code_bytes + code_size);
unique_ptr<Module> module(new Module());
WasmBinaryBuilder builder(*module, code, false);
builder.read();
EOS_ASSERT(module->memory.initial * Memory::kPageSize <= wasm_constraints::maximum_linear_memory, binaryen_exception, "exceeds maximum linear memory");
// create a temporary globals to use
TrivialGlobalManager globals;
for (auto& global : module->globals) {
globals[global->name] = ConstantExpressionRunner<TrivialGlobalManager>(globals).visit(global->init).value;
}
call_indirect_table_type table;
table.resize(module->table.initial);
for (auto& segment : module->table.segments) {
Address offset = ConstantExpressionRunner<TrivialGlobalManager>(globals).visit(segment.offset).value.geti32();
EOS_ASSERT( uint64_t(offset) + segment.data.size() <= module->table.initial, binaryen_exception, "");
for (size_t i = 0; i != segment.data.size(); ++i) {
table[offset + i] = segment.data[i];
}
}
// initialize the import lut
import_lut_type import_lut;
import_lut.reserve(module->imports.size());
for (auto& import : module->imports) {
std::string full_name = string(import->module.c_str()) + "." + string(import->base.c_str());
if (import->kind == ExternalKind::Function) {
auto& intrinsic_map = intrinsic_registrator::get_map();
auto intrinsic_itr = intrinsic_map.find(full_name);
if (intrinsic_itr != intrinsic_map.end()) {
import_lut.emplace(make_pair((uintptr_t)import.get(), intrinsic_itr->second));
continue;
}
}
EOS_ASSERT( !"unresolvable", wasm_exception, "${module}.${export} unresolveable", ("module",import->module.c_str())("export",import->base.c_str()) );
}
return std::make_unique<binaryen_instantiated_module>(_memory, initial_memory, move(table), move(import_lut), move(module));
} catch (const ParseException &e) {
FC_THROW_EXCEPTION(wasm_execution_error, "Error building interpreter: ${s}", ("s", e.text));
}
}
}}}}
Subproject commit 4724baf2095cdc1bb1722254874b51070adf0e74
Subproject commit 8ca96ad6b18709d65a7d1f67f8893978f25babcf
Subproject commit f085773d29ecc457894170fae740b726465f1382
Subproject commit 29cd7df702e79954076461af0eadad2e9d745d44
......@@ -332,9 +332,7 @@ namespace eosio { namespace testing {
vcfg.genesis.initial_key = get_public_key( config::system_account_name, "active" );
for(int i = 0; i < boost::unit_test::framework::master_test_suite().argc; ++i) {
if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--binaryen"))
vcfg.wasm_runtime = chain::wasm_interface::vm_type::binaryen;
else if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--wavm"))
if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--wavm"))
vcfg.wasm_runtime = chain::wasm_interface::vm_type::wavm;
else if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--wabt"))
vcfg.wasm_runtime = chain::wasm_interface::vm_type::wabt;
......
......@@ -96,14 +96,10 @@ namespace eosio { namespace testing {
cfg.genesis.initial_key = get_public_key( config::system_account_name, "active" );
for(int i = 0; i < boost::unit_test::framework::master_test_suite().argc; ++i) {
if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--binaryen"))
cfg.wasm_runtime = chain::wasm_interface::vm_type::binaryen;
else if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--wavm"))
if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--wavm"))
cfg.wasm_runtime = chain::wasm_interface::vm_type::wavm;
else if(boost::unit_test::framework::master_test_suite().argv[i] == std::string("--wabt"))
cfg.wasm_runtime = chain::wasm_interface::vm_type::wabt;
else
cfg.wasm_runtime = chain::wasm_interface::vm_type::binaryen;
}
open();
......
......@@ -6,10 +6,13 @@ Third parties are encouraged to make pull requests to this file (`develop` branc
| Description | URL |
| ----------- | --- |
| Watch for specific actions and send them to an HTTP URL | https://github.com/eosauthority/eosio-watcher-plugin |
| BP Heartbeat | https://github.com/bancorprotocol/eos-producer-heartbeat-plugin |
| ElasticSearch | https://github.com/EOSLaoMao/elasticsearch_plugin |
| Kafka | https://github.com/TP-Lab/kafka_plugin |
| MySQL | https://github.com/eosBLACK/eosio_mysqldb_plugin |
| SQL | https://github.com/asiniscalchi/eosio_sql_plugin |
| ElasticSearch | https://github.com/EOSLaoMao/elasticsearch_plugin |
| Watch for specific actions and send them to an HTTP URL | https://github.com/eosauthority/eosio-watcher-plugin |
| ZeroMQ | https://github.com/cc32d9/eos_zmq_plugin |
## DISCLAIMER:
......
......@@ -37,7 +37,7 @@ struct async_result_visitor : public fc::visitor<std::string> {
#define CALL(api_name, api_handle, api_namespace, call_name, http_response_code) \
{std::string("/v1/" #api_name "/" #call_name), \
[this, api_handle](string, string body, url_response_callback cb) mutable { \
[api_handle](string, string body, url_response_callback cb) mutable { \
api_handle.validate(); \
try { \
if (body.empty()) body = "{}"; \
......@@ -50,7 +50,7 @@ struct async_result_visitor : public fc::visitor<std::string> {
#define CALL_ASYNC(api_name, api_handle, api_namespace, call_name, call_result, http_response_code) \
{std::string("/v1/" #api_name "/" #call_name), \
[this, api_handle](string, string body, url_response_callback cb) mutable { \
[api_handle](string, string body, url_response_callback cb) mutable { \
if (body.empty()) body = "{}"; \
api_handle.validate(); \
api_handle.call_name(fc::json::from_string(body).as<api_namespace::call_name ## _params>(),\
......@@ -79,7 +79,10 @@ void chain_api_plugin::plugin_startup() {
auto ro_api = app().get_plugin<chain_plugin>().get_read_only_api();
auto rw_api = app().get_plugin<chain_plugin>().get_read_write_api();
app().get_plugin<http_plugin>().add_api({
auto& _http_plugin = app().get_plugin<http_plugin>();
ro_api.set_shorten_abi_errors( !_http_plugin.verbose_errors() );
_http_plugin.add_api({
CHAIN_RO_CALL(get_info, 200l),
CHAIN_RO_CALL(get_block, 200),
CHAIN_RO_CALL(get_block_header_state, 200),
......
......@@ -212,7 +212,7 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
("blocks-dir", bpo::value<bfs::path>()->default_value("blocks"),
"the location of the blocks directory (absolute path or relative to application data dir)")
("checkpoint", bpo::value<vector<string>>()->composing(), "Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.")
("wasm-runtime", bpo::value<eosio::chain::wasm_interface::vm_type>()->value_name("wavm/binaryen/wabt"), "Override default WASM runtime")
("wasm-runtime", bpo::value<eosio::chain::wasm_interface::vm_type>()->value_name("wavm/wabt"), "Override default WASM runtime")
("abi-serializer-max-time-ms", bpo::value<uint32_t>()->default_value(config::default_abi_serializer_max_time_ms),
"Override default maximum ABI serialization time allowed in ms")
("chain-state-db-size-mb", bpo::value<uint64_t>()->default_value(config::default_state_size / (1024 * 1024)), "Maximum size (in MiB) of the chain state database")
......@@ -1214,7 +1214,7 @@ static float64_t to_softfloat64( double d ) {
return *reinterpret_cast<float64_t*>(&d);
}
static fc::variant get_global_row( const database& db, const abi_def& abi, const abi_serializer& abis, const fc::microseconds& abi_serializer_max_time_ms ) {
fc::variant get_global_row( const database& db, const abi_def& abi, const abi_serializer& abis, const fc::microseconds& abi_serializer_max_time_ms, bool shorten_abi_errors ) {
const auto table_type = get_table_type(abi, N(global));
EOS_ASSERT(table_type == read_only::KEYi64, chain::contract_table_query_exception, "Invalid table type ${type} for table global", ("type",table_type));
......@@ -1227,7 +1227,7 @@ static fc::variant get_global_row( const database& db, const abi_def& abi, const
vector<char> data;
read_only::copy_inline_row(*it, data);
return abis.binary_to_variant(abis.get_table_type(N(global)), data, abi_serializer_max_time_ms);
return abis.binary_to_variant(abis.get_table_type(N(global)), data, abi_serializer_max_time_ms, shorten_abi_errors );
}
read_only::get_producers_result read_only::get_producers( const read_only::get_producers_params& p ) const {
......@@ -1272,12 +1272,12 @@ read_only::get_producers_result read_only::get_producers( const read_only::get_p
}
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));
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));
}
result.total_producer_vote_weight = get_global_row(d, abi, abis, abi_serializer_max_time)["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();
return result;
}
......@@ -1665,7 +1665,7 @@ read_only::get_account_results read_only::get_account( const get_account_params&
if ( it != idx.end() ) {
vector<char> data;
copy_inline_row(*it, data);
result.total_resources = abis.binary_to_variant( "user_resources", data, abi_serializer_max_time );
result.total_resources = abis.binary_to_variant( "user_resources", data, abi_serializer_max_time, shorten_abi_errors );
}
}
......@@ -1676,7 +1676,7 @@ read_only::get_account_results read_only::get_account( const get_account_params&
if ( it != idx.end() ) {
vector<char> data;
copy_inline_row(*it, data);
result.self_delegated_bandwidth = abis.binary_to_variant( "delegated_bandwidth", data, abi_serializer_max_time );
result.self_delegated_bandwidth = abis.binary_to_variant( "delegated_bandwidth", data, abi_serializer_max_time, shorten_abi_errors );
}
}
......@@ -1687,7 +1687,7 @@ read_only::get_account_results read_only::get_account( const get_account_params&
if ( it != idx.end() ) {
vector<char> data;
copy_inline_row(*it, data);
result.refund_request = abis.binary_to_variant( "refund_request", data, abi_serializer_max_time );
result.refund_request = abis.binary_to_variant( "refund_request", data, abi_serializer_max_time, shorten_abi_errors );
}
}
......@@ -1698,7 +1698,7 @@ read_only::get_account_results read_only::get_account( const get_account_params&
if ( it != idx.end() ) {
vector<char> data;
copy_inline_row(*it, data);
result.voter_info = abis.binary_to_variant( "voter_info", data, abi_serializer_max_time );
result.voter_info = abis.binary_to_variant( "voter_info", data, abi_serializer_max_time, shorten_abi_errors );
}
}
}
......@@ -1724,7 +1724,7 @@ read_only::abi_json_to_bin_result read_only::abi_json_to_bin( const read_only::a
auto action_type = abis.get_action_type(params.action);
EOS_ASSERT(!action_type.empty(), action_validate_exception, "Unknown action ${action} in contract ${contract}", ("action", params.action)("contract", params.code));
try {
result.binargs = abis.variant_to_binary(action_type, params.args, abi_serializer_max_time);
result.binargs = abis.variant_to_binary( action_type, params.args, abi_serializer_max_time, shorten_abi_errors );
} EOS_RETHROW_EXCEPTIONS(chain::invalid_action_args_exception,
"'${args}' is invalid args for action '${action}' code '${code}'. expected '${proto}'",
("args", params.args)("action", params.action)("code", params.code)("proto", action_abi_to_variant(abi, action_type)))
......@@ -1741,7 +1741,7 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a
abi_def abi;
if( abi_serializer::to_abi(code_account.abi, abi) ) {
abi_serializer abis( abi, abi_serializer_max_time );
result.args = abis.binary_to_variant( abis.get_action_type( params.action ), params.binargs, abi_serializer_max_time );
result.args = abis.binary_to_variant( abis.get_action_type( params.action ), params.binargs, abi_serializer_max_time, shorten_abi_errors );
} else {
EOS_ASSERT(false, abi_not_found_exception, "No ABI found for ${contract}", ("contract", params.code));
}
......
......@@ -68,6 +68,7 @@ uint64_t convert_to_type(const string& str, const string& desc);
class read_only {
const controller& db;
const fc::microseconds abi_serializer_max_time;
bool shorten_abi_errors = true;
public:
static const string KEYi64;
......@@ -77,6 +78,8 @@ public:
void validate() const {}
void set_shorten_abi_errors( bool f ) { shorten_abi_errors = f; }
using get_info_params = empty;
struct get_info_results {
......@@ -434,7 +437,7 @@ public:
copy_inline_row(*itr2, data);
if (p.json) {
result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(p.table), data, abi_serializer_max_time));
result.rows.emplace_back( abis.binary_to_variant( abis.get_table_type(p.table), data, abi_serializer_max_time, shorten_abi_errors ) );
} else {
result.rows.emplace_back(fc::variant(data));
}
......@@ -495,7 +498,7 @@ public:
copy_inline_row(*itr, data);
if (p.json) {
result.rows.emplace_back(abis.binary_to_variant(abis.get_table_type(p.table), data, abi_serializer_max_time));
result.rows.emplace_back( abis.binary_to_variant( abis.get_table_type(p.table), data, abi_serializer_max_time, shorten_abi_errors ) );
} else {
result.rows.emplace_back(fc::variant(data));
}
......
......@@ -36,7 +36,7 @@ void db_size_api_plugin::plugin_startup() {
}
db_size_stats db_size_api_plugin::get() {
chainbase::database& db = app().get_plugin<chain_plugin>().chain().db();
const chainbase::database& db = app().get_plugin<chain_plugin>().chain().db();
db_size_stats ret;
ret.free_bytes = db.get_segment_manager()->get_free_memory();
......
......@@ -21,7 +21,7 @@ void history_api_plugin::plugin_initialize(const variables_map&) {}
#define CALL(api_name, api_handle, api_namespace, call_name) \
{std::string("/v1/" #api_name "/" #call_name), \
[this, api_handle](string, string body, url_response_callback cb) mutable { \
[api_handle](string, string body, url_response_callback cb) mutable { \
try { \
if (body.empty()) body = "{}"; \
auto result = api_handle.call_name(fc::json::from_string(body).as<api_namespace::call_name ## _params>()); \
......
......@@ -206,7 +206,7 @@ namespace eosio {
void record_account_action( account_name n, const base_action_trace& act ) {
auto& chain = chain_plug->chain();
auto& db = chain.db();
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
const auto& idx = db.get_index<account_history_index, by_account_action_seq>();
auto itr = idx.lower_bound( boost::make_tuple( name(n.value+1), 0 ) );
......@@ -227,7 +227,7 @@ namespace eosio {
void on_system_action( const action_trace& at ) {
auto& chain = chain_plug->chain();
auto& db = chain.db();
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
if( at.act.name == N(newaccount) )
{
const auto create = at.act.data_as<chain::newaccount>();
......@@ -256,7 +256,7 @@ namespace eosio {
if( filter( at ) ) {
//idump((fc::json::to_pretty_string(at)));
auto& chain = chain_plug->chain();
auto& db = chain.db();
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
db.create<action_history_object>( [&]( auto& aho ) {
auto ps = fc::raw::pack_size( at );
......@@ -344,10 +344,12 @@ namespace eosio {
EOS_ASSERT( my->chain_plug, chain::missing_chain_plugin_exception, "" );
auto& chain = my->chain_plug->chain();
chain.db().add_index<account_history_index>();
chain.db().add_index<action_history_index>();
chain.db().add_index<account_control_history_multi_index>();
chain.db().add_index<public_key_history_multi_index>();
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
// TODO: Use separate chainbase database for managing the state of the history_plugin (or remove deprecated history_plugin entirely)
db.add_index<account_history_index>();
db.add_index<action_history_index>();
db.add_index<account_control_history_multi_index>();
db.add_index<public_key_history_multi_index>();
my->applied_transaction_connection.emplace(
chain.applied_transaction.connect( [&]( const transaction_trace_ptr& p ) {
......
......@@ -606,4 +606,8 @@ namespace eosio {
return (!my->listen_endpoint || my->listen_endpoint->address().is_loopback());
}
bool http_plugin::verbose_errors()const {
return verbose_http_errors;
}
}
......@@ -60,12 +60,12 @@ namespace eosio {
* called with the response code and body.
*
* The handler will be called from the appbase application io_service
* thread. The callback can be called from any thread and will
* thread. The callback can be called from any thread and will
* automatically propagate the call to the http thread.
*
* The HTTP service will run in its own thread with its own io_service to
* make sure that HTTP request processing does not interfer with other
* plugins.
* plugins.
*/
class http_plugin : public appbase::plugin<http_plugin>
{
......@@ -85,7 +85,7 @@ namespace eosio {
void add_handler(const string& url, const url_handler&);
void add_api(const api_description& api) {
for (const auto& call : api)
for (const auto& call : api)
add_handler(call.first, call.second);
}
......@@ -95,6 +95,8 @@ namespace eosio {
bool is_on_loopback() const;
bool is_secure() const;
bool verbose_errors()const;
private:
std::unique_ptr<class http_plugin_impl> my;
};
......
......@@ -111,7 +111,8 @@ public:
void remove_account_control( const account_name& name, const permission_name& permission );
/// @return true if act should be added to mongodb, false to skip it
bool filter_include( const chain::action_trace& action_trace ) const;
bool filter_include( const account_name& receiver, const action_name& act_name,
const vector<chain::permission_level>& authorization ) const;
void init();
void wipe_database();
......@@ -127,6 +128,7 @@ public:
bool filter_on_star = true;
std::set<filter_entry> filter_on;
std::set<filter_entry> filter_out;
bool update_blocks_via_block_num = false;
bool store_blocks = true;
bool store_block_states = true;
bool store_transactions = true;
......@@ -217,20 +219,22 @@ const std::string mongo_db_plugin_impl::accounts_col = "accounts";
const std::string mongo_db_plugin_impl::pub_keys_col = "pub_keys";
const std::string mongo_db_plugin_impl::account_controls_col = "account_controls";
bool mongo_db_plugin_impl::filter_include( const chain::action_trace& action_trace ) const {
bool mongo_db_plugin_impl::filter_include( const account_name& receiver, const action_name& act_name,
const vector<chain::permission_level>& authorization ) const
{
bool include = false;
if( filter_on_star ) {
include = true;
} else {
auto itr = std::find_if( filter_on.cbegin(), filter_on.cend(), [&action_trace]( const auto& filter ) {
return filter.match( action_trace.receipt.receiver, action_trace.act.name, 0 );
auto itr = std::find_if( filter_on.cbegin(), filter_on.cend(), [&receiver, &act_name]( const auto& filter ) {
return filter.match( receiver, act_name, 0 );
} );
if( itr != filter_on.cend() ) {
include = true;
} else {
for( const auto& a : action_trace.act.authorization ) {
auto itr = std::find_if( filter_on.cbegin(), filter_on.cend(), [&action_trace, &a]( const auto& filter ) {
return filter.match( action_trace.receipt.receiver, action_trace.act.name, a.actor );
for( const auto& a : authorization ) {
auto itr = std::find_if( filter_on.cbegin(), filter_on.cend(), [&receiver, &act_name, &a]( const auto& filter ) {
return filter.match( receiver, act_name, a.actor );
} );
if( itr != filter_on.cend() ) {
include = true;
......@@ -241,15 +245,16 @@ bool mongo_db_plugin_impl::filter_include( const chain::action_trace& action_tra
}
if( !include ) { return false; }
if( filter_out.empty() ) { return true; }
auto itr = std::find_if( filter_out.cbegin(), filter_out.cend(), [&action_trace]( const auto& filter ) {
return filter.match( action_trace.receipt.receiver, action_trace.act.name, 0 );
auto itr = std::find_if( filter_out.cbegin(), filter_out.cend(), [&receiver, &act_name]( const auto& filter ) {
return filter.match( receiver, act_name, 0 );
} );
if( itr != filter_out.cend() ) { return false; }
for( const auto& a : action_trace.act.authorization ) {
auto itr = std::find_if( filter_out.cbegin(), filter_out.cend(), [&action_trace, &a]( const auto& filter ) {
return filter.match( action_trace.receipt.receiver, action_trace.act.name, a.actor );
for( const auto& a : authorization ) {
auto itr = std::find_if( filter_out.cbegin(), filter_out.cend(), [&receiver, &act_name, &a]( const auto& filter ) {
return filter.match( receiver, act_name, a.actor );
} );
if( itr != filter_out.cend() ) { return false; }
}
......@@ -694,6 +699,27 @@ void mongo_db_plugin_impl::_process_accepted_transaction( const chain::transacti
using bsoncxx::builder::basic::make_array;
namespace bbb = bsoncxx::builder::basic;
const auto& trx = t->trx;
if( !filter_on_star || !filter_out.empty() ) {
bool include = false;
for( const auto& a : trx.actions ) {
if( filter_include( a.account, a.name, a.authorization ) ) {
include = true;
break;
}
}
if( !include ) {
for( const auto& a : trx.context_free_actions ) {
if( filter_include( a.account, a.name, a.authorization ) ) {
include = true;
break;
}
}
}
if( !include ) return;
}
auto trans_doc = bsoncxx::builder::basic::document{};
auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
......@@ -701,7 +727,6 @@ void mongo_db_plugin_impl::_process_accepted_transaction( const chain::transacti
const auto& trx_id = t->id;
const auto trx_id_str = trx_id.str();
const auto& trx = t->trx;
trans_doc.append( kvp( "trx_id", trx_id_str ) );
......@@ -776,7 +801,8 @@ mongo_db_plugin_impl::add_action_trace( mongocxx::bulk_write& bulk_action_traces
}
bool added = false;
if( start_block_reached && store_action_traces && filter_include( atrace ) ) {
if( start_block_reached && store_action_traces &&
filter_include( atrace.receipt.receiver, atrace.act.name, atrace.act.authorization ) ) {
auto action_traces_doc = bsoncxx::builder::basic::document{};
const chain::base_action_trace& base = atrace; // without inline action traces
......@@ -930,9 +956,16 @@ void mongo_db_plugin_impl::_process_accepted_block( const chain::block_state_ptr
block_state_doc.append( kvp( "createdAt", b_date{now} ) );
try {
if( !_block_states.update_one( make_document( kvp( "block_id", block_id_str ) ),
make_document( kvp( "$set", block_state_doc.view() ) ), update_opts ) ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block_state ${bid}", ("bid", block_id) );
if( update_blocks_via_block_num ) {
if( !_block_states.update_one( make_document( kvp( "block_num", b_int32{static_cast<int32_t>(block_num)} ) ),
make_document( kvp( "$set", block_state_doc.view() ) ), update_opts ) ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block_state ${num}", ("num", block_num) );
}
} else {
if( !_block_states.update_one( make_document( kvp( "block_id", block_id_str ) ),
make_document( kvp( "$set", block_state_doc.view() ) ), update_opts ) ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block_state ${bid}", ("bid", block_id) );
}
}
} catch( ... ) {
handle_mongo_exception( "block_states insert: " + json, __LINE__ );
......@@ -963,9 +996,16 @@ void mongo_db_plugin_impl::_process_accepted_block( const chain::block_state_ptr
block_doc.append( kvp( "createdAt", b_date{now} ) );
try {
if( !_blocks.update_one( make_document( kvp( "block_id", block_id_str ) ),
make_document( kvp( "$set", block_doc.view() ) ), update_opts ) ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block ${bid}", ("bid", block_id) );
if( update_blocks_via_block_num ) {
if( !_blocks.update_one( make_document( kvp( "block_num", b_int32{static_cast<int32_t>(block_num)} ) ),
make_document( kvp( "$set", block_doc.view() ) ), update_opts ) ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block ${num}", ("num", block_num) );
}
} else {
if( !_blocks.update_one( make_document( kvp( "block_id", block_id_str ) ),
make_document( kvp( "$set", block_doc.view() ) ), update_opts ) ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail, "Failed to insert block ${bid}", ("bid", block_id) );
}
}
} catch( ... ) {
handle_mongo_exception( "blocks insert: " + json, __LINE__ );
......@@ -1427,6 +1467,8 @@ void mongo_db_plugin::set_program_options(options_description& cli, options_desc
"MongoDB URI connection string, see: https://docs.mongodb.com/master/reference/connection-string/."
" If not specified then plugin is disabled. Default database 'EOS' is used if not specified in URI."
" Example: mongodb://127.0.0.1:27017/EOS")
("mongodb-update-via-block-num", bpo::value<bool>()->default_value(false),
"Update blocks/block_state with latest via block number so that duplicates are overwritten.")
("mongodb-store-blocks", bpo::value<bool>()->default_value(true),
"Enables storing blocks in mongodb.")
("mongodb-store-block-states", bpo::value<bool>()->default_value(true),
......@@ -1476,6 +1518,9 @@ void mongo_db_plugin::plugin_initialize(const variables_map& options)
if( options.count( "mongodb-block-start" )) {
my->start_block_num = options.at( "mongodb-block-start" ).as<uint32_t>();
}
if( options.count( "mongodb-update-via-block-num" )) {
my->update_blocks_via_block_num = options.at( "mongodb-update-via-block-num" ).as<bool>();
}
if( options.count( "mongodb-store-blocks" )) {
my->store_blocks = options.at( "mongodb-store-blocks" ).as<bool>();
}
......
......@@ -1556,7 +1556,7 @@ namespace eosio {
else {
c->last_handshake_recv.last_irreversible_block_num = msg.known_trx.pending;
reset_lib_num (c);
start_sync(c, msg.known_blocks.pending);
start_sync(c, msg.known_trx.pending);
}
}
......
......@@ -514,9 +514,9 @@ void producer_plugin::set_program_options(
("greylist-account", boost::program_options::value<vector<string>>()->composing()->multitoken(),
"account that can not access to extended CPU/NET virtual resources")
("produce-time-offset-us", boost::program_options::value<int32_t>()->default_value(0),
"offset of non last block producing time in micro second. Negative number results in blocks to go out sooner, and positive number results in blocks to go out later")
"offset of non last block producing time in microseconds. Negative number results in blocks to go out sooner, and positive number results in blocks to go out later")
("last-block-time-offset-us", boost::program_options::value<int32_t>()->default_value(0),
"offset of last block producing time in micro second. Negative number results in blocks to go out sooner, and positive number results in blocks to go out later")
"offset of last block producing time in microseconds. Negative number results in blocks to go out sooner, and positive number results in blocks to go out later")
("incoming-defer-ratio", bpo::value<double>()->default_value(1.0),
"ratio between incoming transations and deferred transactions when both are exhausted")
;
......
......@@ -37,7 +37,7 @@ struct async_result_visitor : public fc::visitor<std::string> {
#define CALL(api_name, api_handle, api_namespace, call_name, http_response_code) \
{std::string("/v1/" #api_name "/" #call_name), \
[this, api_handle](string, string body, url_response_callback cb) mutable { \
[api_handle](string, string body, url_response_callback cb) mutable { \
try { \
if (body.empty()) body = "{}"; \
auto result = api_handle.call_name(fc::json::from_string(body).as<api_namespace::call_name ## _params>()); \
......
......@@ -192,7 +192,6 @@ struct se_wallet_impl {
return optional<signature_type>{};
fc::ecdsa_sig sig = ECDSA_SIG_new();
BIGNUM *r = BN_new(), *s = BN_new();
CFErrorRef error = nullptr;
CFDataRef digestData = CFDataCreateWithBytesNoCopy(nullptr, (UInt8*)d.data(), d.data_size(), kCFAllocatorNull);
......@@ -205,10 +204,8 @@ struct se_wallet_impl {
}
const UInt8* der_bytes = CFDataGetBytePtr(signature);
BN_bin2bn(der_bytes+4, der_bytes[3], r);
BN_bin2bn(der_bytes+6+der_bytes[3], der_bytes[4+der_bytes[3]+1], s);
ECDSA_SIG_set0(sig, r, s);
long derSize = CFDataGetLength(signature);
d2i_ECDSA_SIG(&sig.obj, &der_bytes, derSize);
public_key_data kd;
compact_signature compact_sig;
......@@ -303,7 +300,7 @@ se_wallet::se_wallet() : my(new detail::se_wallet_impl()) {
}
unsigned int major, minor;
if(sscanf(model, "MacBookPro%u,%u", &major, &minor) == 2) {
if(major >= 13 && minor >= 2) {
if((major >= 15) || (major >= 13 && minor >= 2)) {
my->populate_existing_keys();
return;
}
......
......@@ -3,3 +3,4 @@ add_subdirectory( cleos )
add_subdirectory( keosd )
add_subdirectory( eosio-launcher )
add_subdirectory( eosio-abigen )
add_subdirectory( eosio-blocklog )
......@@ -18,6 +18,7 @@
#include <boost/asio/ssl.hpp>
#include <fc/variant.hpp>
#include <fc/io/json.hpp>
#include <fc/network/platform_root_ca.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/http_plugin/http_plugin.hpp>
#include <eosio/chain_plugin/chain_plugin.hpp>
......@@ -230,14 +231,7 @@ namespace eosio { namespace client { namespace http {
}
else { //https
boost::asio::ssl::context ssl_context(boost::asio::ssl::context::sslv23_client);
#if defined( __APPLE__ )
//TODO: this is undocumented/not supported; fix with keychain based approach
ssl_context.load_verify_file("/private/etc/ssl/cert.pem");
#elif defined( _WIN32 )
EOS_THROW(http_exception, "HTTPS on Windows not supported");
#else
ssl_context.set_default_verify_paths();
#endif
fc::add_platform_root_cas_to_context(ssl_context);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(cp.context->ios, ssl_context);
SSL_set_tlsext_host_name(socket.native_handle(), url.server.c_str());
......
......@@ -166,7 +166,8 @@ bfs::path determine_home_directory()
}
string url = "http://127.0.0.1:8888/";
string wallet_url = "http://127.0.0.1:8900/";
string default_wallet_url = "unix://" + (determine_home_directory() / "eosio-wallet" / (string(key_store_executable_name) + ".sock")).string();
string wallet_url; //to be set to default_wallet_url in main
bool no_verify = false;
vector<string> headers;
......@@ -768,25 +769,22 @@ struct set_action_permission_subcommand {
};
bool local_port_used(const string& lo_address, uint16_t port) {
bool local_port_used() {
using namespace boost::asio;
io_service ios;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(lo_address), port);
boost::asio::ip::tcp::socket socket(ios);
boost::system::error_code ec = error::would_block;
//connecting/failing to connect to localhost should be always fast - don't care about timeouts
socket.async_connect(endpoint, [&](const boost::system::error_code& error) { ec = error; } );
do {
ios.run_one();
} while (ec == error::would_block);
local::stream_protocol::endpoint endpoint(wallet_url.substr(strlen("unix://")));
local::stream_protocol::socket socket(ios);
boost::system::error_code ec;
socket.connect(endpoint, ec);
return !ec;
}
void try_local_port( const string& lo_address, uint16_t port, uint32_t duration ) {
void try_local_port(uint32_t duration) {
using namespace std::chrono;
auto start_time = duration_cast<std::chrono::milliseconds>( system_clock::now().time_since_epoch() ).count();
while ( !local_port_used(lo_address, port)) {
while ( !local_port_used()) {
if (duration_cast<std::chrono::milliseconds>( system_clock::now().time_since_epoch()).count() - start_time > duration ) {
std::cerr << "Unable to connect to keosd, if keosd is running please kill the process and try again.\n";
throw connection_exception(fc::log_messages{FC_LOG_MESSAGE(error, "Unable to connect to keosd")});
......@@ -806,16 +804,11 @@ void ensure_keosd_running(CLI::App* app) {
if (subapp->got_subcommand("listproducers") || subapp->got_subcommand("listbw") || subapp->got_subcommand("bidnameinfo")) // system list* do not require wallet
return;
}
if (wallet_url != default_wallet_url)
return;
auto parsed_url = parse_url(wallet_url);
auto resolved_url = resolve_url(context, parsed_url);
if (!resolved_url.is_loopback)
return;
for (const auto& addr: resolved_url.resolved_addresses)
if (local_port_used(addr, resolved_url.resolved_port)) // Hopefully taken by keosd
return;
if (local_port_used())
return;
boost::filesystem::path binPath = boost::dll::program_location();
binPath.remove_filename();
......@@ -827,13 +820,15 @@ void ensure_keosd_running(CLI::App* app) {
binPath.remove_filename().remove_filename().append("keosd").append(key_store_executable_name);
}
const auto& lo_address = resolved_url.resolved_addresses.front();
if (boost::filesystem::exists(binPath)) {
namespace bp = boost::process;
binPath = boost::filesystem::canonical(binPath);
vector<std::string> pargs;
pargs.push_back("--http-server-address=" + lo_address + ":" + std::to_string(resolved_url.resolved_port));
pargs.push_back("--http-server-address");
pargs.push_back("");
pargs.push_back("--https-server-address");
pargs.push_back("");
::boost::process::child keos(binPath, pargs,
bp::std_in.close(),
......@@ -842,13 +837,12 @@ void ensure_keosd_running(CLI::App* app) {
if (keos.running()) {
std::cerr << binPath << " launched" << std::endl;
keos.detach();
try_local_port(lo_address, resolved_url.resolved_port, 2000);
try_local_port(2000);
} else {
std::cerr << "No wallet service listening on " << lo_address << ":"
<< std::to_string(resolved_url.resolved_port) << ". Failed to launch " << binPath << std::endl;
std::cerr << "No wallet service listening on " << wallet_url << ". Failed to launch " << binPath << std::endl;
}
} else {
std::cerr << "No wallet service listening on " << lo_address << ":" << std::to_string(resolved_url.resolved_port)
std::cerr << "No wallet service listening on "
<< ". Cannot automatically start keosd because keosd was not found." << std::endl;
}
}
......@@ -896,6 +890,7 @@ struct create_account_subcommand {
string stake_net;
string stake_cpu;
uint32_t buy_ram_bytes_in_kbytes = 0;
uint32_t buy_ram_bytes = 0;
string buy_ram_eos;
bool transfer;
bool simple;
......@@ -913,7 +908,9 @@ struct create_account_subcommand {
createAccount->add_option("--stake-cpu", stake_cpu,
(localized("The amount of EOS delegated for CPU bandwidth")))->required();
createAccount->add_option("--buy-ram-kbytes", buy_ram_bytes_in_kbytes,
(localized("The amount of RAM bytes to purchase for the new account in kibibytes (KiB), default is 8 KiB")));
(localized("The amount of RAM bytes to purchase for the new account in kibibytes (KiB)")));
createAccount->add_option("--buy-ram-bytes", buy_ram_bytes,
(localized("The amount of RAM bytes to purchase for the new account in bytes")));
createAccount->add_option("--buy-ram", buy_ram_eos,
(localized("The amount of RAM bytes to purchase for the new account in EOS")));
createAccount->add_flag("--transfer", transfer,
......@@ -934,12 +931,10 @@ struct create_account_subcommand {
} EOS_RETHROW_EXCEPTIONS(public_key_type_exception, "Invalid active public key: ${public_key}", ("public_key", active_key_str));
auto create = create_newaccount(creator, account_name, owner_key, active_key);
if (!simple) {
if ( buy_ram_eos.empty() && buy_ram_bytes_in_kbytes == 0) {
std::cerr << "ERROR: Either --buy-ram or --buy-ram-kbytes with non-zero value is required" << std::endl;
return;
}
EOSC_ASSERT( buy_ram_eos.size() || buy_ram_bytes_in_kbytes || buy_ram_bytes, "ERROR: One of --buy-ram, --buy-ram-kbytes or --buy-ram-bytes should have non-zero value" );
EOSC_ASSERT( !buy_ram_bytes_in_kbytes || !buy_ram_bytes, "ERROR: --buy-ram-kbytes and --buy-ram-bytes cannot be set at the same time" );
action buyram = !buy_ram_eos.empty() ? create_buyram(creator, account_name, to_asset(buy_ram_eos))
: create_buyrambytes(creator, account_name, buy_ram_bytes_in_kbytes * 1024);
: create_buyrambytes(creator, account_name, (buy_ram_bytes_in_kbytes) ? (buy_ram_bytes_in_kbytes * 1024) : buy_ram_bytes);
auto net = to_asset(stake_net);
auto cpu = to_asset(stake_cpu);
if ( net.get_amount() != 0 || cpu.get_amount() != 0 ) {
......@@ -1200,6 +1195,7 @@ struct delegate_bandwidth_subcommand {
string stake_cpu_amount;
string stake_storage_amount;
string buy_ram_amount;
uint32_t buy_ram_bytes = 0;
bool transfer = false;
delegate_bandwidth_subcommand(CLI::App* actionRoot) {
......@@ -1209,6 +1205,7 @@ struct delegate_bandwidth_subcommand {
delegate_bandwidth->add_option("stake_net_quantity", stake_net_amount, localized("The amount of EOS to stake for network bandwidth"))->required();
delegate_bandwidth->add_option("stake_cpu_quantity", stake_cpu_amount, localized("The amount of EOS to stake for CPU bandwidth"))->required();
delegate_bandwidth->add_option("--buyram", buy_ram_amount, localized("The amount of EOS to buyram"));
delegate_bandwidth->add_option("--buy-ram-bytes", buy_ram_bytes, localized("The amount of RAM to buy in number of bytes"));
delegate_bandwidth->add_flag("--transfer", transfer, localized("Transfer voting power and right to unstake EOS to receiver"));
add_standard_transaction_options(delegate_bandwidth);
......@@ -1220,12 +1217,11 @@ struct delegate_bandwidth_subcommand {
("stake_cpu_quantity", to_asset(stake_cpu_amount))
("transfer", transfer);
std::vector<chain::action> acts{create_action({permission_level{from_str,config::active_name}}, config::system_account_name, N(delegatebw), act_payload)};
if (buy_ram_amount.length()) {
fc::variant act_payload2 = fc::mutable_variant_object()
("payer", from_str)
("receiver", receiver_str)
("quant", to_asset(buy_ram_amount));
acts.push_back(create_action({permission_level{from_str,config::active_name}}, config::system_account_name, N(buyram), act_payload2));
EOSC_ASSERT( !(buy_ram_amount.size()) || !buy_ram_bytes, "ERROR: --buyram and --buy-ram-bytes cannot be set at the same time" );
if (buy_ram_amount.size()) {
acts.push_back( create_buyram(from_str, receiver_str, to_asset(buy_ram_amount)) );
} else if (buy_ram_bytes) {
acts.push_back( create_buyrambytes(from_str, receiver_str, buy_ram_bytes) );
}
send_actions(std::move(acts));
});
......@@ -1353,27 +1349,22 @@ struct buyram_subcommand {
string receiver_str;
string amount;
bool kbytes = false;
bool bytes = false;
buyram_subcommand(CLI::App* actionRoot) {
auto buyram = actionRoot->add_subcommand("buyram", localized("Buy RAM"));
buyram->add_option("payer", from_str, localized("The account paying for RAM"))->required();
buyram->add_option("receiver", receiver_str, localized("The account receiving bought RAM"))->required();
buyram->add_option("amount", amount, localized("The amount of EOS to pay for RAM, or number of kbytes of RAM if --kbytes is set"))->required();
buyram->add_flag("--kbytes,-k", kbytes, localized("buyram in number of kbytes"));
buyram->add_option("amount", amount, localized("The amount of EOS to pay for RAM, or number of bytes/kibibytes of RAM if --bytes/--kbytes is set"))->required();
buyram->add_flag("--kbytes,-k", kbytes, localized("buyram in number of kibibytes (KiB)"));
buyram->add_flag("--bytes,-b", bytes, localized("buyram in number of bytes"));
add_standard_transaction_options(buyram);
buyram->set_callback([this] {
if (kbytes) {
fc::variant act_payload = fc::mutable_variant_object()
("payer", from_str)
("receiver", receiver_str)
("bytes", fc::to_uint64(amount) * 1024ull);
send_actions({create_action({permission_level{from_str,config::active_name}}, config::system_account_name, N(buyrambytes), act_payload)});
EOSC_ASSERT( !kbytes || !bytes, "ERROR: --kbytes and --bytes cannot be set at the same time" );
if (kbytes || bytes) {
send_actions( { create_buyrambytes(from_str, receiver_str, fc::to_uint64(amount) * ((kbytes) ? 1024ull : 1ull)) } );
} else {
fc::variant act_payload = fc::mutable_variant_object()
("payer", from_str)
("receiver", receiver_str)
("quant", to_asset(amount));
send_actions({create_action({permission_level{from_str,config::active_name}}, config::system_account_name, N(buyram), act_payload)});
send_actions( { create_buyram(from_str, receiver_str, to_asset(amount)) } );
}
});
}
......@@ -1745,6 +1736,7 @@ int main( int argc, char** argv ) {
bindtextdomain(locale_domain, locale_path);
textdomain(locale_domain);
context = eosio::client::http::create_http_context();
wallet_url = default_wallet_url;
CLI::App app{"Command Line Interface to EOSIO Client"};
app.require_subcommand();
......
add_executable( eosio-blocklog main.cpp )
if( UNIX AND NOT APPLE )
set(rt_library rt )
endif()
find_package( Gperftools QUIET )
if( GPERFTOOLS_FOUND )
message( STATUS "Found gperftools; compiling eosio-blocklog with TCMalloc")
list( APPEND PLATFORM_SPECIFIC_LIBS tcmalloc )
endif()
target_include_directories(eosio-blocklog PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries( eosio-blocklog
PRIVATE appbase
PRIVATE eosio_chain fc ${CMAKE_DL_LIBS} ${PLATFORM_SPECIFIC_LIBS} )
install( TARGETS
eosio-blocklog
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
)
/**
* @file
* @copyright defined in eosio/LICENSE.txt
*/
#include <eosio/chain/abi_serializer.hpp>
#include <eosio/chain/block_log.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/reversible_block_object.hpp>
#include <fc/io/json.hpp>
#include <fc/filesystem.hpp>
#include <fc/variant.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
using namespace eosio::chain;
namespace bfs = boost::filesystem;
namespace bpo = boost::program_options;
using bpo::options_description;
using bpo::variables_map;
struct blocklog {
blocklog()
{}
void read_log();
void set_program_options(options_description& cli);
void initialize(const variables_map& options);
bfs::path blocks_dir;
bfs::path output_file;
uint32_t first_block;
uint32_t last_block;
bool no_pretty_print;
};
void blocklog::read_log() {
block_log block_logger(blocks_dir);
const auto end = block_logger.read_head();
EOS_ASSERT( end, block_log_exception, "No blocks found in block log" );
EOS_ASSERT( end->block_num() > 1, block_log_exception, "Only one block found in block log" );
ilog( "existing block log contains block num 1 through block num ${n}", ("n",end->block_num()) );
optional<chainbase::database> reversible_blocks;
try {
reversible_blocks.emplace(blocks_dir / config::reversible_blocks_dir_name, chainbase::database::read_only, config::default_reversible_cache_size);
reversible_blocks->add_index<reversible_block_index>();
const auto& idx = reversible_blocks->get_index<reversible_block_index,by_num>();
auto first = idx.lower_bound(end->block_num());
auto last = idx.rbegin();
if (first != idx.end() && last != idx.rend())
ilog( "existing reversible block num ${first} through block num ${last} ", ("first",first->get_block()->block_num())("last",last->get_block()->block_num()) );
else {
elog( "no blocks available in reversible block database: only block_log blocks are available" );
reversible_blocks.reset();
}
} catch( const std::runtime_error& e ) {
if( std::string(e.what()) == "database dirty flag set" ) {
elog( "database dirty flag set (likely due to unclean shutdown): only block_log blocks are available" );
} else if( std::string(e.what()) == "database metadata dirty flag set" ) {
elog( "database metadata dirty flag set (likely due to unclean shutdown): only block_log blocks are available" );
} else {
throw;
}
}
std::ofstream output_blocks;
std::ostream* out;
if (!output_file.empty()) {
output_blocks.open(output_file.generic_string().c_str());
if (output_blocks.fail()) {
std::ostringstream ss;
ss << "Unable to open file '" << output_file.string() << "'";
throw std::runtime_error(ss.str());
}
out = &output_blocks;
}
else
out = &std::cout;
uint32_t block_num = (first_block < 1) ? 1 : first_block;
signed_block_ptr next;
fc::variant pretty_output;
const fc::microseconds deadline = fc::seconds(10);
auto print_block = [&](signed_block_ptr& next) {
abi_serializer::to_variant(*next,
pretty_output,
[]( account_name n ) { return optional<abi_serializer>(); },
deadline);
const auto block_id = next->id();
const uint32_t ref_block_prefix = block_id._hash[1];
const auto enhanced_object = fc::mutable_variant_object
("block_num",next->block_num())
("id", block_id)
("ref_block_prefix", ref_block_prefix)
(pretty_output.get_object());
fc::variant v(std::move(enhanced_object));
if (no_pretty_print)
fc::json::to_stream(*out, v, fc::json::stringify_large_ints_and_doubles);
else
*out << fc::json::to_pretty_string(v) << "\n";
};
while((block_num <= last_block) && (next = block_logger.read_block_by_num( block_num ))) {
print_block(next);
++block_num;
out->flush();
}
if (!reversible_blocks) {
return;
}
const reversible_block_object* obj = nullptr;
while( (block_num <= last_block) && (obj = reversible_blocks->find<reversible_block_object,by_num>(block_num)) ) {
auto next = obj->get_block();
print_block(next);
++block_num;
}
}
void blocklog::set_program_options(options_description& cli)
{
cli.add_options()
("blocks-dir", bpo::value<bfs::path>()->default_value("blocks"),
"the location of the blocks directory (absolute path or relative to the current directory)")
("output-file,o", bpo::value<bfs::path>(),
"the file to write the block log output to (absolute or relative path). If not specified then output is to stdout.")
("first", bpo::value<uint32_t>(&first_block)->default_value(1),
"the first block number to log")
("last", bpo::value<uint32_t>(&last_block)->default_value(std::numeric_limits<uint32_t>::max()),
"the last block number (inclusive) to log")
("no-pretty-print", bpo::bool_switch(&no_pretty_print)->default_value(false),
"Do not pretty print the output. Useful if piping to jq to improve performance.")
("help", "Print this help message and exit.")
;
}
void blocklog::initialize(const variables_map& options) {
try {
auto bld = options.at( "blocks-dir" ).as<bfs::path>();
if( bld.is_relative())
blocks_dir = bfs::current_path() / bld;
else
blocks_dir = bld;
if (options.count( "output-file" )) {
bld = options.at( "output-file" ).as<bfs::path>();
if( bld.is_relative())
output_file = bfs::current_path() / bld;
else
output_file = bld;
}
} FC_LOG_AND_RETHROW()
}
int main(int argc, char** argv)
{
std::ios::sync_with_stdio(false); // for potential performance boost for large block log files
options_description cli ("eosio-blocklog command line options");
try {
blocklog blog;
blog.set_program_options(cli);
variables_map vmap;
bpo::store(bpo::parse_command_line(argc, argv, cli), vmap);
bpo::notify(vmap);
if (vmap.count("help") > 0) {
cli.print(std::cerr);
return 0;
}
blog.initialize(vmap);
blog.read_log();
} catch( const fc::exception& e ) {
elog( "${e}", ("e", e.to_detail_string()));
return -1;
} catch( const boost::exception& e ) {
elog("${e}", ("e",boost::diagnostic_information(e)));
return -1;
} catch( const std::exception& e ) {
elog("${e}", ("e",e.what()));
return -1;
} catch( ... ) {
elog("unknown exception");
return -1;
}
return 0;
}
......@@ -26,6 +26,7 @@
#include <fc/crypto/private_key.hpp>
#include <fc/crypto/public_key.hpp>
#include <fc/io/json.hpp>
#include <fc/optional.hpp>
#include <fc/network/ip.hpp>
#include <fc/reflect/variant.hpp>
#include <fc/log/logger_config.hpp>
......@@ -387,63 +388,65 @@ string producer_names::producer_name(unsigned int producer_number) {
}
struct launcher_def {
bool force_overwrite;
size_t total_nodes;
size_t prod_nodes;
size_t producers;
size_t next_node;
string shape;
p2p_plugin p2p;
allowed_connection allowed_connections = PC_NONE;
bfs::path genesis;
bfs::path output;
bfs::path host_map_file;
bfs::path server_ident_file;
bfs::path stage;
string erd;
bfs::path config_dir_base;
bfs::path data_dir_base;
bool skip_transaction_signatures = false;
string eosd_extra_args;
std::map<uint,string> specific_nodeos_args;
testnet_def network;
string gelf_endpoint;
vector <string> aliases;
vector <host_def> bindings;
int per_host = 0;
last_run_def last_run;
int start_delay = 0;
bool gelf_enabled;
bool nogen;
bool boot;
bool add_enable_stale_production = false;
string launch_name;
string launch_time;
server_identities servers;
producer_set_def producer_set;
vector<string> genesis_block;
bool force_overwrite;
size_t total_nodes;
size_t prod_nodes;
size_t producers;
size_t next_node;
string shape;
p2p_plugin p2p;
allowed_connection allowed_connections = PC_NONE;
bfs::path genesis;
bfs::path output;
bfs::path host_map_file;
bfs::path server_ident_file;
bfs::path stage;
string erd;
bfs::path config_dir_base;
bfs::path data_dir_base;
bool skip_transaction_signatures = false;
string eosd_extra_args;
std::map<uint,string> specific_nodeos_args;
testnet_def network;
string gelf_endpoint;
vector <string> aliases;
vector <host_def> bindings;
int per_host = 0;
last_run_def last_run;
int start_delay = 0;
bool gelf_enabled;
bool nogen;
bool boot;
bool add_enable_stale_production = false;
string launch_name;
string launch_time;
server_identities servers;
producer_set_def producer_set;
string start_temp;
string start_script;
fc::optional<uint32_t> max_block_cpu_usage;
fc::optional<uint32_t> max_transaction_cpu_usage;
eosio::chain::genesis_state genesis_from_file;
void assign_name (eosd_def &node, bool is_bios);
void set_options (bpo::options_description &cli);
void initialize (const variables_map &vmap);
void set_options (bpo::options_description &cli);
void initialize (const variables_map &vmap);
void init_genesis ();
void load_servers ();
bool generate ();
void define_network ();
void bind_nodes ();
host_def *find_host (const string &name);
host_def *find_host_by_name_or_address (const string &name);
host_def *deploy_config_files (tn_node_def &node);
string compose_scp_command (const host_def &host, const bfs::path &source,
const bfs::path &destination);
void write_config_file (tn_node_def &node);
void write_logging_config_file (tn_node_def &node);
void write_genesis_file (tn_node_def &node);
void write_setprods_file ();
void load_servers ();
bool generate ();
void define_network ();
void bind_nodes ();
host_def *find_host (const string &name);
host_def *find_host_by_name_or_address (const string &name);
host_def *deploy_config_files (tn_node_def &node);
string compose_scp_command (const host_def &host, const bfs::path &source,
const bfs::path &destination);
void write_config_file (tn_node_def &node);
void write_logging_config_file (tn_node_def &node);
void write_genesis_file (tn_node_def &node);
void write_setprods_file ();
void write_bios_boot ();
bool is_bios_ndx (size_t ndx);
......@@ -451,25 +454,25 @@ struct launcher_def {
bool next_ndx(size_t &ndx);
size_t skip_ndx (size_t from, size_t offset);
void make_ring ();
void make_star ();
void make_mesh ();
void make_custom ();
void write_dot_file ();
void format_ssh (const string &cmd, const string &host_name, string &ssh_cmd_line);
void do_command(const host_def& host, const string& name, vector<pair<string, string>> env_pairs, const string& cmd);
bool do_ssh (const string &cmd, const string &host_name);
void prep_remote_config_dir (eosd_def &node, host_def *host);
void launch (eosd_def &node, string &gts);
void kill (launch_modes mode, string sig_opt);
static string get_node_num(uint16_t node_num);
pair<host_def, eosd_def> find_node(uint16_t node_num);
vector<pair<host_def, eosd_def>> get_nodes(const string& node_number_list);
void bounce (const string& node_numbers);
void down (const string& node_numbers);
void roll (const string& host_names);
void start_all (string &gts, launch_modes mode);
void ignite ();
void make_ring ();
void make_star ();
void make_mesh ();
void make_custom ();
void write_dot_file ();
void format_ssh (const string &cmd, const string &host_name, string &ssh_cmd_line);
void do_command(const host_def& host, const string& name, vector<pair<string, string>> env_pairs, const string& cmd);
bool do_ssh (const string &cmd, const string &host_name);
void prep_remote_config_dir (eosd_def &node, host_def *host);
void launch (eosd_def &node, string &gts);
void kill (launch_modes mode, string sig_opt);
static string get_node_num(uint16_t node_num);
pair<host_def, eosd_def> find_node(uint16_t node_num);
vector<pair<host_def, eosd_def>> get_nodes(const string& node_number_list);
void bounce (const string& node_numbers);
void down (const string& node_numbers);
void roll (const string& host_names);
void start_all (string &gts, launch_modes mode);
void ignite ();
};
void
......@@ -482,7 +485,7 @@ launcher_def::set_options (bpo::options_description &cfg) {
("mode,m",bpo::value<vector<string>>()->multitoken()->default_value({"any"}, "any"),"connection mode, combination of \"any\", \"producers\", \"specified\", \"none\"")
("shape,s",bpo::value<string>(&shape)->default_value("star"),"network topology, use \"star\" \"mesh\" or give a filename for custom")
("p2p-plugin", bpo::value<string>()->default_value("net"),"select a p2p plugin to use (either net or bnet). Defaults to net.")
("genesis,g",bpo::value<bfs::path>(&genesis)->default_value("./genesis.json"),"set the path to genesis.json")
("genesis,g",bpo::value<string>()->default_value("./genesis.json"),"set the path to genesis.json")
("skip-signature", bpo::bool_switch(&skip_transaction_signatures)->default_value(false), "nodeos does not require transaction signatures.")
("nodeos", bpo::value<string>(&eosd_extra_args), "forward nodeos command line argument(s) to each instance of nodeos, enclose arg(s) in quotes")
("specific-num", bpo::value<vector<uint>>()->composing(), "forward nodeos command line argument(s) (using \"--specific-nodeos\" flag) to this specific instance of nodeos. This parameter can be entered multiple times and requires a paired \"--specific-nodeos\" flag")
......@@ -490,14 +493,16 @@ launcher_def::set_options (bpo::options_description &cfg) {
("delay,d",bpo::value<int>(&start_delay)->default_value(0),"seconds delay before starting each node after the first")
("boot",bpo::bool_switch(&boot)->default_value(false),"After deploying the nodes and generating a boot script, invoke it.")
("nogen",bpo::bool_switch(&nogen)->default_value(false),"launch nodes without writing new config files")
("host-map",bpo::value<bfs::path>(&host_map_file)->default_value(""),"a file containing mapping specific nodes to hosts. Used to enhance the custom shape argument")
("servers",bpo::value<bfs::path>(&server_ident_file)->default_value(""),"a file containing ip addresses and names of individual servers to deploy as producers or non-producers ")
("host-map",bpo::value<string>(),"a file containing mapping specific nodes to hosts. Used to enhance the custom shape argument")
("servers",bpo::value<string>(),"a file containing ip addresses and names of individual servers to deploy as producers or non-producers ")
("per-host",bpo::value<int>(&per_host)->default_value(0),"specifies how many nodeos instances will run on a single host. Use 0 to indicate all on one.")
("network-name",bpo::value<string>(&network.name)->default_value("testnet_"),"network name prefix used in GELF logging source")
("enable-gelf-logging",bpo::value<bool>(&gelf_enabled)->default_value(true),"enable gelf logging appender in logging configuration file")
("gelf-endpoint",bpo::value<string>(&gelf_endpoint)->default_value("10.160.11.21:12201"),"hostname:port or ip:port of GELF endpoint")
("template",bpo::value<string>(&start_temp)->default_value("testnet.template"),"the startup script template")
("script",bpo::value<string>(&start_script)->default_value("bios_boot.sh"),"the generated startup script name")
("max-block-cpu-usage",bpo::value<uint32_t>(),"Provide the \"max-block-cpu-usage\" value to use in the genesis.json file")
("max-transaction-cpu-usage",bpo::value<uint32_t>(),"Provide the \"max-transaction-cpu-usage\" value to use in the genesis.json file")
;
}
......@@ -529,6 +534,22 @@ launcher_def::initialize (const variables_map &vmap) {
}
}
if (vmap.count("max-block-cpu-usage")) {
max_block_cpu_usage = vmap["max-block-cpu-usage"].as<uint32_t>();
}
if (vmap.count("max-transaction-cpu-usage")) {
max_transaction_cpu_usage = vmap["max-transaction-cpu-usage"].as<uint32_t>();
}
genesis = vmap["genesis"].as<string>();
if (vmap.count("host-map")) {
host_map_file = vmap["host-map"].as<string>();
}
if (vmap.count("servers")) {
server_ident_file = vmap["servers"].as<string>();
}
if (vmap.count("specific-num")) {
const auto specific_nums = vmap["specific-num"].as<vector<uint>>();
const auto specific_args = vmap["specific-nodeos"].as<vector<string>>();
......@@ -1157,27 +1178,20 @@ launcher_def::write_logging_config_file(tn_node_def &node) {
void
launcher_def::init_genesis () {
bfs::path genesis_path = bfs::current_path() / "genesis.json";
bfs::ifstream src(genesis_path);
if (!src.good()) {
const bfs::path genesis_path = genesis.is_complete() ? genesis : bfs::current_path() / genesis;
if (!bfs::exists(genesis_path)) {
cout << "generating default genesis file " << genesis_path << endl;
eosio::chain::genesis_state default_genesis;
fc::json::save_to_file( default_genesis, genesis_path, true );
src.open(genesis_path);
}
string bioskey = string(network.nodes["bios"].keys[0].get_public_key());
string str;
string prefix("initial_key");
while(getline(src,str)) {
size_t pos = str.find(prefix);
if (pos != string::npos) {
size_t cut = str.find("EOS",pos);
genesis_block.push_back(str.substr(0,cut) + bioskey + "\",");
}
else {
genesis_block.push_back(str);
}
}
fc::json::from_file(genesis_path).as<eosio::chain::genesis_state>(genesis_from_file);
genesis_from_file.initial_key = public_key_type(bioskey);
if (max_block_cpu_usage)
genesis_from_file.initial_configuration.max_block_cpu_usage = *max_block_cpu_usage;
if (max_transaction_cpu_usage)
genesis_from_file.initial_configuration.max_transaction_cpu_usage = *max_transaction_cpu_usage;
}
void
......@@ -1191,10 +1205,7 @@ launcher_def::write_genesis_file(tn_node_def &node) {
}
filename = dd / "genesis.json";
bfs::ofstream gf ( dd / "genesis.json");
for (auto &line : genesis_block) {
gf << line << "\n";
}
fc::json::save_to_file( genesis_from_file, dd / "genesis.json", true );
}
void
......@@ -1707,6 +1718,13 @@ launcher_def::bounce (const string& node_numbers) {
const string node_num = node.get_node_num();
cout << "Bouncing " << node.name << endl;
string cmd = "./scripts/eosio-tn_bounce.sh " + eosd_extra_args;
if (node_num != "bios" && !specific_nodeos_args.empty()) {
const auto node_num_i = boost::lexical_cast<uint16_t,string>(node_num);
if (specific_nodeos_args.count(node_num_i)) {
cmd += " " + specific_nodeos_args[node_num_i];
}
}
do_command(host, node.name, { { "EOSIO_HOME", host.eosio_home }, { "EOSIO_NODE", node_num } }, cmd);
}
}
......
......@@ -43,7 +43,7 @@ int main(int argc, char** argv)
http_plugin::set_defaults({
.address_config_prefix = "",
.default_unix_socket_path = keosd::config::key_store_executable_name + ".sock",
.default_http_port = 8900
.default_http_port = 0
});
app().register_plugin<wallet_api_plugin>();
if(!app().initialize<wallet_plugin, wallet_api_plugin, http_plugin>(argc, argv))
......
......@@ -59,7 +59,7 @@ add_test(NAME p2p_dawn515_test COMMAND tests/p2p_tests/dawn_515/test.sh WORKING_
set_property(TEST p2p_dawn515_test PROPERTY LABELS nonparallelizable_tests)
if(BUILD_MONGO_DB_PLUGIN)
add_test(NAME nodeos_run_test-mongodb COMMAND tests/nodeos_run_test.py --mongodb -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_run_test PROPERTY LABELS nonparallelizable_tests)
set_property(TEST nodeos_run_test-mongodb PROPERTY LABELS nonparallelizable_tests)
endif()
add_test(NAME distributed-transactions-test COMMAND tests/distributed-transactions-test.py -d 2 -p 1 -n 4 -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
......@@ -81,20 +81,22 @@ add_test(NAME nodeos_sanity_lr_test COMMAND tests/nodeos_run_test.py -v --sanity
set_property(TEST nodeos_sanity_lr_test PROPERTY LABELS long_running_tests)
add_test(NAME bnet_nodeos_sanity_lr_test COMMAND tests/nodeos_run_test.py -v --sanity-test --p2p-plugin bnet --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST bnet_nodeos_sanity_lr_test PROPERTY LABELS long_running_tests)
add_test(NAME nodeos_run_check_lr_test COMMAND tests/nodeos_run_test.py -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_run_check_lr_test PROPERTY LABELS long_running_tests)
#add_test(NAME distributed_transactions_lr_test COMMAND tests/distributed-transactions-test.py -d 2 -p 21 -n 21 -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
#set_property(TEST distributed_transactions_lr_test PROPERTY LABELS long_running_tests)
add_test(NAME nodeos_forked_chain_lr_test COMMAND tests/nodeos_forked_chain_test.py -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME nodeos_forked_chain_lr_test COMMAND tests/nodeos_forked_chain_test.py -v --wallet-port 9901 --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_forked_chain_lr_test PROPERTY LABELS long_running_tests)
add_test(NAME nodeos_voting_lr_test COMMAND tests/nodeos_voting_test.py -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME nodeos_voting_lr_test COMMAND tests/nodeos_voting_test.py -v --wallet-port 9902 --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_voting_lr_test PROPERTY LABELS long_running_tests)
add_test(NAME bnet_nodeos_voting_lr_test COMMAND tests/nodeos_voting_test.py -v --p2p-plugin bnet --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME bnet_nodeos_voting_lr_test COMMAND tests/nodeos_voting_test.py -v --wallet-port 9903 --p2p-plugin bnet --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST bnet_nodeos_voting_lr_test PROPERTY LABELS long_running_tests)
add_test(NAME nodeos_under_min_avail_ram_lr_test COMMAND tests/nodeos_under_min_avail_ram.py -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME nodeos_under_min_avail_ram_lr_test COMMAND tests/nodeos_under_min_avail_ram.py -v --wallet-port 9904 --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST nodeos_under_min_avail_ram_lr_test PROPERTY LABELS long_running_tests)
......
此差异已折叠。
......@@ -31,7 +31,7 @@ class Node(object):
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-many-arguments
def __init__(self, host, port, pid=None, cmd=None, enableMongo=False, mongoHost="localhost", mongoPort=27017, mongoDb="EOStest"):
def __init__(self, host, port, pid=None, cmd=None, walletMgr=None, enableMongo=False, mongoHost="localhost", mongoPort=27017, mongoDb="EOStest"):
self.host=host
self.port=port
self.pid=pid
......@@ -44,16 +44,18 @@ class Node(object):
self.mongoDb=mongoDb
self.endpointHttp="http://%s:%d" % (self.host, self.port)
self.endpointArgs="--url %s" % (self.endpointHttp)
self.miscEosClientArgs="--no-auto-keosd"
self.mongoEndpointArgs=""
self.infoValid=None
self.lastRetrievedHeadBlockNum=None
self.lastRetrievedLIB=None
self.transCache={}
self.walletMgr=walletMgr
if self.enableMongo:
self.mongoEndpointArgs += "--host %s --port %d %s" % (mongoHost, mongoPort, mongoDb)
def eosClientArgs(self):
return self.endpointArgs + " " + self.miscEosClientArgs
walletArgs=" " + self.walletMgr.getWalletEndpointArgs() if self.walletMgr is not None else ""
return self.endpointArgs + walletArgs + " " + Utils.MiscEosClientArgs
def __str__(self):
#return "Host: %s, Port:%d, Pid:%s, Cmd:\"%s\"" % (self.host, self.port, self.pid, self.cmd)
......@@ -64,11 +66,80 @@ class Node(object):
assert trans
assert isinstance(trans, dict), print("Input type is %s" % type(trans))
def printTrans(trans):
Utils.Print("ERROR: Failure in transaction validation.")
executed="executed"
def printTrans(trans, status):
Utils.Print("ERROR: Valid transaction should be \"%s\" but it was \"%s\"." % (executed, status))
Utils.Print("Transaction: %s" % (json.dumps(trans, indent=1)))
assert trans["processed"]["receipt"]["status"] == "executed", printTrans(trans)
transStatus=Node.getTransStatus(trans)
assert transStatus == executed, printTrans(trans, transStatus)
@staticmethod
def __printTransStructureError(trans, context):
Utils.Print("ERROR: Failure in expected transaction structure. Missing trans%s." % (context))
Utils.Print("Transaction: %s" % (json.dumps(trans, indent=1)))
class Context:
def __init__(self, obj, desc):
self.obj=obj
self.sections=[obj]
self.keyContext=[]
self.desc=desc
def __json(self):
return "%s=\n%s" % (self.desc, json.dumps(self.obj, indent=1))
def __keyContext(self):
msg=""
for key in self.keyContext:
if msg=="":
msg="["
else:
msg+="]["
msg+=key
if msg!="":
msg+="]"
return msg
def __contextDesc(self):
return "%s%s" % (self.desc, self.__keyContext())
def add(self, newKey):
assert isinstance(newKey, str), print("ERROR: Trying to use %s as a key" % (newKey))
subSection=self.sections[-1]
assert isinstance(subSection, dict), print("ERROR: Calling \"add\" method when context is not a dictionary. %s in %s" % (self.__contextDesc(), self.__json()))
assert newKey in subSection, print("ERROR: %s%s does not contain key \"%s\". %s" % (self.__contextDesc(), key, self.__json()))
current=subSection[newKey]
self.sections.append(current)
self.keyContext.append(newKey)
return current
def index(self, i):
assert isinstance(i, int), print("ERROR: Trying to use \"%s\" as a list index" % (i))
cur=self.getCurrent()
assert isinstance(cur, list), print("ERROR: Calling \"index\" method when context is not a list. %s in %s" % (self.__contextDesc(), self.__json()))
listLen=len(cur)
assert i < listLen, print("ERROR: Index %s is beyond the size of the current list (%s). %s in %s" % (i, listLen, self.__contextDesc(), self.__json()))
return self.sections.append(cur[i])
def getCurrent(self):
return self.sections[-1]
@staticmethod
def getTransStatus(trans):
cntxt=Node.Context(trans, "trans")
cntxt.add("processed")
cntxt.add("receipt")
return cntxt.add("status")
@staticmethod
def getTransBlockNum(trans):
cntxt=Node.Context(trans, "trans")
cntxt.add("processed")
cntxt.add("action_traces")
cntxt.index(0)
return cntxt.add("block_num")
@staticmethod
def stdinAndCheckOutput(cmd, subcommand):
......@@ -140,17 +211,22 @@ class Node(object):
assert trans
assert isinstance(trans, dict), print("Input type is %s" % type(trans))
#Utils.Print("%s" % trans)
assert "transaction_id" in trans, print("trans does not contain key %s. trans={%s}" % ("transaction_id", json.dumps(trans, indent=2, sort_keys=True)))
transId=trans["transaction_id"]
return transId
@staticmethod
def isTrans(obj):
"""Identify if this is a transaction dictionary."""
if obj is None or not isinstance(obj, dict):
return False
return True if "transaction_id" in obj else False
@staticmethod
def byteArrToStr(arr):
return arr.decode("utf-8")
def setWalletEndpointArgs(self, args):
self.endpointArgs="--url http://%s:%d %s" % (self.host, self.port, args)
def validateAccounts(self, accounts):
assert(accounts)
assert(isinstance(accounts, list))
......@@ -249,8 +325,10 @@ class Node(object):
return self.isBlockPresent(blockNum, blockType=BlockType.lib)
class BlockWalker:
def __init__(self, node, trans, startBlockNum=None, endBlockNum=None):
self.trans=trans
def __init__(self, node, transId, startBlockNum=None, endBlockNum=None):
assert(isinstance(transId, str))
self.trans=None
self.transId=transId
self.node=node
self.startBlockNum=startBlockNum
self.endBlockNum=endBlockNum
......@@ -258,32 +336,45 @@ class Node(object):
def walkBlocks(self):
start=None
end=None
blockNum=self.trans["processed"]["action_traces"][0]["block_num"]
if self.trans is None and self.transId in self.transCache.keys():
self.trans=self.transCache[self.transId]
if self.trans is not None:
cntxt=Node.Context(self.trans, "trans")
cntxt.add("processed")
cntxt.add("action_traces")
cntxt.index(0)
blockNum=cntxt.add("block_num")
else:
blockNum=None
# it should be blockNum or later, but just in case the block leading up have any clues...
start=None
if self.startBlockNum is not None:
start=self.startBlockNum
else:
elif blockNum is not None:
start=blockNum-5
if self.endBlockNum is not None:
end=self.endBlockNum
else:
info=self.node.getInfo()
end=info["head_block_num"]
msg="Original transaction=\n%s\nExpected block_num=%s\n" % (json.dumps(trans, indent=2, sort_keys=True), blockNum)
if start is None:
if end > 100:
start=end-100
else:
start=0
transDesc=" id =%s" % (self.transId)
if self.trans is not None:
transDesc="=%s" % (json.dumps(self.trans, indent=2, sort_keys=True))
msg="Original transaction%s\nExpected block_num=%s\n" % (transDesc, blockNum)
for blockNum in range(start, end+1):
block=self.node.getBlock(blockNum)
msg+=json.dumps(block, indent=2, sort_keys=True)+"\n"
return msg
# pylint: disable=too-many-branches
def getTransaction(self, transOrTransId, silentErrors=False, exitOnError=False, delayedRetry=True):
transId=None
trans=None
assert(isinstance(transOrTransId, (str,dict)))
if isinstance(transOrTransId, str):
transId=transOrTransId
else:
trans=transOrTransId
transId=Node.getTransId(trans)
def getTransaction(self, transId, silentErrors=False, exitOnError=False, delayedRetry=True):
assert(isinstance(transId, str))
exitOnErrorForDelayed=not delayedRetry and exitOnError
timeout=3
blockWalker=None
......@@ -296,7 +387,7 @@ class Node(object):
if trans is not None or not delayedRetry:
return trans
if blockWalker is None:
blockWalker=Node.BlockWalker(self, trans)
blockWalker=Node.BlockWalker(self, transId)
if Utils.Debug: Utils.Print("Could not find transaction with id %s, delay and retry" % (transId))
time.sleep(timeout)
......@@ -367,16 +458,11 @@ class Node(object):
return False
def getBlockIdByTransId(self, transOrTransId, delayedRetry=True):
"""Given a transaction (dictionary) or transaction Id (string), will return the actual block id (int) containing the transaction"""
assert(transOrTransId)
transId=None
assert(isinstance(transOrTransId, (str,dict)))
if isinstance(transOrTransId, str):
transId=transOrTransId
else:
transId=Node.getTransId(transOrTransId)
trans=self.getTransaction(transOrTransId, exitOnError=True, delayedRetry=delayedRetry)
def getBlockIdByTransId(self, transId, delayedRetry=True):
"""Given a transaction Id (string), will return the actual block id (int) containing the transaction"""
assert(transId)
assert(isinstance(transId, str))
trans=self.getTransaction(transId, exitOnError=True, delayedRetry=delayedRetry)
refBlockNum=None
key=""
......@@ -466,6 +552,7 @@ class Node(object):
account.activePublicKey, stakeNet, CORE_SYMBOL, stakeCPU, CORE_SYMBOL, buyRAM, CORE_SYMBOL)
msg="(creator account=%s, account=%s)" % (creatorAccount.name, account.name);
trans=self.processCleosCmd(cmd, cmdDesc, silentErrors=False, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
transId=Node.getTransId(trans)
if stakedDeposit > 0:
......@@ -483,11 +570,13 @@ class Node(object):
cmdDesc, creatorAccount.name, account.name, account.ownerPublicKey, account.activePublicKey)
msg="(creator account=%s, account=%s)" % (creatorAccount.name, account.name);
trans=self.processCleosCmd(cmd, cmdDesc, silentErrors=False, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
transId=Node.getTransId(trans)
if stakedDeposit > 0:
self.waitForTransInBlock(transId) # seems like account creation needs to be finlized before transfer can happen
trans = self.transferFunds(creatorAccount, account, "%0.04f %s" % (stakedDeposit/10000, CORE_SYMBOL), "init")
self.trackCmdTransaction(trans)
transId=Node.getTransId(trans)
return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)
......@@ -638,6 +727,7 @@ class Node(object):
trans=None
try:
trans=Utils.runCmdArrReturnJson(cmdArr)
self.trackCmdTransaction(trans)
except subprocess.CalledProcessError as ex:
msg=ex.output.decode("utf-8")
Utils.Print("ERROR: Exception during funds transfer. %s" % (msg))
......@@ -819,6 +909,7 @@ class Node(object):
trans=None
try:
trans=Utils.runCmdReturnJson(cmd, trace=False)
self.trackCmdTransaction(trans)
except subprocess.CalledProcessError as ex:
if not shouldFail:
msg=ex.output.decode("utf-8")
......@@ -876,6 +967,7 @@ class Node(object):
if Utils.Debug: Utils.Print("cmd: %s" % (cmdArr))
try:
trans=Utils.runCmdArrReturnJson(cmdArr)
self.trackCmdTransaction(trans, ignoreNonTrans=True)
return (True, trans)
except subprocess.CalledProcessError as ex:
msg=ex.output.decode("utf-8")
......@@ -887,6 +979,7 @@ class Node(object):
cmdDesc="set action permission"
cmd="%s -j %s %s %s %s" % (cmdDesc, account, code, pType, requirement)
trans=self.processCleosCmd(cmd, cmdDesc, silentErrors=False, exitOnError=exitOnError)
self.trackCmdTransaction(trans)
return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)
......@@ -895,11 +988,12 @@ class Node(object):
toAccount=fromAccount
cmdDesc="system delegatebw"
transferStr="--transfer" if transferTo else ""
transferStr="--transfer" if transferTo else ""
cmd="%s -j %s %s \"%s %s\" \"%s %s\" %s" % (
cmdDesc, fromAccount.name, toAccount.name, netQuantity, CORE_SYMBOL, cpuQuantity, CORE_SYMBOL, transferStr)
msg="fromAccount=%s, toAccount=%s" % (fromAccount.name, toAccount.name);
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)
......@@ -909,6 +1003,7 @@ class Node(object):
cmdDesc, producer.name, producer.activePublicKey, url, location)
msg="producer=%s" % (producer.name);
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)
......@@ -918,6 +1013,7 @@ class Node(object):
cmdDesc, account.name, " ".join(producers))
msg="account=%s, producers=[ %s ]" % (account.name, ", ".join(producers));
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)
......@@ -949,7 +1045,7 @@ class Node(object):
return None
if exitOnError and trans is None:
Utils.cmdError("could not \"%s\" - %s" % (cmdDesc,exitMsg))
Utils.cmdError("could not \"%s\". %s" % (cmdDesc,exitMsg))
errorExit("Failed to \"%s\"" % (cmdDesc))
return trans
......@@ -963,12 +1059,12 @@ class Node(object):
cmd="curl %s/v1/test_control/kill_node_on_producer -d '{ \"producer\":\"%s\", \"where_in_sequence\":%d, \"based_on_lib\":\"%s\" }' -X POST -H \"Content-Type: application/json\"" % \
(self.endpointHttp, producer, whereInSequence, basedOnLib)
if Utils.Debug: Utils.Print("cmd: %s" % (cmd))
trans=None
rtn=None
try:
if returnType==ReturnType.json:
trans=Utils.runCmdReturnJson(cmd, silentErrors=silentErrors)
rtn=Utils.runCmdReturnJson(cmd, silentErrors=silentErrors)
elif returnType==ReturnType.raw:
trans=Utils.runCmdReturnStr(cmd)
rtn=Utils.runCmdReturnStr(cmd)
else:
unhandledEnumType(returnType)
except subprocess.CalledProcessError as ex:
......@@ -986,11 +1082,11 @@ class Node(object):
exitMsg=": " + exitMsg
else:
exitMsg=""
if exitOnError and trans is None:
if exitOnError and rtn is None:
Utils.cmdError("could not \"%s\" - %s" % (cmd,exitMsg))
Utils.errorExit("Failed to \"%s\"" % (cmd))
return trans
return rtn
def waitForTransBlockIfNeeded(self, trans, waitForTransBlock, exitOnError=False):
if not waitForTransBlock:
......@@ -1166,7 +1262,7 @@ class Node(object):
cmdArr=[]
myCmd=self.cmd
toAddOrSwap=copy.deepcopy(addOrSwapFlags) if addOrSwapFlags is not None else {}
toAddOrSwap=copy.deepcopy(addOrSwapFlags) if addOrSwapFlags is not None else {}
if not newChain:
skip=False
swapValue=None
......@@ -1227,6 +1323,26 @@ class Node(object):
self.killed=False
return True
def trackCmdTransaction(self, trans, ignoreNonTrans=False):
if trans is None:
if Utils.Debug: Utils.Print(" cmd returned transaction: %s" % (trans))
return
if ignoreNonTrans and not Node.isTrans(trans):
if Utils.Debug: Utils.Print(" cmd returned a non-transaction")
return
transId=Node.getTransId(trans)
if Utils.Debug:
status=Node.getTransStatus(trans)
blockNum=Node.getTransBlockNum(trans)
if transId in self.transCache.keys():
replaceMsg="replacing previous trans=\n%s" % json.dumps(self.transCache[transId], indent=2, sort_keys=True)
else:
replaceMsg=""
Utils.Print(" cmd returned transaction id: %s, status: %s, (possible) block num: %s %s" % (transId, status, blockNum, replaceMsg))
self.transCache[transId]=trans
def reportStatus(self):
Utils.Print("Node State:")
Utils.Print(" cmd : %s" % (self.cmd))
......
......@@ -26,6 +26,7 @@ class AppArgs:
class TestHelper(object):
LOCAL_HOST="localhost"
DEFAULT_PORT=8888
DEFAULT_WALLET_PORT=9899
@staticmethod
# pylint: disable=too-many-branches
......@@ -70,6 +71,12 @@ class TestHelper(object):
if "--port" in includeArgs:
parser.add_argument("-p", "--port", type=int, help="%s host port" % Utils.EosServerName,
default=TestHelper.DEFAULT_PORT)
if "--wallet-host" in includeArgs:
parser.add_argument("--wallet-host", type=str, help="%s host" % Utils.EosWalletName,
default=TestHelper.LOCAL_HOST)
if "--wallet-port" in includeArgs:
parser.add_argument("--wallet-port", type=int, help="%s port" % Utils.EosWalletName,
default=TestHelper.DEFAULT_WALLET_PORT)
if "--prod-count" in includeArgs:
parser.add_argument("-c", "--prod-count", type=int, help="Per node producer count", default=1)
if "--defproducera_prvt_key" in includeArgs:
......
此差异已折叠。
......@@ -257,11 +257,6 @@ def myTest(transWillEnterBlock):
currencyAccount=accounts[0]
currencyAccount.name="currency0000"
Print("Stand up walletd")
if walletMgr.launch() is False:
error("Failed to stand up eos walletd.")
return False
testWalletName="test"
Print("Creating wallet \"%s\"." % (testWalletName))
testWallet=walletMgr.create(testWalletName)
......@@ -328,7 +323,7 @@ def myTest(transWillEnterBlock):
return False
Print("Get details for transaction %s" % (transId))
transaction=node2.getTransaction(trans[1], exitOnError=True)
transaction=node2.getTransaction(transId, exitOnError=True)
signature=transaction["transaction"]["signatures"][0]
blockNum=int(transaction["transaction"]["ref_block_num"])
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -383,7 +383,7 @@ try {
chain.create_account(acc1a);
chain.produce_block();
chainbase::database &db = chain.control->db();
const chainbase::database &db = chain.control->db();
using resource_usage_object = eosio::chain::resource_limits::resource_usage_object;
using by_owner = eosio::chain::resource_limits::by_owner;
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册