diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/block_weight/block_weight.cpp | 2 | ||||
-rw-r--r-- | tests/core_tests/chaingen.h | 19 | ||||
-rw-r--r-- | tests/core_tests/wallet_tools.cpp | 2 | ||||
-rw-r--r-- | tests/difficulty/difficulty.cpp | 5 | ||||
-rwxr-xr-x | tests/functional_tests/bans.py | 117 | ||||
-rwxr-xr-x | tests/functional_tests/blockchain.py | 172 | ||||
-rwxr-xr-x | tests/functional_tests/cold_signing.py | 22 | ||||
-rwxr-xr-x | tests/functional_tests/functional_tests_rpc.py | 2 | ||||
-rwxr-xr-x | tests/functional_tests/multisig.py | 17 | ||||
-rwxr-xr-x | tests/functional_tests/transfer.py | 87 | ||||
-rwxr-xr-x | tests/functional_tests/wallet_address.py | 50 | ||||
-rw-r--r-- | tests/hash-target.cpp | 3 | ||||
-rw-r--r-- | tests/hash/main.cpp | 4 | ||||
-rw-r--r-- | tests/libwallet_api_tests/main.cpp | 3 | ||||
-rw-r--r-- | tests/trezor/daemon.cpp | 8 | ||||
-rw-r--r-- | tests/trezor/trezor_tests.cpp | 87 | ||||
-rw-r--r-- | tests/trezor/trezor_tests.h | 2 | ||||
-rw-r--r-- | tests/unit_tests/blockchain_db.cpp | 4 |
18 files changed, 573 insertions, 33 deletions
diff --git a/tests/block_weight/block_weight.cpp b/tests/block_weight/block_weight.cpp index 7b3fdfe57..f193133da 100644 --- a/tests/block_weight/block_weight.cpp +++ b/tests/block_weight/block_weight.cpp @@ -195,8 +195,10 @@ static void test(test_t t, uint64_t blocks) int main() { + TRY_ENTRY(); test(test_max, 2 * LONG_TERM_BLOCK_WEIGHT_WINDOW); test(test_lcg, 9 * LONG_TERM_BLOCK_WEIGHT_WINDOW); test(test_min, 1 * LONG_TERM_BLOCK_WEIGHT_WINDOW); return 0; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index 64431960e..797d1207b 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -643,7 +643,15 @@ public: log_event("cryptonote::block"); cryptonote::block_verification_context bvc = AUTO_VAL_INIT(bvc); - m_c.handle_incoming_block(t_serializable_object_to_blob(b), &b, bvc); + cryptonote::blobdata bd = t_serializable_object_to_blob(b); + std::vector<cryptonote::block> pblocks; + if (m_c.prepare_handle_incoming_blocks(std::vector<cryptonote::block_complete_entry>(1, {bd, {}}), pblocks)) + { + m_c.handle_incoming_block(bd, &b, bvc); + m_c.cleanup_handle_incoming_blocks(); + } + else + bvc.m_verifivation_failed = true; bool r = check_block_verification_context(bvc, m_ev_index, b, m_validator); CHECK_AND_NO_ASSERT_MES(r, false, "block verification context check failed"); return r; @@ -666,7 +674,14 @@ public: log_event("serialized_block"); cryptonote::block_verification_context bvc = AUTO_VAL_INIT(bvc); - m_c.handle_incoming_block(sr_block.data, NULL, bvc); + std::vector<cryptonote::block> pblocks; + if (m_c.prepare_handle_incoming_blocks(std::vector<cryptonote::block_complete_entry>(1, {sr_block.data, {}}), pblocks)) + { + m_c.handle_incoming_block(sr_block.data, NULL, bvc); + m_c.cleanup_handle_incoming_blocks(); + } + else + bvc.m_verifivation_failed = true; cryptonote::block blk; std::stringstream ss; diff --git a/tests/core_tests/wallet_tools.cpp b/tests/core_tests/wallet_tools.cpp index 616774d18..d9cee34c1 100644 --- a/tests/core_tests/wallet_tools.cpp +++ b/tests/core_tests/wallet_tools.cpp @@ -135,7 +135,7 @@ bool wallet_tools::fill_tx_sources(tools::wallet2 * wallet, std::vector<cryptono } } - MINFO("Selected " << i << " from tx: " << dump_keys(td.m_txid.data) + MDEBUG("Selected " << i << " from tx: " << dump_keys(td.m_txid.data) << " ki: " << dump_keys(td.m_key_image.data) << " amnt: " << td.amount() << " rct: " << td.is_rct() diff --git a/tests/difficulty/difficulty.cpp b/tests/difficulty/difficulty.cpp index 9985b8710..11ce0bd73 100644 --- a/tests/difficulty/difficulty.cpp +++ b/tests/difficulty/difficulty.cpp @@ -36,6 +36,7 @@ #include <algorithm> #include <stdexcept> +#include "misc_log_ex.h" #include "cryptonote_config.h" #include "cryptonote_basic/difficulty.h" @@ -82,6 +83,8 @@ static int test_wide_difficulty(const char *filename) } int main(int argc, char *argv[]) { + TRY_ENTRY(); + if (argc < 2) { cerr << "Wrong arguments" << endl; return 1; @@ -136,4 +139,6 @@ int main(int argc, char *argv[]) { data.clear(fstream::badbit); } return 0; + + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/functional_tests/bans.py b/tests/functional_tests/bans.py new file mode 100755 index 000000000..bb3051a6a --- /dev/null +++ b/tests/functional_tests/bans.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2019 The Monero Project +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be +# used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import time + +"""Test peer baning RPC calls + +Test the following RPCs: + - set_bans + - get_bans + +""" + +from framework.daemon import Daemon + +class BanTest(): + def run_test(self): + print 'Testing bans' + + daemon = Daemon() + res = daemon.get_bans() + assert 'bans' not in res or len(res.bans) == 0 + + daemon.set_bans([{'host': '1.2.3.4', 'ban': True, 'seconds': 100}]) + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '1.2.3.4' + assert res.bans[0].seconds >= 98 and res.bans[0].seconds <= 100 # allow for slow RPC + + daemon.set_bans([{'host': '5.6.7.8', 'ban': True, 'seconds': 100}]) + res = daemon.get_bans() + assert len(res.bans) == 2 + for i in range(2): + assert res.bans[i].host == '1.2.3.4' or res.bans[i].host == '5.6.7.8' + assert res.bans[i].seconds >= 7 and res.bans[0].seconds <= 100 # allow for slow RPC + + daemon.set_bans([{'host': '1.2.3.4', 'ban': False}]) + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '5.6.7.8' + assert res.bans[0].seconds >= 98 and res.bans[0].seconds <= 100 # allow for slow RPC + + time.sleep(2) + + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '5.6.7.8' + assert res.bans[0].seconds >= 96 and res.bans[0].seconds <= 98 # allow for slow RPC + + daemon.set_bans([{'host': '3.4.5.6', 'ban': False}]) + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '5.6.7.8' + assert res.bans[0].seconds >= 96 and res.bans[0].seconds <= 98 # allow for slow RPC + + daemon.set_bans([{'host': '3.4.5.6', 'ban': True, 'seconds': 2}]) + res = daemon.get_bans() + assert len(res.bans) == 2 + for i in range(2): + assert res.bans[i].host == '5.6.7.8' or res.bans[i].host == '3.4.5.6' + if res.bans[i].host == '5.6.7.8': + assert res.bans[i].seconds >= 96 and res.bans[0].seconds <= 98 # allow for slow RPC + else: + assert res.bans[i].seconds >= 1 and res.bans[0].seconds <= 2 # allow for slow RPC + + time.sleep(2) + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '5.6.7.8' + assert res.bans[0].seconds >= 94 and res.bans[0].seconds <= 96 # allow for slow RPC + + daemon.set_bans([{'host': '5.6.7.8', 'ban': True, 'seconds': 20}]) + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '5.6.7.8' + assert res.bans[0].seconds >= 18 and res.bans[0].seconds <= 20 # allow for slow RPC + + daemon.set_bans([{'host': '5.6.7.8', 'ban': True, 'seconds': 200}]) + res = daemon.get_bans() + assert len(res.bans) == 1 + assert res.bans[0].host == '5.6.7.8' + assert res.bans[0].seconds >= 198 and res.bans[0].seconds <= 200 # allow for slow RPC + + daemon.set_bans([{'host': '5.6.7.8', 'ban': False}]) + res = daemon.get_bans() + assert 'bans' not in res or len(res.bans) == 0 + + +if __name__ == '__main__': + BanTest().run_test() diff --git a/tests/functional_tests/blockchain.py b/tests/functional_tests/blockchain.py index d805fccda..56164600d 100755 --- a/tests/functional_tests/blockchain.py +++ b/tests/functional_tests/blockchain.py @@ -46,6 +46,7 @@ from framework.daemon import Daemon class BlockchainTest(): def run_test(self): self._test_generateblocks(5) + self._test_alt_chains() def _test_generateblocks(self, blocks): assert blocks >= 2 @@ -60,8 +61,8 @@ class BlockchainTest(): prev_block = res_info.top_block_hash res_height = daemon.get_height() assert res_height.height == height - assert int(res_info.wide_cumulative_difficulty) == (res_info.cumulative_difficulty_top64 << 64) + res_info.cumulative_difficulty - cumulative_difficulty = int(res_info.wide_cumulative_difficulty) + assert int(res_info.wide_cumulative_difficulty, 16) == (res_info.cumulative_difficulty_top64 << 64) + res_info.cumulative_difficulty + cumulative_difficulty = int(res_info.wide_cumulative_difficulty, 16) # we should not see a block at height ok = False @@ -90,11 +91,11 @@ class BlockchainTest(): assert block_header.orphan_status == False assert block_header.depth == blocks - n - 1 assert block_header.prev_hash == prev_block, prev_block - assert int(block_header.wide_difficulty) == (block_header.difficulty_top64 << 64) + block_header.difficulty - assert int(block_header.wide_cumulative_difficulty) == (block_header.cumulative_difficulty_top64 << 64) + block_header.cumulative_difficulty + assert int(block_header.wide_difficulty, 16) == (block_header.difficulty_top64 << 64) + block_header.difficulty + assert int(block_header.wide_cumulative_difficulty, 16) == (block_header.cumulative_difficulty_top64 << 64) + block_header.cumulative_difficulty assert block_header.reward >= 600000000000 # tail emission - cumulative_difficulty += int(block_header.wide_difficulty) - assert cumulative_difficulty == int(block_header.wide_cumulative_difficulty) + cumulative_difficulty += int(block_header.wide_difficulty, 16) + assert cumulative_difficulty == int(block_header.wide_cumulative_difficulty, 16) assert block_header.block_size > 0 assert block_header.block_weight >= block_header.block_size assert block_header.long_term_weight > 0 @@ -122,7 +123,7 @@ class BlockchainTest(): assert res_getblocktemplate.expected_reward >= 600000000000 assert len(res_getblocktemplate.blocktemplate_blob) > 0 assert len(res_getblocktemplate.blockhashing_blob) > 0 - assert int(res_getblocktemplate.wide_difficulty) == (res_getblocktemplate.difficulty_top64 << 64) + res_getblocktemplate.difficulty + assert int(res_getblocktemplate.wide_difficulty, 16) == (res_getblocktemplate.difficulty_top64 << 64) + res_getblocktemplate.difficulty # diff etc should be the same assert res_getblocktemplate.prev_hash == res_info.top_block_hash @@ -152,6 +153,163 @@ class BlockchainTest(): except: ok = True assert ok + # get transactions + res = daemon.get_info() + assert res.height == height + blocks - 1 + nblocks = height + blocks - 1 + res = daemon.getblockheadersrange(0, nblocks - 1) + assert len(res.headers) == nblocks + assert res.headers[-1] == block_header + txids = [x.miner_tx_hash for x in res.headers] + res = daemon.get_transactions(txs_hashes = txids) + assert len(res.txs) == nblocks + assert not 'missed_txs' in res or len(res.missed_txs) == 0 + running_output_index = 0 + for i in range(len(txids)): + tx = res.txs[i] + assert tx.tx_hash == txids[i] + assert not tx.double_spend_seen + assert not tx.in_pool + assert tx.block_height == i + if i > 0: + for idx in tx.output_indices: + assert idx == running_output_index + running_output_index += 1 + res_out = daemon.get_outs([{'amount': 0, 'index': i} for i in tx.output_indices], get_txid = True) + assert len(res_out.outs) == len(tx.output_indices) + for out in res_out.outs: + assert len(out.key) == 64 + assert len(out.mask) == 64 + assert not out.unlocked + assert out.height == i + 1 + assert out.txid == txids[i + 1] + + for i in range(height + nblocks - 1): + res_sum = daemon.get_coinbase_tx_sum(i, 1) + res_header = daemon.getblockheaderbyheight(i) + assert res_sum.emission_amount == res_header.block_header.reward + + res = daemon.get_coinbase_tx_sum(0, 1) + assert res.emission_amount == 17592186044415 + assert res.fee_amount == 0 + sum_blocks = height + nblocks - 1 + res = daemon.get_coinbase_tx_sum(0, sum_blocks) + extrapolated = 17592186044415 + 17592186044415 * 2 * (sum_blocks - 1) + assert res.emission_amount < extrapolated and res.emission_amount > extrapolated - 1e12 + assert res.fee_amount == 0 + sum_blocks_emission = res.emission_amount + res = daemon.get_coinbase_tx_sum(1, sum_blocks) + assert res.emission_amount == sum_blocks_emission - 17592186044415 + assert res.fee_amount == 0 + + res = daemon.get_output_distribution([0, 1, 17592186044415], 0, 0) + assert len(res.distributions) == 3 + for a in range(3): + assert res.distributions[a].amount == [0, 1, 17592186044415][a] + assert res.distributions[a].start_height == 0 + assert res.distributions[a].base == 0 + assert len(res.distributions[a].distribution) == height + nblocks - 1 + assert res.distributions[a].binary == False + for i in range(height + nblocks - 1): + assert res.distributions[a].distribution[i] == (1 if i > 0 and a == 0 else 1 if a == 2 and i == 0 else 0) + + res = daemon.get_output_histogram([], min_count = 0, max_count = 0) + assert len(res.histogram) == 2 + for i in range(2): + assert res.histogram[i].amount in [0, 17592186044415] + assert res.histogram[i].total_instances in [height + nblocks - 2, 1] + assert res.histogram[i].unlocked_instances == 0 + assert res.histogram[i].recent_instances == 0 + + def _test_alt_chains(self): + print('Testing alt chains') + daemon = Daemon() + res = daemon.get_alt_blocks_hashes() + starting_alt_blocks = res.blks_hashes if 'blks_hashes' in res else [] + res = daemon.get_info() + root_block_hash = res.top_block_hash + height = res.height + prev_hash = res.top_block_hash + res_template = daemon.getblocktemplate('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm') + nonce = 0 + + # 5 siblings + alt_blocks = [None] * 5 + for i in range(len(alt_blocks)): + res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1, prev_block = prev_hash, starting_nonce = nonce) + assert res.height == height + assert len(res.blocks) == 1 + txid = res.blocks[0] + res = daemon.getblockheaderbyhash(txid) + nonce = res.block_header.nonce + print('mined ' + ('alt' if res.block_header.orphan_status else 'tip') + ' block ' + str(height) + ', nonce ' + str(nonce)) + assert res.block_header.prev_hash == prev_hash + assert res.block_header.orphan_status == (i > 0) + alt_blocks[i] = txid + nonce += 1 + + print 'mining 3 on 1' + # three more on [1] + chain1 = [] + res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3, prev_block = alt_blocks[1], starting_nonce = nonce) + assert res.height == height + 3 + assert len(res.blocks) == 3 + blk_hash = res.blocks[2] + res = daemon.getblockheaderbyhash(blk_hash) + nonce = res.block_header.nonce + assert not res.block_header.orphan_status + nonce += 1 + chain1.append(blk_hash) + chain1.append(res.block_header.prev_hash) + + print('Checking alt blocks match') + res = daemon.get_alt_blocks_hashes() + assert len(res.blks_hashes) == len(starting_alt_blocks) + 4 + for txid in alt_blocks: + assert txid in res.blks_hashes or txid == alt_blocks[1] + + print 'mining 4 on 3' + # 4 more on [3], the chain will reorg when we mine the 4th + top_block_hash = blk_hash + prev_block = alt_blocks[3] + for i in range(4): + res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1, prev_block = prev_block) + assert res.height == height + 1 + i + assert len(res.blocks) == 1 + prev_block = res.blocks[-1] + res = daemon.getblockheaderbyhash(res.blocks[-1]) + assert res.block_header.orphan_status == (i < 3) + + res = daemon.get_info() + assert res.height == ((height + 4) if i < 3 else height + 5) + assert res.top_block_hash == (top_block_hash if i < 3 else prev_block) + + res = daemon.get_info() + assert res.height == height + 5 + assert res.top_block_hash == prev_block + + print('Checking alt blocks match') + res = daemon.get_alt_blocks_hashes() + blks_hashes = res.blks_hashes + assert len(blks_hashes) == len(starting_alt_blocks) + 7 + for txid in alt_blocks: + assert txid in blks_hashes or txid == alt_blocks[3] + for txid in chain1: + assert txid in blks_hashes + + res = daemon.get_alternate_chains() + assert len(res.chains) == 4 + tips = [chain.block_hash for chain in res.chains] + for txid in tips: + assert txid in blks_hashes + for chain in res.chains: + assert chain.length in [1, 4] + assert chain.length == len(chain.block_hashes) + assert chain.height == height + chain.length - 1 # all happen start at the same height + assert chain.main_chain_parent_block == root_block_hash + for txid in [alt_blocks[0], alt_blocks[2], alt_blocks[4]]: + assert len([chain for chain in res.chains if chain.block_hash == txid]) == 1 + if __name__ == '__main__': BlockchainTest().run_test() diff --git a/tests/functional_tests/cold_signing.py b/tests/functional_tests/cold_signing.py index 6895aec60..e5430f87c 100755 --- a/tests/functional_tests/cold_signing.py +++ b/tests/functional_tests/cold_signing.py @@ -89,6 +89,12 @@ class ColdSigningTest(): dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} payment_id = '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde' + self.hot_wallet.refresh() + res = self.hot_wallet.export_outputs() + self.cold_wallet.import_outputs(res.outputs_data_hex) + res = self.cold_wallet.export_key_images(True) + self.hot_wallet.import_key_images(res.signed_key_images, offset = res.offset) + res = self.hot_wallet.transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False) assert len(res.tx_hash) == 32*2 txid = res.tx_hash @@ -104,6 +110,22 @@ class ColdSigningTest(): unsigned_txset = res.unsigned_txset print 'Signing transaction with cold wallet' + res = self.cold_wallet.describe_transfer(unsigned_txset = unsigned_txset) + assert len(res.desc) == 1 + desc = res.desc[0] + assert desc.amount_in >= amount + fee + assert desc.amount_out == desc.amount_in - fee + assert desc.ring_size == 11 + assert desc.unlock_time == 0 + assert desc.payment_id == payment_id + assert desc.change_amount == desc.amount_in - 1000000000000 - fee + assert desc.change_address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' + assert desc.fee == fee + assert len(desc.recipients) == 1 + rec = desc.recipients[0] + assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' + assert rec.amount == 1000000000000 + res = self.cold_wallet.sign_transfer(unsigned_txset) assert len(res.signed_txset) > 0 signed_txset = res.signed_txset diff --git a/tests/functional_tests/functional_tests_rpc.py b/tests/functional_tests/functional_tests_rpc.py index f2fef7e95..83b75a088 100755 --- a/tests/functional_tests/functional_tests_rpc.py +++ b/tests/functional_tests/functional_tests_rpc.py @@ -133,3 +133,5 @@ if len(FAIL) == 0: print('Done, ' + str(len(PASS)) + '/' + str(len(tests)) + ' tests passed') else: print('Done, ' + str(len(FAIL)) + '/' + str(len(tests)) + ' tests failed: ' + string.join(FAIL, ', ')) + +sys.exit(0 if len(FAIL) == 0 else 1) diff --git a/tests/functional_tests/multisig.py b/tests/functional_tests/multisig.py index a0e8551cd..a61f30001 100755 --- a/tests/functional_tests/multisig.py +++ b/tests/functional_tests/multisig.py @@ -129,6 +129,7 @@ class MultisigTest(): addresses.append(res.address) for i in range(N_total): assert addresses[i] == expected_address + self.wallet_address = expected_address for i in range(N_total): res = self.wallet[i].is_multisig() @@ -181,6 +182,22 @@ class MultisigTest(): for i in range(len(signers[1:])): print('Signing multisig transaction with wallet ' + str(signers[i+1])) + res = self.wallet[signers[i+1]].describe_transfer(multisig_txset = multisig_txset) + assert len(res.desc) == 1 + desc = res.desc[0] + assert desc.amount_in >= amount + fee + assert desc.amount_out == desc.amount_in - fee + assert desc.ring_size == 11 + assert desc.unlock_time == 0 + assert desc.payment_id == '0000000000000000' + assert desc.change_amount == desc.amount_in - 1000000000000 - fee + assert desc.change_address == self.wallet_address + assert desc.fee == fee + assert len(desc.recipients) == 1 + rec = desc.recipients[0] + assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' + assert rec.amount == 1000000000000 + res = self.wallet[signers[i+1]].sign_multisig(multisig_txset) multisig_txset = res.tx_data_hex assert len(res.tx_hash_list if 'tx_hash_list' in res else []) == (i == len(signers[1:]) - 1) diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py index b7a85f1d6..050277c51 100755 --- a/tests/functional_tests/transfer.py +++ b/tests/functional_tests/transfer.py @@ -42,6 +42,7 @@ class TransferTest(): self.mine() self.transfer() self.check_get_bulk_payments() + self.check_double_spend_detection() def create(self): print 'Creating wallets' @@ -62,9 +63,14 @@ class TransferTest(): print("Mining some blocks") daemon = Daemon() + res = daemon.get_info() + height = res.height + daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) for i in range(len(self.wallet)): self.wallet[i].refresh() + res = self.wallet[i].get_height() + assert res.height == height + 80 def transfer(self): daemon = Daemon() @@ -169,6 +175,27 @@ class TransferTest(): assert e.double_spend_seen == False assert e.confirmations == 1 + res = self.wallet[0].get_height() + wallet_height = res.height + res = self.wallet[0].get_transfer_by_txid(txid) + assert len(res.transfers) == 1 + assert res.transfers[0] == res.transfer + t = res.transfer + assert t.txid == txid + assert t.payment_id == payment_id + assert t.height == wallet_height - 1 + assert t.timestamp > 0 + assert t.amount == 0 # to self, so it's just "pay a fee" really + assert t.fee == fee + assert t.note == '' + assert len(t.destinations) == 1 + assert t.destinations[0] == {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} + assert t.type == 'out' + assert t.unlock_time == 0 + assert t.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' + assert t.double_spend_seen == False + assert t.confirmations == 1 + res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance @@ -483,5 +510,65 @@ class TransferTest(): res = self.wallet[2].get_bulk_payments(payment_ids = ['1'*64, '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde', '2'*64]) assert len(res.payments) >= 1 # one tx was sent + def check_double_spend_detection(self): + print('Checking double spend detection') + txes = [[None, None], [None, None]] + for i in range(2): + self.wallet[0].restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted') + self.wallet[0].refresh() + res = self.wallet[0].get_balance() + unlocked_balance = res.unlocked_balance + res = self.wallet[0].sweep_all(address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', do_not_relay = True, get_tx_hex = True) + assert len(res.tx_hash_list) == 1 + assert len(res.tx_hash_list[0]) == 32*2 + txes[i][0] = res.tx_hash_list[0] + assert len(res.fee_list) == 1 + assert res.fee_list[0] > 0 + assert len(res.amount_list) == 1 + assert res.amount_list[0] == unlocked_balance - res.fee_list[0] + assert len(res.tx_blob_list) > 0 + assert len(res.tx_blob_list[0]) > 0 + assert not 'tx_metadata_list' in res or len(res.tx_metadata_list) == 0 + assert not 'multisig_txset' in res or len(res.multisig_txset) == 0 + assert not 'unsigned_txset' in res or len(res.unsigned_txset) == 0 + assert len(res.tx_blob_list) == 1 + txes[i][1] = res.tx_blob_list[0] + + daemon = Daemon() + res = daemon.send_raw_transaction(txes[0][1]) + assert res.not_relayed == False + assert res.low_mixin == False + assert res.double_spend == False + assert res.invalid_input == False + assert res.invalid_output == False + assert res.too_big == False + assert res.overspend == False + assert res.fee_too_low == False + assert res.not_rct == False + + res = daemon.get_transactions([txes[0][0]]) + assert len(res.txs) >= 1 + tx = [tx for tx in res.txs if tx.tx_hash == txes[0][0]][0] + assert tx.in_pool + assert not tx.double_spend_seen + + res = daemon.send_raw_transaction(txes[1][1]) + assert res.not_relayed == False + assert res.low_mixin == False + assert res.double_spend == True + assert res.invalid_input == False + assert res.invalid_output == False + assert res.too_big == False + assert res.overspend == False + assert res.fee_too_low == False + assert res.not_rct == False + + res = daemon.get_transactions([txes[0][0]]) + assert len(res.txs) >= 1 + tx = [tx for tx in res.txs if tx.tx_hash == txes[0][0]][0] + assert tx.in_pool + assert tx.double_spend_seen + + if __name__ == '__main__': TransferTest().run_test() diff --git a/tests/functional_tests/wallet_address.py b/tests/functional_tests/wallet_address.py index 66a1633ca..cb9c52e7a 100755 --- a/tests/functional_tests/wallet_address.py +++ b/tests/functional_tests/wallet_address.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +#encoding=utf-8 # Copyright (c) 2019 The Monero Project # @@ -45,6 +46,8 @@ class WalletAddressTest(): self.check_main_address() self.check_keys() self.create_subaddresses() + self.open_close() + self.languages() def create(self): print 'Creating wallet' @@ -148,5 +151,52 @@ class WalletAddressTest(): res = wallet.get_address_index('82pP87g1Vkd3LUMssBCumk3MfyEsFqLAaGDf6oxddu61EgSFzt8gCwUD4tr3kp9TUfdPs2CnpD7xLZzyC1Ei9UsW3oyCWDf') assert res.index == {'major': 1, 'minor': 0} + def open_close(self): + print 'Testing open/close' + wallet = Wallet() + + res = wallet.get_address() + assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' + + wallet.close_wallet() + ok = False + try: res = wallet.get_address() + except: ok = True + assert ok + + wallet.restore_deterministic_wallet(seed = 'peeled mixture ionic radar utopia puddle buying illness nuns gadget river spout cavernous bounced paradise drunk looking cottage jump tequila melting went winter adjust spout') + res = wallet.get_address() + assert res.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' + + wallet.close_wallet() + ok = False + try: wallet.get_address() + except: ok = True + assert ok + + wallet.restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted') + res = wallet.get_address() + assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' + + def languages(self): + print('Testing languages') + wallet = Wallet() + res = wallet.get_languages() + assert 'English' in res.languages + assert 'English' in res.languages_local + assert 'Dutch' in res.languages + assert 'Nederlands' in res.languages_local + assert 'Japanese' in res.languages + assert u'日本語' in res.languages_local + try: wallet.close_wallet() + except: pass + languages = res.languages + for language in languages: + print 'Creating ' + str(language) + ' wallet' + wallet.create_wallet(filename = '', language = language) + res = wallet.query_key('mnemonic') + wallet.close_wallet() + + if __name__ == '__main__': WalletAddressTest().run_test() diff --git a/tests/hash-target.cpp b/tests/hash-target.cpp index 12acc5a67..1e988c302 100644 --- a/tests/hash-target.cpp +++ b/tests/hash-target.cpp @@ -32,6 +32,7 @@ #include <cstdlib> #include <cstring> #include <limits> +#include "misc_log_ex.h" #include "crypto/hash.h" #include "cryptonote_basic/difficulty.h" @@ -39,6 +40,7 @@ using namespace std; using cryptonote::check_hash; int main(int argc, char *argv[]) { + TRY_ENTRY(); crypto::hash h; for (cryptonote::difficulty_type diff = 1;; diff += 1 + (diff >> 8)) { for (uint16_t b = 0; b < 256; b++) { @@ -83,4 +85,5 @@ int main(int argc, char *argv[]) { } } return 0; + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/hash/main.cpp b/tests/hash/main.cpp index adf1bd9c4..d62098a60 100644 --- a/tests/hash/main.cpp +++ b/tests/hash/main.cpp @@ -35,6 +35,7 @@ #include <string> #include <cfenv> +#include "misc_log_ex.h" #include "warnings.h" #include "crypto/hash.h" #include "crypto/variant2_int_sqrt.h" @@ -89,6 +90,8 @@ int test_variant2_int_sqrt(); int test_variant2_int_sqrt_ref(); int main(int argc, char *argv[]) { + TRY_ENTRY(); + hash_f *f; hash_func *hf; fstream input; @@ -183,6 +186,7 @@ int main(int argc, char *argv[]) { } } return error ? 1 : 0; + CATCH_ENTRY_L0("main", 1); } #if defined(__x86_64__) || (defined(_MSC_VER) && defined(_WIN64)) diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index 02faae50d..c34da04b7 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -1139,6 +1139,8 @@ TEST_F(WalletManagerMainnetTest, RecoverAndRefreshWalletMainNetAsync) int main(int argc, char** argv) { + TRY_ENTRY(); + tools::on_startup(); // we can override default values for "TESTNET_DAEMON_ADDRESS" and "WALLETS_ROOT_DIR" @@ -1173,4 +1175,5 @@ int main(int argc, char** argv) ::testing::InitGoogleTest(&argc, argv); Monero::WalletManagerFactory::setLogLevel(Monero::WalletManagerFactory::LogLevel_Max); return RUN_ALL_TESTS(); + CATCH_ENTRY_L0("main", 1); } diff --git a/tests/trezor/daemon.cpp b/tests/trezor/daemon.cpp index 5e987793a..41af93f3f 100644 --- a/tests/trezor/daemon.cpp +++ b/tests/trezor/daemon.cpp @@ -101,6 +101,9 @@ void mock_daemon::load_params(boost::program_options::variables_map const & vm) mock_daemon::~mock_daemon() { + if(m_http_client.is_connected()) + m_http_client.disconnect(); + if (!m_terminated) { try @@ -134,11 +137,14 @@ void mock_daemon::init() if(m_http_client.is_connected()) m_http_client.disconnect(); - CHECK_AND_ASSERT_THROW_MES(m_http_client.set_server(rpc_addr(), boost::none), "RPC client init fail"); + CHECK_AND_ASSERT_THROW_MES(m_http_client.set_server(rpc_addr(), boost::none, epee::net_utils::ssl_support_t::e_ssl_support_disabled), "RPC client init fail"); } void mock_daemon::deinit() { + if(m_http_client.is_connected()) + m_http_client.disconnect(); + try { m_rpc_server.deinit(); diff --git a/tests/trezor/trezor_tests.cpp b/tests/trezor/trezor_tests.cpp index fd02674ff..a867a4047 100644 --- a/tests/trezor/trezor_tests.cpp +++ b/tests/trezor/trezor_tests.cpp @@ -60,13 +60,14 @@ namespace #define HW_TREZOR_NAME "Trezor" #define TREZOR_ACCOUNT_ORDERING &m_miner_account, &m_alice_account, &m_bob_account, &m_eve_account -#define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE) \ +#define TREZOR_COMMON_TEST_CASE(genclass, CORE, BASE) do { \ rollback_chain(CORE, BASE.head_block()); \ { \ genclass ctest; \ BASE.fork(ctest); \ GENERATE_AND_PLAY_INSTANCE(genclass, ctest, *(CORE)); \ - } + } \ +} while(0) #define TREZOR_SETUP_CHAIN(NAME) do { \ ++tests_count; \ @@ -83,6 +84,11 @@ static device_trezor_test *ensure_trezor_test_device(); static void rollback_chain(cryptonote::core * core, const cryptonote::block & head); static void setup_chain(cryptonote::core * core, gen_trezor_base & trezor_base, std::string chain_path, bool fix_chain, const po::variables_map & vm_core); +static long get_env_long(const char * flag_name, boost::optional<long> def = boost::none){ + const char *env_data = getenv(flag_name); + return env_data ? atol(env_data) : (def ? def.get() : 0); +} + int main(int argc, char* argv[]) { TRY_ENTRY(); @@ -127,12 +133,13 @@ int main(int argc, char* argv[]) const bool heavy_tests = command_line::get_arg(vm, arg_heavy_tests); const bool fix_chain = command_line::get_arg(vm, arg_fix_chain); - hw::register_device(HW_TREZOR_NAME, ensure_trezor_test_device()); - // hw::trezor::register_all(); // We use our shim instead. + hw::register_device(HW_TREZOR_NAME, ensure_trezor_test_device()); // shim device for call tracking // Bootstrapping common chain & accounts - const uint8_t initial_hf = 9; - const uint8_t max_hf = 10; + const uint8_t initial_hf = (uint8_t)get_env_long("TEST_MIN_HF", 11); + const uint8_t max_hf = (uint8_t)get_env_long("TEST_MAX_HF", 11); + MINFO("Test versions " << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")"); + MINFO("Testing hardforks [" << (int)initial_hf << ", " << (int)max_hf << "]"); cryptonote::core core_obj(nullptr); cryptonote::core * const core = &core_obj; @@ -150,16 +157,20 @@ int main(int argc, char* argv[]) mock_daemon::default_options(vm_core); // Transaction tests - for(uint8_t hf=initial_hf; hf <= max_hf; ++hf) + for(uint8_t hf=initial_hf; hf <= max_hf + 1; ++hf) { - MDEBUG("Transaction tests for HF " << (int)hf); - if (hf > initial_hf) + if (hf > initial_hf || hf > max_hf) { daemon->stop_and_deinit(); daemon = nullptr; trezor_base.daemon(nullptr); + if (hf > max_hf) + { + break; + } } + MDEBUG("Transaction tests for HF " << (int)hf); trezor_base.set_hard_fork(hf); TREZOR_SETUP_CHAIN(std::string("HF") + std::to_string((int)hf)); @@ -196,7 +207,6 @@ int main(int argc, char* argv[]) TREZOR_COMMON_TEST_CASE(gen_trezor_many_utxo, core, trezor_base); } - daemon->stop(); core->deinit(); el::Level level = (failed_tests.empty() ? el::Level::Info : el::Level::Error); MLOG(level, "\nREPORT:"); @@ -225,6 +235,7 @@ static void rollback_chain(cryptonote::core * core, const cryptonote::block & he crypto::hash head_hash = get_block_hash(head), cur_hash{}; uint64_t height = get_block_height(head), cur_height=0; + MDEBUG("Rollbacking to " << height << " to hash " << head_hash); do { core->get_blockchain_top(cur_height, cur_hash); @@ -593,7 +604,7 @@ gen_trezor_base::gen_trezor_base(){ gen_trezor_base::gen_trezor_base(const gen_trezor_base &other): m_generator(other.m_generator), m_bt(other.m_bt), m_miner_account(other.m_miner_account), m_bob_account(other.m_bob_account), m_alice_account(other.m_alice_account), m_eve_account(other.m_eve_account), - m_hard_forks(other.m_hard_forks), m_trezor(other.m_trezor), m_rct_config(other.m_rct_config), + m_hard_forks(other.m_hard_forks), m_trezor(other.m_trezor), m_rct_config(other.m_rct_config), m_top_hard_fork(other.m_top_hard_fork), m_heavy_tests(other.m_heavy_tests), m_test_get_tx_key(other.m_test_get_tx_key), m_live_refresh_enabled(other.m_live_refresh_enabled), m_network_type(other.m_network_type), m_daemon(other.m_daemon) { @@ -625,6 +636,7 @@ void gen_trezor_base::fork(gen_trezor_base & other) other.m_events = m_events; other.m_head = m_head; other.m_hard_forks = m_hard_forks; + other.m_top_hard_fork = m_top_hard_fork; other.m_trezor_path = m_trezor_path; other.m_heavy_tests = m_heavy_tests; other.m_rct_config = m_rct_config; @@ -806,8 +818,6 @@ bool gen_trezor_base::generate(std::vector<test_event_entry>& events) // RCT transactions, wallets have to be used wallet_tools::process_transactions(m_wl_alice.get(), events, blk_5r, m_bt); wallet_tools::process_transactions(m_wl_bob.get(), events, blk_5r, m_bt); - MDEBUG("Available funds on Alice: " << get_available_funds(m_wl_alice.get())); - MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get())); // Send Alice -> Bob, manually constructed. Simple TX test, precondition. cryptonote::transaction tx_1; @@ -827,7 +837,12 @@ bool gen_trezor_base::generate(std::vector<test_event_entry>& events) CHECK_AND_ASSERT_THROW_MES(resx, "tx_1 semantics failed"); CHECK_AND_ASSERT_THROW_MES(resy, "tx_1 non-semantics failed"); - REWIND_BLOCKS_HF(events, blk_6r, blk_6, m_miner_account, CUR_HF); + REWIND_BLOCKS_N_HF(events, blk_6r, blk_6, m_miner_account, 10, CUR_HF); + wallet_tools::process_transactions(m_wl_alice.get(), events, blk_6, m_bt); + wallet_tools::process_transactions(m_wl_bob.get(), events, blk_6, m_bt); + MDEBUG("Available funds on Alice: " << get_available_funds(m_wl_alice.get())); + MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get())); + m_head = blk_6r; m_events = events; return true; @@ -889,15 +904,44 @@ void gen_trezor_base::load(std::vector<test_event_entry>& events) MDEBUG("Available funds on Bob: " << get_available_funds(m_wl_bob.get())); } +void gen_trezor_base::rewind_blocks(std::vector<test_event_entry>& events, size_t rewind_n, uint8_t hf) +{ + auto & generator = m_generator; // macro shortcut + REWIND_BLOCKS_N_HF(events, blk_new, m_head, m_miner_account, rewind_n, hf); + m_head = blk_new; + m_events = events; + MDEBUG("Blocks rewound: " << rewind_n << ", #blocks: " << num_blocks(events) << ", #events: " << events.size()); + + wallet_tools::process_transactions(m_wl_alice.get(), events, m_head, m_bt); + wallet_tools::process_transactions(m_wl_bob.get(), events, m_head, m_bt); +} + void gen_trezor_base::fix_hf(std::vector<test_event_entry>& events) { // If current test requires higher hard-fork, move it up const auto current_hf = m_hard_forks.back().first; - if (m_rct_config.bp_version == 2 && current_hf < 10){ + + if (current_hf > m_top_hard_fork) + { + throw std::runtime_error("Generated chain hardfork is higher than desired maximum"); + } + + if (m_rct_config.bp_version == 2 && m_top_hard_fork < 10) + { + throw std::runtime_error("Desired maximum is too low for BPv2"); + } + + if (current_hf < m_top_hard_fork) + { auto hardfork_height = num_blocks(events); - ADD_HARDFORK(m_hard_forks, 10, hardfork_height); + ADD_HARDFORK(m_hard_forks, m_top_hard_fork, hardfork_height); add_top_hfork(events, m_hard_forks); - MDEBUG("Hardfork height: " << hardfork_height); + MDEBUG("Hardfork added at height: " << hardfork_height << ", from " << (int)current_hf << " to " << (int)m_top_hard_fork); + + if (current_hf < 10) + { // buffer blocks, add 10 to apply v10 rules + rewind_blocks(events, 10, m_top_hard_fork); + } } } @@ -934,10 +978,9 @@ void gen_trezor_base::add_transactions_to_events( { // If current test requires higher hard-fork, move it up const auto current_hf = m_hard_forks.back().first; - const uint8_t tx_hf = m_rct_config.bp_version == 2 ? 10 : 9; - if (tx_hf > current_hf){ - throw std::runtime_error("Too late for HF change"); - } + const uint8_t tx_hf = m_top_hard_fork; + CHECK_AND_ASSERT_THROW_MES(tx_hf <= current_hf, "Too late for HF change: " << (int)tx_hf << " current: " << (int)current_hf); + CHECK_AND_ASSERT_THROW_MES(m_rct_config.bp_version < 2 || tx_hf >= 10, "HF too low for BPv2: " << (int)tx_hf); std::list<cryptonote::transaction> tx_list; for(const auto & tx : txs) @@ -1808,7 +1851,7 @@ bool wallet_api_tests::generate(std::vector<test_event_entry>& events) CHECK_AND_ASSERT_THROW_MES(w->init(daemon()->rpc_addr(), 0), "Wallet init fail"); CHECK_AND_ASSERT_THROW_MES(w->refresh(), "Refresh fail"); uint64_t balance = w->balance(0); - MINFO("Balance: " << balance); + MDEBUG("Balance: " << balance); CHECK_AND_ASSERT_THROW_MES(w->status() == Monero::PendingTransaction::Status_Ok, "Status nok"); auto addr = get_address(m_eve_account); diff --git a/tests/trezor/trezor_tests.h b/tests/trezor/trezor_tests.h index bed49fec4..46eb5e6a5 100644 --- a/tests/trezor/trezor_tests.h +++ b/tests/trezor/trezor_tests.h @@ -84,6 +84,8 @@ public: virtual void mine_and_test(std::vector<test_event_entry>& events); + virtual void rewind_blocks(std::vector<test_event_entry>& events, size_t rewind_n, uint8_t hf); + virtual void set_hard_fork(uint8_t hf); crypto::hash head_hash() const { return get_block_hash(m_head); } diff --git a/tests/unit_tests/blockchain_db.cpp b/tests/unit_tests/blockchain_db.cpp index 4fbc21ddc..f302d7946 100644 --- a/tests/unit_tests/blockchain_db.cpp +++ b/tests/unit_tests/blockchain_db.cpp @@ -271,6 +271,8 @@ TYPED_TEST(BlockchainDBTest, AddBlock) this->get_filenames(); this->init_hard_fork(); + db_wtxn_guard guard(this->m_db); + // adding a block with no parent in the blockchain should throw. // note: this shouldn't be possible, but is a good (and cheap) failsafe. // @@ -317,6 +319,8 @@ TYPED_TEST(BlockchainDBTest, RetrieveBlockData) this->get_filenames(); this->init_hard_fork(); + db_wtxn_guard guard(this->m_db); + ASSERT_NO_THROW(this->m_db->add_block(this->m_blocks[0], t_sizes[0], t_sizes[0], t_diffs[0], t_coins[0], this->m_txs[0])); ASSERT_EQ(t_sizes[0], this->m_db->get_block_weight(0)); |