diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index e04ae6f037d..a1e25be44f3 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -27,6 +27,7 @@ #include #include +#include #include @@ -37,6 +38,8 @@ #include #include +#include + #include #include #include @@ -94,9 +97,15 @@ private_key_type testing_fixture::get_private_key(const public_key_type& public_ return itr->second; } +flat_set testing_fixture::available_keys() const { + auto range = key_ring | boost::adaptors::map_keys; + return {range.begin(), range.end()}; +} + testing_blockchain::testing_blockchain(chainbase::database& db, fork_database& fork_db, block_log& blocklog, chain_initializer_interface& initializer, testing_fixture& fixture) : chain_controller(db, fork_db, blocklog, initializer, native_contract::make_administrator()), + db(db), fixture(fixture) {} void testing_blockchain::produce_blocks(uint32_t count, uint32_t blocks_to_miss) { @@ -157,6 +166,34 @@ types::PublicKey testing_blockchain::get_block_signing_key(const types::AccountN return get_database().get(producerName).signing_key; } +void testing_blockchain::sign_transaction(SignedTransaction& trx) { + auto GetAuthority = [this](const types::AccountPermission& permission) { + auto key = boost::make_tuple(permission.account, permission.permission); + return db.get(key).auth; + }; + auto checker = MakeAuthorityChecker(GetAuthority, fixture.available_keys()); + + for (const auto& message : trx.messages) + for (const auto& authorization : message.authorization) + if (!checker.satisfied(authorization)) + elog("Attempting to automatically sign transaction, but testing_fixture doesn't have the keys!"); + + for (const auto& key : checker.used_keys()) + // TODO: Use a real chain_id here + trx.sign(fixture.get_private_key(key), chain_id_type{}); +} + +ProcessedTransaction testing_blockchain::push_transaction(SignedTransaction trx, uint32_t skip_flags) { + if (skip_trx_sigs) + skip_flags |= chain_controller::skip_transaction_signatures; + + if (auto_sign_trxs) { + sign_transaction(trx); + } + + return chain_controller::push_transaction(trx, skip_flags); +} + void testing_network::connect_blockchain(testing_blockchain& new_database) { if (blockchains.count(&new_database)) return; diff --git a/tests/common/database_fixture.hpp b/tests/common/database_fixture.hpp index b655700cd88..fd6d95603cb 100644 --- a/tests/common/database_fixture.hpp +++ b/tests/common/database_fixture.hpp @@ -119,6 +119,7 @@ class testing_fixture { void store_private_key(const private_key_type& key); private_key_type get_private_key(const public_key_type& public_key) const; + flat_set available_keys() const; protected: std::vector anonymous_temp_dirs; @@ -178,8 +179,27 @@ class testing_blockchain : public chain_controller { /// @brief Get the specified block producer's signing key 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); + + /// @brief Override push_transaction to apply testing policies + ProcessedTransaction push_transaction(SignedTransaction trx, uint32_t skip_flags = 0); + + /// @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 + void set_skip_transaction_signature_checking(bool skip_sigs) { + skip_trx_sigs = skip_sigs; + } + /// @brief Set whether testing_blockchain::push_transaction attempts to sign transactions or not + void set_auto_sign_transactions(bool auto_sign) { + auto_sign_trxs = auto_sign; + } + protected: + chainbase::database& db; testing_fixture& fixture; + bool skip_trx_sigs = true; + bool auto_sign_trxs = false; }; using boost::signals2::scoped_connection; diff --git a/tests/common/macro_support.hpp b/tests/common/macro_support.hpp index ee9df2096c7..bfec2829676 100644 --- a/tests/common/macro_support.hpp +++ b/tests/common/macro_support.hpp @@ -51,7 +51,7 @@ inline std::vector sort_names( std::vector&& names ) { "newaccount", types::newaccount{#creator, #name, owner, active, recovery, deposit}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Created account " << #name); \ } #define MKACCT2(chain, name) \ @@ -83,7 +83,7 @@ inline std::vector sort_names( std::vector&& names ) { "updateauth", types::updateauth{#account, authname, parentname, auth}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Set " << #account << "'s " << authname << " authority."); \ } @@ -96,7 +96,7 @@ inline std::vector sort_names( std::vector&& names ) { "deleteauth", types::deleteauth{#account, authname}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Deleted " << #account << "'s " << authname << " authority."); \ } @@ -109,7 +109,7 @@ inline std::vector sort_names( std::vector&& names ) { "linkauth", types::linkauth{#account, #codeacct, messagetype, authname}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Link " << #codeacct << "::" << messagetype << " to " << #account \ << "'s " << authname << " authority."); \ } @@ -124,7 +124,7 @@ inline std::vector sort_names( std::vector&& names ) { "unlinkauth", types::unlinkauth{#account, #codeacct, messagetype}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Unlink " << #codeacct << "::" << messagetype << " from " << #account); \ } #define LINKAUTH3(chain, account, codeacct) LINKAUTH5(chain, account, codeacct, "") @@ -138,7 +138,7 @@ inline std::vector sort_names( std::vector&& names ) { "transfer", types::transfer{#sender, #recipient, Amount.amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Transfered " << Amount << " from " << #sender << " to " << #recipient); \ } #define XFER4(chain, sender, recipient, amount) XFER5(chain, sender, recipient, amount, "") @@ -151,7 +151,7 @@ inline std::vector sort_names( std::vector&& names ) { "lock", types::lock{#sender, #recipient, amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Staked " << amount << " to " << #recipient); \ } #define STAKE3(chain, account, amount) STAKE4(chain, account, account, amount) @@ -165,7 +165,7 @@ inline std::vector sort_names( std::vector&& names ) { "unlock", types::unlock{#account, amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Begin unstake " << amount << " to " << #account); \ } @@ -177,7 +177,7 @@ inline std::vector sort_names( std::vector&& names ) { "claim", types::claim{#account, amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Finish unstake " << amount << " to " << #account); \ } @@ -190,7 +190,7 @@ inline std::vector sort_names( std::vector&& names ) { "setproducer", types::setproducer{#owner, key, cfg}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Create producer " << #owner); \ } #define MKPDCR3(chain, owner, key) MKPDCR4(chain, owner, key, BlockchainConfiguration{}); @@ -207,7 +207,7 @@ inline std::vector sort_names( std::vector&& names ) { "okproducer", types::okproducer{#voter, #producer, approved? 1 : 0}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Set producer approval from " << #voter << " for " << #producer << " to " << approved); \ } @@ -220,7 +220,7 @@ inline std::vector sort_names( std::vector&& names ) { "setproducer", types::setproducer{owner, key, cfg}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ + chain.push_transaction(trx); \ BOOST_TEST_CHECKPOINT("Update producer " << owner); \ } #define UPPDCR3(chain, owner, key) UPPDCR4(chain, owner, key, chain.get_producer(owner).configuration)