From c7fa0764559021b088c850276093032311a80d59 Mon Sep 17 00:00:00 2001 From: Julian Len Date: Fri, 13 Dec 2024 12:57:22 -0300 Subject: [PATCH] added a test when a tx is already processed do not modify the state --- .../co/rsk/peg/RegisterBtcTransactionIT.java | 100 ++++++++++++------ 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/rskj-core/src/test/java/co/rsk/peg/RegisterBtcTransactionIT.java b/rskj-core/src/test/java/co/rsk/peg/RegisterBtcTransactionIT.java index df7ebb9bdb..b5db6bbfb9 100644 --- a/rskj-core/src/test/java/co/rsk/peg/RegisterBtcTransactionIT.java +++ b/rskj-core/src/test/java/co/rsk/peg/RegisterBtcTransactionIT.java @@ -26,7 +26,9 @@ import org.ethereum.config.blockchain.upgrades.ActivationConfig; import org.ethereum.config.blockchain.upgrades.ActivationConfigsForTest; import org.ethereum.core.*; +import org.ethereum.crypto.ECKey; import org.ethereum.vm.PrecompiledContracts; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.*; @@ -36,66 +38,102 @@ public class RegisterBtcTransactionIT { private final BridgeConstants bridgeConstants = BridgeMainNetConstants.getInstance(); private final NetworkParameters btcParams = bridgeConstants.getBtcParams(); private final BridgeSupportBuilder bridgeSupportBuilder = BridgeSupportBuilder.builder(); + private Repository track; + private Repository repository; + private Block rskExecutionBlock; + private FederationSupport federationSupport; + private BridgeStorageProvider bridgeStorageProvider; + private BtcTransaction bitcoinTransaction; + private PartialMerkleTree pmtWithTransactions; + private int btcBlockWithPmtHeight; + private Transaction rskTx; + private ECKey ecKey; + private RskAddress rskReceiver; + private BridgeSupport bridgeSupport; + private BridgeEventLoggerImpl bridgeEventLogger; + private Coin btcTransferred; + + @BeforeEach + void setUp() throws Exception{ + rskTx = TransactionUtils.createTransaction(); + repository = BridgeSupportTestUtil.createRepository(); + track = repository.startTracking(); - @Test - void whenRegisterALegacyBtcTransaction_shouldRegisterTheNewUtxoAndTransferTheRbtcBalance() throws Exception { - // Arrange ActivationConfig.ForBlock activations = ActivationConfigsForTest.all().forBlock(0); - Repository repository = BridgeSupportTestUtil.createRepository(); - Repository track = repository.startTracking(); - Block rskExecutionBlock = getRskExecutionBlock(); + rskExecutionBlock = getRskExecutionBlock(); BtcLockSenderProvider btcLockSenderProvider = new BtcLockSenderProvider(); FeePerKbSupport feePerKbSupport = getFeePerKbSupport(repository, bridgeConstants); Federation federation = P2shErpFederationBuilder.builder().build(); FederationStorageProvider federationStorageProvider = getFederationStorageProvider(track, federation); - FederationSupport federationSupport = getFederationSupport(federationStorageProvider, activations, bridgeConstants.getFederationConstants()); - - BtcECKey btcPublicKey = BitcoinTestUtils.getBtcEcKeyFromSeed("seed"); - Coin btcTransferred = bridgeConstants.getMinimumPeginTxValue(activations); - BtcTransaction bitcoinTransaction = createPegInTransaction(federationSupport.getActiveFederation().getAddress(), btcTransferred, btcPublicKey); - TransactionOutput output = bitcoinTransaction.getOutput(0); - List expectedFederationUtxos = Collections.singletonList(getUtxo(bitcoinTransaction, output)); + federationSupport = getFederationSupport(federationStorageProvider, activations, bridgeConstants.getFederationConstants()); - BridgeStorageProvider bridgeStorageProvider = new BridgeStorageProvider(track, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants.getBtcParams(), activations); + bridgeStorageProvider = new BridgeStorageProvider(track, PrecompiledContracts.BRIDGE_ADDR, bridgeConstants.getBtcParams(), activations); BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(bridgeConstants.getBtcParams(), 100, 100); BtcBlockStoreWithCache btcBlockStoreWithCache = btcBlockStoreFactory.newInstance(track, bridgeConstants, bridgeStorageProvider, activations); - PartialMerkleTree pmtWithTransactions = createValidPmtForTransactions(Collections.singletonList(bitcoinTransaction.getHash()), bridgeConstants.getBtcParams()); - int btcBlockWithPmtHeight = bridgeConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); + BtcECKey btcPublicKey = BitcoinTestUtils.getBtcEcKeyFromSeed("seed"); + ecKey = ECKey.fromPublicOnly(btcPublicKey.getPubKey()); + rskReceiver = new RskAddress(ecKey.getAddress()); + btcTransferred = bridgeConstants.getMinimumPeginTxValue(activations); + bitcoinTransaction = createPegInTransaction(federationSupport.getActiveFederation().getAddress(), btcTransferred, btcPublicKey); + + pmtWithTransactions = createValidPmtForTransactions(Collections.singletonList(bitcoinTransaction.getHash()), bridgeConstants.getBtcParams()); + btcBlockWithPmtHeight = bridgeConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); int chainHeight = btcBlockWithPmtHeight + bridgeConstants.getBtc2RskMinimumAcceptableConfirmations(); - BridgeEventLoggerImpl bridgeEventLogger = spy(new BridgeEventLoggerImpl(bridgeConstants, activations, new ArrayList<>())); + bridgeEventLogger = spy(new BridgeEventLoggerImpl(bridgeConstants, activations, new ArrayList<>())); recreateChainFromPmt(btcBlockStoreWithCache, chainHeight, pmtWithTransactions, btcBlockWithPmtHeight, bridgeConstants.getBtcParams()); - bridgeStorageProvider.save(); + bridgeSupport = getBridgeSupport(bridgeEventLogger, bridgeStorageProvider, activations, federationSupport, feePerKbSupport, rskExecutionBlock, btcBlockStoreFactory, track, btcLockSenderProvider); + } - BridgeSupport bridgeSupport = getBridgeSupport(bridgeEventLogger, bridgeStorageProvider, activations, federationSupport, feePerKbSupport, rskExecutionBlock, btcBlockStoreFactory, track, btcLockSenderProvider); - - Transaction rskTx = TransactionUtils.createTransaction(); - org.ethereum.crypto.ECKey key = org.ethereum.crypto.ECKey.fromPublicOnly(btcPublicKey.getPubKey()); + @Test + void whenRegisterALegacyBtcTransaction_shouldRegisterTheNewUtxoAndTransferTheRbtcBalance() throws Exception { + // Arrange + TransactionOutput output = bitcoinTransaction.getOutput(0); + List expectedFederationUtxos = Collections.singletonList(getUtxo(bitcoinTransaction, output)); - RskAddress receiver = new RskAddress(key.getAddress()); - co.rsk.core.Coin receiverBalance = track.getBalance(receiver); + co.rsk.core.Coin receiverBalance = track.getBalance(rskReceiver); co.rsk.core.Coin expectedReceiverBalance = receiverBalance.add(co.rsk.core.Coin.fromBitcoin(btcTransferred)); // Act - bridgeSupport.registerBtcTransaction(rskTx, bitcoinTransaction.bitcoinSerialize(), btcBlockWithPmtHeight, pmtWithTransactions.bitcoinSerialize()); - - bridgeSupport.save(); - track.commit(); + registerBtcTransactionAndCommit(); // Assert Optional heightIfBtcTxHashIsAlreadyProcessed = bridgeStorageProvider.getHeightIfBtcTxhashIsAlreadyProcessed(bitcoinTransaction.getHash()); - assertTrue(heightIfBtcTxHashIsAlreadyProcessed.isPresent()); assertEquals(rskExecutionBlock.getNumber(), heightIfBtcTxHashIsAlreadyProcessed.get()); assertEquals(expectedFederationUtxos, federationSupport.getActiveFederationBtcUTXOs()); - assertEquals(expectedReceiverBalance, repository.getBalance(receiver)); + assertEquals(expectedReceiverBalance, repository.getBalance(rskReceiver)); + + verify(bridgeEventLogger, times(1)).logPeginBtc(rskReceiver, bitcoinTransaction, btcTransferred, 0); + + } + + @Test + void whenRegisterARepeatedLegacyBtcTransaction_shouldNotPerformAnyChange() throws Exception { + // Arrange + registerBtcTransactionAndCommit(); - verify(bridgeEventLogger, times(1)).logPeginBtc(receiver, bitcoinTransaction, btcTransferred, 0); + RskAddress receiverBalance = new RskAddress(ecKey.getAddress()); + co.rsk.core.Coin expectedReceiverBalance = track.getBalance(receiverBalance); + List expectedFederationUTXOs = federationSupport.getActiveFederationBtcUTXOs(); + + // Act + registerBtcTransactionAndCommit(); + + // Assert + assertEquals(expectedFederationUTXOs, federationSupport.getActiveFederationBtcUTXOs()); + assertEquals(expectedReceiverBalance, repository.getBalance(receiverBalance)); + } + + private void registerBtcTransactionAndCommit() throws Exception { + bridgeSupport.registerBtcTransaction(rskTx, bitcoinTransaction.bitcoinSerialize(), btcBlockWithPmtHeight, pmtWithTransactions.bitcoinSerialize()); + bridgeSupport.save(); + track.commit(); } private static UTXO getUtxo(BtcTransaction bitcoinTransaction, TransactionOutput output) {