提交 19129a2d 编写于 作者: D Daniel Larimer

resovle conflicts with master

......@@ -142,7 +142,7 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.wast.hpp
DEPENDS ${DESTINATION_FOLDER}/${target}.wast
COMMAND echo "const char* ${TARGET_VARIABLE}_wast = R\"=====(" > ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMAND echo "const char* const ${TARGET_VARIABLE}_wast = R\"=====(" > ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMAND cat ${DESTINATION_FOLDER}/${target}.wast >> ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMAND echo ")=====\";" >> ${DESTINATION_FOLDER}/${target}.wast.hpp
COMMENT "Generating ${target}.wast.hpp"
......@@ -152,7 +152,7 @@ macro(add_wast_target target INCLUDE_FOLDERS DESTINATION_FOLDER)
if (EXISTS ${DESTINATION_FOLDER}/${target}.abi )
add_custom_command(OUTPUT ${DESTINATION_FOLDER}/${target}.abi.hpp
DEPENDS ${DESTINATION_FOLDER}/${target}.abi
COMMAND echo "const char* ${TARGET_VARIABLE}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMAND echo "const char* const ${TARGET_VARIABLE}_abi = R\"=====(" > ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMAND cat ${DESTINATION_FOLDER}/${target}.abi >> ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMAND echo ")=====\";" >> ${DESTINATION_FOLDER}/${target}.abi.hpp
COMMENT "Generating ${target}.abi.hpp"
......
......@@ -27,6 +27,12 @@
{"name":"key", "type":"name"},
{"name":"balance", "type":"uint64"}
]
},{
"name": "nonce",
"base": "",
"fields": [
{"name":"value", "type":"string"}
]
}
],
"actions": [{
......@@ -35,6 +41,9 @@
},{
"name": "issue",
"type": "issue"
},{
"name": "nonce",
"type": "nonce"
}
],
"tables": [{
......
......@@ -6,6 +6,7 @@
#include <eosiolib/token.hpp>
#include <eosiolib/db.hpp>
#include <eosiolib/reflect.hpp>
#include <eosiolib/print.hpp>
#include <eosiolib/generic_currency.hpp>
#include <eosiolib/datastream.hpp>
......@@ -25,7 +26,7 @@ namespace eosiosystem {
typename currency::token_type total_cpu_weight;
};
typedef eosio::table64<SystemAccount, N(totalband), total_bandwidth> total_bandwidth;
typedef eosio::table64<SystemAccount, N(totalband), SystemAccount, total_bandwidth> total_bandwidth;
struct delegated_bandwidth {
account_name from;
......@@ -75,7 +76,13 @@ namespace eosiosystem {
EOSLIB_SERIALIZE( delnetbw, (delegator)(receiver)(stake_quantity) )
};
static void on( const delnetbw& del ) {
ACTION( SystemAccount, nonce ) {
eosio::string value;
EOSLIB_SERIALIZE( nonce, (value) );
};
static void on( const delnetbw& del ) {
require_auth( del.from );
// require_account( receiver );
......@@ -90,11 +97,14 @@ namespace eosiosystem {
require_auth( reg.proxy_to_register );
}
static void on( const nonce& ) {
}
static void apply( account_name code, action_name act ) {
if( !eosio::dispatch<contract, regproducer, regproxy>( code, act) ) {
if ( !eosio::dispatch<currency, typename currency::transfer_memo, typename currency::issue>( code, act ) ) {
assert( false, "received unexpected action" );
if( !eosio::dispatch<contract, regproducer, regproxy, nonce>( code, act) ) {
if ( !eosio::dispatch<currency, typename currency::transfer, typename currency::issue>( code, act ) ) {
eosio::print("Unexpected action: ", act, "\n");
assert( false, "received unexpected action");
}
}
} /// apply
......
此差异已折叠。
此差异已折叠。
......@@ -74,8 +74,8 @@ namespace eosio {
* Each user stores their balance in the singleton table under the
* scope of their account name.
*/
typedef table64<code, accounts_table_name, account> accounts;
typedef table64<code, stats_table_name, currency_stats> stats;
typedef table64<code, accounts_table_name, code, account> accounts;
typedef table64<code, stats_table_name, code, currency_stats> stats;
static token_type get_balance( account_name owner ) {
return accounts::get_or_create( token_type::symbol, owner ).balance;
......@@ -115,7 +115,7 @@ namespace eosio {
static void apply( account_name c, action_name act) {
eosio::dispatch<generic_currency, transfer_memo, issue>(c,act);
eosio::dispatch<generic_currency, transfer, issue>(c,act);
}
};
......
......@@ -11,7 +11,7 @@ namespace eosio {
* @tparam SingletonName - the name of this singlton variable
* @tparam T - the type of the singleton
*/
template<account_name Code, uint64_t SingletonName, typename T>
template<account_name Code, uint64_t SingletonName, account_name BillToAccount, typename T>
class singleton
{
public:
......@@ -52,7 +52,7 @@ namespace eosio {
return result;
}
static void set( const T& value = T(), scope_name scope = Code ) {
static void set( const T& value = T(), scope_name scope = Code, account_name b = BillToAccount ) {
auto size = pack_size( value );
char buf[size+ sizeof(SingletonName)];
......@@ -62,7 +62,7 @@ namespace eosio {
ds << SingletonName;
ds << value;
store_i64( scope, SingletonName, buf, sizeof(buf) );
store_i64( scope, SingletonName, b, buf, sizeof(buf) );
}
};
......
......@@ -8,19 +8,19 @@ namespace eosio {
* @tparam TableName - the name of the table with rows of type T
* @tparam T - a struct where the first 8 bytes are used as primary/unique key
*/
template<uint64_t DefaultScope, uint64_t TableName, typename T>
template<uint64_t DefaultScope, uint64_t TableName, uint64_t BillToAccount, typename T>
class table64
{
public:
static bool exists( uint64_t key, scope_name scope = DefaultScope) {
auto read = load_i64( scope, DefaultScope, TableName, (char*)&key, sizeof(key) );
auto read = load_i64( DefaultScope, scope, TableName, (char*)&key, sizeof(key) );
return read > 0;
}
static T get( uint64_t key, scope_name scope = DefaultScope ) {
char temp[1024];
*reinterpret_cast<uint64_t *>(temp) = key;
auto read = load_i64( scope, DefaultScope , TableName, temp, sizeof(temp) );
auto read = load_i64( DefaultScope, scope , TableName, temp, sizeof(temp) );
assert( read > 0, "key does not exist" );
datastream<const char*> ds(temp, read);
......@@ -33,7 +33,7 @@ namespace eosio {
char temp[1024];
*reinterpret_cast<uint64_t *>(temp) = key;
auto read = load_i64( scope, DefaultScope, TableName, temp, sizeof(temp) );
auto read = load_i64( DefaultScope, scope, TableName, temp, sizeof(temp) );
if( read < 0 ) {
set( def, scope );
return def;
......@@ -60,7 +60,7 @@ namespace eosio {
return result;
}
static void set( const T& value = T(), scope_name scope = DefaultScope ) {
static void set( const T& value = T(), scope_name scope = DefaultScope, uint64_t bta = BillToAccount ) {
auto size = pack_size( value );
char buf[size];
assert( size <= 1024, "singleton too big to store" );
......@@ -68,7 +68,7 @@ namespace eosio {
datastream<char*> ds( buf, size );
ds << value;
store_i64( scope, TableName, buf, ds.tellp() );
store_i64( scope, TableName, bta, buf, ds.tellp() );
}
static void remove( uint64_t key, scope_name scope = DefaultScope ) {
......@@ -77,7 +77,7 @@ namespace eosio {
};
template<uint64_t Code, uint64_t TableName, typename T>
template<uint64_t Code, uint64_t TableName, uint64_t BillToAccount, typename T>
class table_i64i64i64 {
public:
table_i64i64i64( uint64_t scope = Code )
......@@ -119,12 +119,12 @@ namespace eosio {
return true;
}
void store( const T& value, account_name bill_to ) {
void store( const T& value, account_name bill_to = BillToAccount ) {
char temp[1024];
datastream<char*> ds(temp, sizeof(temp) );
ds << value;
store_i64i64i64( _scope, TableName, temp, ds.tellp() );
store_i64i64i64( _scope, TableName, bill_to, temp, ds.tellp() );
}
void remove(uint64_t primary_key, uint64_t seconday_key, uint64_t tertiary_key) {
......
......@@ -193,10 +193,10 @@ namespace identity {
}
};
typedef table_i64i64i64<code, N(certs), certrow> certs_table;
typedef table64<code, N(ident), identrow> idents_table;
typedef table64<code, N(account), identity_name> accounts_table;
typedef table64<code, N(trust), trustrow> trust_table;
typedef table_i64i64i64<code, N(certs), code, certrow> certs_table;
typedef table64<code, N(ident), code, identrow> idents_table;
typedef table64<code, N(account), code, identity_name> accounts_table;
typedef table64<code, N(trust), code, trustrow> trust_table;
static identity_name get_claimed_identity( account_name acnt ) {
return accounts_table::get_or_default(acnt, 0);
......
......@@ -49,7 +49,7 @@ namespace identity_test {
}
};
typedef singleton<code, N(result), uint64_t> result_table;
typedef singleton<code, N(result), code, uint64_t> result_table;
static void on( const get_owner_for_identity& c ) {
account_name owner = identity_contract::get_owner_for_identity(c.identity);
......
......@@ -3,7 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/
#include <proxy/proxy.hpp>
#include <eosiolib/native_currency.hpp>
#include <eosio.system/eosio.system.hpp>
#include <eosiolib/transaction.hpp>
namespace proxy {
......@@ -44,9 +44,10 @@ namespace proxy {
template<size_t ...Args>
void apply_onerror( const deferred_transaction& failed_dtrx ) {
eosio::print("starting onerror\n");
const auto self = current_receiver();
config code_config;
assert(configs::get(code_config, self), "Attempting to use unconfigured proxy");
assert(configs::get(code_config, self), "Attempting use of unconfigured proxy");
auto id = code_config.next_id++;
configs::store(code_config, self);
......@@ -63,12 +64,14 @@ extern "C" {
/// The apply method implements the dispatch of events to this contract
void apply( uint64_t code, uint64_t action ) {
if ( code == N(eosio) ) {
if( action == N(transfer) ) {
apply_transfer(code, unpack_action<native_currency::transfer>());
} else if ( action == N(onerror)) {
if ( code == N(eosio)) {
if (action == N(onerror)) {
apply_onerror(deferred_transaction::from_current_action());
}
} else if ( code == N(eosio.system) ) {
if( action == N(transfer) ) {
apply_transfer(code, unpack_action<eosiosystem::contract<N(eosio.system)>::currency::transfer_memo>());
}
} else if (code == current_receiver() ) {
if ( action == N(setowner)) {
apply_setowner(current_action<set_owner>());
......
......@@ -22,6 +22,6 @@ namespace proxy {
uint32_t next_id = 0;
};
using configs = eosio::table<N(proxy),N(proxy),N(configs),config,uint64_t>;
using configs = eosio::table<N(proxy),N(proxy),N(configs),N(proxy),config,uint64_t>;
} /// namespace proxy
......@@ -15,127 +15,127 @@
"name": "inita",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initb",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initc",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initd",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inite",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initf",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initg",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inith",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initi",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initj",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initk",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initl",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initm",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initn",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inito",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initp",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initq",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initr",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "inits",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initt",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
},{
"name": "initu",
"owner_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"active_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"liquid_balance": "1000000.0000 EOS"
"liquid_balance": "1000000.0000 EOS",
"staking_balance": "100.0000 EOS"
}],
"initial_producers": [{
......
......@@ -9,6 +9,7 @@ add_library( eosio_chain
block.cpp
wast_to_wasm.cpp
wasm_interface.cpp
wasm_eosio_constraints.cpp
apply_context.cpp
rate_limiting.cpp
......
......@@ -205,22 +205,22 @@ void apply_context::cancel_deferred( uint32_t sender_id ) {
results.canceled_deferred.emplace_back(receiver, sender_id);
}
const contracts::table_id_object* apply_context::find_table( name scope, name code, name table ) {
const contracts::table_id_object* apply_context::find_table( name code, name scope, name table ) {
require_read_lock(code, scope);
return db.find<table_id_object, contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
return db.find<table_id_object, contracts::by_code_scope_table>(boost::make_tuple(code, scope, table));
}
const contracts::table_id_object& apply_context::find_or_create_table( name scope, name code, name table ) {
const contracts::table_id_object& apply_context::find_or_create_table( name code, name scope, name table ) {
require_read_lock(code, scope);
const auto* existing_tid = db.find<contracts::table_id_object, contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
const auto* existing_tid = db.find<contracts::table_id_object, contracts::by_code_scope_table>(boost::make_tuple(code, scope, table));
if (existing_tid != nullptr) {
return *existing_tid;
}
require_write_lock(scope);
return mutable_db.create<contracts::table_id_object>([&](contracts::table_id_object &t_id){
t_id.scope = scope;
t_id.code = code;
t_id.scope = scope;
t_id.table = table;
});
}
......
......@@ -487,7 +487,8 @@ signed_block chain_controller::_generate_block( block_timestamp_type when,
_finalize_pending_cycle();
if( !(skip & skip_producer_signature) )
FC_ASSERT( producer_obj.signing_key == block_signing_key.get_public_key() );
FC_ASSERT( producer_obj.signing_key == block_signing_key.get_public_key(),
"producer key ${pk}, block key ${bk}", ("pk", producer_obj.signing_key)("bk", block_signing_key.get_public_key()) );
_pending_block->timestamp = when;
_pending_block->producer = producer_obj.owner;
......@@ -1594,6 +1595,8 @@ void chain_controller::update_usage( transaction_metadata& meta, uint32_t act_us
uint128_t virtual_max_uacts = dgpo.virtual_act_bandwidth * config::rate_limiting_precision;
if( !(_skip_flags & genesis_setup) ) {
#warning TODO: restore bandwidth checks
/* setting of bandwidth currently not implemented
FC_ASSERT( (used_ubytes * dgpo.total_net_weight) <= (buo.net_weight * virtual_max_ubytes), "authorizing account '${n}' has insufficient net bandwidth for this transaction",
("n",name(authaccnt.first))
("used_bytes",double(used_ubytes)/1000000.)
......@@ -1608,6 +1611,7 @@ void chain_controller::update_usage( transaction_metadata& meta, uint32_t act_us
("virtual_max_uacts", double(virtual_max_uacts)/1000000. )
("total_cpu_tokens", dgpo.total_cpu_weight)
);
*/
}
// for any transaction not sent by code, update the affirmative last time a given permission was used
......
......@@ -240,7 +240,7 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
create_native_account(config::system_account_name);
// Queue up messages which will run contracts to create the initial accounts
auto init_eosio_sytem = genesis_state_type::initial_account_type(name(config::eosio_system_acount_name).to_string(), 0, 0, genesis.initial_key, genesis.initial_key);
auto init_eosio_sytem = genesis_state_type::initial_account_type(name(config::eosio_system_account_name).to_string(), 0, 0, genesis.eosio_system_key, genesis.eosio_system_key);
genesis.initial_accounts.emplace_back(move(init_eosio_sytem));
for (const auto& acct : genesis.initial_accounts) {
......@@ -256,17 +256,17 @@ std::vector<action> chain_initializer::prepare_database( chain_controller& chain
// Create initial contracts eosio.system
auto wasm = wast_to_wasm(eosio_system_wast);
action eosio_system_setcode({{config::eosio_system_acount_name, config::active_name}},
action eosio_system_setcode({{config::eosio_system_account_name, config::active_name}},
contracts::setcode{
.account = config::eosio_system_acount_name,
.account = config::eosio_system_account_name,
.vmtype = 0,
.vmversion = 0,
.code = bytes(wasm.begin(), wasm.end())
});
auto abi = fc::json::from_string(eosio_system_abi).template as<contracts::abi_def>();
action eosio_system_setabi({{config::eosio_system_acount_name, config::active_name}},
action eosio_system_setabi({{config::eosio_system_account_name, config::active_name}},
contracts::setabi{
.account = config::eosio_system_acount_name,
.account = config::eosio_system_account_name,
.abi = abi
});
messages_to_process.emplace_back(move(eosio_system_setcode));
......
......@@ -40,14 +40,14 @@ void intialize_eosio_tokens(chainbase::database& db, const account_name& system_
}
static void modify_eosio_balance( apply_context& context, const account_name& account, share_type amt) {
const auto& t_id = context.find_or_create_table(account, config::system_account_name, N(currency));
const auto& t_id = context.find_or_create_table(config::system_account_name, account, N(currency));
uint64_t key = N(account);
share_type balance = 0;
context.front_record<key_value_index, by_scope_primary>(t_id, &key, (char *)&balance, sizeof(balance));
balance += amt;
context.store_record<key_value_object>(t_id, &key, (const char *)&balance, sizeof(balance));
context.store_record<key_value_object>(t_id, config::system_account_name, &key, (const char *)&balance, sizeof(balance));
}
......@@ -309,7 +309,7 @@ static const abi_serializer& get_abi_serializer() {
}
static optional<variant> get_pending_recovery(apply_context& context, account_name account ) {
const auto* t_id = context.find_table(account, config::system_account_name, N(recovery));
const auto* t_id = context.find_table(config::system_account_name, account, N(recovery));
if (t_id) {
uint64_t key = account;
int32_t record_size = context.front_record<key_value_index, by_scope_primary>(*t_id, &key, nullptr, 0);
......@@ -330,13 +330,13 @@ static optional<variant> get_pending_recovery(apply_context& context, account_na
static uint32_t get_next_sender_id(apply_context& context) {
context.require_write_lock( config::eosio_auth_scope );
const auto& t_id = context.find_or_create_table(config::eosio_auth_scope, config::system_account_name, N(deferred.seq));
const auto& t_id = context.find_or_create_table(config::system_account_name, config::eosio_auth_scope, N(deferred.seq));
uint64_t key = N(config::eosio_auth_scope);
uint32_t next_serial = 0;
context.front_record<key_value_index, by_scope_primary>(t_id, &key, (char *)&next_serial, sizeof(uint32_t));
uint32_t result = next_serial++;
context.store_record<key_value_object>(t_id, &key, (char *)&next_serial, sizeof(uint32_t));
context.store_record<key_value_object>(t_id, config::system_account_name, &key, (char *)&next_serial, sizeof(uint32_t));
return result;
}
......@@ -423,15 +423,15 @@ void apply_eosio_postrecovery(apply_context& context) {
context.execute_deferred(std::move(dtrx));
const auto& t_id = context.find_or_create_table(account, config::system_account_name, N(recovery));
const auto& t_id = context.find_or_create_table(config::system_account_name, account, N(recovery));
auto data = get_abi_serializer().variant_to_binary("pending_recovery", record_data);
context.store_record<key_value_object>(t_id,&account.value, data.data() + sizeof(uint64_t), data.size() - sizeof(uint64_t));
context.store_record<key_value_object>(t_id, 0, &account.value, data.data() + sizeof(uint64_t), data.size() - sizeof(uint64_t));
context.console_append_formatted("Recovery Started for account ${account} : ${memo}\n", mutable_variant_object()("account", account)("memo", recover_act.memo));
}
static void remove_pending_recovery(apply_context& context, const account_name& account) {
const auto& t_id = context.find_or_create_table(account, config::system_account_name, N(recovery));
const auto& t_id = context.find_or_create_table(config::system_account_name, account, N(recovery));
context.remove_record<key_value_object>(t_id, &account.value);
}
......
......@@ -34,14 +34,14 @@ class apply_context {
void cancel_deferred( uint32_t sender_id );
using table_id_object = contracts::table_id_object;
const table_id_object* find_table( name scope, name code, name table );
const table_id_object& find_or_create_table( name scope, name code, name table );
const table_id_object* find_table( name code, name scope, name table );
const table_id_object& find_or_create_table( name code, name scope, name table );
template <typename ObjectType>
int32_t store_record( const table_id_object& t_id, const typename ObjectType::key_type* keys, const char* value, size_t valuelen );
int32_t store_record( const table_id_object& t_id, const account_name& bta, const typename ObjectType::key_type* keys, const char* value, size_t valuelen );
template <typename ObjectType>
int32_t update_record( const table_id_object& t_id, const typename ObjectType::key_type* keys, const char* value, size_t valuelen );
int32_t update_record( const table_id_object& t_id, const account_name& bta, const typename ObjectType::key_type* keys, const char* value, size_t valuelen );
template <typename ObjectType>
int32_t remove_record( const table_id_object& t_id, const typename ObjectType::key_type* keys );
......@@ -591,7 +591,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename ObjectType>
int32_t apply_context::store_record( const table_id_object& t_id, const typename ObjectType::key_type* keys, const char* value, size_t valuelen ) {
int32_t apply_context::store_record( const table_id_object& t_id, const account_name& bta, const typename ObjectType::key_type* keys, const char* value, size_t valuelen ) {
require_write_lock( t_id.scope );
auto tuple = impl::exact_tuple<ObjectType>::get(t_id, keys);
......@@ -613,7 +613,7 @@ using apply_handler = std::function<void(apply_context&)>;
}
template <typename ObjectType>
int32_t apply_context::update_record( const table_id_object& t_id, const typename ObjectType::key_type* keys, const char* value, size_t valuelen ) {
int32_t apply_context::update_record( const table_id_object& t_id, const account_name& bta, const typename ObjectType::key_type* keys, const char* value, size_t valuelen ) {
require_write_lock( t_id.scope );
auto tuple = impl::exact_tuple<ObjectType>::get(t_id, keys);
......
......@@ -18,7 +18,7 @@ const static uint64_t system_account_name = N(eosio);
const static uint64_t nobody_account_name = N(nobody);
const static uint64_t anybody_account_name = N(anybody);
const static uint64_t producers_account_name = N(producers);
const static uint64_t eosio_system_acount_name = N(eosio.system);
const static uint64_t eosio_system_account_name = N(eosio.system);
const static uint64_t eosio_auth_scope = N(eosio.auth);
const static uint64_t eosio_all_scope = N(eosio.all);
......
......@@ -18,13 +18,13 @@ namespace eosio { namespace chain { namespace contracts {
OBJECT_CTOR(table_id_object)
id_type id;
scope_name scope;
account_name code;
scope_name scope;
table_name table;
uint32_t count = 0; /// the number of elements in the table
};
struct by_scope_code_table;
struct by_code_scope_table;
using table_id_multi_index = chainbase::shared_multi_index_container<
table_id_object,
......@@ -32,10 +32,10 @@ namespace eosio { namespace chain { namespace contracts {
ordered_unique<tag<by_id>,
member<table_id_object, table_id_object::id_type, &table_id_object::id>
>,
ordered_unique<tag<by_scope_code_table>,
ordered_unique<tag<by_code_scope_table>,
composite_key< table_id_object,
member<table_id_object, scope_name, &table_id_object::scope>,
member<table_id_object, account_name, &table_id_object::code>,
member<table_id_object, scope_name, &table_id_object::scope>,
member<table_id_object, table_name, &table_id_object::table>
>
>
......@@ -48,6 +48,7 @@ namespace eosio { namespace chain { namespace contracts {
struct by_scope_secondary;
struct by_scope_tertiary;
struct key_value_object : public chainbase::object<key_value_object_type, key_value_object> {
OBJECT_CTOR(key_value_object, (value))
......@@ -58,7 +59,7 @@ namespace eosio { namespace chain { namespace contracts {
table_id t_id;
uint64_t primary_key;
shared_string value;
uint64_t payer = 0;
account_name payer = 0;
};
using key_value_index = chainbase::shared_multi_index_container<
......@@ -143,6 +144,7 @@ namespace eosio { namespace chain { namespace contracts {
table_id t_id;
shared_string primary_key;
shared_string value;
account_name payer;
};
using keystr_value_index = chainbase::shared_multi_index_container<
......@@ -170,6 +172,7 @@ namespace eosio { namespace chain { namespace contracts {
uint128_t primary_key;
uint128_t secondary_key;
shared_string value;
account_name payer;
};
using key128x128_value_index = chainbase::shared_multi_index_container<
......@@ -207,6 +210,7 @@ namespace eosio { namespace chain { namespace contracts {
uint64_t primary_key;
uint64_t secondary_key;
shared_string value;
account_name payer;
};
using key64x64_value_index = chainbase::shared_multi_index_container<
......@@ -245,6 +249,7 @@ namespace eosio { namespace chain { namespace contracts {
uint64_t secondary_key;
uint64_t tertiary_key;
shared_string value;
account_name payer;
};
using key64x64x64_value_index = chainbase::shared_multi_index_container<
......@@ -291,11 +296,9 @@ CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::key64x64x64_value_object, eosi
CHAINBASE_SET_INDEX_TYPE(eosio::chain::contracts::index64_object, eosio::chain::contracts::index64_index)
FC_REFLECT(eosio::chain::contracts::table_id_object, (id)(scope)(code)(table) )
FC_REFLECT(eosio::chain::contracts::key_value_object, (id)(t_id)(primary_key)(value) )
FC_REFLECT(eosio::chain::contracts::index64_object, (id)(t_id)(primary_key)(secondary_key) )
FC_REFLECT(eosio::chain::contracts::keystr_value_object, (id)(t_id)(primary_key)(value) )
FC_REFLECT(eosio::chain::contracts::key128x128_value_object, (id)(t_id)(primary_key)(secondary_key)(value) )
FC_REFLECT(eosio::chain::contracts::key64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(value) )
FC_REFLECT(eosio::chain::contracts::key64x64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(tertiary_key)(value) )
FC_REFLECT(eosio::chain::contracts::table_id_object, (id)(code)(scope)(table) )
FC_REFLECT(eosio::chain::contracts::key_value_object, (id)(t_id)(primary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::keystr_value_object, (id)(t_id)(primary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::key128x128_value_object, (id)(t_id)(primary_key)(secondary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::key64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(value)(payer) )
FC_REFLECT(eosio::chain::contracts::key64x64x64_value_object, (id)(t_id)(primary_key)(secondary_key)(tertiary_key)(value)(payer) )
......@@ -62,6 +62,7 @@ struct genesis_state_type {
time_point initial_timestamp;
public_key_type initial_key;
public_key_type eosio_system_key;
vector<initial_account_type> initial_accounts;
vector<initial_producer_type> initial_producers;
......
......@@ -20,6 +20,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( unlinkable_block_exception, eosio::chain::chain_exception, 3090000, "unlinkable block" )
FC_DECLARE_DERIVED_EXCEPTION( black_swan_exception, eosio::chain::chain_exception, 3100000, "black swan" )
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, eosio::chain::chain_exception, 3110000, "unknown block" )
FC_DECLARE_DERIVED_EXCEPTION( chain_type_exception, eosio::chain::chain_exception, 3120000, "chain type exception" )
FC_DECLARE_DERIVED_EXCEPTION( block_tx_output_exception, eosio::chain::block_validate_exception, 3020001, "transaction outputs in block do not match transaction outputs from applying block" )
FC_DECLARE_DERIVED_EXCEPTION( block_concurrency_exception, eosio::chain::block_validate_exception, 3020002, "block does not guarantee concurrent exection without conflicts" )
......@@ -52,6 +53,13 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( pop_empty_chain, eosio::chain::undo_database_exception, 3070001, "there are no blocks to pop" )
FC_DECLARE_DERIVED_EXCEPTION( name_type_exception, eosio::chain::chain_type_exception, 3120001, "Invalid name" )
FC_DECLARE_DERIVED_EXCEPTION( public_key_type_exception, eosio::chain::chain_type_exception, 3120002, "Invalid public key" )
FC_DECLARE_DERIVED_EXCEPTION( authority_type_exception, eosio::chain::chain_type_exception, 3120003, "Invalid authority" )
FC_DECLARE_DERIVED_EXCEPTION( action_type_exception, eosio::chain::chain_type_exception, 3120004, "Invalid action" )
FC_DECLARE_DERIVED_EXCEPTION( transaction_type_exception, eosio::chain::chain_type_exception, 3120005, "Invalid transaction" )
FC_DECLARE_DERIVED_EXCEPTION( abi_type_exception, eosio::chain::chain_type_exception, 3120006, "Invalid ABI" )
#define EOS_RECODE_EXC( cause_type, effect_type ) \
catch( const cause_type& e ) \
......
#pragma once
namespace IR {
struct Module;
};
namespace eosio { namespace chain {
//Throws if something in the module violates
void validate_eosio_wasm_constraints(const IR::Module& m);
}}
......@@ -28,8 +28,8 @@ struct wasm_cache::entry {
struct wasm_context {
wasm_context(wasm_cache::entry &code, apply_context& ctx) : code(code), context(ctx)
{
//initialize to minimum bytes and limit this to 32 bit space
sbrk_bytes = (1 << IR::numBytesPerPageLog2) > UINT32_MAX ? UINT32_MAX : 1 << IR::numBytesPerPageLog2;
MemoryInstance* default_mem = Runtime::getDefaultMemory(code.instance);
sbrk_bytes = default_mem ? Runtime::getMemoryNumPages(default_mem) << IR::numBytesPerPageLog2 : 0;
}
wasm_cache::entry& code;
apply_context& context;
......
......@@ -2,15 +2,16 @@
#include <fc/variant.hpp>
#include <boost/algorithm/string.hpp>
#include <fc/exception/exception.hpp>
#include <eosio/chain/exceptions.hpp>
namespace eosio { namespace chain {
void name::set( const char* str ) {
try {
const auto len = strnlen(str,14);
FC_ASSERT( len <= 13 );
EOS_ASSERT( len <= 13, name_type_exception, "Name is longer than 13 characters (${name}) ", ("name",string(str)) );
value = string_to_name(str);
FC_ASSERT( to_string() == string(str), "name not properly normalized", ("name",string(str))("normalized",to_string()) );
EOS_ASSERT( to_string() == string(str), name_type_exception, "Name not properly normalized (name: ${name}, normalized: ${normalized}) ", ("name",string(str))("normalized",to_string()) );
}FC_CAPTURE_AND_RETHROW( (str) ) }
name::operator string()const {
......
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <fc/exception/exception.hpp>
#include <eosio/chain/exceptions.hpp>
#include "IR/Module.h"
#include "IR/Operators.h"
namespace eosio { namespace chain {
using namespace IR;
struct nop_opcode_visitor {
typedef void Result;
#define VISIT_OPCODE(opcode,name,nameString,Imm,...) \
virtual void name(Imm) {}
ENUM_OPERATORS(VISIT_OPCODE)
#undef VISIT_OPCODE
void unknown(Opcode) {
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract encountered unknown opcode");
}
};
struct eosio_constraints_visitor : public nop_opcode_visitor {
///Make this some sort of visitor enum to reduce chance of copy pasta errors (but
// the override declaration makes it somewhat safe)
//While it's possible to access beyond 1MiB by giving an offset that's 1MiB-1 and
// an 8 byte data type, that's fine. There will be enough of a guard on the end
// of 1MiB where it's not a problem
void fail_large_offset(U32 offset) {
if(offset >= 1024*1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract used an invalid large memory store/load offset");
}
void i32_load (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void i64_load (LoadOrStoreImm<3> imm) override { fail_large_offset(imm.offset); }
void i32_load8_s (LoadOrStoreImm<0> imm) override { fail_large_offset(imm.offset); }
void i32_load8_u (LoadOrStoreImm<0> imm) override { fail_large_offset(imm.offset); }
void i32_load16_s (LoadOrStoreImm<1> imm) override { fail_large_offset(imm.offset); }
void i32_load16_u (LoadOrStoreImm<1> imm) override { fail_large_offset(imm.offset); }
void i64_load8_s (LoadOrStoreImm<0> imm) override { fail_large_offset(imm.offset); }
void i64_load8_u (LoadOrStoreImm<0> imm) override { fail_large_offset(imm.offset); }
void i64_load16_s (LoadOrStoreImm<1> imm) override { fail_large_offset(imm.offset); }
void i64_load16_u (LoadOrStoreImm<1> imm) override { fail_large_offset(imm.offset); }
void i64_load32_s (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void i64_load32_u (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void i32_store (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void i64_store (LoadOrStoreImm<3> imm) override { fail_large_offset(imm.offset); }
void i32_store8 (LoadOrStoreImm<0> imm) override { fail_large_offset(imm.offset); }
void i32_store16 (LoadOrStoreImm<1> imm) override { fail_large_offset(imm.offset); }
void i64_store8 (LoadOrStoreImm<0> imm) override { fail_large_offset(imm.offset); }
void i64_store16 (LoadOrStoreImm<1> imm) override { fail_large_offset(imm.offset); }
void i64_store32 (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void f32_load (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void f64_load (LoadOrStoreImm<3> imm) override { fail_large_offset(imm.offset); }
void f32_store (LoadOrStoreImm<2> imm) override { fail_large_offset(imm.offset); }
void f64_store (LoadOrStoreImm<3> imm) override { fail_large_offset(imm.offset); }
#define VISIT_OPCODE(opcode,name,nameString,Imm,...) \
void name(Imm) override { FC_THROW_EXCEPTION(wasm_execution_error, "Smart contracts may not use WASM memory operators"); }
ENUM_MEMORY_OPERATORS(VISIT_OPCODE);
#undef VISIT_OPCODE
};
void validate_eosio_wasm_constraints(const Module& m) {
if(m.memories.defs.size() && m.memories.defs[0].type.size.min > 16)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract initial memory size must be less than or equal to 1MiB");
for(const DataSegment& ds : m.dataSegments) {
if(ds.baseOffset.type != InitializerExpression::Type::i32_const)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract has unexpected memory base offset type");
if(static_cast<uint32_t>(ds.baseOffset.i32) + ds.data.size() > 64*1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract data segments must lie in first 64KiB");
}
if(m.tables.defs.size() && m.tables.defs[0].type.size.min > 1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract table limited to 1024 elements");
unsigned mutable_globals_total_size = 0;
for(const GlobalDef& global_def : m.globals.defs) {
if(!global_def.type.isMutable)
continue;
switch(global_def.type.valueType) {
case ValueType::any:
case ValueType::num:
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract has unexpected global definition value type");
case ValueType::i64:
case ValueType::f64:
mutable_globals_total_size += 4;
case ValueType::i32:
case ValueType::f32:
mutable_globals_total_size += 4;
}
}
if(mutable_globals_total_size > 1024)
FC_THROW_EXCEPTION(wasm_execution_error, "Smart contract has more than 1KiB of mutable globals");
//Some of the OperatorDecoderStream users inside of WAVM track the control stack and quit parsing from
// OperatorDecoderStream when the control stack is empty (since that would indicate unreachable code).
// Not doing that here, yet, since it's not clear it's required for the purpose of the validation
eosio_constraints_visitor visitor;
for(const FunctionDef& fd : m.functions.defs) {
OperatorDecoderStream decoder(fd.code);
while(decoder) {
decoder.decodeOp(visitor);
}
}
}
}}
\ No newline at end of file
......@@ -4,6 +4,7 @@
#include <eosio/chain/exceptions.hpp>
#include <boost/core/ignore_unused.hpp>
#include <eosio/chain/wasm_interface_private.hpp>
#include <eosio/chain/wasm_eosio_constraints.hpp>
#include <fc/exception/exception.hpp>
#include <fc/crypto/sha1.hpp>
#include <fc/io/raw.hpp>
......@@ -221,6 +222,7 @@ namespace eosio { namespace chain {
Serialization::MemoryInputStream stream((const U8 *) wasm_binary, wasm_binary_size);
#warning TODO: restore checktime injection?
WASM::serializeWithInjection(stream, *module);
validate_eosio_wasm_constraints(*module);
root_resolver resolver;
LinkResult link_result = linkModule(*module, resolver);
......@@ -715,35 +717,34 @@ class db_api : public context_aware_api {
using KeyType = typename ObjectType::key_type;
static constexpr int KeyCount = ObjectType::number_of_keys;
using KeyArrayType = KeyType[KeyCount];
using ContextMethodType = int(apply_context::*)(const table_id_object&, const KeyType*, const char*, size_t);
using ContextMethodType = int(apply_context::*)(const table_id_object&, const account_name&, const KeyType*, const char*, size_t);
private:
int call(ContextMethodType method, const scope_name& scope, const name& table, array_ptr<const char> data, size_t data_len) {
const auto& t_id = context.find_or_create_table(scope, context.receiver, table);
int call(ContextMethodType method, const scope_name& scope, const name& table, account_name bta, array_ptr<const char> data, size_t data_len) {
const auto& t_id = context.find_or_create_table(context.receiver, scope, table);
FC_ASSERT(data_len >= KeyCount * sizeof(KeyType), "Data is not long enough to contain keys");
const KeyType* keys = reinterpret_cast<const KeyType *>((const char *)data);
const char* record_data = ((const char*)data) + sizeof(KeyArrayType);
size_t record_len = data_len - sizeof(KeyArrayType);
return (context.*(method))(t_id, keys, record_data, record_len) + sizeof(KeyArrayType);
return (context.*(method))(t_id, bta, keys, record_data, record_len) + sizeof(KeyArrayType);
}
public:
using context_aware_api::context_aware_api;
int store(const scope_name& scope, const name& table, array_ptr<const char> data, size_t data_len) {
auto res = call(&apply_context::store_record<ObjectType>, scope, table, data, data_len);
int store(const scope_name& scope, const name& table, const account_name& bta, array_ptr<const char> data, size_t data_len) {
auto res = call(&apply_context::store_record<ObjectType>, scope, table, bta, data, data_len);
//ilog("STORE [${scope},${code},${table}] => ${res} :: ${HEX}", ("scope",scope)("code",context.receiver)("table",table)("res",res)("HEX", fc::to_hex(data, data_len)));
return res;
}
int update(const scope_name& scope, const name& table, array_ptr<const char> data, size_t data_len) {
return call(&apply_context::update_record<ObjectType>, scope, table, data, data_len);
int update(const scope_name& scope, const name& table, const account_name& bta, array_ptr<const char> data, size_t data_len) {
return call(&apply_context::update_record<ObjectType>, scope, table, bta, data, data_len);
}
int remove(const scope_name& scope, const name& table, const KeyArrayType &keys) {
const auto& t_id = context.find_or_create_table(scope, context.receiver, table);
const auto& t_id = context.find_or_create_table(context.receiver, scope, table);
return context.remove_record<ObjectType>(t_id, keys);
}
};
......@@ -756,8 +757,8 @@ class db_index_api : public context_aware_api {
using ContextMethodType = int(apply_context::*)(const table_id_object&, KeyType*, char*, size_t);
int call(ContextMethodType method, const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
auto maybe_t_id = context.find_table(scope, context.receiver, table);
int call(ContextMethodType method, const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
auto maybe_t_id = context.find_table(context.receiver, scope, table);
if (maybe_t_id == nullptr) {
return -1;
}
......@@ -779,34 +780,34 @@ class db_index_api : public context_aware_api {
public:
using context_aware_api::context_aware_api;
int load(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
auto res = call(&apply_context::load_record<IndexType, Scope>, scope, code, table, data, data_len);
int load(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
auto res = call(&apply_context::load_record<IndexType, Scope>, code, scope, table, data, data_len);
//ilog("LOAD [${scope},${code},${table}] => ${res} :: ${HEX}", ("scope",scope)("code",code)("table",table)("res",res)("HEX", fc::to_hex(data, data_len)));
return res;
}
int front(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::front_record<IndexType, Scope>, scope, code, table, data, data_len);
int front(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::front_record<IndexType, Scope>, code, scope, table, data, data_len);
}
int back(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::back_record<IndexType, Scope>, scope, code, table, data, data_len);
int back(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::back_record<IndexType, Scope>, code, scope, table, data, data_len);
}
int next(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::next_record<IndexType, Scope>, scope, code, table, data, data_len);
int next(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::next_record<IndexType, Scope>, code, scope, table, data, data_len);
}
int previous(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::previous_record<IndexType, Scope>, scope, code, table, data, data_len);
int previous(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::previous_record<IndexType, Scope>, code, scope, table, data, data_len);
}
int lower_bound(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::lower_bound_record<IndexType, Scope>, scope, code, table, data, data_len);
int lower_bound(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::lower_bound_record<IndexType, Scope>, code, scope, table, data, data_len);
}
int upper_bound(const scope_name& scope, const account_name& code, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::upper_bound_record<IndexType, Scope>, scope, code, table, data, data_len);
int upper_bound(const account_name& code, const scope_name& scope, const name& table, array_ptr<char> data, size_t data_len) {
return call(&apply_context::upper_bound_record<IndexType, Scope>, code, scope, table, data, data_len);
}
};
......@@ -1008,8 +1009,8 @@ REGISTER_INTRINSICS(memory_api,
#define DB_METHOD_SEQ(SUFFIX) \
(store, int32_t(int64_t, int64_t, int, int), "store_"#SUFFIX )\
(update, int32_t(int64_t, int64_t, int, int), "update_"#SUFFIX )\
(store, int32_t(int64_t, int64_t, int64_t, int, int), "store_"#SUFFIX ) \
(update, int32_t(int64_t, int64_t, int64_t, int, int), "update_"#SUFFIX ) \
(remove, int32_t(int64_t, int64_t, int), "remove_"#SUFFIX )
#define DB_INDEX_METHOD_SEQ(SUFFIX)\
......
file(GLOB HEADERS "include/eosio/tester/*.hpp")
file(GLOB HEADERS "include/eosio/testing/*.hpp")
## SORT .cpp by most likely to change / break compile
add_library( eosio_testing
......
......@@ -14,10 +14,11 @@ namespace eosio { namespace testing {
*/
class tester {
public:
tester();
tester(bool process_genesis = true);
void close();
void open();
void create_init_accounts();
signed_block produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) );
void produce_blocks( uint32_t n = 1 );
......@@ -37,8 +38,9 @@ namespace eosio { namespace testing {
void create_account( account_name name, asset initial_balance = asset(), account_name creator = N(inita), bool multisig = false );
void create_account( account_name name, string balance = "0.0000 EOS", account_name creator = N(inita), bool multisig = false );
transaction_trace transfer( account_name from, account_name to, asset amount, string memo = "", account_name currency = config::eosio_system_acount_name );
transaction_trace transfer( account_name from, account_name to, string amount, string memo = "", account_name currency = config::eosio_system_acount_name );
transaction_trace push_nonce( account_name from, const string& role, const string& v = "blah" );
transaction_trace transfer( account_name from, account_name to, asset amount, string memo = "", account_name currency = config::eosio_system_account_name );
transaction_trace transfer( account_name from, account_name to, string amount, string memo = "", account_name currency = config::eosio_system_account_name );
template<typename ObjectType, typename IndexBy, typename... Args>
const auto& get( Args&&... args ) {
......
......@@ -5,6 +5,8 @@
#include <eosio/chain/contracts/contract_table_objects.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio.system/eosio.system.abi.hpp>
#include <fc/utility.hpp>
#include <fc/io/json.hpp>
......@@ -15,15 +17,59 @@
namespace eosio { namespace testing {
tester::tester() {
tester::tester(bool process_genesis) {
cfg.block_log_dir = tempdir.path() / "blocklog";
cfg.shared_memory_dir = tempdir.path() / "shared";
cfg.shared_memory_size = 1024*1024*8;
cfg.genesis.initial_timestamp = fc::time_point::from_iso_string("2020-01-01T00:00:00.000");
cfg.genesis.initial_key = get_public_key( config::system_account_name, "active" );
cfg.genesis.eosio_system_key = get_public_key( config::eosio_system_account_name, "active");
open();
if (process_genesis)
create_init_accounts();
}
void tester::create_init_accounts() {
contracts::abi_def eosio_system_abi_def = fc::json::from_string(eosio_system_abi).as<contracts::abi_def>();
chain::contracts::abi_serializer eosio_system_serializer(eosio_system_abi_def);
signed_transaction trx;
set_tapos(trx);
action act;
act.account = config::eosio_system_account_name;
act.name = N(issue);
act.authorization = vector<permission_level>{{config::eosio_system_account_name,config::active_name}};
act.data = eosio_system_serializer.variant_to_binary("issue", fc::json::from_string("{\"to\":\"eosio.system\",\"quantity\":\"1000000000.0000 EOS\"}"));
trx.actions.push_back(act);
set_tapos(trx);
trx.sign( get_private_key( config::eosio_system_account_name, "active" ), chain_id_type() );
push_transaction(trx);
create_account(N(inita), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initb), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initc), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initd), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inite), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initf), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initg), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inith), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initi), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initj), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initk), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initl), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initm), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initn), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inito), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initp), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initq), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initr), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(inits), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initt), "1000000.0000 EOS", config::eosio_system_account_name);
create_account(N(initu), "1000000.0000 EOS", config::eosio_system_account_name);
}
public_key_type tester::get_public_key( name keyname, string role ) const {
......@@ -59,7 +105,7 @@ namespace eosio { namespace testing {
auto next_time = head_time + skip_time;
uint32_t slot = control->get_slot_at_time( next_time );
auto sch_pro = control->get_scheduled_producer(slot);
auto priv_key = get_private_key( sch_pro, "producer" );
auto priv_key = get_private_key( sch_pro, "active" );
return control->generate_block( next_time, sch_pro, priv_key, skip_missed_block_penalty );
}
......@@ -99,6 +145,7 @@ namespace eosio { namespace testing {
set_tapos(trx);
trx.sign( get_private_key( creator, "active" ), chain_id_type() );
push_transaction( trx );
transfer(creator, a, initial_balance);
}
transaction_trace tester::push_transaction( packed_transaction& trx ) {
......@@ -113,25 +160,51 @@ namespace eosio { namespace testing {
void tester::create_account( account_name a, string initial_balance, account_name creator, bool multisig ) {
create_account( a, asset::from_string(initial_balance), creator, multisig );
}
auto resolver = []( tester& t, const account_name& name ) -> optional<contracts::abi_serializer> {
try {
const auto& accnt = t.control->get_database().get<account_object, by_name>(name);
contracts::abi_def abi;
if (contracts::abi_serializer::to_abi(accnt.abi, abi)) {
return contracts::abi_serializer(abi);
}
return optional<contracts::abi_serializer>();
} FC_RETHROW_EXCEPTIONS(error, "Failed to find or parse ABI for ${name}", ("name", name))
};
transaction_trace tester::push_nonce(account_name from, const string& role, const string& v) {
variant pretty_trx = fc::mutable_variant_object()
("actions", fc::variants({
fc::mutable_variant_object()
("account", name(config::eosio_system_account_name))
("name", "nonce")
("authorization", fc::variants({
fc::mutable_variant_object()
("actor", from)
("permission", name(config::owner_name))
}))
("data", fc::mutable_variant_object()
("value", v)
)
})
);
signed_transaction trx;
auto resolve = [this](const account_name& name) -> optional<contracts::abi_serializer> {
return resolver(*this, name);
};
contracts::abi_serializer::from_variant(pretty_trx, trx, resolve);
set_tapos( trx );
trx.sign( get_private_key( from, role ), chain_id_type() );
return push_transaction( trx );
}
transaction_trace tester::transfer( account_name from, account_name to, string amount, string memo, account_name currency ) {
return transfer( from, to, asset::from_string(amount), memo );
}
transaction_trace tester::transfer( account_name from, account_name to, asset amount, string memo, account_name currency ) {
auto resolver = [this]( const account_name& name ) -> optional<contracts::abi_serializer> {
try {
const auto& accnt = control->get_database().get<account_object,by_name>( name );
contracts::abi_def abi;
if (contracts::abi_serializer::to_abi(accnt.abi, abi)) {
return contracts::abi_serializer(abi);
}
return optional<contracts::abi_serializer>();
} FC_RETHROW_EXCEPTIONS(error, "Failed to find or parse ABI for ${name}", ("name", name))
};
variant pretty_trx = fc::mutable_variant_object()
("actions", fc::variants({
fc::mutable_variant_object()
......@@ -145,14 +218,17 @@ namespace eosio { namespace testing {
("data", fc::mutable_variant_object()
("from", from)
("to", to)
("amount", amount)
("quantity", amount)
("memo", memo)
)
})
);
signed_transaction trx;
contracts::abi_serializer::from_variant(pretty_trx, trx, resolver);
auto resolve = [this](const account_name& name) -> optional<contracts::abi_serializer> {
return resolver(*this, name);
};
contracts::abi_serializer::from_variant(pretty_trx, trx, resolve);
set_tapos( trx );
trx.sign( get_private_key( from, name(config::active_name).to_string() ), chain_id_type() );
......@@ -258,7 +334,7 @@ namespace eosio { namespace testing {
}
share_type tester::get_balance( const account_name& account ) const {
return get_currency_balance( config::system_account_name, EOS_SYMBOL, account ).amount;
return get_currency_balance( config::eosio_system_account_name, EOS_SYMBOL, account ).amount;
}
/**
* Reads balance as stored by generic_currency contract
......@@ -267,7 +343,7 @@ namespace eosio { namespace testing {
const symbol& asset_symbol,
const account_name& account ) const {
const auto& db = control->get_database();
const auto* tbl = db.find<contracts::table_id_object, contracts::by_scope_code_table>(boost::make_tuple(account, code, N(account)));
const auto* tbl = db.find<contracts::table_id_object, contracts::by_code_scope_table>(boost::make_tuple(code, account, N(account)));
share_type result = 0;
// the balance is implied to be 0 if either the table or row does not exist
......
......@@ -8,6 +8,15 @@
FC_THROW_EXCEPTION( exc_type, FORMAT, __VA_ARGS__ ); \
FC_MULTILINE_MACRO_END
#define EOS_CAPTURE_AND_RETHROW(exc_type, FORMAT, ... ) \
catch (fc::exception& e) { \
exc_type new_exception(FC_LOG_MESSAGE( error, FORMAT, __VA_ARGS__ )); \
for (const auto& log: e.get_log()) { \
new_exception.append_log(log); \
} \
throw new_exception; \
}
#define EOS_DECLARE_OP_BASE_EXCEPTIONS( op_name ) \
FC_DECLARE_DERIVED_EXCEPTION( \
......
......@@ -620,13 +620,6 @@ namespace WASM
Opcode opcode;
serialize(bodyStream,opcode);
////disallow memory operations
#define VISIT_OPCODE(_,name,...) \
if(opcode == Opcode::name) \
throw FatalSerializationException("memory instructions not allowed");
ENUM_MEMORY_OPERATORS(VISIT_OPCODE)
#undef VISIT_OPCODE
switch(opcode)
{
#define VISIT_OPCODE(_,name,nameString,Imm,...) \
......
......@@ -320,7 +320,7 @@ read_only::get_table_rows_result read_only::get_table_rows( const read_only::get
vector<asset> read_only::get_currency_balance( const read_only::get_currency_balance_params& p )const {
vector<asset> results;
walk_table<contracts::key_value_index, contracts::by_scope_primary>(p.account, p.code, N(account), [&](const contracts::key_value_object& obj){
walk_table<contracts::key_value_index, contracts::by_scope_primary>(p.code, p.account, N(account), [&](const contracts::key_value_object& obj){
share_type balance;
fc::datastream<const char *> ds(obj.value.data(), obj.value.size());
fc::raw::unpack(ds, balance);
......
......@@ -160,8 +160,8 @@ public:
struct get_table_rows_params {
bool json = false;
name scope;
name code;
name scope;
name table;
// string table_type;
string table_key;
......@@ -226,10 +226,10 @@ public:
}
template<typename IndexType, typename Scope, typename Function>
void walk_table(const name& scope, const name& code, const name& table, Function f) const
void walk_table(const name& code, const name& scope, const name& table, Function f) const
{
const auto& d = db.get_database();
const auto* t_id = d.find<chain::contracts::table_id_object, chain::contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
const auto* t_id = d.find<chain::contracts::table_id_object, chain::contracts::by_code_scope_table>(boost::make_tuple(code, scope, table));
if (t_id != nullptr) {
const auto &idx = d.get_index<IndexType, Scope>();
decltype(t_id->id) next_tid(t_id->id._id + 1);
......@@ -251,7 +251,7 @@ public:
abi_serializer abis;
abis.set_abi(abi);
const auto* t_id = d.find<chain::contracts::table_id_object, chain::contracts::by_scope_code_table>(boost::make_tuple(p.scope, p.code, p.table));
const auto* t_id = d.find<chain::contracts::table_id_object, chain::contracts::by_code_scope_table>(boost::make_tuple(p.code, p.scope, p.table));
if (t_id != nullptr) {
const auto &idx = d.get_index<IndexType, Scope>();
decltype(t_id->id) next_tid(t_id->id._id + 1);
......@@ -368,7 +368,7 @@ FC_REFLECT(eosio::chain_apis::read_only::get_block_params, (block_num_or_id))
FC_REFLECT_DERIVED( eosio::chain_apis::read_only::get_block_results, (eosio::chain::signed_block), (id)(block_num)(ref_block_prefix) );
FC_REFLECT( eosio::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) )
FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(scope)(code)(table)(table_key)(lower_bound)(upper_bound)(limit) )
FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_params, (json)(code)(scope)(table)(table_key)(lower_bound)(upper_bound)(limit) )
FC_REFLECT( eosio::chain_apis::read_only::get_table_rows_result, (rows)(more) );
FC_REFLECT( eosio::chain_apis::read_only::get_currency_balance_params, (code)(account)(symbol));
......
......@@ -249,7 +249,7 @@ struct txn_test_gen_plugin_impl {
{
signed_transaction trx;
trx.actions.push_back(act_a_to_b);
trx.actions.emplace_back(action({}, config::eosio_system_acount_name, "nonce", fc::raw::pack(nonce)));
trx.actions.emplace_back(action({}, config::eosio_system_account_name, "nonce", fc::raw::pack(nonce)));
trx.set_reference_block(cc.head_block_id());
trx.expiration = cc.head_block_time() + fc::seconds(30);
trx.sign(a_priv_key, chainid);
......@@ -259,7 +259,7 @@ struct txn_test_gen_plugin_impl {
{
signed_transaction trx;
trx.actions.push_back(act_b_to_a);
trx.actions.emplace_back(action({}, config::eosio_system_acount_name, "nonce", fc::raw::pack(nonce)));
trx.actions.emplace_back(action({}, config::eosio_system_account_name, "nonce", fc::raw::pack(nonce)));
trx.set_reference_block(cc.head_block_id());
trx.expiration = cc.head_block_time() + fc::seconds(30);
trx.sign(b_priv_key, chainid);
......
......@@ -96,9 +96,134 @@ auto smatch_to_variant(const std::smatch& smatch) {
return result;
};
const char* error_advice_3120001 = R"=====(Name should be less than 13 characters and only contains the following symbol .12345abcdefghijklmnopqrstuvwxyz)=====";
const char* error_advice_3120002 = R"=====(Public key should be encoded in base58 and starts with EOS prefix)=====";
const char* error_advice_3120003 = R"=====(Ensure that your authority JSON follows the following format!
{
"threshold":"uint32_t",
"keys":[{ "key":"public_key", "weight":"uint16_t" }],
"accounts":[{
"permission":{ "actor":"account_name", "permission":"permission_name" },
"weight":"uint16_t"
}]
}
e.g.
{
"threshold":"1",
"keys":[{ "key":"EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", "weight":"1" }],
"accounts":[{
"permission":{ "actor":"initb", "permission":"social" },
"weight":"1
}]
})=====";
const char* error_advice_3120004 = R"=====(Ensure that your action JSON follows the contract's abi!)=====";
const char* error_advice_3120005 = R"=====(Ensure that your transaction JSON follows the following format!\n"
{
"ref_block_num":"uint16_t",
"ref_block_prefix":"uint32_t",
"expiration":"YYYY-MM-DDThh:mm",
"region": "uint16_t",
"read_scope":[ "account_name" ],
"write_scope":[ "account_name" ],
"actions":[{
"account":"account_name",
"name":"action_name",
"authorization":[{ "actor":"account_name","permission":"permission_name" }],
"data":"bytes"
}]
}"
e.g.
{
"ref_block_num":"1000",
"ref_block_prefix":"3463702842",
"expiration":"2018-01-23T01:51:05",
"region": "0",
"read_scope":[ "initb", "initc" ],
"write_scope":[ "initb", "initc" ],
"actions":[{
"account":"eosio",
"name":"transfer",
"authorization":[{ "actor":"initb","permission":"active" }],
"data":"000000008093dd74000000000094dd74e80300000000000000"
}]
})=====";
const char* error_advice_3120006 = R"=====(Ensure that your abi JSON follows the following format!
{
"types" : [{ "new_type_name":"type_name", "type":"type_name" }],
"structs" : [{ "name":"type_name", "base":"type_name", "fields": [{ "name":"field_name", "type": "type_name" }] }],
"actions" : [{ "name":"action_name","type":"type_name"}],
"tables" : [{
"name":"table_name",
"index_type":"type_name",
"key_names":[ "field_name" ],
"key_types":[ "type_name" ],
"type":"type_name" "
}]
}
e.g.
{
"types" : [{ "new_type_name":"account_name", "type":"name" }],
"structs" : [
{ "name":"foo", "base":"", "fields": [{ "name":"by", "type": "account_name" }] },\n "
{ "name":"foobar", "base":"", "fields": [{ "name":"by", "type": "account_name" }] }
],
"actions" : [{ "name":"foo","type":"foo"}],
"tables" : [{
"name":"foobar_table",
"index_type":"i64",
"key_names":[ "by" ],
"key_types":[ "account_name" ],
"type":"foobar" "
}]
})=====";
const std::map<int64_t, std::string> error_advice = {
{ 3120001, error_advice_3120001 },
{ 3120002, error_advice_3120002 },
{ 3120003, error_advice_3120003 },
{ 3120004, error_advice_3120004 },
{ 3120005, error_advice_3120005 },
{ 3120006, error_advice_3120006 }
};
namespace eosio { namespace client { namespace help {
bool print_recognized_error_code(const fc::exception& e) {
// eos recognized error code is from 3000000 to 3999999
// refer to libraries/chain/include/eosio/chain/exceptions.hpp
if (e.code() >= 3000000 && e.code() <= 3999999) {
std::string advice, explanation;
// Get advice, if any
const auto advice_itr = error_advice.find(e.code());
if (advice_itr != error_advice.end()) advice = advice_itr->second;
// Get explanation from log, if any
for (auto &log : e.get_log()) {
// Check if there's a log to display
if (!log.get_format().empty()) {
// Localize the message as needed
explanation += "\n " + localized_with_variant(log.get_format().data(), log.get_data());
}
}
if (!explanation.empty()) explanation = std::string("Error Details:") + explanation;
std::cerr << "\033[31m" << "Error " << e.code() << ": " << e.what() << "\033[0m";
if (!advice.empty()) std::cerr << "\n" << "\033[32m" << advice << "\033[0m";
if (!explanation.empty()) std::cerr << "\n" << "\033[33m" << explanation << "\033[0m" << std::endl;
return true;
}
return false;
}
bool print_help_text(const fc::exception& e) {
// Check if the exception has recognized error code
if (print_recognized_error_code(e)) return true;
bool result = false;
// Large input strings to std::regex can cause SIGSEGV, this is a known bug in libstdc++.
// See https://stackoverflow.com/questions/36304204/%D0%A1-regex-segfault-on-long-sequences
......
......@@ -34,7 +34,6 @@ Subcommands:
set Set or update blockchain state
transfer Transfer EOS from account to account
wallet Interact with local wallet
benchmark Configure and execute benchmarks
push Push arbitrary transactions to the blockchain
```
......@@ -228,7 +227,7 @@ uint64_t generate_nonce_value() {
chain::action generate_nonce() {
auto v = generate_nonce_value();
return chain::action( {}, config::eosio_system_acount_name, "nonce", fc::raw::pack(v));
return chain::action( {}, config::eosio_system_account_name, "nonce", fc::raw::pack(v));
}
vector<chain::permission_level> get_account_permissions(const vector<string>& permissions) {
......@@ -361,16 +360,20 @@ struct set_account_permission_subcommand {
} else {
authority auth;
if (boost::istarts_with(authorityJsonOrFile, "EOS")) {
auth = authority(public_key_type(authorityJsonOrFile));
try {
auth = authority(public_key_type(authorityJsonOrFile));
} EOS_CAPTURE_AND_RETHROW(public_key_type_exception, "")
} else {
fc::variant parsedAuthority;
if (boost::istarts_with(authorityJsonOrFile, "{")) {
parsedAuthority = fc::json::from_string(authorityJsonOrFile);
} else {
parsedAuthority = fc::json::from_file(authorityJsonOrFile);
}
auth = parsedAuthority.as<authority>();
try {
if (boost::istarts_with(authorityJsonOrFile, "{")) {
parsedAuthority = fc::json::from_string(authorityJsonOrFile);
} else {
parsedAuthority = fc::json::from_file(authorityJsonOrFile);
}
auth = parsedAuthority.as<authority>();
} EOS_CAPTURE_AND_RETHROW(authority_type_exception, "Fail to parse Authority JSON")
}
name parent;
......@@ -478,18 +481,23 @@ int main( int argc, char** argv ) {
// create account
string creator;
string account_name;
string ownerKey;
string activeKey;
string owner_key_str;
string active_key_str;
bool skip_sign = false;
auto createAccount = create->add_subcommand("account", localized("Create a new account on the blockchain"), false);
createAccount->add_option("creator", creator, localized("The name of the account creating the new account"))->required();
createAccount->add_option("name", account_name, localized("The name of the new account"))->required();
createAccount->add_option("OwnerKey", ownerKey, localized("The owner public key for the account"))->required();
createAccount->add_option("ActiveKey", activeKey, localized("The active public key for the account"))->required();
createAccount->add_option("OwnerKey", owner_key_str, localized("The owner public key for the account"))->required();
createAccount->add_option("ActiveKey", active_key_str, localized("The active public key for the account"))->required();
createAccount->add_flag("-s,--skip-signature", skip_sign, localized("Specify that unlocked wallet keys should not be used to sign transaction"));
add_standard_transaction_options(createAccount);
createAccount->set_callback([&] {
create_account(creator, account_name, public_key_type(ownerKey), public_key_type(activeKey), skip_sign);
public_key_type owner_key, active_key;
try {
owner_key = public_key_type(owner_key_str);
active_key = public_key_type(active_key_str);
} EOS_CAPTURE_AND_RETHROW(public_key_type_exception, "Invalid Public Key")
create_account(creator, account_name, owner_key, active_key, skip_sign);
});
// Get subcommand
......@@ -720,7 +728,9 @@ int main( int argc, char** argv ) {
if (abi->count()) {
contracts::setabi handler;
handler.account = account;
handler.abi = fc::json::from_file(abiPath).as<contracts::abi_def>();
try {
handler.abi = fc::json::from_file(abiPath).as<contracts::abi_def>();
} EOS_CAPTURE_AND_RETHROW(abi_type_exception, "Fail to parse ABI JSON")
actions.emplace_back( vector<chain::permission_level>{{account,"active"}}, handler);
}
......@@ -759,7 +769,7 @@ int main( int argc, char** argv ) {
("quantity", asset(amount))
("memo", memo);
auto args = fc::mutable_variant_object
("code", name(config::eosio_system_acount_name))
("code", name(config::eosio_system_account_name))
("action", "transfer")
("args", transfer);
......@@ -767,7 +777,7 @@ int main( int argc, char** argv ) {
std::vector<chain::action> actions;
actions.emplace_back(vector<chain::permission_level>{{sender,"active"}},
config::eosio_system_acount_name, "transfer", result.get_object()["binargs"].as<bytes>());
config::eosio_system_account_name, "transfer", result.get_object()["binargs"].as<bytes>());
if (tx_force_unique) {
actions.emplace_back( generate_nonce() );
......@@ -923,10 +933,15 @@ int main( int argc, char** argv ) {
add_standard_transaction_options(actionsSubcommand);
actionsSubcommand->set_callback([&] {
ilog("Converting argument to binary...");
fc::variant action_args_var;
try {
action_args_var = fc::json::from_string(data);
} EOS_CAPTURE_AND_RETHROW(action_type_exception, "Fail to parse action JSON")
auto arg= fc::mutable_variant_object
("code", contract)
("action", action)
("args", fc::json::from_string(data));
("args", action_args_var);
auto result = call(json_to_bin_func, arg);
auto accountPermissions = get_account_permissions(permissions);
......@@ -946,7 +961,11 @@ int main( int argc, char** argv ) {
auto trxSubcommand = push->add_subcommand("transaction", localized("Push an arbitrary JSON transaction"));
trxSubcommand->add_option("transaction", trxJson, localized("The JSON of the transaction to push"))->required();
trxSubcommand->set_callback([&] {
auto trx_result = call(push_txn_func, fc::json::from_string(trxJson));
fc::variant trx_var;
try {
trx_var = fc::json::from_string(trxJson);
} EOS_CAPTURE_AND_RETHROW(transaction_type_exception, "Fail to parse transaction JSON")
auto trx_result = call(push_txn_func, trx_var);
std::cout << fc::json::to_pretty_string(trx_result) << std::endl;
});
......@@ -955,7 +974,11 @@ int main( int argc, char** argv ) {
auto trxsSubcommand = push->add_subcommand("transactions", localized("Push an array of arbitrary JSON transactions"));
trxsSubcommand->add_option("transactions", trxsJson, localized("The JSON array of the transactions to push"))->required();
trxsSubcommand->set_callback([&] {
auto trxs_result = call(push_txn_func, fc::json::from_string(trxsJson));
fc::variant trx_var;
try {
trx_var = fc::json::from_string(trxJson);
} EOS_CAPTURE_AND_RETHROW(transaction_type_exception, "Fail to parse transaction JSON")
auto trxs_result = call(push_txn_func, trx_var);
std::cout << fc::json::to_pretty_string(trxs_result) << std::endl;
});
......
......@@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE( schedule_test ) { try {
} FC_LOG_AND_RETHROW() }/// schedule_test
BOOST_AUTO_TEST_CASE( push_block ) { try {
tester test1, test2;
tester test1, test2(false);
for (uint32 i = 0; i < 1000; ++i) {
test2.control->push_block(test1.produce_block());
......@@ -47,7 +47,6 @@ BOOST_AUTO_TEST_CASE( push_block ) { try {
test1.transfer(N(inita), N(alice), asset(1000), "memo");
test2.control->push_block(test1.produce_block());
} FC_LOG_AND_RETHROW() }/// schedule_test
......
......@@ -35,26 +35,13 @@ auto make_vetorecovery(const tester &t, account_name account, permission_name ve
return trx;
}
auto push_nonce(tester &t, const string& role) {
// ensure the old owner key is valid
signed_transaction trx;
auto v = t.control->head_block_num();
trx.actions.emplace_back( vector<permission_level>{{N(alice),config::owner_name}},
config::eosio_system_acount_name, N(nonce),
fc::raw::pack(v) );
t.set_tapos(trx);
trx.sign(t.get_private_key(N(alice), role), chain_id_type());
t.push_transaction(trx);
return trx.id();
};
BOOST_AUTO_TEST_SUITE(recovery_tests)
BOOST_FIXTURE_TEST_CASE( test_recovery_owner, tester ) try {
produce_blocks(1000);
create_account(N(alice), asset::from_string("1000.000 EOS"));
create_account(N(alice), asset::from_string("1000.0000 EOS"));
produce_block();
fc::time_point expected_recovery(fc::seconds(control->head_block_time().sec_since_epoch()) +fc::days(30));
......@@ -73,13 +60,13 @@ BOOST_FIXTURE_TEST_CASE( test_recovery_owner, tester ) try {
auto skip_time = expected_recovery - control->head_block_time() - fc::milliseconds(config::block_interval_ms);
produce_block(skip_time);
control->push_deferred_transactions(true);
auto last_old_nonce_id = push_nonce(*this, "owner");
auto last_old_nonce_id = push_nonce(N(alice), "owner").id;
produce_block();
control->push_deferred_transactions(true);
BOOST_REQUIRE_EQUAL(chain_has_transaction(last_old_nonce_id), true);
BOOST_REQUIRE_THROW(push_nonce(*this, "owner"), tx_missing_sigs);
auto first_new_nonce_id = push_nonce(*this, "owner.recov");
BOOST_REQUIRE_THROW(push_nonce(N(alice), "owner"), tx_missing_sigs);
auto first_new_nonce_id = push_nonce(N(alice), "owner.recov").id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
......@@ -87,7 +74,7 @@ BOOST_FIXTURE_TEST_CASE( test_recovery_owner, tester ) try {
BOOST_FIXTURE_TEST_CASE( test_recovery_owner_veto, tester ) try {
produce_blocks(1000);
create_account(N(alice), asset::from_string("1000.000 EOS"));
create_account(N(alice), asset::from_string("1000.0000 EOS"));
produce_block();
fc::time_point expected_recovery(fc::seconds(control->head_block_time().sec_since_epoch()) +fc::days(30));
......@@ -105,7 +92,7 @@ BOOST_FIXTURE_TEST_CASE( test_recovery_owner_veto, tester ) try {
auto skip_time = expected_recovery - control->head_block_time() - fc::milliseconds(config::block_interval_ms);
produce_block(skip_time);
control->push_deferred_transactions(true);
auto last_old_nonce_id = push_nonce(*this, "owner");
auto last_old_nonce_id = push_nonce(N(alice), "owner").id;
// post the veto at the last possible time
{
......@@ -120,8 +107,8 @@ BOOST_FIXTURE_TEST_CASE( test_recovery_owner_veto, tester ) try {
// make sure the old owner is still in control
BOOST_REQUIRE_THROW(push_nonce(*this, "owner.recov"), tx_missing_sigs);
auto first_new_nonce_id = push_nonce(*this, "owner");
BOOST_REQUIRE_THROW(push_nonce(N(alice), "owner.recov"), tx_missing_sigs);
auto first_new_nonce_id = push_nonce(N(alice), "owner").id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
......@@ -129,7 +116,7 @@ BOOST_FIXTURE_TEST_CASE( test_recovery_owner_veto, tester ) try {
BOOST_FIXTURE_TEST_CASE( test_recovery_bad_creator, tester ) try {
produce_blocks(1000);
create_account(N(alice), asset::from_string("1000.000 EOS"), N(inita), true);
create_account(N(alice), asset::from_string("1000.0000 EOS"), N(inita), true);
produce_block();
fc::time_point expected_recovery(fc::seconds(control->head_block_time().sec_since_epoch()) +fc::days(30));
......@@ -173,7 +160,7 @@ BOOST_FIXTURE_TEST_CASE( test_recovery_bad_creator, tester ) try {
control->push_deferred_transactions(true);
// make sure the recovery goes through
auto first_new_nonce_id = push_nonce(*this, "owner");
auto first_new_nonce_id = push_nonce(N(alice), "owner").id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
......
......@@ -20,26 +20,26 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
{
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("10.0000 EOS") );
FC_ASSERT( dans_balance == asset::from_string("110.0000 EOS") );
}
test.produce_block();
{
const asset dans_balance( test.get_balance( N(dan) ) );
FC_ASSERT( dans_balance == asset::from_string("10.0000 EOS") );
FC_ASSERT( dans_balance == asset::from_string("110.0000 EOS") );
}
/// insufficient funds
BOOST_REQUIRE_THROW(test.transfer(N(dan),N(bart), "11.0000 EOS", "memo"), action_validate_exception);
BOOST_REQUIRE_THROW(test.transfer(N(dan),N(bart), "111.0000 EOS", "memo"), assert_exception);
/// this should succeed because dan has sufficient balance
test.transfer(N(dan),N(bart), "10.0000 EOS", "memo");
test.transfer(N(dan),N(bart), "110.0000 EOS", "memo");
/// verify that bart now has 10.000
/// verify that bart now has 110.000 + 100.000
const asset barts_balance( test.get_balance( N(bart) ) );
FC_ASSERT( barts_balance == asset::from_string("10.0000 EOS") );
FC_ASSERT( barts_balance == asset::from_string("210.0000 EOS") );
{
/// verify that dan now has 0.000
......@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
/// should throw because -1 becomes uint64 max which is greater than balance
BOOST_REQUIRE_THROW(test.transfer(N(bart),N(dan), asset(-1), "memo"), action_validate_exception);
BOOST_REQUIRE_THROW(test.transfer(N(bart),N(dan), asset(-1), "memo"), assert_exception);
auto resolver = [&]( const account_name& name ) -> optional<abi_serializer> {
try {
......@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", name(config::eosio_system_acount_name))
("account", name(config::eosio_system_account_name))
("name", "transfer")
("authorization", variants({
mutable_variant_object()
......@@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
("data", mutable_variant_object()
("from", "bart")
("to", "dan")
("amount", amount)
("quantity", amount)
("memo", "memo")
)
})
......@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", name(config::eosio_system_acount_name))
("account", name(config::eosio_system_account_name))
("name", "transfer")
("authorization", variants({
mutable_variant_object()
......@@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
("data", mutable_variant_object()
("from", "bart")
("to", "dan")
("amount", amount)
("quantity", amount)
("memo", "memo")
)
})
......@@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("account", name(config::eosio_system_acount_name))
("account", name(config::eosio_system_account_name))
("name", "transfer")
("authorization", variants({
mutable_variant_object()
......@@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
("data", mutable_variant_object()
("from", "bart")
("to", "dan")
("amount", amount)
("quantity", amount)
("memo", "memo")
)
})
......
......@@ -304,12 +304,6 @@ const char* my_abi = R"=====(
},{
"name": "abidef_arr",
"type": "abi_def[]"
},{
"name": "nonce",
"type": "nonce"
},{
"name": "nonce_arr",
"type": "nonce[]"
}]
}
],
......@@ -1296,8 +1290,8 @@ BOOST_AUTO_TEST_CASE(general)
{
"publickey" : "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV",
"publickey_arr" : ["EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV","EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV"],
"asset" : "100.00 EOS",
"asset_arr" : ["100.00 EOS","100.00 EOS"],
"asset" : "100.0000 EOS",
"asset_arr" : ["100.0000 EOS","100.0000 EOS"],
"string" : "ola ke ase",
"string_arr" : ["ola ke ase","ola ke desi"],
......@@ -1364,8 +1358,6 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"2",
"expiration":"2021-12-20T15:30",
"region": "1",
"read_scope":["acc1"],
"write_scope":["acc1"],
"actions":[{"scope":"scopename1", "name":"actionname1", "authorization":[{"actor":"acc1","permission":"permname1"}], "data":"445566"}]
},
"transaction_arr": [{
......@@ -1373,16 +1365,12 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"2",
"expiration":"2021-12-20T15:30",
"region": "1",
"read_scope":["acc1"],
"write_scope":["acc1"],
"actions":[{"scope":"acc1", "name":"actionname1", "authorization":[{"actor":"acc1","permission":"permname1"}], "data":"445566"}]
},{
"ref_block_num":"2",
"ref_block_prefix":"3",
"expiration":"2021-12-20T15:40",
"region": "1",
"read_scope":["acc2"],
"write_scope":["acc2"],
"actions":[{"scope":"acc2", "name":"actionname2", "authorization":[{"actor":"acc2","permission":"permname2"}], "data":""}]
}],
"strx": {
......@@ -1390,8 +1378,6 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"2",
"expiration":"2021-12-20T15:30",
"region": "1",
"read_scope":["acc1"],
"write_scope":["acc1"],
"signatures" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"actions":[{"scope":"scopename1", "name":"actionname1", "authorization":[{"actor":"acc1","permission":"permname1"}], "data":"445566"}]
},
......@@ -1400,8 +1386,6 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"2",
"expiration":"2021-12-20T15:30",
"region": "1",
"read_scope":["acc1"],
"write_scope":["acc1"],
"signatures" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"actions":[{"scope":"acc1", "name":"actionname1", "authorization":[{"actor":"acc1","permission":"permname1"}], "data":"445566"}]
},{
......@@ -1409,8 +1393,6 @@ BOOST_AUTO_TEST_CASE(general)
"ref_block_prefix":"3",
"expiration":"2021-12-20T15:40",
"region": "1",
"read_scope":["acc2"],
"write_scope":["acc2"],
"signatures" : ["EOSJzdpi5RCzHLGsQbpGhndXBzcFs8vT5LHAtWLMxPzBdwRHSmJkcCdVu6oqPUQn1hbGUdErHvxtdSTS1YA73BThQFwT77X1U"],
"actions":[{"scope":"acc2", "name":"actionname2", "authorization":[{"actor":"acc2","permission":"permname2"}], "data":""}]
}],
......@@ -1505,14 +1487,6 @@ BOOST_AUTO_TEST_CASE(general)
"structs" : [{"name":"struct1", "base":"base1", "fields": [{"name":"name1", "type": "type1"}, {"name":"name2", "type": "type2"}] }],
"actions" : [{"name":"action1","type":"type1"}],
"tables" : [{"name":"table1","index_type":"indextype1","key_names":["keyname1"],"key_types":["typename1"],"type":"type1"}]
}],
"nonce": {
"value": "nonce1"
},
"nonce_arr": [{
"value": "nonce1"
},{
"value": "nonce2"
}]
}
)=====";
......
......@@ -96,4 +96,78 @@ static const char grow_memory_wast[] = R"=====(
)
)
)
)=====";
\ No newline at end of file
)=====";
static const char biggest_memory_wast[] = R"=====(
(module
(import "env" "sbrk" (func $sbrk (param i32) (result i32)))
(table 0 anyfunc)
(memory $0 16)
(export "memory" (memory $0))
(export "apply" (func $apply))
(func $apply (param $0 i64) (param $1 i64)
(drop
(call $sbrk
(i32.const 1)
)
)
)
)
)=====";
static const char too_big_memory_wast[] = R"=====(
(module
(table 0 anyfunc)
(memory $0 17)
(export "memory" (memory $0))
(export "apply" (func $apply))
(func $apply (param $0 i64) (param $1 i64))
)
)=====";
static const char valid_sparse_table[] = R"=====(
(module
(table 1024 anyfunc)
(func $apply (param $0 i64) (param $1 i64))
(elem (i32.const 0) $apply)
(elem (i32.const 1022) $apply $apply)
)
)=====";
static const char too_big_table[] = R"=====(
(module
(table 1025 anyfunc)
(func $apply (param $0 i64) (param $1 i64))
(elem (i32.const 0) $apply)
(elem (i32.const 1022) $apply $apply)
)
)=====";
static const char memory_init_borderline[] = R"=====(
(module
(memory $0 16)
(data (i32.const 65532) "sup!")
)
)=====";
static const char memory_init_toolong[] = R"=====(
(module
(memory $0 16)
(data (i32.const 65533) "sup!")
)
)=====";
static const char memory_init_negative[] = R"=====(
(module
(memory $0 16)
(data (i32.const -1) "sup!")
)
)=====";
static const char memory_table_import[] = R"=====(
(module
(table (import "foo" "table") 10 anyfunc)
(memory (import "nom" "memory") 0)
)
)=====";
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/contracts/abi_serializer.hpp>
#include <eosio/chain/exceptions.hpp>
#include <asserter/asserter.wast.hpp>
#include <asserter/asserter.abi.hpp>
......@@ -268,8 +269,8 @@ BOOST_FIXTURE_TEST_CASE( test_api_bootstrap, tester ) try {
BOOST_FIXTURE_TEST_CASE( test_proxy, tester ) try {
produce_blocks(2);
create_account( N(proxy), asset::from_string("10000.0000 EOS") );
create_accounts( {N(alice), N(bob)}, asset::from_string("1000.0000 EOS") );
create_account( N(proxy), asset::from_string("0.0000 EOS") );
create_accounts( {N(alice), N(bob)}, asset::from_string("0.0000 EOS") );
transfer( N(inita), N(alice), "10.0000 EOS", "memo" );
produce_block();
......@@ -324,8 +325,8 @@ BOOST_FIXTURE_TEST_CASE( test_proxy, tester ) try {
BOOST_FIXTURE_TEST_CASE( test_deferred_failure, tester ) try {
produce_blocks(2);
create_accounts( {N(proxy), N(bob)}, asset::from_string("10000.0000 EOS") );
create_account( N(alice), asset::from_string("1000.0000 EOS") );
create_accounts( {N(proxy), N(bob)}, asset::from_string("0.0000 EOS") );
create_account( N(alice), asset::from_string("0.0000 EOS") );
transfer( N(inita), N(alice), "10.0000 EOS", "memo" );
produce_block();
......@@ -519,7 +520,7 @@ BOOST_FIXTURE_TEST_CASE( memory_operators, tester ) try {
transfer( N(inita), N(current_memory), "10.0000 EOS", "memo" );
produce_block();
set_code(N(current_memory), current_memory_wast);
BOOST_CHECK_THROW(set_code(N(current_memory), current_memory_wast), eosio::chain::wasm_execution_error);
produce_blocks(1);
{
signed_transaction trx;
......@@ -551,6 +552,173 @@ BOOST_FIXTURE_TEST_CASE( memory_operators, tester ) try {
} FC_LOG_AND_RETHROW()
//Make sure we can create a wasm with 16 pages, but not grow it any
BOOST_FIXTURE_TEST_CASE( big_memory, tester ) try {
produce_blocks(2);
create_accounts( {N(bigmem)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(bigmem), "10.0000 EOS", "memo" );
produce_block();
set_code(N(bigmem), biggest_memory_wast); //should pass, 16 pages is fine
produce_blocks(1);
signed_transaction trx;
action act;
act.account = N(bigmem);
act.name = N();
act.authorization = vector<permission_level>{{N(bigmem),config::active_name}};
trx.actions.push_back(act);
set_tapos(trx);
trx.sign(get_private_key( N(bigmem), "active" ), chain_id_type());
//but should not be able to grow beyond 16th page
BOOST_CHECK_THROW(push_transaction(trx), fc::exception);
produce_blocks(1);
//should fail, 17 blocks is no no
BOOST_CHECK_THROW(set_code(N(bigmem), too_big_memory_wast), eosio::chain::wasm_execution_error);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( table_init_tests, tester ) try {
produce_blocks(2);
create_accounts( {N(tableinit)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(tableinit), "10.0000 EOS", "memo" );
produce_block();
set_code(N(tableinit), valid_sparse_table);
produce_blocks(1);
BOOST_CHECK_THROW(set_code(N(tableinit), too_big_table), eosio::chain::wasm_execution_error);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( memory_init_border, tester ) try {
produce_blocks(2);
create_accounts( {N(memoryborder)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(memoryborder), "10.0000 EOS", "memo" );
produce_block();
set_code(N(memoryborder), memory_init_borderline);
produce_blocks(1);
BOOST_CHECK_THROW(set_code(N(memoryborder), memory_init_toolong), eosio::chain::wasm_execution_error);
BOOST_CHECK_THROW(set_code(N(memoryborder), memory_init_negative), eosio::chain::wasm_execution_error);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( imports, tester ) try {
produce_blocks(2);
create_accounts( {N(imports)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(imports), "10.0000 EOS", "memo" );
produce_block();
//this will fail to link but that's okay; mainly looking to make sure that the constraint
// system doesn't choke when memories and tables exist only as imports
BOOST_CHECK_THROW(set_code(N(imports), memory_table_import), fc::exception);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( lotso_globals, tester ) try {
produce_blocks(2);
create_accounts( {N(globals)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(globals), "10.0000 EOS", "memo" );
produce_block();
std::stringstream ss;
ss << "(module ";
for(unsigned int i = 0; i < 85; ++i)
ss << "(global $g" << i << " (mut i32) (i32.const 0))" << "(global $g" << i+100 << " (mut i64) (i64.const 0))";
//that gives us 1020 bytes of mutable globals
//add a few immutable ones for good measure
for(unsigned int i = 0; i < 10; ++i)
ss << "(global $g" << i+200 << " i32 (i32.const 0))";
set_code(N(globals),
string(ss.str() + ")")
.c_str());
//1024 should pass
set_code(N(globals),
string(ss.str() + "(global $z (mut i32) (i32.const -12)))")
.c_str());
//1028 should fail
BOOST_CHECK_THROW(set_code(N(globals),
string(ss.str() + "(global $z (mut i64) (i64.const -12)))")
.c_str()), eosio::chain::wasm_execution_error);;
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( offset_check, tester ) try {
produce_blocks(2);
create_accounts( {N(offsets)}, asset::from_string("1000.0000 EOS") );
transfer( N(inita), N(offsets), "10.0000 EOS", "memo" );
produce_block();
//floats not tested since they are blocked in the serializer before eosio_constraints
vector<string> loadops = {
"i32.load", "i64.load", /* "f32.load", "f64.load",*/ "i32.load8_s", "i32.load8_u",
"i32.load16_s", "i32.load16_u", "i64.load8_s", "i64.load8_u", "i64.load16_s",
"i64.load16_u", "i64.load32_s", "i64.load32_u"
};
vector<vector<string>> storeops = {
{"i32.store", "i32"},
{"i64.store", "i64"},
/*{"f32.store", "f32"},
{"f64.store", "f64"},*/
{"i32.store8", "i32"},
{"i32.store16", "i32"},
{"i64.store8", "i64"},
{"i64.store16", "i64"},
{"i64.store32", "i64"},
};
for(const string& s : loadops) {
std::stringstream ss;
ss << "(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) ";
ss << "(drop (" << s << " offset=1048574 (i32.const 0)))";
ss << "))";
set_code(N(offsets), ss.str().c_str());
produce_block();
}
for(const vector<string>& o : storeops) {
std::stringstream ss;
ss << "(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) ";
ss << "(" << o[0] << " offset=1048574 (i32.const 0) (" << o[1] << ".const 0))";
ss << "))";
set_code(N(offsets), ss.str().c_str());
produce_block();
}
for(const string& s : loadops) {
std::stringstream ss;
ss << "(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) ";
ss << "(drop (" << s << " offset=1048580 (i32.const 0)))";
ss << "))";
BOOST_CHECK_THROW(set_code(N(offsets), ss.str().c_str()), eosio::chain::wasm_execution_error);
produce_block();
}
for(const vector<string>& o : storeops) {
std::stringstream ss;
ss << "(module (memory $0 16) (func $apply (param $0 i64) (param $1 i64) ";
ss << "(" << o[0] << " offset=1048580 (i32.const 0) (" << o[1] << ".const 0))";
ss << "))";
BOOST_CHECK_THROW(set_code(N(offsets), ss.str().c_str()), eosio::chain::wasm_execution_error);
produce_block();
}
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE(noop, tester) try {
produce_blocks(2);
create_accounts( {N(noop), N(alice)}, asset::from_string("1000.0000 EOS") );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册