def verify_asset_transaction(asset_transaction)
      raise ArgumentError, "Asset Transaction is missing" if !asset_transaction

      # Perform a depth-first scanning.
      # When completed, we'll only have transactions that have all previous txs fully verified.
      atx_stack = [ asset_transaction ]
      i = 0
      max_size = atx_stack.size
      while i < atx_stack.size # note: array dynamically changes as we scan it
        atx = atx_stack[i]
        BTC::Invariant(atx.is_a?(AssetTransaction), "Must be AssetTransaction instance")

        more_atxs_to_verify = partial_verify_asset_transaction(atx)
        if more_atxs_to_verify == nil # Validation failed - return immediately
          return false
        elsif more_atxs_to_verify.size == 0 # atx is fully verifiable (issue-only or we used cached parents), remove it from the list
          
          # outputs may not be all verified because they can be transfers with cached verified inputs.
          # so we need to verify local balance and apply asset ids from inputs to outputs
          if !verify_transfers(atx) 
            return false
          end

          if i == 0 # that was the topmost transaction, we are done.
            return true
          end

          @source.asset_transaction_was_verified(atx)
          atx_stack.delete_at(i)
          i -= 1
          # If this is was the last parent to check, then the previous item would be :parents marker
          # Once we validate the child behind that marker, we might have another child or the marker again.
          # Unroll the stack until the previous item is not a child with all parents verified.
          while (child_atx = atx_stack[i]) == :parents
            BTC::Invariant(i >= 1, ":parents marker should be preceded by an asset transaction")
            atx_stack.delete_at(i)
            i -= 1
            child_atx = atx_stack.delete_at(i)

            # Now all inputs are verified, we only need to verify the transfer outputs against them.
            # This will make outputs verified for the later transactions (earlier in the list).
            if !verify_transfers(child_atx)
              return false
            end

            # Now transaction is fully verified.
            # Source can cache it if needed.
            @source.asset_transaction_was_verified(child_atx)

            if i == 0 # this was the topmost child, return
              return true
            end
            i -= 1
          end
        else
          # we have more things to verify - dig inside these transactions
          # Start with the last one so once any tx is verifed, we can move back and color inputs of the child transaction.
          atx_stack.insert(i+1, :parents, *more_atxs_to_verify)
          max_size = atx_stack.size if atx_stack.size > max_size
          j = i
          i += more_atxs_to_verify.size + 1
        end
      end
      return true
    end
def verify_asset_transaction(asset_transaction)
      raise ArgumentError, "Asset Transaction is missing" if !asset_transaction

      # Perform a depth-first scanning.
      # When completed, we'll only have transactions that have all previous txs fully verified.
      atx_stack = [ asset_transaction ]
      i = 0
      max_size = atx_stack.size
      while i < atx_stack.size # note: array dynamically changes as we scan it
        atx = atx_stack[i]
        BTC::Invariant(atx.is_a?(AssetTransaction), "Must be AssetTransaction instance")

        more_atxs_to_verify = partial_verify_asset_transaction(atx)
        if more_atxs_to_verify == nil # Validation failed - return immediately
          return false
        elsif more_atxs_to_verify.size == 0 # atx is fully verifiable (issue-only or we used cached parents), remove it from the list
          
          # outputs may not be all verified because they can be transfers with cached verified inputs.
          # so we need to verify local balance and apply asset ids from inputs to outputs
          if !verify_transfers(atx) 
            return false
          end

          if i == 0 # that was the topmost transaction, we are done.
            return true
          end

          @source.asset_transaction_was_verified(atx)
          atx_stack.delete_at(i)
          i -= 1
          # If this is was the last parent to check, then the previous item would be :parents marker
          # Once we validate the child behind that marker, we might have another child or the marker again.
          # Unroll the stack until the previous item is not a child with all parents verified.
          while (child_atx = atx_stack[i]) == :parents
            BTC::Invariant(i >= 1, ":parents marker should be preceded by an asset transaction")
            atx_stack.delete_at(i)
            i -= 1
            child_atx = atx_stack.delete_at(i)

            # Now all inputs are verified, we only need to verify the transfer outputs against them.
            # This will make outputs verified for the later transactions (earlier in the list).
            if !verify_transfers(child_atx)
              return false
            end

            # Now transaction is fully verified.
            # Source can cache it if needed.
            @source.asset_transaction_was_verified(child_atx)

            if i == 0 # this was the topmost child, return
              return true
            end
            i -= 1
          end
        else
          # we have more things to verify - dig inside these transactions
          # Start with the last one so once any tx is verifed, we can move back and color inputs of the child transaction.
          atx_stack.insert(i+1, :parents, *more_atxs_to_verify)
          max_size = atx_stack.size if atx_stack.size > max_size
          j = i
          i += more_atxs_to_verify.size + 1
        end
      end
      return true
    end
Scans backwards and validates every AssetTransaction on the way.
 Does not verify Bitcoin transactions (assumes amounts and scripts are already validated).
 Updates verified flags on the asset transaction.
 Returns `true` if asset transaction is verified succesfully.
 Returns `false` otherwise.