Compare commits

...

81 Commits

Author SHA1 Message Date
Clayton Calabrese 4ccaca399f Merge branch 'fix_missing_node_py_changes' of https://github.com/AntelopeIO/leap into fix_missing_node_py_changes 2023-03-22 18:14:16 -05:00
Clayton Calabrese 09390a4725 return lost changes to Node.py functions 2023-03-22 18:13:24 -05:00
Matt Witherspoon 7c94e3a102 add PACKED_STRUCT on ControlStructureImm to silence warning 2023-03-22 18:12:54 -05:00
Matt Witherspoon f469d2b78a add static_assert()s on required size of IR::OpcodeAndImm<>s 2023-03-22 18:12:54 -05:00
Matt Witherspoon a9c5cd9f95 fix comparison of different signedness warning in log_index 2023-03-22 18:12:54 -05:00
Lin Huang 41f5a148bb correct version after merging from 4.0.0-rc1 2023-03-22 18:12:54 -05:00
Zach Butler 1f0f5280d5 Restore markdown formatting erroneously deleted in commit 06c9e25327 2023-03-22 18:12:54 -05:00
Zach Butler 6b54dac75f Cardinal objects should be in a numbered list 2023-03-22 18:12:54 -05:00
Zach Butler df4a974b8a Pull note about sudo into its own quote block 2023-03-22 18:12:54 -05:00
Zach Butler c9596cd699 Minor pinned build script README changes 2023-03-22 18:12:54 -05:00
Clayton Calabrese 6c8441bc6c return lost changes to Node.py functions 2023-03-22 17:15:59 -05:00
Matt Witherspoon 1985e28a63 Merge pull request #866 from AntelopeIO/ignored_pack_warn_fix
fix noisy `ignoring packed attribute` warning on `IR::ControlStructureImm`
2023-03-22 11:06:46 -07:00
Vlad 2829420ecb Merge pull request #856 from AntelopeIO/increase-snapshot-test-robustness
[4.0] Increase robustness of snapshot diff python test
2023-03-22 11:51:46 -04:00
Matt Witherspoon 95c22b6e70 add PACKED_STRUCT on ControlStructureImm to silence warning 2023-03-22 10:57:40 -04:00
Matt Witherspoon f8ca18d5f5 add static_assert()s on required size of IR::OpcodeAndImm<>s 2023-03-22 10:55:29 -04:00
Matt Witherspoon bef672aae2 Merge pull request #860 from AntelopeIO/log_index_un_signed_warn
fix comparison of different signedness warning in log_index
2023-03-22 07:30:28 -07:00
Kevin Heifner 87c7480656 Merge pull request #852 from AntelopeIO/GH-850-test-fix
[4.0] Test Fix: Pass a large time limit to get table call
2023-03-22 09:25:02 -05:00
Matt Witherspoon c2366d392b fix comparison of different signedness warning in log_index 2023-03-21 20:17:49 -04:00
766C6164 cb64c3fb38 schedule snapshot at exact block num of another one 2023-03-21 15:43:31 -04:00
Lin Huang c7d0f6c1c2 Merge pull request #855 from AntelopeIO/merge_4_0_0_rc_1
[4.0 -> main] Merge 4.0.0-rc1 version bump to main
2023-03-21 15:31:31 -04:00
Lin Huang 3beffd5765 correct version after merging from 4.0.0-rc1 2023-03-21 14:46:34 -04:00
Lin Huang 1e3f12dc60 Merge remote-tracking branch 'origin/release/4.0' into merge_4_0_0_rc_1 2023-03-21 14:43:12 -04:00
Lin Huang 61cb264885 Merge pull request #851 from AntelopeIO/create_release_4_0_rc_1
Create v4.0.0-rc1 on release/4.0 branch
2023-03-21 14:34:46 -04:00
Kevin Heifner 446a04a607 GH-850 Pass a large time limit so python does not have to handle more=true case. 2023-03-21 13:09:26 -05:00
Zach f3aab2cfa5 Merge pull request #849 from AntelopeIO/zach-readme
Fix README.md Formatting
2023-03-21 14:08:04 -04:00
Lin Huang 28ac7906dc Create v4.0.0-rc1 on release/4.0 branch 2023-03-21 14:03:42 -04:00
Lin Huang 5d4a7ee60e Merge pull request #848 from AntelopeIO/bump_to_4_1
Bump Leap Main branch version to 4.1.0-dev
2023-03-21 13:35:49 -04:00
Zach Butler 8fc769efd1 Restore markdown formatting erroneously deleted in commit 06c9e25327 2023-03-21 13:19:33 -04:00
Zach Butler 7f27916d3d Cardinal objects should be in a numbered list 2023-03-21 13:19:19 -04:00
Zach Butler df3685516e Pull note about sudo into its own quote block 2023-03-21 13:17:58 -04:00
Zach Butler 866dfae99c Minor pinned build script README changes 2023-03-21 13:12:34 -04:00
Lin Huang 4ef610fa33 Bump Leap Main branch version to 4.1.0-dev 2023-03-21 13:00:08 -04:00
Zach 17ca88c8ad Merge pull request #847 from AntelopeIO/zach-libcurl4-openssl-dev
Restore libcurl4-openssl-dev
2023-03-20 22:26:45 -04:00
Zach Butler 60e757d677 export TZ 2023-03-20 18:36:55 -04:00
Zach Butler cc6c3255a7 SC2034 - warning: DEBIAN_FRONTEND appears unused. Verify use (or export if used externally). 2023-03-20 18:01:01 -04:00
Zach Butler 958f6d53b6 tzdata does not need to be separate 2023-03-20 18:00:26 -04:00
Zach Butler e0dac2c6ed Restore libcurl4-openssl-dev 2023-03-20 17:51:58 -04:00
Zach Butler 5027a17a3b Sort packages, each one on its own line 2023-03-20 17:48:57 -04:00
Zach Butler 9398564118 Quote strings 2023-03-20 17:48:49 -04:00
Zach Butler d42262bfeb "apt-get install -y" 2023-03-20 17:48:31 -04:00
Zach Butler 3ba58b20b7 Whitespace 2023-03-20 17:48:23 -04:00
Zach 35b56406cc Merge pull request #835 from AntelopeIO/zach-ascii-art
Change ASCII Art Banner in Build Script
2023-03-20 13:41:26 -04:00
Zach 069245d4f3 Merge pull request #812 from AntelopeIO/zach-lint
Pinned Build Script Linter Changes
2023-03-20 13:39:33 -04:00
Zach 0f84d4e534 Merge pull request #833 from AntelopeIO/zach-revert-799
Fix Pinned Build on Ubuntu 22.04
2023-03-20 10:01:05 -04:00
Lin Huang ace9c40d56 Merge pull request #845 from AntelopeIO/fix_pr_192_bad_merge
Fix test coverage regression by a bad merge conflict in PR #192
2023-03-17 19:31:54 -04:00
Lin Huang 3c53734d2f add missing 2023-03-17 18:59:30 -04:00
Lin Huang 255617660d Fix test coverage regression by a bad merge conflict in PR #192 2023-03-17 18:29:20 -04:00
Vlad e3807c2b5f Merge pull request #842 from AntelopeIO/snapshot-diff-test-fix
snapshot-diff-test fix
2023-03-17 14:35:44 -04:00
766C6164 5324a5da79 sync scheduled snapshot with 2 others 2023-03-17 13:56:06 -04:00
ClaytonCalabrese 264737b4ef Merge pull request #791 from AntelopeIO/performance_harness_distributed_producer_ports
[PH] Distribute Transaction Generators Across Producer Nodes.
2023-03-17 12:28:19 -05:00
766C6164 b4fe3c654f test fix 2023-03-17 12:49:47 -04:00
Clayton Calabrese be75e8aa3a merge from main 2023-03-17 11:26:55 -05:00
Zach Butler 383fb714d4 Appreciate our users and make them feel like they are part of a community 2023-03-17 02:09:45 -04:00
Zach Butler 01b4454090 Cooler Leap ASCII art banner at end of pinned build script 2023-03-17 02:09:38 -04:00
Zach Butler 08aca00905 Revert "Merge pull request #799 from AntelopeIO/sbailey/autofind_llvm_7-11"
Co-authored-by: Matt Witherspoon <32485495+spoonincode@users.noreply.github.com>
2023-03-17 00:53:32 -04:00
Zach Butler 03b1ebd46f Fix shebang in bash build scripts
Looking for BASH in the environment instead of invoking it directly
enables attacks where malware could escalate privileges by pointing BASH
to itself and tricking the user into entering a superuser password when
a user invokes our script, a familiar request the user may be expecting.
2023-03-16 21:03:43 -04:00
Zach Butler 0697aa31f3 SC2016 - note: Expressions don't expand in single quotes, use double quotes for that 2023-03-16 21:03:43 -04:00
Zach Butler 07208ec800 SC2006 - note: Use $(...) notation instead of legacy backticks ... 2023-03-16 21:03:42 -04:00
Zach Butler eee850dc38 SC2086 - note: Double quote to prevent globbing and word splitting. 2023-03-16 21:03:42 -04:00
Zach Butler 1038a94e66 SC2294 - warning: eval negates the benefit of arrays. Drop eval to preserve whitespace/symbols (or eval as string). 2023-03-16 21:03:42 -04:00
Zach Butler 633a8d37b3 SC2164 - Use "pushd ... || exit" or "pushd ... || return" in case pushd fails. 2023-03-16 21:03:42 -04:00
Zach Butler 83e6c6c6eb SC2034 - warning: "output" appears unused. Verify use (or export if used externally). 2023-03-16 21:03:41 -04:00
Zach Butler 46e50a4ee5 SC2034 - warning: ARCH appears unused. Verify use (or export if used externally). 2023-03-16 21:03:41 -04:00
Zach Butler 28c790be89 SC2034 - warning: CORE_SYM appears unused. Verify use (or export if used externally). 2023-03-16 21:03:41 -04:00
Zach Butler 25a7550166 SC2068 - error: Double quote array expansions to avoid re-splitting elements 2023-03-16 21:03:41 -04:00
Zach Butler 2e831bf906 SC2242 - error: Can only exit with status 0-255. Other data should be written to stdout/stderr. 2023-03-16 21:03:40 -04:00
Zach Butler 108a902a83 E011 - then keyword is not on same line as if or elif keyword 2023-03-16 21:03:40 -04:00
Zach Butler 2c92ef7ef2 E001 - Trailing Whitespace 2023-03-16 21:03:40 -04:00
Zach Butler a3284f4d5d E003 - Inconsistent indentation 2023-03-16 21:03:40 -04:00
Clayton Calabrese 39bdbfe675 use lambda for transaction generator calculations 2023-03-16 17:52:37 -05:00
Clayton Calabrese 15d92a1797 use proper arg instead of empty string in launch transaction generators 2023-03-16 12:34:45 -05:00
Clayton Calabrese 5e21ecfea4 handle whitespace stripping in launch transaction generators 2023-03-16 12:31:37 -05:00
Clayton Calabrese 07ec10dd46 update readme to reflect port endpoint changes in performance harness 2023-03-16 11:03:47 -05:00
Clayton Calabrese e3915ba846 merge from main 2023-03-16 10:53:05 -05:00
Clayton Calabrese 26da362b5d Convert Cluster's connectionPairList to match proper format 2023-03-14 16:04:17 -05:00
Clayton Calabrese 3e19ad1fb0 rework when splitting of connectionpairList happens to simplify use 2023-03-14 13:27:25 -05:00
Clayton Calabrese 9a2eb7b85b allow passing of endpoints in addition to ports. Create even distribution of generators accross ports based on number of ports passed to the transaction generator launcher 2023-03-14 10:25:56 -05:00
Clayton Calabrese 29564f6a6f Remove hardcoded number of ports in transaction generator 2023-03-08 09:45:20 -06:00
Clayton Calabrese 5747877d1c update readmes for trxgen and perf test to fit new port system 2023-03-07 17:45:19 -06:00
Clayton Calabrese 1c2f0567ce account for other routes into transactiongeneratorlauncher when dealing with ports 2023-03-07 16:55:33 -06:00
Clayton Calabrese 5baeede259 evenly distribute created transaction generators across multiple producer's ports 2023-03-07 16:17:29 -06:00
18 changed files with 452 additions and 229 deletions
+3 -23
View File
@@ -14,7 +14,7 @@ set( CMAKE_CXX_EXTENSIONS ON )
set( CXX_STANDARD_REQUIRED ON)
set(VERSION_MAJOR 4)
set(VERSION_MINOR 0)
set(VERSION_MINOR 1)
set(VERSION_PATCH 0)
set(VERSION_SUFFIX dev)
@@ -77,29 +77,9 @@ if(ENABLE_OC AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32)
list(APPEND EOSIO_WASM_RUNTIMES eos-vm-oc)
# EOS VM OC requires LLVM, but move the check up here to a central location so that the EosioTester.cmakes
# can be created with the exact version found
# find_package VERSION range is only available in 3.19 and newer.
if(${CMAKE_VERSION} VERSION_LESS "3.19")
find_package(LLVM REQUIRED CONFIG)
else()
# Preferring the latest LLVM version, search through major 11..7 and minor 9..0 in reverse order.
# Minor versions may break API. This manifests in the LLVM config files such that a range of `11...<12`
# will NOT find LLVM `11.1`. We loop over minor as well as major to resolve this.
set(max_minor 9)
set(major 11)
set(minor ${max_minor})
while(NOT LLVM_FOUND AND major GREATER_EQUAL 7)
math(EXPR end "${major} + 1")
find_package(LLVM ${major}.${minor}...<${end} CONFIG QUIET)
if(minor GREATER 0)
math(EXPR minor "${minor} - 1")
else()
math(EXPR major "${major} - 1")
set(minor ${max_minor})
endif()
endwhile()
endif()
find_package(LLVM REQUIRED CONFIG)
if(LLVM_VERSION_MAJOR VERSION_LESS 7 OR LLVM_VERSION_MAJOR VERSION_GREATER_EQUAL 12)
message(FATAL_ERROR "Leap requires an LLVM version 7 through 11")
message(FATAL_ERROR "Leap requires an LLVM version 7 through 11")
endif()
endif()
endif()
+12 -12
View File
@@ -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,12 +111,14 @@ 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:
- 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).
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).
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):
> 🔒 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:
```bash
scripts/pinned_build.sh deps build "$(nproc)"
```
@@ -146,11 +148,9 @@ To build, make sure you are in the root of the `leap` repo, then run the followi
```bash
mkdir -p build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/usr/lib/llvm-11 ..
make -j "$(nproc)" package
```
If CMake fails to find a valid llvm configure file, it may be necessary to add `-DCMAKE_PREFIX_PATH=/usr/lib/llvm-11` to the cmake command.
</details>
<details> <summary>Ubuntu 18.04 Bionic</summary>
+1 -1
View File
@@ -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() + 7) >> 3, 1);
interval = std::max((log_bundle.log_index.num_blocks() + 7u) >> 3, 1u);
}
uint32_t expected_block_num = log_bundle.log_data.first_block_num();
@@ -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); }
int num_blocks() const { return num_blocks_; }
unsigned num_blocks() const { return num_blocks_; }
uint64_t nth_block_position(uint32_t n) {
file_.seek(n*sizeof(uint64_t));
uint64_t r;
+18 -2
View File
@@ -12,10 +12,11 @@ namespace IR
struct NoImm {};
struct MemoryImm {};
PACKED_STRUCT(
struct ControlStructureImm
{
ResultType resultType{};
};
});
struct BranchImm
{
@@ -675,4 +676,19 @@ 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);
+25 -4
View File
@@ -1,6 +1,27 @@
#!/usr/bin/env bash
#!/bin/bash
apt-get update
apt-get update --fix-missing
DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
apt-get -y install zip unzip libncurses5 wget git build-essential cmake curl libgmp-dev libssl-dev libzstd-dev time zlib1g-dev libtinfo-dev bzip2 libbz2-dev python3 python3-numpy file
export DEBIAN_FRONTEND='noninteractive'
export TZ='Etc/UTC'
apt-get install -y \
build-essential \
bzip2 \
cmake \
curl \
file \
git \
libbz2-dev \
libcurl4-openssl-dev \
libgmp-dev \
libncurses5 \
libssl-dev \
libtinfo-dev \
libzstd-dev \
python3 \
python3-numpy \
time \
tzdata \
unzip \
wget \
zip \
zlib1g-dev
+137 -103
View File
@@ -1,151 +1,185 @@
#!/usr/bin/env bash
#!/bin/bash
set -eo pipefail
echo "Leap Pinned Build"
if [[ "$(uname)" == "Linux" ]]; then
if [[ -e /etc/os-release ]]; then
# obtain NAME and other information
. /etc/os-release
if [[ ${NAME} != "Ubuntu" ]]; then
echo "Currently only supporting Ubuntu based builds. Proceed at your own risk."
fi
else
echo "Currently only supporting Ubuntu based builds. /etc/os-release not found. Your Linux distribution is not supported. Proceed at your own risk."
fi
if [[ -e /etc/os-release ]]; then
# obtain NAME and other information
. /etc/os-release
if [[ "${NAME}" != "Ubuntu" ]]; then
echo "Currently only supporting Ubuntu based builds. Proceed at your own risk."
fi
else
echo "Currently only supporting Ubuntu based builds. /etc/os-release not found. Your Linux distribution is not supported. Proceed at your own risk."
fi
else
echo "Currently only supporting Ubuntu based builds. Your architecture is not supported. Proceed at your own risk."
fi
if [ $# -eq 0 ] || [ -z "$1" ]
then
echo "Please supply a directory for the build dependencies to be placed and a directory for leap build and a value for the number of jobs to use for building."
echo "The binary packages will be created and placed into the leap build directory."
echo "./pinned_build.sh <dependencies directory> <leap build directory> <1-100>"
exit -1
if [ $# -eq 0 ] || [ -z "$1" ]; then
echo "Please supply a directory for the build dependencies to be placed and a directory for leap build and a value for the number of jobs to use for building."
echo "The binary packages will be created and placed into the leap build directory."
echo "./pinned_build.sh <dependencies directory> <leap build directory> <1-100>"
exit 255
fi
CORE_SYM=EOS
export CORE_SYM='EOS'
# CMAKE_C_COMPILER requires absolute path
DEP_DIR=`realpath $1`
LEAP_DIR=$2
JOBS=$3
DEP_DIR="$(realpath "$1")"
LEAP_DIR="$2"
JOBS="$3"
CLANG_VER=11.0.1
BOOST_VER=1.70.0
LLVM_VER=7.1.0
ARCH=`uname -m`
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )";
START_DIR="$(pwd)"
pushdir() {
DIR=$1
mkdir -p ${DIR}
pushd ${DIR} &> /dev/null
DIR="$1"
mkdir -p "${DIR}"
pushd "${DIR}" &> /dev/null
}
popdir() {
EXPECTED=$1
D=`popd`
popd &> /dev/null
echo ${D}
D=`eval echo $D | head -n1 | cut -d " " -f1`
EXPECTED="$1"
D="$(popd)"
popd &> /dev/null
echo "${D}"
D="$(eval echo "$D" | head -n1 | cut -d " " -f1)"
# -ef compares absolute paths
if ! [[ ${D} -ef ${EXPECTED} ]]; then
echo "Directory is not where expected EXPECTED=${EXPECTED} at ${D}"
exit 1
fi
# -ef compares absolute paths
if ! [[ "${D}" -ef "${EXPECTED}" ]]; then
echo "Directory is not where expected EXPECTED=${EXPECTED} at ${D}"
exit 1
fi
}
try(){
output=$($@)
res=$?
if [[ ${res} -ne 0 ]]; then
exit -1
fi
"$@"
res=$?
if [[ ${res} -ne 0 ]]; then
exit 255
fi
}
install_clang() {
CLANG_DIR=$1
if [ ! -d "${CLANG_DIR}" ]; then
echo "Installing Clang ${CLANG_VER} @ ${CLANG_DIR}"
mkdir -p ${CLANG_DIR}
CLANG_FN=clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-16.04.tar.xz
try wget -O ${CLANG_FN} https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VER}/${CLANG_FN}
try tar -xvf ${CLANG_FN} -C ${CLANG_DIR}
pushdir ${CLANG_DIR}
mv clang+*/* .
popdir ${DEP_DIR}
rm ${CLANG_FN}
fi
export PATH=${CLANG_DIR}/bin:$PATH
export CLANG_DIR=${CLANG_DIR}
CLANG_DIR="$1"
if [ ! -d "${CLANG_DIR}" ]; then
echo "Installing Clang ${CLANG_VER} @ ${CLANG_DIR}"
mkdir -p "${CLANG_DIR}"
CLANG_FN="clang+llvm-${CLANG_VER}-x86_64-linux-gnu-ubuntu-16.04.tar.xz"
try wget -O "${CLANG_FN}" "https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VER}/${CLANG_FN}"
try tar -xvf "${CLANG_FN}" -C "${CLANG_DIR}"
pushdir "${CLANG_DIR}"
mv clang+*/* .
popdir "${DEP_DIR}"
rm "${CLANG_FN}"
fi
export PATH="${CLANG_DIR}/bin:$PATH"
export CLANG_DIR="${CLANG_DIR}"
}
install_llvm() {
LLVM_DIR=$1
if [ ! -d "${LLVM_DIR}" ]; then
echo "Installing LLVM ${LLVM_VER} @ ${LLVM_DIR}"
mkdir -p ${LLVM_DIR}
try wget -O llvm-${LLVM_VER}.src.tar.xz https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/llvm-${LLVM_VER}.src.tar.xz
try tar -xvf llvm-${LLVM_VER}.src.tar.xz
pushdir "${LLVM_DIR}.src"
pushdir build
try cmake -DCMAKE_TOOLCHAIN_FILE=${SCRIPT_DIR}/pinned_toolchain.cmake -DCMAKE_INSTALL_PREFIX=${LLVM_DIR} -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=host -DLLVM_BUILD_TOOLS=Off -DLLVM_ENABLE_RTTI=On -DLLVM_ENABLE_TERMINFO=Off -DCMAKE_EXE_LINKER_FLAGS=-pthread -DCMAKE_SHARED_LINKER_FLAGS=-pthread -DLLVM_ENABLE_PIC=NO ..
try make -j${JOBS}
try make -j${JOBS} install
popdir "${LLVM_DIR}.src"
popdir ${DEP_DIR}
rm -rf ${LLVM_DIR}.src
rm llvm-${LLVM_VER}.src.tar.xz
fi
export LLVM_DIR=${LLVM_DIR}
LLVM_DIR="$1"
if [ ! -d "${LLVM_DIR}" ]; then
echo "Installing LLVM ${LLVM_VER} @ ${LLVM_DIR}"
mkdir -p "${LLVM_DIR}"
try wget -O "llvm-${LLVM_VER}.src.tar.xz" "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VER}/llvm-${LLVM_VER}.src.tar.xz"
try tar -xvf "llvm-${LLVM_VER}.src.tar.xz"
pushdir "${LLVM_DIR}.src"
pushdir build
try cmake -DCMAKE_TOOLCHAIN_FILE="${SCRIPT_DIR}/pinned_toolchain.cmake" -DCMAKE_INSTALL_PREFIX="${LLVM_DIR}" -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD=host -DLLVM_BUILD_TOOLS=Off -DLLVM_ENABLE_RTTI=On -DLLVM_ENABLE_TERMINFO=Off -DCMAKE_EXE_LINKER_FLAGS=-pthread -DCMAKE_SHARED_LINKER_FLAGS=-pthread -DLLVM_ENABLE_PIC=NO ..
try make -j "${JOBS}"
try make -j "${JOBS}" install
popdir "${LLVM_DIR}.src"
popdir "${DEP_DIR}"
rm -rf "${LLVM_DIR}.src"
rm "llvm-${LLVM_VER}.src.tar.xz"
fi
export LLVM_DIR="${LLVM_DIR}"
}
install_boost() {
BOOST_DIR=$1
BOOST_DIR="$1"
if [ ! -d "${BOOST_DIR}" ]; then
echo "Installing Boost ${BOOST_VER} @ ${BOOST_DIR}"
try wget -O boost_${BOOST_VER//\./_}.tar.gz https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VER}/source/boost_${BOOST_VER//\./_}.tar.gz
try tar --transform="s:^boost_${BOOST_VER//\./_}:boost_${BOOST_VER//\./_}patched:" -xvzf boost_${BOOST_VER//\./_}.tar.gz -C ${DEP_DIR}
pushdir ${BOOST_DIR}
patch -p1 < "${SCRIPT_DIR}/0001-beast-fix-moved-from-executor.patch"
try ./bootstrap.sh -with-toolset=clang --prefix=${BOOST_DIR}/bin
./b2 toolset=clang cxxflags='-stdlib=libc++ -D__STRICT_ANSI__ -nostdinc++ -I${CLANG_DIR}/include/c++/v1 -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fPIE' linkflags='-stdlib=libc++ -pie' link=static threading=multi --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -q -j${JOBS} install
popdir ${DEP_DIR}
rm boost_${BOOST_VER//\./_}.tar.gz
fi
export BOOST_DIR=${BOOST_DIR}
if [ ! -d "${BOOST_DIR}" ]; then
echo "Installing Boost ${BOOST_VER} @ ${BOOST_DIR}"
try wget -O "boost_${BOOST_VER//\./_}.tar.gz" "https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VER}/source/boost_${BOOST_VER//\./_}.tar.gz"
try tar --transform="s:^boost_${BOOST_VER//\./_}:boost_${BOOST_VER//\./_}patched:" -xvzf "boost_${BOOST_VER//\./_}.tar.gz" -C "${DEP_DIR}"
pushdir "${BOOST_DIR}"
patch -p1 < "${SCRIPT_DIR}/0001-beast-fix-moved-from-executor.patch"
try ./bootstrap.sh -with-toolset=clang --prefix="${BOOST_DIR}/bin"
./b2 toolset=clang cxxflags="-stdlib=libc++ -D__STRICT_ANSI__ -nostdinc++ -I\${CLANG_DIR}/include/c++/v1 -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fPIE" linkflags='-stdlib=libc++ -pie' link=static threading=multi --with-iostreams --with-date_time --with-filesystem --with-system --with-program_options --with-chrono --with-test -q -j "${JOBS}" install
popdir "${DEP_DIR}"
rm "boost_${BOOST_VER//\./_}.tar.gz"
fi
export BOOST_DIR="${BOOST_DIR}"
}
pushdir ${DEP_DIR}
pushdir "${DEP_DIR}"
install_clang ${DEP_DIR}/clang-${CLANG_VER}
install_llvm ${DEP_DIR}/llvm-${LLVM_VER}
install_boost ${DEP_DIR}/boost_${BOOST_VER//\./_}patched
install_clang "${DEP_DIR}/clang-${CLANG_VER}"
install_llvm "${DEP_DIR}/llvm-${LLVM_VER}"
install_boost "${DEP_DIR}/boost_${BOOST_VER//\./_}patched"
# go back to the directory where the script starts
popdir ${START_DIR}
popdir "${START_DIR}"
pushdir ${LEAP_DIR}
pushdir "${LEAP_DIR}"
# build Leap
echo "Building Leap ${SCRIPT_DIR}"
try cmake -DCMAKE_TOOLCHAIN_FILE=${SCRIPT_DIR}/pinned_toolchain.cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=${LLVM_DIR}/lib/cmake -DCMAKE_PREFIX_PATH=${BOOST_DIR}/bin ${SCRIPT_DIR}/..
try cmake -DCMAKE_TOOLCHAIN_FILE="${SCRIPT_DIR}/pinned_toolchain.cmake" -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="${LLVM_DIR}/lib/cmake" -DCMAKE_PREFIX_PATH="${BOOST_DIR}/bin" "${SCRIPT_DIR}/.."
try make -j${JOBS}
try make -j "${JOBS}"
try cpack
echo " .----------------. .----------------. .----------------. .----------------. ";
echo "| .--------------. || .--------------. || .--------------. || .--------------. |";
echo "| | _____ | || | _________ | || | __ | || | ______ | |";
echo "| | |_ _| | || | |_ ___ | | || | / \ | || | |_ __ \ | |";
echo "| | | | | || | | |_ \_| | || | / /\ \ | || | | |__) | | |";
echo "| | | | _ | || | | _| _ | || | / ____ \ | || | | ___/ | |";
echo "| | _| |__/ | | || | _| |___/ | | || | _/ / \ \_ | || | _| |_ | |";
echo "| | |________| | || | |_________| | || ||____| |____|| || | |_____| | |";
echo "| | | || | | || | | || | | |";
echo "| '--------------' || '--------------' || '--------------' || '--------------' |";
echo " '----------------' '----------------' '----------------' '----------------' ";
echo "Leap has successfully built and constructed its packages. You should be able to find the packages at ${LEAP_DIR}. Enjoy!!!"
# art generated with DALL-E (https://openai.com/blog/dall-e), then fed through ASCIIart.club (https://asciiart.club) with permission
cat <<'TXT' # BASH interpolation must remain disabled for the ASCII art to print correctly
,▄▄A`
_╓▄██`
╓▄▓▓▀▀`
╓▓█▀╓▄▓
▓▌▓▓▓▀
,▄▓███▓H
_╨╫▀╚▀╠▌`╙¥,
╓« _╟▄▄ `½, ╓▄▄╦▄≥_
╙▓╫╬▒R▀▀╙▀▀▓φ_ «_╙Y╥▄mmMM#╦▄,_ ,╓╦mM╩╨╙╙╙\`║═
`` `▀▄__╫▓▓╨` _```"""*ⁿⁿ^`````Ω, `╟∩
╙▌▓▓"` ,«ñ` ╔╬▓▌⌂ ╔▌
╙█▌,,╔╗M╨,░ ` "╫▓m_ ╟H _
_,,,,__,╠█▓▒` .╣▌µ _ _.╓╔▄▄▓█▓▓N_ ╙▀╩KKM╙╟▓N
,▄▓█▓████▀▀▀╙▀╓╔φ»█▓▓Ñ╦«, :»»µ╦▓▓█▀└╙▀███▓╥__ _,╓▄▓▓▓M▓`,
__╓Φ▓█╫▓▓▓▓▓▓▓▓▓▓▓▓▓▀K▀▀███▓▓▓▓▓▓▀▀╙ `▀▀▀▓▄▄K╨╙└ `▀▌╙█▄*.
,╓Φ▓▓▀▄▓▀` ╙▀╙ ╙▓╙╙▓▄*
.▄▓╫▀╦▄▀` ╙▓╙µ╙▀
▄▓▀╨▓▓╨_ `▀▄▄M
_█▌▄▌╙` `╙
╙└`
Ñ▓▓▓▓ ¢▄▄▄▄▄▄▄▄▄▄ , ,,,,,,,,,,,_
_╫▓▓█▌ ╟▓████████▀ ╓╣▓▌_ ╠╫▓█▓▓▓▓█▓▓▓▓▄
_▓▓▓█▌ ╟╫██▄,,,,_ æ▄███▓▄ ▐║████▀╨╨▀▓███▌
:╫▓▓█▌ ╟╢████████▓ ,╬███████▓, ▐║████▓▄▄▓▓███▀
:╫▓▓█▌_ _╟║███▀▀▀▀▀▀ ╓╫███╣╫╬███▓N_ j▐██▀▀▀▀▀▀▀▀▀`
___________]╫▓▓█▓φ╓╓╓╓╓╓,__╟╣█▌▌,,,,,_ _╬▓████████████▓▄_ ▐M█▌
_ _________]╫▌▓█████████▓▓▄╟╣████████▓▄╣██▓▀^ _ ╙▓██▓▓╗__M█▓
___ _ _ ▀╣▀╣╩╩╩╩╩╩╩▀▀▀▀╙▀▀▀▀▀▀▀▀▀▀▀▀▀▀` ╙▀▀▀▀╩═╩▀▀
_ __ __ _____ ___ ____ _ __ _ ____ ___
____ ____ __ _ _ _ _ _ _ __ _ __ __
__ _ ________ ___ ________ ___ _ _ _ _
_ __ __ _ __ ____ _ _ ____ _ _ _ _
_ _ _ ____ ____ _ _ _ __ _ _ _ __
---
Leap has successfully built and constructed its packages. You should be able to
find the packages at:
TXT
echo "${LEAP_DIR}"
echo
echo 'Thank you, fam!!'
echo
+6 -2
View File
@@ -125,8 +125,12 @@ add_test(NAME nodeos_protocol_feature_test COMMAND tests/nodeos_protocol_feature
set_property(TEST nodeos_protocol_feature_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME compute_transaction_test COMMAND tests/compute_transaction_test.py -v -p 2 -n 3 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST compute_transaction_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME read_only_trx_test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST read_only_trx_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME read-only-trx-basic-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST read-only-trx-basic-test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME read-only-trx-parallel-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --read-only-threads 3 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST read-only-trx-parallel-test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME read-only-trx-parallel-eos-vm-oc-test COMMAND tests/read_only_trx_test.py -v -p 2 -n 3 --eos-vm-oc-enable --read-only-threads 3 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST read-only-trx-parallel-eos-vm-oc-test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME subjective_billing_test COMMAND tests/subjective_billing_test.py -v -p 2 -n 4 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST subjective_billing_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME get_account_test COMMAND tests/get_account_test.py -v -p 2 --clean-run ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
+7 -6
View File
@@ -1693,7 +1693,6 @@ class Cluster(object):
waitToComplete:bool=False, abiFile=None, actionsData=None, actionsAuths=None):
Utils.Print("Configure txn generators")
node=self.getNode(nodeId)
p2pListenPort = self.getNodeP2pPort(nodeId)
info = node.getInfo()
chainId = info['chain_id']
lib_id = info['last_irreversible_block_id']
@@ -1702,13 +1701,12 @@ class Cluster(object):
tpsLimitPerGenerator=tpsPerGenerator
self.preExistingFirstTrxFiles = glob.glob(f"{Utils.DataDir}/first_trx_*.txt")
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=targetTps, tpsLimitPerGenerator=tpsLimitPerGenerator)
connectionPairList = [f"{self.host}:{self.getNodeP2pPort(nodeId)}"]
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=targetTps, tpsLimitPerGenerator=tpsLimitPerGenerator, connectionPairList=connectionPairList)
self.trxGenLauncher = TransactionGeneratorsLauncher(chainId=chainId, lastIrreversibleBlockId=lib_id,
contractOwnerAccount=contractOwnerAcctName, accts=','.join(map(str, acctNamesList)),
privateKeys=','.join(map(str, acctPrivKeysList)), trxGenDurationSec=durationSec, logDir=Utils.DataDir,
abiFile=abiFile, actionsData=actionsData, actionsAuths=actionsAuths,
peerEndpoint=self.host, port=p2pListenPort, tpsTrxGensConfig=tpsTrxGensConfig)
abiFile=abiFile, actionsData=actionsData, actionsAuths=actionsAuths, tpsTrxGensConfig=tpsTrxGensConfig)
Utils.Print("Launch txn generators and start generating/sending transactions")
self.trxGenLauncher.launch(waitToComplete=waitToComplete)
@@ -1729,4 +1727,7 @@ class Cluster(object):
for line in f:
firstTrxs.append(line.rstrip('\n'))
Utils.Print(f"first transactions: {firstTrxs}")
node.waitForTransactionsInBlock(firstTrxs)
status = node.waitForTransactionsInBlock(firstTrxs)
if status is None:
Utils.Print('ERROR: Failed to spin up transaction generators: never received first transactions')
return status
+4
View File
@@ -484,6 +484,10 @@ class Node(Transactions):
def scheduleSnapshot(self):
return self.processUrllibRequest("producer", "schedule_snapshot")
def scheduleSnapshotAt(self, sbn):
param = { "start_block_num": sbn, "end_block_num": sbn }
return self.processUrllibRequest("producer", "schedule_snapshot", param)
# kill all existing nodeos in case lingering from previous test
@staticmethod
@@ -10,16 +10,19 @@ sys.path.append(harnessPath)
from .testUtils import Utils
from pathlib import Path
from re import sub
Print = Utils.Print
class TpsTrxGensConfig:
def __init__(self, targetTps: int, tpsLimitPerGenerator: int):
def __init__(self, targetTps: int, tpsLimitPerGenerator: int, connectionPairList: list):
self.targetTps: int = targetTps
self.tpsLimitPerGenerator: int = tpsLimitPerGenerator
self.numGenerators = math.ceil(self.targetTps / self.tpsLimitPerGenerator)
self.connectionPairList = connectionPairList
self.numConnectionPairs = len(self.connectionPairList)
round_to_multiple = lambda num, multiple: math.ceil(num/multiple) * multiple
self.numGenerators = round_to_multiple(math.ceil(self.targetTps / self.tpsLimitPerGenerator), self.numConnectionPairs)
self.initialTpsPerGenerator = math.floor(self.targetTps / self.numGenerators)
self.modTps = self.targetTps % self.numGenerators
self.cleanlyDivisible = self.modTps == 0
@@ -35,8 +38,7 @@ class TpsTrxGensConfig:
class TransactionGeneratorsLauncher:
def __init__(self, chainId: int, lastIrreversibleBlockId: int, contractOwnerAccount: str, accts: str, privateKeys: str, trxGenDurationSec: int, logDir: str,
abiFile: Path, actionsData, actionsAuths,
peerEndpoint: str, port: int, tpsTrxGensConfig: TpsTrxGensConfig):
abiFile: Path, actionsData, actionsAuths, tpsTrxGensConfig: TpsTrxGensConfig):
self.chainId = chainId
self.lastIrreversibleBlockId = lastIrreversibleBlockId
self.contractOwnerAccount = contractOwnerAccount
@@ -46,14 +48,14 @@ class TransactionGeneratorsLauncher:
self.tpsTrxGensConfig = tpsTrxGensConfig
self.logDir = logDir
self.abiFile = abiFile
self.actionsData=actionsData
self.actionsAuths=actionsAuths
self.peerEndpoint = peerEndpoint
self.port = port
self.actionsData = actionsData
self.actionsAuths = actionsAuths
def launch(self, waitToComplete=True):
self.subprocess_ret_codes = []
connectionPairIter = 0
for id, targetTps in enumerate(self.tpsTrxGensConfig.targetTpsPerGenList):
connectionPair = self.tpsTrxGensConfig.connectionPairList[connectionPairIter].rsplit(":")
popenStringList = [
'./tests/trx_generator/trx_generator',
'--generator-id', f'{id}',
@@ -65,8 +67,8 @@ class TransactionGeneratorsLauncher:
'--trx-gen-duration', f'{self.trxGenDurationSec}',
'--target-tps', f'{targetTps}',
'--log-dir', f'{self.logDir}',
'--peer-endpoint', f'{self.peerEndpoint}',
'--port', f'{self.port}']
'--peer-endpoint', f'{connectionPair[0]}',
'--port', f'{connectionPair[1]}']
if self.abiFile is not None and self.actionsData is not None and self.actionsAuths is not None:
popenStringList.extend(['--abi-file', f'{self.abiFile}',
'--actions-data', f'{self.actionsData}',
@@ -74,6 +76,7 @@ class TransactionGeneratorsLauncher:
if Utils.Debug:
Print(f"Running trx_generator: {' '.join(popenStringList)}")
self.subprocess_ret_codes.append(subprocess.Popen(popenStringList))
connectionPairIter = (connectionPairIter + 1) % len(self.tpsTrxGensConfig.connectionPairList)
exitCodes=None
if waitToComplete:
exitCodes = [ret_code.wait() for ret_code in self.subprocess_ret_codes]
@@ -100,20 +103,20 @@ def parseArgs():
parser.add_argument("abi_file", type=str, help="The path to the contract abi file to use for the supplied transaction action data")
parser.add_argument("actions_data", type=str, help="The json actions data file or json actions data description string to use")
parser.add_argument("actions_auths", type=str, help="The json actions auth file or json actions auths description string to use, containting authAcctName to activePrivateKey pairs.")
parser.add_argument("peer_endpoint", type=str, help="set the peer endpoint to send transactions to", default="127.0.0.1")
parser.add_argument("port", type=int, help="set the peer endpoint port to send transactions to", default=9876)
parser.add_argument("connection_pair_list", type=str, help="Comma separated list of endpoint:port combinations to send transactions to", default="localhost:9876")
args = parser.parse_args()
return args
def main():
args = parseArgs()
connectionPairList = sub('[\s+]', '', args.connection_pair_list)
connectionPairList = connectionPairList.rsplit(',')
trxGenLauncher = TransactionGeneratorsLauncher(chainId=args.chain_id, lastIrreversibleBlockId=args.last_irreversible_block_id,
contractOwnerAccount=args.contract_owner_account, accts=args.accounts,
privateKeys=args.priv_keys, trxGenDurationSec=args.trx_gen_duration, logDir=args.log_dir,
abiFile=args.abi_file, actionsData=args.actions_data, actionsAuths=args.actions_auths,
peerEndpoint=args.peer_endpoint, port=args.port,
tpsTrxGensConfig=TpsTrxGensConfig(targetTps=args.target_tps, tpsLimitPerGenerator=args.tps_limit_per_generator))
tpsTrxGensConfig=TpsTrxGensConfig(targetTps=args.target_tps, tpsLimitPerGenerator=args.tps_limit_per_generator, connectionPairList=connectionPairList))
exit_codes = trxGenLauncher.launch()
+11 -10
View File
@@ -118,10 +118,10 @@ class NodeosQueries:
# could be a transaction response
if cntxt.hasKey("processed"):
cntxt.add("processed")
cntxt.add("action_traces")
cntxt.index(0)
if not cntxt.isSectionNull("except"):
return "no_block"
cntxt.add("action_traces")
cntxt.index(0)
return cntxt.add("block_num")
# or what the trace api plugin returns
@@ -242,7 +242,7 @@ class NodeosQueries:
assert(isinstance(transId, str))
exitOnErrorForDelayed=not delayedRetry and exitOnError
timeout=3
cmdDesc="get transaction_trace"
cmdDesc=self.fetchTransactionCommand()
cmd="%s %s" % (cmdDesc, transId)
msg="(transaction id=%s)" % (transId);
for i in range(0,(int(60/timeout) - 1)):
@@ -295,8 +295,8 @@ class NodeosQueries:
refBlockNum=None
key=""
try:
key="[transaction][transaction_header][ref_block_num]"
refBlockNum=trans["transaction_header"]["ref_block_num"]
key = self.fetchKeyCommand()
refBlockNum = self.fetchRefBlock(trans)
refBlockNum=int(refBlockNum)+1
except (TypeError, ValueError, KeyError) as _:
Utils.Print("transaction%s not found. Transaction: %s" % (key, trans))
@@ -347,8 +347,8 @@ class NodeosQueries:
def getTable(self, contract, scope, table, exitOnError=False):
cmdDesc = "get table"
cmd="%s %s %s %s" % (cmdDesc, contract, scope, table)
msg="contract=%s, scope=%s, table=%s" % (contract, scope, table);
cmd=f"{cmdDesc} {self.cleosLimit} {contract} {scope} {table}"
msg=f"contract={contract}, scope={scope}, table={table}"
return self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
def getTableAccountBalance(self, contract, scope):
@@ -529,7 +529,7 @@ class NodeosQueries:
return m.group(1)
except subprocess.CalledProcessError as ex:
end=time.perf_counter()
msg=ex.output.decode("utf-8")
msg=ex.stderr.decode("utf-8")
Utils.Print("ERROR: Exception during code hash retrieval. cmd Duration: %.3f sec. %s" % (end-start, msg))
return None
@@ -580,8 +580,9 @@ class NodeosQueries:
except subprocess.CalledProcessError as ex:
if not silentErrors:
end=time.perf_counter()
msg=ex.output.decode("utf-8")
errorMsg="Exception during \"%s\". Exception message: %s. cmd Duration=%.3f sec. %s" % (cmdDesc, msg, end-start, exitMsg)
out=ex.output.decode("utf-8")
msg=ex.stderr.decode("utf-8")
errorMsg="Exception during \"%s\". Exception message: %s. stdout: %s. cmd Duration=%.3f sec. %s" % (cmdDesc, msg, out, end-start, exitMsg)
if exitOnError:
Utils.cmdError(errorMsg)
Utils.errorExit(errorMsg)
+6 -7
View File
@@ -107,7 +107,7 @@ class Transactions(NodeosQueries):
self.trackCmdTransaction(trans, reportStatus=reportStatus)
except subprocess.CalledProcessError as ex:
end=time.perf_counter()
msg=ex.output.decode("utf-8")
msg=ex.stderr.decode("utf-8")
Utils.Print("ERROR: Exception during funds transfer. cmd Duration: %.3f sec. %s" % (end-start, msg))
if exitOnError:
Utils.cmdError("could not transfer \"%s\" from %s to %s" % (amountStr, source, destination))
@@ -131,7 +131,7 @@ class Transactions(NodeosQueries):
Utils.Print("cmd Duration: %.3f sec" % (end-start))
except subprocess.CalledProcessError as ex:
end=time.perf_counter()
msg=ex.output.decode("utf-8")
msg=ex.stderr.decode("utf-8")
Utils.Print("ERROR: Exception during spawn of funds transfer. cmd Duration: %.3f sec. %s" % (end-start, msg))
if exitOnError:
Utils.cmdError("could not transfer \"%s\" from %s to %s" % (amountStr, source, destination))
@@ -158,15 +158,15 @@ class Transactions(NodeosQueries):
except subprocess.CalledProcessError as ex:
if not shouldFail:
end=time.perf_counter()
msg=ex.output.decode("utf-8")
Utils.Print("ERROR: Exception during set contract. cmd Duration: %.3f sec. %s" % (end-start, msg))
out=ex.output.decode("utf-8")
msg=ex.stderr.decode("utf-8")
Utils.Print("ERROR: Exception during set contract. stderr: %s. stdout: %s. cmd Duration: %.3f sec." % (msg, out, end-start))
return None
else:
retMap={}
retMap["returncode"]=ex.returncode
retMap["cmd"]=ex.cmd
retMap["output"]=ex.output
retMap["stdout"]=ex.stdout
retMap["stderr"]=ex.stderr
return retMap
@@ -213,7 +213,7 @@ class Transactions(NodeosQueries):
Utils.Print("cmd Duration: %.3f sec" % (end-start))
return (NodeosQueries.getTransStatus(retTrans) == 'executed', retTrans)
except subprocess.CalledProcessError as ex:
msg=ex.output.decode("utf-8")
msg=ex.stderr.decode("utf-8")
if not silentErrors:
end=time.perf_counter()
Utils.Print("ERROR: Exception during push transaction. cmd Duration=%.3f sec. %s" % (end - start, msg))
@@ -245,7 +245,6 @@ class Transactions(NodeosQueries):
except subprocess.CalledProcessError as ex:
msg=ex.stderr.decode("utf-8")
output=ex.output.decode("utf-8")
msg=ex.output.decode("utf-8")
if not silentErrors:
end=time.perf_counter()
Utils.Print("ERROR: Exception during push message. stderr: %s. stdout: %s. cmd Duration=%.3f sec." % (msg, output, end - start))
+27 -14
View File
@@ -126,13 +126,15 @@ try:
waitForBlock(node0, blockNum, blockType=BlockType.lib)
Print("Configure and launch txn generators")
targetTpsPerGenerator = 10
testTrxGenDurationSec=60*30
cluster.launchTrxGenerators(contractOwnerAcctName=cluster.eosioAccount.name, acctNamesList=[account1Name, account2Name],
acctPrivKeysList=[account1PrivKey,account2PrivKey], nodeId=snapshotNodeId, tpsPerGenerator=targetTpsPerGenerator,
numGenerators=trxGeneratorCnt, durationSec=testTrxGenDurationSec, waitToComplete=False)
cluster.waitForTrxGeneratorsSpinup(nodeId=snapshotNodeId, numGenerators=trxGeneratorCnt)
status = cluster.waitForTrxGeneratorsSpinup(nodeId=snapshotNodeId, numGenerators=trxGeneratorCnt)
assert status is not None, "ERROR: Failed to spinup Transaction Generators"
blockNum=node0.getBlockNum(BlockType.head)
timePerBlock=500
@@ -156,11 +158,8 @@ try:
minReqPctLeeway=0.60
minRequiredTransactions=minReqPctLeeway*transactionsPerBlock
assert steadyStateAvg>=minRequiredTransactions, "Expected to at least receive %s transactions per block, but only getting %s" % (minRequiredTransactions, steadyStateAvg)
Print("Create snapshot")
ret = nodeProg.scheduleSnapshot()
assert ret is not None, "Snapshot creation failed"
Print("Create snapshot (node 0)")
ret = nodeSnap.createSnapshot()
assert ret is not None, "Snapshot creation failed"
ret_head_block_num = ret["payload"]["head_block_num"]
@@ -177,6 +176,29 @@ try:
Utils.processLeapUtilCmd("snapshot to-json --input-file {}".format(snapshotFile), "snapshot to-json", silentErrors=False)
snapshotFile = snapshotFile + ".json"
Print("Trim programmable blocklog to snapshot head block num and relaunch programmable node")
nodeProg.kill(signal.SIGTERM)
output=cluster.getBlockLog(progNodeId, blockLogAction=BlockLogAction.trim, first=0, last=ret_head_block_num, throwException=True)
removeState(progNodeId)
Utils.rmFromFile(Utils.getNodeConfigDir(progNodeId, "config.ini"), "p2p-peer-address")
isRelaunchSuccess = nodeProg.relaunch(chainArg="--replay", addSwapFlags={}, timeout=relaunchTimeout, cachePopen=True)
assert isRelaunchSuccess, "Failed to relaunch programmable node"
Print("Schedule snapshot (node 2)")
ret = nodeProg.scheduleSnapshotAt(ret_head_block_num)
assert ret is not None, "Snapshot scheduling failed"
Print("Wait for programmable node lib to advance")
waitForBlock(nodeProg, ret_head_block_num+1, blockType=BlockType.lib)
Print("Kill programmable node")
nodeProg.kill(signal.SIGTERM)
Print("Convert snapshot to JSON")
progSnapshotFile = getLatestSnapshot(progNodeId)
Utils.processLeapUtilCmd("snapshot to-json --input-file {}".format(progSnapshotFile), "snapshot to-json", silentErrors=False)
progSnapshotFile = progSnapshotFile + ".json"
Print("Trim irreversible blocklog to snapshot head block num")
nodeIrr.kill(signal.SIGTERM)
output=cluster.getBlockLog(irrNodeId, blockLogAction=BlockLogAction.trim, first=0, last=ret_head_block_num, throwException=True)
@@ -204,15 +226,6 @@ try:
irrSnapshotFile = irrSnapshotFile + ".json"
assert Utils.compareFiles(snapshotFile, irrSnapshotFile), f"Snapshot files differ {snapshotFile} != {irrSnapshotFile}"
Print("Kill programmable node")
nodeProg.kill(signal.SIGTERM)
Print("Convert snapshot to JSON")
progSnapshotFile = getLatestSnapshot(progNodeId)
Utils.processLeapUtilCmd("snapshot to-json --input-file {}".format(progSnapshotFile), "snapshot to-json", silentErrors=False)
progSnapshotFile = progSnapshotFile + ".json"
assert Utils.compareFiles(progSnapshotFile, irrSnapshotFile), f"Snapshot files differ {progSnapshotFile} != {irrSnapshotFile}"
testSuccessful=True
+2 -1
View File
@@ -118,7 +118,8 @@ try:
tpsPerGenerator=targetTpsPerGenerator, numGenerators=trxGeneratorCnt, durationSec=testTrxGenDurationSec,
waitToComplete=False)
cluster.waitForTrxGeneratorsSpinup(nodeId=node0.nodeId, numGenerators=trxGeneratorCnt)
status = cluster.waitForTrxGeneratorsSpinup(nodeId=node0.nodeId, numGenerators=trxGeneratorCnt)
assert status is not None, "ERROR: Failed to spinup Transaction Generators"
blockNum=head(node0)
timePerBlock=500
+1 -2
View File
@@ -488,8 +488,7 @@ Performance Test Basic Single Test:
* `abi_file` The path to the contract abi file to use for the supplied transaction action data
* `actions_data` The json actions data file or json actions data description string to use
* `actions_auths` The json actions auth file or json actions auths description string to use, containting authAcctName to activePrivateKey pairs.
* `peer_endpoint` set the peer endpoint to send transactions to, default="127.0.0.1"
* `port` set the peer endpoint port to send transactions to, default=9876
* `connection_pair_list` Comma separated list of endpoint:port combinations to send transactions to
</details>
#### Transaction Generator
@@ -327,7 +327,9 @@ class PerformanceTestBasic:
def runTpsTest(self) -> PtbTpsTestResult:
completedRun = False
self.producerNode = self.cluster.getNode(self.producerNodeId)
self.producerP2pPort = self.cluster.getNodeP2pPort(self.producerNodeId)
self.connectionPairList = []
for producer in range(0, self.clusterConfig.pnodes):
self.connectionPairList.append(f"{self.cluster.getNode(producer).host}:{self.cluster.getNodeP2pPort(producer)}")
self.validationNode = self.cluster.getNode(self.validationNodeId)
self.wallet = self.walletMgr.create('default')
self.setupContract()
@@ -371,13 +373,13 @@ class PerformanceTestBasic:
self.cluster.biosNode.kill(signal.SIGTERM)
self.data.startBlock = self.waitForEmptyBlocks(self.validationNode, self.emptyBlockGoal)
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=self.ptbConfig.targetTps, tpsLimitPerGenerator=self.ptbConfig.tpsLimitPerGenerator)
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=self.ptbConfig.targetTps, tpsLimitPerGenerator=self.ptbConfig.tpsLimitPerGenerator, connectionPairList=self.connectionPairList)
self.cluster.trxGenLauncher = TransactionGeneratorsLauncher(chainId=chainId, lastIrreversibleBlockId=lib_id, contractOwnerAccount=self.clusterConfig.specifiedContract.account.name,
accts=','.join(map(str, self.accountNames)), privateKeys=','.join(map(str, self.accountPrivKeys)),
trxGenDurationSec=self.ptbConfig.testTrxGenDurationSec, logDir=self.trxGenLogDirPath,
abiFile=abiFile, actionsData=actionsDataJson, actionsAuths=actionsAuthsJson,
peerEndpoint=self.producerNode.host, port=self.producerP2pPort, tpsTrxGensConfig=tpsTrxGensConfig)
tpsTrxGensConfig=tpsTrxGensConfig)
trxGenExitCodes = self.cluster.trxGenLauncher.launch()
print(f"Transaction Generator exit codes: {trxGenExitCodes}")
+168 -23
View File
@@ -1,8 +1,11 @@
#!/usr/bin/env python3
import random
import time
import signal
import threading
from TestHarness import Account, Cluster, TestHelper, Utils, WalletMgr
from TestHarness import Account, Cluster, ReturnType, TestHelper, Utils, WalletMgr
from TestHarness.TestHelper import AppArgs
###############################################################
@@ -29,6 +32,10 @@ pnodes=args.p
topo=args.s
delay=args.d
total_nodes = pnodes if args.n < pnodes else args.n
# For this test, we need at least 1 non-producer
if total_nodes <= pnodes:
Print ("non-producing nodes %d must be greater than 0. Force it to %d. producing nodes: %d," % (total_nodes - pnodes, pnodes + 1, pnodes))
total_nodes = pnodes + 1
debug=args.v
nodesFile=args.nodes_file
dontLaunch=nodesFile is not None
@@ -45,6 +52,7 @@ if nodesFile is not None:
Utils.Debug=debug
testSuccessful=False
errorInThread=False
random.seed(seed) # Use a fixed seed for repeatability.
cluster=Cluster(walletd=True,unshared=args.unshared)
@@ -54,6 +62,9 @@ EOSIO_ACCT_PRIVATE_DEFAULT_KEY = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79z
EOSIO_ACCT_PUBLIC_DEFAULT_KEY = "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"
try:
TestHelper.printSystemInfo("BEGIN")
cluster.setWalletMgr(walletMgr)
if dontLaunch: # run test against remote cluster
jsonStr=None
with open(nodesFile, "r") as f:
@@ -71,11 +82,25 @@ try:
cluster.killall(allInstances=killAll)
cluster.cleanup()
Print ("producing nodes: %s, non-producing nodes: %d, topology: %s, delay between nodes launch(seconds): %d" % (pnodes, total_nodes-pnodes, topo, delay))
Print ("producing nodes: %d, non-producing nodes: %d, topology: %s, delay between nodes launch(seconds): %d" % (pnodes, total_nodes-pnodes, topo, delay))
cluster.killall(allInstances=killAll)
cluster.cleanup()
Print("Stand up cluster")
# set up read-only options for API node
specificExtraNodeosArgs={}
# producer nodes will be mapped to 0 through pnodes-1, so the number pnodes is the no-producing API node
specificExtraNodeosArgs[pnodes]=" --plugin eosio::net_api_plugin"
if args.read_only_threads > 0:
specificExtraNodeosArgs[pnodes]+=" --read-only-threads "
specificExtraNodeosArgs[pnodes]+=str(args.read_only_threads)
if args.eos_vm_oc_enable:
specificExtraNodeosArgs[pnodes]+=" --eos-vm-oc-enable"
if args.wasm_runtime:
specificExtraNodeosArgs[pnodes]+=" --wasm-runtime "
specificExtraNodeosArgs[pnodes]+=args.wasm_runtime
extraNodeosArgs=" --http-max-response-time-ms 990000 --disable-subjective-api-billing false "
if cluster.launch(pnodes=pnodes, totalNodes=total_nodes, topo=topo, delay=delay,extraNodeosArgs=extraNodeosArgs ) is False:
if cluster.launch(pnodes=pnodes, totalNodes=total_nodes, topo=topo, delay=delay, specificExtraNodeosArgs=specificExtraNodeosArgs, extraNodeosArgs=extraNodeosArgs ) is False:
errorExit("Failed to stand up eos cluster.")
Print ("Wait for Cluster stabilization")
@@ -97,7 +122,7 @@ try:
userAccount = Account(userAccountName)
userAccount.ownerPublicKey = EOSIO_ACCT_PUBLIC_DEFAULT_KEY
userAccount.activePublicKey = EOSIO_ACCT_PUBLIC_DEFAULT_KEY
cluster.createAccountAndVerify(userAccount, cluster.eosioAccount)
cluster.createAccountAndVerify(userAccount, cluster.eosioAccount, stakeCPU=2000)
noAuthTableContractDir="unittests/test-contracts/no_auth_table"
noAuthTableWasmFile="no_auth_table.wasm"
@@ -116,28 +141,148 @@ try:
}
return apiNode.pushTransaction(trx, opts)
Print("Insert a user")
results = sendTransaction('insert', {"user": userAccountName, "id": 1, "age": 10}, auth=[{"actor": userAccountName, "permission":"active"}])
assert(results[0])
apiNode.waitForTransactionInBlock(results[1]['transaction_id'])
def sendReadOnlyTrxOnThread(startId, numTrxs):
Print("start sendReadOnlyTrxOnThread")
# verify the return value (age) from read-only is the same as created.
Print("Send a read-only Get transaction to verify previous Insert")
results = sendTransaction('getage', {"user": userAccountName}, opts='--read')
assert(results[0])
assert(results[1]['processed']['action_traces'][0]['return_value_data'] == 10)
global errorInThread
errorInThread = False
try:
for i in range(numTrxs):
results = sendTransaction('age', {"user": userAccountName, "id": startId + i}, opts='--read')
assert(results[0])
assert(results[1]['processed']['action_traces'][0]['return_value_data'] == 25)
except Exception as e:
Print("Exception in sendReadOnlyTrxOnThread: ", e)
errorInThread = True
# verify non-read-only modification works
Print("Send a non-read-only Modify transaction")
results = sendTransaction('modify', {"user": userAccountName, "age": 25}, auth=[{"actor": userAccountName, "permission": "active"}])
assert(results[0])
apiNode.waitForTransactionInBlock(results[1]['transaction_id'])
def sendTrxsOnThread(startId, numTrxs, opts=None):
Print("sendTrxsOnThread: ", startId, numTrxs, opts)
# verify 'cleos push action getage "user": "user" --read' works
Print("Send a read-only Get action")
results = apiNode.pushMessage(testAccountName, 'getage', "{{\"user\": \"{}\"}}".format(userAccountName), opts='--read');
assert(results[0])
assert(results[1]['processed']['action_traces'][0]['return_value_data'] == 25)
global errorInThread
errorInThread = False
try:
for i in range(numTrxs):
results = sendTransaction('age', {"user": userAccountName, "id": startId + i}, auth=[{"actor": userAccountName, "permission":"active"}], opts=opts)
assert(results[0])
except Exception as e:
Print("Exception in sendTrxsOnThread: ", e)
errorInThread = True
def doRpc(resource, command, numRuns, fieldIn, expectedValue, code, payload={}):
global errorInThread
errorInThread = False
try:
for i in range(numRuns):
ret_json = apiNode.processUrllibRequest(resource, command, payload)
if code is None:
assert(ret_json["payload"][fieldIn] is not None)
if expectedValue is not None:
assert(ret_json["payload"][fieldIn] == expectedValue)
else:
assert(ret_json["code"] == code)
except Exception as e:
Print("Exception in doRpc: ", e)
errorInThread = True
def runReadOnlyTrxAndRpcInParallel(resource, command, fieldIn=None, expectedValue=None, code=None, payload={}):
Print("runReadOnlyTrxAndRpcInParallel: ", command)
numRuns = 10
trxThread = threading.Thread(target = sendReadOnlyTrxOnThread, args = (0, numRuns ))
rpcThread = threading.Thread(target = doRpc, args = (resource, command, numRuns, fieldIn, expectedValue, code, payload))
trxThread.start()
rpcThread.start()
trxThread.join()
rpcThread.join()
assert(not errorInThread)
def mixedOpsTest(opt=None):
Print("mixedOpsTest -- opt = ", opt)
numRuns = 300
readOnlyThread = threading.Thread(target = sendReadOnlyTrxOnThread, args = (0, numRuns ))
readOnlyThread.start()
sendTrxThread = threading.Thread(target = sendTrxsOnThread, args = (numRuns, numRuns, opt))
sendTrxThread.start()
pushBlockThread = threading.Thread(target = doRpc, args = ("chain", "push_block", numRuns, None, None, 202, {"block":"signed_block"}))
pushBlockThread.start()
readOnlyThread.join()
sendTrxThread.join()
pushBlockThread.join()
assert(not errorInThread)
def sendMulReadOnlyTrx(numThreads):
threadList = []
num_trxs_per_thread = 500
for i in range(numThreads):
thr = threading.Thread(target = sendReadOnlyTrxOnThread, args = (i * num_trxs_per_thread, num_trxs_per_thread ))
thr.start()
threadList.append(thr)
for thr in threadList:
thr.join()
def basicTests():
Print("Insert a user")
results = sendTransaction('insert', {"user": userAccountName, "id": 1, "age": 10}, auth=[{"actor": userAccountName, "permission":"active"}])
assert(results[0])
apiNode.waitForTransactionInBlock(results[1]['transaction_id'])
# verify the return value (age) from read-only is the same as created.
Print("Send a read-only Get transaction to verify previous Insert")
results = sendTransaction('getage', {"user": userAccountName}, opts='--read')
assert(results[0])
assert(results[1]['processed']['action_traces'][0]['return_value_data'] == 10)
# verify non-read-only modification works
Print("Send a non-read-only Modify transaction")
results = sendTransaction('modify', {"user": userAccountName, "age": 25}, auth=[{"actor": userAccountName, "permission": "active"}])
assert(results[0])
apiNode.waitForTransactionInBlock(results[1]['transaction_id'])
def multiReadOnlyTests():
Print("Verify multiple read-only Get actions work after Modify")
sendMulReadOnlyTrx(numThreads=5)
def chainApiTests():
# verify chain APIs can run in parallel with read-ony transactions
runReadOnlyTrxAndRpcInParallel("chain", "get_info", "server_version")
runReadOnlyTrxAndRpcInParallel("chain", "get_consensus_parameters", "chain_config")
runReadOnlyTrxAndRpcInParallel("chain", "get_activated_protocol_features", "activated_protocol_features")
runReadOnlyTrxAndRpcInParallel("chain", "get_block", "block_num", expectedValue=1, payload={"block_num_or_id":1})
runReadOnlyTrxAndRpcInParallel("chain", "get_block_info", "block_num", expectedValue=1, payload={"block_num":1})
runReadOnlyTrxAndRpcInParallel("chain", "get_account", "account_name", expectedValue=userAccountName, payload = {"account_name":userAccountName})
runReadOnlyTrxAndRpcInParallel("chain", "get_code", "account_name", expectedValue=testAccountName, payload = {"account_name":testAccountName})
runReadOnlyTrxAndRpcInParallel("chain", "get_code_hash", "account_name", expectedValue=testAccountName, payload = {"account_name":testAccountName})
runReadOnlyTrxAndRpcInParallel("chain", "get_abi", "account_name", expectedValue=testAccountName, payload = {"account_name":testAccountName})
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_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"})
runReadOnlyTrxAndRpcInParallel("chain", "get_required_keys", code=400)
runReadOnlyTrxAndRpcInParallel("chain", "get_transaction_id", code=200, payload = {"ref_block_num":"1"})
runReadOnlyTrxAndRpcInParallel("chain", "push_block", code=202, payload = {"block":"signed_block"})
runReadOnlyTrxAndRpcInParallel("chain", "get_producer_schedule", "active")
runReadOnlyTrxAndRpcInParallel("chain", "get_scheduled_transactions", "transactions", payload = {"json":"true","lower_bound":""})
def netApiTests():
# NET APIs
runReadOnlyTrxAndRpcInParallel("net", "status", code=201, payload = "localhost")
runReadOnlyTrxAndRpcInParallel("net", "connections", code=201)
runReadOnlyTrxAndRpcInParallel("net", "connect", code=201, payload = "localhost")
runReadOnlyTrxAndRpcInParallel("net", "disconnect", code=201, payload = "localhost")
basicTests()
if args.read_only_threads > 0: # Save test time. No need to run other tests if multi-threaded is not enabled
multiReadOnlyTests()
chainApiTests()
netApiTests()
mixedOpsTest()
testSuccessful = True
finally: