def verify_transfers(asset_transaction)
      # Do not verify colors on inputs if no transfers occur. 
      # Typically it's an issuance tx. If there are assets on inputs, they are destroyed.
      if asset_transaction.transfer_outputs.size == 0
        return true
      end

      color_transaction_inputs(asset_transaction)

      current_asset_id = nil

      inputs = asset_transaction.inputs.dup
      current_asset_id = nil
      current_input = nil
      current_input_remainder = 0

      asset_transaction.outputs.each do |aout|
        # Only check outputs that can be colored (value > 0) and are transfer outputs (after the marker)
        if aout.has_value? && !aout.marker? && !aout.issue?

          aout.asset_id = nil
          remaining_value = aout.value

          # Try to fill in the output with available inputs.
          while remaining_value > 0

            BTC::Invariant((current_input_remainder == 0) ? (current_input == nil) : true,
              "Remainder must be == 0 only when current_input is nil")

            BTC::Invariant((current_input_remainder > 0) ? (current_input && current_input.colored?) : true,
              "Remainder must be > 0 only when transfer input is colored")

            current_input ||= inputs.shift

            # skip uncolored inputs
            while current_input && !current_input.colored?
              current_input = inputs.shift
            end

            if !current_input
              Diagnostics.current.add_message("Failed to assign AssetID to transfer output #{aout.index}: not enough colored inputs (#{remaining_value} missing for output #{aout.index}).")
              return false
            end

            # Need to consume aout.value units from inputs and extract the asset ID
            if !current_input.verified?
              Diagnostics.current.add_message("Failed to assign AssetID to transfer output #{aout.index}: input #{current_input.index} is not verified.")
              return false
            end

            # Make sure asset ID matches.
            # If output gets assigned units from 2 or more inputs, all asset ids must be the same.
            if !aout.asset_id
              aout.asset_id = current_input.asset_id
            else
              if aout.asset_id != current_input.asset_id
                Diagnostics.current.add_message("Failed to assign AssetID to transfer output #{aout.index}: already assigned another AssetID.")
                return false
              end
            end

            # If we have remainder from the previous output, use it.
            # Otherwise use the whole input's value.
            qty = if current_input_remainder > 0
              current_input_remainder
            else
              current_input.value
            end

            if qty <= remaining_value
              remaining_value -= qty
              # choose next input, clear remainder.
              current_input_remainder = 0
              current_input = nil
            else
              current_input_remainder = qty - remaining_value
              remaining_value = 0
              # keep the current input to use with `current_input_remainder` in the next output
            end
          end # filling in the output

          aout.verified = true

          BTC::Invariant(aout.verified && aout.asset_id && aout.value > 0, "Transfer output should be fully verified")
        end # only transfer outputs with value > 0
      end # each output

      # Some inputs may have remained. If those have some assets, they'll be destroyed.
      if current_input_remainder > 0
        Diagnostics.current.add_message("Warning: #{current_input_remainder} units left over from input #{current_input.index} will be destroyed.")
      end

      while current_input = inputs.shift
        if current_input.colored?
          Diagnostics.current.add_message("Warning: #{current_input.value} units from input #{current_input.index} will be destroyed.")
        end
      end

      return true
    end
def verify_transfers(asset_transaction)
      # Do not verify colors on inputs if no transfers occur. 
      # Typically it's an issuance tx. If there are assets on inputs, they are destroyed.
      if asset_transaction.transfer_outputs.size == 0
        return true
      end

      color_transaction_inputs(asset_transaction)

      current_asset_id = nil

      inputs = asset_transaction.inputs.dup
      current_asset_id = nil
      current_input = nil
      current_input_remainder = 0

      asset_transaction.outputs.each do |aout|
        # Only check outputs that can be colored (value > 0) and are transfer outputs (after the marker)
        if aout.has_value? && !aout.marker? && !aout.issue?

          aout.asset_id = nil
          remaining_value = aout.value

          # Try to fill in the output with available inputs.
          while remaining_value > 0

            BTC::Invariant((current_input_remainder == 0) ? (current_input == nil) : true,
              "Remainder must be == 0 only when current_input is nil")

            BTC::Invariant((current_input_remainder > 0) ? (current_input && current_input.colored?) : true,
              "Remainder must be > 0 only when transfer input is colored")

            current_input ||= inputs.shift

            # skip uncolored inputs
            while current_input && !current_input.colored?
              current_input = inputs.shift
            end

            if !current_input
              Diagnostics.current.add_message("Failed to assign AssetID to transfer output #{aout.index}: not enough colored inputs (#{remaining_value} missing for output #{aout.index}).")
              return false
            end

            # Need to consume aout.value units from inputs and extract the asset ID
            if !current_input.verified?
              Diagnostics.current.add_message("Failed to assign AssetID to transfer output #{aout.index}: input #{current_input.index} is not verified.")
              return false
            end

            # Make sure asset ID matches.
            # If output gets assigned units from 2 or more inputs, all asset ids must be the same.
            if !aout.asset_id
              aout.asset_id = current_input.asset_id
            else
              if aout.asset_id != current_input.asset_id
                Diagnostics.current.add_message("Failed to assign AssetID to transfer output #{aout.index}: already assigned another AssetID.")
                return false
              end
            end

            # If we have remainder from the previous output, use it.
            # Otherwise use the whole input's value.
            qty = if current_input_remainder > 0
              current_input_remainder
            else
              current_input.value
            end

            if qty <= remaining_value
              remaining_value -= qty
              # choose next input, clear remainder.
              current_input_remainder = 0
              current_input = nil
            else
              current_input_remainder = qty - remaining_value
              remaining_value = 0
              # keep the current input to use with `current_input_remainder` in the next output
            end
          end # filling in the output

          aout.verified = true

          BTC::Invariant(aout.verified && aout.asset_id && aout.value > 0, "Transfer output should be fully verified")
        end # only transfer outputs with value > 0
      end # each output

      # Some inputs may have remained. If those have some assets, they'll be destroyed.
      if current_input_remainder > 0
        Diagnostics.current.add_message("Warning: #{current_input_remainder} units left over from input #{current_input.index} will be destroyed.")
      end

      while current_input = inputs.shift
        if current_input.colored?
          Diagnostics.current.add_message("Warning: #{current_input.value} units from input #{current_input.index} will be destroyed.")
        end
      end

      return true
    end
verify_issues
 Attempts to verify transfer transactions assuming all inputs are verified.
 Returns `true` if all transfers are verified (also updates `verified` and `asset_id` on them).
 Returns `false` if any transfer is invalid or some inputs are not verified.