void pending_chain_state::get_undo_state( const chain_interface_ptr& undo_state_arg )const
{
    auto undo_state = std::dynamic_pointer_cast<pending_chain_state>(undo_state_arg);
    chain_interface_ptr prev_state = _prev_state.lock();
    FC_ASSERT( prev_state );
    for( const auto& item : properties )
    {
        auto prev_value = prev_state->get_property( (chain_property_enum)item.first );
        undo_state->set_property( (chain_property_enum)item.first, prev_value );
    }
    for( const auto& item : assets )
    {
        auto prev_value = prev_state->get_asset_record( item.first );
        if( !!prev_value ) undo_state->store_asset_record( *prev_value );
        else undo_state->store_asset_record( item.second.make_null() );
    }
    for( const auto& item : slates )
    {
        auto prev_value = prev_state->get_delegate_slate( item.first );
        if( prev_value ) undo_state->store_delegate_slate( item.first, *prev_value );
        else undo_state->store_delegate_slate( item.first, delegate_slate() );
    }
    for( const auto& item : accounts )
    {
        auto prev_value = prev_state->get_account_record( item.first );
        if( !!prev_value ) undo_state->store_account_record( *prev_value );
        else undo_state->store_account_record( item.second.make_null() );
    }
    for( const auto& item : proposals )
    {
        auto prev_value = prev_state->get_proposal_record( item.first );
        if( !!prev_value ) undo_state->store_proposal_record( *prev_value );
        else undo_state->store_proposal_record( item.second.make_null() );
    }
    for( const auto& item : proposal_votes )
    {
        auto prev_value = prev_state->get_proposal_vote( item.first );
        if( !!prev_value ) undo_state->store_proposal_vote( *prev_value );
        else {
            undo_state->store_proposal_vote( item.second.make_null() );
        }
    }
    for( const auto& item : balances )
    {
        auto prev_value = prev_state->get_balance_record( item.first );
        if( !!prev_value ) undo_state->store_balance_record( *prev_value );
        else undo_state->store_balance_record( item.second.make_null() );
    }
    for( const auto& item : transactions )
    {
        auto prev_value = prev_state->get_transaction( item.first );
        if( !!prev_value ) undo_state->store_transaction( item.first, *prev_value );
        else undo_state->store_transaction( item.first, transaction_record() );
    }
    for( const auto& item : bids )
    {
        auto prev_value = prev_state->get_bid_record( item.first );
        if( prev_value.valid() ) undo_state->store_bid_record( item.first, *prev_value );
        else  undo_state->store_bid_record( item.first, order_record() );
    }
    for( const auto& item : asks )
    {
        auto prev_value = prev_state->get_ask_record( item.first );
        if( prev_value.valid() ) undo_state->store_ask_record( item.first, *prev_value );
        else  undo_state->store_ask_record( item.first, order_record() );
    }
    for( const auto& item : shorts )
    {
        auto prev_value = prev_state->get_short_record( item.first );
        if( prev_value.valid() ) undo_state->store_short_record( item.first, *prev_value );
        else  undo_state->store_short_record( item.first, order_record() );
    }
    for( const auto& item : collateral )
    {
        auto prev_value = prev_state->get_collateral_record( item.first );
        if( prev_value.valid() ) undo_state->store_collateral_record( item.first, *prev_value );
        else  undo_state->store_collateral_record( item.first, collateral_record() );
    }
    for( const auto& item : slots )
    {
        auto prev_value = prev_state->get_slot_record( item.first );
        if( prev_value ) undo_state->store_slot_record( *prev_value );
        else
        {
            slot_record invalid_slot_record;
            invalid_slot_record.start_time = item.first;
            invalid_slot_record.block_produced = true;
            invalid_slot_record.block_id = block_id_type();
            undo_state->store_slot_record( invalid_slot_record );
        }
    }
}
                  bool get_next_ask()
                  { try {
                     if( _current_ask && _current_ask->state.balance > 0 )
                     {
                        wlog( "current ask" );
                        return _current_ask.valid();
                     }
                     _current_ask.reset();

                     /**
                      *  Margin calls take priority over all other ask orders
                      */
                     while( _current_bid && _collateral_itr.valid() )
                     {
                        auto cover_ask = market_order( cover_order,
                                                 _collateral_itr.key(),
                                                 order_record(_collateral_itr.value().payoff_balance),
                                                 _collateral_itr.value().collateral_balance  );

                        if( cover_ask.get_price().quote_asset_id == _quote_id &&
                            cover_ask.get_price().base_asset_id == _base_id )
                        {
                            if( _current_bid->get_price() < cover_ask.get_highest_cover_price()  )
                            {
                               // cover position has been blown out, current bid is not able to
                               // cover the position, so it will sit until the price recovers
                               // enough to fill it.
                               //
                               // The idea here is that the longs have agreed to a maximum
                               // protection equal to the collateral.  If they would like to
                               // sell their USD for XTS this is the best price the short is
                               // obligated to offer.
                               FC_CAPTURE_AND_THROW( insufficient_collateral, (_current_bid)(cover_ask)(cover_ask.get_highest_cover_price()));
                               --_collateral_itr;
                               continue;
                            }
                            // max bid must be greater than call price
                            if( _current_bid->get_price() < cover_ask.get_price() )
                            {
                             //  if( _current_ask->get_price() > cover_ask.get_price() )
                               {
                                  _current_ask = cover_ask;
                                  _current_payoff_balance = _collateral_itr.value().payoff_balance;
                                  --_collateral_itr;
                                  return _current_ask.valid();
                               }
                            }
                        }
                        break;
                     }

                     if( _ask_itr.valid() )
                     {
                        auto ask = market_order( ask_order, _ask_itr.key(), _ask_itr.value() );
                        wlog( "ASK ITER VALID: ${o}", ("o",ask) );
                        if( ask.get_price().quote_asset_id == _quote_id &&
                            ask.get_price().base_asset_id == _base_id )
                        {
                            _current_ask = ask;
                        }
                        ++_ask_itr;
                        return true;
                     }
                     return _current_ask.valid();
                  } FC_CAPTURE_AND_RETHROW() }
   void  pending_chain_state::get_undo_state( const chain_interface_ptr& undo_state_arg )const
   {
      auto undo_state = std::dynamic_pointer_cast<pending_chain_state>(undo_state_arg);
      FC_ASSERT( _prev_state );
      for( auto item : properties )
      {
         auto previous_value = _prev_state->get_property( (chain_property_enum)item.first );
         undo_state->set_property( (chain_property_enum)item.first, previous_value );
      }

      for( auto record : assets )
      {
         auto prev_asset = _prev_state->get_asset_record( record.first );
         if( !!prev_asset ) undo_state->store_asset_record( *prev_asset );
         else undo_state->store_asset_record( record.second.make_null() );
      }

      for( auto record : names )
      {
         auto prev_name = _prev_state->get_name_record( record.first );
         if( !!prev_name ) undo_state->store_name_record( *prev_name );
         else undo_state->store_name_record( record.second.make_null() );
      }

      for( auto record : proposals )
      {
         auto prev_proposal = _prev_state->get_proposal_record( record.first );
         if( !!prev_proposal ) undo_state->store_proposal_record( *prev_proposal );
         else undo_state->store_proposal_record( record.second.make_null() );
      }
      for( auto record : proposal_votes )
      {
         auto prev_proposal_vote = _prev_state->get_proposal_vote( record.first );
         if( !!prev_proposal_vote ) undo_state->store_proposal_vote( *prev_proposal_vote );
         else { undo_state->store_proposal_vote( record.second.make_null() ); }
      }

      for( auto record : balances ) 
      {
         auto prev_address = _prev_state->get_balance_record( record.first );
         if( !!prev_address ) undo_state->store_balance_record( *prev_address );
         else undo_state->store_balance_record( record.second.make_null() );
      }
      for( auto record : bids )
      {
         auto prev_value = _prev_state->get_bid_record( record.first );
         if( prev_value.valid() ) undo_state->store_bid_record( record.first, *prev_value );
         else  undo_state->store_bid_record( record.first, order_record() );
      }
      for( auto record : asks )
      {
         auto prev_value = _prev_state->get_ask_record( record.first );
         if( prev_value.valid() ) undo_state->store_ask_record( record.first, *prev_value );
         else  undo_state->store_ask_record( record.first, order_record() );
      }
      for( auto record : shorts )
      {
         auto prev_value = _prev_state->get_short_record( record.first );
         if( prev_value.valid() ) undo_state->store_short_record( record.first, *prev_value );
         else  undo_state->store_short_record( record.first, order_record() );
      }
      for( auto record : collateral )
      {
         auto prev_value = _prev_state->get_collateral_record( record.first );
         if( prev_value.valid() ) undo_state->store_collateral_record( record.first, *prev_value );
         else  undo_state->store_collateral_record( record.first, collateral_record() );
      }
   }
   void pending_chain_state::get_undo_state( const chain_interface_ptr& undo_state_arg )const
   {
      auto undo_state = std::dynamic_pointer_cast<pending_chain_state>( undo_state_arg );
      chain_interface_ptr prev_state = _prev_state.lock();
      FC_ASSERT( prev_state );
      for( const auto& item : properties )
      {
         auto prev_value = prev_state->get_property( (chain_property_enum)item.first );
         undo_state->set_property( (chain_property_enum)item.first, prev_value );
      }
      for( const auto& item : assets )
      {
         auto prev_value = prev_state->get_asset_record( item.first );
         if( !!prev_value ) undo_state->store_asset_record( *prev_value );
         else undo_state->store_asset_record( item.second.make_null() );
      }
      for( const auto& item : slates )
      {
         auto prev_value = prev_state->get_delegate_slate( item.first );
         if( prev_value ) undo_state->store_delegate_slate( item.first, *prev_value );
         else undo_state->store_delegate_slate( item.first, delegate_slate() );
      }
      for( const auto& item : accounts )
      {
         auto prev_value = prev_state->get_account_record( item.first );
         if( !!prev_value ) undo_state->store_account_record( *prev_value );
         else undo_state->store_account_record( item.second.make_null() );
      }
#if 0
      for( const auto& item : proposals )
      {
         auto prev_value = prev_state->get_proposal_record( item.first );
         if( !!prev_value ) undo_state->store_proposal_record( *prev_value );
         else undo_state->store_proposal_record( item.second.make_null() );
      }
      for( const auto& item : proposal_votes )
      {
         auto prev_value = prev_state->get_proposal_vote( item.first );
         if( !!prev_value ) undo_state->store_proposal_vote( *prev_value );
         else { undo_state->store_proposal_vote( item.second.make_null() ); }
      }
#endif
      for( const auto& item : balances )
      {
         auto prev_value = prev_state->get_balance_record( item.first );
         if( !!prev_value ) undo_state->store_balance_record( *prev_value );
         else undo_state->store_balance_record( item.second.make_null() );
      }
      for( const auto& item : transactions )
      {
         auto prev_value = prev_state->get_transaction( item.first );
         if( !!prev_value ) undo_state->store_transaction( item.first, *prev_value );
         else undo_state->store_transaction( item.first, transaction_record() );
      }
      for( const auto& item : bids )
      {
         auto prev_value = prev_state->get_bid_record( item.first );
         if( prev_value.valid() ) undo_state->store_bid_record( item.first, *prev_value );
         else  undo_state->store_bid_record( item.first, order_record() );
      }
      for( const auto& item : asks )
      {
         auto prev_value = prev_state->get_ask_record( item.first );
         if( prev_value.valid() ) undo_state->store_ask_record( item.first, *prev_value );
         else  undo_state->store_ask_record( item.first, order_record() );
      }
      for( const auto& item : shorts )
      {
         auto prev_value = prev_state->get_short_record( item.first );
         if( prev_value.valid() ) undo_state->store_short_record( item.first, *prev_value );
         else  undo_state->store_short_record( item.first, order_record() );
      }
      for( const auto& item : collateral )
      {
         auto prev_value = prev_state->get_collateral_record( item.first );
         if( prev_value.valid() ) undo_state->store_collateral_record( item.first, *prev_value );
         else  undo_state->store_collateral_record( item.first, collateral_record() );
      }
      for( const auto& item : slots )
      {
         auto prev_value = prev_state->get_slot_record( item.first );
         if( prev_value ) undo_state->store_slot_record( *prev_value );
         else
         {
             slot_record invalid_slot_record;
             invalid_slot_record.start_time = item.first;
             invalid_slot_record.block_produced = true;
             invalid_slot_record.block_id = block_id_type();
             undo_state->store_slot_record( invalid_slot_record );
         }
      }
      for( const auto& item : market_statuses )
      {
         auto prev_value = prev_state->get_market_status( item.first.first, item.first.second );
         if( prev_value ) undo_state->store_market_status( *prev_value );
         else
         {
            undo_state->store_market_status( market_status() );
         }
      }
      for( const auto& item : feeds )
      {
         auto prev_value = prev_state->get_feed( item.first );
         if( prev_value ) undo_state->set_feed( *prev_value );
         else undo_state->set_feed( feed_record{item.first} );
      }
      for( const auto& item : burns )
      {
         undo_state->store_burn_record( burn_record( item.first ) );
      }

      const auto dirty_markets = prev_state->get_dirty_markets();
      undo_state->set_dirty_markets(dirty_markets);

      /* NOTE: Recent operations are currently not rewound on undo */
   }