/** 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
Example #2
0
            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 );
            }
Example #3
0
   /**
    *  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