Class: Reth::JSONRPC::LogFilter

Inherits:
Object
  • Object
show all
Includes:
Helper
Defined in:
lib/reth/jsonrpc/filter.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helper

#bytes_to_hex, #chain, #decode_block_tag, #discovery, #encode_block, #encode_loglist, #encode_tx, #get_block, #get_compilers, #get_ivar_value, #hex_to_bytes, #hex_to_int, #int_to_hex, #peermanager

Constructor Details

#initialize(obj, chain) ⇒ LogFilter

Returns a new instance of LogFilter.



42
43
44
45
46
47
48
49
50
# File 'lib/reth/jsonrpc/filter.rb', line 42

def initialize(obj, chain)
  @chain = chain
  @first_block, @last_block, @addresses, @topics = parse_obj obj

  @last_head = @chain.head
  @last_block_checked = nil

  @log_dict = {}
end

Class Method Details

.create(obj, chain) ⇒ Object



32
33
34
35
36
37
# File 'lib/reth/jsonrpc/filter.rb', line 32

def create(obj, chain)
  f = new obj, chain
  id = Filter.next_id
  Filter.map[id] = f
  id
end

Instance Method Details

#checkObject



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/reth/jsonrpc/filter.rb', line 52

def check
  first, last = get_from_to @first_block, @last_block
  first = [@last_head.number + 1, first].min if @first_block.is_a?(String)
  raise "first must not be greater than last" unless first <= last

  if @last_block_checked
    first = [@last_block_checked.number + 1, first].max
    return {} if first > last
  end

  blocks_to_check = []
  (first...last).each do |n|
    blocks_to_check.push @chain.index.get_block_by_number(n)
  end

  head = @chain.head
  head_candidate = @chain.head_candidate

  if last == head_candidate.number
    blocks_to_check.push head_candidate
  else
    blocks_to_check.push @chain.get(@chain.index.get_block_by_number(last))
  end

  int32 = RLP::Sedes::BigEndianInt.new 32

  new_logs = {}
  blocks_to_check.each_with_index do |block, i|
    unless [Ethereum::Block, Ethereum::CachedBlock].include?(block.class)
      # must be blockhash
      bloom = @chain.get_bloom block

      if @addresses
        pass_address_check = @addresses.any? {|addr| Ethereum::Bloom.query(bloom, addr) }
        next unless pass_address_check
      end

      topics = (@topics || []).map {|t| int32.serialize(t) }
      topic_bloom = Ethereum::Bloom.from_array topics
      next if Ethereum::Bloom.combine(bloom, topic_bloom) != bloom

      block = @chain.get block
    end

    r_idx = nil
    l_idx = nil
    log = nil
    block.get_receipts.each_with_index do |receipt, ri|
      r_idx = ri

      receipt.logs.each_with_index do |_log, li|
        log = _log
        l_idx = li

        next if @addresses && !@addresses.include?(log.address)

        if @topics
          topic_match = log.topics.size >= @topics.size
          next unless topic_match

          @topics.zip(log.topics).each do |filter_topic, log_topic|
            if filter_topic && filter_topic != log_topic
              topic_match = false
              break
            end
          end
          next unless topic_match
        end

        tx = block.get_transaction r_idx
        id = Ethereum::Utils.keccak256 "#{tx.full_hash}#{l_idx}"
        pending = block == head_candidate
        new_logs[id] = {
          log: log,
          log_idx: l_idx,
          block: block,
          txhash: tx.full_hash,
          tx_idx: r_idx
        }
      end
    end
  end

  @last_block_checked = if blocks_to_check.last != head_candidate
                          blocks_to_check.last
                        else
                          blocks_to_check.size >= 2 ? blocks_to_check[-2] : nil
                        end

  if @last_block_checked && ![Ethereum::Block, Ethereum::CachedBlock].include?(@last_block_checked.class)
    @last_block_checked = @chain.get @last_block_checked
  end

  actually_new_ids = new_logs.keys - @log_dict.keys
  @log_dict.merge! new_logs

  actually_new_ids.map {|id| [id, new_logs[id]] }.to_h
end

#logsObject



151
152
153
154
# File 'lib/reth/jsonrpc/filter.rb', line 151

def logs
  check
  @log_dict.values
end

#new_logsObject



156
157
158
# File 'lib/reth/jsonrpc/filter.rb', line 156

def new_logs
  check.values
end

#to_sObject



160
161
162
# File 'lib/reth/jsonrpc/filter.rb', line 160

def to_s
  "<Filter(addressed=#{@addresses}, topics=#{@topics}, first=#{@first_block}, last=#{@last_block})>"
end