diff --git a/rskj-core/src/main/java/co/rsk/peg/Bridge.java b/rskj-core/src/main/java/co/rsk/peg/Bridge.java index 6af54db63e1..d1ae21c9b51 100644 --- a/rskj-core/src/main/java/co/rsk/peg/Bridge.java +++ b/rskj-core/src/main/java/co/rsk/peg/Bridge.java @@ -37,6 +37,7 @@ import co.rsk.peg.utils.BtcTransactionFormatUtils; import co.rsk.peg.whitelist.LockWhitelistEntry; import co.rsk.peg.whitelist.OneOffWhiteListEntry; +import co.rsk.peg.whitelist.WhitelistResponseCode; import co.rsk.rpc.modules.trace.ProgramSubtrace; import com.google.common.annotations.VisibleForTesting; import org.ethereum.config.Constants; @@ -70,7 +71,7 @@ */ public class Bridge extends PrecompiledContracts.PrecompiledContract { - private static final Logger logger = LoggerFactory.getLogger("bridge"); + private static final Logger logger = LoggerFactory.getLogger(Bridge.class); private static final PanicProcessor panicProcessor = new PanicProcessor(); // No parameters @@ -207,10 +208,6 @@ public class Bridge extends PrecompiledContracts.PrecompiledContract { public static final CallTransaction.Function GET_ACTIVE_POWPEG_REDEEM_SCRIPT = BridgeMethods.GET_ACTIVE_POWPEG_REDEEM_SCRIPT.getFunction(); - public static final int LOCK_WHITELIST_UNLIMITED_MODE_CODE = 0; - public static final int LOCK_WHITELIST_ENTRY_NOT_FOUND_CODE = -1; - public static final int LOCK_WHITELIST_INVALID_ADDRESS_FORMAT_ERROR_CODE = -2; - // Log topics used by Bridge Contract pre RSKIP146 public static final DataWord RELEASE_BTC_TOPIC = DataWord.fromString("release_btc_topic"); public static final DataWord UPDATE_COLLECTIONS_TOPIC = DataWord.fromString("update_collections_topic"); @@ -1056,20 +1053,21 @@ public long getLockWhitelistEntryByAddress(Object[] args) { try { addressBase58 = (String) args[0]; } catch (Exception e) { - logger.warn("Exception in getLockWhitelistEntryByAddress", e); - return LOCK_WHITELIST_INVALID_ADDRESS_FORMAT_ERROR_CODE; + logger.warn("[getLockWhitelistEntryByAddress] Error while parsing the provided address. {}", e.getMessage()); + return WhitelistResponseCode.INVALID_ADDRESS_FORMAT.getCode(); } LockWhitelistEntry entry = bridgeSupport.getLockWhitelistEntryByAddress(addressBase58); if (entry == null) { // Empty string is returned when address is not found - return LOCK_WHITELIST_ENTRY_NOT_FOUND_CODE; + logger.debug("[getLockWhitelistEntryByAddress] Address not found: {}", addressBase58); + return WhitelistResponseCode.ADDRESS_NOT_EXIST.getCode(); } return entry.getClass() == OneOffWhiteListEntry.class ? - ((OneOffWhiteListEntry)entry).maxTransferValue().getValue() : - LOCK_WHITELIST_UNLIMITED_MODE_CODE; + ((OneOffWhiteListEntry)entry).maxTransferValue().getValue() : + WhitelistResponseCode.UNLIMITED_MODE.getCode(); } public Integer addOneOffLockWhitelistAddress(Object[] args) { @@ -1081,7 +1079,7 @@ public Integer addOneOffLockWhitelistAddress(Object[] args) { addressBase58 = (String) args[0]; maxTransferValue = (BigInteger) args[1]; } catch (Exception e) { - logger.warn("Exception in addOneOffLockWhitelistAddress", e); + logger.warn("[addOneOffLockWhitelistAddress] Error while parsing the provided address and max value. {}", e.getMessage()); return 0; } @@ -1095,7 +1093,7 @@ public Integer addUnlimitedLockWhitelistAddress(Object[] args) { try { addressBase58 = (String) args[0]; } catch (Exception e) { - logger.warn("Exception in addUnlimitedLockWhitelistAddress", e); + logger.warn("[addUnlimitedLockWhitelistAddress] Exception in addUnlimitedLockWhitelistAddress", e); return 0; } @@ -1109,7 +1107,7 @@ public Integer removeLockWhitelistAddress(Object[] args) { try { addressBase58 = (String) args[0]; } catch (Exception e) { - logger.warn("Exception in removeLockWhitelistAddress", e); + logger.warn("[removeLockWhitelistAddress] Error while parsing the provided address. {}", e.getMessage()); return 0; } @@ -1119,6 +1117,7 @@ public Integer removeLockWhitelistAddress(Object[] args) { public Integer setLockWhitelistDisableBlockDelay(Object[] args) throws IOException, BlockStoreException { logger.trace("setLockWhitelistDisableBlockDelay"); BigInteger lockWhitelistDisableBlockDelay = (BigInteger) args[0]; + return bridgeSupport.setLockWhitelistDisableBlockDelay(rskTx, lockWhitelistDisableBlockDelay); } diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java b/rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java index b4f777d1c37..1d5da1f6c4d 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java @@ -15,8 +15,6 @@ public enum BridgeStorageIndexKey { OLD_FEDERATION_KEY("oldFederation"), PENDING_FEDERATION_KEY("pendingFederation"), FEDERATION_ELECTION_KEY("federationElection"), - LOCK_ONE_OFF_WHITELIST_KEY("lockWhitelist"), - LOCK_UNLIMITED_WHITELIST_KEY("unlimitedLockWhitelist"), LOCKING_CAP_KEY("lockingCap"), RELEASE_REQUEST_QUEUE_WITH_TXHASH("releaseRequestQueueWithTxHash"), PEGOUTS_WAITING_FOR_CONFIRMATIONS_WITH_TXHASH_KEY("releaseTransactionSetWithTxHash"), diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java b/rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java index ba85bfc198b..217175047d3 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java @@ -29,11 +29,6 @@ import co.rsk.peg.federation.PendingFederation; import co.rsk.peg.flyover.FlyoverFederationInformation; import co.rsk.peg.vote.AddressBasedAuthorizer; -import co.rsk.peg.whitelist.LockWhitelist; -import co.rsk.peg.whitelist.LockWhitelistEntry; -import co.rsk.peg.whitelist.OneOffWhiteListEntry; -import co.rsk.peg.whitelist.UnlimitedWhiteListEntry; -import org.apache.commons.lang3.tuple.Pair; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.core.Repository; import org.ethereum.vm.DataWord; @@ -86,8 +81,6 @@ public class BridgeStorageProvider { private ABICallElection federationElection; - private LockWhitelist lockWhitelist; - private Coin lockingCap; private HashMap> storageVersionEntries; @@ -500,50 +493,6 @@ public ABICallElection getFederationElection(AddressBasedAuthorizer authorizer) return federationElection; } - /** - * Save the lock whitelist - */ - public void saveLockWhitelist() { - if (lockWhitelist == null) { - return; - } - - List oneOffEntries = lockWhitelist.getAll(OneOffWhiteListEntry.class); - safeSaveToRepository(LOCK_ONE_OFF_WHITELIST_KEY, Pair.of(oneOffEntries, lockWhitelist.getDisableBlockHeight()), BridgeSerializationUtils::serializeOneOffLockWhitelist); - - if (activations.isActive(RSKIP87)) { - List unlimitedEntries = lockWhitelist.getAll(UnlimitedWhiteListEntry.class); - safeSaveToRepository(LOCK_UNLIMITED_WHITELIST_KEY, unlimitedEntries, BridgeSerializationUtils::serializeUnlimitedLockWhitelist); - } - } - - public LockWhitelist getLockWhitelist() { - if (lockWhitelist != null) { - return lockWhitelist; - } - - Pair, Integer> oneOffWhitelistAndDisableBlockHeightData = - safeGetFromRepository(LOCK_ONE_OFF_WHITELIST_KEY, - data -> BridgeSerializationUtils.deserializeOneOffLockWhitelistAndDisableBlockHeight(data, networkParameters)); - if (oneOffWhitelistAndDisableBlockHeightData == null) { - lockWhitelist = new LockWhitelist(new HashMap<>()); - return lockWhitelist; - } - - Map whitelistedAddresses = new HashMap<>(); - - whitelistedAddresses.putAll(oneOffWhitelistAndDisableBlockHeightData.getLeft()); - - if (activations.isActive(RSKIP87)) { - whitelistedAddresses.putAll(safeGetFromRepository(LOCK_UNLIMITED_WHITELIST_KEY, - data -> BridgeSerializationUtils.deserializeUnlimitedLockWhitelistEntries(data, networkParameters))); - } - - lockWhitelist = new LockWhitelist(whitelistedAddresses, oneOffWhitelistAndDisableBlockHeightData.getRight()); - - return lockWhitelist; - } - public void saveLockingCap() { if (activations.isActive(RSKIP134)) { safeSaveToRepository(LOCKING_CAP_KEY, this.getLockingCap(), BridgeSerializationUtils::serializeCoin); @@ -636,7 +585,7 @@ private void saveCoinbaseInformations() { return; } - if (coinbaseInformationMap == null || coinbaseInformationMap.size() == 0) { + if (coinbaseInformationMap == null || coinbaseInformationMap.isEmpty()) { return; } coinbaseInformationMap.forEach((Sha256Hash blockHash, CoinbaseInformation data) -> @@ -936,8 +885,6 @@ public void save() throws IOException { saveFederationElection(); - saveLockWhitelist(); - saveLockingCap(); saveHeightBtcTxHashAlreadyProcessed(); diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java b/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java index a027e0fdd17..9da4f79732c 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java @@ -61,7 +61,6 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; -import org.bouncycastle.util.encoders.Hex; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.config.blockchain.upgrades.ConsensusRule; import org.ethereum.core.*; @@ -88,11 +87,6 @@ public class BridgeSupport { public static final int MAX_RELEASE_ITERATIONS = 30; public static final Integer FEDERATION_CHANGE_GENERIC_ERROR_CODE = -10; - public static final Integer LOCK_WHITELIST_GENERIC_ERROR_CODE = -10; - public static final Integer LOCK_WHITELIST_INVALID_ADDRESS_FORMAT_ERROR_CODE = -2; - public static final Integer LOCK_WHITELIST_ALREADY_EXISTS_ERROR_CODE = -1; - public static final Integer LOCK_WHITELIST_UNKNOWN_ERROR_CODE = 0; - public static final Integer LOCK_WHITELIST_SUCCESS_CODE = 1; public static final Integer BTC_TRANSACTION_CONFIRMATION_INEXISTENT_BLOCK_HASH_ERROR_CODE = -1; public static final Integer BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE = -2; @@ -113,8 +107,6 @@ public class BridgeSupport { private static final Logger logger = LoggerFactory.getLogger(BridgeSupport.class); private static final PanicProcessor panicProcessor = new PanicProcessor(); - private static final String INVALID_ADDRESS_FORMAT_MESSAGE = "invalid address format"; - private static final List FEDERATION_CHANGE_FUNCTIONS = Collections.unmodifiableList(Arrays.asList( "create", "add", @@ -123,7 +115,6 @@ public class BridgeSupport { "rollback" )); - private final FeePerKbSupport feePerKbSupport; private final BridgeConstants bridgeConstants; private final BridgeStorageProvider provider; private final Repository rskRepository; @@ -133,6 +124,8 @@ public class BridgeSupport { private final PeginInstructionsProvider peginInstructionsProvider; private final FederationSupport federationSupport; + private final FeePerKbSupport feePerKbSupport; + private final WhitelistSupport whitelistSupport; private final Context btcContext; private final BtcBlockStoreWithCache.Factory btcBlockStoreFactory; @@ -144,19 +137,20 @@ public class BridgeSupport { private final SignatureCache signatureCache; public BridgeSupport( - BridgeConstants bridgeConstants, - BridgeStorageProvider provider, - BridgeEventLogger eventLogger, - BtcLockSenderProvider btcLockSenderProvider, - PeginInstructionsProvider peginInstructionsProvider, - Repository repository, - Block executionBlock, - Context btcContext, - FederationSupport federationSupport, - FeePerKbSupport feePerKbSupport, - BtcBlockStoreWithCache.Factory btcBlockStoreFactory, - ActivationConfig.ForBlock activations, - SignatureCache signatureCache) { + BridgeConstants bridgeConstants, + BridgeStorageProvider provider, + BridgeEventLogger eventLogger, + BtcLockSenderProvider btcLockSenderProvider, + PeginInstructionsProvider peginInstructionsProvider, + Repository repository, + Block executionBlock, + Context btcContext, + FederationSupport federationSupport, + FeePerKbSupport feePerKbSupport, + WhitelistSupport whitelistSupport, + BtcBlockStoreWithCache.Factory btcBlockStoreFactory, + ActivationConfig.ForBlock activations, + SignatureCache signatureCache) { this.rskRepository = repository; this.provider = provider; this.rskExecutionBlock = executionBlock; @@ -167,6 +161,7 @@ public BridgeSupport( this.btcContext = btcContext; this.federationSupport = federationSupport; this.feePerKbSupport = feePerKbSupport; + this.whitelistSupport = whitelistSupport; this.btcBlockStoreFactory = btcBlockStoreFactory; this.activations = activations; this.signatureCache = signatureCache; @@ -196,6 +191,7 @@ ActivationConfig.ForBlock getActivations() { public void save() throws IOException { provider.save(); feePerKbSupport.save(); + whitelistSupport.save(); } /** @@ -713,11 +709,16 @@ protected void processPegoutOrMigration(BtcTransaction btcTx) throws IOException logger.info("[processPegoutOrMigration] BTC Tx {} processed in RSK", btcTx.getHash(false)); } - private boolean shouldProcessPegInVersionLegacy(TxSenderAddressType txSenderAddressType, BtcTransaction btcTx, - Address senderBtcAddress, Coin totalAmount, int height) { + private boolean shouldProcessPegInVersionLegacy( + TxSenderAddressType txSenderAddressType, + BtcTransaction btcTx, + Address senderBtcAddress, + Coin totalAmount, + int height) { + return isTxLockableForLegacyVersion(txSenderAddressType, btcTx, senderBtcAddress) && - verifyLockSenderIsWhitelisted(senderBtcAddress, totalAmount, height) && - verifyLockDoesNotSurpassLockingCap(btcTx, totalAmount); + whitelistSupport.verifyLockSenderIsWhitelisted(senderBtcAddress, totalAmount, height) && + verifyLockDoesNotSurpassLockingCap(btcTx, totalAmount); } protected boolean isTxLockableForLegacyVersion(TxSenderAddressType txSenderAddressType, BtcTransaction btcTx, Address senderBtcAddress) { @@ -1211,7 +1212,7 @@ private void processPegoutsInBatch( if (currentBlockNumber < nextPegoutCreationBlockNumber) { return; } - + List pegoutEntries = pegoutRequests.getEntries(); Coin totalPegoutValue = pegoutEntries .stream() @@ -2429,135 +2430,28 @@ public byte[] getPendingFederatorPublicKeyOfType(int index, FederationMember.Key return federationSupport.getMemberPublicKeyOfType(currentPendingFederation.getMembers(), index, keyType, "Federator"); } - /** - * Returns the lock whitelist size, that is, - * the number of whitelisted addresses - * @return the lock whitelist size - */ public Integer getLockWhitelistSize() { - return provider.getLockWhitelist().getSize(); + return whitelistSupport.getLockWhitelistSize(); } - /** - * Returns the lock whitelist address stored - * at the given index, or null if the - * index is out of bounds - * @param index the index at which to get the address - * @return the base58-encoded address stored at the given index, or null if index is out of bounds - */ public LockWhitelistEntry getLockWhitelistEntryByIndex(int index) { - List entries = provider.getLockWhitelist().getAll(); - - if (index < 0 || index >= entries.size()) { - return null; - } - - return entries.get(index); + return whitelistSupport.getLockWhitelistEntryByIndex(index); } - /** - * - * @param addressBase58 - * @return - */ public LockWhitelistEntry getLockWhitelistEntryByAddress(String addressBase58) { - try { - Address address = getParsedAddress(addressBase58); - return provider.getLockWhitelist().get(address); - } catch (AddressFormatException e) { - logger.warn(INVALID_ADDRESS_FORMAT_MESSAGE, e); - return null; - } + return whitelistSupport.getLockWhitelistEntryByAddress(addressBase58); } - /** - * Adds the given address to the lock whitelist. - * Returns 1 upon success, or -1 if the address was - * already in the whitelist. - * @param addressBase58 the base58-encoded address to add to the whitelist - * @param maxTransferValue the max amount of satoshis enabled to transfer for this address - * @return 1 upon success, -1 if the address was already - * in the whitelist, -2 if address is invalid - * LOCK_WHITELIST_GENERIC_ERROR_CODE otherwise. - */ public Integer addOneOffLockWhitelistAddress(Transaction tx, String addressBase58, BigInteger maxTransferValue) { - try { - Address address = getParsedAddress(addressBase58); - Coin maxTransferValueCoin = Coin.valueOf(maxTransferValue.longValueExact()); - return this.addLockWhitelistAddress(tx, new OneOffWhiteListEntry(address, maxTransferValueCoin)); - } catch (AddressFormatException e) { - logger.warn(INVALID_ADDRESS_FORMAT_MESSAGE, e); - return LOCK_WHITELIST_INVALID_ADDRESS_FORMAT_ERROR_CODE; - } + return whitelistSupport.addOneOffLockWhitelistAddress(tx, addressBase58, maxTransferValue); } public Integer addUnlimitedLockWhitelistAddress(Transaction tx, String addressBase58) { - try { - Address address = getParsedAddress(addressBase58); - return this.addLockWhitelistAddress(tx, new UnlimitedWhiteListEntry(address)); - } catch (AddressFormatException e) { - logger.warn(INVALID_ADDRESS_FORMAT_MESSAGE, e); - return LOCK_WHITELIST_INVALID_ADDRESS_FORMAT_ERROR_CODE; - } - } - - private Integer addLockWhitelistAddress(Transaction tx, LockWhitelistEntry entry) { - if (!isLockWhitelistChangeAuthorized(tx)) { - return LOCK_WHITELIST_GENERIC_ERROR_CODE; - } - - LockWhitelist whitelist = provider.getLockWhitelist(); - - try { - if (whitelist.isWhitelisted(entry.address())) { - return LOCK_WHITELIST_ALREADY_EXISTS_ERROR_CODE; - } - whitelist.put(entry.address(), entry); - return LOCK_WHITELIST_SUCCESS_CODE; - } catch (Exception e) { - logger.error("Unexpected error in addLockWhitelistAddress: {}", e.getMessage()); - panicProcessor.panic("lock-whitelist", e.getMessage()); - return LOCK_WHITELIST_UNKNOWN_ERROR_CODE; - } - } - - private boolean isLockWhitelistChangeAuthorized(Transaction tx) { - AddressBasedAuthorizer authorizer = bridgeConstants.getLockWhitelistChangeAuthorizer(); - - return authorizer.isAuthorized(tx, signatureCache); + return whitelistSupport.addUnlimitedLockWhitelistAddress(tx, addressBase58); } - /** - * Removes the given address from the lock whitelist. - * Returns 1 upon success, or -1 if the address was - * not in the whitelist. - * @param addressBase58 the base58-encoded address to remove from the whitelist - * @return 1 upon success, -1 if the address was not - * in the whitelist, -2 if the address is invalid, - * LOCK_WHITELIST_GENERIC_ERROR_CODE otherwise. - */ public Integer removeLockWhitelistAddress(Transaction tx, String addressBase58) { - if (!isLockWhitelistChangeAuthorized(tx)) { - return LOCK_WHITELIST_GENERIC_ERROR_CODE; - } - - LockWhitelist whitelist = provider.getLockWhitelist(); - - try { - Address address = getParsedAddress(addressBase58); - - if (!whitelist.remove(address)) { - return -1; - } - - return 1; - } catch (AddressFormatException e) { - return -2; - } catch (Exception e) { - logger.error("Unexpected error in removeLockWhitelistAddress: {}", e.getMessage()); - panicProcessor.panic("lock-whitelist", e.getMessage()); - return 0; - } + return whitelistSupport.removeLockWhitelistAddress(tx, addressBase58); } public Coin getFeePerKb() { @@ -2568,27 +2462,10 @@ public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb) { return feePerKbSupport.voteFeePerKbChange(tx, feePerKb, signatureCache); } - /** - * Sets a delay in the BTC best chain to disable lock whitelist - * @param tx current RSK transaction - * @param disableBlockDelayBI block since current BTC best chain height to disable lock whitelist - * @return 1 if it was successful, -1 if a delay was already set, -2 if disableBlockDelay contains an invalid value - */ - public Integer setLockWhitelistDisableBlockDelay(Transaction tx, BigInteger disableBlockDelayBI) throws IOException, BlockStoreException { - if (!isLockWhitelistChangeAuthorized(tx)) { - return LOCK_WHITELIST_GENERIC_ERROR_CODE; - } - LockWhitelist lockWhitelist = provider.getLockWhitelist(); - if (lockWhitelist.isDisableBlockSet()) { - return -1; - } - int disableBlockDelay = disableBlockDelayBI.intValueExact(); - int bestChainHeight = getBtcBlockchainBestChainHeight(); - if (disableBlockDelay + bestChainHeight <= bestChainHeight) { - return -2; - } - lockWhitelist.setDisableBlockHeight(bestChainHeight + disableBlockDelay); - return 1; + public Integer setLockWhitelistDisableBlockDelay(Transaction tx, BigInteger disableBlockDelayBI) + throws IOException, BlockStoreException { + int btcBlockchainBestChainHeight = getBtcBlockchainBestChainHeight(); + return whitelistSupport.setLockWhitelistDisableBlockDelay(tx, disableBlockDelayBI, btcBlockchainBestChainHeight); } public Coin getLockingCap() { @@ -3180,10 +3057,6 @@ private void ensureBtcBlockStore() throws IOException, BlockStoreException { } } - private Address getParsedAddress(String base58Address) throws AddressFormatException { - return Address.fromBase58(btcContext.getParams(), base58Address); - } - private void generateRejectionRelease( BtcTransaction btcTx, Address btcRefundAddress, @@ -3266,24 +3139,6 @@ private void generateRejectionRelease( generateRejectionRelease(btcTx, senderBtcAddress, null, rskTxHash, totalAmount, createWallet); } - private boolean verifyLockSenderIsWhitelisted(Address senderBtcAddress, Coin totalAmount, int height) { - // If the address is not whitelisted, then return the funds - // using the exact same utxos sent to us. - // That is, build a pegout waiting for confirmations and get it in the pegoutWaitingForConfirmations set. - // Otherwise, transfer SBTC to the sender of the BTC - // The RSK account to update is the one that matches the pubkey "spent" on the first bitcoin tx input - LockWhitelist lockWhitelist = provider.getLockWhitelist(); - if (!lockWhitelist.isWhitelistedFor(senderBtcAddress, totalAmount, height)) { - logger.info("Rejecting lock. Address {} is not whitelisted.", senderBtcAddress); - return false; - } - - // Consume this whitelisted address - lockWhitelist.consume(senderBtcAddress); - - return true; - } - private boolean verifyLockDoesNotSurpassLockingCap(BtcTransaction btcTx, Coin totalAmount) { if (!activations.isActive(ConsensusRule.RSKIP134)) { return true; diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeSupportFactory.java b/rskj-core/src/main/java/co/rsk/peg/BridgeSupportFactory.java index 1b8236a354b..b2b260e5890 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeSupportFactory.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeSupportFactory.java @@ -22,6 +22,7 @@ import co.rsk.core.RskAddress; import co.rsk.peg.BtcBlockStoreWithCache.Factory; import co.rsk.peg.btcLockSender.BtcLockSenderProvider; + import co.rsk.peg.feeperkb.FeePerKbStorageProvider; import co.rsk.peg.feeperkb.FeePerKbSupport; import co.rsk.peg.feeperkb.constants.FeePerKbConstants; @@ -33,6 +34,11 @@ import co.rsk.peg.utils.BridgeEventLogger; import co.rsk.peg.utils.BridgeEventLoggerImpl; import co.rsk.peg.utils.BrigeEventLoggerLegacyImpl; +import co.rsk.peg.whitelist.WhitelistStorageProvider; +import co.rsk.peg.whitelist.WhitelistStorageProviderImpl; +import co.rsk.peg.whitelist.WhitelistSupport; +import co.rsk.peg.whitelist.WhitelistSupportImpl; +import co.rsk.peg.whitelist.constants.WhitelistConstants; import java.util.List; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.config.blockchain.upgrades.ConsensusRule; @@ -51,18 +57,24 @@ public class BridgeSupportFactory { private final ActivationConfig activationConfig; private final SignatureCache signatureCache; - public BridgeSupportFactory(Factory btcBlockStoreFactory, - BridgeConstants bridgeConstants, - ActivationConfig activationConfig, - SignatureCache signatureCache) { + public BridgeSupportFactory( + Factory btcBlockStoreFactory, + BridgeConstants bridgeConstants, + ActivationConfig activationConfig, + SignatureCache signatureCache) { + this.btcBlockStoreFactory = btcBlockStoreFactory; this.bridgeConstants = bridgeConstants; this.activationConfig = activationConfig; this.signatureCache = signatureCache; } - public BridgeSupport newInstance(Repository repository, Block executionBlock, - RskAddress contractAddress, List logs) { + public BridgeSupport newInstance( + Repository repository, + Block executionBlock, + RskAddress contractAddress, + List logs) { + ActivationConfig.ForBlock activations = activationConfig.forBlock(executionBlock.getNumber()); Context btcContext = new Context(bridgeConstants.getBtcParams()); @@ -76,12 +88,11 @@ public BridgeSupport newInstance(Repository repository, Block executionBlock, ); FederationSupport federationSupport = new FederationSupport(bridgeConstants, provider, executionBlock, activations); - FeePerKbSupport feePerKbSupport = newFeePerKbSupportInstance(bridgeStorageAccessor, bridgeConstants); + FeePerKbSupport feePerKbSupport = getFeePerKbSupportInstance(bridgeStorageAccessor); + WhitelistSupport whitelistSupport = getWhitelistSupportInstance(bridgeStorageAccessor, activations); - BridgeEventLogger eventLogger; - if (logs == null) { - eventLogger = null; - } else { + BridgeEventLogger eventLogger = null; + if (logs != null) { if (activations.isActive(ConsensusRule.RSKIP146)) { eventLogger = new BridgeEventLoggerImpl(bridgeConstants, activations, logs, signatureCache); } else { @@ -93,25 +104,39 @@ public BridgeSupport newInstance(Repository repository, Block executionBlock, PeginInstructionsProvider peginInstructionsProvider = new PeginInstructionsProvider(); return new BridgeSupport( - bridgeConstants, - provider, - eventLogger, - btcLockSenderProvider, - peginInstructionsProvider, - repository, - executionBlock, - btcContext, - federationSupport, - feePerKbSupport, - btcBlockStoreFactory, - activations, - signatureCache + bridgeConstants, + provider, + eventLogger, + btcLockSenderProvider, + peginInstructionsProvider, + repository, + executionBlock, + btcContext, + federationSupport, + feePerKbSupport, + whitelistSupport, + btcBlockStoreFactory, + activations, + signatureCache ); } - private FeePerKbSupport newFeePerKbSupportInstance(StorageAccessor bridgeStorageAccessor, BridgeConstants bridgeConstants) { + private FeePerKbSupport getFeePerKbSupportInstance(StorageAccessor bridgeStorageAccessor) { FeePerKbConstants feePerKbConstants = bridgeConstants.getFeePerKbConstants(); FeePerKbStorageProvider feePerKbStorageProvider = new FeePerKbStorageProviderImpl(bridgeStorageAccessor); + return new FeePerKbSupportImpl(feePerKbConstants, feePerKbStorageProvider); } + + private WhitelistSupport getWhitelistSupportInstance(StorageAccessor bridgeStorageAccessor, ActivationConfig.ForBlock activations) { + WhitelistConstants whitelistConstants = bridgeConstants.getWhitelistConstants(); + WhitelistStorageProvider whitelistStorageProvider = new WhitelistStorageProviderImpl(bridgeStorageAccessor); + + return new WhitelistSupportImpl( + whitelistConstants, + whitelistStorageProvider, + activations, + signatureCache + ); + } } diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeUtils.java b/rskj-core/src/main/java/co/rsk/peg/BridgeUtils.java index 7a791b68197..c659c232f44 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeUtils.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeUtils.java @@ -34,6 +34,7 @@ import co.rsk.peg.flyover.FlyoverTxResponseCodes; import co.rsk.peg.utils.BtcTransactionFormatUtils; import co.rsk.peg.vote.AddressBasedAuthorizer; +import co.rsk.peg.whitelist.constants.WhitelistConstants; import org.ethereum.config.Constants; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.config.blockchain.upgrades.ConsensusRule; @@ -465,7 +466,8 @@ private static boolean isFromFederationChangeAuthorizedSender(Transaction rskTx, } private static boolean isFromLockWhitelistChangeAuthorizedSender(Transaction rskTx, BridgeConstants bridgeConfiguration, SignatureCache signatureCache) { - AddressBasedAuthorizer authorizer = bridgeConfiguration.getLockWhitelistChangeAuthorizer(); + WhitelistConstants whitelistConstants = bridgeConfiguration.getWhitelistConstants(); + AddressBasedAuthorizer authorizer = whitelistConstants.getLockWhitelistChangeAuthorizer(); return authorizer.isAuthorized(rskTx, signatureCache); } diff --git a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeConstants.java b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeConstants.java index 8c3739a091f..9f90b555af9 100644 --- a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeConstants.java +++ b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeConstants.java @@ -25,6 +25,7 @@ import java.util.List; import co.rsk.peg.feeperkb.constants.FeePerKbConstants; +import co.rsk.peg.whitelist.constants.WhitelistConstants; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.config.blockchain.upgrades.ConsensusRule; @@ -38,6 +39,8 @@ public abstract class BridgeConstants { protected List genesisFederationPublicKeys; protected Instant genesisFederationCreationTime; + protected WhitelistConstants whitelistConstants; + protected int btc2RskMinimumAcceptableConfirmations; protected int btc2RskMinimumAcceptableConfirmationsOnRsk; protected int rsk2BtcMinimumAcceptableConfirmations; @@ -60,8 +63,6 @@ public abstract class BridgeConstants { protected AddressBasedAuthorizer federationChangeAuthorizer; - protected AddressBasedAuthorizer lockWhitelistChangeAuthorizer; - protected AddressBasedAuthorizer increaseLockingCapAuthorizer; protected Coin initialLockingCap; @@ -95,6 +96,8 @@ public NetworkParameters getBtcParams() { public FeePerKbConstants getFeePerKbConstants() { return feePerKbConstants; } + public WhitelistConstants getWhitelistConstants() { return whitelistConstants; } + public String getBtcParamsString() { return btcParamsString; } @@ -149,8 +152,6 @@ public long getFundsMigrationAgeSinceActivationEnd(ActivationConfig.ForBlock act public AddressBasedAuthorizer getFederationChangeAuthorizer() { return federationChangeAuthorizer; } - public AddressBasedAuthorizer getLockWhitelistChangeAuthorizer() { return lockWhitelistChangeAuthorizer; } - public AddressBasedAuthorizer getIncreaseLockingCapAuthorizer() { return increaseLockingCapAuthorizer; } public int getLockingCapIncrementsMultiplier() { return lockingCapIncrementsMultiplier; } diff --git a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeDevNetConstants.java b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeDevNetConstants.java index 5f730c6969b..6982af34ea5 100644 --- a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeDevNetConstants.java +++ b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeDevNetConstants.java @@ -81,17 +81,6 @@ public BridgeDevNetConstants(List federationPublicKeys) { AddressBasedAuthorizer.MinimumRequiredCalculation.MAJORITY ); - // Key generated with GenNodeKey using generator 'auth-lock-whitelist' - List lockWhitelistAuthorizedKeys = Arrays.stream(new String[]{ -// "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - "0447b4aba974c61c6c4045893267346730ec965b308e7ca04a899cf06a901face3106e1eef1bdad04928cd8263522eda4872d20d3fe1ef5e551785c4a482656a6e" - }).map(hex -> ECKey.fromPublicOnly(Hex.decode(hex))).collect(Collectors.toList()); - - lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( - lockWhitelistAuthorizedKeys, - AddressBasedAuthorizer.MinimumRequiredCalculation.ONE - ); - federationActivationAgeLegacy = 10L; federationActivationAge = 20L; @@ -146,6 +135,7 @@ public BridgeDevNetConstants(List federationPublicKeys) { btcHeightWhenPegoutTxIndexActivates = 1_000_000; pegoutTxIndexGracePeriodInBtcBlocks = 4_320; // 30 days in BTC blocks (considering 1 block every 10 minutes) } + public static BridgeDevNetConstants getInstance() { return instance; } diff --git a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeMainNetConstants.java b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeMainNetConstants.java index df065348649..95d3649f271 100644 --- a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeMainNetConstants.java +++ b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeMainNetConstants.java @@ -7,6 +7,7 @@ import co.rsk.peg.vote.AddressBasedAuthorizer; import com.google.common.collect.Lists; import java.time.ZonedDateTime; +import co.rsk.peg.whitelist.constants.WhitelistMainNetConstants; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -19,6 +20,7 @@ public class BridgeMainNetConstants extends BridgeConstants { private BridgeMainNetConstants() { btcParamsString = NetworkParameters.ID_MAINNET; feePerKbConstants = FeePerKbMainNetConstants.getInstance(); + whitelistConstants = WhitelistMainNetConstants.getInstance(); BtcECKey federator0PublicKey = BtcECKey.fromPublicOnly(Hex.decode("03b53899c390573471ba30e5054f78376c5f797fda26dde7a760789f02908cbad2")); BtcECKey federator1PublicKey = BtcECKey.fromPublicOnly(Hex.decode("027319afb15481dbeb3c426bcc37f9a30e7f51ceff586936d85548d9395bcc2344")); @@ -69,15 +71,6 @@ private BridgeMainNetConstants() { AddressBasedAuthorizer.MinimumRequiredCalculation.MAJORITY ); - List lockWhitelistAuthorizedKeys = Arrays.stream(new String[]{ - "041a2449e9d63409c5a8ea3a21c4109b1a6634ee88fd57176d45ea46a59713d5e0b688313cf252128a3e49a0b2effb4b413e5a2525a6fa5894d059f815c9d9efa6" - }).map(hex -> ECKey.fromPublicOnly(Hex.decode(hex))).collect(Collectors.toList()); - - lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( - lockWhitelistAuthorizedKeys, - AddressBasedAuthorizer.MinimumRequiredCalculation.ONE - ); - federationActivationAgeLegacy = 18500L; federationActivationAge = 40320L; diff --git a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeRegTestConstants.java b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeRegTestConstants.java index 884f0252221..e1ecdb85e49 100644 --- a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeRegTestConstants.java +++ b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeRegTestConstants.java @@ -24,6 +24,7 @@ import co.rsk.peg.vote.AddressBasedAuthorizer; import java.nio.charset.StandardCharsets; import java.time.ZonedDateTime; +import co.rsk.peg.whitelist.constants.WhitelistRegTestConstants; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -50,6 +51,7 @@ public class BridgeRegTestConstants extends BridgeConstants { public BridgeRegTestConstants(List federationPublicKeys) { btcParamsString = NetworkParameters.ID_REGTEST; feePerKbConstants = FeePerKbRegTestConstants.getInstance(); + whitelistConstants = WhitelistRegTestConstants.getInstance(); genesisFederationPublicKeys = federationPublicKeys; genesisFederationCreationTime = ZonedDateTime.parse("2016-01-01T00:00:00Z").toInstant(); @@ -88,16 +90,6 @@ public BridgeRegTestConstants(List federationPublicKeys) { fundsMigrationAgeSinceActivationEnd = 150L; specialCaseFundsMigrationAgeSinceActivationEnd = 150L; - // Key generated with GenNodeKey using generator 'auth-lock-whitelist' - List lockWhitelistAuthorizedKeys = Arrays.stream(new String[]{ - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - }).map(hex -> ECKey.fromPublicOnly(Hex.decode(hex))).collect(Collectors.toList()); - - lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( - lockWhitelistAuthorizedKeys, - AddressBasedAuthorizer.MinimumRequiredCalculation.ONE - ); - initialLockingCap = Coin.COIN.multiply(1_000L); // 1_000 BTC lockingCapIncrementsMultiplier = 2; diff --git a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeTestNetConstants.java b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeTestNetConstants.java index 60b4cbcd4a5..67020e573da 100644 --- a/rskj-core/src/main/java/co/rsk/peg/constants/BridgeTestNetConstants.java +++ b/rskj-core/src/main/java/co/rsk/peg/constants/BridgeTestNetConstants.java @@ -22,6 +22,7 @@ import co.rsk.bitcoinj.core.Coin; import co.rsk.bitcoinj.core.NetworkParameters; import co.rsk.peg.vote.AddressBasedAuthorizer; +import co.rsk.peg.whitelist.constants.WhitelistTestNetConstants; import java.time.ZonedDateTime; import java.util.Arrays; import java.util.List; @@ -36,6 +37,7 @@ public class BridgeTestNetConstants extends BridgeConstants { BridgeTestNetConstants() { btcParamsString = NetworkParameters.ID_TESTNET; feePerKbConstants = FeePerKbTestNetConstants.getInstance(); + whitelistConstants = WhitelistTestNetConstants.getInstance(); BtcECKey federator0PublicKey = BtcECKey.fromPublicOnly( Hex.decode("039a060badbeb24bee49eb2063f616c0f0f0765d4ca646b20a88ce828f259fcdb9") @@ -84,16 +86,6 @@ public class BridgeTestNetConstants extends BridgeConstants { AddressBasedAuthorizer.MinimumRequiredCalculation.MAJORITY ); - // Passphrases are kept private - List lockWhitelistAuthorizedKeys = Arrays.stream(new String[]{ - "04bf7e3bca7f7c58326382ed9c2516a8773c21f1b806984bb1c5c33bd18046502d97b28c0ea5b16433fbb2b23f14e95b36209f304841e814017f1ede1ecbdcfce3" - }).map(hex -> ECKey.fromPublicOnly(Hex.decode(hex))).collect(Collectors.toList()); - - lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( - lockWhitelistAuthorizedKeys, - AddressBasedAuthorizer.MinimumRequiredCalculation.ONE - ); - federationActivationAgeLegacy = 60L; federationActivationAge = 120L; diff --git a/rskj-core/src/main/java/co/rsk/peg/storage/FeePerKbStorageIndexKey.java b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageIndexKey.java similarity index 92% rename from rskj-core/src/main/java/co/rsk/peg/storage/FeePerKbStorageIndexKey.java rename to rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageIndexKey.java index eabac1b0166..75d404fc50d 100644 --- a/rskj-core/src/main/java/co/rsk/peg/storage/FeePerKbStorageIndexKey.java +++ b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageIndexKey.java @@ -1,4 +1,4 @@ -package co.rsk.peg.storage; +package co.rsk.peg.feeperkb; import org.ethereum.vm.DataWord; diff --git a/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageProviderImpl.java b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageProviderImpl.java index fd2f715ae12..7552fdf3243 100644 --- a/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageProviderImpl.java +++ b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbStorageProviderImpl.java @@ -8,8 +8,8 @@ import java.util.Optional; -import static co.rsk.peg.storage.FeePerKbStorageIndexKey.FEE_PER_KB_ELECTION; -import static co.rsk.peg.storage.FeePerKbStorageIndexKey.FEE_PER_KB; +import static co.rsk.peg.feeperkb.FeePerKbStorageIndexKey.FEE_PER_KB_ELECTION; +import static co.rsk.peg.feeperkb.FeePerKbStorageIndexKey.FEE_PER_KB; public class FeePerKbStorageProviderImpl implements FeePerKbStorageProvider { private final StorageAccessor bridgeStorageAccessor; diff --git a/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupport.java b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupport.java index 3bc5a63a475..52e92882656 100644 --- a/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupport.java +++ b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupport.java @@ -24,7 +24,5 @@ public interface FeePerKbSupport { */ Integer voteFeePerKbChange(Transaction tx, Coin feePerKb, SignatureCache signatureCache); - void save(); - } diff --git a/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupportImpl.java b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupportImpl.java index 4c9448b5af2..9e7304def68 100644 --- a/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupportImpl.java +++ b/rskj-core/src/main/java/co/rsk/peg/feeperkb/FeePerKbSupportImpl.java @@ -16,19 +16,19 @@ public class FeePerKbSupportImpl implements FeePerKbSupport { private static final Logger logger = LoggerFactory.getLogger(FeePerKbSupportImpl.class); private static final String SET_FEE_PER_KB_ABI_FUNCTION = "setFeePerKb"; - private final FeePerKbStorageProvider provider; - private final FeePerKbConstants feePerKbConstants; + private final FeePerKbStorageProvider storageProvider; + private final FeePerKbConstants constants; - public FeePerKbSupportImpl(FeePerKbConstants feePerKbConstants, FeePerKbStorageProvider provider) { - this.provider = provider; - this.feePerKbConstants = feePerKbConstants; + public FeePerKbSupportImpl(FeePerKbConstants constants, FeePerKbStorageProvider storageProvider) { + this.storageProvider = storageProvider; + this.constants = constants; } @Override public Coin getFeePerKb() { - Optional currentFeePerKb = provider.getFeePerKb(); + Optional currentFeePerKb = storageProvider.getFeePerKb(); - return currentFeePerKb.orElseGet(feePerKbConstants::getGenesisFeePerKb); + return currentFeePerKb.orElseGet(constants::getGenesisFeePerKb); } @Override @@ -36,8 +36,8 @@ public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb, SignatureCache logger.info("[voteFeePerKbChange] Voting new fee per kb value: {}", feePerKb); - AddressBasedAuthorizer authorizer = feePerKbConstants.getFeePerKbChangeAuthorizer(); - Coin maxFeePerKb = feePerKbConstants.getMaxFeePerKb(); + AddressBasedAuthorizer authorizer = constants.getFeePerKbChangeAuthorizer(); + Coin maxFeePerKb = constants.getMaxFeePerKb(); if (!authorizer.isAuthorized(tx, signatureCache)) { logger.warn("[voteFeePerKbChange] Unauthorized signature."); @@ -54,7 +54,7 @@ public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb, SignatureCache return FeePerKbResponseCode.EXCESSIVE_FEE_VOTED.getCode(); } - ABICallElection feePerKbElection = provider.getFeePerKbElection(authorizer); + ABICallElection feePerKbElection = storageProvider.getFeePerKbElection(authorizer); ABICallSpec feeVote = new ABICallSpec(SET_FEE_PER_KB_ABI_FUNCTION, new byte[][]{BridgeSerializationUtils.serializeCoin(feePerKb)}); boolean successfulVote = feePerKbElection.vote(feeVote, tx.getSender(signatureCache)); if (!successfulVote) { @@ -87,7 +87,7 @@ public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb, SignatureCache } logger.info("[voteFeePerKbChange] Fee per kb changed to {}", winnerFee); - provider.setFeePerKb(winnerFee); + storageProvider.setFeePerKb(winnerFee); feePerKbElection.clear(); return FeePerKbResponseCode.SUCCESSFUL_VOTE.getCode(); @@ -95,6 +95,6 @@ public Integer voteFeePerKbChange(Transaction tx, Coin feePerKb, SignatureCache @Override public void save() { - provider.save(); + storageProvider.save(); } } diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistResponseCode.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistResponseCode.java new file mode 100644 index 00000000000..3bb7e3fb5d4 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistResponseCode.java @@ -0,0 +1,23 @@ +package co.rsk.peg.whitelist; + +public enum WhitelistResponseCode { + GENERIC_ERROR(-10), + UNAUTHORIZED_CALLER(-10), + INVALID_ADDRESS_FORMAT(-2), + DISABLE_BLOCK_DELAY_INVALID(-2), + ADDRESS_ALREADY_WHITELISTED(-1), + ADDRESS_NOT_EXIST(-1), + DELAY_ALREADY_SET(-1), + UNLIMITED_MODE(0), + SUCCESS(1); + + private final int code; + + WhitelistResponseCode(int code) { + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageIndexKey.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageIndexKey.java new file mode 100644 index 00000000000..647b3804246 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageIndexKey.java @@ -0,0 +1,21 @@ +package co.rsk.peg.whitelist; + +import org.ethereum.vm.DataWord; + +/** + * Enum for Whitelist storage index key. + */ +public enum WhitelistStorageIndexKey { + LOCK_ONE_OFF("lockWhitelist"), + LOCK_UNLIMITED("unlimitedLockWhitelist"); + + private final String key; + + WhitelistStorageIndexKey(String key) { + this.key = key; + } + + public DataWord getKey() { + return DataWord.fromString(key); + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageProvider.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageProvider.java new file mode 100644 index 00000000000..d6917d52406 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageProvider.java @@ -0,0 +1,14 @@ +package co.rsk.peg.whitelist; + +import co.rsk.bitcoinj.core.NetworkParameters; +import org.ethereum.config.blockchain.upgrades.ActivationConfig; + +/** + * Interface for storage access for whitelisting. + */ +public interface WhitelistStorageProvider { + + void save(ActivationConfig.ForBlock activations); + + LockWhitelist getLockWhitelist(ActivationConfig.ForBlock activations, NetworkParameters networkParameters); +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageProviderImpl.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageProviderImpl.java new file mode 100644 index 00000000000..e997c33ad63 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistStorageProviderImpl.java @@ -0,0 +1,86 @@ +package co.rsk.peg.whitelist; + +import static co.rsk.peg.whitelist.WhitelistStorageIndexKey.LOCK_ONE_OFF; +import static co.rsk.peg.whitelist.WhitelistStorageIndexKey.LOCK_UNLIMITED; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP87; + +import co.rsk.bitcoinj.core.Address; +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.BridgeSerializationUtils; +import co.rsk.peg.storage.StorageAccessor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.config.blockchain.upgrades.ActivationConfig; + +/** + * Implementation of {@link WhitelistStorageProvider} that saves the whitelist to the Storage and + * get the lock Whitelist. + */ +public class WhitelistStorageProviderImpl implements WhitelistStorageProvider { + + private final StorageAccessor bridgeStorageAccessor; + private LockWhitelist lockWhitelist; + + public WhitelistStorageProviderImpl(StorageAccessor bridgeStorageAccessor) { + this.bridgeStorageAccessor = bridgeStorageAccessor; + } + + @Override + public void save(ActivationConfig.ForBlock activations) { + if (lockWhitelist == null) { + return; + } + + List oneOffEntries = lockWhitelist.getAll(OneOffWhiteListEntry.class); + Pair, Integer> pairValue = Pair.of(oneOffEntries, lockWhitelist.getDisableBlockHeight()); + bridgeStorageAccessor.safeSaveToRepository( + LOCK_ONE_OFF.getKey(), + pairValue, + BridgeSerializationUtils::serializeOneOffLockWhitelist + ); + + if (activations.isActive(RSKIP87)) { + List unlimitedEntries = lockWhitelist.getAll(UnlimitedWhiteListEntry.class); + bridgeStorageAccessor.safeSaveToRepository( + LOCK_UNLIMITED.getKey(), + unlimitedEntries, + BridgeSerializationUtils::serializeUnlimitedLockWhitelist + ); + } + } + + @Override + public synchronized LockWhitelist getLockWhitelist(ActivationConfig.ForBlock activations, NetworkParameters networkParameters) { + if (lockWhitelist == null) { + lockWhitelist = initializeLockWhitelist(activations, networkParameters); + } + return lockWhitelist; + } + + private LockWhitelist initializeLockWhitelist(ActivationConfig.ForBlock activations, NetworkParameters networkParameters) { + Pair, Integer> oneOffWhitelistAndDisableBlockHeightData = bridgeStorageAccessor.safeGetFromRepository( + LOCK_ONE_OFF.getKey(), + data -> BridgeSerializationUtils.deserializeOneOffLockWhitelistAndDisableBlockHeight(data, networkParameters) + ); + + if (oneOffWhitelistAndDisableBlockHeightData == null) { + lockWhitelist = new LockWhitelist(new HashMap<>()); + return lockWhitelist; + } + + Map whitelistedAddresses = new HashMap<>(oneOffWhitelistAndDisableBlockHeightData.getLeft()); + + if (activations.isActive(RSKIP87)) { + whitelistedAddresses.putAll(bridgeStorageAccessor.safeGetFromRepository( + LOCK_UNLIMITED.getKey(), + data -> BridgeSerializationUtils.deserializeUnlimitedLockWhitelistEntries(data, networkParameters) + )); + } + + lockWhitelist = new LockWhitelist(whitelistedAddresses, oneOffWhitelistAndDisableBlockHeightData.getRight()); + + return lockWhitelist; + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistSupport.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistSupport.java new file mode 100644 index 00000000000..020e649ea83 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistSupport.java @@ -0,0 +1,93 @@ +package co.rsk.peg.whitelist; + +import co.rsk.bitcoinj.core.Address; +import co.rsk.bitcoinj.core.Coin; +import java.math.BigInteger; +import org.ethereum.core.Transaction; + +/** + * Interface for the whitelist support. This interface is used to add, remove and get whitelist + * entries. + */ +public interface WhitelistSupport { + + /** + * Returns the lock whitelist size, that is, the number of whitelisted addresses + * + * @return the lock whitelist size + */ + int getLockWhitelistSize(); + + /** + * Returns the lock whitelist entry stored at the given index, or null if the index is out of + * bounds + * + * @param index the index at which to get the entry + * @return the whitelist entry stored at the given index, or null if index is out of + * bounds + */ + LockWhitelistEntry getLockWhitelistEntryByIndex(int index); + + /** + * Returns the lock whitelist entry for a given address, or null if the address is not whitelisted + * + * @param addressBase58 the address in base58 format to search for + * @return the whitelist entry for the given address, or null if the addrres is not whitelisted + */ + LockWhitelistEntry getLockWhitelistEntryByAddress(String addressBase58); + + /** + * Adds the given address to the lock whitelist, allowing peg-ins up to certain max value + * + * @param tx the RSK transaction where the call was made + * @param addressBase58 the base58-encoded address to add to the whitelist + * @param maxTransferValue the max amount of satoshis enabled to transfer for this address + * @return 1 SUCCESS, -1 ADDRESS_ALREADY_WHITELISTED, -2 INVALID_ADDRESS_FORMAT, + * -10 UNAUTHORIZED_CALLER. + */ + int addOneOffLockWhitelistAddress(Transaction tx, String addressBase58, BigInteger maxTransferValue); + + /** + * Adds the given address to the lock whitelist, allowing unlimited peg-in value + * + * @param tx the RSK transaction where the call was made + * @param addressBase58 the base58-encoded address to add to the whitelist + * @return 1 SUCCESS, -1 ADDRESS_ALREADY_WHITELISTED, -2 INVALID_ADDRESS_FORMAT, + * -10 UNAUTHORIZED_CALLER. + */ + int addUnlimitedLockWhitelistAddress(Transaction tx, String addressBase58); + + /** + * Removes the given address from the lock whitelist. + * + * @param tx the RSK transaction where the call was made + * @param addressBase58 the base58-encoded address to remove from the whitelist + * @return 1 SUCCESS, -1 ADDRESS_NOT_EXIST, -2 INVALID_ADDRESS_FORMAT, -10 UNAUTHORIZED_CALLER. + */ + int removeLockWhitelistAddress(Transaction tx, String addressBase58); + + /** + * Sets a delay in the BTC best chain to disable lock whitelist + * + * @param tx the RSK transaction where the call was made + * @param disableBlockDelayBI block since current BTC best chain height to disable lock whitelist + * @param btcBlockchainBestChainHeight current btc blockchain best chain height + * @return 1 SUCCESS, -1 DELAY_ALREADY_SET, -2 DISABLE_BLOCK_DELAY_INVALID, -10 UNAUTHORIZED_CALLER + */ + int setLockWhitelistDisableBlockDelay(Transaction tx, BigInteger disableBlockDelayBI, int btcBlockchainBestChainHeight); + + /** + * Checks that a given address is whitelisted and authorized to perform peg-in operations + * + * @param senderBtcAddress the Bitcoin address to check if it's whitelisted + * @param totalAmount the amount that is trying to peg + * @param height the Bitcoin network height where the peg-in transaction was included + * @return true if sender is authorized to peg-in the corresponding amount, false otherwise + */ + boolean verifyLockSenderIsWhitelisted(Address senderBtcAddress, Coin totalAmount, int height); + + /** + * Saves the whitelisted addresses to the storage + */ + void save(); +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistSupportImpl.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistSupportImpl.java new file mode 100644 index 00000000000..ae3bb7de10f --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/WhitelistSupportImpl.java @@ -0,0 +1,174 @@ +package co.rsk.peg.whitelist; + +import static co.rsk.peg.whitelist.WhitelistResponseCode.*; + +import co.rsk.bitcoinj.core.*; +import co.rsk.peg.vote.AddressBasedAuthorizer; +import co.rsk.peg.whitelist.constants.WhitelistConstants; +import java.math.BigInteger; +import java.util.List; +import org.ethereum.config.blockchain.upgrades.ActivationConfig; +import org.ethereum.core.SignatureCache; +import org.ethereum.core.Transaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WhitelistSupportImpl implements WhitelistSupport { + + private static final Logger logger = LoggerFactory.getLogger(WhitelistSupportImpl.class); + private static final String INVALID_ADDRESS_FORMAT_MESSAGE = "invalid address format"; + private final WhitelistConstants constants; + private final WhitelistStorageProvider storageProvider; + private final ActivationConfig.ForBlock activations; + private final SignatureCache signatureCache; + private final NetworkParameters networkParameters; + + public WhitelistSupportImpl( + WhitelistConstants constants, + WhitelistStorageProvider storageProvider, + ActivationConfig.ForBlock activations, + SignatureCache signatureCache) { + + this.constants = constants; + this.storageProvider = storageProvider; + this.activations = activations; + this.signatureCache = signatureCache; + + this.networkParameters = constants.getBtcParams(); + } + + @Override + public int getLockWhitelistSize() { + return storageProvider.getLockWhitelist(activations, networkParameters).getSize(); + } + + @Override + public LockWhitelistEntry getLockWhitelistEntryByIndex(int index) { + List entries = storageProvider.getLockWhitelist( + activations, + networkParameters + ).getAll(); + + if (index < 0 || index >= entries.size()) { + return null; + } + return entries.get(index); + } + + @Override + public LockWhitelistEntry getLockWhitelistEntryByAddress(String addressBase58) { + try { + Address address = Address.fromBase58(networkParameters, addressBase58); + + return storageProvider.getLockWhitelist(activations, networkParameters).get(address); + } catch (AddressFormatException e) { + logger.warn("[getLockWhitelistEntryByAddress] {}", INVALID_ADDRESS_FORMAT_MESSAGE, e); + return null; + } + } + + @Override + public int addOneOffLockWhitelistAddress(Transaction tx, String addressBase58, BigInteger maxTransferValue) { + try { + Address address = Address.fromBase58(networkParameters, addressBase58); + Coin maxTransferValueCoin = Coin.valueOf(maxTransferValue.longValueExact()); + LockWhitelistEntry entry = new OneOffWhiteListEntry(address, maxTransferValueCoin); + + return addLockWhitelistAddress(tx, entry); + } catch (AddressFormatException e) { + logger.warn("[addOneOffLockWhitelistAddress] {}", INVALID_ADDRESS_FORMAT_MESSAGE, e); + return INVALID_ADDRESS_FORMAT.getCode(); + } + } + + @Override + public int addUnlimitedLockWhitelistAddress(Transaction tx, String addressBase58) { + try { + Address address = Address.fromBase58(networkParameters, addressBase58); + LockWhitelistEntry entry = new UnlimitedWhiteListEntry(address); + + return addLockWhitelistAddress(tx, entry); + } catch (AddressFormatException e) { + logger.warn("[addUnlimitedLockWhitelistAddress] {}", INVALID_ADDRESS_FORMAT_MESSAGE, e); + return INVALID_ADDRESS_FORMAT.getCode(); + } + } + + private Integer addLockWhitelistAddress(Transaction tx, LockWhitelistEntry entry) { + if (!isLockWhitelistChangeAuthorized(tx)) { + return UNAUTHORIZED_CALLER.getCode(); + } + + LockWhitelist whitelist = storageProvider.getLockWhitelist(activations, networkParameters); + if (whitelist.isWhitelisted(entry.address())) { + return ADDRESS_ALREADY_WHITELISTED.getCode(); + } + whitelist.put(entry.address(), entry); + return SUCCESS.getCode(); + } + + @Override + public int removeLockWhitelistAddress(Transaction tx, String addressBase58) { + if (!isLockWhitelistChangeAuthorized(tx)) { + return UNAUTHORIZED_CALLER.getCode(); + } + + LockWhitelist whitelist = storageProvider.getLockWhitelist(activations, networkParameters); + try { + Address address = Address.fromBase58(networkParameters, addressBase58); + if (!whitelist.remove(address)) { + return ADDRESS_NOT_EXIST.getCode(); + } + return SUCCESS.getCode(); + } catch (AddressFormatException e) { + logger.error("[removeLockWhitelistAddress] {}", INVALID_ADDRESS_FORMAT_MESSAGE, e); + return INVALID_ADDRESS_FORMAT.getCode(); + } + } + + @Override + public int setLockWhitelistDisableBlockDelay(Transaction tx, BigInteger disableBlockDelayBI, int btcBlockchainBestChainHeight) { + + if (!isLockWhitelistChangeAuthorized(tx)) { + return UNAUTHORIZED_CALLER.getCode(); + } + + LockWhitelist lockWhitelist = storageProvider.getLockWhitelist(activations, networkParameters); + if (lockWhitelist.isDisableBlockSet()) { + return DELAY_ALREADY_SET.getCode(); + } + + int disableBlockDelay = disableBlockDelayBI.intValueExact(); + if (disableBlockDelay + btcBlockchainBestChainHeight <= btcBlockchainBestChainHeight) { + return DISABLE_BLOCK_DELAY_INVALID.getCode(); + } + + lockWhitelist.setDisableBlockHeight(btcBlockchainBestChainHeight + disableBlockDelay); + + return SUCCESS.getCode(); + } + + @Override + public boolean verifyLockSenderIsWhitelisted(Address senderBtcAddress, Coin totalAmount, int height) { + final String ADDRESS_NOT_WHITELISTED_MESSAGE = "Rejected lock. Address is not whitelisted. Address: "; + LockWhitelist lockWhitelist = storageProvider.getLockWhitelist(activations, networkParameters); + if (!lockWhitelist.isWhitelistedFor(senderBtcAddress, totalAmount, height)) { + logger.info("[verifyLockSenderIsWhitelisted] {} {}", ADDRESS_NOT_WHITELISTED_MESSAGE, senderBtcAddress); + return false; + } + // Consume this whitelisted address + lockWhitelist.consume(senderBtcAddress); + + return true; + } + + private boolean isLockWhitelistChangeAuthorized(Transaction tx) { + AddressBasedAuthorizer authorizer = constants.getLockWhitelistChangeAuthorizer(); + return authorizer.isAuthorized(tx, signatureCache); + } + + @Override + public void save() { + storageProvider.save(activations); + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistConstants.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistConstants.java new file mode 100644 index 00000000000..830d93f906e --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistConstants.java @@ -0,0 +1,17 @@ +package co.rsk.peg.whitelist.constants; + +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.vote.AddressBasedAuthorizer; + +public class WhitelistConstants { + protected NetworkParameters btcParams; + protected AddressBasedAuthorizer lockWhitelistChangeAuthorizer; + + public NetworkParameters getBtcParams() { + return btcParams; + } + + public AddressBasedAuthorizer getLockWhitelistChangeAuthorizer() { + return lockWhitelistChangeAuthorizer; + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistMainNetConstants.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistMainNetConstants.java new file mode 100644 index 00000000000..d198f65f7b5 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistMainNetConstants.java @@ -0,0 +1,31 @@ +package co.rsk.peg.whitelist.constants; + +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.vote.AddressBasedAuthorizer; +import java.util.Collections; +import java.util.List; +import org.bouncycastle.util.encoders.Hex; +import org.ethereum.crypto.ECKey; + +public class WhitelistMainNetConstants extends WhitelistConstants { + + private static final WhitelistMainNetConstants instance = new WhitelistMainNetConstants(); + + private WhitelistMainNetConstants() { + btcParams = NetworkParameters.fromID(NetworkParameters.ID_MAINNET); + + ECKey authorizerPublicKey = ECKey.fromPublicOnly(Hex.decode( + "041a2449e9d63409c5a8ea3a21c4109b1a6634ee88fd57176d45ea46a59713d5e0b688313cf252128a3e49a0b2effb4b413e5a2525a6fa5894d059f815c9d9efa6" + )); + List lockWhitelistAuthorizedKeys = Collections.singletonList(authorizerPublicKey); + + lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( + lockWhitelistAuthorizedKeys, + AddressBasedAuthorizer.MinimumRequiredCalculation.ONE + ); + } + + public static WhitelistMainNetConstants getInstance() { + return instance; + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistRegTestConstants.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistRegTestConstants.java new file mode 100644 index 00000000000..34b187f7434 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistRegTestConstants.java @@ -0,0 +1,31 @@ +package co.rsk.peg.whitelist.constants; + +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.vote.AddressBasedAuthorizer; +import java.util.Collections; +import java.util.List; +import org.bouncycastle.util.encoders.Hex; +import org.ethereum.crypto.ECKey; + +public class WhitelistRegTestConstants extends WhitelistConstants { + + private static final WhitelistRegTestConstants instance = new WhitelistRegTestConstants(); + + private WhitelistRegTestConstants() { + btcParams = NetworkParameters.fromID(NetworkParameters.ID_REGTEST); + + ECKey authorizerPublicKey = ECKey.fromPublicOnly(Hex.decode( + "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" + )); + List lockWhitelistAuthorizedKeys = Collections.singletonList(authorizerPublicKey); + + lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( + lockWhitelistAuthorizedKeys, + AddressBasedAuthorizer.MinimumRequiredCalculation.ONE + ); + } + + public static WhitelistRegTestConstants getInstance() { + return instance; + } +} diff --git a/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistTestNetConstants.java b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistTestNetConstants.java new file mode 100644 index 00000000000..5851e5fdec2 --- /dev/null +++ b/rskj-core/src/main/java/co/rsk/peg/whitelist/constants/WhitelistTestNetConstants.java @@ -0,0 +1,31 @@ +package co.rsk.peg.whitelist.constants; + +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.vote.AddressBasedAuthorizer; +import java.util.Collections; +import java.util.List; +import org.bouncycastle.util.encoders.Hex; +import org.ethereum.crypto.ECKey; + +public class WhitelistTestNetConstants extends WhitelistConstants { + + private static final WhitelistTestNetConstants instance = new WhitelistTestNetConstants(); + + private WhitelistTestNetConstants() { + btcParams = NetworkParameters.fromID(NetworkParameters.ID_TESTNET); + + ECKey authorizerPublicKey = ECKey.fromPublicOnly(Hex.decode( + "04bf7e3bca7f7c58326382ed9c2516a8773c21f1b806984bb1c5c33bd18046502d97b28c0ea5b16433fbb2b23f14e95b36209f304841e814017f1ede1ecbdcfce3" + )); + List lockWhitelistAuthorizedKeys = Collections.singletonList(authorizerPublicKey); + + lockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( + lockWhitelistAuthorizedKeys, + AddressBasedAuthorizer.MinimumRequiredCalculation.ONE + ); + } + + public static WhitelistTestNetConstants getInstance() { + return instance; + } +} diff --git a/rskj-core/src/test/java/co/rsk/net/utils/TransactionUtils.java b/rskj-core/src/test/java/co/rsk/net/utils/TransactionUtils.java index eca5f32b372..42ad339284c 100644 --- a/rskj-core/src/test/java/co/rsk/net/utils/TransactionUtils.java +++ b/rskj-core/src/test/java/co/rsk/net/utils/TransactionUtils.java @@ -18,10 +18,15 @@ package co.rsk.net.utils; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import co.rsk.core.RskAddress; import org.bouncycastle.util.encoders.Hex; import org.ethereum.TestUtils; import org.ethereum.config.Constants; import org.ethereum.core.Account; +import org.ethereum.core.SignatureCache; import org.ethereum.core.Transaction; import org.ethereum.crypto.HashUtil; import org.ethereum.util.ByteUtil; @@ -33,7 +38,10 @@ /** * Created by ajlopez on 7/22/2016. */ -public class TransactionUtils { +public final class TransactionUtils { + + private TransactionUtils() { + } public static List getTransactions(int n) { List txs = new ArrayList<>(); @@ -79,4 +87,10 @@ public static Transaction createTransaction(byte[] privateKey, String toAddress, public static Transaction createTransaction() { return getTransactions(1).get(0); } + + public static Transaction getTransactionFromCaller(SignatureCache signatureCache, RskAddress caller) { + Transaction tx = mock(Transaction.class); + when(tx.getSender(signatureCache)).thenReturn(caller); + return tx; + } } diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeStorageProviderTest.java b/rskj-core/src/test/java/co/rsk/peg/BridgeStorageProviderTest.java index 05b6b2c896d..0c8da2c3529 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeStorageProviderTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeStorageProviderTest.java @@ -36,14 +36,9 @@ import co.rsk.peg.federation.*; import co.rsk.peg.flyover.FlyoverFederationInformation; import co.rsk.peg.vote.AddressBasedAuthorizer; -import co.rsk.peg.whitelist.LockWhitelist; -import co.rsk.peg.whitelist.LockWhitelistEntry; -import co.rsk.peg.whitelist.OneOffWhiteListEntry; -import co.rsk.peg.whitelist.UnlimitedWhiteListEntry; import co.rsk.trie.Trie; import co.rsk.trie.TrieStore; import co.rsk.trie.TrieStoreImpl; -import org.apache.commons.lang3.tuple.Pair; import org.bouncycastle.util.encoders.Hex; import org.ethereum.TestUtils; import org.ethereum.config.blockchain.upgrades.ActivationConfig; @@ -70,9 +65,9 @@ import java.math.BigInteger; import java.time.Instant; import java.util.*; -import java.util.concurrent.atomic.AtomicReference; import static co.rsk.peg.federation.FederationFormatVersion.*; +import static org.ethereum.TestUtils.mockAddress; import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -1286,226 +1281,6 @@ void saveFederationElection() { } } - @Test - void getLockWhitelist_nonNullBytes() { - List calls = new ArrayList<>(); - LockWhitelist whitelistMock = new LockWhitelist(new HashMap<>()); - LockWhitelistEntry oneOffEntry = new OneOffWhiteListEntry(getBtcAddress("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), Coin.COIN); - LockWhitelistEntry unlimitedEntry = new UnlimitedWhiteListEntry(getBtcAddress("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")); - whitelistMock.put(oneOffEntry.address(), oneOffEntry); - whitelistMock.put(unlimitedEntry.address(), unlimitedEntry); - Repository repositoryMock = mock(Repository.class); - // Overriding Activation to make sure it serializes the unlimited whitelist data - BridgeStorageProvider storageProvider = new BridgeStorageProvider( - repositoryMock, - mockAddress("aabbccdd"), - bridgeTestnetInstance, - activationsAllForks - ); - - when(repositoryMock.getStorageBytes(any(RskAddress.class), eq(LOCK_ONE_OFF_WHITELIST_KEY.getKey()))) - .then((InvocationOnMock invocation) -> { - calls.add(0); - RskAddress contractAddress = invocation.getArgument(0); - DataWord address = invocation.getArgument(1); - // Make sure the bytes are got from the correct address in the repo - assertArrayEquals(new byte[]{(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd}, contractAddress.getBytes()); - Assertions.assertEquals(LOCK_ONE_OFF_WHITELIST_KEY.getKey(), address); - return new byte[]{(byte)0xaa}; - }); - when(repositoryMock.getStorageBytes(any(RskAddress.class), eq(LOCK_UNLIMITED_WHITELIST_KEY.getKey()))) - .then((InvocationOnMock invocation) -> { - calls.add(0); - RskAddress contractAddress = invocation.getArgument(0); - DataWord address = invocation.getArgument(1); - // Make sure the bytes are got from the correct address in the repo - assertArrayEquals(new byte[]{(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd}, contractAddress.getBytes()); - Assertions.assertEquals(LOCK_UNLIMITED_WHITELIST_KEY.getKey(), address); - return new byte[]{(byte)0xbb}; - }); - try (MockedStatic bridgeSerializationUtilsMocked = mockStatic(BridgeSerializationUtils.class)) { - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.deserializeOneOffLockWhitelistAndDisableBlockHeight(any(byte[].class), any(NetworkParameters.class))) - .then((InvocationOnMock invocation) -> { - calls.add(0); - byte[] data = invocation.getArgument(0); - NetworkParameters parameters = invocation.getArgument(1); - assertEquals(NetworkParameters.fromID(NetworkParameters.ID_TESTNET), parameters); - // Make sure we're deserializing what just came from the repo with the correct AddressBasedAuthorizer - assertArrayEquals(new byte[]{(byte) 0xaa}, data); - HashMap map = new HashMap<>(); - map.put(oneOffEntry.address(), oneOffEntry); - return Pair.of(map, 0); - }); - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.deserializeUnlimitedLockWhitelistEntries(any(byte[].class), any(NetworkParameters.class))) - .then((InvocationOnMock invocation) -> { - calls.add(0); - byte[] unlimitedData = invocation.getArgument(0); - NetworkParameters parameters = invocation.getArgument(1); - assertEquals(NetworkParameters.fromID(NetworkParameters.ID_TESTNET), parameters); - // Make sure we're deserializing what just came from the repo with the correct AddressBasedAuthorizer - assertArrayEquals(new byte[]{(byte) 0xbb}, unlimitedData); - HashMap map = new HashMap<>(); - map.put(unlimitedEntry.address(), unlimitedEntry); - return map; - }); - - assertEquals(whitelistMock.getAll(), storageProvider.getLockWhitelist().getAll()); - assertEquals(4, calls.size()); // 1 for each call to deserializeFederationOnlyBtcKeys & getStorageBytes (we call getStorageBytes twice) - } - } - - @Test - void getLockWhitelist_nullBytes() { - List calls = new ArrayList<>(); - Repository repositoryMock = mock(Repository.class); - BridgeStorageProvider storageProvider = new BridgeStorageProvider(repositoryMock, mockAddress("aabbccdd"), bridgeTestnetInstance, - activationsAllForks); - - when(repositoryMock.getStorageBytes(any(RskAddress.class), any(DataWord.class))) - .then((InvocationOnMock invocation) -> { - calls.add(0); - RskAddress contractAddress = invocation.getArgument(0); - DataWord address = invocation.getArgument(1); - // Make sure the bytes are got from the correct address in the repo - assertArrayEquals(new byte[]{(byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd}, contractAddress.getBytes()); - Assertions.assertEquals(LOCK_ONE_OFF_WHITELIST_KEY.getKey(), address); - return new byte[]{(byte)0xee}; - }); - try (MockedStatic bridgeSerializationUtilsMocked = mockStatic(BridgeSerializationUtils.class)) { - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.deserializeOneOffLockWhitelistAndDisableBlockHeight(any(byte[].class), any(NetworkParameters.class))) - .then((InvocationOnMock invocation) -> { - calls.add(0); - return null; - }); - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.deserializeUnlimitedLockWhitelistEntries(any(byte[].class), any(NetworkParameters.class))) - .then((InvocationOnMock invocation) -> { - calls.add(0); // THIS ONE WON'T BE CALLED BECAUSE ONEOFF IS EMPTY - Assertions.fail("As we don't have data for one-off, we shouldn't have called deserialize unlimited"); - return null; - }); - - LockWhitelist result = storageProvider.getLockWhitelist(); - Assertions.assertNotNull(result); - Assertions.assertEquals(0, result.getSize().intValue()); - Assertions.assertEquals(2, calls.size()); // 1 for each call to deserializeFederationOnlyBtcKeys & getStorageBytes - } - } - - @Test - void saveLockWhitelist() { - LockWhitelist whitelistMock = mock(LockWhitelist.class); - List storageBytesCalls = new ArrayList<>(); - List serializeCalls = new ArrayList<>(); - Repository repositoryMock = mock(Repository.class); - // Overriding activation to make sure it serializes the unlimited whitelist data - BridgeStorageProvider storageProvider = new BridgeStorageProvider(repositoryMock, mockAddress("aabbccdd"), bridgeTestnetInstance, - activationsAllForks); - - try (MockedStatic bridgeSerializationUtilsMocked = mockStatic(BridgeSerializationUtils.class)) { - // Mock the One-Off serialization - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.serializeOneOffLockWhitelist(any(Pair.class))) - .then((InvocationOnMock invocation) -> { - Pair, Integer> data = invocation.getArgument(0); - Assertions.assertEquals(whitelistMock.getAll(OneOffWhiteListEntry.class), data.getLeft()); - Assertions.assertSame(whitelistMock.getDisableBlockHeight(), data.getRight()); - serializeCalls.add(0); - return Hex.decode("ccdd"); - }); - - Mockito - .doAnswer((InvocationOnMock invocation) -> { - storageBytesCalls.add(0); - RskAddress contractAddress = invocation.getArgument(0); - DataWord address = invocation.getArgument(1); - byte[] data = invocation.getArgument(2); - // Make sure the bytes are set to the correct address in the repo and that what's saved is what was serialized - assertArrayEquals(Hex.decode("aabbccdd"), contractAddress.getBytes()); - Assertions.assertEquals(LOCK_ONE_OFF_WHITELIST_KEY.getKey(), address); - assertArrayEquals(Hex.decode("ccdd"), data); - return null; - }) - .when(repositoryMock).addStorageBytes(any(RskAddress.class), eq(LOCK_ONE_OFF_WHITELIST_KEY.getKey()), any(byte[].class)); - - // Mock the Unlimited serialization - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.serializeUnlimitedLockWhitelist(any(List.class))) - .then((InvocationOnMock invocation) -> { - List unlimitedWhiteListEntries = invocation.getArgument(0); - assertEquals(whitelistMock.getAll(UnlimitedWhiteListEntry.class), unlimitedWhiteListEntries); - serializeCalls.add(0); - return Hex.decode("bbcc"); - }); - - Mockito - .doAnswer((InvocationOnMock invocation) -> { - storageBytesCalls.add(0); - RskAddress contractAddress = invocation.getArgument(0); - DataWord address = invocation.getArgument(1); - byte[] data = invocation.getArgument(2); - // Make sure the bytes are set to the correct address in the repo and that what's saved is what was serialized - assertArrayEquals(Hex.decode("aabbccdd"), contractAddress.getBytes()); - Assertions.assertEquals(LOCK_UNLIMITED_WHITELIST_KEY.getKey(), address); - assertArrayEquals(Hex.decode("bbcc"), data); - return null; - }) - .when(repositoryMock).addStorageBytes(any(RskAddress.class), eq(LOCK_UNLIMITED_WHITELIST_KEY.getKey()), any(byte[].class)); - - storageProvider.saveLockWhitelist(); - // Shouldn't have tried to save nor serialize anything - Assertions.assertEquals(0, storageBytesCalls.size()); - Assertions.assertEquals(0, serializeCalls.size()); - TestUtils.setInternalState(storageProvider, "lockWhitelist", whitelistMock); - storageProvider.saveLockWhitelist(); - Assertions.assertEquals(2, storageBytesCalls.size()); - Assertions.assertEquals(2, serializeCalls.size()); - } - } - - @Test - void saveLockWhiteListAfterGetWithData() { - AtomicReference storageCalled = new AtomicReference<>(); - storageCalled.set(Boolean.FALSE); - Repository repositoryMock = mock(Repository.class); - OneOffWhiteListEntry oneOffEntry = new OneOffWhiteListEntry(getBtcAddress("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), Coin.COIN); - BridgeStorageProvider storageProvider = new BridgeStorageProvider(repositoryMock, mockAddress("aabbccdd"), bridgeTestnetInstance, - config.getActivationConfig().forBlock(500L)); - - when(repositoryMock.getStorageBytes(any(RskAddress.class), eq(LOCK_ONE_OFF_WHITELIST_KEY.getKey()))) - .then((InvocationOnMock invocation) -> new byte[]{(byte)0xaa}); - - try (MockedStatic bridgeSerializationUtilsMocked = mockStatic(BridgeSerializationUtils.class)) { - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.deserializeOneOffLockWhitelistAndDisableBlockHeight(any(byte[].class), any(NetworkParameters.class))) - .then((InvocationOnMock invocation) -> { - HashMap map = new HashMap<>(); - map.put(oneOffEntry.address(), oneOffEntry); - return Pair.of(map, 0); - }); - - bridgeSerializationUtilsMocked - .when(() -> BridgeSerializationUtils.serializeOneOffLockWhitelist(any(Pair.class))) - .thenReturn(new byte[]{(byte) 0xee}); - - Mockito - .doAnswer((InvocationOnMock invocation) -> { - storageCalled.set(Boolean.TRUE); - return null; - }) - .when(repositoryMock).addStorageBytes(any(RskAddress.class), eq(LOCK_ONE_OFF_WHITELIST_KEY.getKey()), eq(new byte[]{(byte) 0xee})); - - Assertions.assertTrue(storageProvider.getLockWhitelist().getSize() > 0); - - storageProvider.saveLockWhitelist(); - - Assertions.assertTrue(storageCalled.get()); - } - } - @Test void getReleaseRequestQueue_before_rskip_146_activation() throws IOException { Repository repositoryMock = mock(Repository.class); @@ -3721,16 +3496,6 @@ private BtcTransaction createTransaction() { return tx; } - private RskAddress mockAddress(String addr) { - RskAddress mock = mock(RskAddress.class); - when(mock.getBytes()).thenReturn(Hex.decode(addr)); - return mock; - } - - private Address getBtcAddress(String addr) { - return new Address(networkParameters, Hex.decode(addr)); - } - private Federation buildMockFederation(Integer... pks) { FederationArgs federationArgs = new FederationArgs(FederationTestUtils.getFederationMembersFromPks(pks), Instant.ofEpochMilli(1000), diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportAddSignatureTest.java b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportAddSignatureTest.java index d0b7e26836e..8de5170122d 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportAddSignatureTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportAddSignatureTest.java @@ -1,6 +1,7 @@ package co.rsk.peg; import co.rsk.peg.feeperkb.FeePerKbSupport; +import co.rsk.peg.whitelist.WhitelistSupport; import java.time.Instant; import java.math.BigInteger; import java.util.*; @@ -67,12 +68,14 @@ class BridgeSupportAddSignatureTest { private ActivationConfig.ForBlock activationsBeforeForks; private ActivationConfig.ForBlock activationsAfterForks; private BridgeSupportBuilder bridgeSupportBuilder; + private WhitelistSupport whitelistSupport; @BeforeEach void setUpOnEachTest() { activationsBeforeForks = ActivationConfigsForTest.genesis().forBlock(0); activationsAfterForks = ActivationConfigsForTest.all().forBlock(0); bridgeSupportBuilder = new BridgeSupportBuilder(); + whitelistSupport = mock(WhitelistSupport.class); } @Test @@ -109,6 +112,7 @@ void addSignature_fedPubKey_belongs_to_active_federation() throws Exception { new Context(bridgeRegTestConstants.getBtcParams()), mockFederationSupport, feePerKbSupport, + whitelistSupport, null, null, null @@ -143,6 +147,7 @@ void addSignature_fedPubKey_belongs_to_retiring_federation() throws Exception { new Context(bridgeRegTestConstants.getBtcParams()), mockFederationSupport, feePerKbSupport, + whitelistSupport, null, null, null @@ -208,6 +213,7 @@ void addSignature_fedPubKey_no_belong_to_retiring_or_active_federation() throws new Context(bridgeRegTestConstants.getBtcParams()), mockFederationSupport, feePerKbSupport, + whitelistSupport, null, null, null diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportFlyoverTest.java b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportFlyoverTest.java index 2c4ece49930..545c73d0e76 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportFlyoverTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportFlyoverTest.java @@ -39,6 +39,7 @@ import co.rsk.peg.flyover.FlyoverTxResponseCodes; import co.rsk.peg.pegininstructions.PeginInstructionsProvider; import co.rsk.peg.utils.BridgeEventLogger; +import co.rsk.peg.whitelist.WhitelistSupport; import co.rsk.test.builders.BridgeSupportBuilder; import org.bouncycastle.util.encoders.Hex; import org.ethereum.config.blockchain.upgrades.ActivationConfig; @@ -76,6 +77,7 @@ class BridgeSupportFlyoverTest { protected final NetworkParameters btcRegTestParams = bridgeConstantsRegtest.getBtcParams(); protected final NetworkParameters btcMainnetParams = bridgeConstantsMainnet.getBtcParams(); private BridgeSupportBuilder bridgeSupportBuilder; + private WhitelistSupport whitelistSupport; private ActivationConfig.ForBlock activations; private SignatureCache signatureCache; @@ -86,6 +88,7 @@ void setUpOnEachTest() { when(activations.isActive(ConsensusRule.RSKIP176)).thenReturn(true); when(activations.isActive(ConsensusRule.RSKIP219)).thenReturn(true); bridgeSupportBuilder = new BridgeSupportBuilder(); + whitelistSupport = mock(WhitelistSupport.class); } private BtcTransaction createBtcTransactionWithOutputToAddress(Coin amount, Address btcAddress) { @@ -2839,6 +2842,7 @@ void registerFlyoverBtcTransaction_amount_sent_is_0() btcContext, mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache @@ -2921,6 +2925,7 @@ void registerFlyoverBtcTransaction_surpasses_locking_cap_and_shouldTransfer_is_t btcContext, mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache @@ -3013,6 +3018,7 @@ void registerFlyoverBtcTransaction_surpasses_locking_cap_and_shouldTransfer_is_f btcContext, mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache @@ -3107,6 +3113,7 @@ void registerFlyoverBtcTransaction_surpasses_locking_cap_and_tries_to_register_a btcContext, mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache @@ -3216,6 +3223,7 @@ void registerFlyoverBtcTransaction_OK() btcContext, federationSupportMock, feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache @@ -3326,6 +3334,7 @@ void createFlyoverFederationInformation_OK() { mock(Context.class), federationSupport, feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache @@ -3377,6 +3386,7 @@ void getFlyoverWallet_ok() { btcContext, mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, mock(BtcBlockStoreWithCache.Factory.class), activations, signatureCache diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTestIntegration.java b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportIT.java similarity index 66% rename from rskj-core/src/test/java/co/rsk/peg/BridgeSupportTestIntegration.java rename to rskj-core/src/test/java/co/rsk/peg/BridgeSupportIT.java index 50b7b0d6465..7ed8a5bba42 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTestIntegration.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportIT.java @@ -22,31 +22,17 @@ import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.core.Is.is; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -import co.rsk.bitcoinj.core.Address; -import co.rsk.bitcoinj.core.AddressFormatException; -import co.rsk.bitcoinj.core.BtcBlock; -import co.rsk.bitcoinj.core.BtcBlockChain; -import co.rsk.bitcoinj.core.BtcECKey; -import co.rsk.bitcoinj.core.BtcTransaction; -import co.rsk.bitcoinj.core.CheckpointManager; -import co.rsk.bitcoinj.core.Coin; -import co.rsk.bitcoinj.core.Context; -import co.rsk.bitcoinj.core.NetworkParameters; -import co.rsk.bitcoinj.core.PartialMerkleTree; -import co.rsk.bitcoinj.core.Sha256Hash; -import co.rsk.bitcoinj.core.StoredBlock; -import co.rsk.bitcoinj.core.TransactionInput; -import co.rsk.bitcoinj.core.TransactionOutput; -import co.rsk.bitcoinj.core.UTXO; -import co.rsk.bitcoinj.core.VerificationException; +import co.rsk.bitcoinj.core.*; import co.rsk.bitcoinj.crypto.TransactionSignature; import co.rsk.bitcoinj.script.Script; import co.rsk.bitcoinj.script.ScriptBuilder; import co.rsk.bitcoinj.store.BlockStoreException; import co.rsk.bitcoinj.wallet.Wallet; import co.rsk.blockchain.utils.BlockGenerator; +import co.rsk.peg.bitcoin.BitcoinTestUtils; import co.rsk.peg.constants.BridgeConstants; import co.rsk.peg.constants.BridgeRegTestConstants; import co.rsk.peg.constants.BridgeTestNetConstants; @@ -55,7 +41,9 @@ import co.rsk.crypto.Keccak256; import co.rsk.db.MutableTrieCache; import co.rsk.db.MutableTrieImpl; +import co.rsk.peg.federation.FederationMember.KeyType; import co.rsk.peg.feeperkb.FeePerKbSupport; +import co.rsk.peg.storage.StorageAccessor; import co.rsk.peg.vote.ABICallElection; import co.rsk.peg.vote.ABICallSpec; import co.rsk.peg.bitcoin.MerkleBranch; @@ -65,10 +53,8 @@ import co.rsk.peg.simples.SimpleBlockChain; import co.rsk.peg.utils.BridgeEventLogger; import co.rsk.peg.vote.AddressBasedAuthorizer; -import co.rsk.peg.whitelist.LockWhitelist; -import co.rsk.peg.whitelist.LockWhitelistEntry; -import co.rsk.peg.whitelist.OneOffWhiteListEntry; -import co.rsk.peg.whitelist.UnlimitedWhiteListEntry; +import co.rsk.peg.whitelist.*; +import co.rsk.peg.whitelist.constants.WhitelistMainNetConstants; import co.rsk.test.builders.BlockChainBuilder; import co.rsk.test.builders.BridgeSupportBuilder; import co.rsk.trie.Trie; @@ -84,14 +70,7 @@ import java.security.MessageDigest; import java.security.SecureRandom; import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import org.bouncycastle.util.BigIntegers; @@ -100,13 +79,7 @@ import org.ethereum.config.Constants; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest; -import org.ethereum.core.Block; -import org.ethereum.core.BlockTxSignatureCache; -import org.ethereum.core.Genesis; -import org.ethereum.core.ReceivedTxSignatureCache; -import org.ethereum.core.Repository; -import org.ethereum.core.SignatureCache; -import org.ethereum.core.Transaction; +import org.ethereum.core.*; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.db.MutableRepository; @@ -119,7 +92,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; @@ -134,7 +106,7 @@ @ExtendWith(MockitoExtension.class) // to avoid Junit5 unnecessary stub error due to some setup generalizations @MockitoSettings(strictness = Strictness.LENIENT) -public class BridgeSupportTestIntegration { +public class BridgeSupportIT { private static final co.rsk.core.Coin LIMIT_MONETARY_BASE = new co.rsk.core.Coin(new BigInteger("21000000000000000000000000")); private static final RskAddress contractAddress = PrecompiledContracts.BRIDGE_ADDR; public static final BlockDifficulty TEST_DIFFICULTY = new BlockDifficulty(BigInteger.ONE); @@ -150,18 +122,30 @@ public class BridgeSupportTestIntegration { private BridgeConstants bridgeConstants; private NetworkParameters btcParams; private ActivationConfig.ForBlock activationsBeforeForks; + private ActivationConfig.ForBlock activations; private SignatureCache signatureCache; private FeePerKbSupport feePerKbSupport; + private WhitelistSupport whitelistSupport; + private WhitelistStorageProvider whitelistStorageProvider; @BeforeEach void setUpOnEachTest() { bridgeConstants = BridgeRegTestConstants.getInstance(); btcParams = bridgeConstants.getBtcParams(); activationsBeforeForks = ActivationConfigsForTest.genesis().forBlock(0); + activations = mock(ActivationConfig.ForBlock.class); signatureCache = new BlockTxSignatureCache(new ReceivedTxSignatureCache()); feePerKbSupport = mock(FeePerKbSupport.class); when(feePerKbSupport.getFeePerKb()).thenReturn(Coin.MILLICOIN); + StorageAccessor inMemoryStorage = new InMemoryStorage(); + whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorage); + whitelistSupport = new WhitelistSupportImpl( + WhitelistMainNetConstants.getInstance(), + whitelistStorageProvider, + activations, + signatureCache + ); } @Test @@ -177,8 +161,8 @@ void testInitialChainHeadWithoutBtcCheckpoints() throws Exception { bridgeSupport.getBtcBlockchainBestChainHeight(); StoredBlock chainHead = bridgeSupport.getBtcBlockStore().getChainHead(); - Assertions.assertEquals(0, chainHead.getHeight()); - Assertions.assertEquals(btcParams.getGenesisBlock(), chainHead.getHeader()); + assertEquals(0, chainHead.getHeight()); + assertEquals(btcParams.getGenesisBlock(), chainHead.getHeader()); } @Test @@ -200,7 +184,7 @@ void testInitialChainHeadWithBtcCheckpoints() throws Exception { long time = bridgeSupport.getActiveFederation().getCreationTime().toEpochMilli() - 604800L; // The magic number is a substraction CheckpointManager does when getting the checkpoints. StoredBlock checkpoint = manager.getCheckpointBefore(time); - Assertions.assertEquals(checkpoint.getHeight(), bridgeSupport.getBtcBlockchainBestChainHeight()); + assertEquals(checkpoint.getHeight(), bridgeSupport.getBtcBlockchainBestChainHeight()); } @Test @@ -216,7 +200,7 @@ void feePerKbFromStorageProvider() { BridgeSupport bridgeSupport = getBridgeSupport(provider, track); - Assertions.assertEquals(expected, bridgeSupport.getFeePerKb()); + assertEquals(expected, bridgeSupport.getFeePerKb()); } @Test @@ -232,23 +216,23 @@ void testGetBtcBlockchainBlockLocatorWithoutBtcCheckpoints() throws Exception { bridgeSupport.getBtcBlockchainBestChainHeight(); StoredBlock chainHead = bridgeSupport.getBtcBlockStore().getChainHead(); - Assertions.assertEquals(0, chainHead.getHeight()); - Assertions.assertEquals(btcParams.getGenesisBlock(), chainHead.getHeader()); + assertEquals(0, chainHead.getHeight()); + assertEquals(btcParams.getGenesisBlock(), chainHead.getHeader()); List locator = bridgeSupport.getBtcBlockchainBlockLocator(); - Assertions.assertEquals(1, locator.size()); - Assertions.assertEquals(btcParams.getGenesisBlock().getHash(), locator.get(0)); + assertEquals(1, locator.size()); + assertEquals(btcParams.getGenesisBlock().getHash(), locator.get(0)); List blocks = createBtcBlocks(btcParams, btcParams.getGenesisBlock(), 10); bridgeSupport.receiveHeaders(blocks.toArray(new BtcBlock[]{})); locator = bridgeSupport.getBtcBlockchainBlockLocator(); - Assertions.assertEquals(6, locator.size()); - Assertions.assertEquals(blocks.get(9).getHash(), locator.get(0)); - Assertions.assertEquals(blocks.get(8).getHash(), locator.get(1)); - Assertions.assertEquals(blocks.get(7).getHash(), locator.get(2)); - Assertions.assertEquals(blocks.get(5).getHash(), locator.get(3)); - Assertions.assertEquals(blocks.get(1).getHash(), locator.get(4)); - Assertions.assertEquals(btcParams.getGenesisBlock().getHash(), locator.get(5)); + assertEquals(6, locator.size()); + assertEquals(blocks.get(9).getHash(), locator.get(0)); + assertEquals(blocks.get(8).getHash(), locator.get(1)); + assertEquals(blocks.get(7).getHash(), locator.get(2)); + assertEquals(blocks.get(5).getHash(), locator.get(3)); + assertEquals(blocks.get(1).getHash(), locator.get(4)); + assertEquals(btcParams.getGenesisBlock().getHash(), locator.get(5)); } @Test @@ -260,7 +244,6 @@ void testGetBtcBlockchainBlockLocatorWithBtcCheckpoints() throws Exception { BridgeStorageProvider provider = new BridgeStorageProvider(track, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); List checkpoints = createBtcBlocks(btcParams, btcParams.getGenesisBlock(), 10); - FeePerKbSupport feePerKbSupport = mock(FeePerKbSupport.class); BridgeSupport bridgeSupport = new BridgeSupport( bridgeConstants, provider, @@ -272,6 +255,7 @@ void testGetBtcBlockchainBlockLocatorWithBtcCheckpoints() throws Exception { new Context(bridgeConstants.getBtcParams()), new FederationSupport(bridgeConstants, provider, null, activationsBeforeForks), feePerKbSupport, + whitelistSupport, btcBlockStoreFactory, mock(ActivationConfig.ForBlock.class), signatureCache @@ -286,23 +270,23 @@ InputStream getCheckPoints() { bridgeSupport.getBtcBlockchainBestChainHeight(); StoredBlock chainHead = bridgeSupport.getBtcBlockStore().getChainHead(); - Assertions.assertEquals(10, chainHead.getHeight()); - Assertions.assertEquals(checkpoints.get(9), chainHead.getHeader()); + assertEquals(10, chainHead.getHeight()); + assertEquals(checkpoints.get(9), chainHead.getHeader()); List locator = bridgeSupport.getBtcBlockchainBlockLocator(); - Assertions.assertEquals(1, locator.size()); - Assertions.assertEquals(checkpoints.get(9).getHash(), locator.get(0)); + assertEquals(1, locator.size()); + assertEquals(checkpoints.get(9).getHash(), locator.get(0)); List blocks = createBtcBlocks(btcParams, checkpoints.get(9), 10); bridgeSupport.receiveHeaders(blocks.toArray(new BtcBlock[]{})); locator = bridgeSupport.getBtcBlockchainBlockLocator(); - Assertions.assertEquals(6, locator.size()); - Assertions.assertEquals(blocks.get(9).getHash(), locator.get(0)); - Assertions.assertEquals(blocks.get(8).getHash(), locator.get(1)); - Assertions.assertEquals(blocks.get(7).getHash(), locator.get(2)); - Assertions.assertEquals(blocks.get(5).getHash(), locator.get(3)); - Assertions.assertEquals(blocks.get(1).getHash(), locator.get(4)); - Assertions.assertEquals(checkpoints.get(9).getHash(), locator.get(5)); + assertEquals(6, locator.size()); + assertEquals(blocks.get(9).getHash(), locator.get(0)); + assertEquals(blocks.get(8).getHash(), locator.get(1)); + assertEquals(blocks.get(7).getHash(), locator.get(2)); + assertEquals(blocks.get(5).getHash(), locator.get(3)); + assertEquals(blocks.get(1).getHash(), locator.get(4)); + assertEquals(checkpoints.get(9).getHash(), locator.get(5)); } private List createBtcBlocks(NetworkParameters _networkParameters, BtcBlock parent, int numberOfBlocksToCreate) { @@ -405,12 +389,12 @@ void callUpdateCollectionsFundsEnoughForJustTheSmallerTx() throws IOException { provider0.getReleaseRequestQueue().add(new BtcECKey().toAddress(btcParams), Coin.valueOf(10, 0)); provider0.getNewFederationBtcUTXOs().add(new UTXO( - PegTestUtils.createHash(), - 1, - Coin.valueOf(12, 0), - 0, - false, - ScriptBuilder.createOutputScript(genesisFederation.getAddress()) + BitcoinTestUtils.createHash(1), + 1, + Coin.valueOf(12, 0), + 0, + false, + ScriptBuilder.createOutputScript(genesisFederation.getAddress()) )); provider0.save(); @@ -452,13 +436,13 @@ void callUpdateCollectionsFundsEnoughForJustTheSmallerTx() throws IOException { // reusing same bridge storage configuration as the height doesn't affect it for releases BridgeStorageProvider provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(2, provider.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(1, provider.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); + assertEquals(2, provider.getReleaseRequestQueue().getEntries().size()); + assertEquals(1, provider.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); // Check value sent to user is 10 BTC minus fee - Assertions.assertEquals(Coin.valueOf(999962800L), provider.getPegoutsWaitingForConfirmations().getEntries().iterator().next().getBtcTransaction().getOutput(0).getValue()); + assertEquals(Coin.valueOf(999962800L), provider.getPegoutsWaitingForConfirmations().getEntries().iterator().next().getBtcTransaction().getOutput(0).getValue()); // Check the wallet has been emptied - Assertions.assertTrue(provider.getNewFederationBtcUTXOs().isEmpty()); + assertTrue(provider.getNewFederationBtcUTXOs().isEmpty()); } @Test @@ -474,12 +458,12 @@ void callUpdateCollectionsThrowsCouldNotAdjustDownwards() throws IOException { provider0.getReleaseRequestQueue().add(new BtcECKey().toAddress(btcParams), Coin.valueOf(37500)); provider0.getNewFederationBtcUTXOs().add(new UTXO( - PegTestUtils.createHash(), - 1, - Coin.valueOf(1000000), - 0, - false, - ScriptBuilder.createOutputScript(genesisFederation.getAddress()) + BitcoinTestUtils.createHash(1), + 1, + Coin.valueOf(1000000), + 0, + false, + ScriptBuilder.createOutputScript(genesisFederation.getAddress()) )); provider0.save(); @@ -534,11 +518,11 @@ void callUpdateCollectionsThrowsCouldNotAdjustDownwards() throws IOException { // reusing same bridge storage configuration as it doesn't affect the release transactions BridgeStorageProvider provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(1, provider.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); + assertEquals(1, provider.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); // Check the wallet has not been emptied - Assertions.assertFalse(provider.getNewFederationBtcUTXOs().isEmpty()); + assertFalse(provider.getNewFederationBtcUTXOs().isEmpty()); } @Test @@ -554,12 +538,12 @@ void callUpdateCollectionsThrowsExceededMaxTransactionSize() throws IOException provider0.getReleaseRequestQueue().add(new BtcECKey().toAddress(btcParams), Coin.COIN.multiply(7)); for (int i = 0; i < 2000; i++) { provider0.getNewFederationBtcUTXOs().add(new UTXO( - PegTestUtils.createHash(), - 1, - Coin.CENT, - 0, - false, - ScriptBuilder.createOutputScript(genesisFederation.getAddress()) + BitcoinTestUtils.createHash(1), + 1, + Coin.CENT, + 0, + false, + ScriptBuilder.createOutputScript(genesisFederation.getAddress()) )); } @@ -616,11 +600,11 @@ void callUpdateCollectionsThrowsExceededMaxTransactionSize() throws IOException // keeping same bridge storage configuration BridgeStorageProvider provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(1, provider.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); + assertEquals(1, provider.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); // Check the wallet has not been emptied - Assertions.assertFalse(provider.getNewFederationBtcUTXOs().isEmpty()); + assertFalse(provider.getNewFederationBtcUTXOs().isEmpty()); } @Test @@ -744,7 +728,14 @@ void callUpdateCollectionsChangeGetsOutOfDust() throws IOException { BridgeStorageProvider provider0 = new BridgeStorageProvider(track, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); provider0.getReleaseRequestQueue().add(new BtcECKey().toAddress(btcParams), Coin.COIN); - provider0.getNewFederationBtcUTXOs().add(new UTXO(PegTestUtils.createHash(), 1, Coin.COIN.add(Coin.valueOf(100)), 0, false, ScriptBuilder.createOutputScript(genesisFederation.getAddress()))); + provider0.getNewFederationBtcUTXOs().add(new UTXO( + BitcoinTestUtils.createHash(1), + 1, + Coin.COIN.add(Coin.valueOf(100)), + 0, + false, + ScriptBuilder.createOutputScript(genesisFederation.getAddress()) + )); provider0.save(); @@ -787,13 +778,13 @@ void callUpdateCollectionsChangeGetsOutOfDust() throws IOException { // reusing same bridge storage configuration BridgeStorageProvider provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(0, provider.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(1, provider.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); - Assertions.assertEquals(LIMIT_MONETARY_BASE.subtract(co.rsk.core.Coin.fromBitcoin(Coin.valueOf(2600))), repository.getBalance(PrecompiledContracts.BRIDGE_ADDR)); - Assertions.assertEquals(co.rsk.core.Coin.fromBitcoin(Coin.valueOf(2600)), repository.getBalance(BridgeSupport.BURN_ADDRESS)); + assertEquals(0, provider.getReleaseRequestQueue().getEntries().size()); + assertEquals(1, provider.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); + assertEquals(LIMIT_MONETARY_BASE.subtract(co.rsk.core.Coin.fromBitcoin(Coin.valueOf(2600))), repository.getBalance(PrecompiledContracts.BRIDGE_ADDR)); + assertEquals(co.rsk.core.Coin.fromBitcoin(Coin.valueOf(2600)), repository.getBalance(BridgeSupport.BURN_ADDRESS)); // Check the wallet has been emptied - Assertions.assertTrue(provider.getNewFederationBtcUTXOs().isEmpty()); + assertTrue(provider.getNewFederationBtcUTXOs().isEmpty()); } @Test @@ -871,9 +862,9 @@ void callUpdateCollectionsWithTransactionsWaitingForConfirmationWithEnoughConfir BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(2, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(1, provider2.getPegoutsWaitingForSignatures().size()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(2, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(1, provider2.getPegoutsWaitingForSignatures().size()); } } @@ -897,14 +888,14 @@ void sendOrphanBlockHeader() throws IOException, BlockStoreException { BridgeSupport bridgeSupport = getBridgeSupport(provider, track, mockFactory, activations); co.rsk.bitcoinj.core.BtcBlock block = new co.rsk.bitcoinj.core.BtcBlock( - btcParams, - 1, - PegTestUtils.createHash(1), - PegTestUtils.createHash(2), - 1, - btcParams.getGenesisBlock().getDifficultyTarget(), - 1, - new ArrayList<>() + btcParams, + 1, + BitcoinTestUtils.createHash(1), + BitcoinTestUtils.createHash(2), + 1, + btcParams.getGenesisBlock().getDifficultyTarget(), + 1, + new ArrayList<>() ); co.rsk.bitcoinj.core.BtcBlock[] headers = new co.rsk.bitcoinj.core.BtcBlock[1]; headers[0] = block; @@ -914,7 +905,7 @@ void sendOrphanBlockHeader() throws IOException, BlockStoreException { track.commit(); - Assertions.assertNull(btcBlockStore.get(block.getHash())); + assertNull(btcBlockStore.get(block.getHash())); } @Test @@ -925,10 +916,10 @@ void addBlockHeaderToBlockchain() throws IOException, BlockStoreException { Context btcContext = new Context(btcParams); BridgeStorageProvider provider = new BridgeStorageProvider( - track, - contractAddress, - bridgeConstants, - activationsBeforeForks + track, + contractAddress, + bridgeConstants, + activationsBeforeForks ); BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(bridgeConstants.getBtcParams()); BtcBlockStoreWithCache btcBlockStore = btcBlockStoreFactory.newInstance(track, bridgeConstants, provider, activations); @@ -939,12 +930,12 @@ void addBlockHeaderToBlockchain() throws IOException, BlockStoreException { BtcBlockChain btcBlockChain = new SimpleBlockChain(btcContext, btcBlockStore); TestUtils.setInternalState(bridgeSupport, "btcBlockChain", btcBlockChain); - Sha256Hash merkleRoot = PegTestUtils.createHash(2); + Sha256Hash merkleRoot = BitcoinTestUtils.createHash(2); co.rsk.bitcoinj.core.BtcBlock prevBlock = new co.rsk.bitcoinj.core.BtcBlock( btcParams, 1, - PegTestUtils.createHash(1), // hash from its previous block + BitcoinTestUtils.createHash(1), // hash from its previous block merkleRoot, 1, 1, @@ -958,14 +949,14 @@ void addBlockHeaderToBlockchain() throws IOException, BlockStoreException { track.save(); co.rsk.bitcoinj.core.BtcBlock block = new co.rsk.bitcoinj.core.BtcBlock( - btcParams, - 1, - prevBlock.getHash(), - PegTestUtils.createHash(2), - 1, - 1, - 1, - new ArrayList<>() + btcParams, + 1, + prevBlock.getHash(), + BitcoinTestUtils.createHash(2), + 1, + 1, + 1, + new ArrayList<>() ); co.rsk.bitcoinj.core.BtcBlock[] headers = new co.rsk.bitcoinj.core.BtcBlock[1]; headers[0] = block; @@ -975,7 +966,7 @@ void addBlockHeaderToBlockchain() throws IOException, BlockStoreException { track.commit(); - Assertions.assertNotNull(btcBlockStore.get(block.getHash())); + assertNotNull(btcBlockStore.get(block.getHash())); } @Test @@ -1006,9 +997,9 @@ void releaseBtcWithDustOutput() throws AddressFormatException, IOException { BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(0, provider.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertTrue(provider.getPegoutsWaitingForSignatures().isEmpty()); + assertEquals(0, provider.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertTrue(provider.getPegoutsWaitingForSignatures().isEmpty()); } @Test @@ -1039,9 +1030,9 @@ void releaseBtc() throws AddressFormatException, IOException { BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(1, provider.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(1, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertTrue(provider.getPegoutsWaitingForSignatures().isEmpty()); + assertEquals(1, provider.getReleaseRequestQueue().getEntries().size()); + assertEquals(1, provider2.getReleaseRequestQueue().getEntries().size()); + assertTrue(provider.getPegoutsWaitingForSignatures().isEmpty()); } @Test @@ -1095,11 +1086,11 @@ void registerBtcTransactionOfAlreadyProcessedTransaction() throws BlockStoreExce BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); + assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); } @Test @@ -1116,7 +1107,7 @@ void registerBtcTransactionOfTransactionNotInMerkleTree() throws BlockStoreExcep byte[] bits = new byte[1]; bits[0] = 0x01; List hashes = new ArrayList<>(); - hashes.add(PegTestUtils.createHash()); + hashes.add(BitcoinTestUtils.createHash(5)); PartialMerkleTree pmt = new PartialMerkleTree(btcParams, bits, hashes, 1); @@ -1127,11 +1118,11 @@ void registerBtcTransactionOfTransactionNotInMerkleTree() throws BlockStoreExcep BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); + assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); } @Test @@ -1159,11 +1150,11 @@ void registerBtcTransactionOfTransactionInMerkleTreeWithNegativeHeight() throws BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); + assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); } @Test @@ -1191,15 +1182,15 @@ void registerBtcTransactionOfTransactionInMerkleTreeWithNotEnoughtHeight() throw BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); + assertTrue(provider2.getNewFederationBtcUTXOs().isEmpty()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); } @Test - void registerBtcTransactionWithoutInputs() throws IOException, BlockStoreException, BridgeIllegalArgumentException { + void registerBtcTransactionWithoutInputs() throws BlockStoreException { NetworkParameters btcParams = NetworkParameters.fromID(NetworkParameters.ID_REGTEST); BtcTransaction noInputsTx = new BtcTransaction(btcParams); @@ -1245,14 +1236,14 @@ void registerBtcTransactionTxNotLockNorReleaseTx() throws BlockStoreException, A BtcTransaction tx = new BtcTransaction(btcParams); Address address = ScriptBuilder.createP2SHOutputScript(2, Lists.newArrayList(new BtcECKey(), new BtcECKey(), new BtcECKey())).getToAddress(btcParams); tx.addOutput(Coin.COIN, address); - tx.addInput(PegTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, new BtcECKey())); + tx.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, new BtcECKey())); Context btcContext = new Context(btcParams); BridgeStorageProvider provider = new BridgeStorageProvider( - track, - contractAddress, - bridgeConstants, - activationsBeforeForks + track, + contractAddress, + bridgeConstants, + activationsBeforeForks ); BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(bridgeConstants.getBtcParams()); BtcBlockStoreWithCache btcBlockStore = btcBlockStoreFactory.newInstance(track, bridgeConstants, provider, activations); @@ -1272,14 +1263,14 @@ void registerBtcTransactionTxNotLockNorReleaseTx() throws BlockStoreException, A Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(hashlist); co.rsk.bitcoinj.core.BtcBlock block = new co.rsk.bitcoinj.core.BtcBlock( - btcParams, - 1, - PegTestUtils.createHash(1), - merkleRoot, - 1, - 1, - 1, - new ArrayList<>() + btcParams, + 1, + BitcoinTestUtils.createHash(1), + merkleRoot, + 1, + 1, + 1, + new ArrayList<>() ); btcBlockChain.add(block); @@ -1291,12 +1282,12 @@ void registerBtcTransactionTxNotLockNorReleaseTx() throws BlockStoreException, A BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(0, provider2.getNewFederationBtcUTXOs().size()); + assertEquals(0, provider2.getNewFederationBtcUTXOs().size()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertFalse(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); } @Test @@ -1371,14 +1362,14 @@ void registerBtcTransactionReleaseTx() throws BlockStoreException, AddressFormat Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(hashlist); co.rsk.bitcoinj.core.BtcBlock registerHeader = new co.rsk.bitcoinj.core.BtcBlock( - btcParams, - 1, - PegTestUtils.createHash(1), - merkleRoot, - 1, - 1, - 1, - new ArrayList<>() + btcParams, + 1, + BitcoinTestUtils.createHash(1), + merkleRoot, + 1, + 1, + 1, + new ArrayList<>() ); int height = 30; @@ -1389,17 +1380,17 @@ void registerBtcTransactionReleaseTx() throws BlockStoreException, AddressFormat track.commit(); - Assertions.assertEquals(LIMIT_MONETARY_BASE, repository.getBalance(PrecompiledContracts.BRIDGE_ADDR)); + assertEquals(LIMIT_MONETARY_BASE, repository.getBalance(PrecompiledContracts.BRIDGE_ADDR)); BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(1, provider2.getNewFederationBtcUTXOs().size()); - Assertions.assertEquals(Coin.COIN, provider2.getNewFederationBtcUTXOs().get(0).getValue()); + assertEquals(1, provider2.getNewFederationBtcUTXOs().size()); + assertEquals(Coin.COIN, provider2.getNewFederationBtcUTXOs().get(0).getValue()); - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx.getHash()).isPresent()); } @Test @@ -1504,14 +1495,14 @@ void registerBtcTransactionMigrationTx() throws BlockStoreException, AddressForm Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(hashlist); co.rsk.bitcoinj.core.BtcBlock registerHeader = new co.rsk.bitcoinj.core.BtcBlock( - btcParams, - 1, - PegTestUtils.createHash(1), - merkleRoot, - 1, - 1, - 1, - new ArrayList<>() + btcParams, + 1, + BitcoinTestUtils.createHash(1), + merkleRoot, + 1, + 1, + 1, + new ArrayList<>() ); int height = 30; @@ -1631,12 +1622,10 @@ void registerBtcTransactionWithCrossFederationsChange() throws Exception { @Test void registerBtcTransactionLockTxWhitelisted() throws Exception { - ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); - - List federation1Keys = Arrays.asList(new BtcECKey[]{ + List federation1Keys = Arrays.asList( BtcECKey.fromPrivate(Hex.decode("fa01")), - BtcECKey.fromPrivate(Hex.decode("fa02")), - }); + BtcECKey.fromPrivate(Hex.decode("fa02")) + ); federation1Keys.sort(BtcECKey.PUBKEY_COMPARATOR); List federation1Members = FederationTestUtils.getFederationMembersWithBtcKeys(federation1Keys); @@ -1649,11 +1638,11 @@ void registerBtcTransactionLockTxWhitelisted() throws Exception { federation1Args ); - List federation2Keys = Arrays.asList(new BtcECKey[]{ + List federation2Keys = Arrays.asList( BtcECKey.fromPrivate(Hex.decode("fb01")), BtcECKey.fromPrivate(Hex.decode("fb02")), - BtcECKey.fromPrivate(Hex.decode("fb03")), - }); + BtcECKey.fromPrivate(Hex.decode("fb03")) + ); federation2Keys.sort(BtcECKey.PUBKEY_COMPARATOR); List federation2Members = FederationTestUtils.getFederationMembersWithBtcKeys(federation2Keys); @@ -1676,13 +1665,13 @@ void registerBtcTransactionLockTxWhitelisted() throws Exception { BtcTransaction tx1 = new BtcTransaction(btcParams); tx1.addOutput(Coin.COIN.multiply(5), federation1.getAddress()); BtcECKey srcKey1 = new BtcECKey(); - tx1.addInput(PegTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey1)); + tx1.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey1)); // Second transaction goes only to the second federation BtcTransaction tx2 = new BtcTransaction(btcParams); tx2.addOutput(Coin.COIN.multiply(10), federation2.getAddress()); BtcECKey srcKey2 = new BtcECKey(); - tx2.addInput(PegTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey2)); + tx2.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey2)); // Third transaction has one output to each federation // Lock is expected to be done accordingly and utxos assigned accordingly as well @@ -1690,21 +1679,21 @@ void registerBtcTransactionLockTxWhitelisted() throws Exception { tx3.addOutput(Coin.COIN.multiply(2), federation1.getAddress()); tx3.addOutput(Coin.COIN.multiply(3), federation2.getAddress()); BtcECKey srcKey3 = new BtcECKey(); - tx3.addInput(PegTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey3)); + tx3.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey3)); BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); BridgeStorageProvider provider = new BridgeStorageProvider( - track, - contractAddress, - bridgeConstants, - activationsBeforeForks + track, + contractAddress, + bridgeConstants, + activationsBeforeForks ); provider.setNewFederation(federation1); provider.setOldFederation(federation2); // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, btcParams); Address address1 = srcKey1.toAddress(btcParams); Address address2 = srcKey2.toAddress(btcParams); Address address3 = srcKey3.toAddress(btcParams); @@ -1716,14 +1705,14 @@ void registerBtcTransactionLockTxWhitelisted() throws Exception { when(mockFactory.newInstance(track, bridgeConstants, provider, activations)).thenReturn(btcBlockStore); BridgeSupport bridgeSupport = getBridgeSupport( - bridgeConstants, - provider, - track, - mock(BridgeEventLogger.class), - new BtcLockSenderProvider(), - executionBlock, - mockFactory, - activations + bridgeConstants, + provider, + track, + mock(BridgeEventLogger.class), + new BtcLockSenderProvider(), + executionBlock, + mockFactory, + activations ); byte[] bits = new byte[1]; bits[0] = 0x3f; @@ -1737,14 +1726,14 @@ void registerBtcTransactionLockTxWhitelisted() throws Exception { Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(hashlist); co.rsk.bitcoinj.core.BtcBlock registerHeader = new co.rsk.bitcoinj.core.BtcBlock( - btcParams, - 1, - PegTestUtils.createHash(1), - merkleRoot, - 1, - 1, - 1, - new ArrayList<>() + btcParams, + 1, + BitcoinTestUtils.createHash(1), + merkleRoot, + 1, + 1, + 1, + new ArrayList<>() ); int height = 30; @@ -1770,46 +1759,46 @@ void registerBtcTransactionLockTxWhitelisted() throws Exception { RskAddress srcKey2RskAddress = new RskAddress(org.ethereum.crypto.ECKey.fromPrivate(srcKey2.getPrivKey()).getAddress()); RskAddress srcKey3RskAddress = new RskAddress(org.ethereum.crypto.ECKey.fromPrivate(srcKey3.getPrivKey()).getAddress()); - Assertions.assertEquals(amountToHaveBeenCreditedToSrc1, repository.getBalance(srcKey1RskAddress)); - Assertions.assertEquals(amountToHaveBeenCreditedToSrc2, repository.getBalance(srcKey2RskAddress)); - Assertions.assertEquals(amountToHaveBeenCreditedToSrc3, repository.getBalance(srcKey3RskAddress)); - Assertions.assertEquals(LIMIT_MONETARY_BASE.subtract(totalAmountExpectedToHaveBeenLocked), repository.getBalance(PrecompiledContracts.BRIDGE_ADDR)); + assertEquals(amountToHaveBeenCreditedToSrc1, repository.getBalance(srcKey1RskAddress)); + assertEquals(amountToHaveBeenCreditedToSrc2, repository.getBalance(srcKey2RskAddress)); + assertEquals(amountToHaveBeenCreditedToSrc3, repository.getBalance(srcKey3RskAddress)); + assertEquals(LIMIT_MONETARY_BASE.subtract(totalAmountExpectedToHaveBeenLocked), repository.getBalance(PrecompiledContracts.BRIDGE_ADDR)); BridgeStorageProvider provider2 = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants, activationsBeforeForks); - Assertions.assertEquals(2, provider2.getNewFederationBtcUTXOs().size()); - Assertions.assertEquals(2, provider2.getOldFederationBtcUTXOs().size()); - Assertions.assertEquals(Coin.COIN.multiply(5), provider2.getNewFederationBtcUTXOs().get(0).getValue()); - Assertions.assertEquals(Coin.COIN.multiply(2), provider2.getNewFederationBtcUTXOs().get(1).getValue()); - Assertions.assertEquals(Coin.COIN.multiply(10), provider2.getOldFederationBtcUTXOs().get(0).getValue()); - Assertions.assertEquals(Coin.COIN.multiply(3), provider2.getOldFederationBtcUTXOs().get(1).getValue()); - - Assertions.assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); - Assertions.assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); - Assertions.assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx1.getHash()).isPresent()); - Assertions.assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx2.getHash()).isPresent()); - Assertions.assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx3.getHash()).isPresent()); + assertEquals(2, provider2.getNewFederationBtcUTXOs().size()); + assertEquals(2, provider2.getOldFederationBtcUTXOs().size()); + assertEquals(Coin.COIN.multiply(5), provider2.getNewFederationBtcUTXOs().get(0).getValue()); + assertEquals(Coin.COIN.multiply(2), provider2.getNewFederationBtcUTXOs().get(1).getValue()); + assertEquals(Coin.COIN.multiply(10), provider2.getOldFederationBtcUTXOs().get(0).getValue()); + assertEquals(Coin.COIN.multiply(3), provider2.getOldFederationBtcUTXOs().get(1).getValue()); + + assertEquals(0, provider2.getReleaseRequestQueue().getEntries().size()); + assertEquals(0, provider2.getPegoutsWaitingForConfirmations().getEntries().size()); + assertTrue(provider2.getPegoutsWaitingForSignatures().isEmpty()); + assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx1.getHash()).isPresent()); + assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx2.getHash()).isPresent()); + assertTrue(provider2.getHeightIfBtcTxhashIsAlreadyProcessed(tx3.getHash()).isPresent()); } @Test - void isBtcTxHashAlreadyProcessed() throws IOException, BlockStoreException { + void isBtcTxHashAlreadyProcessed() throws IOException { BridgeSupport bridgeSupport = getBridgeSupport(getBridgeStorageProviderMockWithProcessedHashes(), null); for (int i = 0; i < 10; i++) { - Assertions.assertTrue(bridgeSupport.isBtcTxHashAlreadyProcessed(Sha256Hash.of(("hash_" + i).getBytes()))); + assertTrue(bridgeSupport.isBtcTxHashAlreadyProcessed(Sha256Hash.of(("hash_" + i).getBytes()))); } - Assertions.assertFalse(bridgeSupport.isBtcTxHashAlreadyProcessed(Sha256Hash.of("anything".getBytes()))); + assertFalse(bridgeSupport.isBtcTxHashAlreadyProcessed(Sha256Hash.of("anything".getBytes()))); } @Test - void getBtcTxHashProcessedHeight() throws IOException, BlockStoreException { + void getBtcTxHashProcessedHeight() throws IOException { BridgeSupport bridgeSupport = getBridgeSupport(getBridgeStorageProviderMockWithProcessedHashes(), null); for (int i = 0; i < 10; i++) { - Assertions.assertEquals(i, bridgeSupport.getBtcTxHashProcessedHeight(Sha256Hash.of(("hash_" + i).getBytes())).longValue()); + assertEquals(i, bridgeSupport.getBtcTxHashProcessedHeight(Sha256Hash.of(("hash_" + i).getBytes())).longValue()); } - Assertions.assertEquals(-1L, bridgeSupport.getBtcTxHashProcessedHeight(Sha256Hash.of("anything".getBytes())).longValue()); + assertEquals(-1L, bridgeSupport.getBtcTxHashProcessedHeight(Sha256Hash.of("anything".getBytes())).longValue()); } @Test @@ -1836,16 +1825,28 @@ void getFederationMethods_genesis() throws IOException { ); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests(true, activeFederation, genesisFederation, null, null, null, null); - Assertions.assertEquals(6, bridgeSupport.getFederationSize().intValue()); - Assertions.assertEquals(4, bridgeSupport.getFederationThreshold().intValue()); - Assertions.assertEquals(genesisFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); + assertEquals(6, bridgeSupport.getFederationSize().intValue()); + assertEquals(4, bridgeSupport.getFederationThreshold().intValue()); + assertEquals(genesisFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); List members = genesisFederation.getMembers(); for (int i = 0; i < 6; i++) { - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKey(i))); - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(members.get(i).getRskPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(members.get(i).getMstPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.MST))); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKey(i) + ); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.BTC) + ); + assertArrayEquals( + members.get(i).getRskPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.RSK) + ); + assertArrayEquals( + members.get(i).getMstPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.MST) + ); } } @@ -1878,15 +1879,27 @@ void getFederationMethods_active() throws IOException { null ); - Assertions.assertEquals(3, bridgeSupport.getFederationSize().intValue()); - Assertions.assertEquals(2, bridgeSupport.getFederationThreshold().intValue()); - Assertions.assertEquals(activeFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); + assertEquals(3, bridgeSupport.getFederationSize().intValue()); + assertEquals(2, bridgeSupport.getFederationThreshold().intValue()); + assertEquals(activeFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); List members = FederationTestUtils.getFederationMembers(3); for (int i = 0; i < 3; i++) { - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKey(i))); - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(members.get(i).getRskPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(members.get(i).getMstPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.MST))); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKey(i) + ); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.BTC) + ); + assertArrayEquals( + members.get(i).getRskPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.RSK) + ); + assertArrayEquals( + members.get(i).getMstPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.MST) + ); } } @@ -1924,15 +1937,27 @@ void getFederationMethods_newActivated() throws IOException { mockedBlock ); - Assertions.assertEquals(3, bridgeSupport.getFederationSize().intValue()); - Assertions.assertEquals(2, bridgeSupport.getFederationThreshold().intValue()); - Assertions.assertEquals(newFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); + assertEquals(3, bridgeSupport.getFederationSize().intValue()); + assertEquals(2, bridgeSupport.getFederationThreshold().intValue()); + assertEquals(newFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); List members = FederationTestUtils.getFederationMembers(3); for (int i = 0; i < 3; i++) { - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKey(i))); - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(members.get(i).getRskPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(members.get(i).getMstPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.MST))); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKey(i) + ); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.BTC) + ); + assertArrayEquals( + members.get(i).getRskPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.RSK) + ); + assertArrayEquals( + members.get(i).getMstPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.MST) + ); } } @@ -1971,16 +1996,27 @@ void getFederationMethods_newNotActivated() throws IOException { mockedBlock ); - Assertions.assertEquals(6, bridgeSupport.getFederationSize().intValue()); - Assertions.assertEquals(4, bridgeSupport.getFederationThreshold().intValue()); - Assertions.assertEquals(oldFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); + assertEquals(6, bridgeSupport.getFederationSize().intValue()); + assertEquals(4, bridgeSupport.getFederationThreshold().intValue()); + assertEquals(oldFederation.getAddress().toString(), bridgeSupport.getFederationAddress().toString()); List members = FederationTestUtils.getFederationMembers(6); for (int i = 0; i < 6; i++) { - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKey(i))); - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(members.get(i).getRskPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(members.get(i).getMstPublicKey().getPubKey(true), bridgeSupport.getFederatorPublicKeyOfType(i, FederationMember.KeyType.MST))); - + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKey(i) + ); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.BTC) + ); + assertArrayEquals( + members.get(i).getRskPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.RSK) + ); + assertArrayEquals( + members.get(i).getMstPublicKey().getPubKey(true), + bridgeSupport.getFederatorPublicKeyOfType(i, KeyType.MST) + ); } } @@ -1988,12 +2024,12 @@ void getFederationMethods_newNotActivated() throws IOException { void getRetiringFederationMethods_none() throws IOException { BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests(false, null, null, null, null, null, null); - Assertions.assertEquals(-1, bridgeSupport.getRetiringFederationSize().intValue()); - Assertions.assertEquals(-1, bridgeSupport.getRetiringFederationThreshold().intValue()); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKey(0)); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC)); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK)); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.MST)); + assertEquals(-1, bridgeSupport.getRetiringFederationSize().intValue()); + assertEquals(-1, bridgeSupport.getRetiringFederationThreshold().intValue()); + assertNull(bridgeSupport.getRetiringFederatorPublicKey(0)); + assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC)); + assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK)); + assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.MST)); } @Test @@ -2032,12 +2068,12 @@ void getRetiringFederationMethods_presentNewInactive() throws IOException { mockedBlock ); - Assertions.assertEquals(-1, bridgeSupport.getRetiringFederationSize().intValue()); - Assertions.assertEquals(-1, bridgeSupport.getRetiringFederationThreshold().intValue()); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKey(0)); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC)); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK)); - Assertions.assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.MST)); + assertEquals(-1, bridgeSupport.getRetiringFederationSize().intValue()); + assertEquals(-1, bridgeSupport.getRetiringFederationThreshold().intValue()); + assertNull(bridgeSupport.getRetiringFederatorPublicKey(0)); + assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC)); + assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK)); + assertNull(bridgeSupport.getRetiringFederatorPublicKeyOfType(0, FederationMember.KeyType.MST)); } @Test @@ -2076,16 +2112,26 @@ void getRetiringFederationMethods_presentNewActive() throws IOException { mockedBlock ); - Assertions.assertEquals(4, bridgeSupport.getRetiringFederationSize().intValue()); - Assertions.assertEquals(3, bridgeSupport.getRetiringFederationThreshold().intValue()); - Assertions.assertEquals(1000, bridgeSupport.getRetiringFederationCreationTime().toEpochMilli()); - Assertions.assertEquals(mockedOldFederation.getAddress().toString(), bridgeSupport.getRetiringFederationAddress().toString()); + assertEquals(4, bridgeSupport.getRetiringFederationSize().intValue()); + assertEquals(3, bridgeSupport.getRetiringFederationThreshold().intValue()); + assertEquals(1000, bridgeSupport.getRetiringFederationCreationTime().toEpochMilli()); + assertEquals(mockedOldFederation.getAddress().toString(), bridgeSupport.getRetiringFederationAddress().toString()); List members = FederationTestUtils.getFederationMembers(4); for (int i = 0; i < 4; i++) { - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getRetiringFederatorPublicKey(i))); - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getRetiringFederatorPublicKeyOfType(i, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(members.get(i).getRskPublicKey().getPubKey(true), bridgeSupport.getRetiringFederatorPublicKeyOfType(i, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(members.get(i).getMstPublicKey().getPubKey(true), bridgeSupport.getRetiringFederatorPublicKeyOfType(i, FederationMember.KeyType.MST))); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getRetiringFederatorPublicKey(i) + ); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getRetiringFederatorPublicKeyOfType(i, KeyType.BTC) + ); + assertArrayEquals(members.get(i).getRskPublicKey().getPubKey(true), + bridgeSupport.getRetiringFederatorPublicKeyOfType(i, KeyType.RSK) + ); + assertArrayEquals(members.get(i).getMstPublicKey().getPubKey(true), + bridgeSupport.getRetiringFederatorPublicKeyOfType(i, KeyType.MST) + ); } } @@ -2093,11 +2139,11 @@ void getRetiringFederationMethods_presentNewActive() throws IOException { void getPendingFederationMethods_none() throws IOException { BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests(false, null, null, null, null, null, null); - Assertions.assertEquals(-1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertNull(bridgeSupport.getPendingFederatorPublicKey(0)); - Assertions.assertNull(bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC)); - Assertions.assertNull(bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK)); - Assertions.assertNull(bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.MST)); + assertEquals(-1, bridgeSupport.getPendingFederationSize().intValue()); + assertNull(bridgeSupport.getPendingFederatorPublicKey(0)); + assertNull(bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC)); + assertNull(bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK)); + assertNull(bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.MST)); } @Test @@ -2105,13 +2151,25 @@ void getPendingFederationMethods_present() throws IOException { PendingFederation mockedPendingFederation = new PendingFederation(FederationTestUtils.getFederationMembers(5)); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests(false, null, null, null, mockedPendingFederation, null, null); - Assertions.assertEquals(5, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(5, bridgeSupport.getPendingFederationSize().intValue()); List members = FederationTestUtils.getFederationMembers(5); for (int i = 0; i < 5; i++) { - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getPendingFederatorPublicKey(i))); - Assertions.assertTrue(Arrays.equals(members.get(i).getBtcPublicKey().getPubKey(), bridgeSupport.getPendingFederatorPublicKeyOfType(i, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(members.get(i).getRskPublicKey().getPubKey(true), bridgeSupport.getPendingFederatorPublicKeyOfType(i, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(members.get(i).getMstPublicKey().getPubKey(true), bridgeSupport.getPendingFederatorPublicKeyOfType(i, FederationMember.KeyType.MST))); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getPendingFederatorPublicKey(i) + ); + assertArrayEquals( + members.get(i).getBtcPublicKey().getPubKey(), + bridgeSupport.getPendingFederatorPublicKeyOfType(i, KeyType.BTC) + ); + assertArrayEquals( + members.get(i).getRskPublicKey().getPubKey(true), + bridgeSupport.getPendingFederatorPublicKeyOfType(i, KeyType.RSK) + ); + assertArrayEquals( + members.get(i).getMstPublicKey().getPubKey(true), + bridgeSupport.getPendingFederatorPublicKeyOfType(i, KeyType.MST) + ); } } @@ -2127,7 +2185,7 @@ void voteFederationChange_methodNotAllowed() throws IOException, BridgeIllegalAr null ); ABICallSpec spec = new ABICallSpec("a-random-method", new byte[][]{}); - Assertions.assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE, bridgeSupport.voteFederationChange(mock(Transaction.class), spec)); + assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE, bridgeSupport.voteFederationChange(mock(Transaction.class), spec)); } @Test @@ -2144,20 +2202,20 @@ void voteFederationChange_notAuthorized() throws IOException, BridgeIllegalArgum ABICallSpec spec = new ABICallSpec("create", new byte[][]{}); Transaction mockedTx = mock(Transaction.class); when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(new RskAddress(ECKey.fromPrivate(BigInteger.valueOf(12L)).getAddress())); - Assertions.assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE, bridgeSupport.voteFederationChange(mockedTx, spec)); + assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE, bridgeSupport.voteFederationChange(mockedTx, spec)); } - private class VotingMocksProvider { - private RskAddress voter; - private ABICallElection election; + private static class VotingMocksProvider { + private final RskAddress voter; + private final ABICallElection election; + private final ABICallSpec spec; + private final Transaction tx; private ABICallSpec winner; - private ABICallSpec spec; - private Transaction tx; public VotingMocksProvider(String function, byte[][] arguments, boolean mockVoteResult) { byte[] voterBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of an authorized voter in regtest, taken from BridgeRegTestConstants - "04dde17c5fab31ffc53c91c2390136c325bb8690dc135b0840075dd7b86910d8ab9e88baad0c32f3eea8833446a6bc5ff1cd2efa99ecb17801bcb65fc16fc7d991" + // Public key hex of an authorized voter in regtest, taken from BridgeRegTestConstants + "04dde17c5fab31ffc53c91c2390136c325bb8690dc135b0840075dd7b86910d8ab9e88baad0c32f3eea8833446a6bc5ff1cd2efa99ecb17801bcb65fc16fc7d991" )).getAddress(); voter = new RskAddress(voterBytes); @@ -2185,10 +2243,6 @@ public ABICallSpec getSpec() { return spec; } - public Transaction getTx() { - return tx; - } - public Optional getWinner() { if (winner == null) { return Optional.empty(); @@ -2220,19 +2274,19 @@ void createFederation_ok() throws IOException, BridgeIllegalArgumentException { null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); // Vote with no winner - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertTrue(Arrays.equals( - new PendingFederation(Collections.emptyList()).getHash().getBytes(), - bridgeSupport.getPendingFederationHash()) + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertArrayEquals( + new PendingFederation(Collections.emptyList()).getHash().getBytes(), + bridgeSupport.getPendingFederationHash() ); verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), times(1)).clear(); @@ -2240,27 +2294,28 @@ void createFederation_ok() throws IOException, BridgeIllegalArgumentException { @Test void createFederation_pendingExists() throws IOException, BridgeIllegalArgumentException { - VotingMocksProvider mocksProvider = new VotingMocksProvider("create", new byte[][]{}, false); + VotingMocksProvider mocksProvider = new VotingMocksProvider("create", new byte[][]{}, + false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - new PendingFederation(Collections.emptyList()), - mocksProvider.getElection(), - null + false, + null, + null, + null, + new PendingFederation(Collections.emptyList()), + mocksProvider.getElection(), + null ); - Assertions.assertTrue(Arrays.equals( - new PendingFederation(Collections.emptyList()).getHash().getBytes(), - bridgeSupport.getPendingFederationHash() - )); - Assertions.assertEquals(-1, mocksProvider.execute(bridgeSupport)); - Assertions.assertTrue(Arrays.equals( - new PendingFederation(Collections.emptyList()).getHash().getBytes(), - bridgeSupport.getPendingFederationHash() - )); + assertArrayEquals( + new PendingFederation(Collections.emptyList()).getHash().getBytes(), + bridgeSupport.getPendingFederationHash() + ); + assertEquals(-1, mocksProvider.execute(bridgeSupport)); + assertArrayEquals( + new PendingFederation(Collections.emptyList()).getHash().getBytes(), + bridgeSupport.getPendingFederationHash() + ); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2268,7 +2323,8 @@ void createFederation_pendingExists() throws IOException, BridgeIllegalArgumentE @Test void createFederation_withPendingActivation() throws IOException, BridgeIllegalArgumentException { - VotingMocksProvider mocksProvider = new VotingMocksProvider("create", new byte[][]{}, false); + VotingMocksProvider mocksProvider = new VotingMocksProvider("create", new byte[][]{}, + false); NetworkParameters btcParams = NetworkParameters.fromID(NetworkParameters.ID_REGTEST); FederationArgs mockedNewFedArgs = new FederationArgs( @@ -2306,9 +2362,9 @@ void createFederation_withPendingActivation() throws IOException, BridgeIllegalA ); ((BridgeStorageProvider) TestUtils.getInternalState(bridgeSupport, "provider")).getOldFederationBtcUTXOs().add(mock(UTXO.class)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(-2, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(-2, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2316,7 +2372,8 @@ void createFederation_withPendingActivation() throws IOException, BridgeIllegalA @Test void createFederation_withExistingRetiringFederation() throws IOException, BridgeIllegalArgumentException { - VotingMocksProvider mocksProvider = new VotingMocksProvider("create", new byte[][]{}, false); + VotingMocksProvider mocksProvider = new VotingMocksProvider("create", new byte[][]{}, + false); NetworkParameters btcParams = NetworkParameters.fromID(NetworkParameters.ID_REGTEST); FederationArgs mockedNewFedArgs = new FederationArgs( @@ -2354,9 +2411,9 @@ void createFederation_withExistingRetiringFederation() throws IOException, Bridg ); ((BridgeStorageProvider) TestUtils.getInternalState(bridgeSupport, "provider")).getOldFederationBtcUTXOs().add(mock(UTXO.class)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(-3, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(-3, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2365,7 +2422,7 @@ void createFederation_withExistingRetiringFederation() throws IOException, Bridg @Test void addFederatorPublicKey_okNoKeys() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add", new byte[][]{ - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") }, true); PendingFederation pendingFederation = new PendingFederation(Collections.emptyList()); @@ -2379,21 +2436,33 @@ void addFederatorPublicKey_okNoKeys() throws IOException, BridgeIllegalArgumentE null ); - Assertions.assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); // Vote with no winner - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKey(0))); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.MST))); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKey(0) + ); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.BTC) + ); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.RSK) + ); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.MST) + ); verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); } @@ -2401,7 +2470,7 @@ void addFederatorPublicKey_okNoKeys() throws IOException, BridgeIllegalArgumentE @Test void addFederatorPublicKey_okKeys() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add", new byte[][]{ - Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a") + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a") }, true); PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList(new BtcECKey[]{ @@ -2417,26 +2486,42 @@ void addFederatorPublicKey_okKeys() throws IOException, BridgeIllegalArgumentExc null ); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); // Vote with no winner - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(2, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKey(0))); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.MST))); - - Assertions.assertTrue(Arrays.equals(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), bridgeSupport.getPendingFederatorPublicKey(1))); - Assertions.assertTrue(Arrays.equals(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), bridgeSupport.getPendingFederatorPublicKeyOfType(1, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), bridgeSupport.getPendingFederatorPublicKeyOfType(1, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), bridgeSupport.getPendingFederatorPublicKeyOfType(1, FederationMember.KeyType.MST))); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(2, bridgeSupport.getPendingFederationSize().intValue()); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKey(0)); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.BTC)); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.RSK)); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.MST)); + + assertArrayEquals( + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + bridgeSupport.getPendingFederatorPublicKey(1)); + assertArrayEquals( + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + bridgeSupport.getPendingFederatorPublicKeyOfType(1, KeyType.BTC)); + assertArrayEquals( + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + bridgeSupport.getPendingFederatorPublicKeyOfType(1, KeyType.RSK)); + assertArrayEquals( + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + bridgeSupport.getPendingFederatorPublicKeyOfType(1, KeyType.MST)); verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); @@ -2445,7 +2530,7 @@ void addFederatorPublicKey_okKeys() throws IOException, BridgeIllegalArgumentExc @Test void addFederatorPublicKey_noPendingFederation() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add", new byte[][]{ - Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a") + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a") }, false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( @@ -2458,9 +2543,9 @@ void addFederatorPublicKey_noPendingFederation() throws IOException, BridgeIlleg null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(-1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(-1, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2469,25 +2554,25 @@ void addFederatorPublicKey_noPendingFederation() throws IOException, BridgeIlleg @Test void addFederatorPublicKey_keyExists() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add", new byte[][]{ - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") }, false); - PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList(new BtcECKey[]{ - BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) - }))); + PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Collections.singletonList( + BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) + ))); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertEquals(-2, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(-2, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2496,7 +2581,7 @@ void addFederatorPublicKey_keyExists() throws IOException, BridgeIllegalArgument @Test void addFederatorPublicKey_invalidKey() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add", new byte[][]{ - Hex.decode("aabbccdd") + Hex.decode("aabbccdd") }, false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( @@ -2509,9 +2594,9 @@ void addFederatorPublicKey_invalidKey() throws IOException, BridgeIllegalArgumen null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2520,9 +2605,9 @@ void addFederatorPublicKey_invalidKey() throws IOException, BridgeIllegalArgumen @Test void addFederatorPublicKeyMultikey_okNoKeys() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), - Hex.decode("026289413837ab836eb76428406a3b4f200418d31d99c259a0532b8e435f35153b"), - Hex.decode("03e12efa1146037bc9325574b0f15749ba6dc0eec360b1670b05029eead511a6ff") + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + Hex.decode("026289413837ab836eb76428406a3b4f200418d31d99c259a0532b8e435f35153b"), + Hex.decode("03e12efa1146037bc9325574b0f15749ba6dc0eec360b1670b05029eead511a6ff") }, true); PendingFederation pendingFederation = new PendingFederation(Collections.emptyList()); @@ -2536,20 +2621,28 @@ void addFederatorPublicKeyMultikey_okNoKeys() throws IOException, BridgeIllegalA null ); - Assertions.assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); // Vote with no winner - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(0, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertTrue(Arrays.equals(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(Hex.decode("026289413837ab836eb76428406a3b4f200418d31d99c259a0532b8e435f35153b"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(Hex.decode("03e12efa1146037bc9325574b0f15749ba6dc0eec360b1670b05029eead511a6ff"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.MST))); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertArrayEquals( + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.BTC)); + assertArrayEquals( + Hex.decode("026289413837ab836eb76428406a3b4f200418d31d99c259a0532b8e435f35153b"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.RSK) + ); + assertArrayEquals( + Hex.decode("03e12efa1146037bc9325574b0f15749ba6dc0eec360b1670b05029eead511a6ff"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.MST) + ); verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); } @@ -2557,44 +2650,62 @@ void addFederatorPublicKeyMultikey_okNoKeys() throws IOException, BridgeIllegalA @Test void addFederatorPublicKeyMultikey_okKeys() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), - Hex.decode("03f64d2c022bca70f3ff0b1e95336be2c1507daa2ad37a484e0b66cbda86cfc6c5"), - Hex.decode("03eed62698319f754407a31fde9a51da8b2be0ab40e9c4c695bb057757729be37f") + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + Hex.decode("03f64d2c022bca70f3ff0b1e95336be2c1507daa2ad37a484e0b66cbda86cfc6c5"), + Hex.decode("03eed62698319f754407a31fde9a51da8b2be0ab40e9c4c695bb057757729be37f") }, true); - PendingFederation pendingFederation = new PendingFederation(Arrays.asList(new FederationMember( - BtcECKey.fromPublicOnly(Hex.decode("02ebd9e8b2caff48b10e661e69fe107d6986d2df1ce7e377f2ef927f3194a61b99")), - ECKey.fromPublicOnly(Hex.decode("02a23343f50363dc9a4c29f0c0a8386780cc8bf469211f4de51d50f8c0f274e9a7")), - ECKey.fromPublicOnly(Hex.decode("030dd584c286275ab2ce249096d0d7e6c78853e0902db061b14f2e39df068f95bc")) + PendingFederation pendingFederation = new PendingFederation(Collections.singletonList(new FederationMember( + BtcECKey.fromPublicOnly(Hex.decode("02ebd9e8b2caff48b10e661e69fe107d6986d2df1ce7e377f2ef927f3194a61b99")), + ECKey.fromPublicOnly(Hex.decode("02a23343f50363dc9a4c29f0c0a8386780cc8bf469211f4de51d50f8c0f274e9a7")), + ECKey.fromPublicOnly(Hex.decode("030dd584c286275ab2ce249096d0d7e6c78853e0902db061b14f2e39df068f95bc")) ))); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); // Vote with no winner - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(2, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertTrue(Arrays.equals(Hex.decode("02ebd9e8b2caff48b10e661e69fe107d6986d2df1ce7e377f2ef927f3194a61b99"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(Hex.decode("02a23343f50363dc9a4c29f0c0a8386780cc8bf469211f4de51d50f8c0f274e9a7"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(Hex.decode("030dd584c286275ab2ce249096d0d7e6c78853e0902db061b14f2e39df068f95bc"), bridgeSupport.getPendingFederatorPublicKeyOfType(0, FederationMember.KeyType.MST))); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(2, bridgeSupport.getPendingFederationSize().intValue()); + assertArrayEquals( + Hex.decode("02ebd9e8b2caff48b10e661e69fe107d6986d2df1ce7e377f2ef927f3194a61b99"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.BTC) + ); + assertArrayEquals( + Hex.decode("02a23343f50363dc9a4c29f0c0a8386780cc8bf469211f4de51d50f8c0f274e9a7"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.RSK) + ); + assertArrayEquals( + Hex.decode("030dd584c286275ab2ce249096d0d7e6c78853e0902db061b14f2e39df068f95bc"), + bridgeSupport.getPendingFederatorPublicKeyOfType(0, KeyType.MST) + ); - Assertions.assertTrue(Arrays.equals(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), bridgeSupport.getPendingFederatorPublicKeyOfType(1, FederationMember.KeyType.BTC))); - Assertions.assertTrue(Arrays.equals(Hex.decode("03f64d2c022bca70f3ff0b1e95336be2c1507daa2ad37a484e0b66cbda86cfc6c5"), bridgeSupport.getPendingFederatorPublicKeyOfType(1, FederationMember.KeyType.RSK))); - Assertions.assertTrue(Arrays.equals(Hex.decode("03eed62698319f754407a31fde9a51da8b2be0ab40e9c4c695bb057757729be37f"), bridgeSupport.getPendingFederatorPublicKeyOfType(1, FederationMember.KeyType.MST))); + assertArrayEquals( + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + bridgeSupport.getPendingFederatorPublicKeyOfType(1, KeyType.BTC) + ); + assertArrayEquals( + Hex.decode("03f64d2c022bca70f3ff0b1e95336be2c1507daa2ad37a484e0b66cbda86cfc6c5"), + bridgeSupport.getPendingFederatorPublicKeyOfType(1, KeyType.RSK) + ); + assertArrayEquals( + Hex.decode("03eed62698319f754407a31fde9a51da8b2be0ab40e9c4c695bb057757729be37f"), + bridgeSupport.getPendingFederatorPublicKeyOfType(1, KeyType.MST) + ); verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); @@ -2603,9 +2714,9 @@ void addFederatorPublicKeyMultikey_okKeys() throws IOException, BridgeIllegalArg @Test void addFederatorPublicKeyMultikey_noPendingFederation() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), - Hex.decode("0259323a848372c51673622b29298b6e5854b28d45de297fe7cff67915ad900a59"), - Hex.decode("0304d9178db5e243667824188f86f7507104d0e237838bfb22bb4af592a8bca08a") + Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a"), + Hex.decode("0259323a848372c51673622b29298b6e5854b28d45de297fe7cff67915ad900a59"), + Hex.decode("0304d9178db5e243667824188f86f7507104d0e237838bfb22bb4af592a8bca08a") }, false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( @@ -2618,9 +2729,9 @@ void addFederatorPublicKeyMultikey_noPendingFederation() throws IOException, Bri null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(-1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(-1, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2629,29 +2740,29 @@ void addFederatorPublicKeyMultikey_noPendingFederation() throws IOException, Bri @Test void addFederatorPublicKeyMultikey_btcKeyExists() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), - Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053"), - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053"), + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") }, false); - PendingFederation pendingFederation = new PendingFederation(Arrays.asList(new FederationMember( - BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")), - ECKey.fromPublicOnly(Hex.decode("03981d06bd7bc419612aa09f860188f08d3c3010796dcb41cdfc43a6875600efa8")), - ECKey.fromPublicOnly(Hex.decode("0365e45f68d6347aaa03c76f3d6f47000df6090801e49eef6d49f547f5c19de5dd")) + PendingFederation pendingFederation = new PendingFederation(Collections.singletonList(new FederationMember( + BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")), + ECKey.fromPublicOnly(Hex.decode("03981d06bd7bc419612aa09f860188f08d3c3010796dcb41cdfc43a6875600efa8")), + ECKey.fromPublicOnly(Hex.decode("0365e45f68d6347aaa03c76f3d6f47000df6090801e49eef6d49f547f5c19de5dd")) ))); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertEquals(-2, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(-2, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2660,29 +2771,29 @@ void addFederatorPublicKeyMultikey_btcKeyExists() throws IOException, BridgeIlle @Test void addFederatorPublicKeyMultikey_rskKeyExists() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), - Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053"), - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053"), + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") }, false); - PendingFederation pendingFederation = new PendingFederation(Arrays.asList(new FederationMember( - BtcECKey.fromPublicOnly(Hex.decode("0290d68bf50a8389e541a19d47c51447b443f41a13049e0783db6a25c419d612db")), - ECKey.fromPublicOnly(Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053")), - ECKey.fromPublicOnly(Hex.decode("0365e45f68d6347aaa03c76f3d6f47000df6090801e49eef6d49f547f5c19de5dd")) + PendingFederation pendingFederation = new PendingFederation(Collections.singletonList(new FederationMember( + BtcECKey.fromPublicOnly(Hex.decode("0290d68bf50a8389e541a19d47c51447b443f41a13049e0783db6a25c419d612db")), + ECKey.fromPublicOnly(Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053")), + ECKey.fromPublicOnly(Hex.decode("0365e45f68d6347aaa03c76f3d6f47000df6090801e49eef6d49f547f5c19de5dd")) ))); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertEquals(-2, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(-2, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2691,15 +2802,15 @@ void addFederatorPublicKeyMultikey_rskKeyExists() throws IOException, BridgeIlle @Test void addFederatorPublicKeyMultikey_mstKeyExists() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), - Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053"), - Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"), + Hex.decode("02cf0dec68ca34502e4ebd35c40a0e66ff47ba520f0418bcd7388717b12ab4b053"), + Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5") }, false); - PendingFederation pendingFederation = new PendingFederation(Arrays.asList(new FederationMember( - BtcECKey.fromPublicOnly(Hex.decode("0290d68bf50a8389e541a19d47c51447b443f41a13049e0783db6a25c419d612db")), - ECKey.fromPublicOnly(Hex.decode("033174d2fb7a3d7a0c87d43fa3e9ba43d4962014960b82bcd793706c05f68111c8")), - ECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) + PendingFederation pendingFederation = new PendingFederation(Collections.singletonList(new FederationMember( + BtcECKey.fromPublicOnly(Hex.decode("0290d68bf50a8389e541a19d47c51447b443f41a13049e0783db6a25c419d612db")), + ECKey.fromPublicOnly(Hex.decode("033174d2fb7a3d7a0c87d43fa3e9ba43d4962014960b82bcd793706c05f68111c8")), + ECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) ))); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( false, @@ -2711,9 +2822,9 @@ void addFederatorPublicKeyMultikey_mstKeyExists() throws IOException, BridgeIlle null ); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); - Assertions.assertEquals(-2, mocksProvider.execute(bridgeSupport)); - Assertions.assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); + assertEquals(-2, mocksProvider.execute(bridgeSupport)); + assertEquals(1, bridgeSupport.getPendingFederationSize().intValue()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2722,9 +2833,9 @@ void addFederatorPublicKeyMultikey_mstKeyExists() throws IOException, BridgeIlle @Test void addFederatorPublicKey_invalidBtcKey() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("aabbccdd"), - Hex.decode("0245db19d3d4b8c3567a47189ae60588e18e1305f3473a7fe99b6ef559bb1d1dc6"), - Hex.decode("029664581b2e8dc9ba7885696a03134aaebe4be834ce0049d62f80499bbe130206") + Hex.decode("aabbccdd"), + Hex.decode("0245db19d3d4b8c3567a47189ae60588e18e1305f3473a7fe99b6ef559bb1d1dc6"), + Hex.decode("029664581b2e8dc9ba7885696a03134aaebe4be834ce0049d62f80499bbe130206") }, false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( @@ -2737,9 +2848,9 @@ void addFederatorPublicKey_invalidBtcKey() throws IOException, BridgeIllegalArgu null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2748,9 +2859,9 @@ void addFederatorPublicKey_invalidBtcKey() throws IOException, BridgeIllegalArgu @Test void addFederatorPublicKey_invalidRskKey() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("0245db19d3d4b8c3567a47189ae60588e18e1305f3473a7fe99b6ef559bb1d1dc6"), - Hex.decode("aabbccdd"), - Hex.decode("029664581b2e8dc9ba7885696a03134aaebe4be834ce0049d62f80499bbe130206") + Hex.decode("0245db19d3d4b8c3567a47189ae60588e18e1305f3473a7fe99b6ef559bb1d1dc6"), + Hex.decode("aabbccdd"), + Hex.decode("029664581b2e8dc9ba7885696a03134aaebe4be834ce0049d62f80499bbe130206") }, false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( @@ -2763,9 +2874,9 @@ void addFederatorPublicKey_invalidRskKey() throws IOException, BridgeIllegalArgu null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2774,9 +2885,9 @@ void addFederatorPublicKey_invalidRskKey() throws IOException, BridgeIllegalArgu @Test void addFederatorPublicKey_invalidMstKey() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("add-multi", new byte[][]{ - Hex.decode("0245db19d3d4b8c3567a47189ae60588e18e1305f3473a7fe99b6ef559bb1d1dc6"), - Hex.decode("029664581b2e8dc9ba7885696a03134aaebe4be834ce0049d62f80499bbe130206"), - Hex.decode("aabbccdd") + Hex.decode("0245db19d3d4b8c3567a47189ae60588e18e1305f3473a7fe99b6ef559bb1d1dc6"), + Hex.decode("029664581b2e8dc9ba7885696a03134aaebe4be834ce0049d62f80499bbe130206"), + Hex.decode("aabbccdd") }, false); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( @@ -2789,9 +2900,9 @@ void addFederatorPublicKey_invalidMstKey() throws IOException, BridgeIllegalArgu null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(BridgeSupport.FEDERATION_CHANGE_GENERIC_ERROR_CODE.intValue(), mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2799,40 +2910,42 @@ void addFederatorPublicKey_invalidMstKey() throws IOException, BridgeIllegalArgu @Test void rollbackFederation_ok() throws IOException, BridgeIllegalArgumentException { - VotingMocksProvider mocksProvider = new VotingMocksProvider("rollback", new byte[][]{}, true); + VotingMocksProvider mocksProvider = new VotingMocksProvider("rollback", new byte[][]{}, + true); - PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList(new BtcECKey[]{ - BtcECKey.fromPublicOnly(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a")), - BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) - }))); + PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList( + BtcECKey.fromPublicOnly(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a")), + BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) + ))); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); // Vote with no winner - Assertions.assertNotNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNotNull(bridgeSupport.getPendingFederationHash()); + assertNotNull(bridgeSupport.getPendingFederationHash()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertNotNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), times(1)).clear(); } @Test void rollbackFederation_noPendingFederation() throws IOException, BridgeIllegalArgumentException { - VotingMocksProvider mocksProvider = new VotingMocksProvider("rollback", new byte[][]{}, true); + VotingMocksProvider mocksProvider = new VotingMocksProvider("rollback", new byte[][]{}, + true); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( false, @@ -2844,9 +2957,9 @@ void rollbackFederation_noPendingFederation() throws IOException, BridgeIllegalA null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(-1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(-1, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2863,7 +2976,7 @@ void commitFederation_ok() throws IOException, BridgeIllegalArgumentException { )); VotingMocksProvider mocksProvider = new VotingMocksProvider("commit", new byte[][]{ - pendingFederation.getHash().getBytes() + pendingFederation.getHash().getBytes() }, true); Block executionBlock = mock(Block.class); @@ -2917,7 +3030,7 @@ void commitFederation_ok() throws IOException, BridgeIllegalArgumentException { executionBlock, eventLoggerMock ); - BridgeStorageProvider provider = (BridgeStorageProvider) TestUtils.getInternalState(bridgeSupport, "provider"); + BridgeStorageProvider provider = TestUtils.getInternalState(bridgeSupport, "provider"); // Mock some utxos in the currently active federation for (int i = 0; i < 5; i++) { @@ -2929,33 +3042,33 @@ void commitFederation_ok() throws IOException, BridgeIllegalArgumentException { // Currently active federation Federation oldActiveFederation = provider.getNewFederation(); - Assertions.assertNotNull(oldActiveFederation); + assertNotNull(oldActiveFederation); // Vote with no winner - Assertions.assertNotNull(provider.getPendingFederation()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNotNull(provider.getPendingFederation()); + assertNotNull(provider.getPendingFederation()); + assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertNotNull(provider.getPendingFederation()); - Assertions.assertEquals(oldActiveFederation, provider.getNewFederation()); - Assertions.assertNull(provider.getOldFederation()); + assertEquals(oldActiveFederation, provider.getNewFederation()); + assertNull(provider.getOldFederation()); // Vote with winner mocksProvider.setWinner(mocksProvider.getSpec()); - Assertions.assertEquals(1, mocksProvider.execute(bridgeSupport)); + assertEquals(1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(provider.getPendingFederation()); + assertNull(provider.getPendingFederation()); Federation retiringFederation = provider.getOldFederation(); Federation activeFederation = provider.getNewFederation(); - Assertions.assertEquals(expectedFederation, activeFederation); - Assertions.assertEquals(retiringFederation, oldActiveFederation); + assertEquals(expectedFederation, activeFederation); + assertEquals(retiringFederation, oldActiveFederation); - Assertions.assertEquals(0, provider.getNewFederationBtcUTXOs().size()); - Assertions.assertEquals(5, provider.getOldFederationBtcUTXOs().size()); + assertEquals(0, provider.getNewFederationBtcUTXOs().size()); + assertEquals(5, provider.getOldFederationBtcUTXOs().size()); for (int i = 0; i < 5; i++) { - Assertions.assertEquals(i, provider.getOldFederationBtcUTXOs().get(i).getIndex()); - Assertions.assertEquals(Coin.valueOf((i + 1) * 1000), provider.getOldFederationBtcUTXOs().get(i).getValue()); + assertEquals(i, provider.getOldFederationBtcUTXOs().get(i).getIndex()); + assertEquals(Coin.valueOf((i + 1) * 1000), provider.getOldFederationBtcUTXOs().get(i).getValue()); } verify(mocksProvider.getElection(), times(1)).clearWinners(); verify(mocksProvider.getElection(), times(1)).clear(); @@ -2967,7 +3080,7 @@ void commitFederation_ok() throws IOException, BridgeIllegalArgumentException { @Test void commitFederation_noPendingFederation() throws IOException, BridgeIllegalArgumentException { VotingMocksProvider mocksProvider = new VotingMocksProvider("commit", new byte[][]{ - new Keccak256(HashUtil.keccak256(Hex.decode("aabbcc"))).getBytes() + new Keccak256(HashUtil.keccak256(Hex.decode("aabbcc"))).getBytes() }, true); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( false, @@ -2979,9 +3092,9 @@ void commitFederation_noPendingFederation() throws IOException, BridgeIllegalArg null ); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); - Assertions.assertEquals(-1, mocksProvider.execute(bridgeSupport)); - Assertions.assertNull(bridgeSupport.getPendingFederationHash()); + assertNull(bridgeSupport.getPendingFederationHash()); + assertEquals(-1, mocksProvider.execute(bridgeSupport)); + assertNull(bridgeSupport.getPendingFederationHash()); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -2989,27 +3102,33 @@ void commitFederation_noPendingFederation() throws IOException, BridgeIllegalArg @Test void commitFederation_incompleteFederation() throws IOException, BridgeIllegalArgumentException { - PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList(new BtcECKey[]{ - BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) - }))); + PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys( + Collections.singletonList(BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5"))) + )); VotingMocksProvider mocksProvider = new VotingMocksProvider("commit", new byte[][]{ - new Keccak256(HashUtil.keccak256(Hex.decode("aabbcc"))).getBytes() + new Keccak256(HashUtil.keccak256(Hex.decode("aabbcc"))).getBytes() }, true); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); - Assertions.assertTrue(Arrays.equals(pendingFederation.getHash().getBytes(), bridgeSupport.getPendingFederationHash())); - Assertions.assertEquals(-2, mocksProvider.execute(bridgeSupport)); - Assertions.assertTrue(Arrays.equals(pendingFederation.getHash().getBytes(), bridgeSupport.getPendingFederationHash())); + assertArrayEquals( + pendingFederation.getHash().getBytes(), + bridgeSupport.getPendingFederationHash() + ); + assertEquals(-2, mocksProvider.execute(bridgeSupport)); + assertArrayEquals( + pendingFederation.getHash().getBytes(), + bridgeSupport.getPendingFederationHash() + ); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -3017,28 +3136,34 @@ void commitFederation_incompleteFederation() throws IOException, BridgeIllegalAr @Test void commitFederation_hashMismatch() throws IOException, BridgeIllegalArgumentException { - PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList(new BtcECKey[]{ - BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")), - BtcECKey.fromPublicOnly(Hex.decode("025eefeeeed5cdc40822880c7db1d0a88b7b986945ed3fc05a0b45fe166fe85e12")) - }))); + PendingFederation pendingFederation = new PendingFederation(FederationTestUtils.getFederationMembersWithKeys(Arrays.asList( + BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")), + BtcECKey.fromPublicOnly(Hex.decode("025eefeeeed5cdc40822880c7db1d0a88b7b986945ed3fc05a0b45fe166fe85e12")) + ))); VotingMocksProvider mocksProvider = new VotingMocksProvider("commit", new byte[][]{ - new Keccak256(HashUtil.keccak256(Hex.decode("aabbcc"))).getBytes() + new Keccak256(HashUtil.keccak256(Hex.decode("aabbcc"))).getBytes() }, true); BridgeSupport bridgeSupport = getBridgeSupportWithMocksForFederationTests( - false, - null, - null, - null, - pendingFederation, - mocksProvider.getElection(), - null + false, + null, + null, + null, + pendingFederation, + mocksProvider.getElection(), + null ); - Assertions.assertTrue(Arrays.equals(pendingFederation.getHash().getBytes(), bridgeSupport.getPendingFederationHash())); - Assertions.assertEquals(-3, mocksProvider.execute(bridgeSupport)); - Assertions.assertTrue(Arrays.equals(pendingFederation.getHash().getBytes(), bridgeSupport.getPendingFederationHash())); + assertArrayEquals( + pendingFederation.getHash().getBytes(), + bridgeSupport.getPendingFederationHash() + ); + assertEquals(-3, mocksProvider.execute(bridgeSupport)); + assertArrayEquals( + pendingFederation.getHash().getBytes(), + bridgeSupport.getPendingFederationHash() + ); verify(mocksProvider.getElection(), never()).clearWinners(); verify(mocksProvider.getElection(), never()).clear(); verify(mocksProvider.getElection(), never()).vote(mocksProvider.getSpec(), mocksProvider.getVoter()); @@ -3073,15 +3198,15 @@ void getActiveFederationWallet() throws IOException { ); Context expectedContext = mock(Context.class); TestUtils.setInternalState(bridgeSupport, "btcContext", expectedContext); - BridgeStorageProvider provider = (BridgeStorageProvider) TestUtils.getInternalState(bridgeSupport, "provider"); + BridgeStorageProvider provider = TestUtils.getInternalState(bridgeSupport, "provider"); Object expectedUtxos = provider.getNewFederationBtcUTXOs(); final Wallet expectedWallet = mock(Wallet.class); try (MockedStatic bridgeUtilsMocked = mockStatic(BridgeUtils.class)) { bridgeUtilsMocked.when(() -> BridgeUtils.getFederationSpendWallet(any(), any(), any(), anyBoolean(), any())).then((InvocationOnMock m) -> { - Assertions.assertEquals(m.getArgument(0), expectedContext); - Assertions.assertEquals(m.getArgument(1), expectedFederation); - Assertions.assertEquals(m.getArgument(2), expectedUtxos); + assertEquals(m.getArgument(0), expectedContext); + assertEquals(m.getArgument(1), expectedFederation); + assertEquals(m.getArgument(2), expectedUtxos); return expectedWallet; }); @@ -3100,11 +3225,10 @@ void getRetiringFederationWallet_nonEmpty() throws IOException { mockedFedArgs ); - List expectedFederationMembers = FederationTestUtils.getFederationMembersWithBtcKeys( - Arrays.asList(new BtcECKey[]{ - BtcECKey.fromPublicOnly(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a")), + List expectedFederationMembers = FederationTestUtils.getFederationMembersWithBtcKeys(Arrays.asList( + BtcECKey.fromPublicOnly(Hex.decode("036bb9eab797eadc8b697f0e82a01d01cabbfaaca37e5bafc06fdc6fdd38af894a")), BtcECKey.fromPublicOnly(Hex.decode("031da807c71c2f303b7f409dd2605b297ac494a563be3b9ca5f52d95a43d183cc5")) - })); + )); FederationArgs expectedFederationArgs = new FederationArgs( expectedFederationMembers, Instant.ofEpochMilli(5005L), @@ -3129,15 +3253,15 @@ void getRetiringFederationWallet_nonEmpty() throws IOException { ); Context expectedContext = mock(Context.class); TestUtils.setInternalState(bridgeSupport, "btcContext", expectedContext); - BridgeStorageProvider provider = (BridgeStorageProvider) TestUtils.getInternalState(bridgeSupport, "provider"); + BridgeStorageProvider provider = TestUtils.getInternalState(bridgeSupport, "provider"); Object expectedUtxos = provider.getOldFederationBtcUTXOs(); final Wallet expectedWallet = mock(Wallet.class); try (MockedStatic bridgeUtilsMocked = mockStatic(BridgeUtils.class)) { bridgeUtilsMocked.when(() -> BridgeUtils.getFederationSpendWallet(any(), any(), any(), anyBoolean(), any())).then((InvocationOnMock m) -> { - Assertions.assertEquals(m.getArgument(0), expectedContext); - Assertions.assertEquals(m.getArgument(1), expectedFederation); - Assertions.assertEquals(m.getArgument(2), expectedUtxos); + assertEquals(m.getArgument(0), expectedContext); + assertEquals(m.getArgument(1), expectedFederation); + assertEquals(m.getArgument(2), expectedUtxos); return expectedWallet; }); @@ -3145,331 +3269,6 @@ void getRetiringFederationWallet_nonEmpty() throws IOException { } } - @Test - void getLockWhitelistMethods() { - NetworkParameters parameters = NetworkParameters.fromID(NetworkParameters.ID_REGTEST); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.getSize()).thenReturn(4); - List entries = Arrays.stream(new Integer[]{2, 3, 4, 5}).map(i -> - new UnlimitedWhiteListEntry(new Address(parameters, BtcECKey.fromPrivate(BigInteger.valueOf(i)).getPubKeyHash())) - ).collect(Collectors.toList()); - when(mockedWhitelist.getAll()).thenReturn(entries); - for (int i = 0; i < 4; i++) { - when(mockedWhitelist.get(entries.get(i).address())).thenReturn(entries.get(i)); - } - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - Assertions.assertEquals(4, bridgeSupport.getLockWhitelistSize().intValue()); - Assertions.assertNull(bridgeSupport.getLockWhitelistEntryByIndex(-1)); - Assertions.assertNull(bridgeSupport.getLockWhitelistEntryByIndex(4)); - Assertions.assertNull(bridgeSupport.getLockWhitelistEntryByIndex(5)); - Assertions.assertNull(bridgeSupport.getLockWhitelistEntryByAddress(new Address(parameters, BtcECKey.fromPrivate(BigInteger.valueOf(-1)).getPubKeyHash()).toBase58())); - for (int i = 0; i < 4; i++) { - Assertions.assertEquals(entries.get(i), bridgeSupport.getLockWhitelistEntryByIndex(i)); - Assertions.assertEquals(entries.get(i), bridgeSupport.getLockWhitelistEntryByAddress(entries.get(i).address().toBase58())); - } - } - - @Test - void addLockWhitelistAddress_ok() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - when(mockedWhitelist.put(any(Address.class), any(OneOffWhiteListEntry.class))).then((InvocationOnMock m) -> { - Address address = m.
getArgument(0); - Assertions.assertEquals("mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN", address.toBase58()); - return true; - }); - - Assertions.assertEquals(1, bridgeSupport.addOneOffLockWhitelistAddress(mockedTx, "mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN", BigInteger.valueOf(Coin.COIN.getValue())).intValue()); - } - - @Test - void addLockWhitelistAddress_addFails() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - ArgumentCaptor
argument = ArgumentCaptor.forClass(Address.class); - when(mockedWhitelist.isWhitelisted(any(Address.class))).thenReturn(true); - - Assertions.assertEquals(-1, bridgeSupport.addOneOffLockWhitelistAddress(mockedTx, "mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN", BigInteger.valueOf(Coin.COIN.getValue())).intValue()); - verify(mockedWhitelist).isWhitelisted(argument.capture()); - MatcherAssert.assertThat(argument.getValue().toBase58(), is("mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN")); - } - - @Test - void addLockWhitelistAddress_notAuthorized() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = Hex.decode("0000000000000000000000000000000000aabbcc"); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - Assertions.assertEquals(BridgeSupport.LOCK_WHITELIST_GENERIC_ERROR_CODE.intValue(), bridgeSupport.addOneOffLockWhitelistAddress(mockedTx, "mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN", BigInteger.valueOf(Coin.COIN.getValue())).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void addLockWhitelistAddress_invalidAddress() throws IOException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - Assertions.assertEquals(-2, bridgeSupport.addOneOffLockWhitelistAddress(mockedTx, "i-am-invalid", BigInteger.valueOf(Coin.COIN.getValue())).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void setLockWhitelistDisableBlockDelay_ok() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.isDisableBlockSet()).thenReturn(false); - int bestChainHeight = 10; - BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); - StoredBlock storedBlock = mock(StoredBlock.class); - when(storedBlock.getHeight()).thenReturn(bestChainHeight); - BtcBlock btcBlock = mock(BtcBlock.class); - doReturn(Sha256Hash.of(Hex.decode("aa"))).when(btcBlock).getHash(); - doReturn(btcBlock).when(storedBlock).getHeader(); - when(btcBlockStore.getChainHead()).thenReturn(storedBlock); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(mockedWhitelist, btcBlockStore); - - BigInteger disableBlockDelayBI = BigInteger.valueOf(100); - - Assertions.assertEquals(1, bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI).intValue()); - verify(mockedWhitelist, times(1)).setDisableBlockHeight(disableBlockDelayBI.intValue() + bestChainHeight); - } - - @Test - void setLockWhitelistDisableBlockDelay_negativeDisableBlockBI() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.isDisableBlockSet()).thenReturn(false); - int bestChainHeight = 10; - BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); - StoredBlock storedBlock = mock(StoredBlock.class); - when(storedBlock.getHeight()).thenReturn(bestChainHeight); - when(btcBlockStore.getChainHead()).thenReturn(storedBlock); - BtcBlock btcBlock = mock(BtcBlock.class); - doReturn(Sha256Hash.of(Hex.decode("aa"))).when(btcBlock).getHash(); - doReturn(btcBlock).when(storedBlock).getHeader(); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(mockedWhitelist, btcBlockStore); - - BigInteger disableBlockDelayBI = BigInteger.valueOf(-2); - - Assertions.assertEquals(-2, bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void setLockWhitelistDisableBlockDelay_disableBlockDelayBIBiggerThanInt() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.isDisableBlockSet()).thenReturn(false); - BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(mockedWhitelist, btcBlockStore); - //Duplicate Int Max Value by 2 because its signed and add 1 to pass the limit - BigInteger disableBlockDelayBI = BigInteger.valueOf((long) Integer.MAX_VALUE * 2 + 1); - - Assertions.assertThrows(ArithmeticException.class, () -> bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI)); - - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void setLockWhitelistDisableBlockDelay_overflow() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.isDisableBlockSet()).thenReturn(false); - int bestChainHeight = (Integer.MAX_VALUE / 2) + 2; - BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); - StoredBlock storedBlock = mock(StoredBlock.class); - when(storedBlock.getHeight()).thenReturn(bestChainHeight); - when(btcBlockStore.getChainHead()).thenReturn(storedBlock); - BtcBlock btcBlock = mock(BtcBlock.class); - doReturn(Sha256Hash.of(Hex.decode("aa"))).when(btcBlock).getHash(); - doReturn(btcBlock).when(storedBlock).getHeader(); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(mockedWhitelist, btcBlockStore); - - BigInteger disableBlockDelayBI = BigInteger.valueOf(Integer.MAX_VALUE / 2); - - Assertions.assertEquals(-2, bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void setLockWhitelistDisableBlockDelay_maxIntValueDisableBlockBI() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.isDisableBlockSet()).thenReturn(false); - int bestChainHeight = 10; - BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); - StoredBlock storedBlock = mock(StoredBlock.class); - when(storedBlock.getHeight()).thenReturn(bestChainHeight); - when(btcBlockStore.getChainHead()).thenReturn(storedBlock); - BtcBlock btcBlock = mock(BtcBlock.class); - doReturn(Sha256Hash.of(Hex.decode("aa"))).when(btcBlock).getHash(); - doReturn(btcBlock).when(storedBlock).getHeader(); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(mockedWhitelist, btcBlockStore); - - BigInteger disableBlockDelayBI = BigInteger.valueOf(Integer.MAX_VALUE); - - Assertions.assertEquals(-2, bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void setLockWhitelistDisableBlockDelay_disabled() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - when(mockedWhitelist.isDisableBlockSet()).thenReturn(true); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - BigInteger disableBlockDelayBI = BigInteger.valueOf(100); - Assertions.assertEquals(-1, bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void setLockWhitelistDisableBlockDelay_notAuthorized() throws IOException, BlockStoreException { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = Hex.decode("0000000000000000000000000000000000aabbcc"); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - BigInteger disableBlockDelayBI = BigInteger.valueOf(100); - Assertions.assertEquals(-10, bridgeSupport.setLockWhitelistDisableBlockDelay(mockedTx, disableBlockDelayBI).intValue()); - verify(mockedWhitelist, never()).put(any(), any()); - } - - @Test - void removeLockWhitelistAddress_ok() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - when(mockedWhitelist.remove(any(Address.class))).then((InvocationOnMock m) -> { - Address address = m.
getArgument(0); - Assertions.assertEquals("mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN", address.toBase58()); - return true; - }); - - Assertions.assertEquals(1, bridgeSupport.removeLockWhitelistAddress(mockedTx, "mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN").intValue()); - } - - @Test - void removeLockWhitelistAddress_removeFails() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - when(mockedWhitelist.remove(any(Address.class))).then((InvocationOnMock m) -> { - Address address = m.
getArgument(0); - Assertions.assertEquals("mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN", address.toBase58()); - return false; - }); - - Assertions.assertEquals(-1, bridgeSupport.removeLockWhitelistAddress(mockedTx, "mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN").intValue()); - } - - @Test - void removeLockWhitelistAddress_notAuthorized() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = Hex.decode("0000000000000000000000000000000000aabbcc"); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - Assertions.assertEquals(BridgeSupport.LOCK_WHITELIST_GENERIC_ERROR_CODE.intValue(), bridgeSupport.removeLockWhitelistAddress(mockedTx, "mwKcYS3H8FUgrPtyGMv3xWvf4jgeZUkCYN").intValue()); - verify(mockedWhitelist, never()).remove(any()); - } - - @Test - void removeLockWhitelistAddress_invalidAddress() { - Transaction mockedTx = mock(Transaction.class); - byte[] senderBytes = ECKey.fromPublicOnly(Hex.decode( - // Public key hex of the authorized whitelist admin in regtest, taken from BridgeRegTestConstants - "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" - )).getAddress(); - RskAddress sender = new RskAddress(senderBytes); - when(mockedTx.getSender(any(SignatureCache.class))).thenReturn(sender); - LockWhitelist mockedWhitelist = mock(LockWhitelist.class); - BridgeSupport bridgeSupport = getBridgeSupportWithMocksForWhitelistTests(mockedWhitelist); - - Assertions.assertEquals(-2, bridgeSupport.removeLockWhitelistAddress(mockedTx, "i-am-invalid").intValue()); - verify(mockedWhitelist, never()).remove(any()); - } - @Test void getBtcBlockchainInitialBlockHeight() throws IOException { Repository repository = createRepository(); @@ -3477,7 +3276,7 @@ void getBtcBlockchainInitialBlockHeight() throws IOException { BridgeSupport bridgeSupport = getBridgeSupport(null, repository, btcBlockStoreFactory); // As we don't have any checkpoint the genesis block at height 0 should be used and returned - Assertions.assertEquals(0, bridgeSupport.getBtcBlockchainInitialBlockHeight()); + assertEquals(0, bridgeSupport.getBtcBlockchainInitialBlockHeight()); } @Test @@ -3509,7 +3308,7 @@ void getBtcTransactionConfirmations_inexistentBlockHash() throws BlockStoreExcep int confirmations = bridgeSupport.getBtcTransactionConfirmations(btcTransactionHash, blockHash, null); - Assertions.assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_INEXISTENT_BLOCK_HASH_ERROR_CODE.intValue(), confirmations); + assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_INEXISTENT_BLOCK_HASH_ERROR_CODE.intValue(), confirmations); } @Test @@ -3520,7 +3319,6 @@ void getBtcTransactionConfirmations_blockNotInBestChain() throws BlockStoreExcep Repository track = repository.startTracking(); Sha256Hash blockHash = Sha256Hash.of(Hex.decode("aabbcc")); - Sha256Hash blockHashInMainChain = Sha256Hash.of(Hex.decode("334455")); BtcBlock blockHeader = mock(BtcBlock.class); when(blockHeader.getHash()).thenReturn(blockHash); @@ -3536,10 +3334,10 @@ void getBtcTransactionConfirmations_blockNotInBestChain() throws BlockStoreExcep when(btcBlockStore.getStoredBlockAtMainChainHeight(block.getHeight())).thenReturn(null); BridgeStorageProvider provider = new BridgeStorageProvider( - track, - PrecompiledContracts.BRIDGE_ADDR, - bridgeConstants, - activationsBeforeForks + track, + PrecompiledContracts.BRIDGE_ADDR, + bridgeConstants, + activationsBeforeForks ); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); @@ -3551,7 +3349,10 @@ void getBtcTransactionConfirmations_blockNotInBestChain() throws BlockStoreExcep int confirmations = bridgeSupport.getBtcTransactionConfirmations(btcTransactionHash, blockHash, null); - Assertions.assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE.intValue(), confirmations); + assertEquals( + BridgeSupport.BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE.intValue(), + confirmations + ); } @Test @@ -3591,7 +3392,7 @@ void getBtcTransactionConfirmations_blockNotInBestChainBlockWithHeightNotFound() int confirmations = bridgeSupport.getBtcTransactionConfirmations(btcTransactionHash, blockHash, null); - Assertions.assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE.intValue(), confirmations); + assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_BLOCK_NOT_IN_BEST_CHAIN_ERROR_CODE.intValue(), confirmations); } @Test @@ -3630,7 +3431,7 @@ void getBtcTransactionConfirmations_blockTooOld() throws BlockStoreException, IO BridgeSupport bridgeSupport = getBridgeSupport(provider, track, mockFactory, activations); int confirmations = bridgeSupport.getBtcTransactionConfirmations(btcTransactionHash, blockHash, null); - Assertions.assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_BLOCK_TOO_OLD_ERROR_CODE.intValue(), confirmations); + assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_BLOCK_TOO_OLD_ERROR_CODE.intValue(), confirmations); } @Test @@ -3670,7 +3471,7 @@ void getBtcTransactionConfirmations_heightInconsistency() throws BlockStoreExcep BridgeSupport bridgeSupport = getBridgeSupport(provider, track, mockFactory, activations); int confirmations = bridgeSupport.getBtcTransactionConfirmations(btcTransactionHash, blockHash, null); - Assertions.assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_INCONSISTENT_BLOCK_ERROR_CODE.intValue(), confirmations); + assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_INCONSISTENT_BLOCK_ERROR_CODE.intValue(), confirmations); } @Test @@ -3714,7 +3515,7 @@ void getBtcTransactionConfirmations_merkleBranchDoesNotProve() throws BlockStore int confirmations = bridgeSupport.getBtcTransactionConfirmations(btcTransactionHash, blockHash, merkleBranch); - Assertions.assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_INVALID_MERKLE_BRANCH_ERROR_CODE.intValue(), confirmations); + assertEquals(BridgeSupport.BTC_TRANSACTION_CONFIRMATION_INVALID_MERKLE_BRANCH_ERROR_CODE.intValue(), confirmations); } @Test @@ -3753,26 +3554,23 @@ void getBtcTransactionConfirmationsGetCost_ok() throws BlockStoreException { args[3] = new Object[]{}; long cost = bridgeSupport.getBtcTransactionConfirmationsGetCost(args); - Assertions.assertEquals(27_000 + 10 * 315, cost); + assertEquals(27_000 + 10 * 315, cost); } @Test - void getBtcTransactionConfirmationsGetCost_blockDoesNotExist() throws BlockStoreException { + void getBtcTransactionConfirmationsGetCost_blockDoesNotExist() { Repository repository = createRepository(); Repository track = repository.startTracking(); Sha256Hash blockHash = Sha256Hash.of(Hex.decode("aabbcc")); - BtcBlockStoreWithCache btcBlockStore = mock(RepositoryBtcBlockStoreWithCache.class); - BridgeStorageProvider provider = new BridgeStorageProvider( - track, - PrecompiledContracts.BRIDGE_ADDR, - bridgeConstants, - activationsBeforeForks + track, + PrecompiledContracts.BRIDGE_ADDR, + bridgeConstants, + activationsBeforeForks ); - BtcBlock header = mock(BtcBlock.class); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); BridgeSupport bridgeSupport = getBridgeSupport(provider, track, mockFactory); @@ -3781,11 +3579,11 @@ void getBtcTransactionConfirmationsGetCost_blockDoesNotExist() throws BlockStore args[1] = blockHash.getBytes(); long cost = bridgeSupport.getBtcTransactionConfirmationsGetCost(args); - Assertions.assertEquals(27_000, cost); + assertEquals(27_000, cost); } @Test - void getBtcTransactionConfirmationsGetCost_getBestChainHeightError() throws BlockStoreException { + void getBtcTransactionConfirmationsGetCost_getBestChainHeightError() { ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); Repository repository = createRepository(); @@ -3808,25 +3606,21 @@ void getBtcTransactionConfirmationsGetCost_getBestChainHeightError() throws Bloc args[1] = blockHash.getBytes(); long cost = bridgeSupport.getBtcTransactionConfirmationsGetCost(args); - Assertions.assertEquals(27_000, cost); + assertEquals(27_000, cost); } @Test - void getBtcTransactionConfirmationsGetCost_blockTooDeep() throws BlockStoreException { - ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); - + void getBtcTransactionConfirmationsGetCost_blockTooDeep() { Repository repository = createRepository(); Repository track = repository.startTracking(); Sha256Hash blockHash = Sha256Hash.of(Hex.decode("aabbcc")); - BtcBlock header = mock(BtcBlock.class); - BridgeStorageProvider provider = new BridgeStorageProvider( - track, - PrecompiledContracts.BRIDGE_ADDR, - bridgeConstants, - activationsBeforeForks + track, + PrecompiledContracts.BRIDGE_ADDR, + bridgeConstants, + activationsBeforeForks ); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); @@ -3837,7 +3631,7 @@ void getBtcTransactionConfirmationsGetCost_blockTooDeep() throws BlockStoreExcep args[1] = blockHash.getBytes(); long cost = bridgeSupport.getBtcTransactionConfirmationsGetCost(args); - Assertions.assertEquals(27_000, cost); + assertEquals(27_000, cost); } @Test @@ -3862,10 +3656,10 @@ void getBtcBlockchainBlockHashAtDepth() throws Exception { BridgeSupport bridgeSupport = getBridgeSupport(provider, track, mockFactory, activations); StoredBlock chainHead = btcBlockStore.getChainHead(); - Assertions.assertEquals(0, chainHead.getHeight()); - Assertions.assertEquals(btcParams.getGenesisBlock(), chainHead.getHeader()); + assertEquals(0, chainHead.getHeight()); + assertEquals(btcParams.getGenesisBlock(), chainHead.getHeader()); - Assertions.assertEquals(btcParams.getGenesisBlock().getHash(), bridgeSupport.getBtcBlockchainBlockHashAtDepth(0)); + assertEquals(btcParams.getGenesisBlock().getHash(), bridgeSupport.getBtcBlockchainBlockHashAtDepth(0)); try { bridgeSupport.getBtcBlockchainBlockHashAtDepth(-1); Assertions.fail(); @@ -3880,7 +3674,7 @@ void getBtcBlockchainBlockHashAtDepth() throws Exception { List blocks = createBtcBlocks(btcParams, btcParams.getGenesisBlock(), 10); bridgeSupport.receiveHeaders(blocks.toArray(new BtcBlock[]{})); - Assertions.assertEquals(btcParams.getGenesisBlock().getHash(), bridgeSupport.getBtcBlockchainBlockHashAtDepth(10)); + assertEquals(btcParams.getGenesisBlock().getHash(), bridgeSupport.getBtcBlockchainBlockHashAtDepth(10)); try { bridgeSupport.getBtcBlockchainBlockHashAtDepth(-1); Assertions.fail(); @@ -3892,7 +3686,7 @@ void getBtcBlockchainBlockHashAtDepth() throws Exception { } catch (IndexOutOfBoundsException e) { } for (int i = 0; i < 10; i++) { - Assertions.assertEquals(blocks.get(i).getHash(), bridgeSupport.getBtcBlockchainBlockHashAtDepth(9 - i)); + assertEquals(blocks.get(i).getHash(), bridgeSupport.getBtcBlockchainBlockHashAtDepth(9 - i)); } } @@ -3901,7 +3695,7 @@ private BridgeStorageProvider getBridgeStorageProviderMockWithProcessedHashes() for (int i = 0; i < 10; i++) { when(providerMock.getHeightIfBtcTxhashIsAlreadyProcessed(Sha256Hash.of(("hash_" + i).getBytes()))) - .thenReturn(Optional.of(Long.valueOf(i))); + .thenReturn(Optional.of((long) i)); } return providerMock; @@ -3957,8 +3751,8 @@ class FederationHolder { private Federation retiringFederation; private ABICallElection federationElection; - public List retiringUTXOs = new ArrayList<>(); - public List activeUTXOs = new ArrayList<>(); + public final List retiringUTXOs = new ArrayList<>(); + public final List activeUTXOs = new ArrayList<>(); PendingFederation getPendingFederation() { return pendingFederation; @@ -4012,22 +3806,22 @@ public void setFederationElection(ABICallElection federationElection) { } if (holder.getFederationElection() == null) { - AddressBasedAuthorizer auth = m.getArgument(0); + AddressBasedAuthorizer auth = m.getArgument(0); holder.setFederationElection(new ABICallElection(auth)); } return holder.getFederationElection(); }); doAnswer((InvocationOnMock m) -> { - holder.setActiveFederation(m.getArgument(0)); + holder.setActiveFederation(m.getArgument(0)); return null; }).when(providerMock).setNewFederation(any()); doAnswer((InvocationOnMock m) -> { - holder.setRetiringFederation(m.getArgument(0)); + holder.setRetiringFederation(m.getArgument(0)); return null; }).when(providerMock).setOldFederation(any()); doAnswer((InvocationOnMock m) -> { - holder.setPendingFederation(m.getArgument(0)); + holder.setPendingFederation(m.getArgument(0)); return null; }).when(providerMock).setPendingFederation(any()); @@ -4041,20 +3835,6 @@ public void setFederationElection(ABICallElection federationElection) { ); } - private BridgeSupport getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(LockWhitelist mockedWhitelist, BtcBlockStoreWithCache btcBlockStore) { - BridgeStorageProvider providerMock = mock(BridgeStorageProvider.class); - when(providerMock.getLockWhitelist()).thenReturn(mockedWhitelist); - - BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); - when(mockFactory.newInstance(any(), any(), any(), any())).thenReturn(btcBlockStore); - - return getBridgeSupport(providerMock, null, mockFactory); - } - - private BridgeSupport getBridgeSupportWithMocksForWhitelistTests(LockWhitelist mockedWhitelist) { - return getBridgeSupportWithMocksAndBtcBlockstoreForWhitelistTests(mockedWhitelist, null); - } - private BridgeSupport getBridgeSupport(BridgeStorageProvider provider, Repository track) { return getBridgeSupport(bridgeConstants, provider, track, mock(BtcBlockStoreWithCache.Factory.class)); } @@ -4084,10 +3864,6 @@ private BridgeSupport getBridgeSupport( ); } - private BridgeSupport getBridgeSupport(BridgeConstants constants, BridgeStorageProvider provider) { - return getBridgeSupport(constants, provider, null, mock(BridgeEventLogger.class), null, null); - } - private BridgeSupport getBridgeSupport( BridgeConstants constants, BridgeStorageProvider provider, @@ -4169,6 +3945,7 @@ private BridgeSupport getBridgeSupport( new Context(constants.getBtcParams()), new FederationSupport(constants, provider, executionBlock, activations), feePerKbSupport, + whitelistSupport, blockStoreFactory, activations, signatureCache @@ -4184,12 +3961,12 @@ private BtcTransaction createTransaction() { private UTXO createUTXO(Coin value, Address address) { return new UTXO( - PegTestUtils.createHash(1), - 1, - value, - 0, - false, - ScriptBuilder.createOutputScript(address) + BitcoinTestUtils.createHash(1), + 1, + value, + 0, + false, + ScriptBuilder.createOutputScript(address) ); } diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportRegisterBtcTransactionTest.java b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportRegisterBtcTransactionTest.java index c908f539721..768b83f3db8 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportRegisterBtcTransactionTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportRegisterBtcTransactionTest.java @@ -39,6 +39,8 @@ import co.rsk.peg.utils.BridgeEventLogger; import co.rsk.peg.utils.UnrefundablePeginReason; import co.rsk.peg.whitelist.LockWhitelist; +import co.rsk.peg.whitelist.WhitelistStorageProvider; +import co.rsk.peg.whitelist.WhitelistSupportImpl; import co.rsk.test.builders.BridgeSupportBuilder; import java.io.IOException; import java.math.BigInteger; @@ -66,6 +68,7 @@ class BridgeSupportRegisterBtcTransactionTest { private static final ActivationConfig.ForBlock fingerrootActivations = ActivationConfigsForTest.fingerroot500().forBlock(0); private static final ActivationConfig.ForBlock arrowhead600Activations = ActivationConfigsForTest.arrowhead600().forBlock(0); private static final ActivationConfig.ForBlock lovell700Activations = ActivationConfigsForTest.lovell700().forBlock(0); + private WhitelistStorageProvider whitelistStorageProvider; private static final Coin minimumPeginTxValue = bridgeMainnetConstants.getMinimumPeginTxValue(ActivationConfigsForTest.all().forBlock(0)); private static final Coin belowMinimumPeginTxValue = minimumPeginTxValue.minus(Coin.SATOSHI); @@ -429,8 +432,9 @@ void init() throws IOException { when(provider.getHeightIfBtcTxhashIsAlreadyProcessed(any(Sha256Hash.class))).thenReturn(Optional.empty()); LockWhitelist lockWhitelist = mock(LockWhitelist.class); + whitelistStorageProvider = mock(WhitelistStorageProvider.class); when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(provider.getLockWhitelist()).thenReturn(lockWhitelist); + when(whitelistStorageProvider.getLockWhitelist(lovell700Activations, btcMainnetParams)).thenReturn(lockWhitelist); when(provider.getOldFederationBtcUTXOs()) .thenReturn(retiringFederationUtxos); @@ -529,6 +533,11 @@ private BridgeSupport buildBridgeSupport(ActivationConfig.ForBlock activations) feePerKbStorageProvider ); + LockWhitelist lockWhitelist = mock(LockWhitelist.class); + whitelistStorageProvider = mock(WhitelistStorageProvider.class); + when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); + when(whitelistStorageProvider.getLockWhitelist(activations, btcMainnetParams)).thenReturn(lockWhitelist); + return new BridgeSupportBuilder() .withBtcBlockStoreFactory(mockFactory) .withBridgeConstants(bridgeMainnetConstants) @@ -541,6 +550,7 @@ private BridgeSupport buildBridgeSupport(ActivationConfig.ForBlock activations) .withPeginInstructionsProvider(peginInstructionsProvider) .withExecutionBlock(rskExecutionBlock) .withFeePerKbSupport(feePerKbSupport) + .withWhitelistSupport(new WhitelistSupportImpl(bridgeMainnetConstants.getWhitelistConstants(), whitelistStorageProvider, activations, mock(SignatureCache.class))) .build(); } @@ -2509,7 +2519,7 @@ void old_fed_migration( LockWhitelist lockWhitelist = mock(LockWhitelist.class); when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(provider.getLockWhitelist()).thenReturn(lockWhitelist); + when(whitelistStorageProvider.getLockWhitelist(lovell700Activations, btcMainnetParams)).thenReturn(lockWhitelist); when(provider.getNewFederationBtcUTXOs()).thenReturn(activeFederationUtxos); diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java index c63c0c185ee..73dc4f2b047 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java @@ -24,10 +24,12 @@ import co.rsk.bitcoinj.store.BlockStoreException; import co.rsk.bitcoinj.wallet.Wallet; import co.rsk.blockchain.utils.BlockGenerator; +import co.rsk.net.utils.TransactionUtils; import co.rsk.peg.constants.*; import co.rsk.core.RskAddress; import co.rsk.crypto.Keccak256; import co.rsk.peg.feeperkb.FeePerKbResponseCode; +import co.rsk.peg.feeperkb.FeePerKbStorageProvider; import co.rsk.peg.feeperkb.FeePerKbSupport; import co.rsk.peg.bitcoin.BitcoinTestUtils; import co.rsk.peg.bitcoin.CoinbaseInformation; @@ -36,14 +38,16 @@ import co.rsk.peg.btcLockSender.BtcLockSender.TxSenderAddressType; import co.rsk.peg.btcLockSender.BtcLockSenderProvider; import co.rsk.peg.federation.*; +import co.rsk.peg.feeperkb.FeePerKbSupportImpl; import co.rsk.peg.pegininstructions.*; +import co.rsk.peg.storage.StorageAccessor; import co.rsk.peg.utils.BridgeEventLogger; import co.rsk.peg.utils.MerkleTreeUtils; import co.rsk.peg.pegin.RejectedPeginReason; import co.rsk.peg.utils.UnrefundablePeginReason; import co.rsk.peg.vote.AddressBasedAuthorizer; -import co.rsk.peg.whitelist.LockWhitelist; -import co.rsk.peg.whitelist.OneOffWhiteListEntry; +import co.rsk.peg.whitelist.*; +import co.rsk.peg.whitelist.constants.WhitelistMainNetConstants; import co.rsk.test.builders.BridgeSupportBuilder; import co.rsk.util.HexUtils; import org.bouncycastle.util.encoders.Hex; @@ -85,8 +89,11 @@ class BridgeSupportTest { private final BridgeConstants bridgeConstantsRegtest = BridgeRegTestConstants.getInstance(); + private final BridgeConstants bridgeMainNetConstants = BridgeMainNetConstants.getInstance(); protected final NetworkParameters btcRegTestParams = bridgeConstantsRegtest.getBtcParams(); private BridgeSupportBuilder bridgeSupportBuilder; + private WhitelistSupport whitelistSupport; + private WhitelistStorageProvider whitelistStorageProvider; private static final String TO_ADDRESS = "0000000000000000000000000000000000000006"; private static final BigInteger DUST_AMOUNT = new BigInteger("1"); @@ -108,6 +115,9 @@ void setUpOnEachTest() { activationsAfterForks = ActivationConfigsForTest.all().forBlock(0); signatureCache = new BlockTxSignatureCache(new ReceivedTxSignatureCache()); bridgeSupportBuilder = new BridgeSupportBuilder(); + StorageAccessor inMemoryStorageAccessor = new InMemoryStorage(); + whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorageAccessor); + whitelistSupport = new WhitelistSupportImpl(WhitelistMainNetConstants.getInstance(), whitelistStorageProvider, mock(ActivationConfig.ForBlock.class), signatureCache); } @Test @@ -151,6 +161,119 @@ void voteFeePerKbChange_success() { assertEquals(FeePerKbResponseCode.SUCCESSFUL_VOTE.getCode(), result); } + @Nested + @Tag("Whitelist") + class WhitelistTest { + private WhitelistSupport whitelistSupport; + private BridgeSupport bridgeSupport; + + @BeforeEach + void setUp() { + whitelistSupport = mock(WhitelistSupportImpl.class); + bridgeSupport = bridgeSupportBuilder + .withWhitelistSupport(whitelistSupport) + .build(); + } + + @Test + void getLockWhitelistSize() { + when(whitelistSupport.getLockWhitelistSize()).thenReturn(10); + + assertEquals(10, bridgeSupport.getLockWhitelistSize()); + } + + @Test + void getLockWhitelistEntryByIndex() { + LockWhitelistEntry entry = mock(LockWhitelistEntry.class); + when(whitelistSupport.getLockWhitelistEntryByIndex(0)).thenReturn(entry); + + assertEquals(entry, bridgeSupport.getLockWhitelistEntryByIndex(0)); + } + + @Test + void getLockWhitelistEntryByAddress() { + LockWhitelistEntry entry = mock(LockWhitelistEntry.class); + when(whitelistSupport.getLockWhitelistEntryByAddress("address")).thenReturn(entry); + + assertEquals(entry, bridgeSupport.getLockWhitelistEntryByAddress("address")); + } + + @Test + void addOneOffLockWhitelistAddress() { + Transaction tx = mock(Transaction.class); + String address = "address"; + BigInteger maxTransferValue = BigInteger.ONE; + when(whitelistSupport.addOneOffLockWhitelistAddress(tx, address, maxTransferValue)).thenReturn(WhitelistResponseCode.SUCCESS.getCode()); + + int result = bridgeSupport.addOneOffLockWhitelistAddress(tx, address, maxTransferValue); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), result); + } + + @Test + void addUnlimitedLockWhitelistAddress() { + Transaction tx = mock(Transaction.class); + String address = "address"; + when(whitelistSupport.addUnlimitedLockWhitelistAddress(tx, address)).thenReturn(WhitelistResponseCode.SUCCESS.getCode()); + + int result = bridgeSupport.addUnlimitedLockWhitelistAddress(tx, address); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), result); + } + + @Test + void removeLockWhitelistAddress() { + Transaction tx = mock(Transaction.class); + String address = "address"; + when(whitelistSupport.removeLockWhitelistAddress(tx, address)).thenReturn(WhitelistResponseCode.SUCCESS.getCode()); + + int result = bridgeSupport.removeLockWhitelistAddress(tx, address); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), result); + } + + @Test + void setLockWhitelistDisableBlockDelay() throws BlockStoreException, IOException { + // Set of Variables to be use in setLockWhitelistDisableBlockDelay + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + BigInteger disableBlockDelayBI = BigInteger.ONE; + when(whitelistSupport.setLockWhitelistDisableBlockDelay(tx, disableBlockDelayBI, 0)).thenReturn(WhitelistResponseCode.SUCCESS.getCode()); + + // Set of variables to be use in bridgeSupportBuilder + BridgeStorageProvider provider = mock(BridgeStorageProvider.class); + Repository rskRepository = mock(Repository.class); + BridgeConstants bridgeConstantsMainNet = BridgeMainNetConstants.getInstance(); + BtcBlockStoreWithCache.Factory btcBlockStoreFactory = mock(BtcBlockStoreWithCache.Factory.class); + ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); + + bridgeSupport = bridgeSupportBuilder + .withWhitelistSupport(whitelistSupport) + .withProvider(provider) + .withRepository(rskRepository) + .withBridgeConstants(bridgeConstantsMainNet) + .withBtcBlockStoreFactory(btcBlockStoreFactory) + .withActivations(activations) + .build(); + + // Set of variables to be used mocking + BtcBlockStoreWithCache btcBlockStore = mock(BtcBlockStoreWithCache.class); + StoredBlock storedBlock = mock(StoredBlock.class); + BtcBlock btcBlock = mock(BtcBlock.class); + NetworkParameters btcParams = bridgeConstantsMainNet.getBtcParams(); + BtcBlock genesisBtcBlock = btcParams.getGenesisBlock(); + Sha256Hash genesisBtcBlockHash = genesisBtcBlock.getHash(); + + when(btcBlockStore.getChainHead()).thenReturn(storedBlock); + when(storedBlock.getHeader()).thenReturn(btcBlock); + when(btcBlock.getHash()).thenReturn(genesisBtcBlockHash); + when(btcBlockStoreFactory.newInstance(rskRepository, bridgeConstantsMainNet, provider, activations)).thenReturn(btcBlockStore); + + int result = bridgeSupport.setLockWhitelistDisableBlockDelay(tx, disableBlockDelayBI); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), result); + } + } + @Test void getLockingCap() { ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); @@ -423,14 +546,13 @@ void eventLoggerLogLockBtc_before_rskip_146_activation() throws Exception { when(activations.isActive(ConsensusRule.RSKIP146)).thenReturn(false); BridgeEventLogger mockedEventLogger = mock(BridgeEventLogger.class); - Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeConstantsRegtest); + Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeMainNetConstants); BridgeStorageProvider mockBridgeStorageProvider = mock(BridgeStorageProvider.class); when(mockBridgeStorageProvider.getHeightIfBtcTxhashIsAlreadyProcessed(any(Sha256Hash.class))).thenReturn(Optional.empty()); LockWhitelist lockWhitelist = mock(LockWhitelist.class); when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(mockBridgeStorageProvider.getLockWhitelist()).thenReturn(lockWhitelist); when(mockBridgeStorageProvider.getNewFederation()).thenReturn(genesisFederation); Block executionBlock = mock(Block.class); @@ -441,7 +563,7 @@ void eventLoggerLogLockBtc_before_rskip_146_activation() throws Exception { // Create transaction Coin lockValue = Coin.COIN; - BtcTransaction tx = new BtcTransaction(bridgeConstantsRegtest.getBtcParams()); + BtcTransaction tx = new BtcTransaction(bridgeMainNetConstants.getBtcParams()); tx.addOutput(lockValue, mockBridgeStorageProvider.getNewFederation().getAddress()); BtcECKey srcKey = new BtcECKey(); tx.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey)); @@ -451,24 +573,28 @@ void eventLoggerLogLockBtc_before_rskip_146_activation() throws Exception { bits[0] = 0x3f; List hashes = new ArrayList<>(); hashes.add(tx.getHash()); - PartialMerkleTree pmt = new PartialMerkleTree(bridgeConstantsRegtest.getBtcParams(), bits, hashes, 1); + PartialMerkleTree pmt = new PartialMerkleTree(bridgeMainNetConstants.getBtcParams(), bits, hashes, 1); Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(new ArrayList<>()); co.rsk.bitcoinj.core.BtcBlock btcBlock = - new co.rsk.bitcoinj.core.BtcBlock(bridgeConstantsRegtest.getBtcParams(), 1, PegTestUtils.createHash(), merkleRoot, + new co.rsk.bitcoinj.core.BtcBlock(bridgeMainNetConstants.getBtcParams(), 1, PegTestUtils.createHash(), merkleRoot, 1, 1, 1, new ArrayList<>()); int height = 1; - mockChainOfStoredBlocks(btcBlockStore, btcBlock, height + bridgeConstantsRegtest.getBtc2RskMinimumAcceptableConfirmations(), height); + mockChainOfStoredBlocks(btcBlockStore, btcBlock, height + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations(), height); + + FeePerKbSupport feePerKbSupport = new FeePerKbSupportImpl(bridgeMainNetConstants.getFeePerKbConstants(), mock(FeePerKbStorageProvider.class)); + when(mockBridgeStorageProvider.getPegoutsWaitingForConfirmations()).thenReturn(mock(PegoutsWaitingForConfirmations.class)); BridgeSupport bridgeSupport = bridgeSupportBuilder - .withBridgeConstants(bridgeConstantsRegtest) + .withBridgeConstants(bridgeMainNetConstants) .withProvider(mockBridgeStorageProvider) .withEventLogger(mockedEventLogger) .withBtcLockSenderProvider(new BtcLockSenderProvider()) .withPeginInstructionsProvider(new PeginInstructionsProvider()) .withExecutionBlock(executionBlock) .withBtcBlockStoreFactory(btcBlockStoreFactory) + .withFeePerKbSupport(feePerKbSupport) .withActivations(activations) .build(); @@ -482,16 +608,12 @@ void eventLoggerLogLockBtc_after_rskip_146_activation() throws Exception { ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); when(activations.isActive(ConsensusRule.RSKIP146)).thenReturn(true); - Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeConstantsRegtest); + Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeMainNetConstants); BridgeEventLogger mockedEventLogger = mock(BridgeEventLogger.class); BridgeStorageProvider mockBridgeStorageProvider = mock(BridgeStorageProvider.class); when(mockBridgeStorageProvider.getHeightIfBtcTxhashIsAlreadyProcessed(any(Sha256Hash.class))).thenReturn(Optional.empty()); - - LockWhitelist lockWhitelist = mock(LockWhitelist.class); - when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(mockBridgeStorageProvider.getLockWhitelist()).thenReturn(lockWhitelist); when(mockBridgeStorageProvider.getNewFederation()).thenReturn(genesisFederation); Block executionBlock = mock(Block.class); @@ -502,20 +624,29 @@ void eventLoggerLogLockBtc_after_rskip_146_activation() throws Exception { // Create transaction Coin lockValue = Coin.COIN; - BtcTransaction tx = new BtcTransaction(bridgeConstantsRegtest.getBtcParams()); + BtcTransaction tx = new BtcTransaction(bridgeMainNetConstants.getBtcParams()); tx.addOutput(lockValue, mockBridgeStorageProvider.getNewFederation().getAddress()); BtcECKey srcKey = new BtcECKey(); tx.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey)); + // Get the tx sender public key + byte[] data = tx.getInput(0).getScriptSig().getChunks().get(1).data; + BtcECKey senderBtcKey = BtcECKey.fromPublicOnly(data); + + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, bridgeMainNetConstants.getBtcParams()); + Address address = senderBtcKey.toAddress(bridgeMainNetConstants.getBtcParams()); + whitelist.put(address, new OneOffWhiteListEntry(address, lockValue)); + // Create header and PMT byte[] bits = new byte[1]; bits[0] = 0x3f; List hashes = new ArrayList<>(); hashes.add(tx.getHash()); - PartialMerkleTree pmt = new PartialMerkleTree(bridgeConstantsRegtest.getBtcParams(), bits, hashes, 1); + PartialMerkleTree pmt = new PartialMerkleTree(bridgeMainNetConstants.getBtcParams(), bits, hashes, 1); Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(new ArrayList<>()); co.rsk.bitcoinj.core.BtcBlock btcBlock = new co.rsk.bitcoinj.core.BtcBlock( - bridgeConstantsRegtest.getBtcParams(), + bridgeMainNetConstants.getBtcParams(), 1, BitcoinTestUtils.createHash(1), merkleRoot, @@ -530,13 +661,20 @@ void eventLoggerLogLockBtc_after_rskip_146_activation() throws Exception { mockChainOfStoredBlocks( btcBlockStore, btcBlock, - height + bridgeConstantsRegtest.getBtc2RskMinimumAcceptableConfirmations(), + height + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations(), height ); + FeePerKbSupport feePerKbSupport = new FeePerKbSupportImpl(bridgeMainNetConstants.getFeePerKbConstants(), mock(FeePerKbStorageProvider.class)); + when(mockBridgeStorageProvider.getPegoutsWaitingForConfirmations()).thenReturn(mock(PegoutsWaitingForConfirmations.class)); + Transaction rskTx = mock(Transaction.class); + when(rskTx.getHash()).thenReturn(Keccak256.ZERO_HASH); + BridgeSupport bridgeSupport = bridgeSupportBuilder - .withBridgeConstants(bridgeConstantsRegtest) + .withBridgeConstants(bridgeMainNetConstants) .withProvider(mockBridgeStorageProvider) + .withFeePerKbSupport(feePerKbSupport) + .withWhitelistSupport(whitelistSupport) .withEventLogger(mockedEventLogger) .withBtcLockSenderProvider(new BtcLockSenderProvider()) .withPeginInstructionsProvider(new PeginInstructionsProvider()) @@ -545,7 +683,7 @@ void eventLoggerLogLockBtc_after_rskip_146_activation() throws Exception { .withActivations(activations) .build(); - bridgeSupport.registerBtcTransaction(mock(Transaction.class), tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); + bridgeSupport.registerBtcTransaction(rskTx, tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); verify(mockedEventLogger, atLeastOnce()).logLockBtc(any(RskAddress.class), any(BtcTransaction.class), any(Address.class), any(Coin.class)); } @Test @@ -562,7 +700,8 @@ void eventLoggerLogPeginRejectionEvents_before_rskip_181_activation() throws Exc LockWhitelist lockWhitelist = mock(LockWhitelist.class); when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(mockBridgeStorageProvider.getLockWhitelist()).thenReturn(lockWhitelist); + WhitelistStorageProvider whitelistProvider = mock(WhitelistStorageProvider.class); + when(whitelistProvider.getLockWhitelist(activations, btcRegTestParams)).thenReturn(lockWhitelist); when(mockBridgeStorageProvider.getNewFederation()).thenReturn(genesisFederation); Block executionBlock = mock(Block.class); @@ -630,7 +769,8 @@ void eventLoggerLogPeginRejectionEvents_after_rskip_181_activation() throws Exce LockWhitelist lockWhitelist = mock(LockWhitelist.class); when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(mockBridgeStorageProvider.getLockWhitelist()).thenReturn(lockWhitelist); + WhitelistStorageProvider whitelistProvider = mock(WhitelistStorageProvider.class); + when(whitelistProvider.getLockWhitelist(activations, btcRegTestParams)).thenReturn(lockWhitelist); when(mockBridgeStorageProvider.getNewFederation()).thenReturn(genesisFederation); Block executionBlock = mock(Block.class); @@ -691,14 +831,10 @@ void eventLoggerLogPeginBtc_before_rskip_170_activation() throws Exception { when(activations.isActive(ConsensusRule.RSKIP170)).thenReturn(false); BridgeEventLogger mockedEventLogger = mock(BridgeEventLogger.class); - Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeConstantsRegtest); + Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeMainNetConstants); BridgeStorageProvider mockBridgeStorageProvider = mock(BridgeStorageProvider.class); when(mockBridgeStorageProvider.getHeightIfBtcTxhashIsAlreadyProcessed(any(Sha256Hash.class))).thenReturn(Optional.empty()); - - LockWhitelist lockWhitelist = mock(LockWhitelist.class); - when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(mockBridgeStorageProvider.getLockWhitelist()).thenReturn(lockWhitelist); when(mockBridgeStorageProvider.getNewFederation()).thenReturn(genesisFederation); Block executionBlock = mock(Block.class); @@ -709,29 +845,45 @@ void eventLoggerLogPeginBtc_before_rskip_170_activation() throws Exception { // Create transaction Coin lockValue = Coin.COIN; - BtcTransaction tx = new BtcTransaction(bridgeConstantsRegtest.getBtcParams()); + BtcTransaction tx = new BtcTransaction(bridgeMainNetConstants.getBtcParams()); tx.addOutput(lockValue, mockBridgeStorageProvider.getNewFederation().getAddress()); BtcECKey srcKey = new BtcECKey(); tx.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey)); + // Get the tx sender public key + byte[] data = tx.getInput(0).getScriptSig().getChunks().get(1).data; + BtcECKey senderBtcKey = BtcECKey.fromPublicOnly(data); + + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, bridgeMainNetConstants.getBtcParams()); + Address address = senderBtcKey.toAddress(bridgeMainNetConstants.getBtcParams()); + whitelist.put(address, new OneOffWhiteListEntry(address, lockValue)); + // Create header and PMT byte[] bits = new byte[1]; bits[0] = 0x3f; List hashes = new ArrayList<>(); hashes.add(tx.getHash()); - PartialMerkleTree pmt = new PartialMerkleTree(bridgeConstantsRegtest.getBtcParams(), bits, hashes, 1); + PartialMerkleTree pmt = new PartialMerkleTree(bridgeMainNetConstants.getBtcParams(), bits, hashes, 1); Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(new ArrayList<>()); co.rsk.bitcoinj.core.BtcBlock btcBlock = - new co.rsk.bitcoinj.core.BtcBlock(bridgeConstantsRegtest.getBtcParams(), 1, PegTestUtils.createHash(), merkleRoot, + new co.rsk.bitcoinj.core.BtcBlock(bridgeMainNetConstants.getBtcParams(), 1, PegTestUtils.createHash(), merkleRoot, 1, 1, 1, new ArrayList<>()); int height = 1; - mockChainOfStoredBlocks(btcBlockStore, btcBlock, height + bridgeConstantsRegtest.getBtc2RskMinimumAcceptableConfirmations(), height); + mockChainOfStoredBlocks(btcBlockStore, btcBlock, height + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations(), height); + + FeePerKbSupport feePerKbSupport = new FeePerKbSupportImpl(bridgeMainNetConstants.getFeePerKbConstants(), mock(FeePerKbStorageProvider.class)); + when(mockBridgeStorageProvider.getPegoutsWaitingForConfirmations()).thenReturn(mock(PegoutsWaitingForConfirmations.class)); + Transaction rskTx = mock(Transaction.class); + when(rskTx.getHash()).thenReturn(Keccak256.ZERO_HASH); BridgeSupport bridgeSupport = bridgeSupportBuilder - .withBridgeConstants(bridgeConstantsRegtest) + .withBridgeConstants(bridgeMainNetConstants) .withProvider(mockBridgeStorageProvider) + .withFeePerKbSupport(feePerKbSupport) + .withWhitelistSupport(whitelistSupport) .withEventLogger(mockedEventLogger) .withBtcLockSenderProvider(new BtcLockSenderProvider()) .withPeginInstructionsProvider(new PeginInstructionsProvider()) @@ -740,7 +892,7 @@ void eventLoggerLogPeginBtc_before_rskip_170_activation() throws Exception { .withActivations(activations) .build(); - bridgeSupport.registerBtcTransaction(mock(Transaction.class), tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); + bridgeSupport.registerBtcTransaction(rskTx, tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); verify(mockedEventLogger, atLeastOnce()).logLockBtc(any(RskAddress.class), any(BtcTransaction.class), any(Address.class), any(Coin.class)); verify(mockedEventLogger, never()).logPeginBtc(any(RskAddress.class), any(BtcTransaction.class), any(Coin.class), anyInt()); @@ -753,14 +905,10 @@ void eventLoggerLogPeginBtc_after_rskip_170_activation() throws Exception { when(activations.isActive(ConsensusRule.RSKIP170)).thenReturn(true); BridgeEventLogger mockedEventLogger = mock(BridgeEventLogger.class); - Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeConstantsRegtest); + Federation genesisFederation = FederationTestUtils.getGenesisFederation(bridgeMainNetConstants); BridgeStorageProvider mockBridgeStorageProvider = mock(BridgeStorageProvider.class); when(mockBridgeStorageProvider.getHeightIfBtcTxhashIsAlreadyProcessed(any(Sha256Hash.class))).thenReturn(Optional.empty()); - - LockWhitelist lockWhitelist = mock(LockWhitelist.class); - when(lockWhitelist.isWhitelistedFor(any(Address.class), any(Coin.class), any(int.class))).thenReturn(true); - when(mockBridgeStorageProvider.getLockWhitelist()).thenReturn(lockWhitelist); when(mockBridgeStorageProvider.getNewFederation()).thenReturn(genesisFederation); Block executionBlock = mock(Block.class); @@ -771,39 +919,55 @@ void eventLoggerLogPeginBtc_after_rskip_170_activation() throws Exception { // Create transaction Coin lockValue = Coin.COIN; - BtcTransaction tx = new BtcTransaction(bridgeConstantsRegtest.getBtcParams()); + BtcTransaction tx = new BtcTransaction(bridgeMainNetConstants.getBtcParams()); tx.addOutput(lockValue, mockBridgeStorageProvider.getNewFederation().getAddress()); BtcECKey srcKey = new BtcECKey(); tx.addInput(BitcoinTestUtils.createHash(1), 0, ScriptBuilder.createInputScript(null, srcKey)); + // Get the tx sender public key + byte[] data = tx.getInput(0).getScriptSig().getChunks().get(1).data; + BtcECKey senderBtcKey = BtcECKey.fromPublicOnly(data); + + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, bridgeMainNetConstants.getBtcParams()); + Address address = senderBtcKey.toAddress(bridgeMainNetConstants.getBtcParams()); + whitelist.put(address, new OneOffWhiteListEntry(address, lockValue)); + // Create header and PMT byte[] bits = new byte[1]; bits[0] = 0x3f; List hashes = new ArrayList<>(); hashes.add(tx.getHash()); - PartialMerkleTree pmt = new PartialMerkleTree(bridgeConstantsRegtest.getBtcParams(), bits, hashes, 1); + PartialMerkleTree pmt = new PartialMerkleTree(bridgeMainNetConstants.getBtcParams(), bits, hashes, 1); Sha256Hash merkleRoot = pmt.getTxnHashAndMerkleRoot(new ArrayList<>()); co.rsk.bitcoinj.core.BtcBlock btcBlock = - new co.rsk.bitcoinj.core.BtcBlock(bridgeConstantsRegtest.getBtcParams(), 1, BitcoinTestUtils.createHash(1), merkleRoot, + new co.rsk.bitcoinj.core.BtcBlock(bridgeMainNetConstants.getBtcParams(), 1, BitcoinTestUtils.createHash(1), merkleRoot, 1, 1, 1, new ArrayList<>()); int height = 1; mockChainOfStoredBlocks(btcBlockStore, btcBlock, - height + bridgeConstantsRegtest.getBtc2RskMinimumAcceptableConfirmations(), height); + height + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations(), height); + + FeePerKbSupport feePerKbSupport = new FeePerKbSupportImpl(bridgeMainNetConstants.getFeePerKbConstants(), mock(FeePerKbStorageProvider.class)); + when(mockBridgeStorageProvider.getPegoutsWaitingForConfirmations()).thenReturn(mock(PegoutsWaitingForConfirmations.class)); + Transaction rskTx = mock(Transaction.class); + when(rskTx.getHash()).thenReturn(Keccak256.ZERO_HASH); BridgeSupport bridgeSupport = bridgeSupportBuilder - .withBridgeConstants(bridgeConstantsRegtest) + .withBridgeConstants(bridgeMainNetConstants) .withProvider(mockBridgeStorageProvider) .withEventLogger(mockedEventLogger) .withBtcLockSenderProvider(new BtcLockSenderProvider()) .withPeginInstructionsProvider(new PeginInstructionsProvider()) .withExecutionBlock(executionBlock) .withBtcBlockStoreFactory(btcBlockStoreFactory) + .withFeePerKbSupport(feePerKbSupport) + .withWhitelistSupport(whitelistSupport) .withActivations(activations) .build(); - bridgeSupport.registerBtcTransaction(mock(Transaction.class), tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); + bridgeSupport.registerBtcTransaction(rskTx, tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); verify(mockedEventLogger, never()).logLockBtc(any(RskAddress.class), any(BtcTransaction.class), any(Address.class), any(Coin.class)); verify(mockedEventLogger, atLeastOnce()).logPeginBtc(any(RskAddress.class), any(BtcTransaction.class), any(Coin.class), anyInt()); @@ -1241,7 +1405,8 @@ void registerBtcTransaction_sending_segwit_tx_twice_locks_just_once() throws Blo BridgeStorageProvider provider = mock(BridgeStorageProvider.class); when(provider.getNewFederation()).thenReturn(fed); when(provider.getCoinbaseInformation(registerHeader.getHash())).thenReturn(new CoinbaseInformation(witnessMerkleRoot)); - when(provider.getLockWhitelist()).thenReturn(new LockWhitelist(new HashMap<>(), 0)); + WhitelistStorageProvider whitelistProvider = mock(WhitelistStorageProvider.class); + when(whitelistProvider.getLockWhitelist(activationsBeforeForks, btcRegTestParams)).thenReturn(new LockWhitelist(new HashMap<>(), 0)); when(provider.getLockingCap()).thenReturn(Coin.FIFTY_COINS); // mock an actual store for the processed txs HashMap processedTxs = new HashMap<>(); @@ -1259,6 +1424,9 @@ void registerBtcTransaction_sending_segwit_tx_twice_locks_just_once() throws Blo Block executionBlock = mock(Block.class); when(executionBlock.getNumber()).thenReturn(666L); + FeePerKbSupport feePerKbSupport = new FeePerKbSupportImpl(bridgeConstantsRegtest.getFeePerKbConstants(), mock(FeePerKbStorageProvider.class)); + when(provider.getPegoutsWaitingForConfirmations()).thenReturn(mock(PegoutsWaitingForConfirmations.class)); + BridgeSupport bridgeSupport = bridgeSupportBuilder .withBridgeConstants(bridgeConstantsRegtest) .withProvider(provider) @@ -1266,6 +1434,7 @@ void registerBtcTransaction_sending_segwit_tx_twice_locks_just_once() throws Blo .withPeginInstructionsProvider(new PeginInstructionsProvider()) .withExecutionBlock(executionBlock) .withBtcBlockStoreFactory(mockFactory) + .withFeePerKbSupport(feePerKbSupport) .withActivations(mockedActivations) .build(); @@ -2522,8 +2691,8 @@ void when_registerBtcTransaction_usesLegacyType_beforeFork_lock_and_no_refund() BridgeStorageProvider provider = new BridgeStorageProvider(repository, contractAddress, bridgeConstantsRegtest, activations); provider.setNewFederation(federation1); - // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, btcRegTestParams); whitelist.put(btcAddress, new OneOffWhiteListEntry(btcAddress, Coin.COIN.multiply(5))); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); @@ -2611,7 +2780,7 @@ void when_registerBtcTransaction_usesLegacyType_afterFork_notWhitelisted_no_lock provider.setNewFederation(federation1); // Don't whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, btcRegTestParams); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); when(mockFactory.newInstance(repository, bridgeConstantsRegtest, provider, activations)).thenReturn(btcBlockStore); @@ -2711,8 +2880,8 @@ void when_registerBtcTransaction_usesLegacyType_afterFork_lock_and_no_refund() t BridgeStorageProvider provider = new BridgeStorageProvider(repository, contractAddress, bridgeConstantsRegtest, activations); provider.setNewFederation(federation1); - //Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + //Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activationsBeforeForks, btcRegTestParams); whitelist.put(btcAddress, new OneOffWhiteListEntry(btcAddress, Coin.COIN.multiply(5))); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); @@ -2876,8 +3045,8 @@ void when_registerBtcTransaction_usesSegCompatibilityType_afterFork_lock_and_no_ BridgeStorageProvider provider = new BridgeStorageProvider(repository, contractAddress, bridgeConstantsRegtest, activations); provider.setNewFederation(federation1); - // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activationsBeforeForks, btcRegTestParams); whitelist.put(btcAddress, new OneOffWhiteListEntry(btcAddress, amountToLock)); BtcBlockStoreWithCache.Factory mockFactory = mock(BtcBlockStoreWithCache.Factory.class); @@ -3550,8 +3719,8 @@ void registerBtcTransaction_accepts_lock_tx_with_witness_after_rskip_143_activat ); provider.setNewFederation(federation1); - // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activationsBeforeForks, btcRegTestParams); whitelist.put(btcAddress, new OneOffWhiteListEntry(btcAddress, Coin.COIN.multiply(10))); BridgeSupport bridgeSupport = getBridgeSupport( @@ -3918,8 +4087,8 @@ void registerBtcTransaction_accepts_lock_tx_without_witness_after_rskip_143_acti BridgeStorageProvider provider = new BridgeStorageProvider(repository, contractAddress, bridgeConstantsRegtest, activations); provider.setNewFederation(federation1); - // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activationsBeforeForks, btcRegTestParams); whitelist.put(btcAddress, new OneOffWhiteListEntry(btcAddress, Coin.COIN.multiply(10))); BridgeSupport bridgeSupport = getBridgeSupport( @@ -4127,8 +4296,8 @@ void registerBtcTransaction_ignores_pegin_instructions_before_rskip_170_activati ); provider.setNewFederation(federation1); - // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activationsBeforeForks, btcRegTestParams); whitelist.put(btcAddressFromBtcLockSender, new OneOffWhiteListEntry(btcAddressFromBtcLockSender, amountToLock)); BtcLockSenderProvider btcLockSenderProvider = getBtcLockSenderProvider( @@ -5707,6 +5876,7 @@ void validationsForRegisterBtcTransaction_invalid_block_merkle_root() throws IOE mock(Context.class), mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, btcBlockStoreFactory, mock(ActivationConfig.ForBlock.class), signatureCache @@ -5762,6 +5932,7 @@ void validationsForRegisterBtcTransaction_successful() throws IOException, Block mock(Context.class), mock(FederationSupport.class), feePerKbSupport, + whitelistSupport, btcBlockStoreFactory, mock(ActivationConfig.ForBlock.class), signatureCache @@ -6510,7 +6681,8 @@ private void assertRefundInProcessPegInVersionLegacy( LockWhitelist lockWhitelist = mock(LockWhitelist.class); when(lockWhitelist.isWhitelistedFor(eq(btcAddress), any(Coin.class), any(int.class))).thenReturn(isWhitelisted); - when(provider.getLockWhitelist()).thenReturn(lockWhitelist); + WhitelistStorageProvider whitelistProvider = mock(WhitelistStorageProvider.class); + when(whitelistProvider.getLockWhitelist(activations, btcRegTestParams)).thenReturn(lockWhitelist); PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations = new PegoutsWaitingForConfirmations(new HashSet<>()); when(provider.getPegoutsWaitingForConfirmations()).thenReturn(pegoutsWaitingForConfirmations); @@ -7199,8 +7371,8 @@ private void assertLockingCap( byte[] data = tx.getInput(0).getScriptSig().getChunks().get(1).data; BtcECKey senderBtcKey = BtcECKey.fromPublicOnly(data); - // Whitelist the addresses - LockWhitelist whitelist = provider.getLockWhitelist(); + // Whitelist the address + LockWhitelist whitelist = whitelistStorageProvider.getLockWhitelist(activations, btcRegTestParams); Address address = senderBtcKey.toAddress(bridgeConstants.getBtcParams()); whitelist.put(address, new OneOffWhiteListEntry(address, lockValue)); // The address is whitelisted @@ -7220,6 +7392,7 @@ private void assertLockingCap( .withActivations(activations) .withSignatureCache(signatureCache) .withFeePerKbSupport(feePerKbSupport) + .withWhitelistSupport(whitelistSupport) .build(); // Simulate blockchain @@ -7239,6 +7412,7 @@ private void assertLockingCap( bridgeSupport.registerBtcTransaction(rskTx, tx.bitcoinSerialize(), height, pmt.bitcoinSerialize()); bridgeSupport.save(); + whitelist.consume(address); // If the address is no longer whitelisted, it means it was consumed, whether the lock was rejected by lockingCap or not assertThat(whitelist.isWhitelisted(address), is(false)); @@ -7284,7 +7458,7 @@ private BridgeSupport getBridgeSupport(BridgeConstants constants, BridgeStorageP if (blockStoreFactory == null) { blockStoreFactory = mock(BtcBlockStoreWithCache.Factory.class); } - FeePerKbSupport feePerKbSupport = mock(FeePerKbSupport.class); + FeePerKbSupport feePerKbSupport = new FeePerKbSupportImpl(bridgeMainNetConstants.getFeePerKbConstants(), mock(FeePerKbStorageProvider.class)); return new BridgeSupport( constants, provider, @@ -7296,6 +7470,7 @@ private BridgeSupport getBridgeSupport(BridgeConstants constants, BridgeStorageP new Context(constants.getBtcParams()), new FederationSupport(constants, provider, executionBlock, activations), feePerKbSupport, + whitelistSupport, blockStoreFactory, activations, signatureCache diff --git a/rskj-core/src/test/java/co/rsk/peg/BridgeTestIntegration.java b/rskj-core/src/test/java/co/rsk/peg/BridgeTestIntegration.java index 69a0ba40040..6d4f13c5eeb 100644 --- a/rskj-core/src/test/java/co/rsk/peg/BridgeTestIntegration.java +++ b/rskj-core/src/test/java/co/rsk/peg/BridgeTestIntegration.java @@ -26,11 +26,18 @@ import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP88; import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP89; import static org.hamcrest.CoreMatchers.is; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; +import co.rsk.peg.bitcoin.BitcoinTestUtils; +import co.rsk.peg.whitelist.WhitelistResponseCode; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -211,9 +218,9 @@ void callUpdateCollectionsWithSignatureNotFromFederation() throws IOException { bridge.init(rskTx, world.getBlockChain().getBestBlock(), track, world.getBlockStore(), null, new LinkedList<>()); try { bridge.execute(Bridge.UPDATE_COLLECTIONS.encode()); - Assertions.fail(); + fail(); } catch (Exception ex) { - Assertions.assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); + assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); } } @@ -269,8 +276,8 @@ void callUpdateCollectionsWithTransactionsWaitingForConfirmation() throws IOExce //Reusing same storage configuration as the height doesn't affect storage configurations for releases. BridgeStorageProvider provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeRegTestConstants, activationConfigAll); - Assertions.assertEquals(3, provider.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); + assertEquals(3, provider.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(0, provider.getPegoutsWaitingForSignatures().size()); } @Test @@ -328,12 +335,12 @@ void callUpdateCollectionsWithTransactionsWaitingForConfirmationWithEnoughConfir // reusing same storage configuration as the height doesn't affect storage configurations for releases. BridgeStorageProvider provider = new BridgeStorageProvider(repository, PrecompiledContracts.BRIDGE_ADDR, bridgeRegTestConstants, activationConfigAll); - Assertions.assertEquals(2, provider.getPegoutsWaitingForConfirmations().getEntries().size()); - Assertions.assertEquals(1, provider.getPegoutsWaitingForSignatures().size()); + assertEquals(2, provider.getPegoutsWaitingForConfirmations().getEntries().size()); + assertEquals(1, provider.getPegoutsWaitingForSignatures().size()); } @Test - void sendNoRskTx() throws IOException { + void sendNoRskTx() { Repository repository = createRepository(); Repository track = repository.startTracking(); @@ -347,9 +354,9 @@ void sendNoRskTx() throws IOException { bridge.init(null, getGenesisBlock(), track, null, null, null); try { bridge.execute(Bridge.RECEIVE_HEADERS.encode()); - Assertions.fail(); + fail(); } catch (Exception ex) { - Assertions.assertTrue(ex.getMessage().contains("Rsk Transaction is null")); + assertTrue(ex.getMessage().contains("Rsk Transaction is null")); } track.commit(); @@ -430,7 +437,7 @@ void sendOrphanBlockHeader() throws VMException { track.commit(); - Assertions.assertEquals(previousHeight, bridge.getBtcBlockchainBestChainHeight(new Object[]{})); + assertEquals(previousHeight, bridge.getBtcBlockchainBestChainHeight(new Object[]{})); // TODO improve test Assertions.assertNotNull(track.getRoot()); } @@ -445,7 +452,7 @@ void executeWithFunctionSignatureLengthTooShortBeforeRskip88() throws VMExceptio bridgeSupportFactory, signatureCache); Transaction mockedTx = mock(Transaction.class); bridge.init(mockedTx, getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertNull(bridge.execute(new byte[3])); + assertNull(bridge.execute(new byte[3])); } @Test @@ -470,9 +477,9 @@ void executeWithFunctionSignatureLengthTooShortAfterRskip88() { try { bridge.init(mockedTx, getGenesisBlock(), createRepository().startTracking(), null, null, null); bridge.execute(new byte[3]); - Assertions.fail(); + fail(); } catch (VMException e) { - Assertions.assertTrue(e.getMessage().contains("Invalid data given")); + assertTrue(e.getMessage().contains("Invalid data given")); } } @@ -487,7 +494,7 @@ void executeWithInexistentFunctionBeforeRskip88() throws VMException { bridgeSupportFactory, signatureCache); Transaction mockedTx = mock(Transaction.class); bridge.init(mockedTx, getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertNull(bridge.execute(new byte[4])); + assertNull(bridge.execute(new byte[4])); } @Test @@ -506,9 +513,9 @@ void executeWithInexistentFunctionAfterRskip88() { try { bridge.init(mockedTx, getGenesisBlock(), createRepository().startTracking(), null, null, null); bridge.execute(new byte[4]); - Assertions.fail(); + fail(); } catch (VMException e) { - Assertions.assertTrue(e.getMessage().contains("Invalid data given")); + assertTrue(e.getMessage().contains("Invalid data given")); } } @@ -536,9 +543,9 @@ void receiveHeadersNotFromTheFederation() { bridge.init(rskTx, getGenesisBlock(), createRepository().startTracking(), null, null, null); try { bridge.execute(Bridge.RECEIVE_HEADERS.encode()); - Assertions.fail(); + fail(); } catch (Exception ex) { - Assertions.assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); + assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); } //track.commit(); @@ -575,7 +582,7 @@ void receiveHeadersWithNonParseableHeader() throws VMException { byte[] data = Bridge.RECEIVE_HEADERS.encode(new Object[]{objectArray}); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @@ -710,7 +717,7 @@ void receiveHeadersWithIncorrectSizeHeaders() throws Exception { headersSerialized[i] = block.bitcoinSerialize(); // Make sure we would be able to deserialize the block - Assertions.assertEquals(block, networkParameters.getDefaultSerializer().makeBlock(headersSerialized[i])); + assertEquals(block, networkParameters.getDefaultSerializer().makeBlock(headersSerialized[i])); } try (MockedStatic bridgeUtilsMocked = mockStatic(BridgeUtils.class)) { @@ -760,9 +767,9 @@ void registerBtcTransactionNotFromFederation() { try { bridge.execute(data); - Assertions.fail(); + fail(); } catch (Exception ex) { - Assertions.assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); + assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); } } @@ -821,7 +828,7 @@ public byte[] bitcoinSerialize() { byte[] data = Bridge.RECEIVE_HEADERS.encode(new Object[]{objectArray}); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @@ -853,7 +860,7 @@ void registerBtcTransactionWithNonParseableTx() throws VMException { byte[] data = Bridge.REGISTER_BTC_TRANSACTION.encode(new byte[3], 1, new byte[30]); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -917,7 +924,7 @@ void registerBtcTransactionWithNonParseableMerkleeProof1() throws Exception { byte[] data = Bridge.REGISTER_BTC_TRANSACTION.encode(tx.bitcoinSerialize(), 1, new byte[3]); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -953,7 +960,7 @@ void registerBtcTransactionWithNonParseableMerkleeProof2() throws VMException { byte[] data = Bridge.REGISTER_BTC_TRANSACTION.encode(tx.bitcoinSerialize(), 1, new byte[30]); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -995,23 +1002,24 @@ void registerBtcTransactionWithHugeDeclaredSizeMerkleeProof() throws VMException hashes.add(Sha256Hash.wrap("0000000000000000000000000000000000000000000000000000000000000002")); hashes.add(Sha256Hash.wrap("0000000000000000000000000000000000000000000000000000000000000003")); PartialMerkleTree pmt = new PartialMerkleTree(btcParams, bits, hashes, 3) { + @Override public void bitcoinSerializeToStream(OutputStream stream) throws IOException { uint32ToByteStreamLE(getTransactionCount(), stream); stream.write(new VarInt(Integer.MAX_VALUE).encode()); //stream.write(new VarInt(hashes.size()).encode()); - for (Sha256Hash hash : hashes) + for (Sha256Hash hash : hashes) { stream.write(hash.getReversedBytes()); + } stream.write(new VarInt(bits.length).encode()); stream.write(bits); } - }; byte[] pmtSerialized = pmt.bitcoinSerialize(); byte[] data = Bridge.REGISTER_BTC_TRANSACTION.encode(tx.bitcoinSerialize(), 1, pmtSerialized); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -1022,18 +1030,24 @@ void getFederationAddress() throws Exception { Repository track = repository.startTracking(); BridgeSupportFactory bridgeSupportFactory = new BridgeSupportFactory( - new RepositoryBtcBlockStoreWithCache.Factory(bridgeRegTestConstants.getBtcParams()), - bridgeRegTestConstants, - activationConfig, - signatureCache); - Bridge bridge = new Bridge(PrecompiledContracts.BRIDGE_ADDR, constants, activationConfig, - bridgeSupportFactory, signatureCache); + new RepositoryBtcBlockStoreWithCache.Factory(bridgeRegTestConstants.getBtcParams()), + bridgeRegTestConstants, + activationConfig, + signatureCache + ); + Bridge bridge = new Bridge( + PrecompiledContracts.BRIDGE_ADDR, + constants, + activationConfig, + bridgeSupportFactory, + signatureCache + ); Transaction mockedTx = mock(Transaction.class); bridge.init(mockedTx, getGenesisBlock(), track, null, null, null); byte[] data = Bridge.GET_FEDERATION_ADDRESS.encode(); - Assertions.assertArrayEquals(Bridge.GET_FEDERATION_ADDRESS.encodeOutputs(genesisFederation.getAddress().toString()), bridge.execute(data)); + assertArrayEquals(Bridge.GET_FEDERATION_ADDRESS.encodeOutputs(genesisFederation.getAddress().toString()), bridge.execute(data)); } @Test @@ -1089,9 +1103,9 @@ void addSignatureNotFromFederation() throws Exception { try { bridge.execute(data); - Assertions.fail(); + fail(); } catch (Exception ex) { - Assertions.assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); + assertTrue(ex.getMessage().contains(ERR_NOT_FROM_ACTIVE_OR_RETIRING_FED)); } } @@ -1126,7 +1140,7 @@ void addSignatureWithNonParseablePublicKey() throws Exception { byte[] rskTxHash = new byte[32]; byte[] data = Bridge.ADD_SIGNATURE.encode(federatorPublicKeySerialized, signaturesObjectArray, rskTxHash); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -1160,7 +1174,7 @@ void addSignatureWithEmptySignatureArray() throws Exception { byte[] rskTxHash = new byte[32]; byte[] data = Bridge.ADD_SIGNATURE.encode(federatorPublicKeySerialized, signaturesObjectArray, rskTxHash); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -1194,7 +1208,7 @@ void addSignatureWithNonParseableSignature() throws Exception { byte[] rskTxHash = new byte[32]; byte[] data = Bridge.ADD_SIGNATURE.encode(federatorPublicKeySerialized, signaturesObjectArray, rskTxHash); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -1228,7 +1242,7 @@ void addSignatureWithNonParseableRskTx() throws Exception { byte[] rskTxHash = new byte[3]; byte[] data = Bridge.ADD_SIGNATURE.encode(federatorPublicKeySerialized, signaturesObjectArray, rskTxHash); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } @Test @@ -1237,9 +1251,9 @@ void exceptionInUpdateCollection() { try { bridge.updateCollections(null); - Assertions.fail(); + fail(); } catch (VMException ex) { - Assertions.assertEquals("Exception onBlock", ex.getMessage()); + assertEquals("Exception onBlock", ex.getMessage()); } } @@ -1249,9 +1263,9 @@ void exceptionInReleaseBtc() { try { bridge.releaseBtc(null); - Assertions.fail(); + fail(); } catch (VMException ex) { - Assertions.assertEquals("Exception in releaseBtc", ex.getMessage()); + assertEquals("Exception in releaseBtc", ex.getMessage()); } } @@ -1261,9 +1275,9 @@ void exceptionInGetStateForBtcReleaseClient() { try { bridge.getStateForBtcReleaseClient(null); - Assertions.fail(); + fail(); } catch (VMException ex) { - Assertions.assertEquals("Exception in getStateForBtcReleaseClient", ex.getMessage()); + assertEquals("Exception in getStateForBtcReleaseClient", ex.getMessage()); } } @@ -1273,9 +1287,9 @@ void exceptionInGetStateForDebugging() { try { bridge.getStateForDebugging(null); - Assertions.fail(); + fail(); } catch (VMException ex) { - Assertions.assertEquals("Exception in getStateForDebugging", ex.getMessage()); + assertEquals("Exception in getStateForDebugging", ex.getMessage()); } } @@ -1285,9 +1299,9 @@ void exceptionInGetBtcBlockchainBestChainHeight() { try { bridge.getBtcBlockchainBestChainHeight(null); - Assertions.fail(); + fail(); } catch (VMException ex) { - Assertions.assertEquals("Exception in getBtcBlockchainBestChainHeight", ex.getMessage()); + assertEquals("Exception in getBtcBlockchainBestChainHeight", ex.getMessage()); } } @@ -1297,9 +1311,9 @@ void exceptionInGetBtcBlockchainBlockLocator() { try { bridge.getBtcBlockchainBlockLocator(null); - Assertions.fail(); + fail(); } catch (VMException ex) { - Assertions.assertEquals("Exception in getBtcBlockchainBlockLocator", ex.getMessage()); + assertEquals("Exception in getBtcBlockchainBlockLocator", ex.getMessage()); } } @@ -1317,18 +1331,19 @@ void getBtcBlockchainBlockLocatorBeforeRskip89Fork() throws Exception { bridgeSupportFactoryMock, signatureCache)); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - when(bridgeSupportMock.getBtcBlockchainBlockLocator()) - .then((InvocationOnMock invocation) -> Arrays.asList(hash)); + when(bridgeSupportMock.getBtcBlockchainBlockLocator()).then( + (InvocationOnMock invocation) -> Collections.singletonList(hash) + ); when(bridgeSupportFactoryMock.newInstance(any(), any(), any(), any())).thenReturn(bridgeSupportMock); bridge.init(mock(Transaction.class), getGenesisBlock(), track, null, null, null); - byte[] result = bridge.execute(Bridge.GET_BTC_BLOCKCHAIN_BLOCK_LOCATOR.encode(new Object[]{})); + byte[] result = bridge.execute(Bridge.GET_BTC_BLOCKCHAIN_BLOCK_LOCATOR.encode()); Object[] decodedResult = (Object[]) BridgeMethods.GET_BTC_BLOCKCHAIN_BLOCK_LOCATOR.getFunction().decodeResult(result)[0]; - Assertions.assertEquals(1, decodedResult.length); - Assertions.assertEquals(hashedString, decodedResult[0]); + assertEquals(1, decodedResult.length); + assertEquals(hashedString, decodedResult[0]); } @Test @@ -1349,11 +1364,10 @@ void getBtcBlockchainBlockLocatorAfterRskip88And89Fork() { bridge.init(mock(Transaction.class), getGenesisBlock(), track, null, null, null); try { - bridge.execute(Bridge.GET_BTC_BLOCKCHAIN_BLOCK_LOCATOR.encode(new Object[]{})); - Assertions.fail(); + bridge.execute(Bridge.GET_BTC_BLOCKCHAIN_BLOCK_LOCATOR.encode()); + fail(); } catch (VMException e) { - Assertions.assertTrue(e.getMessage().contains("Invalid data given:")); - + assertTrue(e.getMessage().contains("Invalid data given:")); } } @@ -1384,7 +1398,7 @@ void getGasForDataFreeTx() { Repository mockRepository = mock(Repository.class); bridge.init(rskTx, rskExecutionBlock, mockRepository, null, null, null); - Assertions.assertEquals(0, bridge.getGasForData(rskTx.getData())); + assertEquals(0, bridge.getGasForData(rskTx.getData())); } @Test @@ -1468,7 +1482,7 @@ void isBtcTxHashAlreadyProcessed_normalFlow() throws IOException, VMException { hashes.add(Sha256Hash.of("hash_4".getBytes())); for (Sha256Hash hash : hashes) { - Assertions.assertTrue(bridge.isBtcTxHashAlreadyProcessed(new Object[]{hash.toString()})); + assertTrue(bridge.isBtcTxHashAlreadyProcessed(new Object[]{hash.toString()})); verify(bridgeSupportMock).isBtcTxHashAlreadyProcessed(hash); } Assertions.assertFalse(bridge.isBtcTxHashAlreadyProcessed(new Object[]{Sha256Hash.of("anything".getBytes()).toString()})); @@ -1490,7 +1504,7 @@ void isBtcTxHashAlreadyProcessed_exception() throws IOException { try { bridge.isBtcTxHashAlreadyProcessed(new Object[]{"notahash"}); - Assertions.fail(); + fail(); } catch (VMException e) { } verify(bridgeSupportMock, never()).isBtcTxHashAlreadyProcessed(any()); @@ -1517,10 +1531,10 @@ void getBtcTxHashProcessedHeight_normalFlow() throws IOException, VMException { hashes.put(Sha256Hash.of("hash_4".getBytes()), 4L); for (Map.Entry entry : hashes.entrySet()) { - Assertions.assertEquals(entry.getValue(), bridge.getBtcTxHashProcessedHeight(new Object[]{entry.getKey().toString()})); + assertEquals(entry.getValue(), bridge.getBtcTxHashProcessedHeight(new Object[]{entry.getKey().toString()})); verify(bridgeSupportMock).getBtcTxHashProcessedHeight(entry.getKey()); } - Assertions.assertNull(bridge.getBtcTxHashProcessedHeight(new Object[]{Sha256Hash.of("anything".getBytes()).toString()})); + assertNull(bridge.getBtcTxHashProcessedHeight(new Object[]{Sha256Hash.of("anything".getBytes()).toString()})); } @Test @@ -1538,7 +1552,7 @@ void getBtcTxHashProcessedHeight_exception() throws IOException { try { bridge.getBtcTxHashProcessedHeight(new Object[]{"notahash"}); - Assertions.fail(); + fail(); } catch (VMException e) { } verify(bridgeSupportMock, never()).getBtcTxHashProcessedHeight(any()); @@ -1558,7 +1572,7 @@ void getFederationSize() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getFederationSize()).thenReturn(1234); - Assertions.assertEquals(1234, bridge.getFederationSize(new Object[]{}).intValue()); + assertEquals(1234, bridge.getFederationSize(new Object[]{}).intValue()); } @Test @@ -1576,7 +1590,7 @@ void getFederationThreshold() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getFederationThreshold()).thenReturn(5678); - Assertions.assertEquals(5678, bridge.getFederationThreshold(new Object[]{}).intValue()); + assertEquals(5678, bridge.getFederationThreshold(new Object[]{}).intValue()); } @Test @@ -1593,7 +1607,7 @@ void getFederationCreationTime() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getFederationCreationTime()).thenReturn(Instant.ofEpochMilli(5000)); - Assertions.assertEquals(5000, bridge.getFederationCreationTime(new Object[]{}).intValue()); + assertEquals(5000, bridge.getFederationCreationTime(new Object[]{}).intValue()); } @Test @@ -1621,35 +1635,37 @@ void getFederatorPublicKey_beforeMultikey() throws VMException { BigInteger.valueOf(invocation.getArgument(0)).toByteArray()); bridge.init(mock(Transaction.class), getGenesisBlock(), null, null, null, null); - Assertions.assertTrue(Arrays.equals(new byte[]{10}, - (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)})) - )[0] - )); + assertArrayEquals( + new byte[]{10}, + (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(BigInteger.valueOf(10))))[0] + ); - Assertions.assertTrue(Arrays.equals(new byte[]{20}, - (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(20)})) - )[0] - )); + assertArrayEquals( + new byte[]{20}, + (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(BigInteger.valueOf(20))))[0] + ); - Assertions.assertTrue(Arrays.equals(new byte[]{1, 0}, - (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(256)})) - )[0] - )); + assertArrayEquals( + new byte[]{1, 0}, + (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(BigInteger.valueOf(256))))[0] + ); } @Test void getFederatorPublicKey_afterMultikey() throws VMException { doReturn(true).when(activationConfig).isActive(eq(RSKIP123), anyLong()); BridgeSupportFactory bridgeSupportFactoryMock = mock(BridgeSupportFactory.class); - Bridge bridge = new Bridge(PrecompiledContracts.BRIDGE_ADDR, constants, activationConfig, - bridgeSupportFactoryMock, signatureCache); + Bridge bridge = new Bridge( + PrecompiledContracts.BRIDGE_ADDR, + constants, + activationConfig, + bridgeSupportFactoryMock, + signatureCache + ); bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)}))); + assertNull(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)}))); verify(bridgeSupportMock, never()).getFederatorPublicKey(any(int.class)); } @@ -1665,7 +1681,7 @@ void getFederatorPublicKeyOfType_beforeMultikey() throws VMException { bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"}))); + assertNull(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"}))); verify(bridgeSupportMock, never()).getFederatorPublicKeyOfType(any(int.class), any(FederationMember.KeyType.class)); } @@ -1687,40 +1703,43 @@ void getFederatorPublicKeyOfType_afterMultikey() throws Exception { ); bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertTrue(Arrays.equals("10btc".getBytes(), - (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"})) - )[0] - )); + assertArrayEquals( + "10btc".getBytes(), + (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(BigInteger.valueOf(10), "btc")))[0] + ); - Assertions.assertTrue(Arrays.equals("200rsk".getBytes(), - (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(200), "rsk"})) - )[0] - )); + assertArrayEquals( + "200rsk".getBytes(), + (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(BigInteger.valueOf(200), "rsk")))[0] + ); - Assertions.assertTrue(Arrays.equals("172mst".getBytes(), - (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(172), "mst"})) - )[0] - )); + assertArrayEquals( + "172mst".getBytes(), + (byte[]) BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult(bridge.execute(BridgeMethods.GET_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(BigInteger.valueOf(172), "mst")))[0] + ); } @Test void getRetiringFederationSize() { BridgeSupportFactory bridgeSupportFactory = new BridgeSupportFactory( - new RepositoryBtcBlockStoreWithCache.Factory(bridgeRegTestConstants.getBtcParams()), - bridgeRegTestConstants, - activationConfig, - signatureCache); - Bridge bridge = new Bridge(PrecompiledContracts.BRIDGE_ADDR, constants, activationConfig, - bridgeSupportFactory, signatureCache); + new RepositoryBtcBlockStoreWithCache.Factory(bridgeRegTestConstants.getBtcParams()), + bridgeRegTestConstants, + activationConfig, + signatureCache + ); + Bridge bridge = new Bridge( + PrecompiledContracts.BRIDGE_ADDR, + constants, + activationConfig, + bridgeSupportFactory, + signatureCache + ); bridge.init(null, getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getRetiringFederationSize()).thenReturn(1234); - Assertions.assertEquals(1234, bridge.getRetiringFederationSize(new Object[]{}).intValue()); + assertEquals(1234, bridge.getRetiringFederationSize(new Object[]{}).intValue()); } @Test @@ -1738,7 +1757,7 @@ void getRetiringFederationThreshold() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getRetiringFederationThreshold()).thenReturn(5678); - Assertions.assertEquals(5678, bridge.getRetiringFederationThreshold(new Object[]{}).intValue()); + assertEquals(5678, bridge.getRetiringFederationThreshold(new Object[]{}).intValue()); } @Test @@ -1755,7 +1774,7 @@ void getRetiringFederationCreationTime() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getRetiringFederationCreationTime()).thenReturn(Instant.ofEpochMilli(5000)); - Assertions.assertEquals(5000, bridge.getRetiringFederationCreationTime(new Object[]{}).intValue()); + assertEquals(5000, bridge.getRetiringFederationCreationTime(new Object[]{}).intValue()); } @Test @@ -1784,19 +1803,19 @@ void getRetiringFederatorPublicKey_beforeMultikey() throws Exception { bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertTrue(Arrays.equals(new byte[]{10}, + assertTrue(Arrays.equals(new byte[]{10}, (byte[]) BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)})) )[0] )); - Assertions.assertTrue(Arrays.equals(new byte[]{20}, + assertTrue(Arrays.equals(new byte[]{20}, (byte[]) BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(20)})) )[0] )); - Assertions.assertTrue(Arrays.equals(new byte[]{1, 0}, + assertTrue(Arrays.equals(new byte[]{1, 0}, (byte[]) BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(256)})) )[0] @@ -1814,7 +1833,7 @@ void getRetiringFederatorPublicKey_afterMultikey() throws Exception { bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull(bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)}))); + assertNull(bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)}))); verify(bridgeSupportMock, never()).getRetiringFederatorPublicKey(any(int.class)); } @@ -1829,7 +1848,7 @@ void getRetiringFederatorPublicKeyOfType_beforeMultikey() throws Exception { bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull(bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"}))); + assertNull(bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"}))); verify(bridgeSupportMock, never()).getRetiringFederatorPublicKeyOfType(any(int.class), any(FederationMember.KeyType.class)); } @@ -1851,19 +1870,19 @@ void getRetiringFederatorPublicKeyOfType_afterMultikey() throws Exception { ); bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertTrue(Arrays.equals("10btc".getBytes(), + assertTrue(Arrays.equals("10btc".getBytes(), (byte[]) BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"})) )[0] )); - Assertions.assertTrue(Arrays.equals("105rsk".getBytes(), + assertTrue(Arrays.equals("105rsk".getBytes(), (byte[]) BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(105), "rsk"})) )[0] )); - Assertions.assertTrue(Arrays.equals("232mst".getBytes(), + assertTrue(Arrays.equals("232mst".getBytes(), (byte[]) BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_RETIRING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(232), "mst"})) )[0] @@ -1885,7 +1904,7 @@ void getPendingFederationSize() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getPendingFederationSize()).thenReturn(1234); - Assertions.assertEquals(1234, bridge.getPendingFederationSize(new Object[]{}).intValue()); + assertEquals(1234, bridge.getPendingFederationSize(new Object[]{}).intValue()); } @Test @@ -1904,19 +1923,19 @@ void getPendingFederatorPublicKey_beforeMultikey() throws Exception { BigInteger.valueOf(invocation.getArgument(0)).toByteArray()); bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertTrue(Arrays.equals(new byte[]{10}, + assertTrue(Arrays.equals(new byte[]{10}, (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)})) )[0] )); - Assertions.assertTrue(Arrays.equals(new byte[]{20}, + assertTrue(Arrays.equals(new byte[]{20}, (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(20)})) )[0] )); - Assertions.assertTrue(Arrays.equals(new byte[]{1, 0}, + assertTrue(Arrays.equals(new byte[]{1, 0}, (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(256)})) )[0] @@ -1934,7 +1953,7 @@ void getPendingFederatorPublicKey_afterMultikey() throws Exception { bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull(bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)}))); + assertNull(bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{BigInteger.valueOf(10)}))); verify(bridgeSupportMock, never()).getPendingFederatorPublicKey(any(int.class)); } @@ -1949,7 +1968,7 @@ void getPendingFederatorPublicKeyOfType_beforeMultikey() throws Exception { bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull(bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"}))); + assertNull(bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"}))); verify(bridgeSupportMock, never()).getPendingFederatorPublicKeyOfType(any(int.class), any(FederationMember.KeyType.class)); } @@ -1971,23 +1990,24 @@ void getPendingFederatorPublicKeyOfType_afterMultikey() throws Exception { ); bridge.init(mock(Transaction.class), getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertTrue(Arrays.equals("10btc".getBytes(), + assertTrue(Arrays.equals("10btc".getBytes(), (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(10), "btc"})) )[0] )); - Assertions.assertTrue(Arrays.equals("82rsk".getBytes(), + assertTrue(Arrays.equals("82rsk".getBytes(), (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(82), "rsk"})) )[0] )); - Assertions.assertTrue(Arrays.equals("123mst".getBytes(), - (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( - bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(new Object[]{BigInteger.valueOf(123), "mst"})) - )[0] - )); + assertArrayEquals( + "123mst".getBytes(), + (byte[]) BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().decodeResult( + bridge.execute(BridgeMethods.GET_PENDING_FEDERATOR_PUBLIC_KEY_OF_TYPE.getFunction().encode(BigInteger.valueOf(123), "mst")) + )[0] + ); } @Test @@ -2006,7 +2026,7 @@ void createFederation() throws BridgeIllegalArgumentException { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.voteFederationChange(txMock, new ABICallSpec("create", new byte[][]{}))).thenReturn(123); - Assertions.assertEquals(123, bridge.createFederation(new Object[]{}).intValue()); + assertEquals(123, bridge.createFederation(new Object[]{}).intValue()); } @Test @@ -2028,7 +2048,7 @@ void addFederatorPublicKey_beforeMultikey() throws Exception { .thenReturn(123); bridge.init(txMock, getGenesisBlock(), null, null, null, null); - Assertions.assertEquals(123, + assertEquals(123, ((BigInteger) BridgeMethods.ADD_FEDERATOR_PUBLIC_KEY.getFunction().decodeResult( bridge.execute(BridgeMethods.ADD_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{Hex.decode("aabbccdd")})) )[0]).intValue() @@ -2049,7 +2069,7 @@ void addFederatorPublicKey_afterMultikey() throws Exception { bridge.init(txMock, getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull( + assertNull( bridge.execute(BridgeMethods.ADD_FEDERATOR_PUBLIC_KEY.getFunction().encode(new Object[]{Hex.decode("aabbccdd")})) ); @@ -2070,7 +2090,7 @@ void addFederatorPublicKeyMultikey_beforeMultikey() throws Exception { bridge.init(txMock, getGenesisBlock(), createRepository().startTracking(), null, null, null); BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); - Assertions.assertNull( + assertNull( bridge.execute(BridgeMethods.ADD_FEDERATOR_PUBLIC_KEY_MULTIKEY.getFunction().encode(new Object[]{ Hex.decode("aabb"), Hex.decode("ccdd"), Hex.decode("eeff") })) @@ -2099,7 +2119,7 @@ void addFederatorPublicKeyMultikey_afterMultikey() throws Exception { }))).thenReturn(123); bridge.init(txMock, getGenesisBlock(), createRepository().startTracking(), null, null, null); - Assertions.assertEquals(123, + assertEquals(123, ((BigInteger) BridgeMethods.ADD_FEDERATOR_PUBLIC_KEY_MULTIKEY.getFunction().decodeResult( bridge.execute(BridgeMethods.ADD_FEDERATOR_PUBLIC_KEY_MULTIKEY.getFunction().encode(new Object[]{ Hex.decode("aabb"), Hex.decode("ccdd"), Hex.decode("eeff") @@ -2124,7 +2144,7 @@ void commitFederation_ok() throws BridgeIllegalArgumentException { when(bridgeSupportMock.voteFederationChange(txMock, new ABICallSpec("commit", new byte[][]{Hex.decode("01020304")}))).thenReturn(123); - Assertions.assertEquals(123, bridge.commitFederation(new Object[]{Hex.decode("01020304")}).intValue()); + assertEquals(123, bridge.commitFederation(new Object[]{Hex.decode("01020304")}).intValue()); } @Test @@ -2140,7 +2160,7 @@ void commitFederation_wrongParameterType() throws BridgeIllegalArgumentException BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); - Assertions.assertEquals(-10, bridge.commitFederation(new Object[]{"i'm not a byte array"}).intValue()); + assertEquals(-10, bridge.commitFederation(new Object[]{"i'm not a byte array"}).intValue()); verify(bridgeSupportMock, never()).voteFederationChange(any(), any()); } @@ -2160,7 +2180,7 @@ void rollbackFederation() throws BridgeIllegalArgumentException { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.voteFederationChange(txMock, new ABICallSpec("rollback", new byte[][]{}))).thenReturn(456); - Assertions.assertEquals(456, bridge.rollbackFederation(new Object[]{}).intValue()); + assertEquals(456, bridge.rollbackFederation(new Object[]{}).intValue()); } @Test @@ -2177,7 +2197,7 @@ void getLockWhitelistSize() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getLockWhitelistSize()).thenReturn(1234); - Assertions.assertEquals(1234, bridge.getLockWhitelistSize(new Object[]{}).intValue()); + assertEquals(1234, bridge.getLockWhitelistSize(new Object[]{}).intValue()); } @Test @@ -2198,8 +2218,8 @@ void getLockWhitelistAddress() { when(bridgeSupportMock.getLockWhitelistEntryByIndex(10)).then((InvocationOnMock invocation) -> mockedEntry10); when(bridgeSupportMock.getLockWhitelistEntryByIndex(20)).then((InvocationOnMock invocation) -> mockedEntry20); - Assertions.assertEquals(mockedEntry10.address().toBase58(), bridge.getLockWhitelistAddress(new Object[]{BigInteger.valueOf(10)})); - Assertions.assertEquals(mockedEntry20.address().toBase58(), bridge.getLockWhitelistAddress(new Object[]{BigInteger.valueOf(20)})); + assertEquals(mockedEntry10.address().toBase58(), bridge.getLockWhitelistAddress(new Object[]{BigInteger.valueOf(10)})); + assertEquals(mockedEntry20.address().toBase58(), bridge.getLockWhitelistAddress(new Object[]{BigInteger.valueOf(20)})); } @Test @@ -2223,7 +2243,7 @@ void getLockWhitelistEntryByAddressBeforeRskip87And88Fork() throws VMException { bridgeSupportFactory, signatureCache); bridge.init(mockedTransaction, getGenesisBlock(), track, null, null, null); - Assertions.assertNull(bridge.execute(Bridge.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.encode(new Object[]{address.toBase58()}))); + assertNull(bridge.execute(Bridge.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.encode(new Object[]{address.toBase58()}))); } @Test @@ -2258,19 +2278,19 @@ void getLockWhitelistEntryByAddressAfterRskip87Fork() throws Exception { result = bridge.execute(Bridge.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.encode(new Object[]{mockedAddressForUnlimited.toBase58()})); BigInteger decodedResult = (BigInteger) BridgeMethods.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.getFunction().decodeResult(result)[0]; - Assertions.assertEquals(0, decodedResult.longValue()); + assertEquals(0, decodedResult.longValue()); // Get the one-off whitelist address result = bridge.execute(Bridge.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.encode(new Object[]{mockedAddressForOneOff.toBase58()})); decodedResult = (BigInteger) BridgeMethods.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.getFunction().decodeResult(result)[0]; - Assertions.assertEquals(Coin.COIN.value, decodedResult.longValue()); + assertEquals(Coin.COIN.value, decodedResult.longValue()); // Try fetch an unexisting address result = bridge.execute(Bridge.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.encode(new Object[]{(new BtcECKey().toAddress(networkParameters)).toBase58()})); decodedResult = (BigInteger) BridgeMethods.GET_LOCK_WHITELIST_ENTRY_BY_ADDRESS.getFunction().decodeResult(result)[0]; - Assertions.assertEquals(-1, decodedResult.longValue()); + assertEquals(-1, decodedResult.longValue()); } @Test @@ -2302,7 +2322,7 @@ void addLockWhitelistAddressBeforeRskip87Fork() throws VMException { BigInteger decodedResult = (BigInteger) BridgeMethods.ADD_LOCK_WHITELIST_ADDRESS.getFunction().decodeResult(result)[0]; - Assertions.assertEquals(BridgeSupport.LOCK_WHITELIST_GENERIC_ERROR_CODE.intValue(), decodedResult.intValue()); + assertEquals(WhitelistResponseCode.GENERIC_ERROR.getCode(), decodedResult.intValue()); } @Test @@ -2325,11 +2345,11 @@ void addLockWhitelistAddressAfterRskip87And88Fork() { try { bridge.execute(Bridge.ADD_LOCK_WHITELIST_ADDRESS.encode(new Object[]{"i-am-an-address", BigInteger.valueOf(25L)})); - Assertions.fail(); + fail(); } catch (Exception e) { Throwable causeException = e.getCause(); - Assertions.assertEquals(BridgeIllegalArgumentException.class, causeException.getClass()); - Assertions.assertTrue(causeException.getMessage().startsWith("Invalid data given")); + assertEquals(BridgeIllegalArgumentException.class, causeException.getClass()); + assertTrue(causeException.getMessage().startsWith("Invalid data given")); } } @@ -2352,7 +2372,7 @@ void addOneOffLockWhitelistAddressBeforeRskip87And88Fork() throws VMException { bridgeSupportFactory, signatureCache); bridge.init(mockedTransaction, getGenesisBlock(), track, null, null, null); - Assertions.assertNull(bridge.execute(Bridge.ADD_ONE_OFF_LOCK_WHITELIST_ADDRESS.encode(new Object[]{"i-am-an-address", BigInteger.valueOf(25L)}))); + assertNull(bridge.execute(Bridge.ADD_ONE_OFF_LOCK_WHITELIST_ADDRESS.encode(new Object[]{"i-am-an-address", BigInteger.valueOf(25L)}))); } @Test @@ -2384,7 +2404,7 @@ void addOneOffLockWhitelistAddressAfterRskip87Fork() throws VMException { BigInteger decodedResult = (BigInteger) BridgeMethods.ADD_ONE_OFF_LOCK_WHITELIST_ADDRESS.getFunction().decodeResult(result)[0]; - Assertions.assertEquals(BridgeSupport.LOCK_WHITELIST_GENERIC_ERROR_CODE.intValue(), decodedResult.intValue()); + assertEquals(WhitelistResponseCode.GENERIC_ERROR.getCode(), decodedResult.intValue()); } @Test @@ -2405,7 +2425,7 @@ void addUnlimitedLockWhitelistAddressBeforeRskip87And88Fork() throws VMException bridgeSupportFactory, signatureCache); bridge.init(mockedTransaction, getGenesisBlock(), track, null, null, null); - Assertions.assertNull(bridge.execute(Bridge.ADD_UNLIMITED_LOCK_WHITELIST_ADDRESS.encode(new Object[]{"i-am-an-address"}))); + assertNull(bridge.execute(Bridge.ADD_UNLIMITED_LOCK_WHITELIST_ADDRESS.encode(new Object[]{"i-am-an-address"}))); } @Test @@ -2439,7 +2459,7 @@ void addUnlimitedLockWhitelistAddressAfterRskip87Fork() throws VMException { BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); - Assertions.assertEquals(BridgeSupport.LOCK_WHITELIST_GENERIC_ERROR_CODE.intValue(), decodedResult.intValue()); + assertEquals(WhitelistResponseCode.GENERIC_ERROR.getCode(), decodedResult.intValue()); } @Test @@ -2457,7 +2477,7 @@ void removeLockWhitelistAddress() { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.removeLockWhitelistAddress(mockedTransaction, "i-am-an-address")).thenReturn(1234); - Assertions.assertEquals(1234, bridge.removeLockWhitelistAddress(new Object[]{"i-am-an-address"}).intValue()); + assertEquals(1234, bridge.removeLockWhitelistAddress(new Object[]{"i-am-an-address"}).intValue()); } @Test @@ -2468,7 +2488,7 @@ void getFeePerKb() { when(bridgeSupportMock.getFeePerKb()) .thenReturn(Coin.valueOf(12345678901234L)); - Assertions.assertEquals(12345678901234L, bridge.getFeePerKb(new Object[]{})); + assertEquals(12345678901234L, bridge.getFeePerKb(new Object[]{})); } @Test @@ -2488,7 +2508,7 @@ void voteFeePerKb_ok() { when(bridgeSupportMock.voteFeePerKbChange(txMock, Coin.valueOf(2))) .thenReturn(123); - Assertions.assertEquals(123, bridge.voteFeePerKbChange(new Object[]{BigInteger.valueOf(2)}).intValue()); + assertEquals(123, bridge.voteFeePerKbChange(new Object[]{BigInteger.valueOf(2)}).intValue()); } @Test @@ -2505,7 +2525,7 @@ void voteFeePerKb_wrongParameterType() throws BridgeIllegalArgumentException { BridgeSupport bridgeSupportMock = mock(BridgeSupport.class); TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); - Assertions.assertEquals(-10, bridge.voteFeePerKbChange(new Object[]{"i'm not a byte array"}).intValue()); + assertEquals(-10, bridge.voteFeePerKbChange(new Object[]{"i'm not a byte array"}).intValue()); verify(bridgeSupportMock, never()).voteFederationChange(any(), any()); } @@ -2602,7 +2622,7 @@ void executeMethodWithOnlyLocalCallsAllowed_nonLocalCallTx_beforeOrchid() throws byte[] data = BridgeMethods.GET_FEDERATION_ADDRESS.getFunction().encode(new Object[]{}); String result = (String) BridgeMethods.GET_FEDERATION_ADDRESS.getFunction().decodeResult(bridge.execute(data))[0]; - Assertions.assertEquals(expectedResult.toBase58(), result); + assertEquals(expectedResult.toBase58(), result); bridge.execute(data); // TODO improve test @@ -2627,10 +2647,10 @@ void executeMethodWithOnlyLocalCallsAllowed_nonLocalCallTx() { byte[] data = BridgeMethods.GET_FEDERATION_ADDRESS.getFunction().encode(new Object[]{}); bridge.execute(data); - Assertions.fail(); + fail(); } catch (VMException e) { verify(bridgeSupportMock, never()).getFederationAddress(); - Assertions.assertTrue(e.getMessage().contains("Non-local-call")); + assertTrue(e.getMessage().contains("Non-local-call")); } } @@ -2661,7 +2681,7 @@ void getBtcTransactionConfirmationsBeforeWasabi() throws Exception { byte[][] arr = new byte[1][]; arr[0] = new byte[]{}; Object[] params = new Object[]{new byte[0], new byte[0], BigInteger.valueOf(1), arr}; - Assertions.assertNull(bridge.execute(Bridge.GET_BTC_TRANSACTION_CONFIRMATIONS.encode(params))); + assertNull(bridge.execute(Bridge.GET_BTC_TRANSACTION_CONFIRMATIONS.encode(params))); } @Test @@ -2696,7 +2716,7 @@ void getBtcTransactionConfirmationsAfterWasabi_ok() throws Exception { Assertions.assertArrayEquals(merkleBranchHashes[2], hashes.get(2).getBytes()); Integer bits = invocation.getArgument(1); - Assertions.assertEquals(123, bits.intValue()); + assertEquals(123, bits.intValue()); return merkleBranch; }); @@ -2710,12 +2730,12 @@ void getBtcTransactionConfirmationsAfterWasabi_ok() throws Exception { Assertions.assertArrayEquals(btcBlockHash, blockHash.getBytes()); MerkleBranch merkleBranchArg = invocation.getArgument(2); - Assertions.assertEquals(merkleBranch, merkleBranchArg); + assertEquals(merkleBranch, merkleBranchArg); return 78; }); - Assertions.assertEquals(78, bridge.getBtcTransactionConfirmations(new Object[]{ + assertEquals(78, bridge.getBtcTransactionConfirmations(new Object[]{ btcTxHash, btcBlockHash, merkleBranchBits, @@ -2758,7 +2778,7 @@ void getBtcTransactionConfirmationsAfterWasabi_errorInBridgeSupport() throws Exc Assertions.assertArrayEquals(merkleBranchHashes[2], hashes.get(2).getBytes()); Integer bits = invocation.getArgument(1); - Assertions.assertEquals(123, bits.intValue()); + assertEquals(123, bits.intValue()); return merkleBranch; }); @@ -2772,7 +2792,7 @@ void getBtcTransactionConfirmationsAfterWasabi_errorInBridgeSupport() throws Exc Assertions.assertArrayEquals(btcBlockHash, blockHash.getBytes()); MerkleBranch merkleBranchArg = invocation.getArgument(2); - Assertions.assertEquals(merkleBranch, merkleBranchArg); + assertEquals(merkleBranch, merkleBranchArg); throw new VMException("bla bla bla"); }); @@ -2784,11 +2804,11 @@ void getBtcTransactionConfirmationsAfterWasabi_errorInBridgeSupport() throws Exc merkleBranchBits, merkleBranchHashes }); - Assertions.fail(); + fail(); } catch (VMException e) { - Assertions.assertTrue(e.getMessage().contains("in getBtcTransactionConfirmations")); - Assertions.assertEquals(VMException.class, e.getCause().getClass()); - Assertions.assertTrue(e.getCause().getMessage().contains("bla bla bla")); + assertTrue(e.getMessage().contains("in getBtcTransactionConfirmations")); + assertEquals(VMException.class, e.getCause().getClass()); + assertTrue(e.getCause().getMessage().contains("bla bla bla")); } } @@ -2826,7 +2846,7 @@ void getBtcTransactionConfirmationsAfterWasabi_merkleBranchConstructionError() t Assertions.assertArrayEquals(merkleBranchHashes[2], hashes.get(2).getBytes()); Integer bits = invocation.getArgument(1); - Assertions.assertEquals(123, bits.intValue()); + assertEquals(123, bits.intValue()); throw new IllegalArgumentException("blabla"); }); @@ -2838,10 +2858,10 @@ void getBtcTransactionConfirmationsAfterWasabi_merkleBranchConstructionError() t merkleBranchBits, merkleBranchHashes }); - Assertions.fail(); + fail(); } catch (VMException e) { - Assertions.assertTrue(e.getMessage().contains("in getBtcTransactionConfirmations")); - Assertions.assertEquals(IllegalArgumentException.class, e.getCause().getClass()); + assertTrue(e.getMessage().contains("in getBtcTransactionConfirmations")); + assertEquals(IllegalArgumentException.class, e.getCause().getClass()); verify(bridgeSupportMock, never()).getBtcTransactionConfirmations(any(), any(), any()); } } @@ -2886,7 +2906,7 @@ void getBtcTransactionConfirmations_gasCost() { byte[] data = fn.encode(args); - Assertions.assertEquals(2 * data.length + 1234L, bridge.getGasForData(data)); + assertEquals(2 * data.length + 1234L, bridge.getGasForData(data)); } } @@ -2905,7 +2925,7 @@ void getBtcBlockchainBlockHashAtDepth() throws BlockStoreException, IOException, Sha256Hash mockedResult = Sha256Hash.of(Hex.decode("aabbcc")); when(bridgeSupportMock.getBtcBlockchainBlockHashAtDepth(555)).thenReturn(mockedResult); - Assertions.assertEquals(mockedResult, Sha256Hash.wrap(bridge.getBtcBlockchainBlockHashAtDepth(new Object[]{BigInteger.valueOf(555)}))); + assertEquals(mockedResult, Sha256Hash.wrap(bridge.getBtcBlockchainBlockHashAtDepth(new Object[]{BigInteger.valueOf(555)}))); } @Test @@ -2990,9 +3010,9 @@ void testCallFromContract_afterOrchid() { for (int i = 0; i < numOps; i++) { vm.step(program); } - Assertions.fail(); + fail(); } catch (RuntimeException e) { - Assertions.assertTrue(e.getMessage().contains("Non-local-call")); + assertTrue(e.getMessage().contains("Non-local-call")); } } @@ -3032,8 +3052,8 @@ void localCallOnlyMethodsDefinition() { BridgeMethods.GET_STATE_FOR_BTC_RELEASE_CLIENT, BridgeMethods.GET_STATE_FOR_DEBUGGING, BridgeMethods.IS_BTC_TX_HASH_ALREADY_PROCESSED - ).stream().forEach(m -> { - Assertions.assertTrue(m.onlyAllowsLocalCalls(bridge, new Object[0])); + ).forEach(m -> { + assertTrue(m.onlyAllowsLocalCalls(bridge, new Object[0])); }); } @@ -3084,7 +3104,7 @@ void getBtcBlockchainBestChainHeight_afterRskip220_onlyAllowsLocalCalls() { Bridge bridge = getBridgeInstance(activationsMock); - Assertions.assertTrue(BridgeMethods.GET_BTC_BLOCKCHAIN_BEST_CHAIN_HEIGHT.onlyAllowsLocalCalls(bridge, new Object[0])); + assertTrue(BridgeMethods.GET_BTC_BLOCKCHAIN_BEST_CHAIN_HEIGHT.onlyAllowsLocalCalls(bridge, new Object[0])); } @Test @@ -3103,7 +3123,7 @@ void receiveHeadersGasCost_beforeDynamicCost() { byte[] data = BridgeMethods.RECEIVE_HEADERS.getFunction().encode(new Object[]{headers}); - Assertions.assertEquals(22000L + 2 * data.length, bridge.getGasForData(data)); + assertEquals(22000L + 2 * data.length, bridge.getGasForData(data)); } } @@ -3128,7 +3148,7 @@ void receiveHeadersGasCost_afterDynamicCost() { if (numberOfHeaders > 1) { cost += 1650L * (numberOfHeaders - 1); } - Assertions.assertEquals(cost, bridge.getGasForData(data)); + assertEquals(cost, bridge.getGasForData(data)); } } @@ -3160,9 +3180,9 @@ void receiveHeadersAccess_beforePublic_noAccessIfNotFromFederationMember() throw try { bridge.execute(data); - Assertions.fail(); + fail(); } catch (VMException e) { - Assertions.assertTrue(e.getMessage().contains("Sender is not part of the active")); + assertTrue(e.getMessage().contains("Sender is not part of the active")); } verify(bridgeSupportMock, never()).receiveHeaders(any(BtcBlock[].class)); } @@ -3194,7 +3214,7 @@ void receiveHeadersAccess_beforePublic_accessIfFromFederationMember() throws Exc byte[] data = BridgeMethods.RECEIVE_HEADERS.getFunction().encode(new Object[]{headers}); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); verify(bridgeSupportMock, times(1)).receiveHeaders(any(BtcBlock[].class)); } @@ -3221,7 +3241,7 @@ void receiveHeadersAccess_afterPublic_accessFromAnyone() throws Exception { byte[] data = BridgeMethods.RECEIVE_HEADERS.getFunction().encode(new Object[]{headers}); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); verify(bridgeSupportMock, times(1)).receiveHeaders(any(BtcBlock[].class)); } @@ -3284,11 +3304,11 @@ void getBtcBlockchainInitialBlockHeight() throws IOException, VMException { TestUtils.setInternalState(bridge, "bridgeSupport", bridgeSupportMock); when(bridgeSupportMock.getBtcBlockchainInitialBlockHeight()).thenReturn(1234); - Assertions.assertEquals(1234, bridge.getBtcBlockchainInitialBlockHeight(new Object[]{}).intValue()); + assertEquals(1234, bridge.getBtcBlockchainInitialBlockHeight(new Object[]{}).intValue()); } private BtcTransaction createTransaction() { - return createTransaction(PegTestUtils.createHash()); + return createTransaction(BitcoinTestUtils.createHash(1)); } private BtcTransaction createTransaction(Sha256Hash hash) { @@ -3363,7 +3383,7 @@ private void getGasForDataPaidTx(int expected, CallTransaction.Function function Repository mockRepository = mock(Repository.class); bridge.init(rskTx, rskExecutionBlock, mockRepository, null, null, null); - Assertions.assertEquals(expected, bridge.getGasForData(rskTx.getData())); + assertEquals(expected, bridge.getGasForData(rskTx.getData())); } private void registerBtcTransactionWithHugeDeclaredSize(BtcTransaction tx) throws VMException { @@ -3395,7 +3415,7 @@ private void registerBtcTransactionWithHugeDeclaredSize(BtcTransaction tx) throw byte[] data = Bridge.REGISTER_BTC_TRANSACTION.encode(serializedTx, 1, new byte[30]); - Assertions.assertNull(bridge.execute(data)); + assertNull(bridge.execute(data)); } private Bridge getBridgeInstance(ActivationConfig.ForBlock activations) { @@ -3411,10 +3431,10 @@ private Bridge getBridgeInstance(ActivationConfig.ForBlock activations) { private static class HugeDeclaredSizeBtcTransaction extends BtcTransaction { - private boolean hackInputsSize; - private boolean hackOutputsSize; - private boolean hackWitnessPushCountSize; - private boolean hackWitnessPushSize; + private final boolean hackInputsSize; + private final boolean hackOutputsSize; + private final boolean hackWitnessPushCountSize; + private final boolean hackWitnessPushSize; public HugeDeclaredSizeBtcTransaction(NetworkParameters params, boolean hackInputsSize, boolean hackOutputsSize, boolean hackWitnessPushCountSize, boolean hackWitnessPushSize) { super(params); @@ -3434,6 +3454,7 @@ public HugeDeclaredSizeBtcTransaction(NetworkParameters params, boolean hackInpu this.hackWitnessPushSize = hackWitnessPushSize; } + @Override protected void bitcoinSerializeToStream(OutputStream stream, boolean serializeWitRequested) throws IOException { boolean serializeWit = serializeWitRequested && hasWitness(); uint32ToByteStreamLE(getVersion(), stream); @@ -3443,12 +3464,14 @@ protected void bitcoinSerializeToStream(OutputStream stream, boolean serializeWi long inputsSize = hackInputsSize ? Integer.MAX_VALUE : getInputs().size(); stream.write(new VarInt(inputsSize).encode()); - for (TransactionInput in : getInputs()) + for (TransactionInput in : getInputs()) { in.bitcoinSerialize(stream); + } long outputsSize = hackOutputsSize ? Integer.MAX_VALUE : getOutputs().size(); stream.write(new VarInt(outputsSize).encode()); - for (TransactionOutput out : getOutputs()) + for (TransactionOutput out : getOutputs()) { out.bitcoinSerialize(stream); + } if (serializeWit) { for (int i = 0; i < getInputs().size(); i++) { TransactionWitness witness = getWitness(i); diff --git a/rskj-core/src/test/java/co/rsk/peg/performance/LockWhitelistTest.java b/rskj-core/src/test/java/co/rsk/peg/performance/LockWhitelistTest.java index 23e172b0031..e8cd298b880 100644 --- a/rskj-core/src/test/java/co/rsk/peg/performance/LockWhitelistTest.java +++ b/rskj-core/src/test/java/co/rsk/peg/performance/LockWhitelistTest.java @@ -26,6 +26,7 @@ import co.rsk.peg.RepositoryBtcBlockStoreWithCache; import co.rsk.peg.whitelist.LockWhitelist; import co.rsk.peg.whitelist.OneOffWhiteListEntry; +import java.math.BigInteger; import org.bouncycastle.util.encoders.Hex; import org.ethereum.core.Repository; import org.ethereum.crypto.ECKey; @@ -34,8 +35,6 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import java.math.BigInteger; - @Deprecated @Disabled class LockWhitelistTest extends BridgePerformanceTestCase { @@ -135,7 +134,8 @@ private BridgeStorageProviderInitializer buildInitializer() { int blocksToGenerate = Helper.randomInRange(minBtcBlocks, maxBtcBlocks); Helper.generateAndAddBlocks(btcBlockChain, blocksToGenerate); - lockWhitelist = provider.getLockWhitelist(); + // TODO: This logic needs to be adjusted to use the new WhitelistStorageProvider class +// lockWhitelist = provider.getLockWhitelist(); int size = Helper.randomInRange(minSize, maxSize); for (int i = 0; i < size; i++) { diff --git a/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistCaller.java b/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistCaller.java new file mode 100644 index 00000000000..4e8f654eaa4 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistCaller.java @@ -0,0 +1,18 @@ +package co.rsk.peg.whitelist; + +import co.rsk.core.RskAddress; + +public enum WhitelistCaller { + AUTHORIZED("6ba9d41b07da470fe340cbd439a42538795eb75b"), + UNAUTHORIZED("e2a5070b4e2cb77fe22dff05d9dcdc4d3eaa6ead"); + + private final String rskAddress; + + WhitelistCaller(String rskAddress) { + this.rskAddress = rskAddress; + } + + public RskAddress getRskAddress() { + return new RskAddress(rskAddress); + } +} diff --git a/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistStorageProviderImplTest.java b/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistStorageProviderImplTest.java new file mode 100644 index 00000000000..2ba0ead7f20 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistStorageProviderImplTest.java @@ -0,0 +1,216 @@ +package co.rsk.peg.whitelist; + +import static co.rsk.peg.whitelist.WhitelistStorageIndexKey.LOCK_ONE_OFF; +import static co.rsk.peg.whitelist.WhitelistStorageIndexKey.LOCK_UNLIMITED; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import co.rsk.bitcoinj.core.Address; +import co.rsk.bitcoinj.core.Coin; +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.BridgeSerializationUtils; +import co.rsk.peg.InMemoryStorage; +import co.rsk.peg.bitcoin.BitcoinTestUtils; +import co.rsk.peg.storage.StorageAccessor; +import co.rsk.peg.whitelist.constants.WhitelistConstants; +import co.rsk.peg.whitelist.constants.WhitelistMainNetConstants; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.config.blockchain.upgrades.ActivationConfig; +import org.ethereum.config.blockchain.upgrades.ConsensusRule; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class WhitelistStorageProviderImplTest { + private final WhitelistConstants whitelistConstants = WhitelistMainNetConstants.getInstance(); + private final NetworkParameters networkParameters = whitelistConstants.getBtcParams(); + private WhitelistStorageProvider whitelistStorageProvider; + private ActivationConfig.ForBlock activationConfig; + private StorageAccessor inMemoryStorage; + private Address firstBtcAddress; + private Address secondBtcAddress; + + @BeforeEach + void setUp() { + inMemoryStorage = new InMemoryStorage(); + whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorage); + activationConfig = mock(ActivationConfig.ForBlock.class); + firstBtcAddress = BitcoinTestUtils.createP2PKHAddress(networkParameters, "firstBtcAddress"); + secondBtcAddress = BitcoinTestUtils.createP2PKHAddress(networkParameters, "secondBtcAddress"); + } + + @Test + void save_whenLockWhitelistIsNull_shouldReturnZeroEntries() { + whitelistStorageProvider.save(activationConfig); + + LockWhitelist actualLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + // Make sure the lockWhitelist cache and storage entries are empty + assertEquals(0, actualLockWhitelist.getAll().size()); + + // There should be no value saved in the one-off entry + Map oneOffWhiteListEntryMap = getAddressFromOneOffStorageEntry(); + assertEquals(0, oneOffWhiteListEntryMap.size()); + + // There should be no value saved in the unlimited entry + Map unlimitedWhiteListEntryMap = getAddressFromUnlimitedStorageEntry(); + assertEquals(0, unlimitedWhiteListEntryMap.size()); + } + + @Test + void save_whenLockWhiteListIsNotNullAndRSKIP87IsNotActive_shouldReturnSavedValue() { + when(activationConfig.isActive(ConsensusRule.RSKIP87)).thenReturn(false); + LockWhitelist lockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + // Make sure the lockWhitelist is empty + assertEquals(0, lockWhitelist.getAll().size()); + + LockWhitelistEntry oneOffWhiteListEntry = createOneOffWhiteListEntry(firstBtcAddress); + lockWhitelist.put(firstBtcAddress, oneOffWhiteListEntry); + + whitelistStorageProvider.save(activationConfig); + + whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorage); + LockWhitelist actualLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + assertEquals(1, actualLockWhitelist.getAll().size()); + + // Making sure the saved value is correct and related to OneOffWhiteListEntry + Map oneOffWhiteListEntryMap = getAddressFromOneOffStorageEntry(); + assertTrue(oneOffWhiteListEntryMap.containsKey(firstBtcAddress)); + + // Making sure there is no value saved in storage related to UnlimitedWhiteListEntry + Map unlimitedWhiteListEntryMap = getAddressFromUnlimitedStorageEntry(); + assertEquals(0, unlimitedWhiteListEntryMap.size()); + } + + @Test + void save_whenIsActiveRSKIP87_shouldSavedUnlimitedLockWhitelist() { + when(activationConfig.isActive(ConsensusRule.RSKIP87)).thenReturn(true); + LockWhitelist lockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + // Make sure the lockWhitelist is empty + assertEquals(0, lockWhitelist.getAll().size()); + + LockWhitelistEntry oneOffWhiteListEntry = createOneOffWhiteListEntry(firstBtcAddress); + LockWhitelistEntry unlimitedWhiteListEntry = createUnlimitedWhiteListEntry(secondBtcAddress); + lockWhitelist.put(firstBtcAddress, oneOffWhiteListEntry); + lockWhitelist.put(secondBtcAddress, unlimitedWhiteListEntry); + + whitelistStorageProvider.save(activationConfig); + + whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorage); + LockWhitelist actualLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + assertEquals(2, actualLockWhitelist.getAll().size()); + + // Making sure the saved value is correct + Map oneOffWhiteListEntryMap = getAddressFromOneOffStorageEntry(); + assertTrue(oneOffWhiteListEntryMap.containsKey(firstBtcAddress)); + + Map lockWhitelistEntryMap = getAddressFromUnlimitedStorageEntry(); + assertTrue(lockWhitelistEntryMap.containsKey(secondBtcAddress)); + } + + @Test + void getLockWhitelist_whenNoEntriesInStorage_shouldReturnZeroEntries() { + LockWhitelist actualLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + assertEquals(0, actualLockWhitelist.getAll().size()); + } + + @Test + void getLockWhitelist_shouldReturnActualEntries() { + // The first time LockWhitelist is null and it queries the storage + LockWhitelist tempLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + // It should return zero entries as there is no value saved in storage. As of here LockWhitelist is not null + assertEquals(0, tempLockWhitelist.getAll().size()); + + // Saving a value directly in storage + saveInMemoryStorageOneOffWhiteListEntry(firstBtcAddress); + // The second time LockWhitelist is not null so that it doesn't query the storage and get the value from cache + tempLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + // Return zero entries as it doesn't query in storage + assertEquals(0, tempLockWhitelist.getAll().size()); + assertFalse(tempLockWhitelist.isWhitelisted(firstBtcAddress)); + + // Recreating whitelistStorageProvider to make sure it is querying the storage + whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorage); + tempLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + // Return one entry that was saved directly in storage + assertEquals(1, tempLockWhitelist.getAll().size()); + // Making sure the correct value was whitelisted + assertTrue(tempLockWhitelist.isWhitelisted(firstBtcAddress)); + } + + @Test + void getWhitelist_whenIsActiveRSKIP87_shouldReturnUnlimitedEntries() { + when(activationConfig.isActive(ConsensusRule.RSKIP87)).thenReturn(true); + saveInMemoryStorageOneOffWhiteListEntry(firstBtcAddress); + saveInMemoryStorageUnlimitedWhiteListEntry(secondBtcAddress); + + LockWhitelist actualLockWhitelist = whitelistStorageProvider.getLockWhitelist(activationConfig, networkParameters); + + assertEquals(2, actualLockWhitelist.getAll().size()); + // Making sure the correct value was whitelisted + assertTrue(actualLockWhitelist.isWhitelisted(firstBtcAddress)); + assertTrue(actualLockWhitelist.isWhitelisted(secondBtcAddress)); + } + + private void saveInMemoryStorageOneOffWhiteListEntry(Address btcAddress) { + OneOffWhiteListEntry oneOffWhiteListEntry = createOneOffWhiteListEntry(btcAddress); + List oneOffWhiteListEntries = Collections.singletonList(oneOffWhiteListEntry); + Pair, Integer> pairValue = Pair.of(oneOffWhiteListEntries, 100); + + inMemoryStorage.safeSaveToRepository( + LOCK_ONE_OFF.getKey(), + pairValue, + BridgeSerializationUtils::serializeOneOffLockWhitelist + ); + } + + private void saveInMemoryStorageUnlimitedWhiteListEntry(Address btcAddress) { + UnlimitedWhiteListEntry unlimitedWhiteListEntry = createUnlimitedWhiteListEntry(btcAddress); + List unlimitedWhiteListEntries = Collections.singletonList(unlimitedWhiteListEntry); + + inMemoryStorage.safeSaveToRepository( + WhitelistStorageIndexKey.LOCK_UNLIMITED.getKey(), + unlimitedWhiteListEntries, + BridgeSerializationUtils::serializeUnlimitedLockWhitelist + ); + } + + private OneOffWhiteListEntry createOneOffWhiteListEntry(Address btcAddress) { + Coin maxTransferValue = Coin.COIN; + return new OneOffWhiteListEntry(btcAddress, maxTransferValue); + } + + private UnlimitedWhiteListEntry createUnlimitedWhiteListEntry(Address btcAddress) { + return new UnlimitedWhiteListEntry(btcAddress); + } + + private Map getAddressFromOneOffStorageEntry() { + Pair, Integer> oneOffWhitelistAndDisableBlockHeightData = inMemoryStorage.safeGetFromRepository( + LOCK_ONE_OFF.getKey(), + data -> BridgeSerializationUtils.deserializeOneOffLockWhitelistAndDisableBlockHeight(data, networkParameters) + ); + return Objects.isNull(oneOffWhitelistAndDisableBlockHeightData) ? new HashMap<>() : oneOffWhitelistAndDisableBlockHeightData.getLeft(); + } + + private Map getAddressFromUnlimitedStorageEntry() { + return inMemoryStorage.safeGetFromRepository( + LOCK_UNLIMITED.getKey(), + data -> BridgeSerializationUtils.deserializeUnlimitedLockWhitelistEntries( + data, + networkParameters) + ); + } +} diff --git a/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistSupportImplTest.java b/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistSupportImplTest.java new file mode 100644 index 00000000000..3af7a66b887 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/peg/whitelist/WhitelistSupportImplTest.java @@ -0,0 +1,362 @@ +package co.rsk.peg.whitelist; + +import static co.rsk.peg.whitelist.WhitelistStorageIndexKey.LOCK_ONE_OFF; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import co.rsk.bitcoinj.core.Address; +import co.rsk.bitcoinj.core.Coin; +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.net.utils.TransactionUtils; +import co.rsk.peg.BridgeSerializationUtils; +import co.rsk.peg.InMemoryStorage; +import co.rsk.peg.bitcoin.BitcoinTestUtils; +import co.rsk.peg.storage.StorageAccessor; +import co.rsk.peg.whitelist.constants.WhitelistConstants; +import co.rsk.peg.whitelist.constants.WhitelistMainNetConstants; +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.ethereum.config.blockchain.upgrades.ActivationConfig; +import org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest; +import org.ethereum.core.BlockTxSignatureCache; +import org.ethereum.core.ReceivedTxSignatureCache; +import org.ethereum.core.SignatureCache; +import org.ethereum.core.Transaction; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class WhitelistSupportImplTest { + private final WhitelistConstants whitelistConstants = WhitelistMainNetConstants.getInstance(); + private final NetworkParameters networkParameters = whitelistConstants.getBtcParams(); + private WhitelistSupport whitelistSupport; + private SignatureCache signatureCache; + private StorageAccessor inMemoryStorage; + private Address btcAddress; + private Address secondBtcAddress; + + @BeforeEach + void setUp() { + inMemoryStorage = new InMemoryStorage(); + WhitelistStorageProvider whitelistStorageProvider = new WhitelistStorageProviderImpl(inMemoryStorage); + ActivationConfig.ForBlock activationConfig = ActivationConfigsForTest.all().forBlock(0); + signatureCache = new BlockTxSignatureCache(new ReceivedTxSignatureCache()); + whitelistSupport = new WhitelistSupportImpl(whitelistConstants, whitelistStorageProvider, activationConfig, signatureCache); + btcAddress = BitcoinTestUtils.createP2PKHAddress(networkParameters, "btcAddress"); + secondBtcAddress = BitcoinTestUtils.createP2PKHAddress(networkParameters, "secondBtcAddress"); + } + + @Test + void getLockWhitelistSize_whenLockWhitelistIsEmpty_shouldReturnZero() { + int actualSize = whitelistSupport.getLockWhitelistSize(); + + assertEquals(0, actualSize); + } + + @Test + void getLockWhitelistSize_whenLockWhitelistHasEntries_shouldReturnOne() { + saveInMemoryStorageOneOffWhiteListEntry(); + + int actualSize = whitelistSupport.getLockWhitelistSize(); + + assertEquals(1, actualSize); + } + + @Test + void getLockWhitelistEntryByIndex_whenLockWhitelistIsEmpty_shouldReturnNull() { + LockWhitelistEntry actualEntry = whitelistSupport.getLockWhitelistEntryByIndex(0); + + assertNull(actualEntry); + } + + @Test + void getLockWhitelistEntryByIndex_whenLockWhitelistHasEntries_shouldReturnOneOffWhiteListEntry() { + saveInMemoryStorageOneOffWhiteListEntry(); + + LockWhitelistEntry actualLockWhitelistEntry = whitelistSupport.getLockWhitelistEntryByIndex(0); + + assertEquals(btcAddress, actualLockWhitelistEntry.address()); + } + + @Test + void getLockWhitelistEntryByIndex_whenIndexIsOutOfBounds_shouldReturnNull() { + saveInMemoryStorageOneOffWhiteListEntry(); + + LockWhitelistEntry actualLockWhitelistEntry = whitelistSupport.getLockWhitelistEntryByIndex(1); + + assertNull(actualLockWhitelistEntry); + } + + @Test + void getLockWhitelistEntryByAddress_whenLockWhitelistIsEmpty_shouldReturnNull() { + LockWhitelistEntry actualEntry = whitelistSupport.getLockWhitelistEntryByAddress(btcAddress.toString()); + + assertNull(actualEntry); + } + + @Test + void getLockWhitelistEntryByAddress_whenLockWhitelistHasEntries_shouldReturnOneOffWhiteListEntry() { + saveInMemoryStorageOneOffWhiteListEntry(); + + LockWhitelistEntry actualLockWhitelistEntry = whitelistSupport.getLockWhitelistEntryByAddress(btcAddress.toString()); + + assertEquals(btcAddress, actualLockWhitelistEntry.address()); + } + + private void saveInMemoryStorageOneOffWhiteListEntry() { + Coin maxTransferValue = Coin.COIN; + final int disableBlockHeight = 100; + OneOffWhiteListEntry oneOffWhiteListEntry = new OneOffWhiteListEntry(btcAddress, maxTransferValue); + List oneOffWhiteListEntries = Collections.singletonList(oneOffWhiteListEntry); + Pair, Integer> pairValue = Pair.of(oneOffWhiteListEntries, disableBlockHeight); + + inMemoryStorage.safeSaveToRepository( + LOCK_ONE_OFF.getKey(), + pairValue, + BridgeSerializationUtils::serializeOneOffLockWhitelist + ); + } + + @Test + void getLockWhitelistEntryByAddress_whenAddressIsInvalid_shouldReturnNull() { + LockWhitelistEntry actualLockWhitelistEntry = whitelistSupport.getLockWhitelistEntryByAddress("invalidAddress"); + assertNull(actualLockWhitelistEntry); + } + + @Test + void addOneOffLockWhitelistAddress_whenAddressIsWhitelisted_shouldReturnSuccess() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), actualResult); + } + + @Test + void addOneOffLockWhitelistAddress_whenAddressIsAlreadyWhitelisted_shouldReturnAddressAlreadyWhitelisted() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + // Add the address to the whitelist + whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + + // Try to add the address again + int actualResult = whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + + assertEquals(WhitelistResponseCode.ADDRESS_ALREADY_WHITELISTED.getCode(), actualResult); + } + + @Test + void addOneOffLockWhitelistAddress_whenAddressIsInvalid_shouldReturnInvalidAddressFormat() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.addOneOffLockWhitelistAddress(tx, "invalidAddress", BigInteger.TEN); + + assertEquals(WhitelistResponseCode.INVALID_ADDRESS_FORMAT.getCode(), actualResult); + } + + @Test + void addOneOffLockWhitelistAddress_whenCallerIsUnauthorized_shouldReturnUnauthorizedCaller() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.UNAUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + + assertEquals(WhitelistResponseCode.UNAUTHORIZED_CALLER.getCode(), actualResult); + } + + @Test + void addUnlimitedLockWhitelistAddress_whenAddressIsWhitelisted_shouldReturnSuccess() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), actualResult); + } + + @Test + void addUnlimitedLockWhitelistAddress_whenAddressIsAlreadyWhitelisted_shouldReturnAddressAlreadyWhitelisted() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + // Add the address to the whitelist + whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + // Try to add the address again + int actualResult = whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + assertEquals(WhitelistResponseCode.ADDRESS_ALREADY_WHITELISTED.getCode(), actualResult); + } + + @Test + void addUnlimitedLockWhitelistAddress_whenAddressIsInvalid_shouldReturnInvalidAddressFormat() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.addUnlimitedLockWhitelistAddress(tx, "invalidAddress"); + + assertEquals(WhitelistResponseCode.INVALID_ADDRESS_FORMAT.getCode(), actualResult); + } + + @Test + void addUnlimitedLockWhitelistAddress_whenCallerIsUnauthorized_shouldReturnUnauthorizedCaller() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.UNAUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + assertEquals(WhitelistResponseCode.UNAUTHORIZED_CALLER.getCode(), actualResult); + } + + @Test + void removeLockWhitelistAddress_whenAddressIsWhitelisted_shouldReturnSuccess() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + // Add the address to the whitelist + whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + // Remove the address from the whitelist + int actualResult = whitelistSupport.removeLockWhitelistAddress(tx, btcAddress.toString()); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), actualResult); + } + + @Test + void removeLockWhitelistAddress_whenAddressIsNotWhitelisted_shouldReturnAddressNotExist() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.removeLockWhitelistAddress(tx, btcAddress.toString()); + + assertEquals(WhitelistResponseCode.ADDRESS_NOT_EXIST.getCode(), actualResult); + } + + @Test + void removeLockWhitelistAddress_whenAddressIsInvalid_shouldReturnInvalidAddressFormat() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + int actualResult = whitelistSupport.removeLockWhitelistAddress(tx, "invalidAddress"); + assertEquals(WhitelistResponseCode.INVALID_ADDRESS_FORMAT.getCode(), actualResult); + } + + @Test + void removeLockWhitelistAddress_whenCallerIsUnauthorized_shouldReturnUnauthorizedCaller() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.UNAUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.removeLockWhitelistAddress(tx, btcAddress.toString()); + + assertEquals(WhitelistResponseCode.UNAUTHORIZED_CALLER.getCode(), actualResult); + } + + @Test + void setLockWhitelistDisableBlockDelay_whenCallerIsUnauthorized_shouldReturnUnauthorizedCaller() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.UNAUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.setLockWhitelistDisableBlockDelay(tx, BigInteger.TEN, 0); + + assertEquals(WhitelistResponseCode.UNAUTHORIZED_CALLER.getCode(), actualResult); + } + + @Test + void setLockWhitelistDisableBlockDelay_whenCallerIsAuthorized_shouldReturnSuccess() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.setLockWhitelistDisableBlockDelay(tx, BigInteger.TEN, 0); + + assertEquals(WhitelistResponseCode.SUCCESS.getCode(), actualResult); + } + + @Test + void setLockWhitelistDisableBlockDelay_whenDisableBlockIsSet_shouldReturnDelayAlreadySet() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + // Set the disable block delay + whitelistSupport.setLockWhitelistDisableBlockDelay(tx, BigInteger.TEN, 0); + + // Try to set the disable block delay again + int actualResult = whitelistSupport.setLockWhitelistDisableBlockDelay(tx, BigInteger.TEN, 0); + + assertEquals(WhitelistResponseCode.DELAY_ALREADY_SET.getCode(), actualResult); + } + + @Test + void setLockWhitelistDisableBlockDelay_whenDisableBlockDelayPlusBtcBlockchainBestChainHeightIsLessOrEqualThanBtcBlockchainBestChainHeight_shouldReturnDisableBlockDelayInvalid() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + + int actualResult = whitelistSupport.setLockWhitelistDisableBlockDelay(tx, BigInteger.ZERO, 0); + + assertEquals(WhitelistResponseCode.DISABLE_BLOCK_DELAY_INVALID.getCode(), actualResult); + } + + @Test + void verifyLockSenderIsWhitelisted_whenOneOffLockWhitelistAddressIsWhitelisted_shouldReturnTrue() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + LockWhitelistEntry lockWhitelistEntry = whitelistSupport.getLockWhitelistEntryByAddress(btcAddress.toString()); + + boolean actualResult = whitelistSupport.verifyLockSenderIsWhitelisted(btcAddress, Coin.SATOSHI, 0); + + assertTrue(lockWhitelistEntry.isConsumed()); + assertTrue(actualResult); + } + + @Test + void verifyLockSenderIsWhitelisted_whenUnlimitedLockWhitelistAddressIsWhitelisted_shouldReturnTrue() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + boolean actualResult = whitelistSupport.verifyLockSenderIsWhitelisted(btcAddress, Coin.SATOSHI, 0); + + assertTrue(actualResult); + } + + @Test + void verifyLockSenderIsWhitelisted_whenAddressIsNotWhitelisted_shouldReturnFalse() { + boolean actualResult = whitelistSupport.verifyLockSenderIsWhitelisted(btcAddress, Coin.SATOSHI, 0); + + assertFalse(actualResult); + } + + @Test + void save_whenLockWhitelistIsNull_shouldReturnZeroEntries() { + whitelistSupport.save(); + + int actualSize = whitelistSupport.getLockWhitelistSize(); + assertEquals(0, actualSize); + assertNull(whitelistSupport.getLockWhitelistEntryByIndex(0)); + assertNull(whitelistSupport.getLockWhitelistEntryByIndex(1)); + } + + @Test + void save_whenOneOffLockWhitelistAddressIsWhitelisted_shouldSaveOneOffLockWhitelistAddress() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + + whitelistSupport.save(); + + int actualSize = whitelistSupport.getLockWhitelistSize(); + Address actualBtcAddress = whitelistSupport.getLockWhitelistEntryByAddress(btcAddress.toString()).address(); + assertEquals(1, actualSize); + assertEquals(btcAddress, actualBtcAddress); + } + + @Test + void save_whenUnlimitedLockWhitelistAddressIsWhitelisted_shouldSaveUnlimitedLockWhitelistAddress() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + whitelistSupport.addUnlimitedLockWhitelistAddress(tx, btcAddress.toString()); + + whitelistSupport.save(); + + int actualSize = whitelistSupport.getLockWhitelistSize(); + Address actualBtcAddress = whitelistSupport.getLockWhitelistEntryByAddress(btcAddress.toString()).address(); + assertEquals(1, actualSize); + assertEquals(btcAddress, actualBtcAddress); + } + + @Test + void save_whenOneOffAndUnlimitedLockWhitelistAddressesAreWhitelisted_shouldSaveBothAddresses() { + Transaction tx = TransactionUtils.getTransactionFromCaller(signatureCache, WhitelistCaller.AUTHORIZED.getRskAddress()); + whitelistSupport.addOneOffLockWhitelistAddress(tx, btcAddress.toString(), BigInteger.TEN); + whitelistSupport.addUnlimitedLockWhitelistAddress(tx, secondBtcAddress.toString()); + + whitelistSupport.save(); + + int actualSize = whitelistSupport.getLockWhitelistSize(); + Address actualBtcAddress = whitelistSupport.getLockWhitelistEntryByAddress(btcAddress.toString()).address(); + Address actualSecondBtcAddress = whitelistSupport.getLockWhitelistEntryByAddress(secondBtcAddress.toString()).address(); + assertEquals(2, actualSize); + assertEquals(btcAddress, actualBtcAddress); + assertEquals(secondBtcAddress, actualSecondBtcAddress); + } +} diff --git a/rskj-core/src/test/java/co/rsk/peg/whitelist/constants/WhitelistConstantsTest.java b/rskj-core/src/test/java/co/rsk/peg/whitelist/constants/WhitelistConstantsTest.java new file mode 100644 index 00000000000..46c0d64dda4 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/peg/whitelist/constants/WhitelistConstantsTest.java @@ -0,0 +1,84 @@ +package co.rsk.peg.whitelist.constants; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.samePropertyValuesAs; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import co.rsk.bitcoinj.core.NetworkParameters; +import co.rsk.peg.vote.AddressBasedAuthorizer; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; +import org.bouncycastle.util.encoders.Hex; +import org.ethereum.crypto.ECKey; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class WhitelistConstantsTest { + + @ParameterizedTest + @MethodSource("getLockWhitelistChangeAuthorizerProvider") + void getLockWhitelistChangeAuthorizer(WhitelistConstants whitelistConstants, AddressBasedAuthorizer expectedLockWhitelistChangeAuthorizer) { + AddressBasedAuthorizer actualLockWhitelistChangeAuthorizer = whitelistConstants.getLockWhitelistChangeAuthorizer(); + + assertThat(actualLockWhitelistChangeAuthorizer, samePropertyValuesAs(expectedLockWhitelistChangeAuthorizer)); + } + + private static Stream getLockWhitelistChangeAuthorizerProvider() { + //MainNet + ECKey mainNetAuthorizerPublicKey = ECKey.fromPublicOnly(Hex.decode( + "041a2449e9d63409c5a8ea3a21c4109b1a6634ee88fd57176d45ea46a59713d5e0b688313cf252128a3e49a0b2effb4b413e5a2525a6fa5894d059f815c9d9efa6" + )); + List mainNetLockWhitelistAuthorizedKeys = Collections.singletonList(mainNetAuthorizerPublicKey); + + AddressBasedAuthorizer mainNetLockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( + mainNetLockWhitelistAuthorizedKeys, + AddressBasedAuthorizer.MinimumRequiredCalculation.ONE + ); + + //TestNet + ECKey testNetAuthorizerPublicKey = ECKey.fromPublicOnly(Hex.decode( + "04bf7e3bca7f7c58326382ed9c2516a8773c21f1b806984bb1c5c33bd18046502d97b28c0ea5b16433fbb2b23f14e95b36209f304841e814017f1ede1ecbdcfce3" + )); + List testNetLockWhitelistAuthorizedKeys = Collections.singletonList(testNetAuthorizerPublicKey); + + AddressBasedAuthorizer testNetLockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( + testNetLockWhitelistAuthorizedKeys, + AddressBasedAuthorizer.MinimumRequiredCalculation.ONE + ); + + //RegTest + ECKey regTestAuthorizerPublicKey = ECKey.fromPublicOnly(Hex.decode( + "04641fb250d7ca7a1cb4f530588e978013038ec4294d084d248869dd54d98873e45c61d00ceeaeeb9e35eab19fa5fbd8f07cb8a5f0ddba26b4d4b18349c09199ad" + )); + List regTestLockWhitelistAuthorizedKeys = Collections.singletonList(regTestAuthorizerPublicKey); + + AddressBasedAuthorizer regTestLockWhitelistChangeAuthorizer = new AddressBasedAuthorizer( + regTestLockWhitelistAuthorizedKeys, + AddressBasedAuthorizer.MinimumRequiredCalculation.ONE + ); + + return Stream.of( + Arguments.of(WhitelistMainNetConstants.getInstance(), mainNetLockWhitelistChangeAuthorizer), + Arguments.of(WhitelistTestNetConstants.getInstance(), testNetLockWhitelistChangeAuthorizer), + Arguments.of(WhitelistRegTestConstants.getInstance(), regTestLockWhitelistChangeAuthorizer) + ); + } + + @ParameterizedTest + @MethodSource("btcParamsProvider") + void getBtcParams(WhitelistConstants whitelistConstants, NetworkParameters expectedNetworkParameters) { + NetworkParameters actualNetworkParameters = whitelistConstants.getBtcParams(); + + assertEquals(expectedNetworkParameters, actualNetworkParameters); + } + + private static Stream btcParamsProvider() { + return Stream.of( + Arguments.of(WhitelistMainNetConstants.getInstance(), NetworkParameters.fromID(NetworkParameters.ID_MAINNET)), + Arguments.of(WhitelistTestNetConstants.getInstance(), NetworkParameters.fromID(NetworkParameters.ID_TESTNET)), + Arguments.of(WhitelistRegTestConstants.getInstance(), NetworkParameters.fromID(NetworkParameters.ID_REGTEST)) + ); + } +} diff --git a/rskj-core/src/test/java/co/rsk/test/builders/BridgeSupportBuilder.java b/rskj-core/src/test/java/co/rsk/test/builders/BridgeSupportBuilder.java index dc0f9ed0ff0..d891c9b6e98 100644 --- a/rskj-core/src/test/java/co/rsk/test/builders/BridgeSupportBuilder.java +++ b/rskj-core/src/test/java/co/rsk/test/builders/BridgeSupportBuilder.java @@ -12,6 +12,7 @@ import co.rsk.peg.feeperkb.FeePerKbSupport; import co.rsk.peg.pegininstructions.PeginInstructionsProvider; import co.rsk.peg.utils.BridgeEventLogger; +import co.rsk.peg.whitelist.WhitelistSupport; import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.core.*; @@ -23,10 +24,11 @@ public class BridgeSupportBuilder { private PeginInstructionsProvider peginInstructionsProvider; private Repository repository; private Block executionBlock; + private FeePerKbSupport feePerKbSupport; + private WhitelistSupport whitelistSupport; private Factory btcBlockStoreFactory; private ActivationConfig.ForBlock activations; private SignatureCache signatureCache; - private FeePerKbSupport feePerKbSupport; public BridgeSupportBuilder() { this.bridgeConstants = mock(BridgeConstants.class); @@ -36,10 +38,11 @@ public BridgeSupportBuilder() { this.peginInstructionsProvider = mock(PeginInstructionsProvider.class); this.repository = mock(Repository.class); this.executionBlock = mock(Block.class); + this.feePerKbSupport = mock(FeePerKbSupport.class); + this.whitelistSupport = mock(WhitelistSupport.class); this.btcBlockStoreFactory = mock(Factory.class); this.activations = mock(ActivationConfig.ForBlock.class); this.signatureCache = mock(BlockTxSignatureCache.class); - this.feePerKbSupport = mock(FeePerKbSupport.class); } public BridgeSupportBuilder withBridgeConstants(BridgeConstants bridgeConstants) { @@ -77,6 +80,16 @@ public BridgeSupportBuilder withExecutionBlock(Block executionBlock) { return this; } + public BridgeSupportBuilder withFeePerKbSupport(FeePerKbSupport feePerKbSupport) { + this.feePerKbSupport = feePerKbSupport; + return this; + } + + public BridgeSupportBuilder withWhitelistSupport(WhitelistSupport whitelistSupport) { + this.whitelistSupport = whitelistSupport; + return this; + } + public BridgeSupportBuilder withBtcBlockStoreFactory(Factory btcBlockStoreFactory) { this.btcBlockStoreFactory = btcBlockStoreFactory; return this; @@ -92,11 +105,6 @@ public BridgeSupportBuilder withSignatureCache(SignatureCache signatureCache) { return this; } - public BridgeSupportBuilder withFeePerKbSupport(FeePerKbSupport feePerKbSupport) { - this.feePerKbSupport = feePerKbSupport; - return this; - } - public BridgeSupport build() { return new BridgeSupport( bridgeConstants, @@ -109,6 +117,7 @@ public BridgeSupport build() { new Context(bridgeConstants.getBtcParams()), new FederationSupport(bridgeConstants, provider, executionBlock, activations), feePerKbSupport, + whitelistSupport, btcBlockStoreFactory, activations, signatureCache diff --git a/rskj-core/src/test/java/org/ethereum/TestUtils.java b/rskj-core/src/test/java/org/ethereum/TestUtils.java index 96b6b60b372..5998dc69925 100644 --- a/rskj-core/src/test/java/org/ethereum/TestUtils.java +++ b/rskj-core/src/test/java/org/ethereum/TestUtils.java @@ -19,6 +19,9 @@ package org.ethereum; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import co.rsk.core.RskAddress; import co.rsk.crypto.Keccak256; import org.apache.commons.lang3.StringUtils; @@ -291,4 +294,9 @@ public static void waitFor(long durationMillis) { } } + public static RskAddress mockAddress(String addr) { + RskAddress mock = mock(RskAddress.class); + when(mock.getBytes()).thenReturn(Hex.decode(addr)); + return mock; + } }