提交 2bd7a750 编写于 作者: B Bart Wyatt

Merge remote-tracking branch 'origin/eos-noon' into reset-wasm-globals

......@@ -26,8 +26,8 @@ namespace eosio {
class action {
public:
template<typename Payload, typename ...Permissions>
action(const scope_name& scope, const action_name& name, const Payload& payload, Permissions... permissions )
:_scope(scope), _name(name), _num_permissions(0)
action(const account_name& account, const action_name& name, const Payload& payload, Permissions... permissions )
:_account(account), _name(name), _num_permissions(0)
{
assert(sizeof(payload) <= MaxPayloadSize, "Payload exceeds maximum size");
memcpy(_payload, &payload, sizeof(payload));
......@@ -36,16 +36,16 @@ namespace eosio {
}
template<typename Payload>
action(const scope_name& scope, const action_name& name, const Payload& payload )
: _scope(scope), _name(name), _num_permissions(0)
action(const account_name& account, const action_name& name, const Payload& payload )
: _account(account), _name(name), _num_permissions(0)
{
assert(sizeof(payload) <= MaxPayloadSize, "payload exceeds maximum size");
_payload_size = sizeof(payload);
memcpy(_payload, &payload, sizeof(payload));
}
action(const scope_name& scope, const action_name& name)
:_scope(scope), _name(name), _payload_size(0), _num_permissions(0)
action(const account_name& account, const action_name& name)
:_account(account), _name(name), _payload_size(0), _num_permissions(0)
{
}
......@@ -69,7 +69,7 @@ namespace eosio {
send_inline(buffer, used);
}
scope_name _scope;
account_name _account;
action_name _name;
char _payload[MaxPayloadSize];
size_t _payload_size;
......@@ -77,12 +77,12 @@ namespace eosio {
size_t _num_permissions;
static constexpr size_t max_buffer_size() {
return sizeof(size_t) + MaxPayloadSize + sizeof(size_t) + (MaxPermissions * sizeof(account_permission)) + sizeof(scope_name) + sizeof(action_name);
return sizeof(size_t) + MaxPayloadSize + sizeof(size_t) + (MaxPermissions * sizeof(account_permission)) + sizeof(account_name) + sizeof(action_name);
}
size_t pack( char *buffer, size_t buffer_size ) const {
datastream<char*> ds( buffer, buffer_size );
eosio::raw::pack(ds, _scope);
eosio::raw::pack(ds, _account);
eosio::raw::pack(ds, _name);
eosio::raw::pack(ds, _permissions, _num_permissions);
eosio::raw::pack(ds, _payload, _payload_size);
......@@ -102,47 +102,17 @@ namespace eosio {
{
}
template<size_t MaxActionsSize, size_t MaxWriteScopes, size_t MaxReadScopes>
template<size_t MaxActionsSize>
friend class deferred_transaction;
};
template<size_t MaxActionsSize = 256, size_t MaxWriteScopes = 2, size_t MaxReadScopes = 4>
template<size_t MaxActionsSize = 256>
class transaction {
private:
static void insert_sorted_unique( scope_name scope, scope_name *scopes, size_t &size, const char* non_unique_message) {
size_t insert_index = 0;
for (; insert_index < size; insert_index++) {
assert(scopes[insert_index] != scope, non_unique_message);
if (scopes[insert_index] > scope) {
break;
}
}
if (insert_index != size) {
for (size_t idx = size; idx > insert_index; idx--) {
scopes[idx] = scopes[idx - 1];
}
}
scopes[insert_index] = scope;
size++;
}
public:
transaction(time expiration = now() + 60, region_id region = 0)
:_expiration(expiration),_region(region),_num_read_scopes(0), _num_write_scopes(0), _action_buffer_size(0), _num_actions(0)
:_expiration(expiration),_region(region), _action_buffer_size(0), _num_actions(0)
{}
void add_read_scope(account_name scope) {
assert(_num_read_scopes < MaxReadScopes, "Too many Read Scopes");
insert_sorted_unique(scope, _read_scopes, _num_read_scopes, "Duplicate Read Scope");
}
void add_write_scope(account_name scope) {
assert(_num_write_scopes < MaxWriteScopes, "Too many Write Scopes");
insert_sorted_unique(scope, _write_scopes, _num_write_scopes, "Duplicate Write Scope");
}
template<size_t ...ActArgs>
void add_action(const action<ActArgs...> &act) {
_action_buffer_size += act.pack(_action_buffer + _action_buffer_size, MaxActionsSize - _action_buffer_size );
......@@ -157,8 +127,6 @@ namespace eosio {
static constexpr size_t max_buffer_size() {
return sizeof(time) + sizeof(region_id) + sizeof(uint16_t) + sizeof(uint32_t) +
sizeof(size_t) + (MaxReadScopes * sizeof(scope_name)) +
sizeof(size_t) + (MaxWriteScopes * sizeof(scope_name)) +
sizeof(size_t) + MaxActionsSize;
}
......@@ -168,8 +136,6 @@ namespace eosio {
eosio::raw::pack(ds, _region);
eosio::raw::pack(ds, uint16_t(0));
eosio::raw::pack(ds, uint32_t(0));
eosio::raw::pack(ds, _read_scopes, _num_read_scopes);
eosio::raw::pack(ds, _write_scopes, _num_write_scopes);
eosio::raw::pack(ds, unsigned_int(_num_actions));
ds.write(_action_buffer, _action_buffer_size);
return ds.tellp();
......@@ -191,12 +157,6 @@ namespace eosio {
uint16_t _ref_block_num;
uint32_t _ref_block_id;
scope_name _read_scopes[MaxReadScopes];
size_t _num_read_scopes;
scope_name _write_scopes[MaxWriteScopes];
size_t _num_write_scopes;
char _action_buffer[MaxActionsSize];
size_t _action_buffer_size;
......@@ -206,7 +166,7 @@ namespace eosio {
template<size_t MaxPayloadSize, size_t MaxPermissions>
static size_t unpack_action(char* buffer, size_t size, size_t offset, action<MaxPayloadSize, MaxPermissions> &act) {
datastream<char*> ds(buffer + offset, size - offset);
eosio::raw::unpack(ds, act._scope);
eosio::raw::unpack(ds, act._account);
eosio::raw::unpack(ds, act._name);
eosio::raw::unpack(ds, act._permissions, act._num_permissions, MaxPermissions);
eosio::raw::unpack(ds, act._payload, act._payload_size, MaxPayloadSize);
......@@ -214,15 +174,15 @@ namespace eosio {
}
};
template<size_t MaxActionsSize = 256, size_t MaxWriteScopes = 2, size_t MaxReadScopes = 4>
class deferred_transaction : public transaction<MaxActionsSize, MaxWriteScopes, MaxReadScopes> {
template<size_t MaxActionsSize = 256>
class deferred_transaction : public transaction<MaxActionsSize> {
public:
uint32_t _sender_id;
account_name _sender;
time _delay_until;
static constexpr size_t max_buffer_size() {
return sizeof(uint32_t) + sizeof(account_name) + sizeof(time) + transaction<MaxActionsSize, MaxWriteScopes, MaxReadScopes>::max_buffer_size();
return sizeof(uint32_t) + sizeof(account_name) + sizeof(time) + transaction<MaxActionsSize>::max_buffer_size();
}
template< size_t MaxPayloadSize = 64, size_t MaxPermissions = 2 >
......@@ -238,8 +198,6 @@ namespace eosio {
eosio::raw::unpack(ds, result._region);
eosio::raw::unpack(ds, result._ref_block_num);
eosio::raw::unpack(ds, result._ref_block_id);
eosio::raw::unpack(ds, result._read_scopes, result._num_read_scopes, MaxReadScopes);
eosio::raw::unpack(ds, result._write_scopes, result._num_write_scopes, MaxWriteScopes);
unsigned_int packed_num_actions;
eosio::raw::unpack(ds, packed_num_actions);
result._num_actions = packed_num_actions.value;
......@@ -249,7 +207,7 @@ namespace eosio {
size_t action_offset = 0;
action<MaxPayloadSize, MaxPermissions> temp;
for (size_t idx; idx < result._num_actions; idx++) {
action_offset = transaction<MaxActionsSize, MaxWriteScopes, MaxReadScopes>::unpack_action(temp_actions, temp_action_size, action_offset, temp);
action_offset = transaction<MaxActionsSize>::unpack_action(temp_actions, temp_action_size, action_offset, temp);
}
assert(action_offset <= MaxActionsSize, "Actions are too large to parse");
result._action_buffer_size = action_offset;
......
......@@ -30,8 +30,6 @@ namespace proxy {
transaction<> out;
out.add_action(out_act);
out.add_write_scope(self);
out.add_write_scope(code_config.owner);
out.send(id, now() + code_config.delay);
}
}
......
#include <algorithm>
#include <eosio/chain/apply_context.hpp>
#include <eosio/chain/chain_controller.hpp>
#include <eosio/chain/wasm_interface.hpp>
......@@ -11,7 +12,7 @@ namespace eosio { namespace chain {
void apply_context::exec_one()
{
try {
auto native = mutable_controller.find_apply_handler(receiver, act.scope, act.name);
auto native = mutable_controller.find_apply_handler(receiver, act.account, act.name);
if (native) {
(*native)(*this);
} else {
......@@ -29,10 +30,30 @@ void apply_context::exec_one()
}
} FC_CAPTURE_AND_RETHROW((_pending_console_output.str()));
if (!_write_scopes.empty()) {
std::sort(_write_scopes.begin(), _write_scopes.end());
}
if (!_read_locks.empty()) {
std::sort(_read_locks.begin(), _read_locks.end());
// remove any write_scopes
auto r_iter = _read_locks.begin();
for( auto w_iter = _write_scopes.cbegin(); (w_iter != _write_scopes.cend()) && (r_iter != _read_locks.end()); ++w_iter) {
shard_lock w_lock = {receiver, *w_iter};
while(r_iter != _read_locks.end() && *r_iter < w_lock ) {
++r_iter;
}
if (*r_iter == w_lock) {
r_iter = _read_locks.erase(r_iter);
}
}
}
// create a receipt for this
vector<data_access_info> data_access;
data_access.reserve(trx.write_scope.size() + trx.read_scope.size());
for (const auto& scope: trx.write_scope) {
data_access.reserve(_write_scopes.size() + _read_locks.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) {
......@@ -54,23 +75,25 @@ void apply_context::exec_one()
}
}
for (const auto& scope: trx.read_scope) {
auto key = boost::make_tuple(scope, receiver);
for (const auto& lock: _read_locks) {
auto key = boost::make_tuple(lock.scope, lock.account);
const auto& scope_sequence = mutable_controller.get_database().find<scope_sequence_object, by_scope_receiver>(key);
if (scope_sequence == nullptr) {
data_access.emplace_back(data_access_info{data_access_info::read, scope, 0});
data_access.emplace_back(data_access_info{data_access_info::read, lock.scope, 0});
} else {
data_access.emplace_back(data_access_info{data_access_info::read, scope, scope_sequence->sequence});
data_access.emplace_back(data_access_info{data_access_info::read, lock.scope, scope_sequence->sequence});
}
}
results.applied_actions.emplace_back(action_trace {receiver, act, _pending_console_output.str(), 0, 0, move(data_access)});
_pending_console_output = std::ostringstream();
_read_locks.clear();
_write_scopes.clear();
}
void apply_context::exec()
{
_notified.push_back(act.scope);
_notified.push_back(act.account);
for( uint32_t i = 0; i < _notified.size(); ++i ) {
receiver = _notified[i];
......@@ -78,7 +101,7 @@ void apply_context::exec()
}
for( uint32_t i = 0; i < _inline_actions.size(); ++i ) {
apply_context ncontext( mutable_controller, mutable_db, trx, _inline_actions[i], published, sender);
apply_context ncontext( mutable_controller, mutable_db, _inline_actions[i], trx_meta);
ncontext.exec();
append_results(move(ncontext.results));
}
......@@ -100,28 +123,32 @@ void apply_context::require_authorization(const account_name& account,
("account",account)("permission",permission) );
}
void apply_context::require_write_scope(const account_name& account)const {
for( const auto& s : trx.write_scope )
if( s == account ) return;
if( trx.write_scope.size() == 1 && trx.write_scope.front() == config::eosio_all_scope )
return;
static bool scopes_contain(const vector<scope_name>& scopes, const scope_name& scope) {
return std::find(scopes.begin(), scopes.end(), scope) != scopes.end();
}
EOS_ASSERT( false, tx_missing_write_scope, "missing write scope ${account}",
("account",account) );
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_read_scope(const account_name& account)const {
for( const auto& s : trx.write_scope )
if( s == account ) return;
for( const auto& s : trx.read_scope )
if( s == account ) return;
void apply_context::require_write_lock(const scope_name& 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( trx.write_scope.size() == 1 && trx.write_scope.front() == config::eosio_all_scope )
return;
if (!scopes_contain(_write_scopes, scope)) {
_write_scopes.emplace_back(scope);
}
}
EOS_ASSERT( false, tx_missing_read_scope, "missing read scope ${account}",
("account",account) );
void apply_context::require_read_lock(const account_name& account, const scope_name& 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)) {
_read_locks.emplace_back(shard_lock{account, scope});
}
}
bool apply_context::has_recipient( account_name code )const {
......@@ -161,8 +188,6 @@ void apply_context::execute_deferred( deferred_transaction&& trx ) {
controller.check_authorization(trx.actions, flat_set<public_key_type>(), false, {receiver});
}
controller.validate_scope( trx );
trx.sender = receiver; // "Attempting to send from another account"
trx.set_reference_block(controller.head_block_id());
......@@ -176,18 +201,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;
......
......@@ -67,7 +67,7 @@ namespace eosio { namespace chain {
digest_type::encoder enc;
fc::raw::pack(enc, at.receiver);
fc::raw::pack(enc, at.act.scope);
fc::raw::pack(enc, at.act.account);
fc::raw::pack(enc, at.act.name);
fc::raw::pack(enc, at.act.data);
fc::raw::pack(enc, at.region_id);
......
......@@ -270,10 +270,21 @@ 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;
bool force_new_cycle = false;
// If this is the first transaction pushed after applying a block, start a new undo session.
// This allows us to quickly rewind to the clean state of the head block, in case a new block arrives.
if( !_pending_block ) {
......@@ -285,18 +296,7 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata& dat
// for now apply the transaction serially but schedule it according to those invariants
validate_referenced_accounts(trx);
auto shardnum = 0;
auto cyclenum = _pending_block->regions.back().cycles_summary.size() - 1;
bool new_cycle = false;
if (!force_new_cycle) {
shardnum = _pending_cycle.schedule( trx );
}
if (shardnum == -1 || force_new_cycle) {
cyclenum += 1;
shardnum = 0;
new_cycle = true;
}
/// TODO: move _pending_cycle into db so that it can be undone if transation fails, for now we will apply
/// the transaction first so that there is nothing to undo... this only works because things are currently
......@@ -304,24 +304,20 @@ transaction_trace chain_controller::_push_transaction( transaction_metadata& dat
// set cycle, shard, region etc
data.region_id = 0;
data.cycle_index = cyclenum;
data.shard_index = shardnum;
data.shard_index = 0;
auto result = _apply_transaction( data );
if( new_cycle ) { /// schedule conflict start new cycle
_finalize_pending_cycle();
_start_pending_cycle();
FC_ASSERT(_pending_cycle.schedule( trx ) == shardnum);
}
auto& bcycle = _pending_block->regions.back().cycles_summary.back();
auto& bshard = bcycle.front();
record_locks_for_data_access(result.action_traces, bshard.read_locks, bshard.write_locks);
auto& bcycle = _pending_block->regions.back().cycles_summary.back();
if( shardnum >= bcycle.size() ) {
_start_pending_shard();
}
fc::deduplicate(bshard.read_locks);
fc::deduplicate(bshard.write_locks);
bshard.transactions.emplace_back( result );
bcycle.at(shardnum).emplace_back( result );
_pending_cycle_trace->shard_traces.at(shardnum).append(result);
_pending_cycle_trace->shard_traces.at(0).append(result);
// The transaction applied successfully. Merge its changes into the pending block session.
temp_session.squash();
......@@ -346,7 +342,6 @@ void chain_controller::_start_pending_block()
*/
void chain_controller::_start_pending_cycle() {
_pending_block->regions.back().cycles_summary.resize( _pending_block->regions[0].cycles_summary.size() + 1 );
_pending_cycle = pending_cycle_state();
_pending_cycle_trace = cycle_trace();
_start_pending_shard();
......@@ -409,10 +404,10 @@ void chain_controller::_apply_cycle_trace( const cycle_trace& res )
for (const auto &ar : tr.action_traces) {
if (!ar.console.empty()) {
auto prefix = fc::format_string(
"[(${s},${a})->${r}]",
"[(${a},${n})->${r}]",
fc::mutable_variant_object()
("s", ar.act.scope)
("a", ar.act.name)
("a", ar.act.account)
("n", ar.act.name)
("r", ar.receiver));
std::cerr << prefix << ": CONSOLE OUTPUT BEGIN =====================" << std::endl;
std::cerr << ar.console;
......@@ -557,6 +552,17 @@ void chain_controller::_apply_block(const signed_block& next_block, uint32_t ski
});
}
static void validate_shard_locks(const vector<shard_lock>& locks, const string& tag) {
if (locks.size() < 2) {
return;
}
for (auto cur = locks.begin() + 1; cur != locks.end(); ++cur) {
auto prev = cur - 1;
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));
}
}
void chain_controller::__apply_block(const signed_block& next_block)
{ try {
......@@ -595,10 +601,40 @@ void chain_controller::__apply_block(const signed_block& next_block)
cycle_trace c_trace;
c_trace.shard_traces.reserve(cycle.size());
uint32_t shard_index = 0;
for (const auto& shard: cycle) {
// validate that no read_scope is used as a write scope in this cycle and that no two shards
// share 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_locks(shard.read_locks, "read");
validate_shard_locks(shard.write_locks, "write");
for (const auto& s: shard.read_locks) {
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) {
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)("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) {
for (const auto& receipt : shard.transactions) {
auto make_metadata = [&](){
auto itr = trx_index.find(receipt.id);
if( itr != trx_index.end() ) {
......@@ -614,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));
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);
......@@ -625,7 +664,16 @@ void chain_controller::__apply_block(const signed_block& next_block)
// check_transaction_authorization(trx, true);
} /// for each transaction id
++shard_index;
// 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
......@@ -676,7 +724,7 @@ void chain_controller::check_authorization( const vector<action>& actions,
for( const auto& declared_auth : act.authorization ) {
// check a minimum permission if one is set, otherwise assume the contract code will validate
auto min_permission_name = lookup_minimum_permission(declared_auth.actor, act.scope, act.name);
auto min_permission_name = lookup_minimum_permission(declared_auth.actor, act.account, act.name);
if (min_permission_name) {
const auto& min_permission = _db.get<permission_object, by_owner>(boost::make_tuple(declared_auth.actor, *min_permission_name));
......@@ -709,38 +757,6 @@ void chain_controller::check_transaction_authorization(const signed_transaction&
check_authorization( trx.actions, trx.get_signature_keys( chain_id_type{} ), allow_unused_signatures );
}
void chain_controller::validate_scope( const transaction& trx )const {
for( uint32_t i = 1; i < trx.read_scope.size(); ++i ) {
EOS_ASSERT( trx.read_scope[i-1] < trx.read_scope[i], transaction_exception,
"Scopes must be sorted and unique" );
}
for( uint32_t i = 1; i < trx.write_scope.size(); ++i ) {
EOS_ASSERT( trx.write_scope[i-1] < trx.write_scope[i], transaction_exception,
"Scopes must be sorted and unique" );
}
/**
* We need to verify that all authorizing accounts have write scope because write
* access is necessary to update bandwidth usage.
*/
///{
auto has_write_scope = [&]( auto s ) { return std::binary_search( trx.write_scope.begin(),
trx.write_scope.end(),
s ); };
for( const auto& a : trx.actions ) {
for( const auto& auth : a.authorization ) {
FC_ASSERT( has_write_scope( auth.actor ), "write scope of the authorizing account is required" );
}
}
///@}
vector<account_name> intersection;
std::set_intersection( trx.read_scope.begin(), trx.read_scope.end(),
trx.write_scope.begin(), trx.write_scope.end(),
std::back_inserter(intersection) );
FC_ASSERT( intersection.size() == 0, "a transaction may not redeclare scope in readscope" );
}
optional<permission_name> chain_controller::lookup_minimum_permission(account_name authorizer_account,
account_name scope,
action_name act_name) const {
......@@ -797,13 +813,8 @@ void chain_controller::validate_tapos(const transaction& trx)const {
void chain_controller::validate_referenced_accounts( const transaction& trx )const
{ try {
for( const auto& scope : trx.read_scope )
require_scope(scope);
for( const auto& scope : trx.write_scope )
require_scope(scope);
for( const auto& act : trx.actions ) {
require_account(act.scope);
require_account(act.account);
for (const auto& auth : act.authorization )
require_account(auth.actor);
}
......@@ -1055,7 +1066,6 @@ void chain_controller::_initialize_chain(contracts::chain_initializer& starter)
auto acts = starter.prepare_database(*this, _db);
transaction genesis_setup_transaction;
genesis_setup_transaction.write_scope = { config::eosio_all_scope };
genesis_setup_transaction.actions = move(acts);
ilog( "applying genesis transaction" );
......@@ -1371,7 +1381,7 @@ static void log_handled_exceptions(const transaction& trx) {
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, meta.trx, act, meta.published, meta.sender);
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));
......@@ -1384,7 +1394,7 @@ transaction_trace chain_controller::__apply_transaction( transaction_metadata& m
at.region_id = meta.region_id;
at.cycle_index = meta.cycle_index;
if (at.receiver == config::system_account_name &&
at.act.scope == config::system_account_name &&
at.act.account == config::system_account_name &&
at.act.name == N(setcode)) {
act_usage += config::setcode_act_usage;
}
......@@ -1418,15 +1428,13 @@ transaction_trace chain_controller::_apply_error( transaction_metadata& meta ) {
result.status = transaction_trace::soft_fail;
transaction etrx;
etrx.read_scope = meta.trx.read_scope;
etrx.write_scope = meta.trx.write_scope;
etrx.actions.emplace_back(vector<permission_level>{{meta.sender_id,config::active_name}},
contracts::onerror(meta.generated_data, meta.generated_data + meta.generated_size) );
try {
auto temp_session = _db.start_undo_session(true);
apply_context context(*this, _db, etrx, etrx.actions.front(), meta.published, meta.sender);
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));
......
......@@ -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");
......@@ -554,8 +554,8 @@ void apply_eosio_nonce(apply_context&) {
}
void apply_eosio_onerror(apply_context& context) {
assert(context.sender);
context.require_recipient(*context.sender);
assert(context.trx_meta.sender);
context.require_recipient(*context.trx_meta.sender);
}
static const abi_serializer& get_abi_serializer() {
......@@ -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));
......@@ -676,7 +676,6 @@ void apply_eosio_postrecovery(apply_context& context) {
dtrx.execute_after = context.controller.head_block_time() + delay_lock;
dtrx.set_reference_block(context.controller.head_block_id());
dtrx.expiration = dtrx.execute_after + fc::seconds(60);
dtrx.write_scope = sort_names({account, config::eosio_auth_scope, config::system_account_name});
dtrx.actions.emplace_back(vector<permission_level>{{account,config::active_name}},
passrecovery { account });
......@@ -700,7 +699,7 @@ void apply_eosio_passrecovery(apply_context& context) {
const auto& account = pass_act.account;
// ensure this is only processed if it is a deferred transaction from the system account
FC_ASSERT(context.sender && *context.sender == config::system_account_name);
FC_ASSERT(context.trx_meta.sender && *context.trx_meta.sender == config::system_account_name);
context.require_authorization(account);
auto maybe_recovery = get_pending_recovery(context, account);
......@@ -718,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,7 +3,9 @@
* @copyright defined in eos/LICENSE.txt
*/
#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>
......@@ -17,11 +19,11 @@ class chain_controller;
class apply_context {
public:
apply_context(chain_controller& con, chainbase::database& db,
const transaction& t, const action& a, const time_point& published, const optional<account_name>& sender)
:controller(con), db(db), trx(t), act(a), mutable_controller(con),
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),
published(published), sender(sender) {}
trx_meta(trx_meta) {}
void exec();
......@@ -75,8 +77,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)const;
void require_read_scope(const account_name& account)const;
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
......@@ -96,7 +98,6 @@ class apply_context {
const chain_controller& controller;
const chainbase::database& db; ///< database where state is stored
const transaction& trx; ///< used to gather the valid read/write scopes
const action& act; ///< message being applied
account_name receiver; ///< the code that is currently running
......@@ -107,10 +108,9 @@ class apply_context {
///< Parallel to act.authorization; tracks which permissions have been used while processing the message
vector<bool> used_authorizations;
const time_point& published;
const optional<account_name>& sender;
const transaction_metadata& trx_meta;
///< pending transaction construction
///< pending transaction construction
/*
typedef uint32_t pending_transaction_handle;
struct pending_transaction : public transaction {
......@@ -191,6 +191,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<shard_lock> _read_locks;
vector<scope_name> _write_scopes;
};
using apply_handler = std::function<void(apply_context&)>;
......@@ -389,7 +392,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);
......@@ -411,7 +414,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);
......@@ -432,7 +435,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);
......@@ -445,7 +448,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);
......@@ -470,7 +473,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);
......@@ -494,7 +497,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);
......@@ -522,7 +525,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>();
......@@ -565,7 +568,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>();
......@@ -604,7 +607,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);
......@@ -628,7 +631,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,9 +48,26 @@ 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<shard_lock> read_locks;
vector<shard_lock> write_locks;
vector<transaction_receipt> transactions; /// new or generated transactions
};
typedef vector<shard_summary> cycle;
typedef vector<transaction_receipt> shard; /// new or generated transactions
typedef vector<shard> cycle;
struct region_summary {
uint16_t region = 0;
vector<cycle> cycles_summary;
......@@ -140,6 +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_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))
......
......@@ -19,7 +19,6 @@
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/contracts/genesis_state.hpp>
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/pending_cycle_state.hpp>
#include <fc/log/logger.hpp>
......@@ -312,8 +311,8 @@ 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_transaction( transaction_metadata& data );
transaction_trace __apply_transaction( transaction_metadata& data );
transaction_trace _apply_error( transaction_metadata& data );
/// Reset the object graph in-memory
......@@ -354,7 +353,6 @@ namespace eosio { namespace chain {
try {
EOS_ASSERT(trx.messages.size() > 0, transaction_exception, "A transaction must have at least one message");
validate_scope(trx);
validate_expiration(trx);
validate_uniqueness(trx);
validate_tapos(trx);
......@@ -366,7 +364,6 @@ namespace eosio { namespace chain {
void validate_tapos(const transaction& trx)const;
void validate_referenced_accounts(const transaction& trx)const;
void validate_expiration(const transaction& trx) const;
void validate_scope(const transaction& trx) const;
void record_transaction(const transaction& trx);
/// @}
......@@ -421,7 +418,6 @@ namespace eosio { namespace chain {
optional<signed_block> _pending_block;
optional<block_trace> _pending_block_trace;
uint32_t _pending_transaction_count = 0;
pending_cycle_state _pending_cycle;
optional<cycle_trace> _pending_cycle_trace;
bool _currently_applying_block = false;
......
......@@ -213,11 +213,11 @@ namespace impl {
void add( mutable_variant_object& vo, const char* name, const action& v )const
{
mutable_variant_object mvo;
mvo("scope", v.scope);
mvo("account", v.account);
mvo("name", v.name);
mvo("authorization", v.authorization);
auto abi = _resolver(v.scope);
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));
......@@ -315,9 +315,9 @@ namespace impl {
void extract( const variant& v, action& act )const
{
const variant_object& vo = v.get_object();
FC_ASSERT(vo.contains("scope"));
FC_ASSERT(vo.contains("account"));
FC_ASSERT(vo.contains("name"));
from_variant(vo["scope"], act.scope);
from_variant(vo["account"], act.account);
from_variant(vo["name"], act.name);
if (vo.contains("authorization")) {
......@@ -329,7 +329,7 @@ namespace impl {
if( data.is_string() ) {
from_variant(data, act.data);
} else if ( data.is_object() ) {
auto abi = _resolver(act.scope);
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));
......@@ -346,7 +346,7 @@ namespace impl {
}
}
FC_ASSERT(!act.data.empty(), "Failed to deserialize data for ${scope}:${name}", ("scope", act.scope)("name", act.name));
FC_ASSERT(!act.data.empty(), "Failed to deserialize data for ${account}:${name}", ("account", act.account)("name", act.name));
}
......
......@@ -109,7 +109,7 @@ struct transfer {
uint64 amount;
string memo;
static name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -128,7 +128,7 @@ struct lock {
account_name to;
share_type amount;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -146,7 +146,7 @@ struct unlock {
account_name account;
share_type amount;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -164,7 +164,7 @@ struct claim {
account_name account;
share_type amount;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -181,7 +181,7 @@ struct newaccount {
authority recovery;
asset deposit;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -196,7 +196,7 @@ struct setcode {
uint8 vmversion;
bytes code;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -209,7 +209,7 @@ struct setabi {
account_name account;
abi_def abi;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -228,7 +228,7 @@ struct setproducer {
public_key_type key;
chain_config configuration;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -247,7 +247,7 @@ struct okproducer {
account_name producer;
int8_t approve;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -265,7 +265,7 @@ struct setproxy {
account_name stakeholder;
account_name proxy;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -280,7 +280,7 @@ struct updateauth {
permission_name parent;
authority data;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -298,7 +298,7 @@ struct deleteauth {
account_name account;
permission_name permission;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -318,7 +318,7 @@ struct linkauth {
action_name type;
permission_name requirement;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -337,7 +337,7 @@ struct unlinkauth {
account_name code;
action_name type;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -349,7 +349,7 @@ struct unlinkauth {
struct onerror : bytes {
using bytes::bytes;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -363,7 +363,7 @@ struct postrecovery {
authority data;
string memo;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -375,7 +375,7 @@ struct postrecovery {
struct passrecovery {
account_name account;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -388,7 +388,7 @@ struct passrecovery {
struct vetorecovery {
account_name account;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......@@ -401,7 +401,7 @@ using nonce_type = name;
struct nonce {
nonce_type value;
static scope_name get_scope() {
static account_name get_account() {
return config::system_account_name;
}
......
......@@ -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_scope, eosio::chain::transaction_exception, 3030020, "missing required read scope" )
FC_DECLARE_DERIVED_EXCEPTION( tx_missing_write_scope, eosio::chain::transaction_exception, 3030021, "missing required write scope" )
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" )
......
......@@ -94,9 +94,7 @@ 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;
}
......
#pragma once
#include <eosio/chain/transaction.hpp>
namespace eosio { namespace chain {
struct pending_cycle_state : cycle_trace {
set<scope_name> read_scopes;
map<scope_name,uint32_t> write_scope_to_shard;
/**
* @return the shard number this transation goes in or (-1) if it
* cannot go on any shard due to conflict
*/
uint32_t schedule( const transaction& trx ) {
uint32_t current_shard = -1;
for( const auto& ws : trx.write_scope ) {
if( read_scopes.find(ws) != read_scopes.end() )
return -1;
auto itr = write_scope_to_shard.find(ws);
if( itr != write_scope_to_shard.end() ) {
if( current_shard == -1 ) {
current_shard = itr->second;
continue;
}
if( current_shard != itr->second )
return -1; /// conflict detected
}
}
for( const auto& rs : trx.read_scope )
{
auto itr = write_scope_to_shard.find(rs);
if( itr != write_scope_to_shard.end() ) {
if( current_shard == -1 ) {
current_shard = itr->second;
continue;
}
if( current_shard != itr->second )
return -1; /// schedule conflict
current_shard = itr->second;
}
}
if( current_shard == -1 ) {
shards.resize( shards.size()+1 );
current_shard = shards.size() - 1;
}
for( auto ws : trx.write_scope )
{
shards.back().write_scopes.insert( ws );
write_scope_to_shard[ws] = current_shard;
}
for( auto rs : trx.read_scope )
read_scopes.insert(rs);
return current_shard;
} /// schedule
struct pending_shard {
set<scope_name> write_scopes;
};
vector<pending_shard> shards;
};
} } /// eosio::chain
......@@ -34,7 +34,7 @@ namespace eosio { namespace chain {
* were properly declared when it executes.
*/
struct action {
scope_name scope;
account_name account;
action_name name;
vector<permission_level> authorization;
vector<char> data;
......@@ -43,7 +43,7 @@ namespace eosio { namespace chain {
template<typename T, std::enable_if_t<std::is_base_of<bytes, T>::value, int> = 1>
action( vector<permission_level> auth, const T& value ) {
scope = T::get_scope();
account = T::get_account();
name = T::get_name();
authorization = move(auth);
data.assign(value.data(), value.data() + value.size());
......@@ -51,7 +51,7 @@ namespace eosio { namespace chain {
template<typename T, std::enable_if_t<!std::is_base_of<bytes, T>::value, int> = 1>
action( vector<permission_level> auth, const T& value ) {
scope = T::get_scope();
account = T::get_account();
name = T::get_name();
authorization = move(auth);
data = fc::raw::pack(value);
......@@ -59,8 +59,8 @@ namespace eosio { namespace chain {
template<typename T>
T as()const {
FC_ASSERT( scope == T::get_scope() );
FC_ASSERT( name == T::get_name() );
FC_ASSERT( account == T::get_account() );
FC_ASSERT( name == T::get_name() );
return fc::raw::unpack<T>(data);
}
};
......@@ -128,8 +128,6 @@ namespace eosio { namespace chain {
* read and write scopes.
*/
struct transaction : public transaction_header {
vector<account_name> read_scope;
vector<account_name> write_scope;
vector<action> actions;
transaction_id_type id()const;
......@@ -196,48 +194,12 @@ 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) )
FC_REFLECT( eosio::chain::action, (scope)(name)(authorization)(data) )
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), (read_scope)(write_scope)(actions) )
FC_REFLECT_DERIVED( eosio::chain::transaction, (eosio::chain::transaction_header), (actions) )
FC_REFLECT_DERIVED( eosio::chain::signed_transaction, (eosio::chain::transaction), (signatures) )
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))
......
/**
* @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
......@@ -412,10 +412,10 @@ namespace eosio { namespace chain {
}
void wasm_interface::apply( wasm_cache::entry& code, apply_context& context ) {
if (context.act.scope == config::system_account_name && context.act.name == N(setcode)) {
if (context.act.account == config::system_account_name && context.act.name == N(setcode)) {
my->call("init", {}, code, context);
} else {
vector<Value> args = {Value(uint64_t(context.act.scope)),
vector<Value> args = {Value(uint64_t(context.act.account)),
Value(uint64_t(context.act.name))};
my->call("apply", args, code, context);
}
......@@ -673,12 +673,12 @@ class action_api : public context_aware_api {
}
fc::time_point_sec publication_time() {
return context.published;
return context.trx_meta.published;
}
name current_sender() {
if (context.sender) {
return *context.sender;
if (context.trx_meta.sender) {
return *context.trx_meta.sender;
} else {
return name();
}
......@@ -911,8 +911,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>
......@@ -63,12 +64,32 @@ namespace fc {
template<typename T>
void move_append(std::vector<T> &dest, std::vector<T>&& src ) {
if (dest.empty()) {
if (src.empty()) {
return;
} else if (dest.empty()) {
dest = std::move(src);
} else {
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
......
......@@ -60,7 +60,7 @@ namespace eosio { namespace testing {
for( const auto& region : trace.block.regions) {
for( const auto& cycle : region.cycles_summary ) {
for ( const auto& shard : cycle ) {
for( const auto& receipt: shard ) {
for( const auto& receipt: shard.transactions ) {
chain_transactions.emplace(receipt.id, receipt);
}
}
......@@ -93,7 +93,6 @@ namespace eosio { namespace testing {
void tester::create_account( account_name a, asset initial_balance, account_name creator, bool multisig ) {
signed_transaction trx;
set_tapos( trx );
trx.write_scope = { creator, config::eosio_auth_scope };
authority owner_auth;
if (multisig) {
......@@ -133,7 +132,6 @@ namespace eosio { namespace testing {
}
transaction_trace tester::transfer( account_name from, account_name to, asset amount, string memo ) {
signed_transaction trx;
trx.write_scope = {from,to};
trx.actions.emplace_back( vector<permission_level>{{from,config::active_name}},
contracts::transfer{
.from = from,
......@@ -151,7 +149,6 @@ namespace eosio { namespace testing {
authority auth,
permission_name parent ) { try {
signed_transaction trx;
trx.write_scope = {config::eosio_auth_scope};
trx.actions.emplace_back( vector<permission_level>{{account,perm}},
contracts::updateauth{
.account = account,
......@@ -210,7 +207,6 @@ namespace eosio { namespace testing {
auto wasm = assemble(wast);
signed_transaction trx;
trx.write_scope = {config::eosio_auth_scope, account};
trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
contracts::setcode{
.account = account,
......@@ -227,7 +223,6 @@ namespace eosio { namespace testing {
void tester::set_abi( account_name account, const char* abi_json) {
auto abi = fc::json::from_string(abi_json).template as<contracts::abi_def>();
signed_transaction trx;
trx.write_scope = {config::eosio_auth_scope};
trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
contracts::setabi{
.account = account,
......
......@@ -48,7 +48,7 @@ public:
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 signed_block&);
void applied_block(const chain::block_trace&);
fc::variant transaction_to_variant(const signed_transaction& pretty_input) const;
chain_plugin* chain_plug;
......@@ -283,45 +283,59 @@ vector<account_name> account_history_plugin_impl::get_controlled_accounts(const
return vector<account_name>(accounts.begin(), accounts.end());
}
void account_history_plugin_impl::applied_block(const signed_block& block)
static vector<account_name> generated_affected_accounts(const chain::transaction_trace& trx_trace) {
vector<account_name> result;
for (const auto& at: trx_trace.action_traces) {
for (const auto& auth: at.act.authorization) {
result.emplace_back(auth.actor);
}
result.emplace_back(at.receiver);
}
fc::deduplicate(result);
return result;
}
void account_history_plugin_impl::applied_block(const chain::block_trace& trace)
{
const auto& block = trace.block;
const auto block_id = block.id();
auto& db = chain_plug->chain().get_mutable_database();
const bool check_relevance = filter_on.size();
for (const signed_transaction& trx : block.input_transactions)
auto process_one = [&](const chain::transaction_trace& trx_trace )
{
if (check_relevance && !is_scope_relevant(trx.read_scope) && !is_scope_relevant(trx.write_scope))
continue;
auto affected_accounts = generated_affected_accounts(trx_trace);
if (check_relevance && !is_scope_relevant(affected_accounts))
return;
auto trx_obj_ptr = db.find<transaction_history_object, by_trx_id>(trx.id());
auto trx_obj_ptr = db.find<transaction_history_object, by_trx_id>(trx_trace.id);
if (trx_obj_ptr != nullptr)
continue; // on restart may already have block
return; // on restart may already have block
db.create<transaction_history_object>([&block_id,&trx](transaction_history_object& transaction_history) {
db.create<transaction_history_object>([&block_id,&trx_trace](transaction_history_object& transaction_history) {
transaction_history.block_id = block_id;
transaction_history.transaction_id = trx.id();
transaction_history.transaction_id = trx_trace.id;
transaction_history.transaction_status = trx_trace.status;
});
auto create_ath_object = [&trx,&db](const account_name& name) {
db.create<account_transaction_history_object>([&trx,&name](account_transaction_history_object& account_transaction_history) {
auto create_ath_object = [&trx_trace,&db](const account_name& name) {
db.create<account_transaction_history_object>([&trx_trace,&name](account_transaction_history_object& account_transaction_history) {
account_transaction_history.name = name;
account_transaction_history.transaction_id = trx.id();
account_transaction_history.transaction_id = trx_trace.id;
});
};
for (const auto& account_name : trx.read_scope)
create_ath_object(account_name);
for (const auto& account_name : trx.write_scope)
for (const auto& account_name : affected_accounts)
create_ath_object(account_name);
for (const chain::action& act : trx.actions)
for (const auto& act_trace : trx_trace.action_traces)
{
if (act.scope == chain::config::system_account_name)
if (act_trace.receiver == chain::config::system_account_name)
{
if (act.name == NEW_ACCOUNT)
if (act_trace.act.name == NEW_ACCOUNT)
{
const auto create = act.as<chain::contracts::newaccount>();
const auto create = act_trace.act.as<chain::contracts::newaccount>();
add(db, create.owner.keys, create.name, OWNER);
add(db, create.active.keys, create.name, ACTIVE);
add(db, create.recovery.keys, create.name, RECOVERY);
......@@ -330,25 +344,32 @@ void account_history_plugin_impl::applied_block(const signed_block& block)
add(db, create.active.accounts, create.name, ACTIVE);
add(db, create.recovery.accounts, create.name, RECOVERY);
}
else if (act.name == UPDATE_AUTH)
else if (act_trace.act.name == UPDATE_AUTH)
{
const auto update = act.as<chain::contracts::updateauth>();
const auto update = act_trace.act.as<chain::contracts::updateauth>();
remove<public_key_history_multi_index, by_account_permission>(db, update.account, update.permission);
add(db, update.data.keys, update.account, update.permission);
remove<account_control_history_multi_index, by_controlled_authority>(db, update.account, update.permission);
add(db, update.data.accounts, update.account, update.permission);
}
else if (act.name == DELETE_AUTH)
else if (act_trace.act.name == DELETE_AUTH)
{
const auto del = act.as<chain::contracts::deleteauth>();
const auto del = act_trace.act.as<chain::contracts::deleteauth>();
remove<public_key_history_multi_index, by_account_permission>(db, del.account, del.permission);
remove<account_control_history_multi_index, by_controlled_authority>(db, del.account, del.permission);
}
}
}
}
};
// go through all the transaction traces
for (const auto& rt: trace.region_traces)
for(const auto& ct: rt.cycle_traces)
for(const auto& st: ct.shard_traces)
for(const auto& trx_trace: st.transaction_traces)
process_one(trx_trace);
}
void account_history_plugin_impl::add(chainbase::database& db, const vector<key_weight>& keys, const account_name& name, const permission_name& permission)
......
......@@ -5,18 +5,21 @@
#pragma once
#include <chainbase/chainbase.hpp>
#include <eosio/chain/transaction.hpp>
namespace eosio {
using chain::block_id_type;
using chain::transaction_id_type;
using chain::transaction_receipt;
using namespace boost::multi_index;
class transaction_history_object : public chainbase::object<chain::transaction_history_object_type, transaction_history_object> {
OBJECT_CTOR(transaction_history_object)
id_type id;
block_id_type block_id;
transaction_id_type transaction_id;
id_type id;
block_id_type block_id;
transaction_id_type transaction_id;
transaction_receipt::status_enum transaction_status;
};
struct by_id;
......@@ -35,5 +38,5 @@ typedef chainbase::generic_index<transaction_history_multi_index> transaction_hi
CHAINBASE_SET_INDEX_TYPE( eosio::transaction_history_object, eosio::transaction_history_multi_index )
FC_REFLECT( eosio::transaction_history_object, (block_id)(transaction_id) )
FC_REFLECT( eosio::transaction_history_object, (block_id)(transaction_id)(transaction_status) )
......@@ -230,7 +230,6 @@ struct faucet_testnet_plugin_impl {
auto active_auth = chain::authority{1, {{active_pub_key, 1}}, {}};
auto recovery_auth = chain::authority{1, {}, {{{_create_account_name, "active"}, 1}}};
trx.write_scope = sort_names({_create_account_name,config::eosio_auth_scope});
trx.actions.emplace_back(vector<chain::permission_level>{{_create_account_name,"active"}},
contracts::newaccount{_create_account_name, new_account_name, owner_auth, active_auth, recovery_auth, deposit});
......
......@@ -73,7 +73,6 @@ struct txn_test_gen_plugin_impl {
signed_transaction trx;
trx.expiration = cc.head_block_time() + fc::seconds(30);
trx.set_reference_block(cc.head_block_id());
trx.write_scope = {creator, config::system_account_name, config::eosio_auth_scope};
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, contracts::lock{creator, creator, 300});
//create "A" account
......@@ -98,7 +97,6 @@ struct txn_test_gen_plugin_impl {
{
uint64_t balance = 10000;
signed_transaction trx;
trx.write_scope = sort_names({creator,newaccountA,newaccountB});
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, contracts::transfer{creator, newaccountA, balance, memo});
trx.actions.emplace_back(vector<chain::permission_level>{{creator,"active"}}, contracts::transfer{creator, newaccountB, balance, memo});
trx.expiration = cc.head_block_time() + fc::seconds(30);
......@@ -150,7 +148,6 @@ struct txn_test_gen_plugin_impl {
//make transaction a->b
{
signed_transaction trx;
trx.write_scope = sort_names({sender,recipient});
trx.actions.emplace_back(vector<chain::permission_level>{{sender,"active"}}, contracts::transfer{sender, recipient, 1, memo});
trx.expiration = cc.head_block_time() + fc::seconds(30);
trx.set_reference_block(cc.head_block_id());
......@@ -163,7 +160,6 @@ struct txn_test_gen_plugin_impl {
//make transaction b->a
{
signed_transaction trx;
trx.write_scope = sort_names({sender,recipient});
trx.actions.emplace_back(vector<chain::permission_level>{{recipient,"active"}}, contracts::transfer{recipient, sender, 1, memo});
trx.expiration = cc.head_block_time() + fc::seconds(30);
trx.set_reference_block(cc.head_block_id());
......
......@@ -275,8 +275,6 @@ fc::variant push_transaction( signed_transaction& trx, bool sign ) {
auto info = get_info();
trx.expiration = info.head_block_time + tx_expiration;
trx.set_reference_block(info.head_block_id);
boost::sort( trx.write_scope );
boost::sort( trx.read_scope );
if (sign) {
sign_transaction(trx);
......@@ -294,8 +292,7 @@ void create_account(name creator, name newaccount, public_key_type owner, public
uint64_t deposit = 1;
signed_transaction trx;
trx.write_scope = sort_names({creator,config::eosio_auth_scope});
trx.actions.emplace_back( vector<chain::permission_level>{{creator,"active"}},
trx.actions.emplace_back( vector<chain::permission_level>{{creator,"active"}},
contracts::newaccount{creator, newaccount, owner_auth, active_auth, recovery_auth, deposit});
std::cout << fc::json::to_pretty_string(push_transaction(trx, sign)) << std::endl;
......@@ -321,9 +318,8 @@ chain::action create_unlinkauth(const name& account, const name& code, const nam
contracts::unlinkauth{account, code, type}};
}
void send_transaction(const std::vector<chain::action>& actions, const std::vector<name>& scopes, bool skip_sign = false) {
void send_transaction(const std::vector<chain::action>& actions, bool skip_sign = false) {
signed_transaction trx;
trx.write_scope = sort_names(scopes);
for (const auto& m: actions) {
trx.actions.emplace_back( m );
}
......@@ -362,7 +358,7 @@ struct set_account_permission_subcommand {
bool is_delete = boost::iequals(authorityJsonOrFile, "null");
if (is_delete) {
send_transaction({create_deleteauth(account, permission, name(permissionAuth))}, {account, config::system_account_name}, skip_sign);
send_transaction({create_deleteauth(account, permission, name(permissionAuth))}, skip_sign);
} else {
authority auth;
if (boost::istarts_with(authorityJsonOrFile, "EOS")) {
......@@ -401,7 +397,7 @@ struct set_account_permission_subcommand {
parent = name(parentStr);
}
send_transaction({create_updateauth(account, permission, parent, auth, name(permissionAuth))}, {name(account), config::system_account_name}, skip_sign);
send_transaction({create_updateauth(account, permission, parent, auth, name(permissionAuth))}, skip_sign);
}
});
}
......@@ -431,10 +427,10 @@ struct set_action_permission_subcommand {
bool is_delete = boost::iequals(requirementStr, "null");
if (is_delete) {
send_transaction({create_unlinkauth(account, code, type)}, {account, config::system_account_name}, skip_sign);
send_transaction({create_unlinkauth(account, code, type)}, skip_sign);
} else {
name requirement = name(requirementStr);
send_transaction({create_linkauth(account, code, type, requirement)}, {name(account), config::system_account_name}, skip_sign);
send_transaction({create_linkauth(account, code, type, requirement)}, skip_sign);
}
});
}
......@@ -513,7 +509,6 @@ int main( int argc, char** argv ) {
auto account_permissions = get_account_permissions(permissions);
signed_transaction trx;
trx.write_scope = sort_names({config::system_account_name, account_name});
trx.actions.emplace_back( account_permissions, contracts::setproducer{account_name, public_key_type(ownerKey), chain_config{}} );
std::cout << fc::json::to_pretty_string(push_transaction(trx, !skip_sign)) << std::endl;
......@@ -699,7 +694,6 @@ int main( int argc, char** argv ) {
handler.code.assign(wasm.begin(), wasm.end());
signed_transaction trx;
trx.write_scope = sort_names({config::eosio_auth_scope, account});
trx.actions.emplace_back( vector<chain::permission_level>{{account,"active"}}, handler);
if (abi->count()) {
......@@ -734,7 +728,6 @@ int main( int argc, char** argv ) {
auto account_permissions = get_account_permissions(permissions);
signed_transaction trx;
trx.write_scope = sort_names({config::system_account_name, account_name});
trx.actions.emplace_back( account_permissions, contracts::okproducer{account_name, producer, approve});
push_transaction(trx, !skip_sign);
......@@ -761,7 +754,6 @@ int main( int argc, char** argv ) {
}
signed_transaction trx;
trx.write_scope = sort_names({config::system_account_name, account_name});
trx.actions.emplace_back( account_permissions, contracts::setproxy{account_name, proxy});
push_transaction(trx, !skip_sign);
......@@ -794,8 +786,7 @@ int main( int argc, char** argv ) {
add_standard_transaction_options(transfer);
transfer->set_callback([&] {
signed_transaction trx;
trx.write_scope = sort_names({sender,recipient});
if (tx_force_unique) {
if (memo.size() == 0) {
// use the memo to add a nonce
......@@ -996,8 +987,7 @@ int main( int argc, char** argv ) {
uint64_t deposit = 1;
signed_transaction trx;
trx.write_scope = sort_names({creator,config::system_account_name});
trx.actions.emplace_back( vector<chain::permission_level>{{creator,"active"}},
trx.actions.emplace_back( vector<chain::permission_level>{{creator,"active"}},
contracts::newaccount{creator, newaccount, owner_auth, active_auth, recovery_auth, deposit});
trx.expiration = info.head_block_time + tx_expiration;
......@@ -1029,7 +1019,6 @@ int main( int argc, char** argv ) {
uint32_t amount = 100000;
signed_transaction trx;
trx.write_scope = sort_names({sender,recipient});
trx.actions.emplace_back( vector<chain::permission_level>{{sender,"active"}},
contracts::transfer{ .from = sender, .to = recipient, .amount = amount, .memo = memo});
trx.expiration = info.head_block_time + tx_expiration;
......@@ -1065,7 +1054,6 @@ int main( int argc, char** argv ) {
auto memo = fc::variant(fc::time_point::now()).as_string() + " " + fc::variant(fc::time_point::now().time_since_epoch()).as_string();
trx.write_scope = sort_names({sender,recipient});
trx.actions.emplace_back( vector<chain::permission_level>{{sender,"active"}},
contracts::transfer{ .from = sender, .to = recipient, .amount = amount, .memo = memo});
trx.expiration = info.head_block_time + tx_expiration;
......@@ -1100,7 +1088,6 @@ int main( int argc, char** argv ) {
string contract;
string action;
string data;
vector<string> scopes;
auto actionsSubcommand = push->add_subcommand("actions", localized("Push a transaction with a single actions"));
actionsSubcommand->fallthrough(false);
actionsSubcommand->add_option("contract", contract,
......@@ -1110,7 +1097,6 @@ int main( int argc, char** argv ) {
actionsSubcommand->add_option("data", data, localized("The arguments to the contract"))->required();
actionsSubcommand->add_option("-p,--permission", permissions,
localized("An account and permission level to authorize, as in 'account@permission'"));
actionsSubcommand->add_option("-S,--scope", scopes, localized("An comma separated list of accounts in scope for this operation"), true);
actionsSubcommand->add_flag("-s,--skip-sign", skip_sign, localized("Specify that unlocked wallet keys should not be used to sign transaction"));
add_standard_transaction_options(actionsSubcommand);
actionsSubcommand->set_callback([&] {
......@@ -1133,12 +1119,6 @@ int main( int argc, char** argv ) {
trx.actions.emplace_back( generate_nonce() );
}
for( const auto& scope : scopes ) {
vector<string> subscopes;
boost::split( subscopes, scope, boost::is_any_of( ", :" ) );
for( const auto& s : subscopes )
trx.write_scope.emplace_back(s);
}
std::cout << fc::json::to_pretty_string(push_transaction(trx, !skip_sign )) << std::endl;
});
......
......@@ -211,7 +211,7 @@ BOOST_FIXTURE_TEST_CASE( prove_action_in_block, tester ) { try {
auto a_data = action_proof_data {
at.receiver,
at.act.scope,
at.act.account,
at.act.name,
at.act.data,
at.region_id,
......
......@@ -11,7 +11,6 @@ using namespace eosio::testing;
auto make_postrecovery(const tester &t, account_name account, string role) {
signed_transaction trx;
trx.write_scope = {config::eosio_auth_scope, account};
trx.actions.emplace_back( vector<permission_level>{{account,config::active_name}},
postrecovery{
.account = account,
......@@ -25,7 +24,6 @@ auto make_postrecovery(const tester &t, account_name account, string role) {
auto make_vetorecovery(const tester &t, account_name account, permission_name vetoperm = N(active), optional<private_key_type> signing_key = optional<private_key_type>()) {
signed_transaction trx;
trx.write_scope = {config::eosio_auth_scope, account};
trx.actions.emplace_back( vector<permission_level>{{account,vetoperm}},
vetorecovery{
.account = account
......@@ -42,7 +40,6 @@ auto make_vetorecovery(const tester &t, account_name account, permission_name ve
auto push_nonce(tester &t, const string& role) {
// ensure the old owner key is valid
signed_transaction trx;
trx.write_scope = {N(alice)};
trx.actions.emplace_back( vector<permission_level>{{N(alice),config::owner_name}},
nonce{
.value = t.control->head_block_num()
......
......@@ -60,7 +60,6 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
auto to = N(dan);
asset amount(1);
signed_transaction trx;
trx.write_scope = {from,to};
trx.actions.emplace_back( vector<permission_level>{{from,config::active_name}},
contracts::transfer{
.from = from,
......@@ -80,7 +79,6 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
auto to = N(dan);
asset amount(1);
signed_transaction trx;
trx.write_scope = {from,to};
trx.actions.emplace_back( vector<permission_level>{{to,config::active_name}},
contracts::transfer{
.from = from,
......@@ -95,25 +93,6 @@ BOOST_AUTO_TEST_CASE( transfer_test ) { try {
BOOST_REQUIRE_THROW( test.control->push_transaction( trx ), tx_missing_auth);
}
{
auto from = N(bart);
auto to = N(dan);
asset amount(1);
signed_transaction trx;
// trx.write_scope = {from,to};
trx.actions.emplace_back( vector<permission_level>{{from,config::active_name}},
contracts::transfer{
.from = from,
.to = to,
.amount = amount.amount,
.memo = "memo"
} );
test.set_tapos( trx );
trx.sign( test.get_private_key( from, "active" ), chain_id_type() );
BOOST_REQUIRE_THROW( test.control->push_transaction( trx ), tx_missing_write_scope);
}
} FC_LOG_AND_RETHROW() } /// transfer_test
......@@ -151,7 +130,6 @@ BOOST_AUTO_TEST_CASE( transfer_delegation ) { try {
asset amount(1);
signed_transaction trx;
trx.write_scope = {from,to};
trx.actions.emplace_back( vector<permission_level>{{from,config::active_name}},
contracts::transfer{
.from = from,
......
......@@ -29,7 +29,7 @@ struct assertdef {
int8_t condition;
string message;
static scope_name get_scope() {
static account_name get_account() {
return N(asserter);
}
......@@ -41,7 +41,7 @@ struct assertdef {
FC_REFLECT(assertdef, (condition)(message));
struct provereset {
static scope_name get_scope() {
static account_name get_account() {
return N(asserter);
}
......@@ -67,7 +67,7 @@ constexpr uint64_t TEST_METHOD(const char* CLASS, const char *METHOD) {
template<uint64_t NAME>
struct test_api_action {
static scope_name get_scope() {
static account_name get_account() {
return N(tester);
}
......@@ -105,7 +105,7 @@ BOOST_FIXTURE_TEST_CASE( basic_test, tester ) try {
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() );
BOOST_CHECK_EQUAL(result.action_traces.at(0).act.scope.to_string(), name(N(asserter)).to_string() );
BOOST_CHECK_EQUAL(result.action_traces.at(0).act.account.to_string(), name(N(asserter)).to_string() );
BOOST_CHECK_EQUAL(result.action_traces.at(0).act.name.to_string(), name(N(procassert)).to_string() );
BOOST_CHECK_EQUAL(result.action_traces.at(0).act.authorization.size(), 1 );
BOOST_CHECK_EQUAL(result.action_traces.at(0).act.authorization.at(0).actor.to_string(), name(N(asserter)).to_string() );
......@@ -198,7 +198,7 @@ BOOST_FIXTURE_TEST_CASE( abi_from_variant, tester ) try {
variant pretty_trx = mutable_variant_object()
("actions", variants({
mutable_variant_object()
("scope", "asserter")
("account", "asserter")
("name", "procassert")
("authorization", variants({
mutable_variant_object()
......@@ -296,9 +296,8 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
// make a transfer from the contract to a user
{
signed_transaction trx;
trx.write_scope = {N(currency),N(alice)};
action transfer_act;
transfer_act.scope = N(currency);
transfer_act.account = N(currency);
transfer_act.name = N(transfer);
transfer_act.authorization = vector<permission_level>{{N(currency), config::active_name}};
transfer_act.data = abi_ser.variant_to_binary("transfer", mutable_variant_object()
......@@ -319,9 +318,8 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
// Overspend!
{
signed_transaction trx;
trx.write_scope = {N(alice),N(bob)};
action transfer_act;
transfer_act.scope = N(currency);
transfer_act.account = N(currency);
transfer_act.name = N(transfer);
transfer_act.authorization = vector<permission_level>{{N(alice), config::active_name}};
transfer_act.data = abi_ser.variant_to_binary("transfer", mutable_variant_object()
......@@ -342,9 +340,8 @@ BOOST_FIXTURE_TEST_CASE( test_currency, tester ) try {
// Full spend
{
signed_transaction trx;
trx.write_scope = {N(alice),N(bob)};
action transfer_act;
transfer_act.scope = N(currency);
transfer_act.account = N(currency);
transfer_act.name = N(transfer);
transfer_act.authorization = vector<permission_level>{{N(alice), config::active_name}};
transfer_act.data = abi_ser.variant_to_binary("transfer", mutable_variant_object()
......@@ -384,9 +381,8 @@ BOOST_FIXTURE_TEST_CASE( test_proxy, tester ) try {
// set up proxy owner
{
signed_transaction trx;
trx.write_scope = {N(proxy)};
action setowner_act;
setowner_act.scope = N(proxy);
setowner_act.account = N(proxy);
setowner_act.name = N(setowner);
setowner_act.authorization = vector<permission_level>{{N(proxy), config::active_name}};
setowner_act.data = abi_ser.variant_to_binary("setowner", mutable_variant_object()
......@@ -442,9 +438,8 @@ BOOST_FIXTURE_TEST_CASE( test_deferred_failure, tester ) try {
// set up proxy owner
{
signed_transaction trx;
trx.write_scope = {N(proxy)};
action setowner_act;
setowner_act.scope = N(proxy);
setowner_act.account = N(proxy);
setowner_act.name = N(setowner);
setowner_act.authorization = vector<permission_level>{{N(proxy), config::active_name}};
setowner_act.data = abi_ser.variant_to_binary("setowner", mutable_variant_object()
......@@ -484,9 +479,8 @@ BOOST_FIXTURE_TEST_CASE( test_deferred_failure, tester ) try {
// set up bob owner
{
signed_transaction trx;
trx.write_scope = {N(bob)};
action setowner_act;
setowner_act.scope = N(bob);
setowner_act.account = N(bob);
setowner_act.name = N(setowner);
setowner_act.authorization = vector<permission_level>{{N(bob), config::active_name}};
setowner_act.data = abi_ser.variant_to_binary("setowner", mutable_variant_object()
......@@ -538,7 +532,7 @@ BOOST_FIXTURE_TEST_CASE( check_entry_behavior, tester ) try {
signed_transaction trx;
action act;
act.scope = N(entrycheck);
act.account = N(entrycheck);
act.name = N();
act.authorization = vector<permission_level>{{N(entrycheck),config::active_name}};
trx.actions.push_back(act);
......@@ -568,7 +562,7 @@ BOOST_FIXTURE_TEST_CASE( simple_no_memory_check, tester ) try {
//the apply func of simple_no_memory_wast tries to call a native func with linear memory pointer
signed_transaction trx;
action act;
act.scope = N(nomem);
act.account = N(nomem);
act.name = N();
act.authorization = vector<permission_level>{{N(nomem),config::active_name}};
trx.actions.push_back(act);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册