Coverage Summary for Class: BlockHeaderBuilder (org.ethereum.core)
Class |
Class, %
|
Method, %
|
Line, %
|
BlockHeaderBuilder |
100%
(1/1)
|
47.6%
(20/42)
|
55.2%
(58/105)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2020 RSK Labs Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package org.ethereum.core;
20
21 import co.rsk.core.BlockDifficulty;
22 import co.rsk.core.Coin;
23 import co.rsk.core.RskAddress;
24 import co.rsk.crypto.Keccak256;
25 import org.ethereum.config.blockchain.upgrades.ActivationConfig;
26 import org.ethereum.config.blockchain.upgrades.ConsensusRule;
27 import org.ethereum.crypto.HashUtil;
28 import org.ethereum.util.RLP;
29
30 import javax.annotation.Nullable;
31 import java.math.BigInteger;
32 import java.util.Arrays;
33
34 import static org.ethereum.crypto.HashUtil.EMPTY_TRIE_HASH;
35
36 public class BlockHeaderBuilder {
37
38 private static final byte[] EMPTY_LIST_HASH = HashUtil.keccak256(RLP.encodeList());
39
40 private byte[] parentHash;
41 private byte[] unclesHash;
42 private RskAddress coinbase;
43 private byte[] stateRoot;
44 private byte[] txTrieRoot;
45 private byte[] receiptTrieRoot;
46 private byte[] logsBloom;
47 private BlockDifficulty difficulty;
48 private long timestamp;
49 private long number;
50 private byte[] gasLimit;
51 private long gasUsed;
52 private Coin paidFees;
53
54 private byte[] extraData;
55 private byte[] bitcoinMergedMiningHeader;
56 private byte[] bitcoinMergedMiningMerkleProof;
57 private byte[] bitcoinMergedMiningCoinbaseTransaction;
58 private byte[] mergedMiningForkDetectionData;
59 private byte[] ummRoot;
60
61 private Coin minimumGasPrice;
62 private int uncleCount;
63
64 private boolean useRskip92Encoding;
65 private boolean includeForkDetectionData;
66
67 private final ActivationConfig activationConfig;
68
69 private boolean createConsensusCompliantHeader;
70 private boolean createUmmCompliantHeader;
71
72 public BlockHeaderBuilder(ActivationConfig activationConfig) {
73 this.activationConfig = activationConfig;
74 createConsensusCompliantHeader = true;
75 createUmmCompliantHeader = true;
76 }
77
78 public BlockHeaderBuilder setCreateConsensusCompliantHeader(boolean createConsensusCompliantHeader) {
79 this.createConsensusCompliantHeader = createConsensusCompliantHeader;
80 return this;
81 }
82
83 public BlockHeaderBuilder setCreateUmmCompliantHeader(boolean createUmmCompliantHeader) {
84 this.createUmmCompliantHeader = createUmmCompliantHeader;
85 return this;
86 }
87
88 public BlockHeaderBuilder setStateRoot(byte[] stateRoot) {
89 this.stateRoot = copy(stateRoot);
90 return this;
91 }
92
93 public BlockHeaderBuilder setDifficulty(BlockDifficulty difficulty) {
94 this.difficulty = difficulty;
95 return this;
96 }
97
98 public BlockHeaderBuilder setPaidFees(Coin paidFees) {
99 this.paidFees = paidFees;
100 return this;
101 }
102
103 public BlockHeaderBuilder setGasUsed(long gasUsed) {
104 this.gasUsed = gasUsed;
105 return this;
106 }
107
108 public BlockHeaderBuilder setLogsBloom(byte[] logsBloom) {
109 this.logsBloom = copy(logsBloom);
110 return this;
111 }
112
113 public BlockHeaderBuilder setBitcoinMergedMiningHeader(byte[] bitcoinMergedMiningHeader) {
114 this.bitcoinMergedMiningHeader = copy(bitcoinMergedMiningHeader);
115 return this;
116 }
117
118 public BlockHeaderBuilder setBitcoinMergedMiningMerkleProof(byte[] bitcoinMergedMiningMerkleProof) {
119 this.bitcoinMergedMiningMerkleProof = copy(bitcoinMergedMiningMerkleProof);
120 return this;
121 }
122
123 public BlockHeaderBuilder setBitcoinMergedMiningCoinbaseTransaction(byte[] bitcoinMergedMiningCoinbaseTransaction) {
124 this.bitcoinMergedMiningCoinbaseTransaction = copy(bitcoinMergedMiningCoinbaseTransaction);
125 return this;
126 }
127
128 public BlockHeaderBuilder setTxTrieRoot(byte[] txTrieRoot) {
129 this.txTrieRoot = copy(txTrieRoot);
130 return this;
131 }
132
133 public BlockHeaderBuilder setEmptyTxTrieRoot() {
134 this.txTrieRoot = EMPTY_TRIE_HASH;
135 return this;
136 }
137
138 public BlockHeaderBuilder setReceiptTrieRoot(byte[] receiptTrieRoot) {
139 this.receiptTrieRoot = copy(receiptTrieRoot);
140 return this;
141 }
142
143 public BlockHeaderBuilder setTimestamp(long timestamp) {
144 this.timestamp = timestamp;
145 return this;
146 }
147
148 public BlockHeaderBuilder setNumber(long number) {
149 this.number = number;
150 return this;
151 }
152
153 public BlockHeaderBuilder setGasLimit(byte[] gasLimit) {
154 this.gasLimit = copy(gasLimit);
155 return this;
156 }
157
158 public BlockHeaderBuilder setExtraData(byte[] extraData) {
159 this.extraData = copy(extraData);
160 return this;
161 }
162
163 public BlockHeaderBuilder setMergedMiningForkDetectionData(byte[] mergedMiningForkDetectionData) {
164 this.mergedMiningForkDetectionData = copy(mergedMiningForkDetectionData);
165 return this;
166 }
167
168 public BlockHeaderBuilder setMinimumGasPrice(Coin minimumGasPrice) {
169 this.minimumGasPrice = minimumGasPrice;
170 return this;
171 }
172
173 public BlockHeaderBuilder setUncleCount(int uncleCount) {
174 this.uncleCount = uncleCount;
175 return this;
176 }
177
178 public BlockHeaderBuilder setUseRskip92Encoding(boolean useRskip92Encoding) {
179 this.useRskip92Encoding = useRskip92Encoding;
180 return this;
181 }
182
183 public BlockHeaderBuilder setIncludeForkDetectionData(boolean includeForkDetectionData) {
184 this.includeForkDetectionData = includeForkDetectionData;
185 return this;
186 }
187
188 public BlockHeaderBuilder setParentHashFromKeccak256(Keccak256 parentHash) {
189 this.parentHash = copy(parentHash);
190 return this;
191 }
192
193 public BlockHeaderBuilder setParentHash(byte[] parentHash) {
194 this.parentHash = copy(parentHash);
195 return this;
196 }
197
198 public BlockHeaderBuilder setEmptyUnclesHash() {
199 this.unclesHash = EMPTY_LIST_HASH;
200 return this;
201 }
202
203 public BlockHeaderBuilder setUnclesHash(byte[] unclesHash) {
204 this.unclesHash = copy(unclesHash);
205 return this;
206 }
207
208 public BlockHeaderBuilder setCoinbase(RskAddress coinbase) {
209 this.coinbase = coinbase;
210 return this;
211 }
212
213 public BlockHeaderBuilder setDifficultyFromBytes(@Nullable byte[] data) {
214 // This is to make it compatible with RLP.parseBlockDifficulty() which was previously
215 // user (but I think it was wrongly included in the RLP class, because these arguments
216 // do not come from any RLP parsing).
217 if (data != null) {
218 difficulty = new BlockDifficulty(new BigInteger(data));
219 } else {
220 difficulty = null;
221 }
222 return this;
223 }
224
225 public BlockHeaderBuilder setEmptyMergedMiningForkDetectionData() {
226 mergedMiningForkDetectionData = new byte[12];
227 return this;
228 }
229
230 public BlockHeaderBuilder setEmptyExtraData() {
231 extraData = new byte[]{};
232 return this;
233 }
234
235 public BlockHeaderBuilder setEmptyLogsBloom() {
236 logsBloom = copy(new Bloom().getData());
237 return this;
238 }
239
240 public BlockHeaderBuilder setEmptyStateRoot() {
241 stateRoot = EMPTY_TRIE_HASH;
242 return this;
243 }
244
245 public BlockHeaderBuilder setEmptyReceiptTrieRoot() {
246 receiptTrieRoot = EMPTY_TRIE_HASH;
247 return this;
248 }
249
250 public BlockHeaderBuilder setUmmRoot(byte[] ummRoot) {
251 this.ummRoot = copy(ummRoot, null);
252 return this;
253 }
254
255 private void initializeWithDefaultValues() {
256 extraData = normalizeValue(extraData, new byte[0]);
257 bitcoinMergedMiningHeader = normalizeValue(bitcoinMergedMiningHeader, new byte[0]);
258 bitcoinMergedMiningMerkleProof = normalizeValue(bitcoinMergedMiningMerkleProof, new byte[0]);
259 bitcoinMergedMiningCoinbaseTransaction = normalizeValue(bitcoinMergedMiningCoinbaseTransaction, new byte[0]);
260
261 unclesHash = normalizeValue(unclesHash, EMPTY_LIST_HASH);
262 coinbase = normalizeValue(coinbase, RskAddress.nullAddress());
263 stateRoot = normalizeValue(stateRoot, EMPTY_TRIE_HASH);
264 txTrieRoot = normalizeValue(txTrieRoot, EMPTY_TRIE_HASH);
265 receiptTrieRoot = normalizeValue(receiptTrieRoot, EMPTY_TRIE_HASH);
266 logsBloom = normalizeValue(logsBloom, new Bloom().getData());
267 paidFees = normalizeValue(paidFees, Coin.ZERO);
268 minimumGasPrice = normalizeValue(minimumGasPrice, Coin.ZERO);
269
270 mergedMiningForkDetectionData = normalizeValue(mergedMiningForkDetectionData, new byte[12]);
271 }
272
273 private <T> T normalizeValue(T value, T defaultValue) {
274 return value == null ? defaultValue : value;
275 }
276
277 private byte[] copy(Keccak256 hash) {
278 return copy(hash.getBytes());
279 }
280
281 private byte[] copy(byte[] bytes) {
282 return copy(bytes, new byte[0]);
283 }
284
285 private byte[] copy(byte[] bytes, byte[] defaultValue) {
286 if (bytes == null) {
287 return defaultValue;
288 }
289
290 return Arrays.copyOf(bytes, bytes.length);
291 }
292
293 public BlockHeader build() {
294 // Initial null values in some fields are replaced by empty
295 // arrays
296 initializeWithDefaultValues();
297
298 if (createConsensusCompliantHeader) {
299 useRskip92Encoding = activationConfig.isActive(ConsensusRule.RSKIP92, number);
300 includeForkDetectionData = activationConfig.isActive(ConsensusRule.RSKIP110, number) &&
301 mergedMiningForkDetectionData.length > 0;
302 }
303
304 if (createUmmCompliantHeader) {
305 if (activationConfig.isActive(ConsensusRule.RSKIPUMM, number)) {
306 if (ummRoot == null) {
307 ummRoot = new byte[0];
308 }
309 }
310 }
311
312 return new BlockHeader(
313 parentHash, unclesHash, coinbase,
314 stateRoot, txTrieRoot, receiptTrieRoot,
315 logsBloom, difficulty, number,
316 gasLimit, gasUsed, timestamp, extraData, paidFees,
317 bitcoinMergedMiningHeader,
318 bitcoinMergedMiningMerkleProof,
319 bitcoinMergedMiningCoinbaseTransaction,
320 mergedMiningForkDetectionData,
321 minimumGasPrice, uncleCount,
322 false, useRskip92Encoding,
323 includeForkDetectionData, ummRoot
324 );
325 }
326 }