Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add host functions to support EVM #316

Merged
merged 19 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ install(FILES libraries/fc/include/fc/crypto/webauthn_json/license.txt DESTINATI
install(FILES libraries/fc/src/network/LICENSE.go DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ COMPONENT base)
install(FILES libraries/yubihsm/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.yubihsm COMPONENT base)
install(FILES libraries/eos-vm/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.eos-vm COMPONENT base)
install(FILES libraries/fc/libraries/ff/LICENSE DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/licenses/eosio/ RENAME LICENSE.libff COMPONENT base)

add_custom_target(dev-install
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}"
Expand Down
3 changes: 3 additions & 0 deletions CMakeModules/EosioTester.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ else()
find_library(libsecp256k1 secp256k1 @CMAKE_INSTALL_PREFIX@/lib64 @CMAKE_INSTALL_PREFIX@/lib NO_DEFAULT_PATH)
endif()

find_library(libff ff @CMAKE_INSTALL_PREFIX@/lib64 @CMAKE_INSTALL_PREFIX@/lib NO_DEFAULT_PATH)
find_library(libwasm WASM @CMAKE_INSTALL_PREFIX@/lib64 @CMAKE_INSTALL_PREFIX@/lib NO_DEFAULT_PATH)
find_library(libwast WAST @CMAKE_INSTALL_PREFIX@/lib64 @CMAKE_INSTALL_PREFIX@/lib NO_DEFAULT_PATH)
find_library(libir IR @CMAKE_INSTALL_PREFIX@/lib64 @CMAKE_INSTALL_PREFIX@/lib NO_DEFAULT_PATH)
Expand Down Expand Up @@ -102,6 +103,8 @@ macro(add_eosio_test_executable test_name)
${libchainbase}
${libbuiltins}
${libsecp256k1}
${libff}
elmato marked this conversation as resolved.
Show resolved Hide resolved
@GMP_LIBRARIES@

${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
Expand Down
3 changes: 3 additions & 0 deletions CMakeModules/EosioTesterBuild.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ else()
find_library(libsecp256k1 secp256k1 @CMAKE_BINARY_DIR@/libraries/fc/secp256k1 NO_DEFAULT_PATH)
endif()

find_library(libff ff @CMAKE_BINARY_DIR@/libraries/fc/libraries/ff NO_DEFAULT_PATH)
find_library(libwasm WASM @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WASM NO_DEFAULT_PATH)
find_library(libwast WAST @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/WAST NO_DEFAULT_PATH)
find_library(libir IR @CMAKE_BINARY_DIR@/libraries/wasm-jit/Source/IR NO_DEFAULT_PATH)
Expand Down Expand Up @@ -100,6 +101,8 @@ macro(add_eosio_test_executable test_name)
${libchainbase}
${libbuiltins}
${libsecp256k1}
${libff}
@GMP_LIBRARIES@

${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ apt-get update && apt-get install \
git \
libboost-all-dev \
libcurl4-openssl-dev \
libgmp-dev \
libssl-dev \
libtinfo5 \
libusb-1.0-0-dev \
Expand Down
31 changes: 31 additions & 0 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ struct controller_impl {
set_activation_handler<builtin_protocol_feature_t::configurable_wasm_limits>();
set_activation_handler<builtin_protocol_feature_t::blockchain_parameters>();
set_activation_handler<builtin_protocol_feature_t::get_code_hash>();
set_activation_handler<builtin_protocol_feature_t::get_block_num>();
set_activation_handler<builtin_protocol_feature_t::crypto_primitives>();

self.irreversible_block.connect([this](const block_state_ptr& bsp) {
wasmif.current_lib(bsp->block_num);
Expand Down Expand Up @@ -2940,6 +2942,15 @@ time_point controller::pending_block_time()const {
return my->pending->get_pending_block_header_state().timestamp;
}

uint32_t controller::pending_block_num()const {
EOS_ASSERT( my->pending, block_validate_exception, "no pending block" );

if( std::holds_alternative<completed_block>(my->pending->_block_stage) )
return std::get<completed_block>(my->pending->_block_stage)._block_state->header.block_num();

return my->pending->get_pending_block_header_state().block_num;
}

account_name controller::pending_block_producer()const {
EOS_ASSERT( my->pending, block_validate_exception, "no pending block" );

Expand Down Expand Up @@ -3579,6 +3590,26 @@ void controller_impl::on_activation<builtin_protocol_feature_t::get_code_hash>()
} );
}

template<>
void controller_impl::on_activation<builtin_protocol_feature_t::get_block_num>() {
db.modify( db.get<protocol_state_object>(), [&]( auto& ps ) {
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "get_block_num" );
} );
}

template<>
void controller_impl::on_activation<builtin_protocol_feature_t::crypto_primitives>() {
db.modify( db.get<protocol_state_object>(), [&]( auto& ps ) {
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "alt_bn128_add" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "alt_bn128_mul" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "alt_bn128_pair" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "mod_exp" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "blake2_f" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "sha3" );
add_intrinsic_to_whitelist( ps.whitelisted_intrinsics, "k1_recover" );
} );
}

/// End of protocol feature activation handlers

} } /// eosio::chain
32 changes: 31 additions & 1 deletion libraries/chain/deep_mind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,28 @@
#include <eosio/chain/protocol_feature_manager.hpp>
#include <fc/crypto/hex.hpp>

namespace {

void set_trace_elapsed_to_zero(eosio::chain::action_trace& trace) {
trace.elapsed = {};
}

void set_trace_elapsed_to_zero(eosio::chain::transaction_trace& trace) {
trace.elapsed = {};
for (auto& act_trace : trace.action_traces) {
set_trace_elapsed_to_zero(act_trace);
}
}

}

namespace eosio::chain {

void deep_mind_handler::update_config(deep_mind_config config)
{
_config = std::move(config);
}

void deep_mind_handler::update_logger(const std::string& logger_name)
{
fc::logger::update( logger_name, _logger );
Expand Down Expand Up @@ -101,7 +121,17 @@ namespace eosio::chain {

void deep_mind_handler::on_applied_transaction(uint32_t block_num, const transaction_trace_ptr& trace)
{
auto packed_trace = fc::raw::pack(*trace);
std::vector<char> packed_trace;

if (_config.zero_elapsed) {
transaction_trace trace_copy = *trace;
set_trace_elapsed_to_zero(trace_copy);
packed_trace = fc::raw::pack(trace_copy);

} else {
packed_trace = fc::raw::pack(*trace);
}

fc_dlog(_logger, "APPLIED_TRANSACTION ${block} ${traces}",
("block", block_num)
("traces", fc::to_hex(packed_trace))
Expand Down
1 change: 1 addition & 0 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ namespace eosio { namespace chain {
account_name pending_block_producer()const;
const block_signing_authority& pending_block_signing_authority()const;
std::optional<block_id_type> pending_producer_block_id()const;
uint32_t pending_block_num()const;

const vector<transaction_receipt>& get_pending_trx_receipts()const;

Expand Down
13 changes: 10 additions & 3 deletions libraries/chain/include/eosio/chain/deep_mind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ struct ram_trace {
class deep_mind_handler
{
public:
struct deep_mind_config {
bool zero_elapsed = false; // if true, the elapsed field of transaction and action traces is always set to 0 (for reproducibility)
};

void update_config(deep_mind_config config);

void update_logger(const std::string& logger_name);
enum class operation_qualifier { none, modify, push };

Expand Down Expand Up @@ -85,9 +91,10 @@ class deep_mind_handler
void on_modify_permission(const permission_object& old_permission, const permission_object& new_permission);
void on_remove_permission(const permission_object& permission);
private:
uint32_t _action_id = 0;
ram_trace _ram_trace;
fc::logger _logger;
uint32_t _action_id = 0;
ram_trace _ram_trace;
deep_mind_config _config;
fc::logger _logger;
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ enum class builtin_protocol_feature_t : uint32_t {
// 15 reserved
blockchain_parameters = 16, // matches release 2.1 value
get_code_hash = 17,
configurable_wasm_limits = 18, // configurable_wasm_limits2
configurable_wasm_limits = 18, // configurable_wasm_limits2,
crypto_primitives = 19,
get_block_num = 20,
reserved_private_fork_protocol_features = 500000,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,15 @@ inline constexpr auto get_intrinsic_table() {
"env.set_wasm_parameters_packed",
"env.get_parameters_packed",
"env.set_parameters_packed",
"env.get_code_hash"
"env.get_code_hash",
"env.alt_bn128_add",
"env.alt_bn128_mul",
"env.alt_bn128_pair",
"env.mod_exp",
"env.sha3",
"env.blake2_f",
"env.k1_recover",
"env.get_block_num"
);
}
inline constexpr std::size_t find_intrinsic_index(std::string_view hf) {
Expand Down
11 changes: 11 additions & 0 deletions libraries/chain/include/eosio/chain/webassembly/error_codes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once


namespace eosio { namespace chain { namespace webassembly { namespace error_codes {

enum crypto : int32_t {
none = 0,
fail = 1
};

}}}} // ns eosio::chain::webassembly::error_codes
95 changes: 95 additions & 0 deletions libraries/chain/include/eosio/chain/webassembly/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,15 @@ namespace webassembly {
*/
uint64_t current_time() const;

/**
* Returns the current block number.
*
* @ingroup system
*
* @return current block number.
*/
uint32_t get_block_num() const;

/**
* Returns the transaction's publication time.
*
Expand Down Expand Up @@ -1690,6 +1699,92 @@ namespace webassembly {
*/
int32_t get_action(uint32_t type, uint32_t index, legacy_span<char> buffer) const;

/**
* Host function for addition on the elliptic curve alt_bn128
*
* @ingroup crypto
* @param op1 - a span containing the first operand G1 point.
* @param op2 - a span containing the second operand G1 point.
* @param[out] result - the result op1 + op2.
* @return 1 if there was an error 0 otherwise
*/
int32_t alt_bn128_add(span<const char> op1, span<const char> op2, span<char> result) const;

/**
* Host function for scalar multiplication on the elliptic curve alt_bn128
*
* @ingroup crypto
* @param g1_point - a span containing G1 point.
* @param scalar - a span containing the scalar.
* @param[out] result - g1 * scalar.
* @return 1 if there was an error 0 otherwise
*/
int32_t alt_bn128_mul(span<const char> g1_point, span<const char> scalar, span<char> result) const;

/**
* Host function for optimal ate pairing check on the elliptic curve alt_bn128
*
* @ingroup crypto
* @param g1_g2_pairs - a span containing pairs of G1,G2 points. (2 * 32 bytes) + (2 * 64 bytes)
* @param[out] result - true if pairing evaluates to 1, false otherwise
* @return 1 if there was an error 0 otherwise
*/
int32_t alt_bn128_pair(span<const char> g1_g2_pairs, bool* result) const;

/**
* Big integer modular exponentiation
*
* <BASE> <EXPONENT> <MODULUS>
* returns an output (BASE**EXPONENT) % MODULUS as a byte array {{{{ with the same length as the modulus }}}}
*
* @ingroup crypto
* @param base - a span containing BASE.
* @param exp - a span containing EXPONENT.
* @param modulus - a span containing MODULUS.
* @param[out] out - the result (BASE**EXPONENT) % MODULUS
* @return 1 if there was an error 0 otherwise
*/
int32_t mod_exp(span<const char> base, span<const char> exp, span<const char> modulus, span<char> out) const;

/**
* BLAKE2 compression function `F`
* https://eips.ethereum.org/EIPS/eip-152
* Precompiled contract which implements the compression function F used in the BLAKE2 cryptographic hashing algorithm.
*
* @ingroup crypto
* @param rounds - the number of rounds - 32-bit unsigned big-endian word
* @param state - a span containing the state vector - 8 unsigned 64-bit little-endian words
* @param message - a span containing the message block vector - 16 unsigned 64-bit little-endian words
* @param t0_offset - offset counters - unsigned 64-bit little-endian word
* @param t1_offset - offset counters - unsigned 64-bit little-endian word
* @param final - the final block indicator flag - 8-bit word
* @param[out] result - the result
* @return 1 if there was an error 0 otherwise
*/
int32_t blake2_f( uint32_t rounds, span<const char> state, span<const char> message, span<const char> t0_offset, span<const char> t1_offset, bool final, span<char> result) const;

/**
* Hashes data using SHA3.
*
* @ingroup crypto
* @param data - a span containing the data.
* @param[out] hash_val - the resulting digest.
* @param keccak - use keccak version.
*/
void sha3( span<const char> data, span<char> hash_val, bool keccak) const;

/**
* Calculates the uncompressed public key used for a given signature on a given digest.
*
* @ingroup crypto
* @param signatue - signature.
* @param digest - digest of the message that was signed.
* @param[out] pub - output buffer for the public key result.
*
* @return 1 if there was an error 0 otherwise.
*/
int32_t k1_recover( span<const char> signature, span<const char> digest, span<char> pub) const;

// compiler builtins api
void __ashlti3(legacy_ptr<int128_t>, uint64_t, uint64_t, uint32_t) const;
void __ashrti3(legacy_ptr<int128_t>, uint64_t, uint64_t, uint32_t) const;
Expand Down
27 changes: 27 additions & 0 deletions libraries/chain/protocol_feature_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,33 @@ Allows privileged contracts to get and set subsets of blockchain parameters.
Builtin protocol feature: GET_CODE_HASH

Enables new `get_code_hash` intrinsic which gets the current code hash of an account.
*/
{}
} )
( builtin_protocol_feature_t::crypto_primitives, builtin_protocol_feature_spec{
"CRYPTO_PRIMITIVES",
fc::variant("7d9d4e4365f803e5d5fd2e2bd792026b3995765b4a833f32f8c09d66bd94c705").as<digest_type>(),
// SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
/*
Builtin protocol feature: CRYPTO_PRIMITIVES

Adds new crypto host functions
- Big integer modular exponentiation (mod_exp)
- Add, multiply, and pairing check functions for the alt_bn128 elliptic curve. (alt_bn128_add, alt_bn128_mul, alt_bn128_pair)
- BLAKE2b F compression function (blake2_f)
- sha3 hash function (with Keccak256 support)
- k1_recover (safe ECDSA uncompressed pubkey recover for the secp256k1 curve)
*/
{}
} )
( builtin_protocol_feature_t::get_block_num, builtin_protocol_feature_spec{
"GET_BLOCK_NUM",
fc::variant("e5d7992006e628a38c5e6c28dd55ff5e57ea682079bf41fef9b3cced0f46b491").as<digest_type>(),
// SHA256 hash of the raw message below within the comment delimiters (do not modify message below).
/*
Builtin protocol feature: GET_BLOCK_NUM

Enables new `get_block_num` intrinsic which returns the current block number.
*/
{}
} )
Expand Down
Loading