<commit_before># Porting part of the code from bitcoin-ruby. see the license.
# https://github.com/lian/bitcoin-ruby/blob/master/COPYING

module Bitcoin

  # bitcoin key class
  class Key

    attr_accessor :priv_key
    attr_accessor :pubkey
    attr_accessor :compressed
    attr_reader :secp256k1_module

    MIN_PRIV_KEy_MOD_ORDER = 0x01
    # Order of secp256k1's generator minus 1.
    MAX_PRIV_KEY_MOD_ORDER = ECDSA::Group::Secp256k1.order - 1

    def initialize(priv_key: nil, pubkey: nil, compressed: true)
      @secp256k1_module =  Bitcoin.secp_impl
      @priv_key = priv_key
      if @priv_key
        raise ArgumentError, 'private key is not on curve' unless validate_private_key_range(@priv_key)
      end
      if pubkey
        @pubkey = pubkey
      else
        @pubkey = generate_pubkey(priv_key, compressed: compressed) if priv_key
      end
      @compressed = compressed
    end

    # generate key pair
    def self.generate
      priv_key, pubkey = Bitcoin.secp_impl.generate_key_pair
      new(priv_key: priv_key, pubkey: pubkey)
    end

    # import private key from wif format
    # https://en.bitcoin.it/wiki/Wallet_import_format
    def self.from_wif(wif)
      hex = Base58.decode(wif)
      raise ArgumentError, 'data is too short' if hex.htb.bytesize < 4
      version = hex[0..1]
      data = hex[2...-8].htb
      checksum = hex[-8..-1]
      raise ArgumentError, 'invalid version' unless version == Bitcoin.chain_params.privkey_version
      raise ArgumentError, 'invalid checksum' unless Bitcoin.calc_checksum(version + data.bth) == checksum
      key_len = data.bytesize
      if key_len == 33 && data[-1].unpack('C').first == 1
        compressed = true
        data = data[0..-2]
      elsif key_len == 32
        compressed = false
      else
        raise ArgumentError, 'Wrong number of bytes for a private key, not 32 or 33'
      end
      new(priv_key: data.bth, compressed: compressed)
    end

    # export private key with wif format
    def to_wif
      version = Bitcoin.chain_params.privkey_version
      hex = version + priv_key
      hex += '01' if compressed?
      hex += Bitcoin.calc_checksum(hex)
      Base58.encode(hex)
    end

    # sign +data+ with private key
    # @param [String] data a data to be signed with binary format
    # @return [String] signature data with binary format
    def sign(data)
      secp256k1_module.sign_data(data, priv_key)
    end

    # verify signature using public key
    # @param [String] sig signature data with binary format
    # @param [String] origin original message
    # @return [Boolean] verify result
    def verify(sig, origin)
      return false unless valid_pubkey?
      begin
        sig = ecdsa_signature_parse_der_lax(sig)
        secp256k1_module.verify_sig(origin, sig, pubkey)
      rescue Exception
        false
      end
    end

    # get hash160 public key.
    def hash160
      Bitcoin.hash160(pubkey)
    end

    # get pay to pubkey hash address
    def to_p2pkh
      Bitcoin::Script.to_p2pkh(hash160).addresses.first
    end

    # get pay to witness pubkey hash address
    def to_p2wpkh
      Bitcoin::Script.to_p2wpkh(hash160).addresses.first
    end

    # get p2wpkh address nested in p2sh.
    def to_nested_p2wpkh
      Bitcoin::Script.to_p2wpkh(hash160).to_p2sh.addresses.first
    end

    def compressed?
      @compressed
    end

    # generate pubkey ec point
    # @return [ECDSA::Point]
    def to_point
      p = pubkey
      p ||= generate_pubkey(priv_key, compressed: compressed)
      ECDSA::Format::PointOctetString.decode(p.htb, Bitcoin::Secp256k1::GROUP)
    end

    # check +pubkey+ (hex) is compress or uncompress pubkey.
    def self.compress_or_uncompress_pubkey?(pubkey)
      p = pubkey.htb
      return false if p.bytesize < 33
      case p[0]
        when "\x04"
          return false unless p.bytesize == 65
        when "\x02", "\x03"
          return false unless p.bytesize == 33
        else
          return false<commit_msg>Remove Key#compressed param and add key_type param instead<commit_after># Porting part of the code from bitcoin-ruby. see the license.
# https://github.com/lian/bitcoin-ruby/blob/master/COPYING

module Bitcoin

  # bitcoin key class
  class Key

    attr_accessor :priv_key
    attr_accessor :pubkey
    attr_accessor :key_type
    attr_reader :secp256k1_module

    TYPES = {uncompressed: 0x00, compressed: 0x01, p2pkh: 0x10, p2wpkh: 0x11, pw2pkh_p2sh: 0x12}

    MIN_PRIV_KEy_MOD_ORDER = 0x01
    # Order of secp256k1's generator minus 1.
    MAX_PRIV_KEY_MOD_ORDER = ECDSA::Group::Secp256k1.order - 1

    # initialize private key
    # @param [String] priv_key a private key with hex format.
    # @param [String] pubkey a public key with hex format.
    # @param [Integer] key_type a key type which determine address type.
    # @param [Boolean] compressed [Deprecated] whether public key is compressed.
    # @return [Bitcoin::Key] a key object.
    def initialize(priv_key: nil, pubkey: nil, key_type: nil, compressed: true)
      puts "[Warning] Use key_type parameter instead of compressed. compressed parameter removed in the future." if key_type.nil? && !compressed.nil?
      if key_type
        @key_type = key_type
        compressed = @key_type != TYPES[:uncompressed]
      else
        @key_type = compressed ? TYPES[:compressed] : TYPES[:uncompressed]
      end
      @secp256k1_module =  Bitcoin.secp_impl
      @priv_key = priv_key
      if @priv_key
        raise ArgumentError, 'private key is not on curve' unless validate_private_key_range(@priv_key)
      end
      if pubkey
        @pubkey = pubkey
      else
        @pubkey = generate_pubkey(priv_key, compressed: compressed) if priv_key
      end
    end

    # generate key pair
    def self.generate(key_type = TYPES[:compressed])
      priv_key, pubkey = Bitcoin.secp_impl.generate_key_pair
      new(priv_key: priv_key, pubkey: pubkey, key_type: key_type)
    end

    # import private key from wif format
    # https://en.bitcoin.it/wiki/Wallet_import_format
    def self.from_wif(wif)
      hex = Base58.decode(wif)
      raise ArgumentError, 'data is too short' if hex.htb.bytesize < 4
      version = hex[0..1]
      data = hex[2...-8].htb
      checksum = hex[-8..-1]
      raise ArgumentError, 'invalid version' unless version == Bitcoin.chain_params.privkey_version
      raise ArgumentError, 'invalid checksum' unless Bitcoin.calc_checksum(version + data.bth) == checksum
      key_len = data.bytesize
      if key_len == 33 && data[-1].unpack('C').first == 1
        key_type = TYPES[:compressed]
        data = data[0..-2]
      elsif key_len == 32
        key_type = TYPES[:uncompressed]
      else
        raise ArgumentError, 'Wrong number of bytes for a private key, not 32 or 33'
      end
      new(priv_key: data.bth, key_type: key_type)
    end

    # export private key with wif format
    def to_wif
      version = Bitcoin.chain_params.privkey_version
      hex = version + priv_key
      hex += '01' if compressed?
      hex += Bitcoin.calc_checksum(hex)
      Base58.encode(hex)
    end

    # sign +data+ with private key
    # @param [String] data a data to be signed with binary format
    # @return [String] signature data with binary format
    def sign(data)
      secp256k1_module.sign_data(data, priv_key)
    end

    # verify signature using public key
    # @param [String] sig signature data with binary format
    # @param [String] origin original message
    # @return [Boolean] verify result
    def verify(sig, origin)
      return false unless valid_pubkey?
      begin
        sig = ecdsa_signature_parse_der_lax(sig)
        secp256k1_module.verify_sig(origin, sig, pubkey)
      rescue Exception
        false
      end
    end

    # get hash160 public key.
    def hash160
      Bitcoin.hash160(pubkey)
    end

    # get pay to pubkey hash address
    # @deprecated
    def to_p2pkh
      Bitcoin::Script.to_p2pkh(hash160).addresses.first
    end

    # get pay to witness pubkey hash address
    # @deprecated
    def to_p2wpkh
      Bitcoin::Script.to_p2wpkh(hash160).addresses.first
    end

    # get p2wpkh address nested in p2sh.
    # @deprecated
    def to_nested_p2wpkh
      Bitcoin::Script.to_p2wpkh(hash160).to_p2sh.addresses.first
    end

    def compressed?
      key_type != TYPES[:uncompressed]
    end

    # generate pubkey ec point
    # @return [ECDSA::Point]
    def to_point
      p = pubkey
      p ||= generate_pubkey(priv_key, compressed: compressed)
      ECDSA::Format::PointOctetString.decode(p.htb, Bitcoin::Secp256k1::GROUP)
    end

    # check +pubkey+ (hex) is compress or uncompress pubkey.
    def self.compress_or_uncompress_pubkey?(pubkey)
      p = pubkey.htb
      return false if p.bytesize < 33
      case p[0]
        when "\x04"
          return false unless p.bytesize == 65
        when "\x02", "\x03"
          return false unless p.bytesize == 33
        else
          return false
{'fraction_non_alphanumeric': 0.0834357198704345, 'fraction_numerical': 0.024014296883726124, 'mean_word_length': 2.6741895773491997, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6674101', 'n_tokens_mistral': 3022, 'n_tokens_neox': 2864, 'n_words': 807}