Coverage Summary for Class: Block (org.ethereum.core)

Class Method, % Line, %
Block 86.5% (45/52) 67.9% (93/137)
Block$MockitoMock$898112400
Block$MockitoMock$898112400$auxiliary$0ASewLdK
Block$MockitoMock$898112400$auxiliary$0RxrWd66
Block$MockitoMock$898112400$auxiliary$2Z7ZK1Kz
Block$MockitoMock$898112400$auxiliary$4cpNyObd
Block$MockitoMock$898112400$auxiliary$5DPf0yFj
Block$MockitoMock$898112400$auxiliary$5ulECbxw
Block$MockitoMock$898112400$auxiliary$C5HNm6uN
Block$MockitoMock$898112400$auxiliary$CatoTNB7
Block$MockitoMock$898112400$auxiliary$cd3ux9bA
Block$MockitoMock$898112400$auxiliary$dpQxpOTT
Block$MockitoMock$898112400$auxiliary$DsaiBxc7
Block$MockitoMock$898112400$auxiliary$Dscv1uVP
Block$MockitoMock$898112400$auxiliary$DUrSbZf0
Block$MockitoMock$898112400$auxiliary$E0x2eb9e
Block$MockitoMock$898112400$auxiliary$eleV1JBH
Block$MockitoMock$898112400$auxiliary$F60Pgd2y
Block$MockitoMock$898112400$auxiliary$FD2mvT4o
Block$MockitoMock$898112400$auxiliary$fgIXTmD9
Block$MockitoMock$898112400$auxiliary$GRijBFMY
Block$MockitoMock$898112400$auxiliary$HmR2gJkl
Block$MockitoMock$898112400$auxiliary$jF3qKgt1
Block$MockitoMock$898112400$auxiliary$koXcF8uw
Block$MockitoMock$898112400$auxiliary$Ld6ItqFN
Block$MockitoMock$898112400$auxiliary$Letz41L1
Block$MockitoMock$898112400$auxiliary$LsDGuJhu
Block$MockitoMock$898112400$auxiliary$MyELbnB6
Block$MockitoMock$898112400$auxiliary$N0KYuP8O
Block$MockitoMock$898112400$auxiliary$nUqLBsj0
Block$MockitoMock$898112400$auxiliary$p0sr49vt
Block$MockitoMock$898112400$auxiliary$pELRHB8k
Block$MockitoMock$898112400$auxiliary$pRkQLFWo
Block$MockitoMock$898112400$auxiliary$pRN7Rfxd
Block$MockitoMock$898112400$auxiliary$Qd6YRNZO
Block$MockitoMock$898112400$auxiliary$rLIJ6Ejo
Block$MockitoMock$898112400$auxiliary$rzAoSGfH
Block$MockitoMock$898112400$auxiliary$SUgYT48K
Block$MockitoMock$898112400$auxiliary$TRyy0bNT
Block$MockitoMock$898112400$auxiliary$ttpMdcdn
Block$MockitoMock$898112400$auxiliary$v2oBk1BX
Block$MockitoMock$898112400$auxiliary$v4flT9hg
Block$MockitoMock$898112400$auxiliary$V4zhidu6
Block$MockitoMock$898112400$auxiliary$w3OmstiE
Block$MockitoMock$898112400$auxiliary$wcKUN68Q
Block$MockitoMock$898112400$auxiliary$zh8yFk8F
Block$MockitoMock$898112400$auxiliary$zZtZrbN1
Total 86.5% (45/52) 67.9% (93/137)


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.core; 21  22 import co.rsk.core.BlockDifficulty; 23 import co.rsk.core.Coin; 24 import co.rsk.core.RskAddress; 25 import co.rsk.core.bc.BlockHashesHelper; 26 import co.rsk.crypto.Keccak256; 27 import co.rsk.panic.PanicProcessor; 28 import com.google.common.collect.ImmutableList; 29 import org.bouncycastle.util.Arrays; 30 import org.bouncycastle.util.BigIntegers; 31 import org.ethereum.util.ByteUtil; 32 import org.ethereum.util.RLP; 33  34 import javax.annotation.Nonnull; 35 import java.math.BigInteger; 36 import java.util.ArrayList; 37 import java.util.Collections; 38 import java.util.List; 39  40 /** 41  * The block in Ethereum is the collection of relevant pieces of information 42  * (known as the blockheader), H, together with information corresponding to 43  * the comprised transactions, R, and a set of other blockheaders U that are known 44  * to have a parent equalBytes to the present block’s parent’s parent 45  * (such blocks are known as uncles). 46  * 47  * @author Roman Mandeleil 48  * @author Nick Savers 49  * @since 20.05.2014 50  */ 51 public class Block { 52  private static final PanicProcessor panicProcessor = new PanicProcessor(); 53  54  private BlockHeader header; 55  56  private List<Transaction> transactionsList; 57  58  private List<BlockHeader> uncleList; 59  60  /* Private */ 61  private byte[] rlpEncoded; 62  63  /* Indicates if this block can or cannot be changed */ 64  private volatile boolean sealed; 65  66  public static Block createBlockFromHeader(BlockHeader header, boolean isRskip126Enabled) { 67  return new Block(header, Collections.emptyList(), Collections.emptyList(), isRskip126Enabled, true, false); 68  } 69  70  public Block(BlockHeader header, List<Transaction> transactionsList, List<BlockHeader> uncleList, boolean isRskip126Enabled, boolean sealed) { 71  this(header, transactionsList, uncleList, isRskip126Enabled, sealed, true); 72  } 73  74  private Block(BlockHeader header, List<Transaction> transactionsList, List<BlockHeader> uncleList, boolean isRskip126Enabled, boolean sealed, boolean checktxs) { 75  byte[] calculatedRoot = BlockHashesHelper.getTxTrieRoot(transactionsList, isRskip126Enabled); 76  77  if (checktxs && !Arrays.areEqual(header.getTxTrieRoot(), calculatedRoot)) { 78  String message = String.format( 79  "Transactions trie root validation failed for block %d %s", header.getNumber(), header.getHash() 80  ); 81  panicProcessor.panic("txroot", message); 82  throw new IllegalArgumentException(message); 83  } 84  85  this.header = header; 86  this.transactionsList = ImmutableList.copyOf(transactionsList); 87  this.uncleList = ImmutableList.copyOf(uncleList); 88  this.sealed = sealed; 89  } 90  91  public void seal() { 92  this.sealed = true; 93  this.header.seal(); 94  } 95  96  public boolean isSealed() { 97  return this.sealed; 98  } 99  100  // TODO(mc) remove this method and create a new ExecutedBlock class or similar 101  public void setTransactionsList(@Nonnull List<Transaction> transactionsList) { 102  /* A sealed block is immutable, cannot be changed */ 103  if (this.sealed) { 104  throw new SealedBlockException("trying to alter transaction list"); 105  } 106  107  this.transactionsList = Collections.unmodifiableList(transactionsList); 108  rlpEncoded = null; 109  } 110  111  public BlockHeader getHeader() { 112  return this.header; 113  } 114  115  public Keccak256 getHash() { 116  return this.header.getHash(); 117  } 118  119  public Keccak256 getParentHash() { 120  return this.header.getParentHash(); 121  } 122  123  public byte[] getUnclesHash() { 124  return this.header.getUnclesHash(); 125  } 126  127  public RskAddress getCoinbase() { 128  return this.header.getCoinbase(); 129  } 130  131  public byte[] getStateRoot() { 132  return this.header.getStateRoot(); 133  } 134  135  public void setStateRoot(byte[] stateRoot) { 136  /* A sealed block is immutable, cannot be changed */ 137  if (this.sealed) { 138  throw new SealedBlockException("trying to alter state root"); 139  } 140  141  this.header.setStateRoot(stateRoot); 142  } 143  144  public byte[] getTxTrieRoot() { 145  return this.header.getTxTrieRoot(); 146  } 147  148  public byte[] getReceiptsRoot() { 149  return this.header.getReceiptsRoot(); 150  } 151  152  public byte[] getLogBloom() { 153  return this.header.getLogsBloom(); 154  } 155  156  public BlockDifficulty getDifficulty() { 157  return this.header.getDifficulty(); 158  } 159  160  public Coin getFeesPaidToMiner() { 161  return this.header.getPaidFees(); 162  } 163  164  public BlockDifficulty getCumulativeDifficulty() { 165  BlockDifficulty calcDifficulty = this.header.getDifficulty(); 166  for (BlockHeader uncle : uncleList) { 167  calcDifficulty = calcDifficulty.add(uncle.getDifficulty()); 168  } 169  return calcDifficulty; 170  } 171  172  public long getTimestamp() { 173  return this.header.getTimestamp(); 174  } 175  176  public long getNumber() { 177  return this.header.getNumber(); 178  } 179  180  public byte[] getGasLimit() { 181  return this.header.getGasLimit(); 182  } 183  184  public long getGasUsed() { 185  return this.header.getGasUsed(); 186  } 187  188  public byte[] getExtraData() { 189  return this.header.getExtraData(); 190  } 191  192  public List<Transaction> getTransactionsList() { 193  return this.transactionsList; 194  } 195  196  public List<BlockHeader> getUncleList() { 197  return this.uncleList; 198  } 199  200  public Coin getMinimumGasPrice() { 201  return this.header.getMinimumGasPrice(); 202  } 203  204  // [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root, 205  // difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp, 206  // extradata, nonce] 207  208  @Override 209  public String toString() { 210  StringBuilder toStringBuff = new StringBuilder(); 211  toStringBuff.append(ByteUtil.toHexString(this.getEncoded())).append("\n"); 212  toStringBuff.append("BlockData [ "); 213  toStringBuff.append("hash=").append(this.getHash()).append("\n"); 214  toStringBuff.append(header.toString()); 215  216  if (!getUncleList().isEmpty()) { 217  toStringBuff.append("Uncles [\n"); 218  for (BlockHeader uncle : getUncleList()) { 219  toStringBuff.append(uncle.toString()); 220  toStringBuff.append("\n"); 221  } 222  toStringBuff.append("]\n"); 223  } else { 224  toStringBuff.append("Uncles []\n"); 225  } 226  if (!getTransactionsList().isEmpty()) { 227  toStringBuff.append("Txs [\n"); 228  for (Transaction tx : getTransactionsList()) { 229  toStringBuff.append(tx); 230  toStringBuff.append("\n"); 231  } 232  toStringBuff.append("]\n"); 233  } else { 234  toStringBuff.append("Txs []\n"); 235  } 236  toStringBuff.append("]"); 237  238  return toStringBuff.toString(); 239  } 240  241  /** 242  * check if param block is son of this block 243  * 244  * @param block - possible a son of this 245  * @return - true if this block is parent of param block 246  */ 247  public boolean isParentOf(Block block) { 248  return this.header.isParentOf(block.getHeader()); 249  } 250  251  public boolean isGenesis() { 252  return this.header.isGenesis(); 253  } 254  255  public boolean isEqual(Block block) { 256  return this.getHash().equals(block.getHash()); 257  } 258  259  public boolean fastEquals(Block block) { 260  return block != null && this.getHash().equals(block.getHash()); 261  } 262  263  private byte[] getTransactionsEncoded() { 264  byte[][] transactionsEncoded = new byte[transactionsList.size()][]; 265  int i = 0; 266  for (Transaction tx : transactionsList) { 267  transactionsEncoded[i] = tx.getEncoded(); 268  ++i; 269  } 270  return RLP.encodeList(transactionsEncoded); 271  } 272  273  private byte[] getUnclesEncoded() { 274  byte[][] unclesEncoded = new byte[uncleList.size()][]; 275  int i = 0; 276  for (BlockHeader uncle : uncleList) { 277  unclesEncoded[i] = uncle.getFullEncoded(); 278  ++i; 279  } 280  return RLP.encodeList(unclesEncoded); 281  } 282  283  public byte[] getEncoded() { 284  if (rlpEncoded == null) { 285  byte[] header = this.header.getFullEncoded(); 286  287  List<byte[]> block = getBodyElements(); 288  block.add(0, header); 289  byte[][] elements = block.toArray(new byte[block.size()][]); 290  291  this.rlpEncoded = RLP.encodeList(elements); 292  } 293  294  return rlpEncoded; 295  } 296  297  private List<byte[]> getBodyElements() { 298  byte[] transactions = getTransactionsEncoded(); 299  byte[] uncles = getUnclesEncoded(); 300  301  List<byte[]> body = new ArrayList<>(); 302  body.add(transactions); 303  body.add(uncles); 304  305  return body; 306  } 307  308  public String getPrintableHash() { 309  return header.getPrintableHash(); 310  } 311  312  private String getParentPrintableHash() { 313  return header.getParentPrintableHash(); 314  } 315  316  public String getPrintableHashForMergedMining() { 317  return this.header.getPrintableHashForMergedMining(); 318  } 319  320  public byte[] getHashForMergedMining() { 321  return this.header.getHashForMergedMining(); 322  } 323  324  public String getShortDescr() { 325  return "#" + getNumber() + " (" + getPrintableHash() + " <~ " 326  + getParentPrintableHash() + ") Txs:" + getTransactionsList().size() + 327  ", Unc: " + getUncleList().size(); 328  } 329  330  public String getHashJsonString() { 331  return getHash().toJsonString(); 332  } 333  334  public String getParentHashJsonString() { 335  return getParentHash().toJsonString(); 336  } 337  338  public byte[] getBitcoinMergedMiningHeader() { 339  return this.header.getBitcoinMergedMiningHeader(); 340  } 341  342  public void setBitcoinMergedMiningHeader(byte[] bitcoinMergedMiningHeader) { 343  /* A sealed block is immutable, cannot be changed */ 344  if (this.sealed) { 345  throw new SealedBlockException("trying to alter bitcoin merged mining header"); 346  } 347  348  this.header.setBitcoinMergedMiningHeader(bitcoinMergedMiningHeader); 349  rlpEncoded = null; 350  } 351  352  public byte[] getBitcoinMergedMiningMerkleProof() { 353  return this.header.getBitcoinMergedMiningMerkleProof(); 354  } 355  356  public void setBitcoinMergedMiningMerkleProof(byte[] bitcoinMergedMiningMerkleProof) { 357  /* A sealed block is immutable, cannot be changed */ 358  if (this.sealed) { 359  throw new SealedBlockException("trying to alter bitcoin merged mining Merkle proof"); 360  } 361  362  this.header.setBitcoinMergedMiningMerkleProof(bitcoinMergedMiningMerkleProof); 363  rlpEncoded = null; 364  } 365  366  public byte[] getBitcoinMergedMiningCoinbaseTransaction() { 367  return this.header.getBitcoinMergedMiningCoinbaseTransaction(); 368  } 369  370  public void setBitcoinMergedMiningCoinbaseTransaction(byte[] bitcoinMergedMiningCoinbaseTransaction) { 371  if (this.sealed) { 372  throw new SealedBlockException("trying to alter bitcoin merged mining coinbase transaction"); 373  } 374  375  this.header.setBitcoinMergedMiningCoinbaseTransaction(bitcoinMergedMiningCoinbaseTransaction); 376  rlpEncoded = null; 377  } 378  379  public BigInteger getGasLimitAsInteger() { 380  return (this.getGasLimit() == null) ? null : BigIntegers.fromUnsignedByteArray(this.getGasLimit()); 381  } 382  383  public void flushRLP() { 384  this.rlpEncoded = null; 385  } 386 }