提交 bd408ae3 编写于 作者: B Bart Wyatt

rename scopes to locks from the perspective of the contracts, add account to...

rename scopes to locks from the perspective of the contracts, add account to the locks in shards and then deal with all the problems that caused
上级 60455838
#include <algorithm>
#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/chain_controller.hpp>
#include <eosio/chain/wasm_interface.hpp>
......@@ -27,19 +28,31 @@ void apply_context::exec_one()
wasm.apply(code, *this);
}
}
} FC_CAPTURE_AND_RETHROW((_pending_console_output.str()));
if (results.read_scopes.empty()) {
std::sort(results.read_scopes.begin(), results.read_scopes.end());
}
if (results.write_scopes.empty()) {
std::sort(results.write_scopes.begin(), results.write_scopes.end());
if (_write_scopes.empty()) {
std::sort(_write_scopes.begin(), _write_scopes.end());
}
if (_read_scopes.empty()) {
std::sort(_read_scopes.begin(), _read_scopes.end());
// remove any write_scopes
auto r_iter = _read_scopes.begin();
for( auto w_iter = _write_scopes.cbegin(); (w_iter != _write_scopes.cend()) && (r_iter != _read_scopes.end()); ++w_iter) {
while(r_iter != _read_scopes.end() && *r_iter < *w_iter) {
++r_iter;
}
if (*r_iter == *w_iter) {
r_iter = _read_scopes.erase(r_iter);
}
}
} FC_CAPTURE_AND_RETHROW((_pending_console_output.str()));
}
// create a receipt for this
vector<data_access_info> data_access;
data_access.reserve(results.write_scopes.size() + results.read_scopes.size());
for (const auto& scope: results.write_scopes) {
data_access.reserve(_write_scopes.size() + _read_scopes.size());
for (const auto& scope: _write_scopes) {
auto key = boost::make_tuple(scope, receiver);
const auto& scope_sequence = mutable_controller.get_database().find<scope_sequence_object, by_scope_receiver>(key);
if (scope_sequence == nullptr) {
......@@ -61,7 +74,7 @@ void apply_context::exec_one()
}
}
for (const auto& scope: results.read_scopes) {
for (const auto& scope: _read_scopes) {
auto key = boost::make_tuple(scope, receiver);
const auto& scope_sequence = mutable_controller.get_database().find<scope_sequence_object, by_scope_receiver>(key);
if (scope_sequence == nullptr) {
......@@ -73,6 +86,8 @@ void apply_context::exec_one()
results.applied_actions.emplace_back(action_trace {receiver, act, _pending_console_output.str(), 0, 0, move(data_access)});
_pending_console_output = std::ostringstream();
_read_scopes.clear();
_write_scopes.clear();
}
void apply_context::exec()
......@@ -85,7 +100,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);
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta, allowed_read_locks, allowed_write_locks);
ncontext.exec();
append_results(move(ncontext.results));
}
......@@ -108,32 +123,30 @@ void apply_context::require_authorization(const account_name& account,
}
static bool scopes_contain(const vector<scope_name>& scopes, const scope_name& scope) {
for (const auto &s : scopes) {
if (s == scope) {
return true;
}
}
return std::find(scopes.begin(), scopes.end(), scope) != scopes.end();
}
return false;
static bool locks_contain(const vector<shard_lock>& locks, const account_name& account, const scope_name& scope) {
return std::find(locks.begin(), locks.end(), shard_lock{account, scope}) != locks.end();
}
void apply_context::require_write_scope(const scope_name& scope) {
if (trx_meta.allowed_write_scopes) {
EOS_ASSERT( scopes_contain(**trx_meta.allowed_write_scopes, scope), tx_missing_write_scope, "missing write scope ${scope}", ("scope",scope) );
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_scope, "missing write scope ${scope}", ("scope",scope) );
}
if (!scopes_contain(results.write_scopes, scope)) {
results.write_scopes.emplace_back(scope);
if (!scopes_contain(_write_scopes, scope)) {
_write_scopes.emplace_back(scope);
}
}
void apply_context::require_read_scope(const scope_name& scope) {
if (trx_meta.allowed_read_scopes) {
EOS_ASSERT( scopes_contain(**trx_meta.allowed_read_scopes, scope), tx_missing_read_scope, "missing read scope ${scope}", ("scope",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_scope, "missing read scope ${scope}", ("scope",scope) );
}
if (!scopes_contain(results.read_scopes, scope)) {
results.read_scopes.emplace_back(scope);
if (!scopes_contain(_read_scopes, scope)) {
_read_scopes.emplace_back(scope);
}
}
......@@ -187,18 +200,18 @@ void apply_context::cancel_deferred( uint32_t sender_id ) {
}
const contracts::table_id_object* apply_context::find_table( name scope, name code, name table ) {
require_read_scope(scope);
require_read_lock(code, scope);
return db.find<table_id_object, contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
}
const contracts::table_id_object& apply_context::find_or_create_table( name scope, name code, name table ) {
require_read_scope(scope);
require_read_lock(code, scope);
const auto* existing_tid = db.find<contracts::table_id_object, contracts::by_scope_code_table>(boost::make_tuple(scope, code, table));
if (existing_tid != nullptr) {
return *existing_tid;
}
require_write_scope(scope);
require_write_lock(scope);
return mutable_db.create<contracts::table_id_object>([&](contracts::table_id_object &t_id){
t_id.scope = scope;
t_id.code = code;
......
......@@ -298,8 +298,19 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata& dat
auto& bcycle = _pending_block->regions.back().cycles_summary.back();
auto& bshard = bcycle.front();
copy_append_names(bshard.read_scopes, result.read_scopes);
copy_append_names(bshard.write_scopes, result.write_scopes);
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});
}
}
}
fc::deduplicate(bshard.read_locks);
fc::deduplicate(bshard.write_locks);
bshard.transactions.emplace_back( result );
_pending_cycle_trace->shard_traces.at(0).append(result);
......@@ -537,15 +548,15 @@ void chain_controller::_apply_block(const signed_block& next_block, uint32_t ski
});
}
static void validate_shard_scopes(const vector<scope_name>& scopes, string tag) {
if (scopes.size() < 2) {
static void validate_shard_locks(const vector<shard_lock>& locks, const string& tag) {
if (locks.size() < 2) {
return;
}
for (auto cur = scopes.begin() + 1; cur < scopes.end(); cur++) {
for (auto cur = locks.begin() + 1; cur < locks.end(); cur++) {
auto prev = cur - 1;
FC_ASSERT(*prev != *cur, "${tag} scope \"${scope}\" is not unique", ("tag",tag)("scope",*cur));
FC_ASSERT(*prev < *cur, "${tag} scopes are not sorted", ("tag",tag));
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));
}
}
......@@ -588,28 +599,28 @@ void chain_controller::__apply_block(const signed_block& next_block)
// validate that no read_scope is used as a write scope in this cycle and that no two shards
// share write scopes
set<scope_name> read_scopes;
map<scope_name, uint32_t> write_scopes;
set<shard_lock> read_locks;
map<shard_lock, uint32_t> write_locks;
for (uint32_t shard_index = 0; shard_index < cycle.size(); shard_index++) {
const auto& shard = cycle.at(shard_index);
// Validate that the shards scopes are correct and available
validate_shard_scopes(shard.read_scopes, "read");
validate_shard_scopes(shard.write_scopes, "write");
for (const auto& s: shard.read_scopes) {
FC_ASSERT(write_scopes.count(s) == 0,
"shard ${i} requires read scope \"${s}\" which is locked for write by shard ${j}",
("i", shard_index)("s", s)("j", write_scopes[s]));
read_scopes.emplace(s);
validate_shard_locks(shard.read_locks, "read");
validate_shard_locks(shard.write_locks, "write");
for (const auto& s: shard.read_locks) {
FC_ASSERT(write_locks.count(s) == 0,
"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_scopes) {
FC_ASSERT(write_scopes.count(s) == 0,
"shard ${i} requires write scope \"${s}\" which is locked for write by shard ${j}",
("i", shard_index)("s", s)("j", write_scopes[s]));
write_scopes[s] = shard_index;
for (const auto& s: shard.write_locks) {
FC_ASSERT(write_locks.count(s) == 0,
"shard ${i} requires write lock \"${a}::${s}\" which is locked for write by shard ${j}",
("i", shard_index)("s", s)("j", write_locks[s]));
write_locks[s] = shard_index;
}
shard_trace s_trace;
......@@ -629,10 +640,8 @@ 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_scopes = &shard.read_scopes;
mtrx.allowed_write_scopes = &shard.write_scopes;
s_trace.transaction_traces.emplace_back(_apply_transaction(mtrx));
s_trace.transaction_traces.emplace_back(_apply_transaction(mtrx, &shard.read_locks, &shard.write_locks));
FC_ASSERT(receipt.status == s_trace.transaction_traces.back().status);
......@@ -1346,16 +1355,14 @@ static void log_handled_exceptions(const transaction& trx) {
} FC_CAPTURE_AND_LOG((trx));
}
transaction_trace chain_controller::__apply_transaction( transaction_metadata& meta ) {
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 result(meta.id);
for (const auto &act : meta.trx.actions) {
apply_context context(*this, _db, act, meta);
apply_context context(*this, _db, act, meta, allowed_read_locks, allowed_write_locks);
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));
fc::move_append(result.canceled_deferred, std::move(context.results.canceled_deferred));
move_append_names(result.read_scopes, std::forward<vector<scope_name>>(context.results.read_scopes));
move_append_names(result.write_scopes, std::forward<vector<scope_name>>(context.results.write_scopes));
}
uint32_t act_usage = result.action_traces.size();
......@@ -1375,10 +1382,10 @@ transaction_trace chain_controller::__apply_transaction( transaction_metadata& m
return result;
}
transaction_trace chain_controller::_apply_transaction( transaction_metadata& meta ) {
transaction_trace chain_controller::_apply_transaction( transaction_metadata& meta, const vector<shard_lock>* allowed_read_locks, const vector<shard_lock>* allowed_write_locks ) {
try {
auto temp_session = _db.start_undo_session(true);
auto result = __apply_transaction(meta);
auto result = __apply_transaction(meta, allowed_read_locks, allowed_write_locks);
temp_session.squash();
return result;
} catch (...) {
......@@ -1389,11 +1396,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 );
return _apply_error( meta, allowed_read_locks, allowed_write_locks );
}
}
transaction_trace chain_controller::_apply_error( transaction_metadata& 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 result(meta.id);
result.status = transaction_trace::soft_fail;
......@@ -1404,12 +1411,10 @@ transaction_trace chain_controller::_apply_error( transaction_metadata& meta ) {
try {
auto temp_session = _db.start_undo_session(true);
apply_context context(*this, _db, etrx.actions.front(), meta);
apply_context context(*this, _db, etrx.actions.front(), meta, allowed_read_locks, allowed_write_locks);
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));
move_append_names(result.read_scopes, std::forward<vector<scope_name>>(context.results.read_scopes));
move_append_names(result.write_scopes, std::forward<vector<scope_name>>(context.results.write_scopes));
uint32_t act_usage = result.action_traces.size();
......
......@@ -84,7 +84,7 @@ void apply_eosio_newaccount(apply_context& context) {
auto create = context.act.as<newaccount>();
try {
context.require_authorization(create.creator);
context.require_write_scope( config::eosio_auth_scope );
context.require_write_lock( config::eosio_auth_scope );
EOS_ASSERT( validate(create.owner), action_validate_exception, "Invalid owner authority");
EOS_ASSERT( validate(create.active), action_validate_exception, "Invalid active authority");
......@@ -149,8 +149,8 @@ void apply_eosio_transfer(apply_context& context) {
try {
EOS_ASSERT(transfer.amount > 0, action_validate_exception, "Must transfer a positive amount");
context.require_write_scope(transfer.to);
context.require_write_scope(transfer.from);
context.require_write_lock(transfer.to);
context.require_write_lock(transfer.from);
context.require_authorization(transfer.from);
......@@ -181,9 +181,9 @@ void apply_eosio_lock(apply_context& context) {
EOS_ASSERT(lock.amount > 0, action_validate_exception, "Locked amount must be positive");
context.require_write_scope(lock.to);
context.require_write_scope(lock.from);
context.require_write_scope(config::system_account_name);
context.require_write_lock(lock.to);
context.require_write_lock(lock.from);
context.require_write_lock(config::system_account_name);
context.require_authorization(lock.from);
......@@ -222,7 +222,7 @@ void apply_eosio_setcode(apply_context& context) {
auto act = context.act.as<setcode>();
context.require_authorization(act.account);
context.require_write_scope( config::eosio_auth_scope );
context.require_write_lock( config::eosio_auth_scope );
FC_ASSERT( act.vmtype == 0 );
FC_ASSERT( act.vmversion == 0 );
......@@ -327,8 +327,8 @@ void apply_eosio_okproducer(apply_context& context) {
context.require_recipient(approve.voter);
context.require_recipient(approve.producer);
context.require_write_scope(config::system_account_name);
context.require_write_scope(approve.voter);
context.require_write_lock(config::system_account_name);
context.require_write_lock(approve.voter);
context.require_authorization(approve.voter);
......@@ -406,7 +406,7 @@ void apply_eosio_setproxy(apply_context& context) {
}
void apply_eosio_updateauth(apply_context& context) {
context.require_write_scope( config::eosio_auth_scope );
context.require_write_lock( config::eosio_auth_scope );
auto update = context.act.as<updateauth>();
EOS_ASSERT(!update.permission.empty(), action_validate_exception, "Cannot create authority with empty name");
......@@ -588,7 +588,7 @@ static optional<variant> get_pending_recovery(apply_context& context, account_na
}
static uint32_t get_next_sender_id(apply_context& context) {
context.require_write_scope( config::eosio_auth_scope );
context.require_write_lock( config::eosio_auth_scope );
const auto& t_id = context.find_or_create_table(config::eosio_auth_scope, config::system_account_name, N(deferred.seq));
uint64_t key = N(config::eosio_auth_scope);
uint32_t next_serial = 0;
......@@ -614,14 +614,14 @@ static auto get_permission_last_used(const apply_context& context, const account
};
void apply_eosio_postrecovery(apply_context& context) {
context.require_write_scope( config::eosio_auth_scope );
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.as<postrecovery>();
const auto &auth = context.act.authorization.front();
const auto& account = recover_act.account;
context.require_write_scope(account);
context.require_write_lock(account);
FC_ASSERT(!get_pending_recovery(context, account), "Account ${account} already has a pending recovery request!", ("account",account));
......@@ -717,7 +717,7 @@ void apply_eosio_passrecovery(apply_context& context) {
}
void apply_eosio_vetorecovery(apply_context& context) {
context.require_write_scope( config::eosio_auth_scope );
context.require_write_lock( config::eosio_auth_scope );
auto pass_act = context.act.as<vetorecovery>();
const auto& account = pass_act.account;
context.require_authorization(account);
......
......@@ -3,6 +3,7 @@
* @copyright defined in eos/LICENSE.txt
*/
#pragma once
#include <eosio/chain/block.hpp>
#include <eosio/chain/transaction.hpp>
#include <eosio/chain/contracts/contract_table_objects.hpp>
#include <fc/utility.hpp>
......@@ -17,10 +18,11 @@ class chain_controller;
class apply_context {
public:
apply_context(chain_controller& con, chainbase::database& db, const action& a, const transaction_metadata& trx_meta)
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)
:controller(con), db(db), act(a), mutable_controller(con),
mutable_db(db), used_authorizations(act.authorization.size(), false),
trx_meta(trx_meta) {}
trx_meta(trx_meta), allowed_read_locks(allowed_read_locks), allowed_write_locks(allowed_write_locks) {}
void exec();
......@@ -74,8 +76,8 @@ class apply_context {
*/
void require_authorization(const account_name& account)const;
void require_authorization(const account_name& account, const permission_name& permission)const;
void require_write_scope(const account_name& account);
void require_read_scope(const account_name& account);
void require_write_lock(const scope_name& scope);
void require_read_lock(const account_name& account, const scope_name& scope);
/**
* Requires that the current action be delivered to account
......@@ -106,6 +108,8 @@ 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
/*
......@@ -156,9 +160,6 @@ class apply_context {
vector<action_trace> applied_actions;
vector<deferred_transaction> generated_transactions;
vector<deferred_reference> canceled_deferred;
vector<scope_name> read_scopes;
vector<scope_name> write_scopes;
};
apply_results results;
......@@ -184,8 +185,6 @@ class apply_context {
fc::move_append(results.applied_actions, move(other.applied_actions));
fc::move_append(results.generated_transactions, move(other.generated_transactions));
fc::move_append(results.canceled_deferred, move(other.canceled_deferred));
move_append_names(results.read_scopes, forward<vector<scope_name>>(other.read_scopes));
move_append_names(results.write_scopes, forward<vector<scope_name>>(other.write_scopes));
}
void exec_one();
......@@ -193,6 +192,9 @@ class apply_context {
vector<account_name> _notified; ///< keeps track of new accounts to be notifed of current message
vector<action> _inline_actions; ///< queued inline messages
std::ostringstream _pending_console_output;
vector<scope_name> _read_scopes;
vector<scope_name> _write_scopes;
};
using apply_handler = std::function<void(apply_context&)>;
......@@ -391,7 +393,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename ObjectType>
int32_t apply_context::store_record( const table_id_object& t_id, const typename ObjectType::key_type* keys, const char* value, size_t valuelen ) {
require_write_scope( t_id.scope );
require_write_lock( t_id.scope );
auto tuple = impl::exact_tuple<ObjectType>::get(t_id, keys);
const auto* obj = db.find<ObjectType, contracts::by_scope_primary>(tuple);
......@@ -413,7 +415,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename ObjectType>
int32_t apply_context::update_record( const table_id_object& t_id, const typename ObjectType::key_type* keys, const char* value, size_t valuelen ) {
require_write_scope( t_id.scope );
require_write_lock( t_id.scope );
auto tuple = impl::exact_tuple<ObjectType>::get(t_id, keys);
const auto* obj = db.find<ObjectType, contracts::by_scope_primary>(tuple);
......@@ -434,7 +436,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename ObjectType>
int32_t apply_context::remove_record( const table_id_object& t_id, const typename ObjectType::key_type* keys ) {
require_write_scope( t_id.scope );
require_write_lock( t_id.scope );
auto tuple = impl::exact_tuple<ObjectType>::get(t_id, keys);
const auto* obj = db.find<ObjectType, contracts::by_scope_primary>(tuple);
......@@ -447,7 +449,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::load_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& idx = db.get_index<IndexType, Scope>();
auto tuple = impl::lower_bound_tuple<IndexType, Scope>::get(t_id, keys);
......@@ -472,7 +474,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::front_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& idx = db.get_index<IndexType, Scope>();
auto tuple = impl::front_record_tuple<IndexType, Scope>::get(t_id);
......@@ -496,7 +498,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::back_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& idx = db.get_index<IndexType, Scope>();
decltype(t_id.id) next_tid(t_id.id._id + 1);
......@@ -524,7 +526,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::next_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& pidx = db.get_index<IndexType, contracts::by_scope_primary>();
......@@ -567,7 +569,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::previous_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& pidx = db.get_index<IndexType, contracts::by_scope_primary>();
......@@ -606,7 +608,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::lower_bound_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& idx = db.get_index<IndexType, Scope>();
auto tuple = impl::lower_bound_tuple<IndexType, Scope>::get(t_id, keys);
......@@ -630,7 +632,7 @@ using apply_handler = std::function<void(apply_context&)>;
template <typename IndexType, typename Scope>
int32_t apply_context::upper_bound_record( const table_id_object& t_id, typename IndexType::value_type::key_type* keys, char* value, size_t valuelen ) {
require_read_scope( t_id.scope );
require_read_lock( t_id.code, t_id.scope );
const auto& idx = db.get_index<IndexType, Scope>();
auto tuple = impl::upper_bound_tuple<IndexType, Scope>::get(t_id, keys);
......
......@@ -48,10 +48,21 @@ namespace eosio { namespace chain {
signature_type producer_signature;
};
struct shard_lock {
account_name account;
scope_name scope;
friend bool operator < ( const shard_lock& a, const shard_lock& b ) { return std::tie(a.account, a.scope) < std::tie(b.account, b.scope); }
friend bool operator <= ( const shard_lock& a, const shard_lock& b ) { return std::tie(a.account, a.scope) <= std::tie(b.account, b.scope); }
friend bool operator > ( const shard_lock& a, const shard_lock& b ) { return std::tie(a.account, a.scope) > std::tie(b.account, b.scope); }
friend bool operator >= ( const shard_lock& a, const shard_lock& b ) { return std::tie(a.account, a.scope) >= std::tie(b.account, b.scope); }
friend bool operator == ( const shard_lock& a, const shard_lock& b ) { return std::tie(a.account, a.scope) == std::tie(b.account, b.scope); }
friend bool operator != ( const shard_lock& a, const shard_lock& b ) { return std::tie(a.account, a.scope) != std::tie(b.account, b.scope); }
};
struct shard_summary {
vector<scope_name> read_scopes;
vector<scope_name> write_scopes;
vector<shard_lock> read_locks;
vector<shard_lock> write_locks;
vector<transaction_receipt> transactions; /// new or generated transactions
};
......@@ -146,7 +157,8 @@ FC_REFLECT(eosio::chain::block_header, (previous)(timestamp)
(producer)(new_producers))
FC_REFLECT_DERIVED(eosio::chain::signed_block_header, (eosio::chain::block_header), (producer_signature))
FC_REFLECT( eosio::chain::shard_summary, (read_scopes)(write_scopes)(transactions))
FC_REFLECT( eosio::chain::shard_lock, (account)(scope))
FC_REFLECT( eosio::chain::shard_summary, (read_locks)(write_locks)(transactions))
FC_REFLECT( eosio::chain::region_summary, (region)(cycles_summary) )
FC_REFLECT_DERIVED(eosio::chain::signed_block_summary, (eosio::chain::signed_block_header), (regions))
FC_REFLECT_DERIVED(eosio::chain::signed_block, (eosio::chain::signed_block_summary), (input_transactions))
......
......@@ -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 transaction& trx, uint32_t region_id, uint32_t cycle_index );
transaction_trace __apply_transaction( transaction_metadata& data );//const transaction& trx, uint32_t region_id, uint32_t cycle_index );
transaction_trace _apply_error( 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 );
/// Reset the object graph in-memory
void _initialize_indexes();
......
......@@ -94,42 +94,10 @@ namespace eosio { namespace chain {
inline std::vector<name> sort_names( std::vector<name>&& names ) {
std::sort( names.begin(), names.end() );
auto itr = std::unique( names.begin(), names.end() );
names.erase( itr, names.end() );
fc::deduplicate(names);
return names;
}
/**
* append incoming scopes to a vector of scopes maintaining the invariants that the final
* vector is sorted and unique
*
* @param scopes
* @param incoming
*/
inline void move_append_names(std::vector<name>& scopes, std::vector<name>&& incoming) {
fc::move_append(scopes, move(incoming));
if (!scopes.empty()) {
sort_names(std::forward<std::vector<name>>(scopes));
}
}
/**
* append incoming scopes to a vector of scopes maintaining the invariants that the final
* vector is sorted and unique
*
* @param scopes
* @param incoming
*/
inline void copy_append_names(std::vector<name>& scopes, const std::vector<name>& incoming) {
scopes.insert(scopes.end(), incoming.begin(), incoming.end());
if (!scopes.empty()) {
sort_names(std::forward<std::vector<name>>(scopes));
}
}
} } // eosio::chain
namespace fc {
......
......@@ -193,8 +193,6 @@ namespace eosio { namespace chain {
vector<action_trace> action_traces;
vector<deferred_transaction> deferred_transactions;
vector<deferred_reference> canceled_deferred;
vector<scope_name> read_scopes;
vector<scope_name> write_scopes;
};
......@@ -231,10 +229,6 @@ namespace eosio { namespace chain {
uint32_t sender_id = 0;
const char* generated_data = nullptr;
size_t generated_size = 0;
// scheduling related information
optional<const vector<scope_name>*> allowed_read_scopes;
optional<const vector<scope_name>*> allowed_write_scopes;
};
} } // eosio::chain
......@@ -250,7 +244,7 @@ FC_REFLECT( eosio::chain::data_access_info, (type)(scope)(sequence))
FC_REFLECT( eosio::chain::action_trace, (receiver)(act)(console)(region_id)(cycle_index)(data_access) )
FC_REFLECT( eosio::chain::transaction_receipt, (status)(id))
FC_REFLECT_ENUM( eosio::chain::transaction_receipt::status_enum, (executed)(soft_fail)(hard_fail))
FC_REFLECT_DERIVED( eosio::chain::transaction_trace, (eosio::chain::transaction_receipt), (action_traces)(deferred_transactions)(read_scopes)(write_scopes) )
FC_REFLECT_DERIVED( eosio::chain::transaction_trace, (eosio::chain::transaction_receipt), (action_traces)(deferred_transactions) )
......@@ -869,8 +869,8 @@ REGISTER_INTRINSICS(action_api,
);
REGISTER_INTRINSICS(apply_context,
(require_write_scope, void(int64_t) )
(require_read_scope, void(int64_t) )
(require_write_lock, void(int64_t) )
(require_read_lock, void(int64_t, int64_t) )
(require_recipient, void(int64_t) )
(require_authorization, void(int64_t), "require_auth", void(apply_context::*)(const account_name&)const)
);
......
#pragma once
#include <stdint.h>
#include <algorithm>
#include <new>
#include <vector>
......@@ -71,6 +72,24 @@ namespace fc {
dest.insert(std::end(dest), std::make_move_iterator(std::begin(src)), std::make_move_iterator(std::end(src)));
}
}
template<typename T>
void copy_append(std::vector<T> &dest, const std::vector<T>& src ) {
if (src.empty()) {
return;
} else {
dest.insert(std::end(dest), std::begin(src), std::end(src));
}
}
template<typename T>
void deduplicate( std::vector<T>& entries ) {
if (entries.size() > 1) {
std::sort( entries.begin(), entries.end() );
auto itr = std::unique( entries.begin(), entries.end() );
entries.erase( itr, entries.end() );
}
}
}
// outside of namespace fc becuase of VC++ conflict with std::swap
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册