def verify_script(script_sig, script_pubkey, witness = ScriptWitness.new)

      return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?

      stack_copy = nil
      had_witness = false

      return false unless eval_script(script_sig, :base)

      stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)

      return false unless eval_script(script_pubkey, :base)

      return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last.htb)

      # Bare witness programs
      if flag?(SCRIPT_VERIFY_WITNESS) && script_pubkey.witness_program?
        had_witness = true
        return set_error(SCRIPT_ERR_WITNESS_MALLEATED) unless script_sig.size == 0
        version, program = script_pubkey.witness_data
        stack_copy = stack.dup
        return false unless verify_witness_program(witness, version, program)
      end

      # Additional validation for spend-to-script-hash transactions
      if flag?(SCRIPT_VERIFY_P2SH) && script_pubkey.p2sh?
        return set_error(SCRIPT_ERR_SIG_PUSHONLY) unless script_sig.push_only?
        tmp = stack
        @stack = stack_copy
        raise 'stack cannot be empty.' if stack.empty?
        begin
          redeem_script = Bitcoin::Script.parse_from_payload(stack.pop.htb)
        rescue Exception => e
          return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
        end
        return false unless eval_script(redeem_script, :base)
        return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)

        # P2SH witness program
        if flag?(SCRIPT_VERIFY_WITNESS) && redeem_script.witness_program?
          had_witness = true
          # The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we reintroduce malleability.
          return set_error(SCRIPT_ERR_WITNESS_MALLEATED_P2SH) unless script_sig == (Bitcoin::Script.new << redeem_script.to_payload.bth)

          version, program = redeem_script.witness_data
          return false unless verify_witness_program(witness, version, program)
        end
      end

      # The CLEANSTACK check is only performed after potential P2SH evaluation,
      # as the non-P2SH evaluation of a P2SH script will obviously not result in a clean stack (the P2SH inputs remain).
      # The same holds for witness evaluation.
      if flag?(SCRIPT_VERIFY_CLEANSTACK)
        # Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK would be possible,
        # which is not a softfork (and P2SH should be one).
        raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
        return set_error(SCRIPT_ERR_CLEANSTACK) unless stack.size == 1
      end

      if flag?(SCRIPT_VERIFY_WITNESS)
        raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
        return set_error(SCRIPT_ERR_WITNESS_UNEXPECTED) if !had_witness && !witness.empty?
      end

      true
    end
def verify_script(script_sig, script_pubkey, witness = ScriptWitness.new)

      return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?

      stack_copy = nil
      had_witness = false

      return false unless eval_script(script_sig, :base)

      stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)

      return false unless eval_script(script_pubkey, :base)

      return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last.htb)

      # Bare witness programs
      if flag?(SCRIPT_VERIFY_WITNESS) && script_pubkey.witness_program?
        had_witness = true
        return set_error(SCRIPT_ERR_WITNESS_MALLEATED) unless script_sig.size == 0
        version, program = script_pubkey.witness_data
        stack_copy = stack.dup
        return false unless verify_witness_program(witness, version, program)
      end

      # Additional validation for spend-to-script-hash transactions
      if flag?(SCRIPT_VERIFY_P2SH) && script_pubkey.p2sh?
        return set_error(SCRIPT_ERR_SIG_PUSHONLY) unless script_sig.push_only?
        tmp = stack
        @stack = stack_copy
        raise 'stack cannot be empty.' if stack.empty?
        begin
          redeem_script = Bitcoin::Script.parse_from_payload(stack.pop.htb)
        rescue Exception => e
          return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
        end
        return false unless eval_script(redeem_script, :base)
        return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)

        # P2SH witness program
        if flag?(SCRIPT_VERIFY_WITNESS) && redeem_script.witness_program?
          had_witness = true
          # The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we reintroduce malleability.
          return set_error(SCRIPT_ERR_WITNESS_MALLEATED_P2SH) unless script_sig == (Bitcoin::Script.new << redeem_script.to_payload.bth)

          version, program = redeem_script.witness_data
          return false unless verify_witness_program(witness, version, program)
        end
      end

      # The CLEANSTACK check is only performed after potential P2SH evaluation,
      # as the non-P2SH evaluation of a P2SH script will obviously not result in a clean stack (the P2SH inputs remain).
      # The same holds for witness evaluation.
      if flag?(SCRIPT_VERIFY_CLEANSTACK)
        # Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK would be possible,
        # which is not a softfork (and P2SH should be one).
        raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
        return set_error(SCRIPT_ERR_CLEANSTACK) unless stack.size == 1
      end

      if flag?(SCRIPT_VERIFY_WITNESS)
        raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
        return set_error(SCRIPT_ERR_WITNESS_UNEXPECTED) if !had_witness && !witness.empty?
      end

      true
    end
initialize runner
 eval script
 @param [Bitcoin::Script] script_sig a signature script (unlock script which data push only)
 @param [Bitcoin::Script] script_pubkey a script pubkey (locking script)
 @param [Bitcoin::ScriptWitness] witness a witness script
 @return [Boolean] result