提交 e0a007da 编写于 作者: D Daniel Larimer 提交者: GitHub

Merge pull request #176 from EOSIO/permission-links-123

Testing #123: Permission links
......@@ -509,7 +509,8 @@ void chain_controller::check_transaction_authorization(const SignedTransaction&
if ((_skip_flags & skip_authority_check) == false) {
const auto& index = _db.get_index<permission_index>().indices();
EOS_ASSERT(getPermission(declaredAuthority).satisfies(minimumPermission, index), tx_irrelevant_auth,
"Message declares irrelevant authority '${auth}'", ("auth", declaredAuthority));
"Message declares irrelevant authority '${auth}'; minimum authority is ${min}",
("auth", declaredAuthority)("min", minimumPermission.name));
}
if ((_skip_flags & skip_transaction_signatures) == false) {
EOS_ASSERT(checker.satisfied(declaredAuthority), tx_missing_sigs,
......@@ -518,8 +519,9 @@ void chain_controller::check_transaction_authorization(const SignedTransaction&
}
}
EOS_ASSERT(checker.all_keys_used(), tx_irrelevant_sig,
"Transaction bears irrelevant signatures from these keys: ${keys}", ("keys", checker.unused_keys()));
if ((_skip_flags & skip_transaction_signatures) == false)
EOS_ASSERT(checker.all_keys_used(), tx_irrelevant_sig,
"Transaction bears irrelevant signatures from these keys: ${keys}", ("keys", checker.unused_keys()));
}
ProcessedTransaction chain_controller::apply_transaction(const SignedTransaction& trx, uint32_t skip)
......
......@@ -146,6 +146,8 @@ void apply_eos_lock(apply_context& context) {
context.require_scope(lock.from);
context.require_scope(config::EosContractName);
context.require_authorization(lock.from);
context.require_recipient(lock.to);
context.require_recipient(lock.from);
......
......@@ -166,7 +166,7 @@ types::PublicKey testing_blockchain::get_block_signing_key(const types::AccountN
return get_database().get<producer_object, by_owner>(producerName).signing_key;
}
void testing_blockchain::sign_transaction(SignedTransaction& trx) {
void testing_blockchain::sign_transaction(SignedTransaction& trx) const {
auto GetAuthority = [this](const types::AccountPermission& permission) {
auto key = boost::make_tuple(permission.account, permission.permission);
return db.get<permission_object, by_owner>(key).auth;
......@@ -184,7 +184,7 @@ void testing_blockchain::sign_transaction(SignedTransaction& trx) {
trx.sign(fixture.get_private_key(key), chain_id_type{});
}
ProcessedTransaction testing_blockchain::push_transaction(SignedTransaction trx, uint32_t skip_flags) {
fc::optional<ProcessedTransaction> testing_blockchain::push_transaction(SignedTransaction trx, uint32_t skip_flags) {
if (skip_trx_sigs)
skip_flags |= chain_controller::skip_transaction_signatures;
......@@ -192,6 +192,10 @@ ProcessedTransaction testing_blockchain::push_transaction(SignedTransaction trx,
sign_transaction(trx);
}
if (hold_for_review) {
review_storage = std::make_pair(trx, skip_flags);
return {};
}
return chain_controller::push_transaction(trx, skip_flags);
}
......
......@@ -180,10 +180,21 @@ public:
PublicKey get_block_signing_key(const AccountName& producerName);
/// @brief Attempt to sign the provided transaction using the keys available to the testing_fixture
void sign_transaction(SignedTransaction& trx);
void sign_transaction(SignedTransaction& trx) const;
/// @brief Override push_transaction to apply testing policies
ProcessedTransaction push_transaction(SignedTransaction trx, uint32_t skip_flags = 0);
/// If transactions are being held for review, transaction will be held after testing policies are applied
fc::optional<ProcessedTransaction> push_transaction(SignedTransaction trx, uint32_t skip_flags = 0);
/// @brief Review and optionally push last held transaction
/// @tparam F A callable with signature `bool f(SignedTransaction&, uint32_t&)`
/// @param reviewer Callable which inspects and potentially alters the held transaction and skip flags, and returns
/// whether it should be pushed or not
template<typename F>
fc::optional<ProcessedTransaction> review_transaction(F&& reviewer) {
if (reviewer(review_storage.first, review_storage.second))
return chain_controller::push_transaction(review_storage.first, review_storage.second);
return {};
}
/// @brief Set whether testing_blockchain::push_transaction checks signatures by default
/// @param skip_sigs If true, push_transaction will skip signature checks; otherwise, no changes will be made
......@@ -194,12 +205,18 @@ public:
void set_auto_sign_transactions(bool auto_sign) {
auto_sign_trxs = auto_sign;
}
/// @brief Set whether testing_blockchain::push_transaction holds transactions for review or not
void set_hold_transactions_for_review(bool hold_trxs) {
hold_for_review = hold_trxs;
}
protected:
chainbase::database& db;
testing_fixture& fixture;
std::pair<SignedTransaction, uint32_t> review_storage;
bool skip_trx_sigs = true;
bool auto_sign_trxs = false;
bool hold_for_review = false;
};
using boost::signals2::scoped_connection;
......
......@@ -483,6 +483,7 @@ BOOST_FIXTURE_TEST_CASE(auth_tests, testing_fixture) {
BOOST_FIXTURE_TEST_CASE(auth_links, testing_fixture) { try {
Make_Blockchain(chain);
Make_Account(chain, alice);
Make_Account(chain, bob);
chain.produce_blocks();
Make_Key(spending);
......@@ -506,16 +507,62 @@ BOOST_FIXTURE_TEST_CASE(auth_links, testing_fixture) { try {
BOOST_CHECK_EQUAL(obj->message_type, "transfer");
}
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);
Transfer_Asset(chain, inita, alice, Asset(1000));
// Take off the training wheels, we're gonna fully validate transactions now
chain.set_auto_sign_transactions(false);
chain.set_skip_transaction_signature_checking(false);
chain.set_hold_transactions_for_review(true);
// This won't run yet; it'll get held for review
Transfer_Asset(chain, alice, bob, Asset(10));
// OK, set the above transfer's authorization level to scud and check that it fails
BOOST_CHECK_THROW(chain.review_transaction([&chain](SignedTransaction& trx, auto) {
trx.messages.front().authorization = {{"alice", "scud"}};
chain.sign_transaction(trx);
return true;
}), tx_irrelevant_auth);
// OK, now set the auth level to spending, and it should succeed
chain.review_transaction([&chain](SignedTransaction& trx, auto) {
trx.messages.front().authorization = {{"alice", "spending"}};
trx.signatures.clear();
chain.sign_transaction(trx);
return true;
});
// Finally, set it to active, it should still succeed
chain.review_transaction([&chain](SignedTransaction& trx, auto) {
trx.messages.front().authorization = {{"alice", "active"}};
trx.signatures.clear();
chain.sign_transaction(trx);
return true;
});
BOOST_CHECK_EQUAL(chain.get_liquid_balance("bob"), Asset(20));
SignedTransaction backup;
// Now we'll lock some funds, but we'll use the scud authority to do it. First, this should fail, but back up the
// transaction for later
Stake_Asset(chain, alice, 100);
BOOST_CHECK_THROW(chain.review_transaction([&chain, &backup](SignedTransaction& trx, auto) {
trx.messages.front().authorization = {{"alice", "scud"}};
trx.scope = {"alice", config::EosContractName};
chain.sign_transaction(trx);
backup = trx;
return true;
}), tx_irrelevant_auth);
// Now set the default authority to scud...
Link_Authority(chain, alice, "scud", eos);
chain.review_transaction([&chain](SignedTransaction& trx, auto) { chain.sign_transaction(trx); return true; });
chain.produce_blocks();
{
auto obj = chain_db.find<permission_link_object, by_message_type>(boost::make_tuple("alice", "eos", "transfer"));
BOOST_CHECK_EQUAL(obj, nullptr);
}
// And now the backed up transaction should succeed, because scud is sufficient authority for all except "transfer"
chain.chain_controller::push_transaction(backup);
// But transfers with scud authority should still not work, because there's an overriding link to spending
Transfer_Asset(chain, alice, bob, Asset(10));
BOOST_CHECK_THROW(chain.review_transaction([&chain](SignedTransaction& trx, auto) {
trx.messages.front().authorization = {{"alice", "scud"}};
chain.sign_transaction(trx);
return true;
}), tx_irrelevant_auth);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册