/* * Copyright (c) 2015 Cryptonomex, Inc., and contributors. * * The MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #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