Coverage Summary for Class: PendingFederation (co.rsk.peg)

Class Class, % Method, % Line, %
PendingFederation 0% (0/1) 0% (0/11) 0% (0/28)


1 /* 2  * This file is part of RskJ 3  * Copyright (C) 2017 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 co.rsk.peg; 20  21 import co.rsk.bitcoinj.core.BtcECKey; 22 import co.rsk.config.BridgeConstants; 23 import co.rsk.crypto.Keccak256; 24 import org.ethereum.config.blockchain.upgrades.ActivationConfig; 25 import org.ethereum.config.blockchain.upgrades.ConsensusRule; 26 import org.ethereum.crypto.HashUtil; 27  28 import java.time.Instant; 29 import java.util.ArrayList; 30 import java.util.Collections; 31 import java.util.List; 32 import java.util.Objects; 33 import java.util.stream.Collectors; 34 import org.slf4j.Logger; 35 import org.slf4j.LoggerFactory; 36  37 /** 38  * Immutable representation of an RSK Pending Federation. 39  * A pending federation is one that is being actively 40  * voted by the current federation to potentially become 41  * the new active federation. 42  * 43  * @author Ariel Mendelzon 44  */ 45 public final class PendingFederation { 46  private static final Logger logger = LoggerFactory.getLogger("PendingFederation"); 47  private static final int MIN_MEMBERS_REQUIRED = 2; 48  49  private final List<FederationMember> members; 50  51  public PendingFederation(List<FederationMember> members) { 52  // Sorting members ensures same order for members 53  // Immutability provides protection against unwanted modification, thus making the Pending Federation instance 54  // effectively immutable 55  this.members = Collections.unmodifiableList(members.stream().sorted(FederationMember.BTC_RSK_MST_PUBKEYS_COMPARATOR).collect(Collectors.toList())); 56  } 57  58  public List<FederationMember> getMembers() { 59  // Safe to return instance since both the list and instances are immutable 60  return members; 61  } 62  63  public List<BtcECKey> getBtcPublicKeys() { 64  // Copy keys since we don't control immutability of BtcECKey(s) 65  return members.stream().map(FederationMember::getBtcPublicKey).collect(Collectors.toList()); 66  } 67  68  public boolean isComplete() { 69  return this.members.size() >= MIN_MEMBERS_REQUIRED; 70  } 71  72  /** 73  * Creates a new PendingFederation with the additional specified member 74  * @param member the new federation member 75  * @return a new PendingFederation with the added member 76  */ 77  public PendingFederation addMember(FederationMember member) { 78  List<FederationMember> newMembers = new ArrayList<>(members); 79  newMembers.add(member); 80  return new PendingFederation(newMembers); 81  } 82  83  /** 84  * Builds a Federation from this PendingFederation 85  * @param creationTime the creation time for the new Federation 86  * @param bridgeConstants to get the bitcoin parameters for the new Federation, 87  * and the keys for creating an ERP Federation 88  * @param activations Activation configuration to check hard fork 89  * @return a Federation 90  */ 91  public Federation buildFederation( 92  Instant creationTime, 93  long blockNumber, 94  BridgeConstants bridgeConstants, 95  ActivationConfig.ForBlock activations 96  ) { 97  if (!this.isComplete()) { 98  throw new IllegalStateException("PendingFederation is incomplete"); 99  } 100  101  if (activations.isActive(ConsensusRule.RSKIP201)) { 102  logger.info("[buildFederation] Going to create an ERP Federation"); 103  return new ErpFederation( 104  members, 105  creationTime, 106  blockNumber, 107  bridgeConstants.getBtcParams(), 108  bridgeConstants.getErpFedPubKeysList(), 109  bridgeConstants.getErpFedActivationDelay() 110  ); 111  } 112  113  return new Federation( 114  members, 115  creationTime, 116  blockNumber, 117  bridgeConstants.getBtcParams() 118  ); 119  } 120  121  @Override 122  public String toString() { 123  return String.format("%d signatures pending federation (%s)", members.size(), isComplete() ? "complete" : "incomplete"); 124  } 125  126  @Override 127  public boolean equals(Object other) { 128  if (this == other) { 129  return true; 130  } 131  132  if (other == null || this.getClass() != other.getClass()) { 133  return false; 134  } 135  136  return this.members.equals(((PendingFederation) other).members); 137  } 138  139  public Keccak256 getHash() { 140  byte[] encoded = BridgeSerializationUtils.serializePendingFederationOnlyBtcKeys(this); 141  return new Keccak256(HashUtil.keccak256(encoded)); 142  } 143  144  @Override 145  public int hashCode() { 146  // Can use java.util.Objects.hash since List<BtcECKey> has a 147  // well-defined hashCode() 148  return Objects.hash(getBtcPublicKeys()); 149  } 150 }