提交 6960bcb1 编写于 作者: B Bart Wyatt

Addressing changes from review

上级 ed2c4b38
......@@ -30,11 +30,11 @@ void apply_context::exec_one()
}
} FC_CAPTURE_AND_RETHROW((_pending_console_output.str()));
if (_write_scopes.empty()) {
if (!_write_scopes.empty()) {
std::sort(_write_scopes.begin(), _write_scopes.end());
}
if (_read_locks.empty()) {
if (!_read_locks.empty()) {
std::sort(_read_locks.begin(), _read_locks.end());
// remove any write_scopes
auto r_iter = _read_locks.begin();
......@@ -101,7 +101,7 @@ void apply_context::exec()
}
for( uint32_t i = 0; i < _inline_actions.size(); ++i ) {
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta, allowed_read_locks, allowed_write_locks);
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta);
ncontext.exec();
append_results(move(ncontext.results));
}
......@@ -132,8 +132,8 @@ static bool locks_contain(const vector<shard_lock>& locks, const account_name& a
}
void apply_context::require_write_lock(const scope_name& scope) {
if (allowed_write_locks) {
EOS_ASSERT( locks_contain(*allowed_write_locks, receiver, scope), tx_missing_write_lock, "missing write lock \"${a}::${s}\"", ("a", receiver)("s",scope) );
if (trx_meta.allowed_write_locks) {
EOS_ASSERT( locks_contain(**trx_meta.allowed_write_locks, receiver, scope), block_lock_exception, "write lock \"${a}::${s}\" required but not provided", ("a", receiver)("s",scope) );
}
if (!scopes_contain(_write_scopes, scope)) {
......@@ -142,8 +142,8 @@ void apply_context::require_write_lock(const scope_name& scope) {
}
void apply_context::require_read_lock(const account_name& account, const scope_name& scope) {
if (allowed_read_locks) {
EOS_ASSERT( locks_contain(*allowed_read_locks, account, scope), tx_missing_read_lock, "missing read lock \"${a}::${s}\"", ("a", account)("s",scope) );
if (trx_meta.allowed_read_locks) {
EOS_ASSERT( locks_contain(**trx_meta.allowed_read_locks, account, scope), block_lock_exception, "read lock \"${a}::${s}\" required but not provided", ("a", account)("s",scope) );
}
if (!locks_contain(_read_locks, account, scope)) {
......
......@@ -270,6 +270,18 @@ transaction_trace chain_controller::_push_transaction(const signed_transaction&
}
static void record_locks_for_data_access(const vector<action_trace>& action_traces, vector<shard_lock>& read_locks, vector<shard_lock>& write_locks ) {
for (const auto& at: action_traces) {
for (const auto& access: at.data_access) {
if (access.type == data_access_info::read) {
read_locks.emplace_back(shard_lock{at.receiver, access.scope});
} else {
write_locks.emplace_back(shard_lock{at.receiver, access.scope});
}
}
}
}
transaction_trace chain_controller::_push_transaction( transaction_metadata& data )
{
const transaction& trx = data.trx;
......@@ -298,15 +310,7 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata& dat
auto& bcycle = _pending_block->regions.back().cycles_summary.back();
auto& bshard = bcycle.front();
for (const auto& at: result.action_traces) {
for (const auto& access: at.data_access) {
if (access.type == data_access_info::read) {
bshard.read_locks.emplace_back(shard_lock{at.receiver, access.scope});
} else {
bshard.write_locks.emplace_back(shard_lock{at.receiver, access.scope});
}
}
}
record_locks_for_data_access(result.action_traces, bshard.read_locks, bshard.write_locks);
fc::deduplicate(bshard.read_locks);
fc::deduplicate(bshard.write_locks);
......@@ -553,10 +557,10 @@ static void validate_shard_locks(const vector<shard_lock>& locks, const string&
return;
}
for (auto cur = locks.begin() + 1; cur < locks.end(); cur++) {
for (auto cur = locks.begin() + 1; cur != locks.end(); ++cur) {
auto prev = cur - 1;
FC_ASSERT(*prev != *cur, "${tag} lock \"${a}::${s}\" is not unique", ("tag",tag)("a",cur->account)("s",cur->scope));
FC_ASSERT(*prev < *cur, "${tag} locks are not sorted", ("tag",tag));
EOS_ASSERT(*prev != *cur, block_lock_exception, "${tag} lock \"${a}::${s}\" is not unique", ("tag",tag)("a",cur->account)("s",cur->scope));
EOS_ASSERT(*prev < *cur, block_lock_exception, "${tag} locks are not sorted", ("tag",tag));
}
}
......@@ -610,19 +614,25 @@ void chain_controller::__apply_block(const signed_block& next_block)
validate_shard_locks(shard.write_locks, "write");
for (const auto& s: shard.read_locks) {
FC_ASSERT(write_locks.count(s) == 0,
EOS_ASSERT(write_locks.count(s) == 0, block_concurrency_exception,
"shard ${i} requires read lock \"${a}::${s}\" which is locked for write by shard ${j}",
("i", shard_index)("s", s)("j", write_locks[s]));
read_locks.emplace(s);
}
for (const auto& s: shard.write_locks) {
FC_ASSERT(write_locks.count(s) == 0,
EOS_ASSERT(write_locks.count(s) == 0, block_concurrency_exception,
"shard ${i} requires write lock \"${a}::${s}\" which is locked for write by shard ${j}",
("i", shard_index)("s", s)("j", write_locks[s]));
("i", shard_index)("a", s.account)("s", s.scope)("j", write_locks[s]));
EOS_ASSERT(read_locks.count(s) == 0, block_concurrency_exception,
"shard ${i} requires write lock \"${a}::${s}\" which is locked for read",
("i", shard_index)("a", s.account)("s", s.scope));
write_locks[s] = shard_index;
}
vector<shard_lock> used_read_locks;
vector<shard_lock> used_write_locks;
shard_trace s_trace;
for (const auto& receipt : shard.transactions) {
auto make_metadata = [&](){
......@@ -640,8 +650,11 @@ void chain_controller::__apply_block(const signed_block& next_block)
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, &shard.read_locks, &shard.write_locks));
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);
......@@ -651,6 +664,16 @@ void chain_controller::__apply_block(const signed_block& next_block)
// check_transaction_authorization(trx, true);
} /// for each transaction id
// Validate that the producer didn't list extra locks to bloat the size of the block
// TODO: this check can be removed when blocks are irreversible
fc::deduplicate(used_read_locks);
fc::deduplicate(used_write_locks);
EOS_ASSERT(std::equal(used_read_locks.cbegin(), used_read_locks.cend(), shard.read_locks.begin()),
block_lock_exception, "Read locks for executing shard: ${s} do not match those listed in the block", ("s", shard_index));
EOS_ASSERT(std::equal(used_write_locks.cbegin(), used_write_locks.cend(), shard.write_locks.begin()),
block_lock_exception, "Write locks for executing shard: ${s} do not match those listed in the block", ("s", shard_index));
s_trace.calculate_root();
c_trace.shard_traces.emplace_back(move(s_trace));
} /// for each shard
......@@ -1355,10 +1378,10 @@ static void log_handled_exceptions(const transaction& trx) {
} FC_CAPTURE_AND_LOG((trx));
}
transaction_trace chain_controller::__apply_transaction( transaction_metadata& meta, const vector<shard_lock>* allowed_read_locks, const vector<shard_lock>* allowed_write_locks ) {
transaction_trace chain_controller::__apply_transaction( transaction_metadata& meta ) {
transaction_trace result(meta.id);
for (const auto &act : meta.trx.actions) {
apply_context context(*this, _db, act, meta, allowed_read_locks, allowed_write_locks);
apply_context context(*this, _db, act, meta);
context.exec();
fc::move_append(result.action_traces, std::move(context.results.applied_actions));
fc::move_append(result.deferred_transactions, std::move(context.results.generated_transactions));
......@@ -1382,10 +1405,10 @@ transaction_trace chain_controller::__apply_transaction( transaction_metadata& m
return result;
}
transaction_trace chain_controller::_apply_transaction( transaction_metadata& meta, const vector<shard_lock>* allowed_read_locks, const vector<shard_lock>* allowed_write_locks ) {
transaction_trace chain_controller::_apply_transaction( transaction_metadata& meta ) {
try {
auto temp_session = _db.start_undo_session(true);
auto result = __apply_transaction(meta, allowed_read_locks, allowed_write_locks);
auto result = __apply_transaction(meta);
temp_session.squash();
return result;
} catch (...) {
......@@ -1396,11 +1419,11 @@ transaction_trace chain_controller::_apply_transaction( transaction_metadata& me
// log exceptions we can handle with the error handle, throws otherwise
log_handled_exceptions(meta.trx);
return _apply_error( meta, allowed_read_locks, allowed_write_locks );
return _apply_error( meta );
}
}
transaction_trace chain_controller::_apply_error( transaction_metadata& meta, const vector<shard_lock>* allowed_read_locks, const vector<shard_lock>* allowed_write_locks ) {
transaction_trace chain_controller::_apply_error( transaction_metadata& meta ) {
transaction_trace result(meta.id);
result.status = transaction_trace::soft_fail;
......@@ -1411,7 +1434,7 @@ transaction_trace chain_controller::_apply_error( transaction_metadata& meta, co
try {
auto temp_session = _db.start_undo_session(true);
apply_context context(*this, _db, etrx.actions.front(), meta, allowed_read_locks, allowed_write_locks);
apply_context context(*this, _db, etrx.actions.front(), meta);
context.exec();
fc::move_append(result.action_traces, std::move(context.results.applied_actions));
fc::move_append(result.deferred_transactions, std::move(context.results.generated_transactions));
......
......@@ -5,6 +5,7 @@
#pragma once
#include <eosio/chain/block.hpp>
#include <eosio/chain/transaction.hpp>
#include <eosio/chain/transaction_metadata.hpp>
#include <eosio/chain/contracts/contract_table_objects.hpp>
#include <fc/utility.hpp>
#include <sstream>
......@@ -18,11 +19,11 @@ class chain_controller;
class apply_context {
public:
apply_context(chain_controller& con, chainbase::database& db, const action& a, const transaction_metadata& trx_meta, const vector<shard_lock>* allowed_read_locks, const vector<shard_lock>* allowed_write_locks)
apply_context(chain_controller& con, chainbase::database& db, const action& a, const transaction_metadata& trx_meta)
:controller(con), db(db), act(a), mutable_controller(con),
mutable_db(db), used_authorizations(act.authorization.size(), false),
trx_meta(trx_meta), allowed_read_locks(allowed_read_locks), allowed_write_locks(allowed_write_locks) {}
trx_meta(trx_meta) {}
void exec();
......@@ -108,8 +109,6 @@ class apply_context {
vector<bool> used_authorizations;
const transaction_metadata& trx_meta;
const vector<shard_lock>* allowed_read_locks;
const vector<shard_lock>* allowed_write_locks;
///< pending transaction construction
/*
......
......@@ -311,9 +311,9 @@ namespace eosio { namespace chain {
transaction_trace _push_transaction( const signed_transaction& trx );
transaction_trace _push_transaction( transaction_metadata& data );
transaction_trace _apply_transaction( transaction_metadata& data, const vector<shard_lock>* allowed_read_locks = nullptr, const vector<shard_lock>* allowed_write_locks = nullptr );
transaction_trace __apply_transaction( transaction_metadata& data, const vector<shard_lock>* allowed_read_locks = nullptr, const vector<shard_lock>* allowed_write_locks = nullptr );
transaction_trace _apply_error( transaction_metadata& data, const vector<shard_lock>* allowed_read_locks = nullptr, const vector<shard_lock>* allowed_write_locks = nullptr );
transaction_trace _apply_transaction( transaction_metadata& data );
transaction_trace __apply_transaction( transaction_metadata& data );
transaction_trace _apply_error( transaction_metadata& data );
/// Reset the object graph in-memory
void _initialize_indexes();
......
......@@ -22,7 +22,9 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( unknown_block_exception, eosio::chain::chain_exception, 3110000, "unknown block" )
FC_DECLARE_DERIVED_EXCEPTION( block_tx_output_exception, eosio::chain::block_validate_exception, 3020001, "transaction outputs in block do not match transaction outputs from applying block" )
FC_DECLARE_DERIVED_EXCEPTION( block_concurrency_exception, eosio::chain::block_validate_exception, 3020002, "block does not guarantee concurrent exection without conflicts" )
FC_DECLARE_DERIVED_EXCEPTION( block_lock_exception, eosio::chain::block_validate_exception, 3020003, "shard locks in block are incorrect or mal-formed" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_auth, eosio::chain::transaction_exception, 3030001, "missing required authority" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_sigs, eosio::chain::transaction_exception, 3030002, "signatures do not satisfy declared authorizations" )
FC_DECLARE_DERIVED_EXCEPTION( tx_irrelevant_auth, eosio::chain::transaction_exception, 3030003, "irrelevant authority included" )
......@@ -41,9 +43,7 @@ namespace eosio { namespace chain {
FC_DECLARE_DERIVED_EXCEPTION( unsatisfied_permission, eosio::chain::transaction_exception, 3030017, "Unsatisfied permission" )
FC_DECLARE_DERIVED_EXCEPTION( tx_msgs_auth_exceeded, eosio::chain::transaction_exception, 3030018, "Number of transaction messages per authorized account has been exceeded" )
FC_DECLARE_DERIVED_EXCEPTION( tx_msgs_code_exceeded, eosio::chain::transaction_exception, 3030019, "Number of transaction messages per code account has been exceeded" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_read_lock, eosio::chain::transaction_exception, 3030020, "missing required read lock" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_write_lock, eosio::chain::transaction_exception, 3030021, "missing required write lock" )
FC_DECLARE_DERIVED_EXCEPTION( wasm_execution_error, eosio::chain::transaction_exception, 3030022, "Runtime Error Processing WASM" )
FC_DECLARE_DERIVED_EXCEPTION( wasm_execution_error, eosio::chain::transaction_exception, 3030020, "Runtime Error Processing WASM" )
FC_DECLARE_DERIVED_EXCEPTION( account_name_exists_exception, eosio::chain::action_validate_exception, 3040001, "account name already exists" )
FC_DECLARE_DERIVED_EXCEPTION( invalid_pts_address, eosio::chain::utility_exception, 3060001, "invalid pts address" )
......
......@@ -194,43 +194,6 @@ namespace eosio { namespace chain {
vector<deferred_transaction> deferred_transactions;
vector<deferred_reference> canceled_deferred;
};
struct transaction_metadata {
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 )
:trx(t)
,id(trx.id())
,published(published)
,sender(sender),sender_id(sender_id),generated_data(generated_data),generated_size(generated_size)
{}
transaction_metadata( const signed_transaction& t, chain_id_type chainid, const time_point& published )
:trx(t)
,id(trx.id())
,bandwidth_usage( fc::raw::pack_size(t) )
,published(published)
{ }
const transaction& trx;
transaction_id_type id;
optional<flat_set<public_key_type>> signing_keys;
uint32_t region_id = 0;
uint32_t cycle_index = 0;
uint32_t shard_index = 0;
uint32_t bandwidth_usage = 0;
time_point published;
// things for processing deferred transactions
optional<account_name> sender;
uint32_t sender_id = 0;
const char* generated_data = nullptr;
size_t generated_size = 0;
};
} } // eosio::chain
FC_REFLECT( eosio::chain::permission_level, (actor)(permission) )
......
/**
* @file
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/transaction.hpp>
#include <eosio/chain/block.hpp>
namespace eosio { namespace chain {
struct transaction_metadata {
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 )
:trx(t)
,id(trx.id())
,published(published)
,sender(sender),sender_id(sender_id),generated_data(generated_data),generated_size(generated_size)
{}
transaction_metadata( const signed_transaction& t, chain_id_type chainid, const time_point& published )
:trx(t)
,id(trx.id())
,bandwidth_usage( fc::raw::pack_size(t) )
,published(published)
{ }
const transaction& trx;
transaction_id_type id;
optional<flat_set<public_key_type>> signing_keys;
uint32_t region_id = 0;
uint32_t cycle_index = 0;
uint32_t shard_index = 0;
uint32_t bandwidth_usage = 0;
time_point published;
// things for processing deferred transactions
optional<account_name> sender;
uint32_t sender_id = 0;
const char* generated_data = nullptr;
size_t generated_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;
};
} } // eosio::chain
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册