Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32daed0840 | |||
| 6d9dff6713 | |||
| f07e688305 | |||
| 44b56b38ca | |||
| c600fbe0b8 | |||
| 07af448870 | |||
| fb21cdecb0 | |||
| b3cc74f621 | |||
| 8d86d7d2d4 | |||
| 59cf021b08 | |||
| 5969e8b6fe | |||
| 8cbd7decca | |||
| c9fcb2ac2c | |||
| b5232f0eaf | |||
| ac1a035b5e | |||
| 2597e02383 | |||
| 191aafc8f6 | |||
| 405ac4178d | |||
| 41bb796d77 | |||
| 1e80205270 | |||
| 483b462717 | |||
| ec471ad8e5 | |||
| 3dbc0baeeb | |||
| f3c424ef90 | |||
| 971102e243 | |||
| 0ed5d6da9e | |||
| 38d3c39e9d |
+2
-2
@@ -14,9 +14,9 @@ set( CMAKE_CXX_EXTENSIONS ON )
|
||||
set( CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(VERSION_MAJOR 4)
|
||||
set(VERSION_MINOR 1)
|
||||
set(VERSION_MINOR 0)
|
||||
set(VERSION_PATCH 0)
|
||||
set(VERSION_SUFFIX dev)
|
||||
set(VERSION_SUFFIX rc2)
|
||||
|
||||
if(VERSION_SUFFIX)
|
||||
set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}")
|
||||
|
||||
@@ -72,7 +72,7 @@ git clone --recursive https://github.com/AntelopeIO/leap.git
|
||||
git clone --recursive git@github.com:AntelopeIO/leap.git
|
||||
```
|
||||
|
||||
> ℹ️ **HTTPS vs. SSH Clone** ℹ️
|
||||
> ℹ️ **HTTPS vs. SSH Clone** ℹ️
|
||||
Both an HTTPS or SSH git clone will yield the same result - a folder named `leap` containing our source code. It doesn't matter which type you use.
|
||||
|
||||
Navigate into that folder:
|
||||
@@ -96,13 +96,13 @@ git submodule update --init --recursive
|
||||
### Step 3 - Build
|
||||
Select build instructions below for a [pinned build](#pinned-build) (preferred) or an [unpinned build](#unpinned-build).
|
||||
|
||||
> ℹ️ **Pinned vs. Unpinned Build** ℹ️
|
||||
> ℹ️ **Pinned vs. Unpinned Build** ℹ️
|
||||
We have two types of builds for Leap: "pinned" and "unpinned." The only difference is that pinned builds use specific versions for some dependencies hand-picked by the Leap engineers - they are "pinned" to those versions. In contrast, unpinned builds use the default dependency versions available on the build system at the time. We recommend performing a "pinned" build to ensure the compiler and boost versions remain the same between builds of different Leap versions. Leap requires these versions to remain the same, otherwise its state might need to be recovered from a portable snapshot or the chain needs to be replayed.
|
||||
|
||||
> ⚠️ **A Warning On Parallel Compilation Jobs (`-j` flag)** ⚠️
|
||||
> ⚠️ **A Warning On Parallel Compilation Jobs (`-j` flag)** ⚠️
|
||||
When building C/C++ software, often the build is performed in parallel via a command such as `make -j "$(nproc)"` which uses all available CPU threads. However, be aware that some compilation units (`*.cpp` files) in Leap will consume nearly 4GB of memory. Failures due to memory exhaustion will typically, but not always, manifest as compiler crashes. Using all available CPU threads may also prevent you from doing other things on your computer during compilation. For these reasons, consider reducing this value.
|
||||
|
||||
> 🐋 **Docker and `sudo`** 🐋
|
||||
> 🐋 **Docker and `sudo`** 🐋
|
||||
If you are in an Ubuntu docker container, omit `sudo` from all commands because you run as `root` by default. Most other docker containers also exclude `sudo`, especially Debian-family containers. If your shell prompt is a hash tag (`#`), omit `sudo`.
|
||||
|
||||
#### Pinned Build
|
||||
@@ -111,14 +111,12 @@ Make sure you are in the root of the `leap` repo, then run the `install_depts.sh
|
||||
sudo scripts/install_deps.sh
|
||||
```
|
||||
|
||||
Next, run the pinned build script. You have to give it three arguments in the following order:
|
||||
1. A temporary folder, for all dependencies that need to be built from source.
|
||||
1. A build folder, where the binaries you need to install will be built to.
|
||||
1. The number of jobs or CPU cores/threads to use (note the [jobs flag](#step-3---build) warning above).
|
||||
Next, run the pinned build script. You have to give it three arguments, in the following order:
|
||||
- A temporary folder, for all dependencies that need to be built from source.
|
||||
- A build folder, where the binaries you need to install will be built to.
|
||||
- The number of jobs or CPU cores/threads to use (note the [jobs flag](#step-3---build) warning above).
|
||||
|
||||
> 🔒 You do not need to run this script with `sudo` or as root.
|
||||
|
||||
For example, the following command runs the `pinned_build.sh` script, specifies a `deps` and `build` folder in the root of the Leap repo for the first two arguments, then builds the packages using all of your computer's CPU threads:
|
||||
The following command runs the `pinned_build.sh` script, specifies a `deps` and `build` folder in the root of the Leap repo for the first two arguments, then builds the packages using all of your computer's CPU threads (Note: you don't need `sudo` for this command):
|
||||
```bash
|
||||
scripts/pinned_build.sh deps build "$(nproc)"
|
||||
```
|
||||
|
||||
@@ -1533,7 +1533,7 @@ namespace eosio { namespace chain {
|
||||
ilog("blocks.log and blocks.index agree on number of blocks");
|
||||
|
||||
if (interval == 0) {
|
||||
interval = std::max((log_bundle.log_index.num_blocks() + 7u) >> 3, 1u);
|
||||
interval = std::max((log_bundle.log_index.num_blocks() + 7) >> 3, 1);
|
||||
}
|
||||
uint32_t expected_block_num = log_bundle.log_data.first_block_num();
|
||||
|
||||
|
||||
@@ -2680,7 +2680,7 @@ struct controller_impl {
|
||||
// only called from non-main threads (read-only trx execution threads)
|
||||
// when producer_plugin starts them
|
||||
void init_thread_local_data() {
|
||||
EOS_ASSERT( !is_main_thread(), misc_exception, "init_thread_local_data called on the main thread");
|
||||
EOS_ASSERT( !is_on_main_thread(), misc_exception, "init_thread_local_data called on the main thread");
|
||||
#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
|
||||
if ( is_eos_vm_oc_enabled() )
|
||||
// EOSVMOC needs further initialization of its thread local data
|
||||
@@ -2691,10 +2691,10 @@ struct controller_impl {
|
||||
wasmif_thread_local = std::make_unique<wasm_interface>( conf.wasm_runtime, conf.eosvmoc_tierup, db, conf.state_dir, conf.eosvmoc_config, !conf.profile_accounts.empty());
|
||||
}
|
||||
|
||||
bool is_main_thread() { return main_thread_id == std::this_thread::get_id(); };
|
||||
bool is_on_main_thread() { return main_thread_id == std::this_thread::get_id(); };
|
||||
|
||||
wasm_interface& get_wasm_interface() {
|
||||
if ( is_main_thread()
|
||||
if ( is_on_main_thread()
|
||||
#ifdef EOSIO_EOS_VM_OC_RUNTIME_ENABLED
|
||||
|| is_eos_vm_oc_enabled()
|
||||
#endif
|
||||
@@ -3686,6 +3686,10 @@ void controller::init_thread_local_data() {
|
||||
my->init_thread_local_data();
|
||||
}
|
||||
|
||||
bool controller::is_on_main_thread() const {
|
||||
return my->is_on_main_thread();
|
||||
}
|
||||
|
||||
/// Protocol feature activation handlers:
|
||||
|
||||
template<>
|
||||
|
||||
@@ -373,6 +373,7 @@ namespace eosio { namespace chain {
|
||||
void set_db_read_only_mode();
|
||||
void unset_db_read_only_mode();
|
||||
void init_thread_local_data();
|
||||
bool is_on_main_thread() const;
|
||||
|
||||
private:
|
||||
friend class apply_context;
|
||||
|
||||
@@ -32,7 +32,7 @@ class log_index {
|
||||
bool is_open() const { return file_.is_open(); }
|
||||
|
||||
uint64_t back() { return nth_block_position(num_blocks()-1); }
|
||||
unsigned num_blocks() const { return num_blocks_; }
|
||||
int num_blocks() const { return num_blocks_; }
|
||||
uint64_t nth_block_position(uint32_t n) {
|
||||
file_.seek(n*sizeof(uint64_t));
|
||||
uint64_t r;
|
||||
|
||||
@@ -12,11 +12,10 @@ namespace IR
|
||||
struct NoImm {};
|
||||
struct MemoryImm {};
|
||||
|
||||
PACKED_STRUCT(
|
||||
struct ControlStructureImm
|
||||
{
|
||||
ResultType resultType{};
|
||||
});
|
||||
};
|
||||
|
||||
struct BranchImm
|
||||
{
|
||||
@@ -676,19 +675,4 @@ namespace IR
|
||||
};
|
||||
|
||||
IR_API const char* getOpcodeName(Opcode opcode);
|
||||
}
|
||||
|
||||
//paranoia for future platforms
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::NoImm>) == 2);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::MemoryImm>) == 2);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::ControlStructureImm>) == 3);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::BranchImm>) == 6);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::BranchTableImm>) == 18);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::LiteralImm<I32>>) == 6);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::LiteralImm<I64>>) == 10);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::LiteralImm<F32>>) == 6);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::LiteralImm<F64>>) == 10);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::GetOrSetVariableImm<false>>) == 6);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::CallImm>) == 6);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::CallIndirectImm>) == 6);
|
||||
static_assert(sizeof(IR::OpcodeAndImm<IR::LoadOrStoreImm<0>>) == 10);
|
||||
}
|
||||
@@ -2374,6 +2374,7 @@ read_only::get_raw_abi_results read_only::get_raw_abi( const get_raw_abi_params&
|
||||
}
|
||||
|
||||
read_only::get_account_results read_only::get_account( const get_account_params& params, const fc::time_point& deadline )const {
|
||||
try {
|
||||
get_account_results result;
|
||||
result.account_name = params.account_name;
|
||||
|
||||
@@ -2541,6 +2542,7 @@ read_only::get_account_results read_only::get_account( const get_account_params&
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} EOS_RETHROW_EXCEPTIONS(chain::account_query_exception, "unable to retrieve account info")
|
||||
}
|
||||
|
||||
read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params, const fc::time_point& deadline )const {
|
||||
|
||||
@@ -403,13 +403,13 @@ namespace eosio {
|
||||
fc_elog( logger(), "Unable to parse arguments to ${api}.${call}", ("api", api_name)( "call", call_name ) );
|
||||
fc_dlog( logger(), "Bad arguments: ${args}", ("args", body) );
|
||||
} catch (fc::exception& e) {
|
||||
error_results results{500, "Internal Service Error", error_results::error_info(e, verbose_http_errors)};
|
||||
cb( 500, fc::time_point::maximum(), fc::variant( results ));
|
||||
error_results results{400, "Exception", error_results::error_info(e, verbose_http_errors)};
|
||||
cb( 400, fc::time_point::maximum(), fc::variant( results ));
|
||||
fc_dlog( logger(), "Exception while processing ${api}.${call}: ${e}",
|
||||
("api", api_name)( "call", call_name )("e", e.to_detail_string()) );
|
||||
} catch (std::exception& e) {
|
||||
error_results results{500, "Internal Service Error", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, e.what())), verbose_http_errors)};
|
||||
cb( 500, fc::time_point::maximum(), fc::variant( results ));
|
||||
error_results results{400, "Exception", error_results::error_info(fc::exception( FC_LOG_MESSAGE( error, e.what())), verbose_http_errors)};
|
||||
cb( 400, fc::time_point::maximum(), fc::variant( results ));
|
||||
fc_dlog( logger(), "STD Exception encountered while processing ${api}.${call}: ${e}",
|
||||
("api", api_name)("call", call_name)("e", e.what()) );
|
||||
} catch (...) {
|
||||
|
||||
@@ -256,39 +256,53 @@ struct block_time_tracker {
|
||||
block_idle_time += idle;
|
||||
}
|
||||
|
||||
void add_fail_time( const fc::microseconds& fail_time ) {
|
||||
trx_fail_time += fail_time;
|
||||
++trx_fail_num;
|
||||
void add_fail_time( const fc::microseconds& fail_time, bool is_transient ) {
|
||||
if( is_transient ) {
|
||||
// transient time includes both success and fail time
|
||||
transient_trx_time += fail_time;
|
||||
++transient_trx_num;
|
||||
} else {
|
||||
trx_fail_time += fail_time;
|
||||
++trx_fail_num;
|
||||
}
|
||||
}
|
||||
|
||||
void add_success_time( const fc::microseconds& time ) {
|
||||
trx_success_time += time;
|
||||
++trx_success_num;
|
||||
void add_success_time( const fc::microseconds& time, bool is_transient ) {
|
||||
if( is_transient ) {
|
||||
transient_trx_time += time;
|
||||
++transient_trx_num;
|
||||
} else {
|
||||
trx_success_time += time;
|
||||
++trx_success_num;
|
||||
}
|
||||
}
|
||||
|
||||
void report( const fc::time_point& idle_trx_time, uint32_t block_num ) {
|
||||
if( _log.is_enabled( fc::log_level::debug ) ) {
|
||||
auto now = fc::time_point::now();
|
||||
add_idle_time( now - idle_trx_time );
|
||||
fc_dlog( _log, "Block #${n} trx idle: ${i}us out of ${t}us, success: ${sn}, ${s}us, fail: ${fn}, ${f}us, other: ${o}us",
|
||||
fc_dlog( _log, "Block #${n} trx idle: ${i}us out of ${t}us, success: ${sn}, ${s}us, fail: ${fn}, ${f}us, transient: ${tn}, ${t}us, other: ${o}us",
|
||||
("n", block_num)
|
||||
("i", block_idle_time)("t", now - clear_time)("sn", trx_success_num)("s", trx_success_time)
|
||||
("fn", trx_fail_num)("f", trx_fail_time)
|
||||
("o", (now - clear_time) - block_idle_time - trx_success_time - trx_fail_time) );
|
||||
("tn", transient_trx_num)("t", transient_trx_time)
|
||||
("o", (now - clear_time) - block_idle_time - trx_success_time - trx_fail_time - transient_trx_time) );
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
block_idle_time = trx_fail_time = trx_success_time = fc::microseconds{};
|
||||
trx_fail_num = trx_success_num = 0;
|
||||
block_idle_time = trx_fail_time = trx_success_time = transient_trx_time = fc::microseconds{};
|
||||
trx_fail_num = trx_success_num = transient_trx_num = 0;
|
||||
clear_time = fc::time_point::now();
|
||||
}
|
||||
|
||||
fc::microseconds block_idle_time;
|
||||
uint32_t trx_success_num = 0;
|
||||
uint32_t trx_fail_num = 0;
|
||||
uint32_t transient_trx_num = 0;
|
||||
fc::microseconds trx_success_time;
|
||||
fc::microseconds trx_fail_time;
|
||||
fc::microseconds transient_trx_time;
|
||||
fc::time_point clear_time{fc::time_point::now()};
|
||||
};
|
||||
|
||||
@@ -429,11 +443,13 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin
|
||||
fc::microseconds _ro_read_window_time_us{ 60000 };
|
||||
static constexpr fc::microseconds _ro_read_window_minimum_time_us{ 10000 };
|
||||
fc::microseconds _ro_read_window_effective_time_us{ 0 }; // calculated during option initialization
|
||||
std::atomic<int64_t> _ro_all_threads_exec_time_us; // total time spent by all threads executing transactions. use atomic for simplicity and performance
|
||||
fc::time_point _ro_read_window_start_time;
|
||||
boost::asio::deadline_timer _ro_write_window_timer;
|
||||
boost::asio::deadline_timer _ro_read_window_timer;
|
||||
fc::microseconds _ro_max_trx_time_us{ 0 }; // calculated during option initialization
|
||||
ro_trx_queue_t _ro_trx_queue;
|
||||
std::atomic<uint32_t> _ro_num_active_trx_exec_tasks{ 0 };
|
||||
std::atomic<uint32_t> _ro_num_active_trx_exec_tasks{ 0 };
|
||||
std::vector<std::future<bool>> _ro_trx_exec_tasks_fut;
|
||||
|
||||
void start_write_window();
|
||||
@@ -688,7 +704,8 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin
|
||||
self->log_trx_results( trx, nullptr, ex, 0, start, is_transient );
|
||||
next( std::move(ex) );
|
||||
self->_idle_trx_time = fc::time_point::now();
|
||||
self->_time_tracker.add_fail_time(self->_idle_trx_time - start);
|
||||
auto dur = self->_idle_trx_time - start;
|
||||
self->_time_tracker.add_fail_time(dur, is_transient);
|
||||
};
|
||||
try {
|
||||
auto result = future.get();
|
||||
@@ -2214,7 +2231,7 @@ producer_plugin_impl::push_transaction( const fc::time_point& block_deadline,
|
||||
log_trx_results( trx, except_ptr );
|
||||
next( except_ptr );
|
||||
}
|
||||
_time_tracker.add_fail_time(fc::time_point::now() - start);
|
||||
_time_tracker.add_fail_time(fc::time_point::now() - start, trx->is_transient());
|
||||
return push_result{.failed = true};
|
||||
}
|
||||
|
||||
@@ -2261,8 +2278,10 @@ producer_plugin_impl::handle_push_result( const transaction_metadata_ptr& trx,
|
||||
auto end = fc::time_point::now();
|
||||
push_result pr;
|
||||
if( trace->except ) {
|
||||
if ( !trx->is_read_only() )
|
||||
_time_tracker.add_fail_time(end - start);
|
||||
if ( chain.is_on_main_thread() ) {
|
||||
auto dur = end - start;
|
||||
_time_tracker.add_fail_time(dur, trx->is_transient());
|
||||
}
|
||||
if( exception_is_exhausted( *trace->except ) ) {
|
||||
if( _pending_block_mode == pending_block_mode::producing ) {
|
||||
fc_dlog(_trx_failed_trace_log, "[TRX_TRACE] Block ${block_num} for producer ${prod} COULD NOT FIT, tx: ${txid} RETRYING ",
|
||||
@@ -2302,8 +2321,10 @@ producer_plugin_impl::handle_push_result( const transaction_metadata_ptr& trx,
|
||||
} else {
|
||||
fc_tlog( _log, "Subjective bill for success ${a}: ${b} elapsed ${t}us, time ${r}us",
|
||||
("a",first_auth)("b",sub_bill)("t",trace->elapsed)("r", end - start));
|
||||
if ( !trx->is_read_only() )
|
||||
_time_tracker.add_success_time(end - start);
|
||||
if ( chain.is_on_main_thread() ) {
|
||||
auto dur = end - start;
|
||||
_time_tracker.add_success_time(dur, trx->is_transient());
|
||||
}
|
||||
log_trx_results( trx, trace, start );
|
||||
// if producing then trx is in objective cpu account billing
|
||||
if (!disable_subjective_enforcement && _pending_block_mode != pending_block_mode::producing) {
|
||||
@@ -2446,7 +2467,7 @@ void producer_plugin_impl::process_scheduled_and_incoming_trxs( const fc::time_p
|
||||
auto trace = chain.push_scheduled_transaction(trx_id, deadline, max_trx_time, 0, false);
|
||||
auto end = fc::time_point::now();
|
||||
if (trace->except) {
|
||||
_time_tracker.add_fail_time(end - start);
|
||||
_time_tracker.add_fail_time(end - start, false); // delayed transaction cannot be transient
|
||||
if (exception_is_exhausted(*trace->except)) {
|
||||
if( block_is_exhausted() ) {
|
||||
exhausted = true;
|
||||
@@ -2466,7 +2487,7 @@ void producer_plugin_impl::process_scheduled_and_incoming_trxs( const fc::time_p
|
||||
num_failed++;
|
||||
}
|
||||
} else {
|
||||
_time_tracker.add_success_time(end - start);
|
||||
_time_tracker.add_success_time(end - start, false); // delayed transaction cannot be transient
|
||||
fc_dlog(_trx_successful_trace_log,
|
||||
"[TRX_TRACE] Block ${block_num} for producer ${prod} is ACCEPTING scheduled tx: ${txid}, time: ${r}, auth: ${a}, cpu: ${cpu}",
|
||||
("block_num", chain.head_block_num() + 1)("prod", get_pending_block_producer())
|
||||
@@ -2766,6 +2787,14 @@ void producer_plugin::log_failed_transaction(const transaction_id_type& trx_id,
|
||||
|
||||
// Called from app thread
|
||||
void producer_plugin_impl::switch_to_write_window() {
|
||||
if ( _log.is_enabled( fc::log_level::debug ) ) {
|
||||
auto now = fc::time_point::now();
|
||||
fc_dlog( _log, "Read-only threads ${n}, read window ${r}us, total all threads ${t}us",
|
||||
("n", _ro_thread_pool_size)
|
||||
("r", now - _ro_read_window_start_time)
|
||||
("t", _ro_all_threads_exec_time_us.load()));
|
||||
}
|
||||
|
||||
// this method can be called from multiple places. it is possible
|
||||
// we are already in write window.
|
||||
if ( app().executor().is_write_window() ) {
|
||||
@@ -2819,6 +2848,8 @@ void producer_plugin_impl::switch_to_read_window() {
|
||||
app().executor().set_to_read_window();
|
||||
chain_plug->chain().set_db_read_only_mode();
|
||||
_received_block = false;
|
||||
_ro_read_window_start_time = fc::time_point::now();
|
||||
_ro_all_threads_exec_time_us = 0;
|
||||
|
||||
// start a read-only transaction execution task in each thread in the thread pool
|
||||
_ro_num_active_trx_exec_tasks = _ro_thread_pool_size;
|
||||
@@ -2933,7 +2964,12 @@ bool producer_plugin_impl::push_read_only_transaction(
|
||||
auto remaining_time_in_read_window_us = _ro_read_window_time_us - time_used_in_read_window_us;
|
||||
// Ensure the trx to finish by the end of read-window.
|
||||
auto window_deadline = std::min( start + remaining_time_in_read_window_us, block_deadline );
|
||||
|
||||
auto trace = chain.push_transaction( trx, window_deadline, _ro_max_trx_time_us, 0, false, 0 );
|
||||
if ( _log.is_enabled( fc::log_level::debug ) ) {
|
||||
auto dur = fc::time_point::now() - start;
|
||||
_ro_all_threads_exec_time_us += dur.count();
|
||||
}
|
||||
auto pr = handle_push_result(trx, next, start, chain, trace, true /*return_failure_trace*/, true /*disable_subjective_enforcement*/, {} /*first_auth*/, 0 /*sub_bill*/, 0 /*prev_billed_cpu_time_us*/);
|
||||
// If a transaction was exhausted, that indicates we are close to
|
||||
// the end of read window. Retry in next round.
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
void pop_entry(bool call_send = true) {
|
||||
send_queue.erase(send_queue.begin());
|
||||
sending = false;
|
||||
if (call_send)
|
||||
if (call_send || !send_queue.empty())
|
||||
send();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,11 @@ from .Node import BlockType
|
||||
from .Node import Node
|
||||
from .WalletMgr import WalletMgr
|
||||
from .launch_transaction_generators import TransactionGeneratorsLauncher, TpsTrxGensConfig
|
||||
from .libc import unshare, CLONE_NEWNET
|
||||
from .interfaces import getInterfaceFlags, setInterfaceUp, IFF_LOOPBACK
|
||||
try:
|
||||
from .libc import unshare, CLONE_NEWNET
|
||||
from .interfaces import getInterfaceFlags, setInterfaceUp, IFF_LOOPBACK
|
||||
except:
|
||||
pass
|
||||
|
||||
# Protocol Feature Setup Policy
|
||||
class PFSetupPolicy:
|
||||
|
||||
@@ -61,7 +61,7 @@ class Node(Transactions):
|
||||
self.fetchBlock = lambda blockNum: self.processUrllibRequest("trace_api", "get_block", {"block_num":blockNum}, silentErrors=False, exitOnError=True)
|
||||
self.fetchKeyCommand = lambda: "[transaction][transaction_header][ref_block_num]"
|
||||
self.fetchRefBlock = lambda trans: trans["transaction_header"]["ref_block_num"]
|
||||
self.cleosLimit = "--time-limit 99999"
|
||||
self.cleosLimit = "--time-limit 999"
|
||||
self.fetchHeadBlock = lambda node, headBlock: node.processUrllibRequest("chain", "get_block_info", {"block_num":headBlock}, silentErrors=False, exitOnError=True)
|
||||
|
||||
def __str__(self):
|
||||
|
||||
+1
-1
@@ -352,7 +352,7 @@ def abi_file_with_nodeos_test():
|
||||
os.makedirs(data_dir, exist_ok=True)
|
||||
walletMgr = WalletMgr(True)
|
||||
walletMgr.launch()
|
||||
node = Node('localhost', 8888, nodeId, cmd="./programs/nodeos/nodeos -e -p eosio --plugin eosio::trace_api_plugin --trace-no-abis --plugin eosio::producer_plugin --plugin eosio::producer_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::chain_plugin --plugin eosio::http_plugin --access-control-allow-origin=* --http-validate-host=false --resource-monitor-not-shutdown-on-threshold-exceeded " + "--data-dir " + data_dir + " --config-dir " + data_dir, walletMgr=walletMgr)
|
||||
node = Node('localhost', 8888, nodeId, cmd="./programs/nodeos/nodeos -e -p eosio --plugin eosio::trace_api_plugin --trace-no-abis --plugin eosio::producer_plugin --plugin eosio::producer_api_plugin --plugin eosio::chain_api_plugin --plugin eosio::chain_plugin --plugin eosio::http_plugin --access-control-allow-origin=* --http-validate-host=false --max-transaction-time=-1 --resource-monitor-not-shutdown-on-threshold-exceeded " + "--data-dir " + data_dir + " --config-dir " + data_dir, walletMgr=walletMgr)
|
||||
node.verifyAlive() # Setting node state to not alive
|
||||
node.relaunch(newChain=True, cachePopen=True)
|
||||
node.waitForBlock(1)
|
||||
|
||||
@@ -56,7 +56,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
"http_plugin", "db_size_api_plugin", "prometheus_plugin"]
|
||||
nodeos_plugins = "--plugin eosio::" + " --plugin eosio::".join(plugin_names)
|
||||
nodeos_flags = (" --data-dir=%s --config-dir=%s --trace-dir=%s --trace-no-abis --access-control-allow-origin=%s "
|
||||
"--contracts-console --http-validate-host=%s --verbose-http-errors --abi-serializer-max-time-ms 30000 --http-max-response-time-ms 30000 "
|
||||
"--contracts-console --http-validate-host=%s --verbose-http-errors --max-transaction-time -1 --abi-serializer-max-time-ms 30000 --http-max-response-time-ms 30000 "
|
||||
"--p2p-peer-address localhost:9011 --resource-monitor-not-shutdown-on-threshold-exceeded ") % (self.data_dir, self.config_dir, self.data_dir, "\'*\'", "false")
|
||||
start_nodeos_cmd = ("%s -e -p eosio %s %s ") % (Utils.EosServerPath, nodeos_plugins, nodeos_flags)
|
||||
self.nodeos.launchCmd(start_nodeos_cmd, self.node_id)
|
||||
@@ -337,7 +337,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_account with valid parameter
|
||||
payload = {"account_name":"default"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_code with empty parameter
|
||||
command = "get_code"
|
||||
@@ -355,7 +355,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_code with valid parameter
|
||||
payload = {"account_name":"default"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_code_hash with empty parameter
|
||||
command = "get_code_hash"
|
||||
@@ -373,7 +373,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_code_hash with valid parameter
|
||||
payload = {"account_name":"default"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_abi with empty parameter
|
||||
command = "get_abi"
|
||||
@@ -391,7 +391,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_abi with valid parameter
|
||||
payload = {"account_name":"default"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_raw_code_and_abi with empty parameter
|
||||
command = "get_raw_code_and_abi"
|
||||
@@ -409,7 +409,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_raw_code_and_abi with valid parameter
|
||||
payload = {"account_name":"default"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_raw_abi with empty parameter
|
||||
command = "get_raw_abi"
|
||||
@@ -427,7 +427,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_raw_abi with valid parameter
|
||||
payload = {"account_name":"default"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_table_rows with empty parameter
|
||||
command = "get_table_rows"
|
||||
@@ -452,7 +452,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
"lower_bound":"0x0000000000000000D0F2A472A8EB6A57",
|
||||
"upper_bound":"0xFFFFFFFFFFFFFFFFD0F2A472A8EB6A57"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_table_by_scope with empty parameter
|
||||
command = "get_table_by_scope"
|
||||
@@ -474,7 +474,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
"lower_bound":"0x0000000000000000D0F2A472A8EB6A57",
|
||||
"upper_bound":"0xFFFFFFFFFFFFFFFFD0F2A472A8EB6A57"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_currency_balance with empty parameter
|
||||
command = "get_currency_balance"
|
||||
@@ -492,7 +492,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_currency_balance with valid parameter
|
||||
payload = {"code":"eosio.token", "account":"unknown"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_currency_stats with empty parameter
|
||||
command = "get_currency_stats"
|
||||
@@ -510,7 +510,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# get_currency_stats with valid parameter
|
||||
payload = {"code":"eosio.token","symbol":"SYS"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_producers with empty parameter
|
||||
command = "get_producers"
|
||||
@@ -585,7 +585,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
"EOS7d9A3uLe6As66jzN8j44TXJUqJSK3bFjjEEqR4oTvNAB3iM9SA",
|
||||
"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"]}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_transaction_id with empty parameter
|
||||
command = "get_transaction_id"
|
||||
@@ -652,7 +652,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
"packed_context_free_data": "context_free_data",
|
||||
"packed_trx": "packed_trx"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# push_transactions with empty parameter
|
||||
command = "push_transactions"
|
||||
@@ -694,7 +694,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
"packed_context_free_data": "context_free_data",
|
||||
"packed_trx": "packed_trx"}
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
|
||||
# test all net api
|
||||
@@ -1091,7 +1091,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
["EOS696giL6VxeJhtEgKtWPK8aQeT8YXNjw2a7vE5wHunffhfa5QSQ"],
|
||||
"cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f"]
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
self.assertEqual(ret_json["error"]["code"], 3120004)
|
||||
|
||||
# create with empty parameter
|
||||
@@ -1105,7 +1105,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
self.assertEqual(ret_json["error"]["code"], 3200006)
|
||||
# create with invalid parameter
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, self.http_post_invalid_param, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
self.assertEqual(ret_json["error"]["code"], 3120000)
|
||||
# create with valid parameter
|
||||
payload = "test1"
|
||||
@@ -1123,12 +1123,12 @@ class PluginHttpTest(unittest.TestCase):
|
||||
self.assertEqual(ret_json["error"]["code"], 3200006)
|
||||
# create with invalid parameter
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, self.http_post_invalid_param, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
self.assertEqual(ret_json["error"]["code"], 3120000)
|
||||
# create with valid parameter
|
||||
payload = "fakeacct"
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# lock_all with empty parameter
|
||||
command = "lock_all"
|
||||
@@ -1153,7 +1153,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
self.assertEqual(ret_json["error"]["code"], 3200006)
|
||||
# lock with invalid parameter
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, self.http_post_invalid_param, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
self.assertEqual(ret_json["error"]["code"], 3120002)
|
||||
# lock with valid parameter
|
||||
payload = {"name":"auser"}
|
||||
@@ -1176,7 +1176,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# unlock with valid parameter
|
||||
payload = ["auser", "nopassword"]
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# import_key with empty parameter
|
||||
command = "import_key"
|
||||
@@ -1194,7 +1194,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# import_key with valid parameter
|
||||
payload = ["auser", "nokey"]
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# remove_key with empty parameter
|
||||
command = "remove_key"
|
||||
@@ -1212,7 +1212,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# remove_key with valid parameter
|
||||
payload = ["auser", "none", "none"]
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# create_key with empty parameter
|
||||
command = "create_key"
|
||||
@@ -1230,7 +1230,7 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# create_key with valid parameter
|
||||
payload = ["auser", "none"]
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# list_wallets with empty parameter
|
||||
command = "list_wallets"
|
||||
@@ -1260,15 +1260,15 @@ class PluginHttpTest(unittest.TestCase):
|
||||
# list_keys with valid parameter
|
||||
payload = ["auser", "unknownkey"]
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, payload, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
# get_public_keys with empty parameter
|
||||
command = "get_public_keys"
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
# get_public_keys with empty content parameter
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, self.empty_content_dict, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 500)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
# list_wallets with invalid parameter
|
||||
ret_json = self.nodeos.processUrllibRequest(resource, command, self.http_post_invalid_param, endpoint=endpoint)
|
||||
self.assertEqual(ret_json["code"], 400)
|
||||
|
||||
@@ -259,7 +259,7 @@ try:
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_raw_code_and_abi", "account_name", expectedValue=testAccountName, payload = {"account_name":testAccountName})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_raw_abi", "account_name", expectedValue=testAccountName, payload = {"account_name":testAccountName})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_producers", "rows", payload = {"json":"true","lower_bound":""})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_table_rows", code=500, payload = {"json":"true","table":"noauth"})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_table_rows", code=400, payload = {"json":"true","table":"noauth"})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_table_by_scope", fieldIn="rows", payload = {"json":"true","table":"noauth"})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_currency_balance", code=200, payload = {"code":"eosio.token", "account":testAccountName})
|
||||
runReadOnlyTrxAndRpcInParallel("chain", "get_currency_stats", fieldIn="SYS", payload = {"code":"eosio.token", "symbol":"SYS"})
|
||||
|
||||
Reference in New Issue
Block a user