/* * Copyright (c) 2015, Cryptonomex, Inc. * All rights reserved. * * This source code is provided for evaluation in private test networks only, until September 8, 2015. After this date, this license expires and * the code may not be used, modified or distributed for any purpose. Redistribution and use in source and binary forms, with or without modification, * are permitted until September 8, 2015, provided that the following conditions are met: * * 1. The code and/or derivative works are used only for private test networks consisting of no more than 10 P2P nodes. * * 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. */ #include #include #include #include #include #include #include #include #include #include "../common/database_fixture.hpp" using namespace graphene::chain; BOOST_AUTO_TEST_SUITE(block_tests) BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture ) { try { const asset_object& core = asset_id_type()(db); uint32_t skip_flags = database::skip_transaction_dupe_check | database::skip_witness_signature | database::skip_transaction_signatures | database::skip_authority_check ; // Sam is the creator of accounts private_key_type committee_key = init_account_priv_key; private_key_type sam_key = generate_private_key("sam"); // // A = old key set // B = new key set // // we measure how many times we test following four cases: // // A-B B-A // alice case_count[0] A == B empty empty // bob case_count[1] A < B empty nonempty // charlie case_count[2] B < A nonempty empty // dan case_count[3] A nc B nonempty nonempty // // and assert that all four cases were tested at least once // account_object sam_account_object = create_account( "sam", sam_key ); //Get a sane head block time generate_block( skip_flags ); db.modify(db.get_global_properties(), [](global_property_object& p) { p.parameters.committee_proposal_review_period = fc::hours(1).to_seconds(); }); transaction tx; processed_transaction ptx; account_object committee_account_object = committee_account(db); // transfer from committee account to Sam account transfer(committee_account_object, sam_account_object, core.amount(100000)); const int num_keys = 5; vector< private_key_type > numbered_private_keys; vector< vector< public_key_type > > numbered_key_id; numbered_private_keys.reserve( num_keys ); numbered_key_id.push_back( vector() ); numbered_key_id.push_back( vector() ); for( int i=0; i > possible_key_sched; const int num_key_sched = (1 << num_keys)-1; possible_key_sched.reserve( num_key_sched ); for( int s=1; s<=num_key_sched; s++ ) { vector< int > v; int i = 0; v.reserve( num_keys ); while( v.size() < num_keys ) { if( s & (1 << i) ) v.push_back( i ); i++; if( i >= num_keys ) i = 0; } possible_key_sched.push_back( v ); } // we can only undo in blocks generate_block( skip_flags ); std::cout << "update_account_keys: this test will take a few minutes...\n"; for( int use_addresses=0; use_addresses<2; use_addresses++ ) { vector< public_key_type > key_ids = numbered_key_id[ use_addresses ]; for( int num_owner_keys=1; num_owner_keys<=2; num_owner_keys++ ) { for( int num_active_keys=1; num_active_keys<=2; num_active_keys++ ) { std::cout << use_addresses << num_owner_keys << num_active_keys << "\n"; for( const vector< int >& key_sched_before : possible_key_sched ) { auto it = key_sched_before.begin(); vector< const private_key_type* > owner_privkey; vector< const public_key_type* > owner_keyid; owner_privkey.reserve( num_owner_keys ); trx.clear(); account_create_operation create_op; create_op.name = "alice"; for( int owner_index=0; owner_index(); generate_block( skip_flags ); for( const vector< int >& key_sched_after : possible_key_sched ) { auto it = key_sched_after.begin(); trx.clear(); account_update_operation update_op; update_op.account = alice_account_id; update_op.owner = authority(); update_op.active = authority(); update_op.new_options = create_op.options; for( int owner_index=0; owner_indexkey_auths[ key_ids[ *(it++) ] ] = 1; // size() < num_owner_keys is possible when some keys are duplicates update_op.owner->weight_threshold = update_op.owner->key_auths.size(); for( int active_index=0; active_indexkey_auths[ key_ids[ *(it++) ] ] = 1; // size() < num_active_keys is possible when some keys are duplicates update_op.active->weight_threshold = update_op.active->key_auths.size(); FC_ASSERT( update_op.new_options.valid() ); update_op.new_options->memo_key = key_ids[ *(it++) ] ; trx.operations.push_back( update_op ); for( int i=0; i> 1; vector< witness_id_type > cur_round; vector< witness_id_type > full_schedule; // if we make the maximum witness count testable, // we'll need to enlarge this. std::bitset< 0x40 > witness_seen; size_t total_blocks = 1000000; cur_round.reserve( num_witnesses ); full_schedule.reserve( total_blocks ); cur_round.push_back( db.get_dynamic_global_properties().current_witness ); // we assert so the test doesn't continue, which would // corrupt memory assert( num_witnesses <= witness_seen.size() ); while( full_schedule.size() < total_blocks ) { if( (db.head_block_num() & 0x3FFF) == 0 ) { wdump( (db.head_block_num()) ); } witness_id_type wid = db.get_scheduled_witness( 1 ); full_schedule.push_back( wid ); cur_round.push_back( wid ); if( cur_round.size() == num_witnesses ) { // check that the current round contains exactly 1 copy // of each witness witness_seen.reset(); for( const witness_id_type& w : cur_round ) { uint64_t inst = w.instance.value; BOOST_CHECK( !witness_seen.test( inst ) ); assert( !witness_seen.test( inst ) ); witness_seen.set( inst ); } cur_round.clear(); } generate_block(); } for( size_t i=0,m=full_schedule.size(); i> 1; witness_scheduler_rng rng( // - - - - + - - - - 1 - - - - + - - - - 2 - - - - + - - - "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" ); witness_scheduler scheduler; vector< witness_id_type > witness_ids; witness_ids.reserve( num_witnesses ); for( size_t i=0; i cur_round; vector< witness_id_type > full_schedule; // if we make the maximum witness count testable, // we'll need to enlarge this. std::bitset< 0x40 > witness_seen; size_t total_blocks = 1000000; cur_round.reserve( num_witnesses ); full_schedule.reserve( total_blocks ); // we assert so the test doesn't continue, which would // corrupt memory assert( num_witnesses <= witness_seen.size() ); while( full_schedule.size() < total_blocks ) { scheduler.produce_schedule( rng ); witness_id_type wid = scheduler.consume_schedule(); full_schedule.push_back( wid ); cur_round.push_back( wid ); if( cur_round.size() == num_witnesses ) { // check that the current round contains exactly 1 copy // of each witness witness_seen.reset(); for( const witness_id_type& w : cur_round ) { uint64_t inst = w.instance.value; BOOST_CHECK( !witness_seen.test( inst ) ); assert( !witness_seen.test( inst ) ); witness_seen.set( inst ); } cur_round.clear(); } } for( size_t i=0,m=full_schedule.size(); i