diff options
Diffstat (limited to 'tests')
36 files changed, 954 insertions, 285 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/block_weight/block_weight.py b/tests/block_weight/block_weight.py index ba533c53c..b23da3d77 100755 --- a/tests/block_weight/block_weight.py +++ b/tests/block_weight/block_weight.py @@ -9,7 +9,6 @@ import math MEDIAN_WINDOW_SMALL = 100 # number of recent blocks for median computation MEDIAN_WINDOW_BIG = 5000 -MULTIPLIER_SMALL = 1.4 # multipliers for determining weights MULTIPLIER_BIG = 50.0 MEDIAN_THRESHOLD = 300*1000 # initial value for median (scaled kB -> B) lcg_seed = 0 @@ -24,9 +23,9 @@ def get_median(vec): #temp = vec temp = sorted(vec) if len(temp) % 2 == 1: - return temp[len(temp)/2] + return temp[len(temp)//2] else: - return int((temp[len(temp)/2]+temp[len(temp)/2-1])/2) + return int((temp[len(temp)//2]+temp[len(temp)//2-1])//2) def LCG(): global lcg_seed diff --git a/tests/core_tests/bulletproofs.h b/tests/core_tests/bulletproofs.h index efc751df7..83f160d71 100644 --- a/tests/core_tests/bulletproofs.h +++ b/tests/core_tests/bulletproofs.h @@ -49,7 +49,7 @@ struct gen_bp_tx_validation_base : public test_chain_unit_base return !tvc.m_verifivation_failed && tx_added; } - bool check_tx_verification_context(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t event_idx, const std::vector<cryptonote::transaction>& /*txs*/) + bool check_tx_verification_context_array(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t event_idx, const std::vector<cryptonote::transaction>& /*txs*/) { size_t failed = 0; for (const cryptonote::tx_verification_context &tvc: tvcs) @@ -97,7 +97,7 @@ template<> struct get_test_options<gen_bp_tx_validation_base> { const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(10, 73), std::make_pair(0, 0)}; const cryptonote::test_options test_options = { - hard_forks + hard_forks, 0 }; }; diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 09bc10ea8..614585349 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -1146,3 +1146,21 @@ bool test_chain_unit_base::verify(const std::string& cb_name, cryptonote::core& } return cb_it->second(c, ev_index, events); } + +bool test_chain_unit_base::check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t event_idx, const cryptonote::block& /*blk*/) +{ + return !bvc.m_verifivation_failed; +} + +bool test_chain_unit_base::check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool /*tx_added*/, size_t /*event_index*/, const cryptonote::transaction& /*tx*/) +{ + return !tvc.m_verifivation_failed; +} + +bool test_chain_unit_base::check_tx_verification_context_array(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t /*tx_added*/, size_t /*event_index*/, const std::vector<cryptonote::transaction>& /*txs*/) +{ + for (const cryptonote::tx_verification_context &tvc: tvcs) + if (tvc.m_verifivation_failed) + return false; + return true; +} diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h index f2bcb7787..c0d31bb8a 100644 --- a/tests/core_tests/chaingen.h +++ b/tests/core_tests/chaingen.h @@ -169,6 +169,10 @@ public: void register_callback(const std::string& cb_name, verify_callback cb); bool verify(const std::string& cb_name, cryptonote::core& c, size_t ev_index, const std::vector<test_event_entry> &events); + bool check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t event_idx, const cryptonote::block& /*blk*/); + bool check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool /*tx_added*/, size_t /*event_index*/, const cryptonote::transaction& /*tx*/); + bool check_tx_verification_context_array(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t /*tx_added*/, size_t /*event_index*/, const std::vector<cryptonote::transaction>& /*txs*/); + private: callbacks_map m_callbacks; }; @@ -487,77 +491,6 @@ uint64_t get_balance(const cryptonote::account_base& addr, const std::vector<cry bool extract_hard_forks(const std::vector<test_event_entry>& events, v_hardforks_t& hard_forks); -//-------------------------------------------------------------------------- -template<class t_test_class> -auto do_check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_index, const cryptonote::transaction& tx, t_test_class& validator, int) - -> decltype(validator.check_tx_verification_context(tvc, tx_added, event_index, tx)) -{ - return validator.check_tx_verification_context(tvc, tx_added, event_index, tx); -} -//-------------------------------------------------------------------------- -template<class t_test_class> -bool do_check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t /*event_index*/, const cryptonote::transaction& /*tx*/, t_test_class&, long) -{ - // Default block verification context check - if (tvc.m_verifivation_failed) - throw std::runtime_error("Transaction verification failed"); - return true; -} -//-------------------------------------------------------------------------- -template<class t_test_class> -bool check_tx_verification_context(const cryptonote::tx_verification_context& tvc, bool tx_added, size_t event_index, const cryptonote::transaction& tx, t_test_class& validator) -{ - // SFINAE in action - return do_check_tx_verification_context(tvc, tx_added, event_index, tx, validator, 0); -} -//-------------------------------------------------------------------------- -template<class t_test_class> -auto do_check_tx_verification_context(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t event_index, const std::vector<cryptonote::transaction>& txs, t_test_class& validator, int) - -> decltype(validator.check_tx_verification_context(tvcs, tx_added, event_index, txs)) -{ - return validator.check_tx_verification_context(tvcs, tx_added, event_index, txs); -} -//-------------------------------------------------------------------------- -template<class t_test_class> -bool do_check_tx_verification_context(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t /*event_index*/, const std::vector<cryptonote::transaction>& /*txs*/, t_test_class&, long) -{ - // Default block verification context check - for (const cryptonote::tx_verification_context &tvc: tvcs) - if (tvc.m_verifivation_failed) - throw std::runtime_error("Transaction verification failed"); - return true; -} -//-------------------------------------------------------------------------- -template<class t_test_class> -bool check_tx_verification_context(const std::vector<cryptonote::tx_verification_context>& tvcs, size_t tx_added, size_t event_index, const std::vector<cryptonote::transaction>& txs, t_test_class& validator) -{ - // SFINAE in action - return do_check_tx_verification_context(tvcs, tx_added, event_index, txs, validator, 0); -} -//-------------------------------------------------------------------------- -template<class t_test_class> -auto do_check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t event_index, const cryptonote::block& blk, t_test_class& validator, int) - -> decltype(validator.check_block_verification_context(bvc, event_index, blk)) -{ - return validator.check_block_verification_context(bvc, event_index, blk); -} -//-------------------------------------------------------------------------- -template<class t_test_class> -bool do_check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t /*event_index*/, const cryptonote::block& /*blk*/, t_test_class&, long) -{ - // Default block verification context check - if (bvc.m_verifivation_failed) - throw std::runtime_error("Block verification failed"); - return true; -} -//-------------------------------------------------------------------------- -template<class t_test_class> -bool check_block_verification_context(const cryptonote::block_verification_context& bvc, size_t event_index, const cryptonote::block& blk, t_test_class& validator) -{ - // SFINAE in action - return do_check_block_verification_context(bvc, event_index, blk, validator, 0); -} - /************************************************************************/ /* */ /************************************************************************/ @@ -613,7 +546,7 @@ public: size_t pool_size = m_c.get_pool_transactions_count(); m_c.handle_incoming_tx(t_serializable_object_to_blob(tx), tvc, m_txs_keeped_by_block, false, false); bool tx_added = pool_size + 1 == m_c.get_pool_transactions_count(); - bool r = check_tx_verification_context(tvc, tx_added, m_ev_index, tx, m_validator); + bool r = m_validator.check_tx_verification_context(tvc, tx_added, m_ev_index, tx); CHECK_AND_NO_ASSERT_MES(r, false, "tx verification context check failed"); return true; } @@ -633,7 +566,7 @@ public: size_t pool_size = m_c.get_pool_transactions_count(); m_c.handle_incoming_txs(tx_blobs, tvcs, m_txs_keeped_by_block, false, false); size_t tx_added = m_c.get_pool_transactions_count() - pool_size; - bool r = check_tx_verification_context(tvcs, tx_added, m_ev_index, txs, m_validator); + bool r = m_validator.check_tx_verification_context_array(tvcs, tx_added, m_ev_index, txs); CHECK_AND_NO_ASSERT_MES(r, false, "tx verification context check failed"); return true; } @@ -643,8 +576,16 @@ 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); - bool r = check_block_verification_context(bvc, m_ev_index, b, m_validator); + 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 = m_validator.check_block_verification_context(bvc, m_ev_index, b); CHECK_AND_NO_ASSERT_MES(r, false, "block verification context check failed"); return r; } @@ -666,7 +607,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; @@ -677,7 +625,7 @@ public: { blk = cryptonote::block(); } - bool r = check_block_verification_context(bvc, m_ev_index, blk, m_validator); + bool r = m_validator.check_block_verification_context(bvc, m_ev_index, blk); CHECK_AND_NO_ASSERT_MES(r, false, "block verification context check failed"); return true; } @@ -701,7 +649,7 @@ public: tx = cryptonote::transaction(); } - bool r = check_tx_verification_context(tvc, tx_added, m_ev_index, tx, m_validator); + bool r = m_validator.check_tx_verification_context(tvc, tx_added, m_ev_index, tx); CHECK_AND_NO_ASSERT_MES(r, false, "transaction verification context check failed"); return true; } @@ -748,7 +696,7 @@ template<typename t_test_class> struct get_test_options { const std::pair<uint8_t, uint64_t> hard_forks[2]; const cryptonote::test_options test_options = { - hard_forks + hard_forks, 0 }; get_test_options():hard_forks{std::make_pair((uint8_t)1, (uint64_t)0), std::make_pair((uint8_t)0, (uint64_t)0)}{} }; @@ -776,7 +724,7 @@ inline bool do_replay_events_get_core(std::vector<test_event_entry>& events, cry // Hardforks can be specified in events. v_hardforks_t hardforks; - cryptonote::test_options test_options_tmp{}; + cryptonote::test_options test_options_tmp{nullptr, 0}; const cryptonote::test_options * test_options_ = >o.test_options; if (extract_hard_forks(events, hardforks)){ hardforks.push_back(std::make_pair((uint8_t)0, (uint64_t)0)); // terminator diff --git a/tests/core_tests/multisig.h b/tests/core_tests/multisig.h index 1e8226d26..10fe6ffe8 100644 --- a/tests/core_tests/multisig.h +++ b/tests/core_tests/multisig.h @@ -84,7 +84,7 @@ template<> struct get_test_options<gen_multisig_tx_validation_base> { const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(4, 1), std::make_pair(0, 0)}; const cryptonote::test_options test_options = { - hard_forks + hard_forks, 0 }; }; diff --git a/tests/core_tests/rct.h b/tests/core_tests/rct.h index 72460d98e..00a2bd88c 100644 --- a/tests/core_tests/rct.h +++ b/tests/core_tests/rct.h @@ -83,7 +83,7 @@ template<> struct get_test_options<gen_rct_tx_validation_base> { const std::pair<uint8_t, uint64_t> hard_forks[4] = {std::make_pair(1, 0), std::make_pair(2, 1), std::make_pair(4, 65), std::make_pair(0, 0)}; const cryptonote::test_options test_options = { - hard_forks + hard_forks, 0 }; }; 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/CMakeLists.txt b/tests/functional_tests/CMakeLists.txt index 60060f56f..fd49ba623 100644 --- a/tests/functional_tests/CMakeLists.txt +++ b/tests/functional_tests/CMakeLists.txt @@ -50,6 +50,12 @@ target_link_libraries(functional_tests ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBRARIES}) -add_test( - NAME functional_tests_rpc - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/functional_tests_rpc.py" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" all) +execute_process(COMMAND ${PYTHON_EXECUTABLE} "-c" "import requests; print('OK')" OUTPUT_VARIABLE REQUESTS_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) +if (REQUESTS_OUTPUT STREQUAL "OK") + add_test( + NAME functional_tests_rpc + COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/functional_tests_rpc.py" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" all) +else() + message(WARNING "functional_tests_rpc skipped, needs the 'requests' python module") + set(CTEST_CUSTOM_TESTS_IGNORE ${CTEST_CUSTOM_TESTS_IGNORE} functional_tests_rpc) +endif() 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..6376b86d0 100755 --- a/tests/functional_tests/blockchain.py +++ b/tests/functional_tests/blockchain.py @@ -45,7 +45,15 @@ from framework.daemon import Daemon class BlockchainTest(): def run_test(self): + self.reset() self._test_generateblocks(5) + self._test_alt_chains() + + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() def _test_generateblocks(self, blocks): assert blocks >= 2 @@ -60,8 +68,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 +98,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 +130,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 +160,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..59a879e0a 100755 --- a/tests/functional_tests/cold_signing.py +++ b/tests/functional_tests/cold_signing.py @@ -38,10 +38,17 @@ from framework.wallet import Wallet class ColdSigningTest(): def run_test(self): + self.reset() self.create(0) self.mine() self.transfer() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self, idx): print 'Creating hot and cold wallet' @@ -89,6 +96,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 +117,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..e754b4e33 100755 --- a/tests/functional_tests/functional_tests_rpc.py +++ b/tests/functional_tests/functional_tests_rpc.py @@ -98,6 +98,7 @@ FAIL = [] for test in tests: try: print('[TEST STARTED] ' + test) + sys.stdout.flush() cmd = [python, srcdir + '/' + test + ".py"] subprocess.check_call(cmd) PASS.append(test) @@ -133,3 +134,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/mining.py b/tests/functional_tests/mining.py index 1b189beb2..78dc68640 100755 --- a/tests/functional_tests/mining.py +++ b/tests/functional_tests/mining.py @@ -43,9 +43,16 @@ from framework.wallet import Wallet class MiningTest(): def run_test(self): + self.reset() self.create() self.mine() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self): print 'Creating wallet' wallet = Wallet() diff --git a/tests/functional_tests/multisig.py b/tests/functional_tests/multisig.py index a0e8551cd..476e3a02d 100755 --- a/tests/functional_tests/multisig.py +++ b/tests/functional_tests/multisig.py @@ -38,6 +38,7 @@ from framework.wallet import Wallet class MultisigTest(): def run_test(self): + self.reset() self.mine('493DsrfJPqiN3Suv9RcRDoZEbQtKZX1sNcGPA3GhkKYEEmivk8kjQrTdRdVc4ZbmzWJuE157z9NNUKmF2VDfdYDR3CziGMk', 5) self.mine('42jSRGmmKN96V2j3B8X2DbiNThBXW1tSi1rW1uwkqbyURenq3eC3yosNm8HEMdHuWwKMFGzMUB3RCTvcTaW9kHpdRPP7p5y', 5) self.mine('47fF32AdrmXG84FcPY697uZdd42pMMGiH5UpiTRTt3YX2pZC7t7wkzEMStEicxbQGRfrYvAAYxH6Fe8rnD56EaNwUgxRd53', 5) @@ -68,6 +69,12 @@ class MultisigTest(): self.import_multisig_info([0, 1, 2, 3], 6) self.check_transaction(txid) + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def mine(self, address, blocks): print("Mining some blocks") daemon = Daemon() @@ -129,6 +136,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 +189,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/proofs.py b/tests/functional_tests/proofs.py index 0a0b6304d..844131095 100755 --- a/tests/functional_tests/proofs.py +++ b/tests/functional_tests/proofs.py @@ -38,6 +38,7 @@ from framework.wallet import Wallet class ProofsTest(): def run_test(self): + self.reset() self.mine('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) self.create_wallets() txid, tx_key, amount = self.transfer() @@ -45,6 +46,12 @@ class ProofsTest(): self.check_tx_proof(txid, amount) self.check_reserve_proof() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def mine(self, address, blocks): print("Mining some blocks") daemon = Daemon() diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py index b7a85f1d6..1ff641d1f 100755 --- a/tests/functional_tests/transfer.py +++ b/tests/functional_tests/transfer.py @@ -29,6 +29,7 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import time +import json """Test simple transfers """ @@ -38,10 +39,19 @@ from framework.wallet import Wallet class TransferTest(): def run_test(self): + self.reset() self.create() self.mine() self.transfer() self.check_get_bulk_payments() + self.check_double_spend_detection() + self.sweep_single() + + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() def create(self): print 'Creating wallets' @@ -62,9 +72,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 +184,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 +519,113 @@ 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 + + def sweep_single(self): + daemon = Daemon() + + print("Sending single output") + + daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) + self.wallet[0].refresh() + res = self.wallet[0].incoming_transfers(transfer_type = 'available') + for t in res.transfers: + assert not t.spent + assert len(res.transfers) > 8 # we mined a lot + index = 8 + assert not res.transfers[index].spent + assert res.transfers[index].amount > 0 + ki = res.transfers[index].key_image + amount = res.transfers[index].amount + daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 10) # ensure unlocked + self.wallet[0].refresh() + res = self.wallet[0].get_balance() + balance = res.balance + res = self.wallet[0].incoming_transfers(transfer_type = 'all') + res = self.wallet[0].sweep_single('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', key_image = ki) + assert len(res.tx_hash) == 64 + tx_hash = res.tx_hash + daemon.generateblocks('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 1) + self.wallet[0].refresh() + res = self.wallet[0].get_balance() + new_balance = res.balance + res = daemon.get_transactions([tx_hash], decode_as_json = True) + assert len(res.txs) == 1 + tx = res.txs[0] + assert tx.tx_hash == tx_hash + assert not tx.in_pool + assert len(tx.as_json) > 0 + try: + j = json.loads(tx.as_json) + except: + j = None + assert j + assert new_balance == balance - amount + assert len(j['vin']) == 1 + assert j['vin'][0]['key']['k_image'] == ki + self.wallet[0].refresh() + res = self.wallet[0].incoming_transfers(transfer_type = 'available') + assert len([t for t in res.transfers if t.key_image == ki]) == 0 + res = self.wallet[0].incoming_transfers(transfer_type = 'unavailable') + assert len([t for t in res.transfers if t.key_image == ki]) == 1 + + if __name__ == '__main__': TransferTest().run_test() diff --git a/tests/functional_tests/txpool.py b/tests/functional_tests/txpool.py index 71109c9e5..d74395f10 100755 --- a/tests/functional_tests/txpool.py +++ b/tests/functional_tests/txpool.py @@ -38,10 +38,17 @@ from framework.wallet import Wallet class TransferTest(): def run_test(self): + self.reset() self.create() self.mine() self.check_txpool() + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() + def create(self): print 'Creating wallet' wallet = Wallet() diff --git a/tests/functional_tests/wallet_address.py b/tests/functional_tests/wallet_address.py index 66a1633ca..8a55521c6 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 # @@ -38,13 +39,23 @@ Test the following RPCs: """ from framework.wallet import Wallet +from framework.daemon import Daemon class WalletAddressTest(): def run_test(self): + self.reset() self.create() self.check_main_address() self.check_keys() self.create_subaddresses() + self.open_close() + self.languages() + + def reset(self): + print 'Resetting blockchain' + daemon = Daemon() + daemon.pop_blocks(1000) + daemon.flush_txpool() def create(self): print 'Creating wallet' @@ -148,5 +159,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 8d5540328..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); @@ -293,7 +304,7 @@ static bool init_core_replay_events(std::vector<test_event_entry>& events, crypt // Hardforks can be specified in events. v_hardforks_t hardforks; - cryptonote::test_options test_options_tmp{}; + cryptonote::test_options test_options_tmp{nullptr, 0}; const cryptonote::test_options * test_options_ = >o.test_options; if (extract_hard_forks(events, hardforks)){ hardforks.push_back(std::make_pair((uint8_t)0, (uint64_t)0)); // terminator @@ -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/ban.cpp b/tests/unit_tests/ban.cpp index eb1ee8932..0b267172f 100644 --- a/tests/unit_tests/ban.cpp +++ b/tests/unit_tests/ban.cpp @@ -192,5 +192,21 @@ TEST(ban, add) ASSERT_TRUE(t >= 4); } +TEST(ban, limit) +{ + test_core pr_core; + cryptonote::t_cryptonote_protocol_handler<test_core> cprotocol(pr_core, NULL); + Server server(cprotocol); + cprotocol.set_p2p_endpoint(&server); + + // starts empty + ASSERT_TRUE(server.get_blocked_hosts().empty()); + ASSERT_FALSE(is_blocked(server,MAKE_IPV4_ADDRESS(1,2,3,4))); + ASSERT_TRUE(server.block_host(MAKE_IPV4_ADDRESS(1,2,3,4), std::numeric_limits<time_t>::max() - 1)); + ASSERT_TRUE(is_blocked(server,MAKE_IPV4_ADDRESS(1,2,3,4))); + ASSERT_TRUE(server.block_host(MAKE_IPV4_ADDRESS(1,2,3,4), 1)); + ASSERT_TRUE(is_blocked(server,MAKE_IPV4_ADDRESS(1,2,3,4))); +} + namespace nodetool { template class node_server<cryptonote::t_cryptonote_protocol_handler<test_core>>; } namespace cryptonote { template class t_cryptonote_protocol_handler<test_core>; } 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)); diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp index bb26b5533..1d1e8e9c0 100644 --- a/tests/unit_tests/hardfork.cpp +++ b/tests/unit_tests/hardfork.cpp @@ -46,7 +46,7 @@ namespace class TestDB: public cryptonote::BaseTestDB { public: - virtual uint64_t height() const { return blocks.size(); } + virtual uint64_t height() const override { return blocks.size(); } virtual void add_block( const block& blk , size_t block_weight , uint64_t long_term_block_weight @@ -54,19 +54,19 @@ public: , const uint64_t& coins_generated , uint64_t num_rct_outs , const crypto::hash& blk_hash - ) { + ) override { blocks.push_back(blk); } - virtual void remove_block() { blocks.pop_back(); } - virtual block get_block_from_height(const uint64_t& height) const { + virtual void remove_block() override { blocks.pop_back(); } + virtual block get_block_from_height(const uint64_t& height) const override { return blocks.at(height); } - virtual void set_hard_fork_version(uint64_t height, uint8_t version) { + virtual void set_hard_fork_version(uint64_t height, uint8_t version) override { if (versions.size() <= height) versions.resize(height+1); versions[height] = version; } - virtual uint8_t get_hard_fork_version(uint64_t height) const { + virtual uint8_t get_hard_fork_version(uint64_t height) const override { return versions.at(height); } diff --git a/tests/unit_tests/logging.cpp b/tests/unit_tests/logging.cpp index 12d49e2fb..056eae604 100644 --- a/tests/unit_tests/logging.cpp +++ b/tests/unit_tests/logging.cpp @@ -44,7 +44,10 @@ static void init() static void cleanup() { + // windows does not let files be deleted if still in use, so leave droppings there +#ifndef _WIN32 boost::filesystem::remove(log_filename); +#endif } static size_t nlines(const std::string &str) diff --git a/tests/unit_tests/long_term_block_weight.cpp b/tests/unit_tests/long_term_block_weight.cpp index bf1368618..b7713c63a 100644 --- a/tests/unit_tests/long_term_block_weight.cpp +++ b/tests/unit_tests/long_term_block_weight.cpp @@ -198,9 +198,10 @@ TEST(long_term_block_weight, multi_pop) const uint64_t effective_median = bc->get_current_cumulative_block_weight_median(); const uint64_t effective_limit = bc->get_current_cumulative_block_weight_limit(); - for (uint64_t h = 0; h < 4; ++h) + const uint64_t num_pop = 4; + for (uint64_t h = 0; h < num_pop; ++h) { - size_t w = h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit(); + size_t w = bc->get_current_cumulative_block_weight_limit(); uint64_t ltw = bc->get_next_long_term_block_weight(w); bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}); ASSERT_TRUE(bc->update_next_cumulative_weight_limit()); @@ -208,10 +209,8 @@ TEST(long_term_block_weight, multi_pop) cryptonote::block b; std::vector<cryptonote::transaction> txs; - bc->get_db().pop_block(b, txs); - bc->get_db().pop_block(b, txs); - bc->get_db().pop_block(b, txs); - bc->get_db().pop_block(b, txs); + for (uint64_t h = 0; h < num_pop; ++h) + bc->get_db().pop_block(b, txs); ASSERT_TRUE(bc->update_next_cumulative_weight_limit()); ASSERT_EQ(effective_median, bc->get_current_cumulative_block_weight_median()); @@ -294,9 +293,11 @@ TEST(long_term_block_weight, pop_invariant_random) { PREFIX(10); - for (uint64_t h = 1; h < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW - 10; ++h) + for (uint64_t h = 1; h < 2 * TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW - 10; ++h) { - size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : bc->get_current_cumulative_block_weight_limit(); + lcg_seed = bc->get_db().height(); + uint32_t r = lcg(); + size_t w = bc->get_db().height() < TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V5 : (r % bc->get_current_cumulative_block_weight_limit()); uint64_t ltw = bc->get_next_long_term_block_weight(w); bc->get_db().add_block(std::make_pair(cryptonote::block(), ""), w, ltw, h, h, {}); ASSERT_TRUE(bc->update_next_cumulative_weight_limit()); diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp index 77fb71d96..326e63db8 100644 --- a/tests/unit_tests/net.cpp +++ b/tests/unit_tests/net.cpp @@ -546,7 +546,7 @@ namespace connected(false) { acceptor.open(boost::asio::ip::tcp::v4()); - acceptor.bind(stream_type::endpoint{boost::asio::ip::tcp::v4(), 0}); + acceptor.bind(stream_type::endpoint{boost::asio::ip::address_v4::loopback(), 0}); acceptor.listen(); acceptor.async_accept(server, [this] (boost::system::error_code error) { this->connected = true; @@ -621,7 +621,8 @@ TEST(socks_client, connect_command) ASSERT_TRUE(test_client->set_connect_command("example.com", 8080)); EXPECT_FALSE(test_client->buffer().empty()); ASSERT_TRUE(net::socks::client::connect_and_send(std::move(test_client), io.acceptor.local_endpoint())); - while (!io.connected); + while (!io.connected) + ASSERT_FALSE(called); const std::uint8_t expected_bytes[] = { 4, 1, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, @@ -657,7 +658,8 @@ TEST(socks_client, connect_command_failed) ); EXPECT_FALSE(test_client->buffer().empty()); ASSERT_TRUE(net::socks::client::connect_and_send(std::move(test_client), io.acceptor.local_endpoint())); - while (!io.connected); + while (!io.connected) + ASSERT_FALSE(called); const std::uint8_t expected_bytes[] = { 4, 1, 0x0b, 0xb8, 0x00, 0x00, 0x13, 0x88, 0x00 @@ -713,7 +715,8 @@ TEST(socks_client, resolve_command) ASSERT_TRUE(test_client->set_resolve_command("example.com")); EXPECT_FALSE(test_client->buffer().empty()); ASSERT_TRUE(net::socks::client::connect_and_send(test_client, io.acceptor.local_endpoint())); - while (!io.connected); + while (!io.connected) + ASSERT_EQ(0u, test_client->called_); const std::uint8_t expected_bytes[] = { 4, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, @@ -753,7 +756,8 @@ TEST(socks_connector, host) boost::unique_future<boost::asio::ip::tcp::socket> sock = net::socks::connector{io.acceptor.local_endpoint()}("example.com", "8080", timeout); - while (!io.connected); + while (!io.connected) + ASSERT_FALSE(sock.is_ready()); const std::uint8_t expected_bytes[] = { 4, 1, 0x1f, 0x90, 0x00, 0x00, 0x00, 0x01, 0x00, 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', 0x00 @@ -779,7 +783,8 @@ TEST(socks_connector, ipv4) boost::unique_future<boost::asio::ip::tcp::socket> sock = net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout); - while (!io.connected); + while (!io.connected) + ASSERT_FALSE(sock.is_ready()); const std::uint8_t expected_bytes[] = { 4, 1, 0x1f, 0x90, 0xfa, 0x58, 0x7d, 0x63, 0x00 }; @@ -804,7 +809,8 @@ TEST(socks_connector, error) boost::unique_future<boost::asio::ip::tcp::socket> sock = net::socks::connector{io.acceptor.local_endpoint()}("250.88.125.99", "8080", timeout); - while (!io.connected); + while (!io.connected) + ASSERT_FALSE(sock.is_ready()); const std::uint8_t expected_bytes[] = { 4, 1, 0x1f, 0x90, 0xfa, 0x58, 0x7d, 0x63, 0x00 }; diff --git a/tests/unit_tests/output_distribution.cpp b/tests/unit_tests/output_distribution.cpp index 45f2c135b..2f3c78642 100644 --- a/tests/unit_tests/output_distribution.cpp +++ b/tests/unit_tests/output_distribution.cpp @@ -62,6 +62,13 @@ public: return d; } + std::vector<uint64_t> get_block_weights(uint64_t start_offset, size_t count) const override + { + std::vector<uint64_t> weights; + while (count--) weights.push_back(1); + return weights; + } + uint64_t blockchain_height; }; diff --git a/tests/unit_tests/output_selection.cpp b/tests/unit_tests/output_selection.cpp index a528679e4..0094fc765 100644 --- a/tests/unit_tests/output_selection.cpp +++ b/tests/unit_tests/output_selection.cpp @@ -101,3 +101,120 @@ TEST(select_outputs, order) PICK(1); // then the one that's on the same height } +#define MKOFFSETS(N, n) \ + offsets.resize(N); \ + size_t n_outs = 0; \ + for (auto &offset: offsets) \ + { \ + offset = n_outs += (n); \ + } + +TEST(select_outputs, gamma) +{ + std::vector<uint64_t> offsets; + + MKOFFSETS(300000, 1); + tools::gamma_picker picker(offsets); + std::vector<double> ages(100000); + double age_scale = 120. * (offsets.size() / (double)n_outs); + for (size_t i = 0; i < ages.size(); ) + { + uint64_t o = picker.pick(); + if (o >= n_outs) + continue; + ages[i] = (n_outs - 1 - o) * age_scale; + ASSERT_GE(ages[i], 0); + ASSERT_LE(ages[i], offsets.size() * 120); + ++i; + } + double median = epee::misc_utils::median(ages); + MDEBUG("median age: " << median / 86400. << " days"); + ASSERT_GE(median, 1.3 * 86400); + ASSERT_LE(median, 1.4 * 86400); +} + +TEST(select_outputs, density) +{ + static const size_t NPICKS = 1000000; + std::vector<uint64_t> offsets; + + MKOFFSETS(300000, 1 + (rand() & 0x1f)); + tools::gamma_picker picker(offsets); + + std::vector<int> picks(/*n_outs*/offsets.size(), 0); + for (int i = 0; i < NPICKS; ) + { + uint64_t o = picker.pick(); + if (o >= n_outs) + continue; + auto it = std::lower_bound(offsets.begin(), offsets.end(), o); + auto idx = std::distance(offsets.begin(), it); + ASSERT_LT(idx, picks.size()); + ++picks[idx]; + ++i; + } + + for (int d = 1; d < 0x20; ++d) + { + // count the number of times an output in a block of d outputs was selected + // count how many outputs are in a block of d outputs + size_t count_selected = 0, count_chain = 0; + for (size_t i = 0; i < offsets.size(); ++i) + { + size_t n_outputs = offsets[i] - (i == 0 ? 0 : offsets[i - 1]); + if (n_outputs == d) + { + count_selected += picks[i]; + count_chain += d; + } + } + float selected_ratio = count_selected / (float)NPICKS; + float chain_ratio = count_chain / (float)n_outs; + MDEBUG(count_selected << "/" << NPICKS << " outputs selected in blocks of density " << d << ", " << 100.0f * selected_ratio << "%"); + MDEBUG(count_chain << "/" << offsets.size() << " outputs in blocks of density " << d << ", " << 100.0f * chain_ratio << "%"); + ASSERT_LT(fabsf(selected_ratio - chain_ratio), 0.02f); + } +} + +TEST(select_outputs, same_distribution) +{ + static const size_t NPICKS = 1000000; + std::vector<uint64_t> offsets; + + MKOFFSETS(300000, 1 + (rand() & 0x1f)); + tools::gamma_picker picker(offsets); + + std::vector<int> chain_picks(offsets.size(), 0); + std::vector<int> output_picks(n_outs, 0); + for (int i = 0; i < NPICKS; ) + { + uint64_t o = picker.pick(); + if (o >= n_outs) + continue; + auto it = std::lower_bound(offsets.begin(), offsets.end(), o); + auto idx = std::distance(offsets.begin(), it); + ASSERT_LT(idx, chain_picks.size()); + ++chain_picks[idx]; + ++output_picks[o]; + ++i; + } + + // scale them both to 0-100 + std::vector<int> chain_norm(100, 0), output_norm(100, 0); + for (size_t i = 0; i < output_picks.size(); ++i) + output_norm[i * 100 / output_picks.size()] += output_picks[i]; + for (size_t i = 0; i < chain_picks.size(); ++i) + chain_norm[i * 100 / chain_picks.size()] += chain_picks[i]; + + double max_dev = 0.0, avg_dev = 0.0; + for (size_t i = 0; i < 100; ++i) + { + const double diff = (double)output_norm[i] - (double)chain_norm[i]; + double dev = fabs(2.0 * diff / (output_norm[i] + chain_norm[i])); + ASSERT_LT(dev, 0.1); + avg_dev += dev; + } + avg_dev /= 100; + MDEBUG("avg_dev: " << avg_dev); + ASSERT_LT(avg_dev, 0.015); +} diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index e239154cf..4d51ec434 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -143,13 +143,16 @@ TEST(ringct, range_proofs) //ct range proofs ctkeyV sc, pc; ctkey sctmp, pctmp; - //add fake input 5000 - tie(sctmp, pctmp) = ctskpkGen(6000); + std::vector<uint64_t> inamounts; + //add fake input 6000 + inamounts.push_back(6000); + tie(sctmp, pctmp) = ctskpkGen(inamounts.back()); sc.push_back(sctmp); pc.push_back(pctmp); - tie(sctmp, pctmp) = ctskpkGen(7000); + inamounts.push_back(7000); + tie(sctmp, pctmp) = ctskpkGen(inamounts.back()); sc.push_back(sctmp); pc.push_back(pctmp); vector<xmr_amount >amounts; @@ -173,14 +176,20 @@ TEST(ringct, range_proofs) const rct::RCTConfig rct_config { RangeProofBorromean, 0 }; - //compute rct data with mixin 500 - rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); + //compute rct data with mixin 3 - should fail since full type with > 1 input + bool ok = false; + try { genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); } + catch(...) { ok = true; } + ASSERT_TRUE(ok); + + //compute rct data with mixin 3 + rctSig s = genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default")); //verify rct data - ASSERT_TRUE(verRct(s)); + ASSERT_TRUE(verRctSimple(s)); //decode received amount - decodeRct(s, amount_keys[1], 1, mask, hw::get_device("default")); + decodeRctSimple(s, amount_keys[1], 1, mask, hw::get_device("default")); // Ring CT with failing MG sig part should not verify! // Since sum of inputs != outputs @@ -190,14 +199,14 @@ TEST(ringct, range_proofs) destinations[1] = Pk; - //compute rct data with mixin 500 - s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); + //compute rct data with mixin 3 + s = genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default")); //verify rct data - ASSERT_FALSE(verRct(s)); + ASSERT_FALSE(verRctSimple(s)); //decode received amount - decodeRct(s, amount_keys[1], 1, mask, hw::get_device("default")); + decodeRctSimple(s, amount_keys[1], 1, mask, hw::get_device("default")); } TEST(ringct, range_proofs_with_fee) @@ -206,13 +215,16 @@ TEST(ringct, range_proofs_with_fee) //ct range proofs ctkeyV sc, pc; ctkey sctmp, pctmp; - //add fake input 5000 - tie(sctmp, pctmp) = ctskpkGen(6001); + std::vector<uint64_t> inamounts; + //add fake input 6001 + inamounts.push_back(6001); + tie(sctmp, pctmp) = ctskpkGen(inamounts.back()); sc.push_back(sctmp); pc.push_back(pctmp); - tie(sctmp, pctmp) = ctskpkGen(7000); + inamounts.push_back(7000); + tie(sctmp, pctmp) = ctskpkGen(inamounts.back()); sc.push_back(sctmp); pc.push_back(pctmp); vector<xmr_amount >amounts; @@ -227,10 +239,6 @@ TEST(ringct, range_proofs_with_fee) skpkGen(Sk, Pk); destinations.push_back(Pk); - //add txn fee for 1 - //has no corresponding destination.. - amounts.push_back(1); - //add output for 12500 amounts.push_back(12500); amount_keys.push_back(hash_to_scalar(zero())); @@ -239,14 +247,14 @@ TEST(ringct, range_proofs_with_fee) const rct::RCTConfig rct_config { RangeProofBorromean, 0 }; - //compute rct data with mixin 500 - rctSig s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); + //compute rct data with mixin 3 + rctSig s = genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 1, 3, rct_config, hw::get_device("default")); //verify rct data - ASSERT_TRUE(verRct(s)); + ASSERT_TRUE(verRctSimple(s)); //decode received amount - decodeRct(s, amount_keys[1], 1, mask, hw::get_device("default")); + decodeRctSimple(s, amount_keys[1], 1, mask, hw::get_device("default")); // Ring CT with failing MG sig part should not verify! // Since sum of inputs != outputs @@ -256,14 +264,14 @@ TEST(ringct, range_proofs_with_fee) destinations[1] = Pk; - //compute rct data with mixin 500 - s = genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); + //compute rct data with mixin 3 + s = genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 500, 3, rct_config, hw::get_device("default")); //verify rct data - ASSERT_FALSE(verRct(s)); + ASSERT_FALSE(verRctSimple(s)); //decode received amount - decodeRct(s, amount_keys[1], 1, mask, hw::get_device("default")); + decodeRctSimple(s, amount_keys[1], 1, mask, hw::get_device("default")); } TEST(ringct, simple) @@ -538,10 +546,10 @@ TEST(ringct, range_proofs_accept_zero_out_middle_simple) EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true)); } -TEST(ringct, range_proofs_accept_zero_in_first) +TEST(ringct, range_proofs_accept_zero) { - const uint64_t inputs[] = {0, 5000}; - const uint64_t outputs[] = {5000}; + const uint64_t inputs[] = {0}; + const uint64_t outputs[] = {0}; EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false)); } @@ -552,13 +560,6 @@ TEST(ringct, range_proofs_accept_zero_in_first_simple) EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true)); } -TEST(ringct, range_proofs_accept_zero_in_last) -{ - const uint64_t inputs[] = {5000, 0}; - const uint64_t outputs[] = {5000}; - EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false)); -} - TEST(ringct, range_proofs_accept_zero_in_last_simple) { const uint64_t inputs[] = {5000, 0}; @@ -566,13 +567,6 @@ TEST(ringct, range_proofs_accept_zero_in_last_simple) EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true)); } -TEST(ringct, range_proofs_accept_zero_in_middle) -{ - const uint64_t inputs[] = {2500, 0, 2500}; - const uint64_t outputs[] = {5000}; - EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false)); -} - TEST(ringct, range_proofs_accept_zero_in_middle_simple) { const uint64_t inputs[] = {2500, 0, 2500}; @@ -762,13 +756,6 @@ TEST(ringct, range_proofs_accept_1_to_N_simple) EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false,true)); } -TEST(ringct, range_proofs_accept_N_to_1) -{ - const uint64_t inputs[] = {1000, 1000, 1000, 1000, 1000}; - const uint64_t outputs[] = {5000}; - EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false)); -} - TEST(ringct, range_proofs_accept_N_to_1_simple) { const uint64_t inputs[] = {1000, 1000, 1000, 1000, 1000}; @@ -776,13 +763,6 @@ TEST(ringct, range_proofs_accept_N_to_1_simple) EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true)); } -TEST(ringct, range_proofs_accept_N_to_N) -{ - const uint64_t inputs[] = {1000, 1000, 1000, 1000, 1000}; - const uint64_t outputs[] = {1000, 1000, 1000, 1000, 1000}; - EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false)); -} - TEST(ringct, range_proofs_accept_N_to_N_simple) { const uint64_t inputs[] = {1000, 1000, 1000, 1000, 1000}; @@ -790,20 +770,6 @@ TEST(ringct, range_proofs_accept_N_to_N_simple) EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, true)); } -TEST(ringct, range_proofs_accept_very_long) -{ - const size_t N=12; - uint64_t inputs[N]; - uint64_t outputs[N]; - for (size_t n = 0; n < N; ++n) { - inputs[n] = n; - outputs[n] = n; - } - std::random_shuffle(inputs, inputs + N); - std::random_shuffle(outputs, outputs + N); - EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, false, false)); -} - TEST(ringct, range_proofs_accept_very_long_simple) { const size_t N=12; @@ -861,7 +827,7 @@ TEST(ringct, prooveRange_is_non_deterministic) TEST(ringct, fee_0_valid) { - const uint64_t inputs[] = {1000, 1000}; + const uint64_t inputs[] = {2000}; const uint64_t outputs[] = {2000, 0}; EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false)); } @@ -875,7 +841,7 @@ TEST(ringct, fee_0_valid_simple) TEST(ringct, fee_non_0_valid) { - const uint64_t inputs[] = {1000, 1000}; + const uint64_t inputs[] = {2000}; const uint64_t outputs[] = {1900, 100}; EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false)); } @@ -917,7 +883,7 @@ TEST(ringct, fee_non_0_invalid_lower_simple) TEST(ringct, fee_burn_valid_one_out) { - const uint64_t inputs[] = {1000, 1000}; + const uint64_t inputs[] = {2000}; const uint64_t outputs[] = {0, 2000}; EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false)); } @@ -931,7 +897,7 @@ TEST(ringct, fee_burn_valid_one_out_simple) TEST(ringct, fee_burn_valid_zero_out) { - const uint64_t inputs[] = {1000, 1000}; + const uint64_t inputs[] = {2000}; const uint64_t outputs[] = {2000}; EXPECT_TRUE(range_proof_test(true, NELTS(inputs), inputs, NELTS(outputs), outputs, true, false)); } @@ -945,7 +911,7 @@ TEST(ringct, fee_burn_valid_zero_out_simple) static rctSig make_sig() { - static const uint64_t inputs[] = {1000, 1000}; + static const uint64_t inputs[] = {2000}; static const uint64_t outputs[] = {1000, 1000}; static rct::rctSig sig = make_sample_rct_sig(NELTS(inputs), inputs, NELTS(outputs), outputs, true); return sig; @@ -1044,7 +1010,7 @@ TEST(ringct, reject_gen_simple_ver_non_simple) TEST(ringct, reject_gen_non_simple_ver_simple) { - const uint64_t inputs[] = {1000, 1000}; + const uint64_t inputs[] = {2000}; const uint64_t outputs[] = {1000, 1000}; rct::rctSig sig = make_sample_rct_sig(NELTS(inputs), inputs, NELTS(outputs), outputs, true); ASSERT_FALSE(rct::verRctSimple(sig)); diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index 27b14ffff..23f028464 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -477,7 +477,7 @@ TEST(Serialization, serializes_ringct_types) rct::ecdhTuple ecdh0, ecdh1; rct::boroSig boro0, boro1; rct::mgSig mg0, mg1; - rct::rangeSig rg0, rg1; + rct::Bulletproof bp0, bp1; rct::rctSig s0, s1; cryptonote::transaction tx0, tx1; @@ -566,12 +566,15 @@ TEST(Serialization, serializes_ringct_types) ASSERT_TRUE(!memcmp(&boro0, &boro1, sizeof(boro0))); // create a full rct signature to use its innards + vector<uint64_t> inamounts; rct::ctkeyV sc, pc; rct::ctkey sctmp, pctmp; - tie(sctmp, pctmp) = rct::ctskpkGen(6000); + inamounts.push_back(6000); + tie(sctmp, pctmp) = rct::ctskpkGen(inamounts.back()); sc.push_back(sctmp); pc.push_back(pctmp); - tie(sctmp, pctmp) = rct::ctskpkGen(7000); + inamounts.push_back(7000); + tie(sctmp, pctmp) = rct::ctskpkGen(inamounts.back()); sc.push_back(sctmp); pc.push_back(pctmp); vector<uint64_t> amounts; @@ -588,9 +591,9 @@ TEST(Serialization, serializes_ringct_types) amount_keys.push_back(rct::hash_to_scalar(rct::zero())); rct::skpkGen(Sk, Pk); destinations.push_back(Pk); - //compute rct data with mixin 500 + //compute rct data with mixin 3 const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 0 }; - s0 = rct::genRct(rct::zero(), sc, pc, destinations, amounts, amount_keys, NULL, NULL, 3, rct_config, hw::get_device("default")); + s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default")); mg0 = s0.p.MGs[0]; ASSERT_TRUE(serialization::dump_binary(mg0, blob)); @@ -605,66 +608,12 @@ TEST(Serialization, serializes_ringct_types) // mixRing and II are not serialized, they are meant to be reconstructed ASSERT_TRUE(mg1.II.empty()); - rg0 = s0.p.rangeSigs.front(); - ASSERT_TRUE(serialization::dump_binary(rg0, blob)); - ASSERT_TRUE(serialization::parse_binary(blob, rg1)); - ASSERT_TRUE(!memcmp(&rg0, &rg1, sizeof(rg0))); - -#if 0 - ASSERT_TRUE(serialization::dump_binary(s0, blob)); - ASSERT_TRUE(serialization::parse_binary(blob, s1)); - ASSERT_TRUE(s0.type == s1.type); - ASSERT_TRUE(s0.p.rangeSigs.size() == s1.p.rangeSigs.size()); - for (size_t n = 0; n < s0.p.rangeSigs.size(); ++n) - { - ASSERT_TRUE(!memcmp(&s0.p.rangeSigs[n], &s1.p.rangeSigs[n], sizeof(s0.p.rangeSigs[n]))); - } - ASSERT_TRUE(s0.p.MGs.size() == s1.p.MGs.size()); - ASSERT_TRUE(s0.p.MGs[0].ss.size() == s1.p.MGs[0].ss.size()); - for (size_t n = 0; n < s0.p.MGs[0].ss.size(); ++n) - { - ASSERT_TRUE(s0.p.MGs[0].ss[n] == s1.p.MGs[0].ss[n]); - } - ASSERT_TRUE(s0.p.MGs[0].cc == s1.p.MGs[0].cc); - // mixRing and II are not serialized, they are meant to be reconstructed - ASSERT_TRUE(s1.p.MGs[0].II.empty()); - - // mixRing and II are not serialized, they are meant to be reconstructed - ASSERT_TRUE(s1.mixRing.size() == 0); - - ASSERT_TRUE(s0.ecdhInfo.size() == s1.ecdhInfo.size()); - for (size_t n = 0; n < s0.ecdhInfo.size(); ++n) - { - ASSERT_TRUE(!memcmp(&s0.ecdhInfo[n], &s1.ecdhInfo[n], sizeof(s0.ecdhInfo[n]))); - } - ASSERT_TRUE(s0.outPk.size() == s1.outPk.size()); - for (size_t n = 0; n < s0.outPk.size(); ++n) - { - // serialization only does the mask - ASSERT_TRUE(!memcmp(&s0.outPk[n].mask, &s1.outPk[n].mask, sizeof(s0.outPk[n].mask))); - } -#endif - - tx0.set_null(); - tx0.version = 2; - cryptonote::txin_to_key txin_to_key1{}; - txin_to_key1.amount = 100; - txin_to_key1.key_offsets.resize(4); - cryptonote::txin_to_key txin_to_key2{}; - txin_to_key2.amount = 200; - txin_to_key2.key_offsets.resize(4); - tx0.vin.push_back(txin_to_key1); - tx0.vin.push_back(txin_to_key2); - tx0.vout.push_back(cryptonote::tx_out()); - tx0.vout.push_back(cryptonote::tx_out()); - tx0.rct_signatures = s0; - ASSERT_EQ(tx0.rct_signatures.p.rangeSigs.size(), 2); - ASSERT_TRUE(serialization::dump_binary(tx0, blob)); - ASSERT_TRUE(serialization::parse_binary(blob, tx1)); - ASSERT_EQ(tx1.rct_signatures.p.rangeSigs.size(), 2); - std::string blob2; - ASSERT_TRUE(serialization::dump_binary(tx1, blob2)); - ASSERT_TRUE(blob == blob2); + ASSERT_FALSE(s0.p.bulletproofs.empty()); + bp0 = s0.p.bulletproofs.front(); + ASSERT_TRUE(serialization::dump_binary(bp0, blob)); + ASSERT_TRUE(serialization::parse_binary(blob, bp1)); + bp1.V = bp0.V; // this is not saved, as it is reconstructed from other tx data + ASSERT_EQ(bp0, bp1); } TEST(Serialization, portability_wallet) |