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

Resolve #152: Disable auth updates in pending transactions #159

Merged
merged 2 commits into from
Aug 10, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions libraries/chain/chain_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ void chain_controller::apply_block(const signed_block& next_block, uint32_t skip

void chain_controller::_apply_block(const signed_block& next_block)
{ try {
auto UnsetApplyingBlock = fc::make_scoped_exit([this] { _currently_applying_block = false; });
_currently_applying_block = true;

uint32_t next_block_num = next_block.block_num();
uint32_t skip = _skip_flags;

Expand Down Expand Up @@ -836,6 +839,10 @@ void chain_controller::initialize_indexes() {

void chain_controller::initialize_chain(chain_initializer_interface& starter)
{ try {
// Behave as though we are applying a block during chain initialization (it's the genesis block!)
auto UnsetApplyingBlock = fc::make_scoped_exit([this] { _currently_applying_block = false; });
_currently_applying_block = true;

if (!_db.find<global_property_object>()) {
_db.with_write_lock([this, &starter] {
auto initial_timestamp = starter.get_chain_start_time();
Expand Down
7 changes: 6 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 @@ -321,7 +326,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