Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #159 from EOSIO/no-pending-auth-updates-152
Browse files Browse the repository at this point in the history
Resolve #152: Disable auth updates in pending transactions
  • Loading branch information
nathanielhourt authored Aug 10, 2017
2 parents 67ef2f4 + 4b9752a commit 7e21097
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 27 deletions.
14 changes: 12 additions & 2 deletions libraries/chain/chain_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,12 @@ void chain_controller::apply_block(const signed_block& next_block, uint32_t skip
if (_checkpoints.rbegin()->first >= block_num)
skip = ~0;// WE CAN SKIP ALMOST EVERYTHING
}
with_skip_flags(skip, [&](){ _apply_block(next_block); });

with_applying_block([&] {
with_skip_flags(skip, [&] {
_apply_block(next_block);
});
});
}

void chain_controller::_apply_block(const signed_block& next_block)
Expand Down Expand Up @@ -876,7 +881,12 @@ chain_controller::chain_controller(database& database, fork_database& fork_db, b

initialize_indexes();
starter.register_types(*this, _db);
initialize_chain(starter);

// Behave as though we are applying a block during chain initialization (it's the genesis block!)
with_applying_block([&] {
initialize_chain(starter);
});

spinup_db();
spinup_fork_db();

Expand Down
16 changes: 15 additions & 1 deletion libraries/chain/include/eos/chain/chain_controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ namespace eos { namespace chain {
*/
signal<void(const SignedTransaction&)> on_pending_transaction;

/**
* @brief Check whether the controller is currently applying a block or not
* @return True if the controller is now applying a block; false otherwise
*/
bool is_applying_block()const { return _currently_applying_block; }

/**
* The controller can override any script endpoint with native code.
Expand Down Expand Up @@ -255,6 +260,15 @@ namespace eos { namespace chain {
void apply_block(const signed_block& next_block, uint32_t skip = skip_nothing);
void _apply_block(const signed_block& next_block);

template<typename Function>
auto with_applying_block(Function&& f) -> decltype((*((Function*)nullptr))()) {
auto on_exit = fc::make_scoped_exit([this](){
_currently_applying_block = false;
});
_currently_applying_block = true;
return f();
}

void check_transaction_authorization(const SignedTransaction& trx)const;

ProcessedTransaction apply_transaction(const SignedTransaction& trx, uint32_t skip = skip_nothing);
Expand Down Expand Up @@ -321,7 +335,7 @@ namespace eos { namespace chain {
optional<database::session> _pending_tx_session;
deque<SignedTransaction> _pending_transactions;

bool _pushing = false;
bool _currently_applying_block = false;
uint64_t _skip_flags = 0;

flat_map<uint32_t,block_id_type> _checkpoints;
Expand Down
54 changes: 30 additions & 24 deletions libraries/native_contract/eos_contract.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <eos/native_contract/eos_contract.hpp>

#include <eos/chain/chain_controller.hpp>
#include <eos/chain/message_handling_contexts.hpp>
#include <eos/chain/message.hpp>
#include <eos/chain/exceptions.hpp>
Expand Down Expand Up @@ -56,19 +57,20 @@ void apply_eos_newaccount(apply_context& context) {
a.name = create.name;
a.creation_date = db.get(dynamic_global_property_object::id_type()).time;
});
const auto& owner_permission = db.create<permission_object>([&create, &new_account](permission_object& p) {
p.name = "owner";
p.parent = 0;
p.owner = new_account.name;
p.auth = std::move(create.owner);
});
db.create<permission_object>([&create, &owner_permission](permission_object& p) {
p.name = "active";
p.parent = owner_permission.id;
p.owner = owner_permission.owner;
p.auth = std::move(create.active);
});

if (context.controller.is_applying_block()) {
const auto& owner_permission = db.create<permission_object>([&create, &new_account](permission_object& p) {
p.name = "owner";
p.parent = 0;
p.owner = new_account.name;
p.auth = std::move(create.owner);
});
db.create<permission_object>([&create, &owner_permission](permission_object& p) {
p.name = "active";
p.parent = owner_permission.id;
p.owner = owner_permission.owner;
p.auth = std::move(create.active);
});
}

const auto& creatorBalance = context.mutable_db.get<BalanceObject, byOwnerName>(create.creator);

Expand Down Expand Up @@ -388,11 +390,12 @@ void apply_eos_updateauth(apply_context& context) {
if (permission) {
EOS_ASSERT(parent.id == permission->parent, message_precondition_exception,
"Changing parent authority is not currently supported");
db.modify(*permission, [&update, parent = parent.id](permission_object& po) {
po.auth = update.authority;
po.parent = parent;
});
} else {
if (context.controller.is_applying_block())
db.modify(*permission, [&update, parent = parent.id](permission_object& po) {
po.auth = update.authority;
po.parent = parent;
});
} else if (context.controller.is_applying_block()) {
db.create<permission_object>([&update, parent = parent.id](permission_object& po) {
po.name = update.permission;
po.owner = update.account;
Expand Down Expand Up @@ -425,7 +428,8 @@ void apply_eos_deleteauth(apply_context& context) {
"Cannot delete a linked authority. Unlink the authority first");
}

db.remove(permission);
if (context.controller.is_applying_block())
db.remove(permission);
}

void apply_eos_linkauth(apply_context& context) {
Expand All @@ -445,10 +449,11 @@ void apply_eos_linkauth(apply_context& context) {
if (link) {
EOS_ASSERT(link->required_permission != requirement.requirement, message_precondition_exception,
"Attempting to update required authority, but new requirement is same as old");
db.modify(*link, [requirement = requirement.requirement](permission_link_object& link) {
link.required_permission = requirement;
});
} else {
if (context.controller.is_applying_block())
db.modify(*link, [requirement = requirement.requirement](permission_link_object& link) {
link.required_permission = requirement;
});
} else if (context.controller.is_applying_block()) {
db.create<permission_link_object>([&requirement](permission_link_object& link) {
link.account = requirement.account;
link.code = requirement.code;
Expand All @@ -467,7 +472,8 @@ void apply_eos_unlinkauth(apply_context& context) {
auto linkKey = boost::make_tuple(unlink.account, unlink.code, unlink.type);
auto link = db.find<permission_link_object, by_message_type>(linkKey);
EOS_ASSERT(link != nullptr, message_precondition_exception, "Attempting to unlink authority, but no link found");
db.remove(*link);
if (context.controller.is_applying_block())
db.remove(*link);
}

} // namespace eos
Expand Down
24 changes: 24 additions & 0 deletions tests/tests/native_contract_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ BOOST_FIXTURE_TEST_CASE(auth_tests, testing_fixture) {
Make_Key(k2);
Set_Authority(chain, alice, "spending", "active", Key_Authority(k1_public_key));

// Ensure authority doesn't appear until next block
BOOST_CHECK_EQUAL((chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "spending"))), nullptr);
chain.produce_blocks();

{
auto obj = chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "spending"));
BOOST_CHECK_NE(obj, nullptr);
Expand All @@ -414,6 +418,8 @@ BOOST_FIXTURE_TEST_CASE(auth_tests, testing_fixture) {
BOOST_CHECK_THROW(Set_Authority(chain, alice, "spending", "owner", Key_Authority(k1_public_key)),
message_precondition_exception);
Delete_Authority(chain, alice, "spending");
BOOST_CHECK_NE((chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "spending"))), nullptr);
chain.produce_blocks();

{
auto obj = chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "spending"));
Expand All @@ -423,7 +429,11 @@ BOOST_FIXTURE_TEST_CASE(auth_tests, testing_fixture) {
chain.produce_blocks();

Set_Authority(chain, alice, "trading", "active", Key_Authority(k1_public_key));
BOOST_CHECK_EQUAL((chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "trading"))), nullptr);
chain.produce_blocks();
Set_Authority(chain, alice, "spending", "trading", Key_Authority(k2_public_key));
BOOST_CHECK_EQUAL((chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "spending"))), nullptr);
chain.produce_blocks();

{
auto trading = chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "trading"));
Expand Down Expand Up @@ -456,7 +466,11 @@ BOOST_FIXTURE_TEST_CASE(auth_tests, testing_fixture) {
BOOST_CHECK_THROW(Set_Authority(chain, alice, "spending", "active", Key_Authority(k1_public_key)),
message_precondition_exception);
Delete_Authority(chain, alice, "spending");
BOOST_CHECK_NE((chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "spending"))), nullptr);
chain.produce_blocks();
Delete_Authority(chain, alice, "trading");
BOOST_CHECK_NE((chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "trading"))), nullptr);
chain.produce_blocks();

{
auto trading = chain_db.find<permission_object, by_owner>(boost::make_tuple("alice", "trading"));
Expand All @@ -475,8 +489,14 @@ BOOST_FIXTURE_TEST_CASE(auth_links, testing_fixture) { try {
Make_Key(scud);

Set_Authority(chain, alice, "spending", "active", Key_Authority(spending_public_key));
chain.produce_blocks();
Set_Authority(chain, alice, "scud", "spending", Key_Authority(scud_public_key));
chain.produce_blocks();
Link_Authority(chain, alice, "spending", eos, "transfer");
BOOST_CHECK_EQUAL(
(chain_db.find<permission_link_object, by_message_type>(boost::make_tuple("alice", "eos", "transfer"))),
nullptr);
chain.produce_blocks();

{
auto obj = chain_db.find<permission_link_object, by_message_type>(boost::make_tuple("alice", "eos", "transfer"));
Expand All @@ -487,6 +507,10 @@ BOOST_FIXTURE_TEST_CASE(auth_links, testing_fixture) { try {
}

Unlink_Authority(chain, alice, eos, "transfer");
BOOST_CHECK_NE(
(chain_db.find<permission_link_object, by_message_type>(boost::make_tuple("alice", "eos", "transfer"))),
nullptr);
chain.produce_blocks();

{
auto obj = chain_db.find<permission_link_object, by_message_type>(boost::make_tuple("alice", "eos", "transfer"));
Expand Down

0 comments on commit 7e21097

Please sign in to comment.