Coverage Summary for Class: AddressesTopicsFilter (org.ethereum.rpc)

Class Class, % Method, % Line, %
AddressesTopicsFilter 0% (0/1) 0% (0/6) 0% (0/59)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 RSK Labs Ltd. 4  * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>) 5  * 6  * This program is free software: you can redistribute it and/or modify 7  * it under the terms of the GNU Lesser General Public License as published by 8  * the Free Software Foundation, either version 3 of the License, or 9  * (at your option) any later version. 10  * 11  * This program is distributed in the hope that it will be useful, 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14  * GNU Lesser General Public License for more details. 15  * 16  * You should have received a copy of the GNU Lesser General Public License 17  * along with this program. If not, see <http://www.gnu.org/licenses/>. 18  */ 19  20 package org.ethereum.rpc; 21  22 import co.rsk.core.RskAddress; 23 import org.ethereum.core.Bloom; 24 import org.ethereum.crypto.Keccak256Helper; 25 import org.ethereum.vm.DataWord; 26 import org.ethereum.vm.LogInfo; 27  28 import java.util.ArrayList; 29 import java.util.List; 30  31 public class AddressesTopicsFilter { 32  private List<Topic[]> topics = new ArrayList<>(); // [[addr1, addr2], null, [A, B], [C]] 33  private RskAddress[] addresses; 34  private Bloom[][] filterBlooms; 35  36  public AddressesTopicsFilter(RskAddress[] addresses, Topic[][] topics) { 37  if (topics != null) { 38  for (int nt = 0; nt < topics.length; nt++) { 39  this.topics.add(topics[nt]); 40  } 41  } 42  43  this.addresses = addresses == null? new RskAddress[0]: addresses; 44  45  initBlooms(); 46  } 47  48  private void initBlooms() { 49  if (filterBlooms != null) { 50  return; 51  } 52  53  List<byte[][]> addrAndTopics = new ArrayList<>(2); 54  55  for (Topic[] toplist : topics) { 56  byte[][] tops = new byte[toplist.length][]; 57  58  for (int k = 0; k < tops.length; k++) { 59  tops[k] = toplist[k].getBytes(); 60  } 61  62  addrAndTopics.add(tops); 63  } 64  65  byte[][] addrs = new byte[addresses.length][]; 66  67  for (int k = 0; k < addresses.length; k++) { 68  addrs[k] = addresses[k].getBytes(); 69  } 70  71  addrAndTopics.add(addrs); 72  73  filterBlooms = new Bloom[addrAndTopics.size()][]; 74  75  for (int i = 0; i < addrAndTopics.size(); i++) { 76  byte[][] orTopics = addrAndTopics.get(i); 77  78  if (orTopics == null || orTopics.length == 0) { 79  filterBlooms[i] = new Bloom[] {new Bloom()}; // always matches 80  } else { 81  filterBlooms[i] = new Bloom[orTopics.length]; 82  for (int j = 0; j < orTopics.length; j++) { 83  if (orTopics[j] != null) { 84  filterBlooms[i][j] = Bloom.create(Keccak256Helper.keccak256(orTopics[j])); 85  } 86  } 87  } 88  } 89  } 90  91  public boolean matchBloom(Bloom blockBloom) { 92  for (Bloom[] andBloom : filterBlooms) { 93  boolean orMatches = false; 94  95  for (Bloom orBloom : andBloom) { 96  if (blockBloom.matches(orBloom)) { 97  orMatches = true; 98  break; 99  } 100  } 101  102  if (!orMatches) { 103  return false; 104  } 105  } 106  107  return true; 108  } 109  110  boolean matchesContractAddress(RskAddress toAddr) { 111  for (RskAddress address : addresses) { 112  if (address.equals(toAddr)) { 113  return true; 114  } 115  } 116  117  return addresses.length == 0; 118  } 119  120  public boolean matchesExactly(LogInfo logInfo) { 121  if (!matchesContractAddress(new RskAddress(logInfo.getAddress()))) { 122  return false; 123  } 124  125  List<DataWord> logTopics = logInfo.getTopics(); 126  127  for (int i = 0; i < this.topics.size(); i++) { 128  if (logTopics.size() <= i) { 129  if (topics.get(i).length == 0) { 130  continue; 131  } 132  133  return false; 134  } 135  136  DataWord logTopic = logTopics.get(i); 137  Topic[] orTopics = topics.get(i); 138  139  if (orTopics != null && orTopics.length > 0) { 140  if (!matchTopic(logTopic, orTopics)) { 141  return false; 142  } 143  } 144  } 145  146  return true; 147  } 148  149  private boolean matchTopic(DataWord logTopic, Topic[] orTopics) { 150  for (Topic orTopic : orTopics) { 151  if (DataWord.valueOf(orTopic.getBytes()).equals(logTopic)) { 152  return true; 153  } 154  } 155  156  return false; 157  } 158 }