Skip to content

Commit

Permalink
Merge branch 'main' into update-tests-to-use-leap-dev-install
Browse files Browse the repository at this point in the history
  • Loading branch information
oschwaldp-oci committed Mar 14, 2023
2 parents 1a73eb8 + e8dce9c commit 13fe485
Show file tree
Hide file tree
Showing 18 changed files with 440 additions and 190 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ ee cmake --version
ee mkdir -p contract/build
ee pushd contract
ee pushd build
ee "cmake -DCMAKE_BUILD_TYPE=$DCMAKE_BUILD_TYPE -DWITH_TEST_ACTIONS=$DWITH_TEST_ACTIONS .."
ee "cmake -DCMAKE_BUILD_TYPE=$DCMAKE_BUILD_TYPE -DWITH_TEST_ACTIONS=$DWITH_TEST_ACTIONS -DWITH_LARGE_STACK=$DWITH_TEST_ACTIONS .."
ee make -j "$(nproc)"

# pack
Expand Down
8 changes: 2 additions & 6 deletions .github/workflows/contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ jobs:
if-no-files-found: error

- name: Download Leap - dev binary
if: matrix.DWITH_TEST_ACTIONS == 'on' || matrix.DWITH_TEST_ACTIONS == 'true'
uses: AntelopeIO/asset-artifact-download-action@v2
with:
owner: AntelopeIO
Expand All @@ -86,27 +85,24 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Install Leap
if: matrix.DWITH_TEST_ACTIONS == 'on' || matrix.DWITH_TEST_ACTIONS == 'true'
run: sudo apt-get install -y ./leap*.deb

- name: Build TrustEVM Contract Tests
if: matrix.DWITH_TEST_ACTIONS == 'on' || matrix.DWITH_TEST_ACTIONS == 'true'
run: .github/workflows/build-contract-test.sh

- name: Upload Artifacts
if: matrix.DWITH_TEST_ACTIONS == 'on' || matrix.DWITH_TEST_ACTIONS == 'true'
uses: actions/upload-artifact@v3
with:
name: contract-test.tar.gz
path: contract-test.tar.gz
if-no-files-found: error

- name: Test TrustEVM Contract
if: matrix.DWITH_TEST_ACTIONS == 'on' || matrix.DWITH_TEST_ACTIONS == 'true'
run: .github/workflows/test-contract.sh
env:
DWITH_TEST_ACTIONS: ${{ matrix.DWITH_TEST_ACTIONS }}

- name: Upload Test Metrics
if: matrix.DWITH_TEST_ACTIONS == 'on' || matrix.DWITH_TEST_ACTIONS == 'true'
uses: actions/upload-artifact@v3
with:
name: test-results.xml
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/test-contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ function ee()
}

ee pushd contract/tests/build
ee "ctest -j \"$(nproc)\" --output-on-failure -T Test || :"
if [ "$DWITH_TEST_ACTIONS" = "on" ] || [ "$DWITH_TEST_ACTIONS" = "true" ]; then
ee "ctest -R consensus_tests -j \"$(nproc)\" --output-on-failure -T Test"
else
ee "ctest -E consensus_tests -j \"$(nproc)\" --output-on-failure -T Test"
fi

cp "$(find ./Testing -name 'Test.xml' | sort | tail -n '1')" "../../../${XUNIT_FILENAME:-test-results.xml}"
echo "Done! - ${0##*/}"
74 changes: 34 additions & 40 deletions cmd/block_conversion_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,30 @@
#include "channels.hpp"
#include "abi_utils.hpp"
#include "utils.hpp"
#include "contract_common/evm_common/block_mapping.hpp"

#include <fstream>

#include <silkworm/types/transaction.hpp>
#include <silkworm/trie/vector_root.hpp>
#include <silkworm/common/endian.hpp>

struct block_mapping {

uint64_t genesis_timestamp = 1667688089000000; //us
uint64_t block_interval = 1000000; //us

void set_genesis_timestamp(uint64_t timestamp){
genesis_timestamp = timestamp;
}

void set_block_interval(uint64_t interval) {
block_interval = interval;
}

inline uint32_t timestamp_to_evm_block(uint64_t timestamp) {
if( timestamp < genesis_timestamp ) {
SILK_CRIT << "Invalid timestamp [" << timestamp << ", genesis: " << genesis_timestamp;
assert(timestamp >= genesis_timestamp);
}
return 1 + (timestamp - genesis_timestamp)/block_interval;
}

inline uint64_t evm_block_to_timestamp(uint32_t block_num) {
return genesis_timestamp + block_num * block_interval;
}

};
using sys = sys_plugin;
class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversion_plugin_impl> {
public:
block_conversion_plugin_impl()
: evm_blocks_channel(appbase::app().get_channel<channels::evm_blocks>()){}


uint32_t timestamp_to_evm_block_num(uint64_t timestamp) const {
if (timestamp < bm.value().genesis_timestamp) {
SILK_CRIT << "Invalid timestamp " << timestamp << ", genesis: " << bm->genesis_timestamp;
assert(timestamp >= bm->genesis_timestamp);
}

return bm->timestamp_to_evm_block_num(timestamp);
}

void load_head() {
auto head_header = appbase::app().get_plugin<engine_plugin>().get_head_canonical_header();
if (!head_header) {
Expand All @@ -67,11 +52,20 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
return;
}

bm.set_block_interval(silkworm::endian::load_big_u64(genesis_header->nonce.data())*1e3);
bm.set_genesis_timestamp(genesis_header->timestamp*1e6);
uint64_t block_interval_ms = silkworm::endian::load_big_u64(genesis_header->nonce.data());
// TODO: Consider redefining genesis nonce to be in units of seconds rather than milliseconds? Or just hardcode to 1 second?

if (block_interval_ms == 0 || block_interval_ms % 1000 != 0) {
SILK_CRIT << "Genesis nonce is invalid. Must be a positive multiple of 1000 representing the block interval in milliseconds. "
"Instead got: " << block_interval_ms;
sys::error("Invalid genesis nonce");
return;
}

bm.emplace(genesis_header->timestamp, block_interval_ms/1e3);

SILK_INFO << "Block interval: " << bm.block_interval;
SILK_INFO << "Genesis timestamp: " << bm.genesis_timestamp;
SILK_INFO << "Block interval: " << bm->block_interval;
SILK_INFO << "Genesis timestamp: " << bm->genesis_timestamp;
}

evmc::bytes32 compute_transaction_root(const silkworm::BlockBody& body) {
Expand All @@ -94,7 +88,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
new_block.header.difficulty = 1;
new_block.header.number = num;
new_block.header.gas_limit = 0x7ffffffffff;
new_block.header.timestamp = bm.evm_block_to_timestamp(num)/1e6;
new_block.header.timestamp = bm.value().evm_block_num_to_evm_timestamp(num)/1e6;
new_block.header.transactions_root = silkworm::kEmptyRoot;
//new_block.header.mix_hash
//new_block.header.nonce
Expand Down Expand Up @@ -136,13 +130,13 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
//SILK_INFO << "--Enter Block #" << b->block_num;

// Keep the last block before genesis timestamp
if (b->timestamp <= bm.genesis_timestamp) {
SILK_DEBUG << "Before genesis: " << bm.genesis_timestamp << " Block #" << b->block_num << " timestamp: " << b->timestamp;
if (b->timestamp <= bm.value().genesis_timestamp) {
SILK_DEBUG << "Before genesis: " << bm->genesis_timestamp << " Block #" << b->block_num << " timestamp: " << b->timestamp;
native_blocks.clear();
native_blocks.push_back(*b);
return;
}

// Add received native block to our local reversible chain.
// If the received native block can't be linked we remove the forked blocks until the fork point.
// Also we remove the forked block transactions from the corresponding evm block as they where previously included
Expand All @@ -151,7 +145,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
//SILK_DEBUG << "Fork at Block #" << b->block_num;
const auto& forked_block = native_blocks.back();

while( bm.timestamp_to_evm_block(forked_block.timestamp) < evm_blocks.back().header.number )
while( timestamp_to_evm_block_num(forked_block.timestamp) < evm_blocks.back().header.number )
evm_blocks.pop_back();

auto& last_evm_block = evm_blocks.back();
Expand All @@ -160,7 +154,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
});

native_blocks.pop_back();
if( native_blocks.size() && bm.timestamp_to_evm_block(native_blocks.back().timestamp) == last_evm_block.header.number )
if( native_blocks.size() && timestamp_to_evm_block_num(native_blocks.back().timestamp) == last_evm_block.header.number )
set_upper_bound(last_evm_block, native_blocks.back());
}

Expand All @@ -172,7 +166,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi

// Process the last native block received.
// We extend the evm chain if necessary up until the block where the received block belongs
auto evm_num = bm.timestamp_to_evm_block(b->timestamp);
auto evm_num = timestamp_to_evm_block_num(b->timestamp);
//SILK_INFO << "Expecting evm number: " << evm_num;

while(evm_blocks.back().header.number < evm_num) {
Expand Down Expand Up @@ -213,11 +207,11 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
}

if( lib_timestamp ) {
auto evm_lib = bm.timestamp_to_evm_block(*lib_timestamp) - 1;
auto evm_lib = timestamp_to_evm_block_num(*lib_timestamp) - 1;
//SILK_DEBUG << "EVM LIB: #" << evm_lib;

// Remove irreversible native blocks
while(bm.timestamp_to_evm_block(native_blocks.front().timestamp) < evm_lib) {
while(timestamp_to_evm_block_num(native_blocks.front().timestamp) < evm_lib) {
//SILK_DEBUG << "Remove IRR native: #" << native_blocks.front().block_num;
native_blocks.pop_front();
}
Expand All @@ -244,7 +238,7 @@ class block_conversion_plugin_impl : std::enable_shared_from_this<block_conversi
std::list<silkworm::Block> evm_blocks;
channels::evm_blocks::channel_type& evm_blocks_channel;
channels::native_blocks::channel_type::handle native_blocks_subscription;
block_mapping bm;
std::optional<evm_common::block_mapping> bm;
};

block_conversion_plugin::block_conversion_plugin() : my(new block_conversion_plugin_impl()) {}
Expand Down
52 changes: 52 additions & 0 deletions cmd/contract_common/evm_common/block_mapping.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include <cstdint>

namespace evm_common {

struct block_mapping {

/**
* @brief Construct object that maps from Antelope timestamp to EVM block number and timestamp
*
* @param genesis_timestamp_sec - the EVM genesis timestamp in seconds
* @param block_interval_sec - time interval between consecutive EVM blocks in seconds (must be positive)
*
* @note The timestamp of the Antelope block containing the init action rounded down to the nearest second must equal genesis_timestamp_sec.
*/
block_mapping(uint64_t genesis_timestamp_sec, uint32_t block_interval_sec = 1)
: block_interval(block_interval_sec == 0 ? 1 : block_interval_sec),
genesis_timestamp(genesis_timestamp_sec)
{}

const uint64_t block_interval; // seconds
const uint64_t genesis_timestamp; // seconds

/**
* @brief Map Antelope timestamp to EVM block num
*
* @param timestamp - Antelope timestamp in microseconds
* @return mapped EVM block number (returns 0 for all timestamps prior to the genesis timestamp)
*/
inline uint32_t timestamp_to_evm_block_num(uint64_t timestamp_us) const {
uint64_t timestamp = timestamp_us / 1e6; // map Antelope block timestamp to EVM block timestamp
if( timestamp < genesis_timestamp ) {
// There should not be any transactions prior to the init action.
// But any entity with an associated timestamp prior to the genesis timestamp can be considered as part of the genesis block.
return 0;
}
return 1 + (timestamp - genesis_timestamp) / block_interval;
}

/**
* @brief Map EVM block num to EVM block timestamp
*
* @param block_num - EVM block number
* @return EVM block timestamp associated with the given EVM block number
*/
inline uint64_t evm_block_num_to_evm_timestamp(uint32_t block_num) const {
return genesis_timestamp + block_num * block_interval;
}
};

} // namespace evm_common
4 changes: 4 additions & 0 deletions contract/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ option(WITH_TEST_ACTIONS
option(WITH_LOGTIME
"Use `logtime` instrisic to log the time spent in transaction execution" OFF)

option(WITH_LARGE_STACK
"Build with 50MB of stack size, needed for unit tests" OFF)

ExternalProject_Add(
evm_runtime_project
SOURCE_DIR ${CMAKE_SOURCE_DIR}/src
Expand All @@ -21,6 +24,7 @@ ExternalProject_Add(
-DCMAKE_TOOLCHAIN_FILE=${CDT_ROOT}/lib/cmake/cdt/CDTWasmToolchain.cmake
-DWITH_TEST_ACTIONS=${WITH_TEST_ACTIONS}
-DWITH_LOGTIME=${WITH_LOGTIME}
-DWITH_LARGE_STACK=${WITH_LARGE_STACK}
UPDATE_COMMAND ""
PATCH_COMMAND ""
TEST_COMMAND ""
Expand Down
8 changes: 4 additions & 4 deletions contract/include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <evm_runtime/types.hpp>

#include <silkworm/types/block.hpp>
#include <silkworm/consensus/engine.hpp>
#include <silkworm/execution/processor.hpp>
#ifdef WITH_TEST_ACTIONS
#include <evm_runtime/test/block_info.hpp>
#endif
Expand Down Expand Up @@ -44,7 +44,7 @@ CONTRACT evm_contract : public contract {
bool gc(uint32_t max);

#ifdef WITH_TEST_ACTIONS
ACTION testtx( const bytes& rlptx, const evm_runtime::test::block_info& bi );
ACTION testtx( const std::optional<bytes>& orlptx, const evm_runtime::test::block_info& bi );
ACTION updatecode( const bytes& address, uint64_t incarnation, const bytes& code_hash, const bytes& code);
ACTION updateaccnt(const bytes& address, const bytes& initial, const bytes& current);
ACTION updatestore(const bytes& address, uint64_t incarnation, const bytes& location, const bytes& initial, const bytes& current);
Expand Down Expand Up @@ -88,8 +88,8 @@ CONTRACT evm_contract : public contract {
check((_config.get().status & static_cast<uint32_t>(status_flags::frozen)) == 0, "contract is frozen");
}

void push_trx(eosio::name ram_payer, silkworm::Block& block, const bytes& rlptx, silkworm::consensus::IEngine& engine, const silkworm::ChainConfig& chain_config);
silkworm::Receipt execute_tx( silkworm::Block& block, const bytes& rlptx, silkworm::ExecutionProcessor& ep );
};


} //evm_runtime
} //evm_runtime
42 changes: 33 additions & 9 deletions contract/include/evm_runtime/print_tracer.hpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,47 @@
#pragma once

#include <evmc/instructions.h>
namespace evm_runtime {

struct print_tracer : EvmTracer {

void on_execution_start(evmc_revision rev, const evmc_message& msg, evmone::bytes_view code) override {
const char* const* opcode_names_ = nullptr;

void on_execution_start(evmc_revision rev, const evmc_message& msg, evmone::bytes_view code) noexcept override {
eosio::print("TRACE: start\n");
};
if (opcode_names_ == nullptr) {
opcode_names_ = evmc_get_instruction_names_table(rev);
}
}

void on_instruction_start(uint32_t pc, const evmone::ExecutionState& state,
const IntraBlockState& intra_block_state) override {
eosio::print("TRACE[inst] ", uint64_t(pc), ": ", uint64_t(state.gas_left), "\n");
std::string get_opcode_name(const char* const* names, std::uint8_t opcode) {
const auto name = names[opcode];
return (name != nullptr) ?name : "opcode 0x" + evmc::hex(opcode) + " not defined";
}

};
void on_instruction_start(uint32_t pc, const intx::uint256* stack_top, int stack_height,
const evmone::ExecutionState& state,
const IntraBlockState& intra_block_state) noexcept override {
const auto opcode = state.code[pc];
auto opcode_name = get_opcode_name(opcode_names_, opcode);
eosio::print(opcode_name.c_str(), "\n");
}

void on_execution_end(const evmc_result& result, const IntraBlockState& intra_block_state) override {
void on_execution_end(const evmc_result& result, const IntraBlockState& intra_block_state) noexcept override {
eosio::print("TRACE: end\n");
}

};
void on_creation_completed(const evmc_result& result, const IntraBlockState& intra_block_state) noexcept override {

}

void on_precompiled_run(const evmc_result& result, int64_t gas,
const IntraBlockState& intra_block_state) noexcept override {

}

void on_reward_granted(const CallResult& result, const IntraBlockState& intra_block_state) noexcept override {

}

};
} //namespace evm_runtime
7 changes: 6 additions & 1 deletion contract/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ add_contract( evm_contract evm_runtime ${SOURCES})

target_include_directories( evm_runtime PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../include
${CMAKE_CURRENT_SOURCE_DIR}/../../cmd/contract_common
${CMAKE_CURRENT_SOURCE_DIR}/../external/intx/include
${CMAKE_CURRENT_SOURCE_DIR}/../external/ethash/include
${CMAKE_CURRENT_SOURCE_DIR}/../external/GSL/include
Expand All @@ -81,4 +82,8 @@ target_include_directories( evm_runtime PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../silkworm/third_party/evmone/evmc/include
)

target_link_options(evm_runtime PUBLIC -stack-size=20480)
if (WITH_LARGE_STACK)
target_link_options(evm_runtime PUBLIC --stack-size=50000000)
else()
target_link_options(evm_runtime PUBLIC --stack-size=20480)
endif()
Loading

0 comments on commit 13fe485

Please sign in to comment.