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 }