提交 f0d9c914 编写于 作者: K Kevin Heifner

Merge commit '08cab1dc' into slim

......@@ -18,6 +18,7 @@ add_subdirectory(exchange)
add_subdirectory(test.inline)
#add_subdirectory(bancor)
add_subdirectory(hello)
add_subdirectory(asserter)
add_subdirectory(infinite)
add_subdirectory(proxy)
......
......@@ -53,10 +53,10 @@
"body": "WAIVER OF CONTRACTUAL RIGHT. The failure of either party to enforce any provision of this Contract shall not be construed as a waiver or limitation of that party's right to subsequently enforce and compel strict compliance with every provision of this Contract. \n\n"
},{
"id": "Arbitrator's Fees to Prevailing Party",
"body": "ARBITRATORS FEES TO PREVAILING PARTY. In any action arising hereunder or any separate action pertaining to the validity of this Agreement, both sides shall pay half the initial cost of arbitration, and the prevailing party shall be awarded reasonable arbitrator's fees and costs.\n \n"
"body": "ARBITRATOR'S FEES TO PREVAILING PARTY. In any action arising hereunder or any separate action pertaining to the validity of this Agreement, both sides shall pay half the initial cost of arbitration, and the prevailing party shall be awarded reasonable arbitrator's fees and costs.\n \n"
},{
"id": "Construction and Interpretation",
"body": "CONSTRUCTION AND INTERPRETATION. The rule requiring construction or interpretation against the drafter is waived. The document shall be deemed as if it were drafted by both parties in a mutual effort. \n \n"
}
]
}
\ No newline at end of file
}
......@@ -31,7 +31,7 @@ NOTICE. Any notice or communication required or permitted under this Contract sh
WAIVER OF CONTRACTUAL RIGHT. The failure of either party to enforce any provision of this Contract shall not be construed as a waiver or limitation of that party's right to subsequently enforce and compel strict compliance with every provision of this Contract.
### CLAUSE NAME: Arbitrator's Fees to Prevailing Party
ARBITRATORS FEES TO PREVAILING PARTY. In any action arising hereunder or any separate action pertaining to the validity of this Agreement, both sides shall pay half the initial cost of arbitration, and the prevailing party shall be awarded reasonable arbitrator's fees and costs.
ARBITRATOR'S FEES TO PREVAILING PARTY. In any action arising hereunder or any separate action pertaining to the validity of this Agreement, both sides shall pay half the initial cost of arbitration, and the prevailing party shall be awarded reasonable arbitrator's fees and costs.
### CLAUSE NAME: Construction and Interpretation
CONSTRUCTION AND INTERPRETATION. The rule requiring construction or interpretation against the drafter is waived. The document shall be deemed as if it were drafted by both parties in a mutual effort.
......
Subproject commit 4f8980c8398a90efe30d94fc7b988c290560e1fd
Subproject commit 7ba0b53193be81548c0ccb3bb4ee64c13a2b9c86
......@@ -13,6 +13,7 @@ namespace eosio { namespace chain { namespace wasm_constraints {
constexpr unsigned maximum_table_elements = 1024; //elements
constexpr unsigned maximum_linear_memory_init = 64*1024; //bytes
constexpr unsigned maximum_func_local_bytes = 8192; //bytes
constexpr unsigned maximum_call_depth = 250; //nested calls
static constexpr unsigned wasm_page_size = 64*1024;
......
#pragma once
#include <eosio/chain/wasm_eosio_binary_ops.hpp>
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <eosio/chain/webassembly/common.hpp>
#include <fc/exception/exception.hpp>
#include <eosio/chain/exceptions.hpp>
......@@ -102,7 +103,6 @@ namespace eosio { namespace chain { namespace wasm_injections {
static void inject( IR::Module& m );
static void initializer();
};
struct memories_injection_visitor {
static void inject( IR::Module& m );
......@@ -207,6 +207,78 @@ namespace eosio { namespace chain { namespace wasm_injections {
};
struct call_depth_check {
static constexpr bool kills = true;
static constexpr bool post = false;
static int32_t global_idx;
static void init() {
global_idx = -1;
}
static void accept( wasm_ops::instr* inst, wasm_ops::visitor_arg& arg ) {
if ( global_idx == -1 ) {
arg.module->globals.defs.push_back({{ValueType::i32, true}, {(I32) eosio::chain::wasm_constraints::maximum_call_depth}});
}
global_idx = arg.module->globals.size()-1;
int32_t assert_idx;
injector_utils::add_import<ResultType::none>(*(arg.module), "call_depth_assert", assert_idx);
wasm_ops::op_types<>::call_t call_assert;
wasm_ops::op_types<>::get_global_t get_global_inst;
wasm_ops::op_types<>::set_global_t set_global_inst;
wasm_ops::op_types<>::i32_eqz_t eqz_inst;
wasm_ops::op_types<>::i32_const_t const_inst;
wasm_ops::op_types<>::i32_add_t add_inst;
wasm_ops::op_types<>::end_t end_inst;
wasm_ops::op_types<>::if__t if_inst;
wasm_ops::op_types<>::else__t else_inst;
call_assert.field = assert_idx;
get_global_inst.field = global_idx;
set_global_inst.field = global_idx;
const_inst.field = -1;
#define INSERT_INJECTED(X) \
tmp = X.pack(); \
injected.insert( injected.end(), tmp.begin(), tmp.end() )
std::vector<U8> injected;
std::vector<U8> tmp;
INSERT_INJECTED(get_global_inst);
INSERT_INJECTED(eqz_inst);
INSERT_INJECTED(if_inst);
INSERT_INJECTED(call_assert);
INSERT_INJECTED(else_inst);
INSERT_INJECTED(const_inst);
INSERT_INJECTED(get_global_inst);
INSERT_INJECTED(add_inst);
INSERT_INJECTED(set_global_inst);
INSERT_INJECTED(end_inst);
/* print the correct call type */
if ( inst->get_code() == wasm_ops::call_code ) {
wasm_ops::op_types<>::call_t* call_inst = reinterpret_cast<wasm_ops::op_types<>::call_t*>(inst);
tmp = call_inst->pack();
}
else {
wasm_ops::op_types<>::call_indirect_t* call_inst = reinterpret_cast<wasm_ops::op_types<>::call_indirect_t*>(inst);
tmp = call_inst->pack();
}
injected.insert( injected.end(), tmp.begin(), tmp.end() );
const_inst.field = 1;
INSERT_INJECTED(get_global_inst);
INSERT_INJECTED(const_inst);
INSERT_INJECTED(add_inst);
INSERT_INJECTED(set_global_inst);
#undef INSERT_INJECTED
arg.new_code->insert( arg.new_code->end(), injected.begin(), injected.end() );
}
};
// float injections
constexpr const char* inject_which_op( uint16_t opcode ) {
switch ( opcode ) {
......@@ -574,8 +646,8 @@ namespace eosio { namespace chain { namespace wasm_injections {
using br_if_t = wasm_ops::br_if <instruction_counter>;
using br_table_t = wasm_ops::br_table <instruction_counter>;
using return__t = wasm_ops::return_ <instruction_counter>;
using call_t = wasm_ops::call <instruction_counter>;
using call_indirect_t = wasm_ops::call_indirect <instruction_counter>;
using call_t = wasm_ops::call <instruction_counter, call_depth_check>;
using call_indirect_t = wasm_ops::call_indirect <instruction_counter, call_depth_check>;
using drop_t = wasm_ops::drop <instruction_counter>;
using select_t = wasm_ops::select <instruction_counter>;
......@@ -792,6 +864,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
injector_utils::init( mod );
instruction_counter::init();
checktime_injector::init();
call_depth_check::init();
}
void inject() {
......
......@@ -57,10 +57,9 @@ namespace eosio { namespace chain {
} catch(Serialization::FatalSerializationException& e) {
EOS_ASSERT(false, wasm_serialization_error, e.message.c_str());
}
wasm_injections::wasm_binary_injection injector(module);
injector.inject();
std::vector<U8> bytes;
try {
Serialization::ArrayOutputStream outstream;
......
......@@ -35,6 +35,7 @@ void max_memory_injection_visitor::inject( Module& m ) {
}
void max_memory_injection_visitor::initializer() {}
int32_t call_depth_check::global_idx = -1;
uint32_t instruction_counter::icnt = 0;
int32_t checktime_injector::checktime_idx = -1;
......
......@@ -49,7 +49,7 @@ namespace eosio { namespace chain {
//there are a couple opportunties for improvement here--
//Easy: Cache the Module created here so it can be reused for instantiaion
//Hard: Kick off instantiation in a separate thread at this location
}
}
void wasm_interface::apply( const digest_type& code_id, const shared_vector<char>& code, apply_context& context ) {
my->get_instantiated_module(code_id, code)->apply(context);
......@@ -1423,6 +1423,108 @@ class compiler_builtins : public context_aware_api {
static constexpr uint32_t SHIFT_WIDTH = (sizeof(uint64_t)*8)-1;
};
class math_api : public context_aware_api {
public:
math_api( apply_context& ctx )
:context_aware_api(ctx,true){}
void diveq_i128(unsigned __int128* self, const unsigned __int128* other) {
fc::uint128_t s(*self);
const fc::uint128_t o(*other);
FC_ASSERT( o != 0, "divide by zero" );
s = s/o;
*self = (unsigned __int128)s;
}
void multeq_i128(unsigned __int128* self, const unsigned __int128* other) {
fc::uint128_t s(*self);
const fc::uint128_t o(*other);
s *= o;
*self = (unsigned __int128)s;
}
uint64_t double_add(uint64_t a, uint64_t b) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
DOUBLE c = DOUBLE(*reinterpret_cast<double *>(&a))
+ DOUBLE(*reinterpret_cast<double *>(&b));
double res = c.convert_to<double>();
return *reinterpret_cast<uint64_t *>(&res);
}
uint64_t double_mult(uint64_t a, uint64_t b) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
DOUBLE c = DOUBLE(*reinterpret_cast<double *>(&a))
* DOUBLE(*reinterpret_cast<double *>(&b));
double res = c.convert_to<double>();
return *reinterpret_cast<uint64_t *>(&res);
}
uint64_t double_div(uint64_t a, uint64_t b) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
DOUBLE divisor = DOUBLE(*reinterpret_cast<double *>(&b));
FC_ASSERT(divisor != 0, "divide by zero");
DOUBLE c = DOUBLE(*reinterpret_cast<double *>(&a)) / divisor;
double res = c.convert_to<double>();
return *reinterpret_cast<uint64_t *>(&res);
}
uint32_t double_eq(uint64_t a, uint64_t b) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
return DOUBLE(*reinterpret_cast<double *>(&a)) == DOUBLE(*reinterpret_cast<double *>(&b));
}
uint32_t double_lt(uint64_t a, uint64_t b) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
return DOUBLE(*reinterpret_cast<double *>(&a)) < DOUBLE(*reinterpret_cast<double *>(&b));
}
uint32_t double_gt(uint64_t a, uint64_t b) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
return DOUBLE(*reinterpret_cast<double *>(&a)) > DOUBLE(*reinterpret_cast<double *>(&b));
}
uint64_t double_to_i64(uint64_t n) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
return DOUBLE(*reinterpret_cast<double *>(&n)).convert_to<int64_t>();
}
uint64_t i64_to_double(int64_t n) {
using DOUBLE = boost::multiprecision::cpp_bin_float_50;
double res = DOUBLE(n).convert_to<double>();
return *reinterpret_cast<uint64_t *>(&res);
}
};
/*
* This api will be removed with fix for `eos #2561`
*/
class call_depth_api : public context_aware_api {
public:
call_depth_api( apply_context& ctx )
:context_aware_api(ctx,true){}
void call_depth_assert() {
FC_THROW_EXCEPTION(wasm_execution_error, "Exceeded call depth maximum");
}
};
REGISTER_INJECTED_INTRINSICS(call_depth_api,
(call_depth_assert, void() )
);
REGISTER_INTRINSICS(math_api,
(diveq_i128, void(int, int) )
(multeq_i128, void(int, int) )
(double_add, int64_t(int64_t, int64_t) )
(double_mult, int64_t(int64_t, int64_t) )
(double_div, int64_t(int64_t, int64_t) )
(double_eq, int32_t(int64_t, int64_t) )
(double_lt, int32_t(int64_t, int64_t) )
(double_gt, int32_t(int64_t, int64_t) )
(double_to_i64, int64_t(int64_t) )
(i64_to_double, int64_t(int64_t) )
);
REGISTER_INTRINSICS(compiler_builtins,
(__ashlti3, void(int, int64_t, int64_t, int) )
(__ashrti3, void(int, int64_t, int64_t, int) )
......
......@@ -883,7 +883,7 @@ namespace eosio {
handshake_initializer::populate(last_handshake_sent);
last_handshake_sent.generation = ++sent_handshake_count;
fc_dlog(logger, "Sending handshake generation ${g} to ${ep}",
("g",last_handshake_sent.generation)("ep", peer_addr));
("g",last_handshake_sent.generation)("ep", peer_name()));
enqueue(last_handshake_sent);
}
......@@ -1416,6 +1416,9 @@ namespace eosio {
if( req.req_blocks.mode == catch_up ) {
c->fork_head = id;
c->fork_head_num = num;
ilog ("got a catch_up notice while in ${s}, fork head num = ${fhn} target LIB = ${lib} next_expected = ${ne}", ("s",stage_str(state))("fhn",num)("lib",sync_known_lib_num)("ne", sync_next_expected_num));
if (state == lib_catchup)
return;
set_state(head_catchup);
}
else {
......@@ -1444,6 +1447,7 @@ namespace eosio {
}
void sync_manager::recv_block (connection_ptr c, const block_id_type &blk_id, uint32_t blk_num, bool accepted) {
fc_dlog(logger," got block ${bn} from ${p}",("bn",blk_num)("p",c->peer_name()));
if (!accepted) {
uint32_t head_num = chain_plug->chain().head_block_num();
if (head_num != last_repeated) {
......@@ -2775,7 +2779,6 @@ namespace eosio {
( "peer-key", bpo::value<vector<string>>()->composing()->multitoken(), "Optional public key of peer allowed to connect. May be used multiple times.")
( "peer-private-key", boost::program_options::value<vector<string>>()->composing()->multitoken(),
"Tuple of [PublicKey, WIF private key] (may specify multiple times)")
( "log-level-net-plugin", bpo::value<string>()->default_value("info"), "Log level: one of 'all', 'debug', 'info', 'warn', 'error', or 'off'")
( "max-clients", bpo::value<int>()->default_value(def_max_clients), "Maximum number of clients from which connections are accepted, use 0 for no limit")
( "connection-cleanup-period", bpo::value<int>()->default_value(def_conn_retry_wait), "number of seconds to wait before cleaning up dead connections")
( "network-version-match", bpo::value<bool>()->default_value(false),
......
......@@ -1234,8 +1234,6 @@ class Cluster(object):
cmdArr.append("--nogen")
nodeosArgs=""
if Utils.Debug:
nodeosArgs += "--log-level-net-plugin debug"
if not self.walletd:
nodeosArgs += " --plugin eosio::wallet_api_plugin"
if self.enableMongo:
......
......@@ -2,20 +2,69 @@
#include <eosio/chain/webassembly/common.hpp>
// These are handcrafted or otherwise tricky to generate with our tool chain
/*
static const char f32_add_wast[] = R"=====(
static const char call_depth_almost_limit_wast[] = R"=====(
(module
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
(type (;0;) (func (param i64)))
(import "env" "printi" (func $printi (type 0)))
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "_foo" (func $_foo))
(export "apply" (func $apply))
(func $_foo (param $0 i32)
(block $label$0
(br_if $label$0
(i32.eqz
(get_local $0)
)
)
(call $_foo
(i32.add
(get_local $0)
(i32.const -1)
)
)
)
)
(func $apply (param $a i64) (param $b i64) (param $c i64)
(call $_foo
(i32.const 249)
)
)
)
)=====";
static const char call_depth_limit_wast[] = R"=====(
(module
(type (;0;) (func (param i64)))
(import "env" "printi" (func $printi (type 0)))
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "_foo" (func $_foo))
(export "apply" (func $apply))
(func $apply (param $0 i64) (param $1 i64)
(call $eosio_assert (i32.eq (i32.trunc_u/f32 (f32.const 0x3f800000)) (i32.const 0x0)) (i32.const 0))
(func $_foo (param $0 i32)
(block $label$0
(br_if $label$0
(i32.eqz
(get_local $0)
)
)
(call $_foo
(i32.add
(get_local $0)
(i32.const -1)
)
)
)
)
(func $apply (param $a i64) (param $b i64) (param $c i64)
(call $_foo
(i32.const 250)
)
)
)
)=====";
*/
static const char aligned_ref_wast[] = R"=====(
(module
......@@ -50,7 +99,6 @@ static const char aligned_ptr_wast[] = R"=====(
)
)=====";
static const char aligned_const_ref_wast[] = R"=====(
(module
(import "env" "sha256" (func $sha256 (param i32 i32 i32)))
......@@ -158,7 +206,6 @@ static const char misaligned_const_ref_wast[] = R"=====(
static const char entry_wast[] = R"=====(
(module
(import "env" "require_auth" (func $require_auth (param i64)))
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
(import "env" "now" (func $now (result i32)))
(table 0 anyfunc)
......@@ -176,7 +223,6 @@ static const char entry_wast[] = R"=====(
)
(func $apply (param $0 i64) (param $1 i64) (param $2 i64)
(block
(call $require_auth (i64.const 6121376101093867520))
(call $eosio_assert
(i32.eq
(i32.load offset=4
......
......@@ -130,6 +130,51 @@ BOOST_FIXTURE_TEST_CASE( basic_test, TESTER ) try {
} FC_LOG_AND_RETHROW() /// basic_test
/**
* Make sure WASM doesn't allow function call depths greater than 250
*/
BOOST_FIXTURE_TEST_CASE( call_depth_test, TESTER ) try {
produce_blocks(2);
create_accounts( {N(check)} );
produce_block();
// test that we can call to 249
{
set_code(N(check), call_depth_almost_limit_wast);
produce_blocks(10);
signed_transaction trx;
action act;
act.account = N(check);
act.name = N();
act.authorization = vector<permission_level>{{N(check),config::active_name}};
trx.actions.push_back(act);
set_transaction_headers(trx);
trx.sign(get_private_key( N(check), "active" ), chain_id_type());
push_transaction(trx);
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
}
// should fail at 250
{
set_code(N(check), call_depth_limit_wast);
produce_blocks(10);
signed_transaction trx;
action act;
act.account = N(check);
act.name = N();
act.authorization = vector<permission_level>{{N(check),config::active_name}};
trx.actions.push_back(act);
set_transaction_headers(trx);
trx.sign(get_private_key( N(check), "active" ), chain_id_type());
BOOST_CHECK_THROW( push_transaction(trx), wasm_execution_error );
produce_blocks(1);
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(trx.id()));
}
} FC_LOG_AND_RETHROW()
/**
* Prove the modifications to global variables are wiped between runs
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册