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 da79afb75f0..9e6144675ca 100644 --- a/rskj-core/src/main/java/co/rsk/peg/Bridge.java +++ b/rskj-core/src/main/java/co/rsk/peg/Bridge.java @@ -29,6 +29,7 @@ import co.rsk.panic.PanicProcessor; import co.rsk.peg.BridgeMethods.BridgeMethodExecutor; import co.rsk.peg.feeperkb.FeePerKbResponseCode; +import co.rsk.peg.lockingcap.LockingCapIllegalArgumentException; import co.rsk.peg.vote.ABICallSpec; import co.rsk.peg.bitcoin.MerkleBranch; import co.rsk.peg.federation.Federation; @@ -461,7 +462,7 @@ private boolean shouldReturnNullOnVoidMethods() { return !activations.isActive(RSKIP417); } - private void teardown() throws IOException { + private void teardown() { bridgeSupport.save(); } @@ -902,7 +903,7 @@ public long getRetiringFederationCreationBlockNumber(Object[] args) { return bridgeSupport.getRetiringFederationCreationBlockNumber(); } - public Integer createFederation(Object[] args) throws BridgeIllegalArgumentException { + public Integer createFederation(Object[] args) { logger.trace("createFederation"); return bridgeSupport.voteFederationChange( @@ -911,7 +912,7 @@ public Integer createFederation(Object[] args) throws BridgeIllegalArgumentExcep ); } - public Integer addFederatorPublicKey(Object[] args) throws BridgeIllegalArgumentException { + public Integer addFederatorPublicKey(Object[] args) { logger.trace("addFederatorPublicKey"); byte[] publicKeyBytes; @@ -928,7 +929,7 @@ public Integer addFederatorPublicKey(Object[] args) throws BridgeIllegalArgument ); } - public Integer addFederatorPublicKeyMultikey(Object[] args) throws BridgeIllegalArgumentException { + public Integer addFederatorPublicKeyMultikey(Object[] args) { logger.trace("addFederatorPublicKeyMultikey"); byte[] btcPublicKeyBytes = (byte[]) args[0]; @@ -944,7 +945,7 @@ public Integer addFederatorPublicKeyMultikey(Object[] args) throws BridgeIllegal ); } - public Integer commitFederation(Object[] args) throws BridgeIllegalArgumentException { + public Integer commitFederation(Object[] args) { logger.trace("commitFederation"); byte[] hash; @@ -961,7 +962,7 @@ public Integer commitFederation(Object[] args) throws BridgeIllegalArgumentExcep ); } - public Integer rollbackFederation(Object[] args) throws BridgeIllegalArgumentException { + public Integer rollbackFederation(Object[] args) { logger.trace("rollbackFederation"); return bridgeSupport.voteFederationChange( @@ -1163,13 +1164,12 @@ public byte[] getActivePowpegRedeemScript(Object[] args) { public boolean increaseLockingCap(Object[] args) throws BridgeIllegalArgumentException { logger.trace("increaseLockingCap"); - Coin newLockingCap = BridgeUtils.getCoinFromBigInteger((BigInteger) args[0]); - if (newLockingCap.getValue() <= 0) { - throw new BridgeIllegalArgumentException("Locking cap must be bigger than zero"); + try { + return bridgeSupport.increaseLockingCap(rskTx, newLockingCap); + } catch (LockingCapIllegalArgumentException e) { + throw new BridgeIllegalArgumentException(e); } - - return bridgeSupport.increaseLockingCap(rskTx, newLockingCap); } public void registerBtcCoinbaseTransaction(Object[] args) throws VMException { diff --git a/rskj-core/src/main/java/co/rsk/peg/BridgeIllegalArgumentException.java b/rskj-core/src/main/java/co/rsk/peg/BridgeIllegalArgumentException.java index 0cb15cfe5a2..96f0145150e 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeIllegalArgumentException.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeIllegalArgumentException.java @@ -36,4 +36,8 @@ public BridgeIllegalArgumentException(String s) { public BridgeIllegalArgumentException(String message, Throwable cause) { super(message, cause); } + + public BridgeIllegalArgumentException(Throwable cause) { + super(cause); + } } 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 47da68f3def..9c42f5952ed 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeStorageIndexKey.java @@ -8,7 +8,6 @@ public enum BridgeStorageIndexKey { RELEASE_REQUEST_QUEUE("releaseRequestQueue"), PEGOUTS_WAITING_FOR_CONFIRMATIONS("releaseTransactionSet"), PEGOUTS_WAITING_FOR_SIGNATURES("rskTxsWaitingFS"), - LOCKING_CAP_KEY("lockingCap"), RELEASE_REQUEST_QUEUE_WITH_TXHASH("releaseRequestQueueWithTxHash"), PEGOUTS_WAITING_FOR_CONFIRMATIONS_WITH_TXHASH_KEY("releaseTransactionSetWithTxHash"), RECEIVE_HEADERS_TIMESTAMP("receiveHeadersLastTimestamp"), 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 38c821473cc..1b9797bd1c5 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeStorageProvider.java @@ -62,8 +62,6 @@ public class BridgeStorageProvider { private PegoutsWaitingForConfirmations pegoutsWaitingForConfirmations; private SortedMap pegoutsWaitingForSignatures; - private Coin lockingCap; - private HashMap btcTxHashesToSave; private Map coinbaseInformationMap; @@ -250,26 +248,6 @@ public void savePegoutsWaitingForSignatures() { safeSaveToRepository(PEGOUTS_WAITING_FOR_SIGNATURES, pegoutsWaitingForSignatures, BridgeSerializationUtils::serializeMap); } - public void saveLockingCap() { - if (activations.isActive(RSKIP134)) { - safeSaveToRepository(LOCKING_CAP_KEY, this.getLockingCap(), BridgeSerializationUtils::serializeCoin); - } - } - - public void setLockingCap(Coin lockingCap) { - this.lockingCap = lockingCap; - } - - public Coin getLockingCap() { - if (activations.isActive(RSKIP134)) { - if (this.lockingCap == null) { - this.lockingCap = safeGetFromRepository(LOCKING_CAP_KEY, BridgeSerializationUtils::deserializeCoin); - } - return this.lockingCap; - } - return null; - } - public CoinbaseInformation getCoinbaseInformation(Sha256Hash blockHash) { if (!activations.isActive(RSKIP143)) { return null; @@ -395,15 +373,15 @@ public Optional getFlyoverFederationInformation(by return Optional.empty(); } - FlyoverFederationInformation flyoverFederationInformation = this.safeGetFromRepository( + FlyoverFederationInformation flyoverFederationInformationInStorage = this.safeGetFromRepository( getStorageKeyForFlyoverFederationInformation(flyoverFederationRedeemScriptHash), data -> BridgeSerializationUtils.deserializeFlyoverFederationInformation(data, flyoverFederationRedeemScriptHash) ); - if (flyoverFederationInformation == null) { + if (flyoverFederationInformationInStorage == null) { return Optional.empty(); } - return Optional.of(flyoverFederationInformation); + return Optional.of(flyoverFederationInformationInStorage); } public void setFlyoverFederationInformation(FlyoverFederationInformation flyoverFederationInformation) { @@ -542,15 +520,13 @@ protected void savePegoutTxSigHashes() { )); } - public void save() throws IOException { + public void save() { saveBtcTxHashesAlreadyProcessed(); saveReleaseRequestQueue(); savePegoutsWaitingForConfirmations(); savePegoutsWaitingForSignatures(); - saveLockingCap(); - saveHeightBtcTxHashAlreadyProcessed(); saveCoinbaseInformations(); 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 6a864cff6e6..1d8bd8a64f0 100644 --- a/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java +++ b/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java @@ -34,10 +34,7 @@ import co.rsk.core.RskAddress; import co.rsk.crypto.Keccak256; import co.rsk.panic.PanicProcessor; -import co.rsk.peg.bitcoin.BitcoinUtils; -import co.rsk.peg.bitcoin.CoinbaseInformation; -import co.rsk.peg.bitcoin.MerkleBranch; -import co.rsk.peg.bitcoin.RskAllowUnconfirmedCoinSelector; +import co.rsk.peg.bitcoin.*; import co.rsk.peg.btcLockSender.BtcLockSender.TxSenderAddressType; import co.rsk.peg.btcLockSender.BtcLockSenderProvider; import co.rsk.peg.federation.*; @@ -45,6 +42,8 @@ import co.rsk.peg.feeperkb.FeePerKbSupport; import co.rsk.peg.flyover.FlyoverFederationInformation; import co.rsk.peg.flyover.FlyoverTxResponseCodes; +import co.rsk.peg.lockingcap.LockingCapIllegalArgumentException; +import co.rsk.peg.lockingcap.LockingCapSupport; import co.rsk.peg.pegin.*; import co.rsk.peg.pegininstructions.PeginInstructionsException; import co.rsk.peg.pegininstructions.PeginInstructionsProvider; @@ -70,9 +69,7 @@ import org.ethereum.vm.DataWord; import org.ethereum.vm.PrecompiledContracts; import org.ethereum.vm.exception.VMException; -import org.ethereum.vm.program.InternalTransaction; -import org.ethereum.vm.program.Program; -import org.ethereum.vm.program.ProgramResult; +import org.ethereum.vm.program.*; import org.ethereum.vm.program.invoke.TransferInvoke; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,6 +113,7 @@ public class BridgeSupport { private final FeePerKbSupport feePerKbSupport; private final WhitelistSupport whitelistSupport; private final FederationSupport federationSupport; + private final LockingCapSupport lockingCapSupport; private final Context btcContext; private final BtcBlockStoreWithCache.Factory btcBlockStoreFactory; @@ -138,6 +136,7 @@ public BridgeSupport( FeePerKbSupport feePerKbSupport, WhitelistSupport whitelistSupport, FederationSupport federationSupport, + LockingCapSupport lockingCapSupport, BtcBlockStoreWithCache.Factory btcBlockStoreFactory, ActivationConfig.ForBlock activations, SignatureCache signatureCache) { @@ -152,6 +151,7 @@ public BridgeSupport( this.feePerKbSupport = feePerKbSupport; this.whitelistSupport = whitelistSupport; this.federationSupport = federationSupport; + this.lockingCapSupport = lockingCapSupport; this.btcBlockStoreFactory = btcBlockStoreFactory; this.activations = activations; this.signatureCache = signatureCache; @@ -173,11 +173,12 @@ InputStream getCheckPoints() { return checkpoints; } - public void save() throws IOException { + public void save() { provider.save(); feePerKbSupport.save(); whitelistSupport.save(); federationSupport.save(); + lockingCapSupport.save(); } /** @@ -271,10 +272,9 @@ private boolean cannotProcessNextBlock(StoredBlock previousBlock) { * Get the wallet for the currently active federation * @return A BTC wallet for the currently active federation * - * @throws IOException * @param shouldConsiderFlyoverUTXOs */ - public Wallet getActiveFederationWallet(boolean shouldConsiderFlyoverUTXOs) throws IOException { + public Wallet getActiveFederationWallet(boolean shouldConsiderFlyoverUTXOs) { Federation federation = getActiveFederation(); List utxos = federationSupport.getActiveFederationBtcUTXOs(); @@ -292,15 +292,14 @@ public Wallet getActiveFederationWallet(boolean shouldConsiderFlyoverUTXOs) thro * or null if there's currently no retiring federation * @return A BTC wallet for the currently active federation * - * @throws IOException * @param shouldConsiderFlyoverUTXOs */ - protected Wallet getRetiringFederationWallet(boolean shouldConsiderFlyoverUTXOs) throws IOException { + protected Wallet getRetiringFederationWallet(boolean shouldConsiderFlyoverUTXOs) { List retiringFederationBtcUTXOs = federationSupport.getRetiringFederationBtcUTXOs(); return getRetiringFederationWallet(shouldConsiderFlyoverUTXOs, retiringFederationBtcUTXOs.size()); } - private Wallet getRetiringFederationWallet(boolean shouldConsiderFlyoverUTXOs, int utxosSizeLimit) throws IOException { + private Wallet getRetiringFederationWallet(boolean shouldConsiderFlyoverUTXOs, int utxosSizeLimit) { Federation federation = getRetiringFederation(); if (federation == null) { logger.debug("[getRetiringFederationWallet] No retiring federation found"); @@ -633,7 +632,7 @@ private void processPegInVersion1( } } - private void executePegIn(BtcTransaction btcTx, PeginInformation peginInformation, Coin amount) throws IOException { + private void executePegIn(BtcTransaction btcTx, PeginInformation peginInformation, Coin amount) { RskAddress rskDestinationAddress = peginInformation.getRskDestinationAddress(); Address senderBtcAddress = peginInformation.getSenderBtcAddress(); TxSenderAddressType senderBtcAddressType = peginInformation.getSenderBtcAddressType(); @@ -759,7 +758,7 @@ private void transferTo(RskAddress receiver, co.rsk.core.Coin amount) { /* Add the btcTx outputs that send btc to the federation(s) to the UTXO list */ - private void saveNewUTXOs(BtcTransaction btcTx) throws IOException { + private void saveNewUTXOs(BtcTransaction btcTx) { // Outputs to the active federation Wallet activeFederationWallet = getActiveFederationWallet(false); List outputsToTheActiveFederation = btcTx.getWalletOutputs( @@ -972,9 +971,11 @@ private void processFundsMigration(Transaction rskTx) throws IOException { long federationAge = rskExecutionBlock.getNumber() - activeFederation.getCreationBlockNumber(); logger.trace("[processFundsMigration] Active federation (age={}) is in migration age.", federationAge); if (hasMinimumFundsToMigrate(retiringFederationWallet)){ + Coin retiringFederationBalance = retiringFederationWallet.getBalance(); + String retiringFederationBalanceInFriendlyFormat = retiringFederationBalance.toFriendlyString(); logger.info( "[processFundsMigration] Retiring federation has funds to migrate: {}.", - retiringFederationWallet.getBalance().toFriendlyString() + retiringFederationBalanceInFriendlyFormat ); migrateFunds( @@ -988,9 +989,11 @@ private void processFundsMigration(Transaction rskTx) throws IOException { if (retiringFederationWallet != null && federationIsPastMigrationAge(activeFederation)) { if (retiringFederationWallet.getBalance().isGreaterThan(Coin.ZERO)) { + Coin retiringFederationBalance = retiringFederationWallet.getBalance(); + String retiringFederationBalanceInFriendlyFormat = retiringFederationBalance.toFriendlyString(); logger.info( "[processFundsMigration] Federation is past migration age and will try to migrate remaining balance: {}.", - retiringFederationWallet.getBalance().toFriendlyString() + retiringFederationBalanceInFriendlyFormat ); try { @@ -2025,7 +2028,7 @@ private List getLiveFederations() { return liveFederations; } - public Integer voteFederationChange(Transaction tx, ABICallSpec callSpec) throws BridgeIllegalArgumentException { + public Integer voteFederationChange(Transaction tx, ABICallSpec callSpec) { return federationSupport.voteFederationChange(tx, callSpec, signatureCache, eventLogger); } @@ -2103,14 +2106,7 @@ public Integer setLockWhitelistDisableBlockDelay(Transaction tx, BigInteger disa } public Coin getLockingCap() { - // Before returning the locking cap, check if it was already set - if (activations.isActive(ConsensusRule.RSKIP134) && this.provider.getLockingCap() == null) { - // Set the initial locking cap value - logger.debug("Setting initial locking cap value"); - this.provider.setLockingCap(bridgeConstants.getInitialLockingCap()); - } - - return this.provider.getLockingCap(); + return lockingCapSupport.getLockingCap().orElse(null); } /** @@ -2122,29 +2118,8 @@ public Optional