<commit_before>module Bitcoin
  module Protocol

    class Parser

      def initialize(handler=nil)
        @h = handler || Handler.new
        @buf = ""
      end

      def log
        @log ||= Bitcoin::Logger.create("parser")
      end

      # handles inv/getdata packets
      #
      def parse_inv(payload, type=:put)
        count, payload = Protocol.unpack_var_int(payload)
        payload.each_byte.each_slice(36){|i|
          hash = i[4..-1].reverse.pack("C32")
          case i[0]
          when 1
            if type == :put
              @h.on_inv_transaction(hash)
            else
              @h.on_get_transaction(hash)
            end
          when 2
            if type == :put
              @h.on_inv_block(hash)
            else
              @h.on_get_block(hash)
            end
          else
            p ['parse_inv error', i]
          end
        }
      end

      def hth(h); h.unpack("H*")[0]; end

      def parse_addr(payload)
        count, payload = Protocol.unpack_var_int(payload)
        payload.each_byte.each_slice(30){|i|
          begin
            @h.on_addr( Addr.new(i.pack("C*")) )
          rescue
            puts "Error parsing addr: #{i.inspect}"
          end
        }
      end

      def parse_headers(payload)
        count, payload = Protocol.unpack_var_int(payload)
        idx = 0
        headers = count.times.map{ Block.new(payload[idx..idx+=81]) }
        @h.on_headers(headers)
      end

      def parse_getblocks(payload)
        version, payload = payload.unpack('a4a*')
        count,   payload = Protocol.unpack_var_int(payload)
        buf,     payload = payload.unpack("a#{count*32}a*")
        hashes    = buf.each_byte.each_slice(32).map{|i| hash = Protocol.hth(i.reverse.pack("C32")) }
        stop_hash = Protocol.hth(payload[0..32].reverse)
        [version, hashes, stop_hash]
      end

      def process_pkt(command, payload)
        case command
        when 'tx';       @h.on_tx( Tx.new(payload) )
        when 'block';    @h.on_block( Block.new(payload) )
        when 'headers';  parse_headers(payload)
        when 'inv';      parse_inv(payload, :put)
        when 'getdata';  parse_inv(payload, :get)
        when 'addr';     parse_addr(payload)
        when 'verack';   @h.on_handshake_complete # nop<commit_msg>only rescue address parsing, not on_addr method call.<commit_after>module Bitcoin
  module Protocol

    class Parser

      def initialize(handler=nil)
        @h = handler || Handler.new
        @buf = ""
      end

      def log
        @log ||= Bitcoin::Logger.create("parser")
      end

      # handles inv/getdata packets
      #
      def parse_inv(payload, type=:put)
        count, payload = Protocol.unpack_var_int(payload)
        payload.each_byte.each_slice(36){|i|
          hash = i[4..-1].reverse.pack("C32")
          case i[0]
          when 1
            if type == :put
              @h.on_inv_transaction(hash)
            else
              @h.on_get_transaction(hash)
            end
          when 2
            if type == :put
              @h.on_inv_block(hash)
            else
              @h.on_get_block(hash)
            end
          else
            p ['parse_inv error', i]
          end
        }
      end

      def hth(h); h.unpack("H*")[0]; end

      def parse_addr(payload)
        count, payload = Protocol.unpack_var_int(payload)
        payload.each_byte.each_slice(30){|i|
          begin
            addr = Addr.new(i.pack("C*"))
          rescue
            puts "Error parsing addr: #{i.inspect}"
          end
          @h.on_addr( addr )
        }
      end

      def parse_headers(payload)
        count, payload = Protocol.unpack_var_int(payload)
        idx = 0
        headers = count.times.map{ Block.new(payload[idx..idx+=81]) }
        @h.on_headers(headers)
      end

      def parse_getblocks(payload)
        version, payload = payload.unpack('a4a*')
        count,   payload = Protocol.unpack_var_int(payload)
        buf,     payload = payload.unpack("a#{count*32}a*")
        hashes    = buf.each_byte.each_slice(32).map{|i| hash = Protocol.hth(i.reverse.pack("C32")) }
        stop_hash = Protocol.hth(payload[0..32].reverse)
        [version, hashes, stop_hash]
      end

      def process_pkt(command, payload)
        case command
        when 'tx';       @h.on_tx( Tx.new(payload) )
        when 'block';    @h.on_block( Block.new(payload) )
        when 'headers';  parse_headers(payload)
        when 'inv';      parse_inv(payload, :put)
        when 'getdata';  parse_inv(payload, :get)
        when 'addr';     parse_addr(payload)
        when 'verack';   @h.on_handshake_complete # nop
{'fraction_non_alphanumeric': 0.11813893653516296, 'fraction_numerical': 0.01072041166380789, 'mean_word_length': 1.7734839476813318, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, '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': '5897783', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1457, 'n_words': 292}