未验证 提交 2fb4ecfc 编写于 作者: G Greg Lee 提交者: GitHub

Merge branch 'slim' into 2628

......@@ -7,7 +7,6 @@
#include <eosio/chain/generated_transaction_object.hpp>
#include <eosio/chain/authorization_manager.hpp>
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/scope_sequence_object.hpp>
#include <eosio/chain/account_object.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <boost/container/flat_set.hpp>
......
......@@ -6,7 +6,6 @@
#include <eosio/chain/fork_database.hpp>
#include <eosio/chain/account_object.hpp>
#include <eosio/chain/scope_sequence_object.hpp>
#include <eosio/chain/block_summary_object.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/contract_table_objects.hpp>
......@@ -104,9 +103,12 @@ struct controller_impl {
SET_APP_HANDLER( eosio, eosio, deleteauth );
SET_APP_HANDLER( eosio, eosio, linkauth );
SET_APP_HANDLER( eosio, eosio, unlinkauth );
/*
SET_APP_HANDLER( eosio, eosio, postrecovery );
SET_APP_HANDLER( eosio, eosio, passrecovery );
SET_APP_HANDLER( eosio, eosio, vetorecovery );
*/
SET_APP_HANDLER( eosio, eosio, canceldelay );
fork_db.irreversible.connect( [&]( auto b ) {
......@@ -208,7 +210,6 @@ struct controller_impl {
db.add_index<block_summary_multi_index>();
db.add_index<transaction_multi_index>();
db.add_index<generated_transaction_multi_index>();
db.add_index<scope_sequence_multi_index>();
authorization.add_indices();
resource_limits.add_indices();
......
......@@ -53,7 +53,6 @@ void apply_eosio_newaccount(apply_context& context) {
EOS_ASSERT( validate(create.owner), action_validate_exception, "Invalid owner authority");
EOS_ASSERT( validate(create.active), action_validate_exception, "Invalid active authority");
EOS_ASSERT( validate(create.recovery), action_validate_exception, "Invalid recovery authority");
auto& db = context.db;
......@@ -74,7 +73,7 @@ void apply_eosio_newaccount(apply_context& context) {
"Cannot create account named ${name}, as that name is already taken",
("name", create.name));
for( const auto& auth : { create.owner, create.active, create.recovery } ){
for( const auto& auth : { create.owner, create.active } ){
validate_authority_precondition( context, auth );
}
......@@ -133,8 +132,6 @@ void apply_eosio_setcode(apply_context& context) {
/** TODO: consider whether a microsecond level local timestamp is sufficient to detect code version changes*/
#warning TODO: update setcode message to include the hash, then validate it in validate
a.code_version = code_id;
// Added resize(0) here to avoid bug in boost vector container
a.code.resize( 0 );
a.code.resize( code_size );
a.last_code_update = context.control.pending_block_time();
memcpy( a.code.data(), act.code.data(), code_size );
......@@ -360,22 +357,6 @@ static const abi_serializer& get_abi_serializer() {
return *_abi_serializer;
}
static optional<variant> get_pending_recovery(apply_context& context, account_name account ) {
const uint64_t id = account;
const auto table = N(recovery);
const auto iter = context.db_find_i64(config::system_account_name, account, table, id);
if (iter != -1) {
const auto buffer_size = context.db_get_i64(iter, nullptr, 0);
bytes value(buffer_size);
const auto written_size = context.db_get_i64(iter, value.data(), buffer_size);
assert(written_size == buffer_size);
return get_abi_serializer().binary_to_variant("pending_recovery", value);
}
return optional<variant_object>();
}
static auto get_account_creation(const apply_context& context, const account_name& account) {
auto const& accnt = context.db.get<account_object, by_name>(account);
......@@ -391,138 +372,6 @@ static auto get_permission_last_used(const apply_context& context, const account
return optional<time_point>();
};
void apply_eosio_postrecovery(apply_context& context) {
// context.require_write_lock( config::eosio_auth_scope );
FC_ASSERT(context.act.authorization.size() == 1, "Recovery Message must have exactly one authorization");
auto recover_act = context.act.data_as<postrecovery>();
const auto &auth = context.act.authorization.front();
const auto& account = recover_act.account;
// context.require_write_lock(account);
FC_ASSERT(!get_pending_recovery(context, account), "Account ${account} already has a pending recovery request!", ("account",account));
fc::microseconds delay_lock;
auto now = context.control.pending_block_time();
if (auth.actor == account && auth.permission == N(active)) {
// process owner recovery from active
delay_lock = fc::days(30);
} else {
// process lost password
auto owner_last_used = get_permission_last_used(context, account, N(owner));
auto active_last_used = get_permission_last_used(context, account, N(active));
if (!owner_last_used || !active_last_used) {
auto account_creation = get_account_creation(context, account);
if (!owner_last_used) {
owner_last_used.emplace(account_creation);
}
if (!active_last_used) {
active_last_used.emplace(account_creation);
}
}
FC_ASSERT(*owner_last_used <= now - fc::days(30), "Account ${account} has had owner key activity recently and cannot be recovered yet!", ("account",account));
FC_ASSERT(*active_last_used <= now - fc::days(30), "Account ${account} has had active key activity recently and cannot be recovered yet!", ("account",account));
delay_lock = fc::days(7);
}
variant update;
fc::to_variant( updateauth {
.account = account,
.permission = N(owner),
.parent = 0,
.auth = recover_act.auth
}, update);
const uint128_t request_id = transaction_id_to_sender_id(context.trx_context.id);
auto record_data = mutable_variant_object()
("account", account)
("request_id", request_id)
("update", update)
("memo", recover_act.memo);
transaction trx;
trx.expiration = context.control.pending_block_time() + fc::microseconds(999'999); // Rounds up to nearest second
trx.delay_sec = (delay_lock + fc::microseconds(999'999)).to_seconds(); // Rounds up to nearest second
trx.set_reference_block(context.control.head_block_id());
trx.actions.emplace_back( vector<permission_level>{{account,config::active_name},{config::system_account_name,config::active_name}},
passrecovery { account } );
// NOTE: we pre-reserve capacity for this during create account
context.schedule_deferred_transaction(request_id, config::system_account_name, std::move(trx));
auto data = get_abi_serializer().variant_to_binary("pending_recovery", record_data);
const uint64_t id = account;
const uint64_t table = N(recovery);
const auto payer = account;
const auto iter = context.db_find_i64(config::system_account_name, account, table, id);
if (iter == -1) {
context.db_store_i64(account, table, payer, id, (const char*)data.data(), data.size());
} else {
context.db_update_i64(iter, payer, (const char*)data.data(), data.size());
}
context.console_append_formatted("Recovery Started for account ${account} : ${memo}\n", mutable_variant_object()("account", account)("memo", recover_act.memo));
context.checktime( 3000 );
}
static void remove_pending_recovery(apply_context& context, const account_name& account) {
const auto iter = context.db_find_i64(config::system_account_name, account, N(recovery), account);
if (iter != -1) {
context.db_remove_i64(iter);
}
}
void apply_eosio_passrecovery(apply_context& context) {
auto pass_act = context.act.data_as<passrecovery>();
const auto& account = pass_act.account;
// ensure this is only processed if it is a deferred transaction from the system account
// TODO: verify this works with any PRIVILEGED account
// FC_ASSERT( context.sender == config::system_account_name );
context.require_authorization(account);
context.require_authorization(config::system_account_name);
auto maybe_recovery = get_pending_recovery(context, account);
FC_ASSERT(maybe_recovery, "No pending recovery found for account ${account}", ("account", account));
auto recovery = *maybe_recovery;
updateauth update;
fc::from_variant(recovery["update"], update);
action act(vector<permission_level>{{account,config::owner_name}}, update);
context.execute_inline(move(act));
remove_pending_recovery(context, account);
context.console_append_formatted("Account ${account} successfully recovered!\n", mutable_variant_object()("account", account));
context.checktime( 3000 );
}
void apply_eosio_vetorecovery(apply_context& context) {
// context.require_write_lock( config::eosio_auth_scope );
auto pass_act = context.act.data_as<vetorecovery>();
const auto& account = pass_act.account;
context.require_authorization(account);
auto maybe_recovery = get_pending_recovery(context, account);
FC_ASSERT(maybe_recovery, "No pending recovery found for account ${account}", ("account", account));
auto recovery = *maybe_recovery;
context.cancel_deferred_transaction(recovery["request_id"].as<uint128_t>());
remove_pending_recovery(context, account);
context.console_append_formatted("Recovery for account ${account} vetoed!\n", mutable_variant_object()("account", account));
context.checktime( 3000 );
}
void apply_eosio_canceldelay(apply_context& context) {
auto cancel = context.act.data_as<canceldelay>();
......
......@@ -25,12 +25,10 @@ namespace eosio { namespace chain {
digest_type code_version;
block_timestamp_type creation_date;
shared_vector<char> code;
shared_vector<char> abi;
shared_string code;
shared_string abi;
void set_abi( const eosio::chain::abi_def& a ) {
// Added resize(0) here to avoid bug in boost vector container
abi.resize( 0 );
abi.resize( fc::raw::pack_size( a ) );
fc::datastream<char*> ds( abi.data(), abi.size() );
fc::raw::pack( ds, a );
......
......@@ -64,7 +64,7 @@ namespace eosio { namespace chain {
table_id t_id;
uint64_t primary_key;
account_name payer = 0;
shared_vector<char> value;
shared_string value;
};
using key_value_index = chainbase::shared_multi_index_container<
......
......@@ -107,7 +107,6 @@ struct newaccount {
account_name name;
authority owner;
authority active;
authority recovery;
static account_name get_account() {
return config::system_account_name;
......@@ -235,44 +234,6 @@ struct onerror {
}
};
struct postrecovery {
account_name account;
authority auth;
string memo;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(postrecovery);
}
};
struct passrecovery {
account_name account;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(passrecovery);
}
};
struct vetorecovery {
account_name account;
static account_name get_account() {
return config::system_account_name;
}
static action_name get_name() {
return N(vetorecovery);
}
};
struct canceldelay {
permission_level canceling_auth;
......@@ -297,15 +258,12 @@ FC_REFLECT( eosio::chain::clause_pair , (id)(body) )
FC_REFLECT( eosio::chain::table_def , (name)(index_type)(key_names)(key_types)(type) )
FC_REFLECT( eosio::chain::abi_def , (types)(structs)(actions)(tables)(ricardian_clauses) )
FC_REFLECT( eosio::chain::newaccount , (creator)(name)(owner)(active)(recovery) )
FC_REFLECT( eosio::chain::setcode , (account)(vmtype)(vmversion)(code) ) //abi
FC_REFLECT( eosio::chain::newaccount , (creator)(name)(owner)(active) )
FC_REFLECT( eosio::chain::setcode , (account)(vmtype)(vmversion)(code) )
FC_REFLECT( eosio::chain::setabi , (account)(abi) )
FC_REFLECT( eosio::chain::updateauth , (account)(permission)(parent)(auth) )
FC_REFLECT( eosio::chain::deleteauth , (account)(permission) )
FC_REFLECT( eosio::chain::linkauth , (account)(code)(type)(requirement) )
FC_REFLECT( eosio::chain::unlinkauth , (account)(code)(type) )
FC_REFLECT( eosio::chain::postrecovery , (account)(auth)(memo) )
FC_REFLECT( eosio::chain::passrecovery , (account) )
FC_REFLECT( eosio::chain::vetorecovery , (account) )
FC_REFLECT( eosio::chain::canceldelay , (canceling_auth)(trx_id) )
FC_REFLECT( eosio::chain::onerror , (sender_id)(sent_trx) )
FC_REFLECT( eosio::chain::onerror, (sender_id)(sent_trx) )
......@@ -21,14 +21,18 @@ namespace eosio { namespace chain {
void apply_eosio_linkauth(apply_context&);
void apply_eosio_unlinkauth(apply_context&);
/*
void apply_eosio_postrecovery(apply_context&);
void apply_eosio_passrecovery(apply_context&);
void apply_eosio_vetorecovery(apply_context&);
*/
void apply_eosio_setcode(apply_context&);
void apply_eosio_setabi(apply_context&);
/*
void apply_eosio_onerror(apply_context&);
*/
void apply_eosio_canceldelay(apply_context&);
///@} end action handlers
......
......@@ -34,7 +34,7 @@ namespace eosio { namespace chain {
time_point delay_until; /// this generated transaction will not be applied until the specified time
time_point expiration; /// this generated transaction will not be applied after this time
time_point published;
shared_vector<char> packed_trx;
shared_string packed_trx;
uint32_t set( const transaction& trx ) {
auto trxsize = fc::raw::pack_size( trx );
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/types.hpp>
#include <eosio/chain/authority.hpp>
#include <eosio/chain/block_timestamp.hpp>
#include "multi_index_includes.hpp"
namespace eosio { namespace chain {
class scope_sequence_object : public chainbase::object<scope_sequence_object_type, scope_sequence_object> {
OBJECT_CTOR(scope_sequence_object)
id_type id;
scope_name scope;
account_name receiver;
uint64_t sequence = 0;
};
using scope_sequence_id_type = scope_sequence_object::id_type;
struct by_scope_receiver;
using scope_sequence_multi_index = chainbase::shared_multi_index_container<
scope_sequence_object,
indexed_by<
ordered_unique<tag<by_id>, member<scope_sequence_object, scope_sequence_object::id_type, &scope_sequence_object::id>>,
ordered_unique<tag<by_scope_receiver>,
composite_key< scope_sequence_object,
member<scope_sequence_object, scope_name, &scope_sequence_object::scope>,
member<scope_sequence_object, account_name, &scope_sequence_object::receiver>
>
>
>
>;
typedef chainbase::generic_index<scope_sequence_multi_index> scope_sequence_index;
} } // eosio::chain
CHAINBASE_SET_INDEX_TYPE(eosio::chain::scope_sequence_object, eosio::chain::scope_sequence_multi_index)
FC_REFLECT(chainbase::oid<eosio::chain::scope_sequence_object>, (_id))
FC_REFLECT(eosio::chain::scope_sequence_object, (id)(scope)(receiver)(sequence))
......@@ -76,19 +76,19 @@ namespace eosio { namespace chain { namespace wasm_injections {
// prepend to the head of the imports
module.functions.imports.insert( module.functions.imports.begin()+(registered_injected.size()-1), new_import.begin(), new_import.end() );
injected_index_mapping.emplace( index, actual_index );
// shift all exported functions by 1
bool have_updated_start = false;
for ( int i=0; i < module.exports.size(); i++ ) {
if ( module.exports[i].kind == IR::ObjectKind::function ) {
// update the start function
if ( !have_updated_start && module.exports[i].index == module.startFunctionIndex ) {
module.startFunctionIndex++;
have_updated_start = true;
}
module.exports[i].index++;
}
}
// update the start function
if ( module.startFunctionIndex != UINTPTR_MAX ) {
module.startFunctionIndex++;
}
// shift all table entries for call indirect
for(TableSegment& ts : module.tableSegments) {
for(auto& idx : ts.indices)
......
......@@ -61,7 +61,7 @@ namespace eosio { namespace chain {
static void validate(const bytes& code);
//Calls apply or error on a given code
void apply(const digest_type& code_id, const shared_vector<char>& code, apply_context& context);
void apply(const digest_type& code_id, const shared_string& code, apply_context& context);
private:
unique_ptr<struct wasm_interface_impl> my;
......
......@@ -47,7 +47,7 @@ namespace eosio { namespace chain {
return mem_image;
}
std::unique_ptr<wasm_instantiated_module_interface>& get_instantiated_module(const digest_type& code_id, const shared_vector<char>& code) {
std::unique_ptr<wasm_instantiated_module_interface>& get_instantiated_module(const digest_type& code_id, const shared_string& code) {
auto it = instantiation_cache.find(code_id);
if(it == instantiation_cache.end()) {
IR::Module module;
......
......@@ -52,7 +52,7 @@ namespace eosio { namespace chain {
//Hard: Kick off instantiation in a separate thread at this location
}
void wasm_interface::apply( const digest_type& code_id, const shared_vector<char>& code, apply_context& context ) {
void wasm_interface::apply( const digest_type& code_id, const shared_string& code, apply_context& context ) {
my->get_instantiated_module(code_id, code)->apply(context);
}
......
Subproject commit 4ebab558f506f13457317fe9f0ca5b79511b76a1
Subproject commit 71cd824247231f2fc7273e9a7839ec004d2975a9
......@@ -200,8 +200,7 @@ namespace eosio { namespace testing {
.creator = creator,
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
set_transaction_headers(trx);
......
......@@ -26,8 +26,6 @@ namespace eosio { namespace chain { namespace plugin_interface {
using applied_transaction = channel_decl<struct applied_transaction_tag, transaction_trace_ptr>;
using accepted_confirmation = channel_decl<struct accepted_confirmation_tag, header_confirmation>;
using incoming_block = channel_decl<struct incoming_blocks_tag, signed_block_ptr>;
using incoming_transaction = channel_decl<struct incoming_transactions_tag, packed_transaction_ptr>;
}
namespace methods {
......@@ -36,10 +34,25 @@ namespace eosio { namespace chain { namespace plugin_interface {
using get_head_block_id = method_decl<chain_plugin_interface, block_id_type ()>;
using get_last_irreversible_block_number = method_decl<chain_plugin_interface, uint32_t ()>;
}
namespace incoming {
namespace channels {
using block = channel_decl<struct block_tag, signed_block_ptr>;
using transaction = channel_decl<struct transaction_tag, packed_transaction_ptr>;
}
namespace methods {
// synchronously push a block/trx to a single provider
using block_sync = method_decl<chain_plugin_interface, void(const signed_block_ptr&), first_provider_policy>;
using transaction_sync = method_decl<chain_plugin_interface, transaction_trace_ptr(const packed_transaction_ptr&), first_provider_policy>;
}
}
// synchronously push a block/trx to a single provider
using incoming_block_sync = method_decl<chain_plugin_interface, void(const signed_block_ptr&), first_provider_policy>;
using incoming_transaction_sync = method_decl<chain_plugin_interface, transaction_trace_ptr(const packed_transaction_ptr&), first_provider_policy>;
namespace compat {
namespace channels {
using transaction_ack = channel_decl<struct accepted_transaction_tag, std::pair<fc::exception_ptr, packed_transaction_ptr>>;
}
}
} } }
\ No newline at end of file
......@@ -45,9 +45,9 @@ public:
,accepted_transaction_channel(app().get_channel<channels::accepted_transaction>())
,applied_transaction_channel(app().get_channel<channels::applied_transaction>())
,accepted_confirmation_channel(app().get_channel<channels::accepted_confirmation>())
,incoming_block_channel(app().get_channel<channels::incoming_block>())
,incoming_block_sync_method(app().get_method<methods::incoming_block_sync>())
,incoming_transaction_sync_method(app().get_method<methods::incoming_transaction_sync>())
,incoming_block_channel(app().get_channel<incoming::channels::block>())
,incoming_block_sync_method(app().get_method<incoming::methods::block_sync>())
,incoming_transaction_sync_method(app().get_method<incoming::methods::transaction_sync>())
{}
bfs::path block_log_dir;
......@@ -72,11 +72,11 @@ public:
channels::accepted_transaction::channel_type& accepted_transaction_channel;
channels::applied_transaction::channel_type& applied_transaction_channel;
channels::accepted_confirmation::channel_type& accepted_confirmation_channel;
channels::incoming_block::channel_type& incoming_block_channel;
incoming::channels::block::channel_type& incoming_block_channel;
// retained references to methods for easy calling
methods::incoming_block_sync::method_type& incoming_block_sync_method;
methods::incoming_transaction_sync::method_type& incoming_transaction_sync_method;
incoming::methods::block_sync::method_type& incoming_block_sync_method;
incoming::methods::transaction_sync::method_type& incoming_transaction_sync_method;
// method provider handles
methods::get_block_by_number::method_type::handle get_block_by_number_provider;
......@@ -454,7 +454,7 @@ read_write::push_transaction_results read_write::push_transaction(const read_wri
abi_serializer::from_variant(params, *pretty_input, resolver);
} EOS_RETHROW_EXCEPTIONS(chain::packed_transaction_type_exception, "Invalid packed transaction")
auto trx_trace_ptr = app().get_method<methods::incoming_transaction_sync>()(pretty_input);
auto trx_trace_ptr = app().get_method<incoming::methods::transaction_sync>()(pretty_input);
fc::variant pretty_output = db.to_variant_with_abi( *trx_trace_ptr );;
//abi_serializer::to_variant(*trx_trace_ptr, pretty_output, resolver);
......
......@@ -27,7 +27,7 @@ namespace eosio {
id_type id;
uint64_t action_sequence_num; ///< the sequence number of the relevant action
shared_vector<char> packed_action_trace;
shared_string packed_action_trace;
uint32_t block_num;
block_timestamp_type block_time;
transaction_id_type trx_id;
......
file(GLOB HEADERS "include/eosio/net_plugin/*.hpp")
file(GLOB HEADERS "include/eosio/net_plugin/*.hpp" )
add_library( net_plugin
net_plugin.cpp
${HEADERS} )
target_link_libraries( net_plugin chain_plugin producer_plugin appbase fc )
target_include_directories( net_plugin PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include )
target_include_directories( net_plugin PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/../chain_interface/include )
......@@ -9,6 +9,7 @@
#include <eosio/chain/controller.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/block.hpp>
#include <eosio/chain/plugin_interface.hpp>
#include <eosio/producer_plugin/producer_plugin.hpp>
#include <eosio/utilities/key_conversion.hpp>
#include <eosio/chain/contract_types.hpp>
......@@ -28,6 +29,8 @@
#include <boost/asio/steady_timer.hpp>
#include <boost/intrusive/set.hpp>
using namespace eosio::chain::plugin_interface::compat;
namespace fc {
extern std::unordered_map<std::string,logger>& get_logger_map();
}
......@@ -189,6 +192,8 @@ namespace eosio {
shared_ptr<tcp::resolver> resolver;
channels::transaction_ack::channel_type::handle incoming_transaction_ack_subscription;
void connect( connection_ptr c );
void connect( connection_ptr c, tcp::resolver::iterator endpoint_itr );
void start_session( connection_ptr c );
......@@ -208,6 +213,8 @@ namespace eosio {
void applied_transaction(const transaction_trace_ptr&);
void accepted_confirmation(const header_confirmation&);
void transaction_ack(const std::pair<fc::exception_ptr, packed_transaction_ptr>&);
bool is_valid( const handshake_message &msg);
void handle_message( connection_ptr c, const handshake_message &msg);
......@@ -2597,7 +2604,7 @@ namespace eosio {
void net_plugin_impl::accepted_transaction(const transaction_metadata_ptr& md) {
fc_ilog(logger,"signaled, id = ${id}",("id", md->id));
dispatcher->bcast_transaction(md->packed_trx);
// dispatcher->bcast_transaction(md->packed_trx);
}
void net_plugin_impl::applied_transaction(const transaction_trace_ptr& txn) {
......@@ -2608,6 +2615,16 @@ namespace eosio {
fc_ilog(logger,"signaled, id = ${id}",("id", head.block_id));
}
void net_plugin_impl::transaction_ack(const std::pair<fc::exception_ptr, packed_transaction_ptr>& results) {
transaction_id_type id = results.second->id();
if (results.first) {
fc_ilog(logger,"signaled NACK, trx-id = ${id} : ${why}",("id", id)("why", results.first->to_detail_string()));
} else {
fc_ilog(logger,"signaled ACK, trx-id = ${id}",("id", id));
dispatcher->bcast_transaction(*results.second);
}
}
bool net_plugin_impl::authenticate_peer(const handshake_message& msg) const {
if(allowed_connections == None)
return false;
......@@ -2887,6 +2904,9 @@ namespace eosio {
cc.applied_transaction.connect( boost::bind(&net_plugin_impl::applied_transaction, my.get(), _1));
cc.accepted_confirmation.connect( boost::bind(&net_plugin_impl::accepted_confirmation, my.get(), _1));
}
my->incoming_transaction_ack_subscription = app().get_channel<channels::transaction_ack>().subscribe(boost::bind(&net_plugin_impl::transaction_ack, my.get(), _1));
my->start_monitors();
for( auto seed_node : my->supplied_peers ) {
......
......@@ -32,6 +32,7 @@ class producer_plugin_impl {
public:
producer_plugin_impl(boost::asio::io_service& io)
:_timer(io)
,_transaction_ack_channel(app().get_channel<compat::channels::transaction_ack>())
{}
void schedule_production_loop();
......@@ -60,11 +61,13 @@ class producer_plugin_impl {
producer_plugin* _self = nullptr;
channels::incoming_block::channel_type::handle _incoming_block_subscription;
channels::incoming_transaction::channel_type::handle _incoming_transaction_subscription;
incoming::channels::block::channel_type::handle _incoming_block_subscription;
incoming::channels::transaction::channel_type::handle _incoming_transaction_subscription;
methods::incoming_block_sync::method_type::handle _incoming_block_sync_provider;
methods::incoming_transaction_sync::method_type::handle _incoming_transaction_sync_provider;
compat::channels::transaction_ack::channel_type& _transaction_ack_channel;
incoming::methods::block_sync::method_type::handle _incoming_block_sync_provider;
incoming::methods::transaction_sync::method_type::handle _incoming_transaction_sync_provider;
void on_block( const block_state_ptr& bsp ) {
if( bsp->header.timestamp <= _last_signed_block_time ) return;
......@@ -102,6 +105,40 @@ class producer_plugin_impl {
} ) );
}
template<typename Type, typename Channel, typename F>
auto publish_results_of(const Type &data, Channel& channel, F f) {
auto publish_success = fc::make_scoped_exit([&, this](){
channel.publish(std::pair<fc::exception_ptr, Type>(nullptr, data));
});
try {
return f();
} catch (const fc::exception& e) {
publish_success.cancel();
channel.publish(std::pair<fc::exception_ptr, Type>(e.dynamic_copy_exception(), data));
throw e;
} catch( const std::exception& e ) {
publish_success.cancel();
auto fce = fc::exception(
FC_LOG_MESSAGE( info, "Caught std::exception: ${what}", ("what",e.what())),
fc::std_exception_code,
BOOST_CORE_TYPEID(e).name(),
e.what()
);
channel.publish(std::pair<fc::exception_ptr, Type>(fce.dynamic_copy_exception(),data));
throw fce;
} catch( ... ) {
publish_success.cancel();
auto fce = fc::unhandled_exception(
FC_LOG_MESSAGE( info, "Caught unknown exception"),
std::current_exception()
);
channel.publish(std::pair<fc::exception_ptr, Type>(fce.dynamic_copy_exception(), data));
throw fce;
}
};
void on_incoming_block(const signed_block_ptr& block) {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
// abort the pending block
......@@ -112,9 +149,13 @@ class producer_plugin_impl {
// restart our production loop
schedule_production_loop();
});
// push the new block
chain.push_block(block);
if( chain.head_block_state()->header.timestamp.next().to_time_point() >= fc::time_point::now() )
_production_enabled = true;
ilog("Received block ${id}... #${n} @ ${t} signed by ${p} [trxs: ${count}, lib: ${lib}, confirmed: ${confs}]",
("p",block->producer)("id",fc::variant(block->id()).as_string().substr(0,16))
("n",block_header::num_from_id(block->id()))("t",block->timestamp)
......@@ -123,8 +164,10 @@ class producer_plugin_impl {
}
transaction_trace_ptr on_incoming_transaction(const packed_transaction_ptr& trx) {
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
return chain.sync_push(std::make_shared<transaction_metadata>(*trx), fc::time_point::now() + fc::milliseconds(_max_pending_transaction_time_ms));
return publish_results_of(trx, _transaction_ack_channel, [&]{
chain::controller& chain = app().get_plugin<chain_plugin>().chain();
return chain.sync_push(std::make_shared<transaction_metadata>(*trx), fc::time_point::now() + fc::milliseconds(_max_pending_transaction_time_ms));
});
}
bool start_block();
......@@ -240,23 +283,23 @@ void producer_plugin::plugin_initialize(const boost::program_options::variables_
my->_max_pending_transaction_time_ms = options.at("max-pending-transaction-time").as<int32_t>();
my->_incoming_block_subscription = app().get_channel<channels::incoming_block>().subscribe([this](const signed_block_ptr& block){
my->_incoming_block_subscription = app().get_channel<incoming::channels::block>().subscribe([this](const signed_block_ptr& block){
try {
my->on_incoming_block(block);
} FC_LOG_AND_DROP();
});
my->_incoming_transaction_subscription = app().get_channel<channels::incoming_transaction>().subscribe([this](const packed_transaction_ptr& trx){
my->_incoming_transaction_subscription = app().get_channel<incoming::channels::transaction>().subscribe([this](const packed_transaction_ptr& trx){
try {
my->on_incoming_transaction(trx);
} FC_LOG_AND_DROP();
});
my->_incoming_block_sync_provider = app().get_method<methods::incoming_block_sync>().register_provider([this](const signed_block_ptr& block){
my->_incoming_block_sync_provider = app().get_method<incoming::methods::block_sync>().register_provider([this](const signed_block_ptr& block){
my->on_incoming_block(block);
});
my->_incoming_transaction_sync_provider = app().get_method<methods::incoming_transaction_sync>().register_provider([this](const packed_transaction_ptr& trx) -> transaction_trace_ptr {
my->_incoming_transaction_sync_provider = app().get_method<incoming::methods::transaction_sync>().register_provider([this](const packed_transaction_ptr& trx) -> transaction_trace_ptr {
return my->on_incoming_transaction(trx);
});
......@@ -457,10 +500,7 @@ block_production_condition::block_production_condition_enum producer_plugin_impl
// If the next block production opportunity is in the present or future, we're synced.
if( !_production_enabled )
{
if( hbs->header.timestamp.next().to_time_point() >= now )
_production_enabled = true;
else
return block_production_condition::not_synced;
return block_production_condition::not_synced;
}
auto pending_block_timestamp = chain.pending_block_state()->header.timestamp;
......
......@@ -105,25 +105,22 @@ struct txn_test_gen_plugin_impl {
{
auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_A_pub_key, 1}}, {}};
auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_A_pub_key, 1}}, {}};
auto recovery_auth = eosio::chain::authority{1, {}, {{{creator, "active"}, 1}}};
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, newaccount{creator, newaccountA, owner_auth, active_auth, recovery_auth});
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, newaccount{creator, newaccountA, owner_auth, active_auth});
}
//create "B" account
{
auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_B_pub_key, 1}}, {}};
auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_B_pub_key, 1}}, {}};
auto recovery_auth = eosio::chain::authority{1, {}, {{{creator, "active"}, 1}}};
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, newaccount{creator, newaccountB, owner_auth, active_auth, recovery_auth});
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, newaccount{creator, newaccountB, owner_auth, active_auth});
}
//create "eosio.token" account
{
auto owner_auth = eosio::chain::authority{1, {{txn_text_receiver_C_pub_key, 1}}, {}};
auto active_auth = eosio::chain::authority{1, {{txn_text_receiver_C_pub_key, 1}}, {}};
auto recovery_auth = eosio::chain::authority{1, {}, {{{creator, "active"}, 1}}};
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, newaccount{creator, newaccountC, owner_auth, active_auth, recovery_auth});
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, newaccount{creator, newaccountC, owner_auth, active_auth});
}
trx.expiration = cc.head_block_time() + fc::seconds(30);
......
......@@ -330,14 +330,13 @@ void print_action_tree( const fc::variant& action ) {
void print_result( const fc::variant& result ) { try {
const auto& processed = result["processed"];
const auto& transaction_id = processed["id"].as_string();
const auto& receipt = processed["receipt"].get_object() ;
const auto& status = receipt["status"].as_string() ;
auto net = receipt["net_usage_words"].as_int64()*8;
auto cpu = receipt["kcpu_usage"].as_int64();
string status = processed["receipt"].is_object() ? processed["receipt"]["status"].as_string() : "failed";
auto net = processed["net_usage"].as_int64()*8;
auto cpu = processed["cpu_usage"].as_int64() / 1024;
cerr << status << " transaction: " << transaction_id << " " << net << " bytes " << cpu << "k cycles\n";
if( status == "hard_fail" ) {
if( status == "failed" ) {
auto soft_except = processed["except"].as<optional<fc::exception>>();
if( soft_except ) {
edump((soft_except->to_detail_string()));
......@@ -380,8 +379,7 @@ chain::action create_newaccount(const name& creator, const name& newaccount, pub
.creator = creator,
.name = newaccount,
.owner = eosio::chain::authority{1, {{owner, 1}}, {}},
.active = eosio::chain::authority{1, {{active, 1}}, {}},
.recovery = eosio::chain::authority{1, {}, {{{creator, config::active_name}, 1}}}
.active = eosio::chain::authority{1, {{active, 1}}, {}}
}
};
}
......@@ -1054,45 +1052,6 @@ struct unregproxy_subcommand {
}
};
struct postrecovery_subcommand {
string account;
string json_str_or_file;
string memo;
postrecovery_subcommand(CLI::App* actionRoot) {
auto post_recovery = actionRoot->add_subcommand("postrecovery", localized("Post recovery request"));
post_recovery->add_option("account", account, localized("The account to post the recovery for"))->required();
post_recovery->add_option("data", json_str_or_file, localized("The authority to post the recovery with as EOS public key, JSON string, or filename"))->required();
post_recovery->add_option("memo", memo, localized("A memo describing the post recovery request"))->required();
add_standard_transaction_options(post_recovery);
post_recovery->set_callback([this] {
authority data_auth = parse_json_authority_or_key(json_str_or_file);
fc::variant act_payload = fc::mutable_variant_object()
("account", account)
("data", data_auth)
("memo", memo);
send_actions({create_action({permission_level{account,config::active_name}}, config::system_account_name, N(postrecovery), act_payload)});
});
}
};
struct vetorecovery_subcommand {
string account;
vetorecovery_subcommand(CLI::App* actionRoot) {
auto veto_recovery = actionRoot->add_subcommand("vetorecovery", localized("Veto a posted recovery"));
veto_recovery->add_option("account", account, localized("The account to veto the recovery for"))->required();
add_standard_transaction_options(veto_recovery);
veto_recovery->set_callback([this] {
fc::variant act_payload = fc::mutable_variant_object()
("account", account);
send_actions({create_action({permission_level{account,config::active_name}}, config::system_account_name, N(vetorecovery), act_payload)});
});
}
};
struct canceldelay_subcommand {
string cancelling_account;
string cancelling_permission;
......@@ -1171,8 +1130,8 @@ void get_account( const string& accountName, bool json_format ) {
<< indent << "quota: " << std::setw(15) << res.ram_quota << " bytes used: " << std::setw(15) << res.ram_usage << " bytes" << std::endl << std::endl;
std::cout << "net bandwidth:" << std::endl;
if ( res.total_resources.is_object() && res.delegated_bandwidth.is_object() ) {
asset net_own( stoll( res.delegated_bandwidth.get_object()["net_weight"].as_string() ) );
if ( res.total_resources.is_object() ) {
asset net_own( res.delegated_bandwidth.is_object() ? stoll( res.delegated_bandwidth.get_object()["net_weight"].as_string() ) : 0 );
auto net_others = to_asset(res.total_resources.get_object()["net_weight"].as_string()) - net_own;
std::cout << indent << "staked:" << std::setw(20) << net_own
<< std::string(11, ' ') << "(total stake delegated from account to self)" << std::endl
......@@ -1189,8 +1148,8 @@ void get_account( const string& accountName, bool json_format ) {
std::cout << "cpu bandwidth:" << std::endl;
if ( res.total_resources.is_object() && res.delegated_bandwidth.is_object() ) {
asset cpu_own( stoll( res.delegated_bandwidth.get_object()["cpu_weight"].as_string() ) );
if ( res.total_resources.is_object() ) {
asset cpu_own( res.delegated_bandwidth.is_object() ? stoll( res.delegated_bandwidth.get_object()["cpu_weight"].as_string() ) : 0 );
auto cpu_others = to_asset(res.total_resources.get_object()["cpu_weight"].as_string()) - cpu_own;
std::cout << indent << "staked:" << std::setw(20) << cpu_own
<< std::string(11, ' ') << "(total stake delegated from account to self)" << std::endl
......@@ -2219,9 +2178,6 @@ int main( int argc, char** argv ) {
auto regProxy = regproxy_subcommand(system);
auto unregProxy = unregproxy_subcommand(system);
auto postRecovery = postrecovery_subcommand(system);
auto vetoRecovery = vetorecovery_subcommand(system);
auto cancelDelay = canceldelay_subcommand(system);
try {
......
......@@ -222,7 +222,7 @@ try:
errorExit("Cluster in bad state, received None node")
Print("Create new account %s via %s" % (testeraAccount.name, initaAccount.name))
transId=node.createAccount(testeraAccount, initaAccount, stakedDeposit=0, waitForTransBlock=False)
transId=node.createInitializeAccount(testeraAccount, initaAccount, stakedDeposit=0, waitForTransBlock=False)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (testeraAccount.name))
......@@ -261,13 +261,13 @@ try:
errorExit("Transfer verification failed. Excepted %s, actual: %s" % (expectedAmount, actualAmount))
Print("Create new account %s via %s" % (currencyAccount.name, initbAccount.name))
transId=node.createAccount(currencyAccount, initbAccount, stakedDeposit=5000)
transId=node.createInitializeAccount(currencyAccount, initbAccount, stakedDeposit=5000)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (currencyAccount.name))
Print("Create new account %s via %s" % (exchangeAccount.name, initaAccount.name))
transId=node.createAccount(exchangeAccount, initaAccount, waitForTransBlock=True)
transId=node.createInitializeAccount(exchangeAccount, initaAccount, waitForTransBlock=True)
if transId is None:
cmdError("%s create account" % (ClientName))
errorExit("Failed to create account %s" % (exchangeAccount.name))
......
......@@ -15,6 +15,7 @@ import inspect
import sys
import random
import json
import shlex
###########################################################################################
class Utils:
......@@ -80,7 +81,8 @@ class Utils:
@staticmethod
def checkOutput(cmd):
assert(isinstance(cmd, list))
retStr=subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode("utf-8")
#retStr=subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode("utf-8")
retStr=subprocess.check_output(cmd).decode("utf-8")
return retStr
@staticmethod
......@@ -168,7 +170,8 @@ class Node(object):
@staticmethod
def runCmdReturnJson(cmd, trace=False):
retStr=Utils.checkOutput(cmd.split())
cmdArr=shlex.split(cmd)
retStr=Utils.checkOutput(cmdArr)
jStr=Node.filterJsonObject(retStr)
if trace: Utils.Print ("RAW > %s"% (retStr))
if trace: Utils.Print ("JSON> %s"% (jStr))
......@@ -180,14 +183,13 @@ class Node(object):
try:
jsonData=json.loads(jStr)
return jsonData
except json.decoder.JSONDecodeError as ex:
Utils.Print (ex)
Utils.Print ("RAW > %s"% retStr)
Utils.Print ("JSON> %s"% jStr)
raise
return jsonData
@staticmethod
def __runCmdArrReturnJson(cmdArr, trace=False):
retStr=Utils.checkOutput(cmdArr)
......@@ -465,6 +467,32 @@ class Node(object):
if Utils.Debug: Utils.Print("Check if block %d is irreversible." % (blockNum))
return self.doesNodeHaveBlockNum(blockNum)
# Create & initialize account and return creation transactions. Return transaction json object
def createInitializeAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False):
cmd='%s %s system newaccount -j %s %s %s %s --stake-net "100 EOS" --stake-cpu "100 EOS" --buy-ram-EOS "100 EOS"' % (
Utils.EosClientPath, self.endpointArgs, creatorAccount.name, account.name,
account.ownerPublicKey, account.activePublicKey)
if Utils.Debug: Utils.Print("cmd: %s" % (cmd))
trans=None
try:
trans=Node.runCmdReturnJson(cmd)
transId=Node.getTransId(trans)
except subprocess.CalledProcessError as ex:
msg=ex.output.decode("utf-8")
Utils.Print("ERROR: Exception during account creation. %s" % (msg))
return None
if stakedDeposit > 0:
self.waitForTransIdOnNode(transId) # seems like account creation needs to be finlized before transfer can happen
trans = self.transferFunds(creatorAccount, account, "%0.04f EOS" % (stakedDeposit/10000), "init")
transId=Node.getTransId(trans)
if waitForTransBlock and not self.waitForTransIdOnNode(transId):
return None
return trans
# Create account and return creation transactions. Return transaction json object
# waitForTransBlock: wait on creation transaction id to appear in a block
def createAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False):
......@@ -1207,7 +1235,7 @@ class Cluster(object):
if self.staging:
cmdArr.append("--nogen")
nodeosArgs=""
nodeosArgs="--max-pending-transaction-time 5000"
if not self.walletd:
nodeosArgs += " --plugin eosio::wallet_api_plugin"
if self.enableMongo:
......@@ -1759,22 +1787,6 @@ class Cluster(object):
if trans is None:
Utils.Print("ERROR: Failed to publish contract %s." % (contract))
return False
Node.validateTransaction(trans)
# TBD: Loading this requires upping the max peding transaction timeout
# contract="eosio.system"
# contractDir="contracts/%s" % (contract)
# wastFile="contracts/%s/%s.wast" % (contract, contract)
# abiFile="contracts/%s/%s.abi" % (contract, contract)
# Utils.Print("Publish %s contract" % (contract))
# trans=biosNode.publishContract(eosioAccount.name, contractDir, wastFile, abiFile, waitForTransBlock=True)
# if trans is None:
# Utils.Print("ERROR: Failed to publish contract %s." % (contract))
# return False
# Node.validateTransaction(trans)
# Create currency, followed by issue currency
contract=eosioTokenAccount.name
......@@ -1792,7 +1804,7 @@ class Cluster(object):
contract=eosioTokenAccount.name
Utils.Print("push issue action to %s contract" % (contract))
action="issue"
data="{\"to\":\"%s\",\"quantity\":\"1000000000.0000 EOS\",\"memo\":\"initial issue\"}" % (eosioTokenAccount.name)
data="{\"to\":\"%s\",\"quantity\":\"1000000000.0000 EOS\",\"memo\":\"initial issue\"}" % (eosioAccount.name)
opts="--permission %s@active" % (contract)
trans=biosNode.pushMessage(contract, action, data, opts)
if trans is None or not trans[0]:
......@@ -1806,20 +1818,32 @@ class Cluster(object):
expectedAmount="1000000000.0000 EOS"
Utils.Print("Verify eosio issue, Expected: %s" % (expectedAmount))
actualAmount=biosNode.getAccountEosBalanceStr(eosioTokenAccount.name)
actualAmount=biosNode.getAccountEosBalanceStr(eosioAccount.name)
if expectedAmount != actualAmount:
Utils.Print("ERROR: Issue verification failed. Excepted %s, actual: %s" %
(expectedAmount, actualAmount))
return False
contract="eosio.system"
contractDir="contracts/%s" % (contract)
wastFile="contracts/%s/%s.wast" % (contract, contract)
abiFile="contracts/%s/%s.abi" % (contract, contract)
Utils.Print("Publish %s contract" % (contract))
trans=biosNode.publishContract(eosioAccount.name, contractDir, wastFile, abiFile, waitForTransBlock=True)
if trans is None:
Utils.Print("ERROR: Failed to publish contract %s." % (contract))
return False
Node.validateTransaction(trans)
initialFunds="1000000.0000 EOS"
Utils.Print("Transfer initial fund %s to individual accounts." % (initialFunds))
trans=None
contract=eosioTokenAccount.name
action="transfer"
for name, keys in producerKeys.items():
data="{\"from\":\"%s\",\"to\":\"%s\",\"quantity\":\"%s\",\"memo\":\"%s\"}" % (eosioTokenAccount.name, name, initialFunds, "init transfer")
opts="--permission %s@active" % (eosioTokenAccount.name)
data="{\"from\":\"%s\",\"to\":\"%s\",\"quantity\":\"%s\",\"memo\":\"%s\"}" % (eosioAccount.name, name, initialFunds, "init transfer")
opts="--permission %s@active" % (eosioAccount.name)
trans=biosNode.pushMessage(contract, action, data, opts)
if trans is None or not trans[0]:
Utils.Print("ERROR: Failed to transfer funds from %s to %s." % (eosioTokenAccount.name, name))
......
#!/bin/sh
# run ctest, disregard failure code
ctest $@
ctest --output-on-failure $@
exit 0
......@@ -73,7 +73,7 @@ if(ENABLE_COVERAGE_TESTING)
COMMAND ${LCOV_PATH} --directory . --capture --gcov-tool ./tools/llvm-gcov.sh --output-file ${Coverage_NAME}.info
COMMAND ${LCOV_PATH} -remove ${Coverage_NAME}.info 'boost/*' '/usr/lib/*' '/usr/include/*' '/externals/*' 'fc/*' 'wasm-jit/*' --output-file ${Coverage_NAME}_filtered.info
COMMAND ${LCOV_PATH} -remove ${Coverage_NAME}.info '*/boost/*' '/usr/lib/*' '/usr/include/*' '*/externals/*' '*/fc/*' '*/wasm-jit/*' --output-file ${Coverage_NAME}_filtered.info
COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${PROJECT_BINARY_DIR}/${Coverage_NAME}_filtered.info
COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.base ${Coverage_NAME}.info ${Coverage_NAME}_filtered.info ${Coverage_NAME}.total ${PROJECT_BINARY_DIR}/${Coverage_NAME}.info.cleaned ${PROJECT_BINARY_DIR}/${Coverage_NAME}_filtered.info.cleaned
......
......@@ -2224,16 +2224,7 @@ BOOST_AUTO_TEST_CASE(newaccount_test)
{"key" : "EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf", "weight" : 57605} ],
"accounts" : [ {"permission" : {"actor" : "prm.acct1", "permission" : "prm.prm1"}, "weight" : 53005 },
{"permission" : {"actor" : "prm.acct2", "permission" : "prm.prm2"}, "weight" : 53405 }]
},
"recovery" : {
"threshold" : 2145483145,
"delay_sec" : 0,
"keys" : [ {"key" : "EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im", "weight" : 57005},
{"key" : "EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf", "weight" : 57605} ],
"accounts" : [ {"permission" : {"actor" : "prm.acct1", "permission" : "prm.prm1"}, "weight" : 53005 },
{"permission" : {"actor" : "prm.acct2", "permission" : "prm.prm2"}, "weight" : 53405 }]
}
}
} }
)=====";
auto var = fc::json::from_string(test_data);
......@@ -2274,21 +2265,6 @@ BOOST_AUTO_TEST_CASE(newaccount_test)
BOOST_TEST("prm.prm2" == newacct.active.accounts[1].permission.permission);
BOOST_TEST(53405u == newacct.active.accounts[1].weight);
BOOST_TEST(2145483145u == newacct.recovery.threshold);
BOOST_TEST_REQUIRE(2 == newacct.recovery.keys.size());
BOOST_TEST("EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im" == (std::string)newacct.recovery.keys[0].key);
BOOST_TEST(57005u == newacct.recovery.keys[0].weight);
BOOST_TEST("EOS5eVr9TVnqwnUBNwf9kwMTbrHvX5aPyyEG97dz2b2TNeqWRzbJf" == (std::string)newacct.recovery.keys[1].key);
BOOST_TEST(57605u == newacct.recovery.keys[1].weight);
BOOST_TEST_REQUIRE(2 == newacct.recovery.accounts.size());
BOOST_TEST("prm.acct1" == newacct.recovery.accounts[0].permission.actor);
BOOST_TEST("prm.prm1" == newacct.recovery.accounts[0].permission.permission);
BOOST_TEST(53005u == newacct.recovery.accounts[0].weight);
BOOST_TEST("prm.acct2" == newacct.recovery.accounts[1].permission.actor);
BOOST_TEST("prm.prm2" == newacct.recovery.accounts[1].permission.permission);
BOOST_TEST(53405u == newacct.recovery.accounts[1].weight);
auto var2 = verify_byte_round_trip_conversion( abis, "newaccount", var );
auto newaccount2 = var2.as<newaccount>();
......@@ -2327,21 +2303,6 @@ BOOST_AUTO_TEST_CASE(newaccount_test)
BOOST_TEST(newacct.active.accounts[1].permission.permission == newaccount2.active.accounts[1].permission.permission);
BOOST_TEST(newacct.active.accounts[1].weight == newaccount2.active.accounts[1].weight);
BOOST_TEST(newacct.recovery.threshold == newaccount2.recovery.threshold);
BOOST_TEST_REQUIRE(newacct.recovery.keys.size() == newaccount2.recovery.keys.size());
BOOST_TEST(newacct.recovery.keys[0].key == newaccount2.recovery.keys[0].key);
BOOST_TEST(newacct.recovery.keys[0].weight == newaccount2.recovery.keys[0].weight);
BOOST_TEST(newacct.recovery.keys[1].key == newaccount2.recovery.keys[1].key);
BOOST_TEST(newacct.recovery.keys[1].weight == newaccount2.recovery.keys[1].weight);
BOOST_TEST_REQUIRE(newacct.recovery.accounts.size() == newaccount2.recovery.accounts.size());
BOOST_TEST(newacct.recovery.accounts[0].permission.actor == newaccount2.recovery.accounts[0].permission.actor);
BOOST_TEST(newacct.recovery.accounts[0].permission.permission == newaccount2.recovery.accounts[0].permission.permission);
BOOST_TEST(newacct.recovery.accounts[0].weight == newaccount2.recovery.accounts[0].weight);
BOOST_TEST(newacct.recovery.accounts[1].permission.actor == newaccount2.recovery.accounts[1].permission.actor);
BOOST_TEST(newacct.recovery.accounts[1].permission.permission == newaccount2.recovery.accounts[1].permission.permission);
BOOST_TEST(newacct.recovery.accounts[1].weight == newaccount2.recovery.accounts[1].weight);
verify_type_round_trip_conversion<newaccount>( abis, "newaccount", var);
......@@ -2548,106 +2509,8 @@ BOOST_AUTO_TEST_CASE(setabi_test)
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(postrecovery_test)
{ try {
abi_serializer abis(eosio_contract_abi(abi_def()));
const char* test_data = R"=====(
{
"account" : "postrec.acc",
"auth": {
"threshold" : "2147483145",
"delay_sec" : "0",
"keys" : [ {"key" : "EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im", "weight" : 57005} ],
"accounts" : [ {"permission" : {"actor" : "postrec.acc", "permission" : "prm.prm1"}, "weight" : 57005 } ]
}
"memo": "postrec.memo"
}
)=====";
auto var = fc::json::from_string(test_data);
auto post_recovery = var.as<postrecovery>();
BOOST_TEST("postrec.acc" == post_recovery.account);
BOOST_TEST(2147483145u == post_recovery.auth.threshold);
BOOST_TEST_REQUIRE(1 == post_recovery.auth.keys.size());
BOOST_TEST("EOS65rXebLhtk2aTTzP4e9x1AQZs7c5NNXJp89W8R3HyaA6Zyd4im" == (std::string)post_recovery.auth.keys[0].key);
BOOST_TEST(57005u == post_recovery.auth.keys[0].weight);
BOOST_TEST_REQUIRE(1 == post_recovery.auth.accounts.size());
BOOST_TEST("postrec.acc" == post_recovery.auth.accounts[0].permission.actor);
BOOST_TEST("prm.prm1" == post_recovery.auth.accounts[0].permission.permission);
BOOST_TEST(57005u == post_recovery.auth.accounts[0].weight);
BOOST_TEST("postrec.memo" == post_recovery.memo);
auto var2 = verify_byte_round_trip_conversion( abis, "postrecovery", var );
auto postrecovery2 = var2.as<postrecovery>();
BOOST_TEST(post_recovery.account == postrecovery2.account);
BOOST_TEST(post_recovery.auth.threshold == postrecovery2.auth.threshold);
BOOST_TEST_REQUIRE(post_recovery.auth.keys.size() == postrecovery2.auth.keys.size());
BOOST_TEST(post_recovery.auth.keys[0].key == postrecovery2.auth.keys[0].key);
BOOST_TEST(post_recovery.auth.keys[0].weight == postrecovery2.auth.keys[0].weight);
BOOST_TEST_REQUIRE(post_recovery.auth.accounts.size() == postrecovery2.auth.accounts.size());
BOOST_TEST(post_recovery.auth.accounts[0].permission.actor == postrecovery2.auth.accounts[0].permission.actor);
BOOST_TEST(post_recovery.auth.accounts[0].permission.permission == postrecovery2.auth.accounts[0].permission.permission);
BOOST_TEST(post_recovery.auth.accounts[0].weight == postrecovery2.auth.accounts[0].weight);
BOOST_TEST(post_recovery.memo == postrecovery2.memo);
verify_type_round_trip_conversion<postrecovery>( abis, "postrecovery", var);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(passrecovery_test)
{ try {
abi_serializer abis(eosio_contract_abi(abi_def()));
const char* test_data = R"=====(
{
"account" : "passrec.acc"
}
)=====";
auto var = fc::json::from_string(test_data);
auto pass_recovery = var.as<passrecovery>();
BOOST_TEST("passrec.acc" == pass_recovery.account);
auto var2 = verify_byte_round_trip_conversion( abis, "passrecovery", var );
auto passrecovery2 = var2.as<passrecovery>();
BOOST_TEST(pass_recovery.account == passrecovery2.account);
verify_type_round_trip_conversion<passrecovery>( abis, "passrecovery", var);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_CASE(vetorecovery_test)
{ try {
abi_serializer abis(eosio_contract_abi(abi_def()));
const char* test_data = R"=====(
{
"account" : "vetorec.acc"
}
)=====";
auto var = fc::json::from_string(test_data);
auto veto_recovery = var.as<vetorecovery>();
BOOST_TEST("vetorec.acc" == veto_recovery.account);
auto var2 = verify_byte_round_trip_conversion( abis, "vetorecovery", var );
auto vetorecovery2 = var2.as<vetorecovery>();
BOOST_TEST(veto_recovery.account == vetorecovery2.account);
verify_type_round_trip_conversion<vetorecovery>( abis, "vetorecovery", var);
} FC_LOG_AND_RETHROW() }
struct action1 {
action1() = default;
......@@ -2734,8 +2597,7 @@ BOOST_AUTO_TEST_CASE(packed_transaction)
.creator = config::system_account_name,
.name = a,
.owner = authority( get_public_key( a, "owner" )),
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
txn.context_free_actions.emplace_back(
vector<permission_level>{{N(testapi2), config::active_name}},
......
......@@ -535,8 +535,7 @@ BOOST_FIXTURE_TEST_CASE(cfa_stateful_api, TESTER) try {
.creator = creator,
.name = a,
.owner = authority( get_public_key( a, "owner" ) ),
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
action act({}, test_api_action<TEST_METHOD("test_transaction", "stateful_api")>{});
trx.context_free_actions.push_back(act);
......@@ -566,8 +565,7 @@ BOOST_FIXTURE_TEST_CASE(deferred_cfa_failed, TESTER) try {
.creator = creator,
.name = a,
.owner = authority( get_public_key( a, "owner" ) ),
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
action act({}, test_api_action<TEST_METHOD("test_transaction", "stateful_api")>{});
trx.context_free_actions.push_back(act);
......@@ -603,8 +601,7 @@ BOOST_FIXTURE_TEST_CASE(deferred_cfa_success, TESTER) try {
.creator = creator,
.name = a,
.owner = authority( get_public_key( a, "owner" ) ),
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
action act({}, test_api_action<TEST_METHOD("test_transaction", "context_free_api")>{});
trx.context_free_actions.push_back(act);
......
......@@ -403,8 +403,7 @@ try {
.creator = acc1,
.name = a,
.owner = owner_auth,
.active = authority( chain.get_public_key( a, "active" ) ),
.recovery = authority( chain.get_public_key( a, "recovery" ) ),
.active = authority( chain.get_public_key( a, "active" ) )
});
chain.set_transaction_headers(trx);
......@@ -456,8 +455,7 @@ try {
.creator = creator,
.name = a,
.owner = authority( chain.get_public_key( a, "owner" ) ),
.active = invalid_auth,//authority( chain.get_public_key( a, "active" ) ),
.recovery = authority( chain.get_public_key( a, "recovery" ) ),
.active = invalid_auth//authority( chain.get_public_key( a, "active" ) ),
});
chain.set_transaction_headers(trx);
......
......@@ -143,6 +143,41 @@ static const char entry_wast[] = R"=====(
)
)=====";
static const char entry_wast_2[] = R"=====(
(module
(import "env" "require_auth" (func $require_auth (param i64)))
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
(import "env" "current_time" (func $current_time (result i64)))
(table 0 anyfunc)
(memory $0 1)
(export "memory" (memory $0))
(export "apply" (func $apply))
(start $entry)
(func $apply (param $0 i64) (param $1 i64) (param $2 i64)
(block
(call $require_auth (i64.const 6121376101093867520))
(call $eosio_assert
(i64.eq
(i64.load offset=4
(i32.const 0)
)
(call $current_time)
)
(i32.const 0)
)
)
)
(func $entry
(block
(i64.store offset=4
(i32.const 0)
(call $current_time)
)
)
)
)
)=====";
static const char simple_no_memory_wast[] = R"=====(
(module
(import "env" "require_auth" (func $require_auth (param i64)))
......
......@@ -35,8 +35,7 @@ BOOST_FIXTURE_TEST_CASE( delay_create_account, validating_tester) { try {
.creator = creator,
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
set_transaction_headers(trx);
trx.delay_sec = 3;
......@@ -63,8 +62,7 @@ BOOST_FIXTURE_TEST_CASE( delay_error_create_account, validating_tester) { try {
.creator = N(bad), /// a does not exist, this should error when execute
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
set_transaction_headers(trx);
trx.delay_sec = 3;
......
......@@ -88,8 +88,7 @@ public:
.creator = creator,
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
trx.actions.emplace_back( get_action( N(eosio), N(buyrambytes), vector<permission_level>{{creator,config::active_name}},
......@@ -130,8 +129,7 @@ public:
.creator = creator,
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
trx.actions.emplace_back( get_action( N(eosio), N(buyram), vector<permission_level>{{creator,config::active_name}},
......
#include <boost/test/unit_test.hpp>
#include <eosio/testing/tester.hpp>
#include <eosio/chain/generated_transaction_object.hpp>
#include <eosio/chain/authorization_manager.hpp>
#ifdef NON_VALIDATING_TEST
#define TESTER tester
#else
#define TESTER validating_tester
#endif
using namespace eosio;
using namespace eosio::chain;
using namespace eosio::testing;
auto make_postrecovery(const TESTER &t, account_name account, string role) {
signed_transaction trx;
trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
postrecovery{
.account = account,
.auth = authority(t.get_public_key(account, role)),
.memo = "Test recovery"
} );
t.set_transaction_headers(trx);
trx.sign(t.get_private_key(account, "active"), chain_id_type());
return trx;
}
auto make_vetorecovery(const TESTER &t, account_name account, permission_name vetoperm = N(active), optional<private_key_type> signing_key = optional<private_key_type>()) {
signed_transaction trx;
trx.actions.emplace_back( vector<permission_level>{{account,vetoperm}},
vetorecovery{
.account = account
} );
t.set_transaction_headers(trx);
if (signing_key) {
trx.sign(*signing_key, chain_id_type());
} else {
trx.sign(t.get_private_key(account, (string)vetoperm), chain_id_type());
}
return trx;
}
BOOST_AUTO_TEST_SUITE(recovery_tests)
BOOST_FIXTURE_TEST_CASE( test_recovery_multisig_owner, TESTER ) try {
produce_block();
create_account(N(alice), config::system_account_name, true);
produce_block();
BOOST_REQUIRE_THROW(push_reqauth(N(alice), "owner"), tx_missing_sigs); // requires multisig authorization
push_reqauth(N(alice), "owner", true);
produce_block();
transaction_id_type recovery_txid;
{
signed_transaction trx = make_postrecovery(*this, N(alice), "owner.recov");
auto trace = push_transaction(trx);
auto gen_size = control->db().get_index<generated_transaction_multi_index,by_trx_id>().size();
BOOST_CHECK_EQUAL(1, gen_size);
recovery_txid = control->db().get_index<generated_transaction_multi_index,by_trx_id>().begin()->trx_id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(trx.id()), true);
}
authority org_auth = (authority)control->get_authorization_manager().get_permission({N(alice), N(owner)}).auth;
produce_block(fc::days(30)+fc::milliseconds(config::block_interval_ms));
authority auth = (authority)control->get_authorization_manager().get_permission({N(alice), N(owner)}).auth;
if (org_auth == auth) BOOST_TEST_FAIL("authority should have changed");
produce_block();
BOOST_REQUIRE_THROW(push_reqauth(N(alice), "owner", true), tx_missing_sigs);
auto first_new_nonce_id = push_reqauth(N(alice), "owner.recov")->id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( test_recovery_owner, TESTER ) try {
produce_block();
create_account(N(alice));
produce_block();
fc::time_point expected_recovery(fc::seconds(control->head_block_time().sec_since_epoch()) +fc::days(30));
transaction_id_type recovery_txid;
{
signed_transaction trx = make_postrecovery(*this, N(alice), "owner.recov");
auto trace = push_transaction(trx);
auto gen_size = control->db().get_index<generated_transaction_multi_index,by_trx_id>().size();
BOOST_CHECK_EQUAL(gen_size, 1);
recovery_txid = control->db().get_index<generated_transaction_multi_index,by_trx_id>().begin()->trx_id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(trx.id()), true);
}
auto skip_time = expected_recovery - control->head_block_time();
produce_block(skip_time);
auto last_old_nonce_id = push_reqauth(N(alice), "owner")->id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(last_old_nonce_id), true);
BOOST_REQUIRE_THROW(push_reqauth(N(alice), "owner"), tx_missing_sigs);
auto first_new_nonce_id = push_reqauth(N(alice), "owner.recov")->id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( test_recovery_owner_veto, TESTER ) try {
produce_block();
create_account(N(alice));
produce_block();
fc::time_point expected_recovery(fc::seconds(control->head_block_time().sec_since_epoch()) +fc::days(30));
transaction_id_type recovery_txid;
{
signed_transaction trx = make_postrecovery(*this, N(alice), "owner.recov");
auto trace = push_transaction(trx);
auto gen_size = control->db().get_index<generated_transaction_multi_index,by_trx_id>().size();
BOOST_CHECK_EQUAL(gen_size, 1);
recovery_txid = control->db().get_index<generated_transaction_multi_index,by_trx_id>().begin()->trx_id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(trx.id()), true);
}
auto skip_time = expected_recovery - control->head_block_time();
produce_block(skip_time);
auto last_old_nonce_id = push_reqauth(N(alice), "owner")->id;
// post the veto at the last possible time
{
signed_transaction trx = make_vetorecovery(*this, N(alice));
auto trace = push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(trx.id()), true);
}
BOOST_REQUIRE_EQUAL(chain_has_transaction(last_old_nonce_id), true);
// make sure the old owner is still in control
BOOST_REQUIRE_THROW(push_reqauth(N(alice), "owner.recov"), tx_missing_sigs);
auto first_new_nonce_id = push_reqauth(N(alice), "owner")->id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( test_recovery_bad_creator, TESTER ) try {
produce_block();
create_account(N(alice), config::system_account_name, true);
produce_block();
fc::time_point expected_recovery(fc::seconds(control->head_block_time().sec_since_epoch()) +fc::days(30));
transaction_id_type recovery_txid;
{
signed_transaction trx = make_postrecovery(*this, N(alice), "owner");
auto trace = push_transaction(trx);
auto gen_size = control->db().get_index<generated_transaction_multi_index,by_trx_id>().size();
BOOST_CHECK_EQUAL(gen_size, 1);
recovery_txid = control->db().get_index<generated_transaction_multi_index,by_trx_id>().begin()->trx_id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(trx.id()), true);
}
auto skip_time = expected_recovery - control->head_block_time();
produce_block(skip_time);
// try all types of veto from the bad partner
{
signed_transaction trx = make_vetorecovery(*this, N(alice), N(active), get_private_key(N(inita),"active"));
BOOST_REQUIRE_THROW(push_transaction(trx), tx_missing_sigs);
}
{
signed_transaction trx = make_vetorecovery(*this, N(alice), N(active), get_private_key(N(inita),"owner"));
BOOST_REQUIRE_THROW(push_transaction(trx), tx_missing_sigs);
}
{
signed_transaction trx = make_vetorecovery(*this, N(alice), N(owner), get_private_key(N(inita),"active"));
BOOST_REQUIRE_THROW(push_transaction(trx), tx_missing_sigs);
}
{
signed_transaction trx = make_vetorecovery(*this, N(alice), N(owner), get_private_key(N(inita),"owner"));
BOOST_REQUIRE_THROW(push_transaction(trx), tx_missing_sigs);
}
produce_block();
// make sure the recovery goes through
auto first_new_nonce_id = push_reqauth(N(alice), "owner")->id;
produce_block();
BOOST_REQUIRE_EQUAL(chain_has_transaction(first_new_nonce_id), true);
} FC_LOG_AND_RETHROW()
BOOST_AUTO_TEST_SUITE_END()
......@@ -670,6 +670,31 @@ BOOST_FIXTURE_TEST_CASE( check_entry_behavior, TESTER ) try {
BOOST_CHECK_EQUAL(transaction_receipt::executed, receipt.status);
} FC_LOG_AND_RETHROW()
BOOST_FIXTURE_TEST_CASE( check_entry_behavior_2, TESTER ) try {
produce_blocks(2);
create_accounts( {N(entrycheck)} );
produce_block();
set_code(N(entrycheck), entry_wast_2);
produce_blocks(10);
signed_transaction trx;
action act;
act.account = N(entrycheck);
act.name = N();
act.authorization = vector<permission_level>{{N(entrycheck),config::active_name}};
trx.actions.push_back(act);
set_transaction_headers(trx);
trx.sign(get_private_key( N(entrycheck), "active" ), chain_id_type());
push_transaction(trx);
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
const auto& receipt = get_transaction_receipt(trx.id());
BOOST_CHECK_EQUAL(transaction_receipt::executed, receipt.status);
} FC_LOG_AND_RETHROW()
/**
* Ensure we can load a wasm w/o memory
*/
......@@ -1023,8 +1048,7 @@ BOOST_FIXTURE_TEST_CASE(eosio_abi, TESTER) try {
.creator = config::system_account_name,
.name = a,
.owner = owner_auth,
.active = authority( get_public_key( a, "active" ) ),
.recovery = authority( get_public_key( a, "recovery" ) ),
.active = authority( get_public_key( a, "active" ) )
});
set_transaction_headers(trx);
trx.sign( get_private_key( config::system_account_name, "active" ), chain_id_type() );
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册