提交 6e41c1bd 编写于 作者: B Bart Wyatt

refactor into an explicit `packed_transaction` and wire that through controller plugins etc

上级 1af6e5c0
......@@ -30,7 +30,7 @@ add_library( eosio_chain
${HEADERS}
)
transaction_metadata.cpp)
target_link_libraries( eosio_chain eos_utilities fc chainbase Logging IR WAST WASM Runtime )
target_include_directories( eosio_chain
......
......@@ -124,16 +124,6 @@ optional<signed_block> chain_controller::fetch_block_by_number(uint32_t num)cons
return optional<signed_block>();
}
/*
const signed_transaction& chain_controller::get_recent_transaction(const transaction_id_type& trx_id) const
{
auto& index = _db.get_index<transaction_multi_index, by_trx_id>();
auto itr = index.find(trx_id);
FC_ASSERT(itr != index.end());
return itr->trx;
}
*/
std::vector<block_id_type> chain_controller::get_block_ids_on_fork(block_id_type head_of_fork) const
{
pair<fork_database::branch_type, fork_database::branch_type> branches = _fork_db.fetch_branch_from(head_block_id(), head_of_fork);
......@@ -250,7 +240,7 @@ bool chain_controller::_push_block(const signed_block& new_block)
* queues full as well, it will be kept in the queue to be propagated later when a new block flushes out the pending
* queues.
*/
transaction_trace chain_controller::push_transaction(const signed_transaction& trx, uint32_t skip)
transaction_trace chain_controller::push_transaction(const packed_transaction& trx, uint32_t skip)
{ try {
return with_skip_flags(skip, [&]() {
return _db.with_write_lock([&]() {
......@@ -259,17 +249,17 @@ transaction_trace chain_controller::push_transaction(const signed_transaction& t
});
} FC_CAPTURE_AND_RETHROW((trx)) }
transaction_trace chain_controller::_push_transaction(const signed_transaction& trx) {
check_transaction_authorization(trx);
transaction_trace chain_controller::_push_transaction(const packed_transaction& trx) {
transaction_metadata mtrx( trx, get_chain_id(), head_block_time());
check_transaction_authorization(mtrx.trx, trx.signatures);
auto result = _push_transaction(mtrx);
_pending_block->input_transactions.push_back(trx);
auto result = _push_transaction(std::move(mtrx));
// notify anyone listening to pending transactions
on_pending_transaction(trx);
_pending_block->input_transactions.emplace_back(trx);
return result;
}
......@@ -286,7 +276,7 @@ static void record_locks_for_data_access(const vector<action_trace>& action_trac
}
}
transaction_trace chain_controller::_push_transaction( transaction_metadata& data )
transaction_trace chain_controller::_push_transaction( transaction_metadata&& data )
{
const transaction& trx = data.trx;
// If this is the first transaction pushed after applying a block, start a new undo session.
......@@ -326,6 +316,8 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata& dat
// The transaction applied successfully. Merge its changes into the pending block session.
temp_session.squash();
_pending_transaction_metas.emplace_back(std::forward<transaction_metadata>(data));
return result;
}
......@@ -483,7 +475,7 @@ signed_block chain_controller::_generate_block( block_timestamp_type when,
_pending_block->producer = producer_obj.owner;
_pending_block->previous = head_block_id();
_pending_block->block_mroot = get_dynamic_global_properties().block_merkle_root.get_root();
_pending_block->transaction_mroot = _pending_block->calculate_transaction_merkle_root();
_pending_block->transaction_mroot = transaction_metadata::calculate_transaction_merkle_root( _pending_transaction_metas );
_pending_block->action_mroot = _pending_block_trace->calculate_action_merkle_root();
......@@ -588,9 +580,11 @@ void chain_controller::__apply_block(const signed_block& next_block)
/// cache the input tranasction ids so that they can be looked up when executing the
/// summary
map<transaction_id_type,const signed_transaction*> trx_index;
vector<transaction_metadata> input_metas;
map<transaction_id_type,transaction_metadata*> trx_index;
for( const auto& t : next_block.input_transactions ) {
trx_index[t.get_transaction().id()] = &t;
input_metas.emplace_back(t, chain_id_type(), next_block.timestamp);
trx_index[input_metas.back().id] = &input_metas.back();
}
block_trace next_block_trace(next_block);
......@@ -639,25 +633,27 @@ void chain_controller::__apply_block(const signed_block& next_block)
shard_trace s_trace;
for (const auto& receipt : shard.transactions) {
auto make_metadata = [&](){
optional<transaction_metadata> _temp;
auto make_metadata = [&]() -> transaction_metadata* {
auto itr = trx_index.find(receipt.id);
if( itr != trx_index.end() ) {
return transaction_metadata( *itr->second, get_chain_id(), next_block.timestamp );
return itr->second;
} else {
const auto& gtrx = _db.get<generated_transaction_object,by_trx_id>(receipt.id);
auto trx = fc::raw::unpack<deferred_transaction>(gtrx.packed_trx.data(), gtrx.packed_trx.size());
return transaction_metadata(trx, gtrx.published, trx.sender, trx.sender_id, gtrx.packed_trx.data(), gtrx.packed_trx.size() );
_temp.emplace(trx, gtrx.published, trx.sender, trx.sender_id, gtrx.packed_trx.data(), gtrx.packed_trx.size() );
return &*_temp;
}
};
auto mtrx = make_metadata();
mtrx.region_id = r.region;
mtrx.cycle_index = cycle_index;
mtrx.shard_index = shard_index;
mtrx.allowed_read_locks.emplace(&shard.read_locks);
mtrx.allowed_write_locks.emplace(&shard.write_locks);
auto *mtrx = make_metadata();
mtrx->region_id = r.region;
mtrx->cycle_index = cycle_index;
mtrx->shard_index = shard_index;
mtrx->allowed_read_locks.emplace(&shard.read_locks);
mtrx->allowed_write_locks.emplace(&shard.write_locks);
s_trace.transaction_traces.emplace_back(_apply_transaction(mtrx));
s_trace.transaction_traces.emplace_back(_apply_transaction(*mtrx));
record_locks_for_data_access(s_trace.transaction_traces.back().action_traces, used_read_locks, used_write_locks);
FC_ASSERT(receipt.status == s_trace.transaction_traces.back().status);
......@@ -690,19 +686,19 @@ void chain_controller::__apply_block(const signed_block& next_block)
} /// for each region
FC_ASSERT(next_block.action_mroot == next_block_trace.calculate_action_merkle_root());
FC_ASSERT( transaction_metadata::calculate_transaction_merkle_root(input_metas) == next_block.transaction_mroot, "merkle root does not match" );
_finalize_block( next_block_trace );
_finalize_block( next_block_trace );
} FC_CAPTURE_AND_RETHROW( (next_block.block_num()) ) }
flat_set<public_key_type> chain_controller::get_required_keys(const signed_transaction& trx,
const flat_set<public_key_type>& candidate_keys)const
flat_set<public_key_type> chain_controller::get_required_keys(const transaction& trx,
const flat_set<public_key_type>& candidate_keys)const
{
auto checker = make_auth_checker( [&](const permission_level& p){ return get_permission(p).auth; },
get_global_properties().configuration.max_authority_depth,
candidate_keys);
const auto decompressed = trx.get_transaction();
for (const auto& act : decompressed.actions ) {
for (const auto& act : trx.actions ) {
for (const auto& declared_auth : act.authorization) {
if (!checker.satisfied(declared_auth)) {
EOS_ASSERT(checker.satisfied(declared_auth), tx_missing_sigs,
......@@ -756,11 +752,11 @@ void chain_controller::check_authorization( const vector<action>& actions,
("keys", checker.unused_keys()));
}
void chain_controller::check_transaction_authorization(const signed_transaction& trx,
void chain_controller::check_transaction_authorization(const transaction& trx,
const vector<signature_type>& signatures,
bool allow_unused_signatures)const
{
auto decompressed = trx.get_transaction();
check_authorization( decompressed.actions, trx.get_signature_keys( chain_id_type{} ), allow_unused_signatures );
check_authorization( trx.actions, trx.get_signature_keys( signatures, chain_id_type{} ), allow_unused_signatures );
}
optional<permission_name> chain_controller::lookup_minimum_permission(account_name authorizer_account,
......@@ -790,10 +786,10 @@ optional<permission_name> chain_controller::lookup_minimum_permission(account_na
} FC_CAPTURE_AND_RETHROW((authorizer_account)(scope)(act_name))
}
void chain_controller::validate_uniqueness( const signed_transaction& trx )const {
void chain_controller::validate_uniqueness( const transaction& trx )const {
if( !should_check_for_duplicate_transactions() ) return;
auto transaction = _db.find<transaction_object, by_trx_id>(trx.get_transaction().id());
auto transaction = _db.find<transaction_object, by_trx_id>(trx.id());
EOS_ASSERT(transaction == nullptr, tx_duplicate, "transaction is not unique");
}
......@@ -885,8 +881,6 @@ const producer_object& chain_controller::validate_block_header(uint32_t skip, co
}
FC_ASSERT( next_block.calculate_transaction_merkle_root() == next_block.transaction_mroot, "merkle root does not match" );
return producer;
}
......@@ -1082,14 +1076,14 @@ void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
ctrace.shard_traces.emplace_back();
auto& strace = ctrace.shard_traces.back();
transaction genesis_setup_transaction; // not actually signed, signature checking is skipped
signed_transaction genesis_setup_transaction; // not actually signed, signature checking is skipped
genesis_setup_transaction.actions = move(acts);
block.input_transactions.emplace_back(genesis_setup_transaction, signed_transaction::zlib);
block.input_transactions.emplace_back(genesis_setup_transaction);
ilog( "applying genesis transaction" );
with_skip_flags(skip_scope_check | skip_transaction_signatures | skip_authority_check | received_block | genesis_setup,
[&](){
transaction_metadata tmeta( genesis_setup_transaction );
transaction_metadata tmeta( packed_transaction(genesis_setup_transaction), chain_id_type(), initial_timestamp );
transaction_trace ttrace = __apply_transaction( tmeta );
strace.append(ttrace);
});
......@@ -1452,7 +1446,7 @@ transaction_trace chain_controller::_apply_error( transaction_metadata& meta ) {
transaction etrx;
etrx.actions.emplace_back(vector<permission_level>{{meta.sender_id,config::active_name}},
contracts::onerror(meta.generated_data, meta.generated_data + meta.generated_size) );
contracts::onerror(meta.raw_data, meta.raw_data + meta.raw_size) );
try {
auto temp_session = _db.start_undo_session(true);
......@@ -1524,7 +1518,7 @@ void chain_controller::push_deferred_transactions( bool flush )
try {
auto trx = fc::raw::unpack<deferred_transaction>(trx_p->packed_trx.data(), trx_p->packed_trx.size());
transaction_metadata mtrx (trx, trx_p->published, trx.sender, trx.sender_id, trx_p->packed_trx.data(), trx_p->packed_trx.size());
_push_transaction(mtrx);
_push_transaction(std::move(mtrx));
generated_transaction_idx.remove(*trx_p);
} FC_CAPTURE_AND_LOG((trx_p->trx_id)(trx_p->sender));
} else {
......
......@@ -113,7 +113,7 @@ namespace eosio { namespace chain {
*/
struct signed_block : public signed_block_summary {
digest_type calculate_transaction_merkle_root()const;
vector<signed_transaction> input_transactions; /// this is loaded and indexed into map<id,trx> that is referenced by summary
vector<packed_transaction> input_transactions; /// this is loaded and indexed into map<id,trx> that is referenced by summary
};
struct shard_trace {
......
......@@ -76,7 +76,7 @@ namespace eosio { namespace chain {
void push_block( const signed_block& b, uint32_t skip = skip_nothing );
transaction_trace push_transaction( const signed_transaction& trx, uint32_t skip = skip_nothing );
transaction_trace push_transaction( const packed_transaction& trx, uint32_t skip = skip_nothing );
void push_deferred_transactions( bool flush = false );
......@@ -104,7 +104,7 @@ namespace eosio { namespace chain {
* This signal is emitted any time a new transaction is added to the pending
* block state.
*/
signal<void(const signed_transaction&)> on_pending_transaction;
signal<void(const packed_transaction&)> on_pending_transaction;
......@@ -164,7 +164,7 @@ namespace eosio { namespace chain {
* @return Subset of candidate_keys whose private keys should be used to sign transaction
* @throws fc::exception if candidate_keys does not contain all required keys
*/
flat_set<public_key_type> get_required_keys(const signed_transaction& trx, const flat_set<public_key_type>& candidate_keys)const;
flat_set<public_key_type> get_required_keys(const transaction& trx, const flat_set<public_key_type>& candidate_keys)const;
bool _push_block( const signed_block& b );
......@@ -199,19 +199,19 @@ namespace eosio { namespace chain {
template<typename Function>
auto without_pending_transactions( Function&& f )
{
vector<signed_transaction> old_input;
vector<transaction_metadata> old_input;
if( _pending_block )
old_input = move(_pending_block->input_transactions);
old_input = move(_pending_transaction_metas);
clear_pending();
/** after applying f() push previously input transactions on top */
auto on_exit = fc::make_scoped_exit( [&](){
for( const auto& t : old_input ) {
for( auto& t : old_input ) {
try {
if (!is_known_transaction(t.get_transaction().id()))
push_transaction( t );
if (!is_known_transaction(t.id))
_push_transaction( std::move(t) );
} catch ( ... ){}
}
});
......@@ -310,8 +310,8 @@ namespace eosio { namespace chain {
//@}
transaction_trace _push_transaction( const signed_transaction& trx );
transaction_trace _push_transaction( transaction_metadata& data );
transaction_trace _push_transaction( const packed_transaction& trx );
transaction_trace _push_transaction( transaction_metadata&& data );
transaction_trace _apply_transaction( transaction_metadata& data );
transaction_trace __apply_transaction( transaction_metadata& data );
transaction_trace _apply_error( transaction_metadata& data );
......@@ -338,7 +338,8 @@ namespace eosio { namespace chain {
return f();
}
void check_transaction_authorization(const signed_transaction& trx,
void check_transaction_authorization(const transaction& trx,
const vector<signature_type>& signatures,
bool allow_unused_signatures = false)const;
......@@ -361,7 +362,7 @@ namespace eosio { namespace chain {
} FC_CAPTURE_AND_RETHROW( (trx) ) }
/// Validate transaction helpers @{
void validate_uniqueness(const signed_transaction& trx)const;
void validate_uniqueness(const transaction& trx)const;
void validate_tapos(const transaction& trx)const;
void validate_referenced_accounts(const transaction& trx)const;
void validate_expiration(const transaction& trx) const;
......@@ -418,7 +419,7 @@ namespace eosio { namespace chain {
optional<database::session> _pending_block_session;
optional<signed_block> _pending_block;
optional<block_trace> _pending_block_trace;
uint32_t _pending_transaction_count = 0;
vector<transaction_metadata> _pending_transaction_metas;
optional<cycle_trace> _pending_cycle_trace;
bool _currently_applying_block = false;
......
......@@ -94,6 +94,7 @@ namespace impl {
template<typename T>
constexpr bool single_type_requires_abi_v() {
return std::is_base_of<transaction, T>::value ||
std::is_same<T, packed_transaction>::value ||
std::is_same<T, action>::value ||
std::is_same<T, transaction_trace>::value ||
std::is_same<T, action_trace>::value;
......@@ -135,6 +136,85 @@ namespace impl {
template<typename T>
using require_abi_t = std::enable_if_t<type_requires_abi_v<T>(), int>;
struct abi_to_variant {
/**
* template which overloads add for types which are not relvant to ABI information
* and can be degraded to the normal ::to_variant(...) processing
*/
template<typename M, typename Resolver, not_require_abi_t<M> = 1>
static void add( mutable_variant_object &mvo, const char* name, const M& v, Resolver )
{
mvo(name,v);
}
/**
* template which overloads add for types which contain ABI information in their trees
* for these types we create new ABI aware visitors
*/
template<typename M, typename Resolver, require_abi_t<M> = 1>
static void add( mutable_variant_object &mvo, const char* name, const M& v, Resolver resolver );
/**
* template which overloads add for vectors of types which contain ABI information in their trees
* for these members we call ::add in order to trigger further processing
*/
template<typename M, typename Resolver, require_abi_t<M> = 1>
static void add( mutable_variant_object &mvo, const char* name, const vector<M>& v, Resolver resolver )
{
vector<variant> array(v.size());
for (const auto& iter: v) {
mutable_variant_object elem_mvo;
add(elem_mvo, "_", iter, resolver);
array.emplace_back(std::move(elem_mvo["_"]));
}
mvo(name, std::move(array));
}
/**
* overload of to_variant_object for actions
* @tparam Resolver
* @param act
* @param resolver
* @return
*/
template<typename Resolver>
static void add(mutable_variant_object &out, const char* name, const action& act, Resolver resolver) {
mutable_variant_object mvo;
mvo("account", act.account);
mvo("name", act.name);
mvo("authorization", act.authorization);
auto abi = resolver(act.account);
if (abi.valid()) {
auto type = abi->get_action_type(act.name);
mvo("data", abi->binary_to_variant(type, act.data));
mvo("hex_data", act.data);
} else {
mvo("data", act.data);
}
out(name, std::move(mvo));
}
/**
* overload of to_variant_object for packed_transaction
* @tparam Resolver
* @param act
* @param resolver
* @return
*/
template<typename Resolver>
static void add(mutable_variant_object &out, const char* name, const packed_transaction& ptrx, Resolver resolver) {
mutable_variant_object mvo;
mvo("signatures", ptrx.signatures);
mvo("compression", ptrx.compression);
mvo("data", ptrx.data);
transaction trx = ptrx.get_transaction();
add(mvo, "transaction", trx, resolver);
out(name, std::move(mvo));
}
};
/**
* Reflection visitor that uses a resolver to resolve ABIs for nested types
* this will degrade to the common fc::to_variant as soon as the type no longer contains
......@@ -162,77 +242,110 @@ namespace impl {
template<typename Member, class Class, Member (Class::*member) >
void operator()( const char* name )const
{
this->add(_vo,name,(_val.*member));
abi_to_variant::add(_vo, name, (_val.*member), _resolver);
}
private:
mutable_variant_object& _vo;
const T& _val;
Resolver _resolver;
};
/**
* template which overloads add for types which are not relvant to ABI information
* and can be degraded to the normal ::to_variant(...) processing
*/
template<typename M, not_require_abi_t<M> = 1>
void add( mutable_variant_object& vo, const char* name, const M& v )const
{
vo(name,v);
struct abi_from_variant {
/**
* template which overloads extract for types which are not relvant to ABI information
* and can be degraded to the normal ::from_variant(...) processing
*/
template<typename M, typename Resolver, not_require_abi_t<M> = 1>
static void extract( const variant& v, M& o, Resolver )
{
from_variant(v, o);
}
/**
* template which overloads extract for types which contain ABI information in their trees
* for these types we create new ABI aware visitors
*/
template<typename M, typename Resolver, require_abi_t<M> = 1>
static void extract( const variant& v, M& o, Resolver resolver );
/**
* template which overloads extract for vectors of types which contain ABI information in their trees
* for these members we call ::extract in order to trigger further processing
*/
template<typename M, typename Resolver, require_abi_t<M> = 1>
static void extract( const variant& v, vector<M>& o, Resolver resolver )
{
const variants& array = v.get_array();
o.clear();
o.reserve( array.size() );
for( auto itr = array.begin(); itr != array.end(); ++itr ) {
M o_iter;
extract(*itr, o_iter, resolver);
o.emplace_back(std::move(o_iter));
}
}
/**
* template which overloads add for types which contain ABI information in their trees
* for these types we create new ABI aware visitors
*/
template<typename M, require_abi_t<M> = 1>
void add( mutable_variant_object& vo, const char* name, const M& v )const
{
mutable_variant_object mvo;
fc::reflector<M>::visit( impl::abi_to_variant_visitor<M, decltype(_resolver)>( mvo, v, _resolver ) );
vo(name, std::move(mvo));
/**
* Non templated overload that has priority for the action structure
* this type has members which must be directly translated by the ABI so it is
* exploded and processed explicitly
*/
template<typename Resolver>
static void extract( const variant& v, action& act, Resolver resolver )
{
const variant_object& vo = v.get_object();
FC_ASSERT(vo.contains("account"));
FC_ASSERT(vo.contains("name"));
from_variant(vo["account"], act.account);
from_variant(vo["name"], act.name);
if (vo.contains("authorization")) {
from_variant(vo["authorization"], act.authorization);
}
/**
* template which overloads add for vectors of types which contain ABI information in their trees
* for these members we call ::add in order to trigger further processing
*/
template<typename M, require_abi_t<M> = 1>
void add( mutable_variant_object& vo, const char* name, const vector<M>& v )const
{
vector<variant> array(v.size());
for (const auto& iter: v) {
mutable_variant_object mvo;
add(mvo, "_", iter);
array.emplace_back(std::move(mvo["_"]));
if( vo.contains( "data" ) ) {
const auto& data = vo["data"];
if( data.is_string() ) {
from_variant(data, act.data);
} else if ( data.is_object() ) {
auto abi = resolver(act.account);
if (abi.valid()) {
auto type = abi->get_action_type(act.name);
act.data = std::move(abi->variant_to_binary(type, data));
}
}
vo(name, std::move(array));
}
/**
* Non templated overload that has priority for the action structure
* this type has members which must be directly translated by the ABI so it is
* exploded and processed explicitly
*/
void add( mutable_variant_object& vo, const char* name, const action& v )const
{
mutable_variant_object mvo;
mvo("account", v.account);
mvo("name", v.name);
mvo("authorization", v.authorization);
auto abi = _resolver(v.account);
if (abi.valid()) {
auto type = abi->get_action_type(v.name);
mvo("data", abi->binary_to_variant(type, v.data));
mvo("hex_data", v.data);
} else {
mvo("data", v.data);
if (act.data.empty()) {
if( vo.contains( "hex_data" ) ) {
const auto& data = vo["hex_data"];
if( data.is_string() ) {
from_variant(data, act.data);
}
}
vo(name, std::move( mvo ));
}
FC_ASSERT(!act.data.empty(), "Failed to deserialize data for ${account}:${name}", ("account", act.account)("name", act.name));
}
mutable_variant_object& _vo;
const T& _val;
Resolver _resolver;
template<typename Resolver>
static void extract( const variant& v, packed_transaction& ptrx, Resolver resolver ) {
const variant_object& vo = v.get_object();
FC_ASSERT(vo.contains("signatures"));
FC_ASSERT(vo.contains("compression"));
from_variant(vo["signatures"], ptrx.signatures);
from_variant(vo["compression"], ptrx.compression);
if (vo.contains("data") && vo["data"].is_string() && !vo["data"].as_string().empty()) {
from_variant(vo["data"], ptrx.data);
} else {
FC_ASSERT(vo.contains("transaction"));
transaction trx;
extract(vo["transaction"], trx, resolver);
ptrx.set_transaction(trx, ptrx.compression);
}
}
};
/**
......@@ -264,109 +377,40 @@ namespace impl {
{
auto itr = _vo.find(name);
if( itr != _vo.end() )
extract( itr->value(), _val.*member );
abi_from_variant::extract( itr->value(), _val.*member, _resolver );
}
private:
/**
* template which overloads extract for types which are not relvant to ABI information
* and can be degraded to the normal ::from_variant(...) processing
*/
template<typename M, not_require_abi_t<M> = 1>
void extract( const variant& v, M& o )const
{
from_variant(v, o);
}
/**
* template which overloads extract for types which contain ABI information in their trees
* for these types we create new ABI aware visitors
*/
template<typename M, require_abi_t<M> = 1>
void extract( const variant& v, M& o )const
{
const variant_object& vo = v.get_object();
fc::reflector<M>::visit( abi_from_variant_visitor<M, decltype(_resolver)>( vo, o, _resolver ) );
}
/**
* template which overloads extract for vectors of types which contain ABI information in their trees
* for these members we call ::extract in order to trigger further processing
*/
template<typename M, require_abi_t<M> = 1>
void extract( const variant& v, vector<M>& o )const
{
const variants& array = v.get_array();
o.clear();
o.reserve( array.size() );
for( auto itr = array.begin(); itr != array.end(); ++itr ) {
M o_iter;
extract(*itr, o_iter);
o.emplace_back(std::move(o_iter));
}
}
/**
* Non templated overload that has priority for the action structure
* this type has members which must be directly translated by the ABI so it is
* exploded and processed explicitly
*/
void extract( const variant& v, action& act )const
{
const variant_object& vo = v.get_object();
FC_ASSERT(vo.contains("account"));
FC_ASSERT(vo.contains("name"));
from_variant(vo["account"], act.account);
from_variant(vo["name"], act.name);
if (vo.contains("authorization")) {
from_variant(vo["authorization"], act.authorization);
}
if( vo.contains( "data" ) ) {
const auto& data = vo["data"];
if( data.is_string() ) {
from_variant(data, act.data);
} else if ( data.is_object() ) {
auto abi = _resolver(act.account);
if (abi.valid()) {
auto type = abi->get_action_type(act.name);
act.data = std::move(abi->variant_to_binary(type, data));
}
}
}
if (act.data.empty()) {
if( vo.contains( "hex_data" ) ) {
const auto& data = vo["hex_data"];
if( data.is_string() ) {
from_variant(data, act.data);
}
}
}
FC_ASSERT(!act.data.empty(), "Failed to deserialize data for ${account}:${name}", ("account", act.account)("name", act.name));
}
const variant_object& _vo;
T& _val;
Resolver _resolver;
};
template<typename M, typename Resolver, require_abi_t<M>>
void abi_to_variant::add( mutable_variant_object &mvo, const char* name, const M& v, Resolver resolver ) {
mutable_variant_object member_mvo;
fc::reflector<M>::visit( impl::abi_to_variant_visitor<M, Resolver>( member_mvo, v, resolver ) );
mvo(name, std::move(member_mvo));
}
template<typename M, typename Resolver, require_abi_t<M>>
void abi_from_variant::extract( const variant& v, M& o, Resolver resolver ) {
const variant_object& vo = v.get_object();
fc::reflector<M>::visit( abi_from_variant_visitor<M, decltype(resolver)>( vo, o, resolver ) );
}
}
template<typename T, typename Resolver>
void abi_serializer::to_variant( const T& o, variant& vo, Resolver resolver ) try {
mutable_variant_object mvo;
fc::reflector<T>::visit( impl::abi_to_variant_visitor<T, Resolver>( mvo, o, resolver ) );
vo = std::move(mvo);
impl::abi_to_variant::add(mvo, "_", o, resolver);
vo = std::move(mvo["_"]);
} FC_RETHROW_EXCEPTIONS(error, "Failed to serialize type", ("object",o))
template<typename T, typename Resolver>
void abi_serializer::from_variant( const variant& v, T& o, Resolver resolver ) try {
const variant_object& vo = v.get_object();
fc::reflector<T>::visit( impl::abi_from_variant_visitor<T, Resolver>( vo, o, resolver ) );
impl::abi_from_variant::extract(v, o, resolver);
} FC_RETHROW_EXCEPTIONS(error, "Failed to deserialize variant", ("variant",v))
......
......@@ -134,20 +134,52 @@ namespace eosio { namespace chain {
struct transaction : public transaction_header {
vector<action> actions;
transaction_id_type id()const;
digest_type sig_digest( const chain_id_type& chain_id )const;
transaction_id_type id()const;
digest_type sig_digest( const chain_id_type& chain_id )const;
flat_set<public_key_type> get_signature_keys( const vector<signature_type>& signatures, const chain_id_type& chain_id )const;
};
struct signed_transaction : public transaction
{
signed_transaction() = default;
// signed_transaction( const signed_transaction& ) = default;
// signed_transaction( signed_transaction&& ) = default;
signed_transaction( transaction&& trx, const vector<signature_type>& signatures)
: transaction(std::forward<transaction>(trx))
, signatures(signatures)
{
}
vector<signature_type> signatures;
const signature_type& sign(const private_key_type& key, const chain_id_type& chain_id);
signature_type sign(const private_key_type& key, const chain_id_type& chain_id)const;
flat_set<public_key_type> get_signature_keys( const chain_id_type& chain_id )const;
};
struct signed_transaction {
struct packed_transaction {
enum compression_type {
none,
zlib,
};
signed_transaction() = default;
packed_transaction() = default;
explicit packed_transaction(const transaction& t, compression_type _compression = none)
{
set_transaction(t, _compression);
}
explicit packed_transaction(const signed_transaction& t, compression_type _compression = none)
:signatures(t.signatures)
{
set_transaction(t, _compression);
}
signed_transaction(const transaction& t, signed_transaction::compression_type _compression) {
explicit packed_transaction(signed_transaction&& t, compression_type _compression = none)
:signatures(std::move(t.signatures))
{
set_transaction(t, _compression);
}
......@@ -155,11 +187,11 @@ namespace eosio { namespace chain {
compression_type compression;
bytes data;
const signature_type& sign(const private_key_type& key, const chain_id_type& chain_id);
signature_type sign(const private_key_type& key, const chain_id_type& chain_id)const;
flat_set<public_key_type> get_signature_keys( const chain_id_type& chain_id )const;
bytes get_raw_transaction()const;
transaction get_transaction()const;
void set_transaction(const transaction& t, signed_transaction::compression_type _compression);
signed_transaction get_signed_transaction()const;
void set_transaction(const transaction& t, compression_type _compression = none);
};
......@@ -222,8 +254,9 @@ FC_REFLECT( eosio::chain::permission_level, (actor)(permission) )
FC_REFLECT( eosio::chain::action, (account)(name)(authorization)(data) )
FC_REFLECT( eosio::chain::transaction_header, (expiration)(region)(ref_block_num)(ref_block_prefix) )
FC_REFLECT_DERIVED( eosio::chain::transaction, (eosio::chain::transaction_header), (actions) )
FC_REFLECT_ENUM( eosio::chain::signed_transaction::compression_type, (none)(zlib))
FC_REFLECT( eosio::chain::signed_transaction, (signatures)(compression)(data) )
FC_REFLECT_DERIVED( eosio::chain::signed_transaction, (eosio::chain::transaction), (signatures) )
FC_REFLECT_ENUM( eosio::chain::packed_transaction::compression_type, (none)(zlib))
FC_REFLECT( eosio::chain::packed_transaction, (signatures)(compression)(data) )
FC_REFLECT_DERIVED( eosio::chain::deferred_transaction, (eosio::chain::transaction), (sender_id)(sender)(execute_after) )
FC_REFLECT_ENUM( eosio::chain::data_access_info::access_type, (read)(write))
FC_REFLECT( eosio::chain::data_access_info, (type)(code)(scope)(sequence))
......
......@@ -9,28 +9,27 @@
namespace eosio { namespace chain {
struct transaction_metadata {
transaction_metadata( const transaction& t )
:trx(t)
,id(trx.id()) {}
// transaction_metadata( const transaction& t )
// :trx(t)
// ,id(trx.id()) {}
transaction_metadata( const transaction& t, const time_point& published, const account_name& sender, uint32_t sender_id, const char* generated_data, size_t generated_size )
transaction_metadata( const transaction& t, const time_point& published, const account_name& sender, uint32_t sender_id, const char* raw_data, size_t raw_size )
:trx(t)
,id(trx.id())
,published(published)
,sender(sender),sender_id(sender_id),generated_data(generated_data),generated_size(generated_size)
,sender(sender),sender_id(sender_id),raw_data(raw_data),raw_size(raw_size)
{}
transaction_metadata( const signed_transaction& t, chain_id_type chainid, const time_point& published )
:decompressed_trx(t.get_transaction())
,trx(*decompressed_trx)
,id(trx.id())
,bandwidth_usage( (uint32_t)fc::raw::pack_size(t) )
,published(published)
{ }
transaction_metadata( const packed_transaction& t, chain_id_type chainid, const time_point& published );
transaction_metadata( transaction_metadata && ) = default;
transaction_metadata& operator= (transaction_metadata &&) = default;
// things for signed_transactions
// things for packed_transaction
optional<bytes> raw_trx;
optional<transaction> decompressed_trx;
// things for signed/packed transactions
optional<flat_set<public_key_type>> signing_keys;
const transaction& trx;
......@@ -45,12 +44,16 @@ struct transaction_metadata {
// things for processing deferred transactions
optional<account_name> sender;
uint32_t sender_id = 0;
const char* generated_data = nullptr;
size_t generated_size = 0;
// packed form to pass to contracts if needed
const char* raw_data = nullptr;
size_t raw_size = 0;
// scopes available to this transaction if we are applying a block
optional<const vector<shard_lock>*> allowed_read_locks;
optional<const vector<shard_lock>*> allowed_write_locks;
static digest_type calculate_transaction_merkle_root( const vector<transaction_metadata>& metas );
};
} } // eosio::chain
......
......@@ -37,8 +37,8 @@ BOOST_AUTO_TEST_SUITE(transaction_test)
trx.actions.emplace_back(vector<permission_level>{{N(decomp), config::active_name}},
test_action {"random data here"});
signed_transaction t;
t.set_transaction(trx, signed_transaction::zlib);
packed_transaction t;
t.set_transaction(trx, packed_transaction::zlib);
auto actual = fc::to_hex(t.data);
BOOST_CHECK_EQUAL(expected, actual);
......@@ -58,10 +58,10 @@ BOOST_AUTO_TEST_SUITE(transaction_test)
char compressed_tx_raw[] = "78da63606060d8bf7ff5eab2198ace8c13962fe3909cb0f114835aa9248866044a3284784ef402d12bde1a19090a1425e6a5e4e72aa42496242a64a416a50200a9d114bb";
signed_transaction t;
packed_transaction t;
t.data.resize((sizeof(compressed_tx_raw) - 1) / 2);
fc::from_hex(compressed_tx_raw, t.data.data(), t.data.size());
t.compression= signed_transaction::zlib;
t.compression= packed_transaction::zlib;
auto actual = t.get_transaction();
BOOST_CHECK_EQUAL(expected.region, actual.region);
......
......@@ -71,31 +71,21 @@ digest_type transaction::sig_digest( const chain_id_type& chain_id )const {
return enc.result();
}
const signature_type& signed_transaction::sign(const private_key_type& key, const chain_id_type& chain_id) {
signatures.push_back(key.sign(get_transaction().sig_digest(chain_id)));
return signatures.back();
}
signature_type signed_transaction::sign(const private_key_type& key, const chain_id_type& chain_id)const {
return key.sign(get_transaction().sig_digest(chain_id));
}
flat_set<public_key_type> signed_transaction::get_signature_keys( const chain_id_type& chain_id )const
flat_set<public_key_type> transaction::get_signature_keys( const vector<signature_type>& signatures, const chain_id_type& chain_id )const
{ try {
using boost::adaptors::transformed;
constexpr size_t recovery_cache_size = 100000;
static recovery_cache_type recovery_cache;
const auto trx = get_transaction();
const digest_type digest = trx.sig_digest(chain_id);
const digest_type digest = sig_digest(chain_id);
flat_set<public_key_type> recovered_pub_keys;
for(const signature_type& sig : signatures) {
recovery_cache_type::index<by_sig>::type::iterator it = recovery_cache.get<by_sig>().find(sig);
if(it == recovery_cache.get<by_sig>().end() || it->trx_id != trx.id()) {
if(it == recovery_cache.get<by_sig>().end() || it->trx_id != id()) {
public_key_type recov = public_key_type(sig, digest);
recovery_cache.emplace_back( cached_pub_key{trx.id(), recov, sig} ); //could fail on dup signatures; not a problem
recovery_cache.emplace_back( cached_pub_key{id(), recov, sig} ); //could fail on dup signatures; not a problem
recovered_pub_keys.insert(recov);
continue;
}
......@@ -108,6 +98,21 @@ flat_set<public_key_type> signed_transaction::get_signature_keys( const chain_id
return recovered_pub_keys;
} FC_CAPTURE_AND_RETHROW() }
const signature_type& signed_transaction::sign(const private_key_type& key, const chain_id_type& chain_id) {
signatures.push_back(key.sign(sig_digest(chain_id)));
return signatures.back();
}
signature_type signed_transaction::sign(const private_key_type& key, const chain_id_type& chain_id)const {
return key.sign(sig_digest(chain_id));
}
flat_set<public_key_type> signed_transaction::get_signature_keys( const chain_id_type& chain_id )const
{
return transaction::get_signature_keys(signatures, chain_id);
}
namespace bio = boost::iostreams;
template<size_t Limit>
......@@ -149,6 +154,24 @@ static transaction zlib_decompress_transaction(const bytes& data) {
}
}
static bytes zlib_decompress(const bytes& data) {
try {
bytes out;
bio::filtering_ostream decomp;
decomp.push(bio::zlib_decompressor());
decomp.push(read_limiter<10*1024*1024>()); // limit to 10 megs decompressed for zip bomb protections
decomp.push(bio::back_inserter(out));
bio::write(decomp, data.data(), data.size());
bio::close(decomp);
return out;
} catch( fc::exception& er ) {
throw;
} catch( ... ) {
fc::unhandled_exception er( FC_LOG_MESSAGE( warn, "internal decompression error"), std::current_exception() );
throw er;
}
}
static bytes pack_transaction(const transaction& t) {
return fc::raw::pack(t);
}
......@@ -164,7 +187,21 @@ static bytes zlib_compress_transaction(const transaction& t) {
return out;
}
transaction signed_transaction::get_transaction()const
bytes packed_transaction::get_raw_transaction() const
{
try {
switch(compression) {
case none:
return data;
case zlib:
return zlib_decompress(data);
default:
FC_THROW("Unknown transaction compression algorithm");
}
} FC_CAPTURE_AND_RETHROW((compression)(data))
}
transaction packed_transaction::get_transaction()const
{
try {
switch(compression) {
......@@ -178,7 +215,12 @@ transaction signed_transaction::get_transaction()const
} FC_CAPTURE_AND_RETHROW((compression)(data))
}
void signed_transaction::set_transaction(const transaction& t, signed_transaction::compression_type _compression)
signed_transaction packed_transaction::get_signed_transaction() const
{
return signed_transaction(get_transaction(), signatures);
}
void packed_transaction::set_transaction(const transaction& t, packed_transaction::compression_type _compression)
{
try {
switch(_compression) {
......
#include <eosio/chain/transaction_metadata.hpp>
#include <eosio/chain/merkle.hpp>
#include <fc/io/raw.hpp>
namespace eosio { namespace chain {
transaction_metadata::transaction_metadata( const packed_transaction& t, chain_id_type chainid, const time_point& published )
:raw_trx(t.get_raw_transaction())
,decompressed_trx(fc::raw::unpack<transaction>(*raw_trx))
,trx(*decompressed_trx)
,id(decompressed_trx->id())
,bandwidth_usage( (uint32_t)fc::raw::pack_size(t) )
,published(published)
,raw_data(raw_trx->data())
,raw_size(raw_trx->size())
{ }
digest_type transaction_metadata::calculate_transaction_merkle_root( const vector<transaction_metadata>& metas ) {
vector<digest_type> ids;
ids.reserve(metas.size());
for( const auto& t : metas )
ids.emplace_back( t.id );
return merkle( std::move(ids) );
}
} } // eosio::chain
\ No newline at end of file
......@@ -22,6 +22,7 @@ namespace eosio { namespace testing {
signed_block produce_block( fc::microseconds skip_time = fc::milliseconds(config::block_interval_ms) );
void produce_blocks( uint32_t n = 1 );
transaction_trace push_transaction( packed_transaction& trx );
transaction_trace push_transaction( signed_transaction& trx );
void set_tapos( signed_transaction& trx ) const;
......
......@@ -113,14 +113,18 @@ namespace eosio { namespace testing {
.deposit = initial_balance
});
trx.sign( get_private_key( creator, "active" ), chain_id_type() );
set_tapos(trx);
trx.sign( get_private_key( creator, "active" ), chain_id_type() );
push_transaction( trx );
}
control->push_transaction( trx );
transaction_trace tester::push_transaction( packed_transaction& trx ) {
return control->push_transaction( trx );
}
transaction_trace tester::push_transaction( signed_transaction& trx ) {
set_tapos(trx);
return control->push_transaction( trx );
auto ptrx = packed_transaction(trx);
return push_transaction( ptrx );
}
void tester::create_account( account_name a, string initial_balance, account_name creator, bool multisig ) {
......@@ -141,8 +145,9 @@ namespace eosio { namespace testing {
.memo = memo
} );
trx.sign( get_private_key( from, "active" ), chain_id_type() );
return control->push_transaction( trx );
set_tapos(trx);
trx.sign( get_private_key( from, "active" ), chain_id_type() );
return push_transaction( trx );
}
void tester::set_authority( account_name account,
......@@ -160,7 +165,7 @@ namespace eosio { namespace testing {
set_tapos( trx );
trx.sign( get_private_key( account, "active" ), chain_id_type() );
control->push_transaction( trx );
push_transaction( trx );
} FC_CAPTURE_AND_RETHROW( (account)(perm)(auth)(parent) ) }
void tester::set_code( account_name account, const char* wast ) try {
......@@ -218,7 +223,7 @@ namespace eosio { namespace testing {
set_tapos( trx );
trx.sign( get_private_key( account, "active" ), chain_id_type() );
control->push_transaction( trx );
push_transaction( trx );
} FC_CAPTURE_AND_RETHROW( (account)(wast) )
void tester::set_abi( account_name account, const char* abi_json) {
......@@ -232,7 +237,7 @@ namespace eosio { namespace testing {
set_tapos( trx );
trx.sign( get_private_key( account, "active" ), chain_id_type() );
control->push_transaction( trx );
push_transaction( trx );
}
bool tester::chain_has_transaction( const transaction_id_type& txid ) const {
......
......@@ -34,7 +34,7 @@ using chain::block_id_type;
using chain::key_weight;
using chain::permission_level_weight;
using chain::permission_name;
using chain::signed_transaction;
using chain::packed_transaction;
using chain::signed_block;
using boost::multi_index_container;
using chain::transaction_id_type;
......@@ -44,12 +44,12 @@ using get_transactions_results = account_history_apis::read_only::get_transactio
class account_history_plugin_impl {
public:
signed_transaction get_transaction(const chain::transaction_id_type& transaction_id) const;
packed_transaction get_transaction(const chain::transaction_id_type& transaction_id) const;
get_transactions_results get_transactions(const account_name& account_name, const optional<uint32_t>& skip_seq, const optional<uint32_t>& num_seq) const;
vector<account_name> get_key_accounts(const public_key_type& public_key) const;
vector<account_name> get_controlled_accounts(const account_name& controlling_account) const;
void applied_block(const chain::block_trace&);
fc::variant transaction_to_variant(const signed_transaction& pretty_input) const;
fc::variant transaction_to_variant(const packed_transaction& pretty_input) const;
chain_plugin* chain_plug;
static const int64_t DEFAULT_TRANSACTION_TIME_LIMIT;
......@@ -67,7 +67,7 @@ private:
typedef std::multimap<block_id_type, transaction_id_type, block_comp> block_transaction_id_map;
optional<block_id_type> find_block_id(const chainbase::database& db, const transaction_id_type& transaction_id) const;
signed_transaction find_transaction(const chain::transaction_id_type& transaction_id, const signed_block& block) const;
packed_transaction find_transaction(const chain::transaction_id_type& transaction_id, const signed_block& block) const;
bool is_scope_relevant(const vector<account_name>& scope);
get_transactions_results ordered_transactions(const block_transaction_id_map& block_transaction_ids, const fc::time_point& start_time, const uint32_t begin, const uint32_t end) const;
static void add(chainbase::database& db, const vector<key_weight>& keys, const account_name& account_name, const permission_name& permission);
......@@ -113,17 +113,17 @@ optional<block_id_type> account_history_plugin_impl::find_block_id(const chainba
return block_id;
}
signed_transaction account_history_plugin_impl::find_transaction(const chain::transaction_id_type& transaction_id, const chain::signed_block& block) const
packed_transaction account_history_plugin_impl::find_transaction(const chain::transaction_id_type& transaction_id, const chain::signed_block& block) const
{
for (const signed_transaction& trx : block.input_transactions)
if (trx.id() == transaction_id)
for (const packed_transaction& trx : block.input_transactions)
if (trx.get_transaction().id() == transaction_id)
return trx;
// ERROR in indexing logic
FC_THROW("Transaction with ID ${tid} was indexed as being in block ID ${bid}, but was not found in that block", ("tid", transaction_id)("bid", block.id()));
}
signed_transaction account_history_plugin_impl::get_transaction(const chain::transaction_id_type& transaction_id) const
packed_transaction account_history_plugin_impl::get_transaction(const chain::transaction_id_type& transaction_id) const
{
const auto& db = chain_plug->chain().get_database();
optional<block_id_type> block_id;
......@@ -215,12 +215,13 @@ get_transactions_results account_history_plugin_impl::ordered_transactions(const
}
for (auto trx = block->input_transactions.crbegin(); trx != block->input_transactions.crend() && current < trx_after_block; ++trx)
{
if(trans_ids_for_block.count(trx->id()))
transaction_id_type trx_id = trx->get_transaction().id();
if(trans_ids_for_block.count(trx_id))
{
if(++current > begin)
{
const auto pretty_trx = transaction_to_variant(*trx);
results.transactions.emplace_back(ordered_transaction_results{(current - 1), trx->id(), pretty_trx});
results.transactions.emplace_back(ordered_transaction_results{(current - 1), trx_id, pretty_trx});
if(current >= end)
{
......@@ -405,7 +406,7 @@ bool account_history_plugin_impl::is_scope_relevant(const vector<account_name>&
return false;
}
fc::variant account_history_plugin_impl::transaction_to_variant(const signed_transaction& txn) const
fc::variant account_history_plugin_impl::transaction_to_variant(const packed_transaction& ptrx) const
{
const chainbase::database& database = chain_plug->chain().get_database();
auto resolver = [&database]( const account_name& name ) -> optional<abi_serializer> {
......@@ -421,7 +422,7 @@ fc::variant account_history_plugin_impl::transaction_to_variant(const signed_tra
};
fc::variant pretty_output;
abi_serializer::to_variant(txn, pretty_output, resolver);
abi_serializer::to_variant(ptrx, pretty_output, resolver);
return pretty_output;
}
......
......@@ -230,7 +230,7 @@ bool chain_plugin::accept_block(const signed_block& block, bool currently_syncin
return true;
}
void chain_plugin::accept_transaction(const signed_transaction& trx) {
void chain_plugin::accept_transaction(const packed_transaction& trx) {
chain().push_transaction(trx, my->skip_flags);
}
......@@ -387,7 +387,7 @@ read_write::push_block_results read_write::push_block(const read_write::push_blo
}
read_write::push_transaction_results read_write::push_transaction(const read_write::push_transaction_params& params) {
signed_transaction pretty_input;
packed_transaction pretty_input;
auto resolver = [&,this]( const account_name& name ) -> optional<abi_serializer> {
const auto* accnt = db.get_database().find<account_object,by_name>( name );
if (accnt != nullptr) {
......@@ -405,7 +405,7 @@ read_write::push_transaction_results read_write::push_transaction(const read_wri
#warning TODO: get transaction results asynchronously
fc::variant pretty_output;
abi_serializer::to_variant(result, pretty_output, resolver);
return read_write::push_transaction_results{ pretty_input.id(), pretty_output };
return read_write::push_transaction_results{ result.id, pretty_output };
}
read_write::push_transactions_results read_write::push_transactions(const read_write::push_transactions_params& params) {
......@@ -504,9 +504,9 @@ read_only::abi_bin_to_json_result read_only::abi_bin_to_json( const read_only::a
}
read_only::get_required_keys_result read_only::get_required_keys( const get_required_keys_params& params )const {
signed_transaction pretty_input;
packed_transaction pretty_input;
from_variant(params.transaction, pretty_input);
auto required_keys_set = db.get_required_keys(pretty_input, params.available_keys);
auto required_keys_set = db.get_required_keys(pretty_input.get_transaction(), params.available_keys);
get_required_keys_result result;
result.required_keys = required_keys_set;
return result;
......
......@@ -340,7 +340,7 @@ public:
chain_apis::read_write get_read_write_api();
bool accept_block(const chain::signed_block& block, bool currently_syncing);
void accept_transaction(const chain::signed_transaction& trx);
void accept_transaction(const chain::packed_transaction& trx);
bool block_is_on_preferred_chain(const chain::block_id_type& block_id);
......
......@@ -240,7 +240,7 @@ struct faucet_testnet_plugin_impl {
trx.sign(_create_account_private_key, chainid);
try {
cc.push_transaction(trx);
cc.push_transaction(packed_transaction(trx));
} catch (const account_name_exists_exception& ) {
// another transaction ended up adding the account, so look for alternates
return find_alternates(new_account_name);
......
......@@ -197,7 +197,7 @@ namespace eosio {
// template<typename VerifierFunc>
// void send_all(net_message_ptr msg, VerifierFunc verify);
void send_all_txn(const signed_transaction& txn);
static void transaction_ready( const signed_transaction& txn);
static void transaction_ready( const packed_transaction& txn);
void broadcast_block_impl( const signed_block &sb);
size_t cache_txn( const transaction_id_type, const signed_transaction &txn);
......@@ -1915,7 +1915,8 @@ namespace eosio {
}
try {
chain_plug->accept_transaction( msg );
// TODO: avoid this reserialization by adjusting messages to deal with packed transactions.
chain_plug->accept_transaction( packed_transaction(msg) );
fc_dlog(logger, "chain accepted transaction" );
} catch( const fc::exception &ex) {
// received a block due to out of sequence
......@@ -2199,8 +2200,10 @@ namespace eosio {
/**
* This one is necessary to hook into the boost notifier api
**/
void net_plugin_impl::transaction_ready( const signed_transaction& txn) {
my_impl->send_all_txn( txn );
void net_plugin_impl::transaction_ready( const packed_transaction& txn) {
// TODO: avoid this reserialization by updating protocol to use packed_transactions directly
auto strx = signed_transaction(txn.get_transaction(), txn.signatures);
my_impl->send_all_txn( strx );
}
void net_plugin_impl::broadcast_block_impl( const chain::signed_block &sb) {
......
......@@ -93,7 +93,7 @@ struct txn_test_gen_plugin_impl {
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, contracts::newaccount{creator, newaccountB, owner_auth, active_auth, recovery_auth, stake});
}
trx.sign(creator_priv_key, chainid);
cc.push_transaction(trx);
cc.push_transaction(packed_transaction(trx));
//now, transfer some balance to new accounts
{
......@@ -104,7 +104,7 @@ struct txn_test_gen_plugin_impl {
trx.expiration = cc.head_block_time() + fc::seconds(30);
trx.set_reference_block(cc.head_block_id());
trx.sign(creator_priv_key, chainid);
cc.push_transaction(trx);
cc.push_transaction(packed_transaction(trx));
}
}
......@@ -156,7 +156,7 @@ struct txn_test_gen_plugin_impl {
fc::crypto::private_key creator_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'a')));
trx.sign(creator_priv_key, chainid);
cc.push_transaction(trx);
cc.push_transaction(packed_transaction(trx));
}
//make transaction b->a
......@@ -168,7 +168,7 @@ struct txn_test_gen_plugin_impl {
fc::crypto::private_key b_priv_key = fc::crypto::private_key::regenerate(fc::sha256(std::string(64, 'b')));
trx.sign(b_priv_key, chainid);
cc.push_transaction(trx);
cc.push_transaction(packed_transaction(trx));
}
}
......
......@@ -69,9 +69,9 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
} );
test.set_tapos( trx );
BOOST_REQUIRE_THROW( test.control->push_transaction( trx ), tx_missing_sigs );
BOOST_REQUIRE_THROW( test.push_transaction( trx ), tx_missing_sigs );
trx.sign( test.get_private_key( from, "active" ), chain_id_type() );
test.control->push_transaction( trx );
test.push_transaction( trx );
}
{
......@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
test.set_tapos( trx );
trx.sign( test.get_private_key( to, "active" ), chain_id_type() );
/// action not provided from authority
BOOST_REQUIRE_THROW( test.control->push_transaction( trx ), tx_missing_auth);
BOOST_REQUIRE_THROW( test.push_transaction( trx ), tx_missing_auth);
}
} FC_LOG_AND_RETHROW() } /// transfer_test
......@@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
wdump((fc::raw::pack_size(trx)));
/// action not provided from authority
test.control->push_transaction( trx );
test.push_transaction( trx );
}
} FC_LOG_AND_RETHROW() }
......
......@@ -89,7 +89,7 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(currency), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
......@@ -113,7 +113,7 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(currency), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
......@@ -137,7 +137,7 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(alice), "active"), chain_id_type());
BOOST_CHECK_EXCEPTION(control->push_transaction(trx), fc::assert_exception, assert_message_is("integer underflow subtracting token balance"));
BOOST_CHECK_EXCEPTION(push_transaction(trx), fc::assert_exception, assert_message_is("integer underflow subtracting token balance"));
produce_block();
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(trx.id()));
......@@ -162,7 +162,7 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(alice), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
......
......@@ -98,7 +98,7 @@ BOOST_FIXTURE_TEST_CASE( basic_test, tester ) try {
set_tapos( trx );
trx.sign( get_private_key( N(asserter), "active" ), chain_id_type() );
auto result = control->push_transaction( trx );
auto result = push_transaction( trx );
BOOST_CHECK_EQUAL(result.status, transaction_receipt::executed);
BOOST_CHECK_EQUAL(result.action_traces.size(), 1);
BOOST_CHECK_EQUAL(result.action_traces.at(0).receiver.to_string(), name(N(asserter)).to_string() );
......@@ -126,7 +126,7 @@ BOOST_FIXTURE_TEST_CASE( basic_test, tester ) try {
trx.sign( get_private_key( N(asserter), "active" ), chain_id_type() );
yes_assert_id = trx.id();
BOOST_CHECK_THROW(control->push_transaction( trx ), fc::assert_exception);
BOOST_CHECK_THROW(push_transaction( trx ), fc::assert_exception);
}
produce_blocks(1);
......@@ -158,7 +158,7 @@ BOOST_FIXTURE_TEST_CASE( prove_mem_reset, tester ) try {
set_tapos( trx );
trx.sign( get_private_key( N(asserter), "active" ), chain_id_type() );
control->push_transaction( trx );
push_transaction( trx );
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
const auto& receipt = get_transaction_receipt(trx.id());
......@@ -213,7 +213,7 @@ BOOST_FIXTURE_TEST_CASE( abi_from_variant, tester ) try {
abi_serializer::from_variant(pretty_trx, trx, resolver);
set_tapos( trx );
trx.sign( get_private_key( N(asserter), "active" ), chain_id_type() );
control->push_transaction( trx );
push_transaction( trx );
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
const auto& receipt = get_transaction_receipt(trx.id());
......@@ -239,7 +239,7 @@ BOOST_FIXTURE_TEST_CASE( test_api_bootstrap, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(tester), "active"), chain_id_type());
BOOST_CHECK_EXCEPTION(control->push_transaction(trx), fc::assert_exception, assert_message_is("test_action::assert_false"));
BOOST_CHECK_EXCEPTION(push_transaction(trx), fc::assert_exception, assert_message_is("test_action::assert_false"));
produce_block();
BOOST_REQUIRE_EQUAL(false, chain_has_transaction(trx.id()));
......@@ -252,7 +252,7 @@ BOOST_FIXTURE_TEST_CASE( test_api_bootstrap, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(tester), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
......@@ -294,7 +294,7 @@ BOOST_FIXTURE_TEST_CASE( test_proxy, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(proxy), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
}
......@@ -351,7 +351,7 @@ BOOST_FIXTURE_TEST_CASE( test_deferred_failure, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(proxy), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
}
......@@ -392,7 +392,7 @@ BOOST_FIXTURE_TEST_CASE( test_deferred_failure, tester ) try {
set_tapos(trx);
trx.sign(get_private_key(N(bob), "active"), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_block();
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
}
......@@ -440,7 +440,7 @@ BOOST_FIXTURE_TEST_CASE( check_entry_behavior, tester ) try {
set_tapos(trx);
trx.sign(get_private_key( N(entrycheck), "active" ), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
const auto& receipt = get_transaction_receipt(trx.id());
......@@ -469,7 +469,7 @@ BOOST_FIXTURE_TEST_CASE( simple_no_memory_check, tester ) try {
trx.actions.push_back(act);
trx.sign(get_private_key( N(nomem), "active" ), chain_id_type());
BOOST_CHECK_THROW(control->push_transaction( trx ), wasm_execution_error);
BOOST_CHECK_THROW(push_transaction( trx ), wasm_execution_error);
} FC_LOG_AND_RETHROW()
//Make sure globals are all reset to their inital values
......@@ -492,7 +492,7 @@ BOOST_FIXTURE_TEST_CASE( check_global_reset, tester ) try {
set_tapos(trx);
trx.sign(get_private_key( N(globalreset), "active" ), chain_id_type());
control->push_transaction(trx);
push_transaction(trx);
produce_blocks(1);
BOOST_REQUIRE_EQUAL(true, chain_has_transaction(trx.id()));
const auto& receipt = get_transaction_receipt(trx.id());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册