/** the genesis block requires some special treatment and initialization */ void store_genesis( const trx_block& b, const signed_transactions& deterministic_trxs, const block_evaluation_state_ptr& state ) { std::vector<uint160> trxs_ids; std::map<int32_t,uint64_t> delegate_votes; for( uint32_t i = 1; i <= 100; ++i ) { delegate_votes[i] = 0; } for( uint32_t cur_trx = 0 ; cur_trx < b.trxs.size(); ++cur_trx ) { store( b.trxs[cur_trx], trx_num( b.block_num, cur_trx) ); trxs_ids.push_back( b.trxs[cur_trx].id() ); if( cur_trx == 0 ) { for( uint32_t o = 0; o < b.trxs[cur_trx].outputs.size(); ++o ) { if( b.trxs[cur_trx].outputs[o].claim_func == claim_name ) { auto claim = b.trxs[cur_trx].outputs[o].as<claim_name_output>(); update_name_record( claim.name, claim ); // if( claim.delegate_id != 0 ) update_delegate( name_record( claim ) ); } } } else // t != 0 { name_record rec = _delegate_records.fetch( b.trxs[cur_trx].vote ); // first transaction registers names... the rest are initial balance for( uint32_t o = 0; o < b.trxs[cur_trx].outputs.size(); ++o ) { delegate_votes[b.trxs[cur_trx].vote] += b.trxs[cur_trx].outputs[o].amount.get_rounded_amount(); rec.votes_for += to_bips( b.trxs[cur_trx].outputs[o].amount.get_rounded_amount(), b.total_shares ); } update_delegate( rec ); } } elog( "total votes:\n ${e}", ("e",fc::json::to_pretty_string( delegate_votes) ) ); uint64_t sum = 0; for( auto i : delegate_votes ) { sum += i.second; } elog( "grand total: ${g}", ("g",sum) ); head_block = b; head_block_id = b.id(); blocks.store( b.block_num, b ); block_trxs.store( b.block_num, trxs_ids ); blk_id2num.store( b.id(), b.block_num ); } // store_genesis
void store( const trx_block& b ) { std::vector<uint160> trxs_ids; for( uint16_t t = 0; t < b.trxs.size(); ++t ) { store( b.trxs[t], trx_num( b.block_num, t) ); trxs_ids.push_back( b.trxs[t].id() ); } head_block = b; head_block_id = b.id(); blocks.store( b.block_num, b ); block_trxs.store( b.block_num, trxs_ids ); }
/** * Scan the blockchain starting from_block_num until the head block, check every * transaction for inputs or outputs accessable by this wallet. */ void wallet::scan_chain( blockchain_db& chain, uint32_t from_block_num ) { try { auto head_block_num = chain.head_block_num(); // for each block for( uint32_t i = from_block_num; i <= head_block_num; ++i ) { ilog( "block: ${i}", ("i",i ) ); auto blk = chain.fetch_full_block( i ); // for each transaction for( uint32_t trx_idx = 0; trx_idx < blk.trx_ids.size(); ++trx_idx ) { ilog( "trx: ${trx_idx}", ("trx_idx",trx_idx ) ); auto trx = chain.fetch_trx( trx_num( i, trx_idx ) ); //blk.trx_ids[trx_idx] ); ilog( "${id} \n\n ${trx}\n\n", ("id",trx.id())("trx",trx) ); // for each output for( uint32_t out_idx = 0; out_idx < trx.outputs.size(); ++out_idx ) { const trx_output& out = trx.outputs[out_idx]; auto out_ref = output_reference( trx.id(),out_idx ); switch( out.claim_func ) { case claim_by_signature: { auto owner = out.as<claim_by_signature_output>().owner; auto aitr = my->_my_addresses.find(owner); if( aitr != my->_my_addresses.end() ) { if( !trx.meta_outputs[out_idx].is_spent() ) my->_unspent_outputs[output_reference( trx.id(), out_idx )] = trx.outputs[out_idx]; else { mark_as_spent( output_reference(trx.id(), out_idx ) ); my->_spent_outputs[output_reference( trx.id(), out_idx )] = trx.outputs[out_idx]; } std::cerr<<"found block["<<i<<"].trx["<<trx_idx<<"].output["<<out_idx<<"] " << std::string(trx.id()) <<" => "<<std::string(owner)<<"\n"; } else { std::cerr<<"skip block["<<i<<"].trx["<<trx_idx<<"].output["<<out_idx<<"] => "<<std::string(owner)<<"\n"; } break; } case claim_by_bid: { auto bid = out.as<claim_by_bid_output>(); auto aitr = my->_my_addresses.find(bid.pay_address); if( aitr != my->_my_addresses.end() ) { if( !trx.meta_outputs[out_idx].is_spent() ) { my->_data.open_bids[out_ref] = trx.outputs[out_idx]; } else { my->_data.open_bids.erase(out_ref); my->_data.closed_bids[out_ref] = trx.outputs[out_idx]; } } else { // skip, it doesn't belong to me } break; } case claim_by_long: { auto short_sell = out.as<claim_by_long_output>(); auto aitr = my->_my_addresses.find(short_sell.pay_address); if( aitr != my->_my_addresses.end() ) { if( !trx.meta_outputs[out_idx].is_spent() ) { my->_data.open_short_sells[out_ref] = trx.outputs[out_idx]; } else { my->_data.open_short_sells.erase(out_ref); my->_data.closed_short_sells[out_ref] = trx.outputs[out_idx]; } } else { // skip, it doesn't belong to me } break; } case claim_by_cover: { auto cover = out.as<claim_by_cover_output>(); auto aitr = my->_my_addresses.find(cover.owner); if( aitr != my->_my_addresses.end() ) { if( !trx.meta_outputs[out_idx].is_spent() ) { my->_data.open_shorts[out_ref] = trx.outputs[out_idx]; } else { my->_data.open_shorts.erase(out_ref); my->_data.covered_shorts[out_ref] = trx.outputs[out_idx]; } } else { // skip, it doesn't belong to me } break; } } } } } } FC_RETHROW_EXCEPTIONS( warn, "" ) }
void store( const trx_block& b, const signed_transactions& deterministic_trxs, const block_evaluation_state_ptr& state ) { try { if( b.block_num == 0 ) { store_genesis( b, deterministic_trxs, state ); return; } std::vector<uint160> trxs_ids; // store individual transactions for( uint32_t cur_trx = 0; cur_trx < b.trxs.size(); ++cur_trx ) { store( b.trxs[cur_trx], trx_num( b.block_num, cur_trx) ); trxs_ids.push_back( b.trxs[cur_trx].id() ); } // store deterministic transactions for( const signed_transaction& trx : deterministic_trxs ) { store( trx, trx_num( b.block_num, trxs_ids.size() ) ); // TODO: why don't we include this here... do determinsitic trxs not // get included in the merkel root... does this hinder light weight // clients. // trxs_ids.push_back( trx.id() ); } head_block = b; head_block_id = b.id(); blocks.store( b.block_num, b ); block_trxs.store( b.block_num, trxs_ids ); blk_id2num.store( b.id(), b.block_num ); // update name name records... for( auto item : state->_name_outputs ) { update_name_record( item.first, item.second ); } // update votes for( auto item : state->_input_votes ) { auto rec = _delegate_records.fetch( abs(item.first) ); if( item.first < 0 ) rec.votes_against -= to_bips(item.second,b.total_shares); else rec.votes_for -= to_bips(item.second,b.total_shares); update_delegate( rec ); } for( auto item : state->_output_votes ) { auto rec = _delegate_records.fetch( abs(item.first) ); if( item.first < 0 ) rec.votes_against += to_bips( item.second, b.total_shares ); else rec.votes_for += to_bips( item.second, b.total_shares ); update_delegate( rec ); } } FC_RETHROW_EXCEPTIONS( warn, "" ) }
void store( const trx_block& b, const signed_transactions& deterministic_trxs, const block_evaluation_state_ptr& state ) { try { std::vector<uint160> trxs_ids; uint16_t t = 0; std::map<int32_t,uint64_t> delegate_votes; for( uint32_t i = 1; i <= 100; ++i ) { delegate_votes[i] = 0; } for( ; t < b.trxs.size(); ++t ) { store( b.trxs[t], trx_num( b.block_num, t) ); trxs_ids.push_back( b.trxs[t].id() ); /*** on the genesis block we need to store initial delegates and vote counts */ if( b.block_num == 0 ) { if( t == 0 ) { for( uint32_t o = 0; o < b.trxs[t].outputs.size(); ++o ) { if( b.trxs[t].outputs[o].claim_func == claim_name ) { auto claim = b.trxs[t].outputs[o].as<claim_name_output>(); update_name_record( claim.name, claim ); // if( claim.delegate_id != 0 ) update_delegate( name_record( claim ) ); } } } else // t != 0 { name_record rec = _delegate_records.fetch( b.trxs[t].vote ); // first transaction registers names... the rest are initial balance for( uint32_t o = 0; o < b.trxs[t].outputs.size(); ++o ) { delegate_votes[b.trxs[t].vote] += b.trxs[t].outputs[o].amount.get_rounded_amount(); rec.votes_for += to_bips( b.trxs[t].outputs[o].amount.get_rounded_amount(), b.total_shares ); } update_delegate( rec ); } } // block == 0 } elog( "total votes:\n ${e}", ("e",fc::json::to_pretty_string( delegate_votes) ) ); uint64_t sum = 0; for( auto i : delegate_votes ) { sum += i.second; } elog( "grand total: ${g}", ("g",sum) ); for( const signed_transaction& trx : deterministic_trxs ) { store( trx, trx_num( b.block_num, t) ); ++t; // trxs_ids.push_back( trx.id() ); } head_block = b; head_block_id = b.id(); blocks.store( b.block_num, b ); block_trxs.store( b.block_num, trxs_ids ); blk_id2num.store( b.id(), b.block_num ); for( auto item : state->_name_outputs ) { update_name_record( item.first, item.second ); } for( auto item : state->_input_votes ) { auto rec = _delegate_records.fetch( abs(item.first) ); if( item.first < 0 ) rec.votes_against -= to_bips(item.second,b.total_shares); else rec.votes_for -= to_bips(item.second,b.total_shares); update_delegate( rec ); } for( auto item : state->_output_votes ) { auto rec = _delegate_records.fetch( abs(item.first) ); if( item.first < 0 ) rec.votes_against += to_bips( item.second, b.total_shares ); else rec.votes_for += to_bips( item.second, b.total_shares ); update_delegate( rec ); } } FC_RETHROW_EXCEPTIONS( warn, "" ) }
/** the genesis block requires some special treatment and initialization */ void store_genesis( const trx_block& b, const signed_transactions& deterministic_trxs, const block_evaluation_state_ptr& state ) { try { std::vector<uint160> trxs_ids; std::map<int32_t,uint64_t> delegate_votes; for( uint32_t i = 1; i <= 100; ++i ) { delegate_votes[i] = 0; } for( uint32_t cur_trx = 0 ; cur_trx < b.trxs.size(); ++cur_trx ) { store( b.trxs[cur_trx], trx_num( b.block_num, cur_trx) ); trxs_ids.push_back( b.trxs[cur_trx].id() ); if( cur_trx == 0 ) { for( uint32_t o = 0; o < b.trxs[cur_trx].outputs.size(); ++o ) { if( b.trxs[cur_trx].outputs[o].claim_func == claim_name ) { auto claim = b.trxs[cur_trx].outputs[o].as<claim_name_output>(); update_name_record( claim.name, claim ); // if( claim.delegate_id != 0 ) update_delegate( name_record( claim ) ); } } } else // cur_trx != 0 { ilog( " processing transaction ${o}", ("o",cur_trx) ); name_record rec = _delegate_records.fetch( b.trxs[cur_trx].vote ); // first transaction registers names... the rest are initial balance for( uint32_t o = 0; o < b.trxs[cur_trx].outputs.size(); ++o ) { ilog( " processing output ${o} ${data}", ("o",o)("data",b.trxs[cur_trx].outputs[o]) ); FC_ASSERT( delegate_votes.find( b.trxs[cur_trx].vote ) != delegate_votes.end() ); delegate_votes[b.trxs[cur_trx].vote] += b.trxs[cur_trx].outputs[o].amount.get_rounded_amount(); ilog( "total_shares: ${total}", ("total",b.total_shares) ); rec.votes_for += to_bips( b.trxs[cur_trx].outputs[o].amount.get_rounded_amount(), b.total_shares ); ilog( "votes for: ${v}", ("v",rec.votes_for) ); ilog( "rec: ${rc}", ("rc",rec) ); } ilog( "updating delegate..." ); update_delegate( rec ); } } elog( "total votes:\n ${e}", ("e",fc::json::to_pretty_string( delegate_votes) ) ); uint64_t sum = 0; for( auto i : delegate_votes ) { sum += i.second; } elog( "grand total: ${g}", ("g",sum) ); head_block = b; head_block_id = b.id(); blocks.store( b.block_num, b ); block_trxs.store( b.block_num, trxs_ids ); blk_id2num.store( b.id(), b.block_num ); } FC_RETHROW_EXCEPTIONS( warn, "error storing genesis block " ) } // store_genesis