Skip to content

Commit

Permalink
Add test case for registering a normal pegout when svp is ongoing. Re…
Browse files Browse the repository at this point in the history
…factor
  • Loading branch information
julia-zack committed Sep 10, 2024
1 parent e5cce24 commit 2f80201
Showing 1 changed file with 109 additions and 39 deletions.
148 changes: 109 additions & 39 deletions rskj-core/src/test/java/co/rsk/peg/BridgeSupportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,12 @@ class BridgeSupportTest {
private Block rskExecutionBlock;
private List<LogInfo> logs;

private Repository repository;
private BridgeStorageProvider bridgeStorageProvider;
private BridgeSupportBuilder bridgeSupportBuilder;
private BridgeSupport bridgeSupport;
private BtcBlockStoreWithCache.Factory btcBlockStoreFactory;
private BtcBlockStoreWithCache btcBlockStoreWithCache;

private WhitelistStorageProvider whitelistStorageProvider;
private WhitelistSupport whitelistSupport;
Expand Down Expand Up @@ -140,7 +143,7 @@ void setUpOnEachTest() {
activationsAfterForks = ActivationConfigsForTest.all().forBlock(0);
signatureCache = new BlockTxSignatureCache(new ReceivedTxSignatureCache());

Repository repository = createRepository();
repository = createRepository();
bridgeStorageProvider = new BridgeStorageProvider(
repository,
contractAddress,
Expand Down Expand Up @@ -587,6 +590,9 @@ void setUp() {
.build();
rskExecutionBlock = Block.createBlockFromHeader(blockHeader, true);

btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(btcMainnetParams, 100, 100);
btcBlockStoreWithCache = btcBlockStoreFactory.newInstance(repository, bridgeMainNetConstants, bridgeStorageProvider, activationsAfterForks);

activeFederation = FederationTestUtils.getErpFederation(federationConstantsMainnet.getBtcParams());
List<UTXO> activeFederationUTXOs = BitcoinTestUtils.createUTXOs(10, activeFederation.getAddress());
proposedFederation = new P2shErpFederationBuilder().build();
Expand Down Expand Up @@ -740,29 +746,43 @@ private Optional<TransactionOutput> searchForOutput(List<TransactionOutput> tran
}

@Test
void registerBtcTransaction_whenProposedFederationDoesNotExist_shouldRegisterTransactionButNotSaveSvpFundTransactionValues() throws Exception {
void registerBtcTransaction_forSvpFundTransaction_whenProposedFederationDoesNotExist_shouldRegisterTransactionButNotUpdateSvpFundTransactionValues() throws Exception {
// arrange
processAndSaveSvpFundTransactionUnsigned();
BtcTransaction svpFundTransaction = getSvpFundTransactionFromPegoutsMap(bridgeStorageProvider.getPegoutsWaitingForConfirmations());
randomSignTransactionInputs(svpFundTransaction, activeFederation.getNumberOfSignaturesRequired());
// recreate a valid chain for bridgeSupport so the tx passes the previous checks in registerBtcTransaction

// recreate a valid chain that has the tx, so it passes the previous checks in registerBtcTransaction
PartialMerkleTree pmtWithTransactions = createValidPmtWithTransactions(Collections.singletonList(svpFundTransaction.getHash()), btcMainnetParams);
int btcBlockHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
bridgeSupport = getBridgeSupportWithValidChainThatHasTransactionAtHeight(pmtWithTransactions, btcBlockHeight);
int btcBlockWithPmtHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
int chainHeight = btcBlockWithPmtHeight + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations();
recreateChainAtHeightWithStoredBlockWithPmtAtHeight(btcBlockStoreWithCache, chainHeight, pmtWithTransactions, btcBlockWithPmtHeight, btcMainnetParams);
bridgeStorageProvider.save();
// recreate bridge support to have this chain
bridgeSupport = bridgeSupportBuilder
.withBridgeConstants(bridgeMainNetConstants)
.withProvider(bridgeStorageProvider)
.withActivations(activationsAfterForks)
.withFederationSupport(federationSupport)
.withFeePerKbSupport(feePerKbSupport)
.withExecutionBlock(rskExecutionBlock)
.withBtcBlockStoreFactory(btcBlockStoreFactory)
.withRepository(repository)
.build();

when(federationSupport.getProposedFederation()).thenReturn(Optional.empty()); // this implies svp should be considered ended

// act
int activeFederationUtxosSizeBeforeRegisteringTx = federationSupport.getActiveFederationBtcUTXOs().size();
bridgeSupport.registerBtcTransaction(rskTx, svpFundTransaction.bitcoinSerialize(), btcBlockHeight, pmtWithTransactions.bitcoinSerialize());
bridgeSupport.registerBtcTransaction(rskTx, svpFundTransaction.bitcoinSerialize(), btcBlockWithPmtHeight, pmtWithTransactions.bitcoinSerialize());
bridgeStorageProvider.save();

// assert
assertTransactionWasRegisteredButSignedHashWasNotSavedAndUnsignedHashWasNotCleared(activeFederationUtxosSizeBeforeRegisteringTx);
}

@Test
void registerBtcTransaction_whenValidationPeriodEnded_shouldRegisterSvpFundTransactionButNotSaveSignedHash() throws Exception {
void registerBtcTransaction_forSvpFundTransaction_whenValidationPeriodEnded_shouldRegisterTransactionButNotUpdateSvpFundTransactionValues() throws Exception {
// arrange
// make rsk execution block to be after validation period ended
long validationPeriodEndBlock = proposedFederation.getCreationBlockNumber()
Expand All @@ -777,14 +797,73 @@ void registerBtcTransaction_whenValidationPeriodEnded_shouldRegisterSvpFundTrans
processAndSaveSvpFundTransactionUnsigned();
BtcTransaction svpFundTransaction = getSvpFundTransactionFromPegoutsMap(bridgeStorageProvider.getPegoutsWaitingForConfirmations());
randomSignTransactionInputs(svpFundTransaction, activeFederation.getNumberOfSignaturesRequired());
// recreate a valid chain for bridgeSupport so the tx passes the previous checks in registerBtcTransaction

// recreate a valid chain that has the tx, so it passes the previous checks in registerBtcTransaction
PartialMerkleTree pmtWithTransactions = createValidPmtWithTransactions(Collections.singletonList(svpFundTransaction.getHash()), btcMainnetParams);
int btcBlockHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
bridgeSupport = getBridgeSupportWithValidChainThatHasTransactionAtHeight(pmtWithTransactions, btcBlockHeight);
int btcBlockWithPmtHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
int chainHeight = btcBlockWithPmtHeight + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations();
recreateChainAtHeightWithStoredBlockWithPmtAtHeight(btcBlockStoreWithCache, chainHeight, pmtWithTransactions, btcBlockWithPmtHeight, btcMainnetParams);
bridgeStorageProvider.save();
// recreate bridge support to have this chain
bridgeSupport = bridgeSupportBuilder
.withBridgeConstants(bridgeMainNetConstants)
.withProvider(bridgeStorageProvider)
.withActivations(activationsAfterForks)
.withFederationSupport(federationSupport)
.withFeePerKbSupport(feePerKbSupport)
.withExecutionBlock(rskExecutionBlock)
.withBtcBlockStoreFactory(btcBlockStoreFactory)
.withRepository(repository)
.build();

// Act
int activeFederationUtxosSizeBeforeRegisteringTx = federationSupport.getActiveFederationBtcUTXOs().size();
bridgeSupport.registerBtcTransaction(rskTx, svpFundTransaction.bitcoinSerialize(), btcBlockWithPmtHeight, pmtWithTransactions.bitcoinSerialize());
bridgeStorageProvider.save();

// assert
assertTransactionWasRegisteredButSignedHashWasNotSavedAndUnsignedHashWasNotCleared(activeFederationUtxosSizeBeforeRegisteringTx);
}

@Test
void registerBtcTransaction_forNormalPegout_whenSvpPeriodIsOngoing_shouldRegisterTransactionButNotUpdateSvpFundTransactionValues() throws Exception {
// Arrange
processAndSaveSvpFundTransactionUnsigned();

BtcTransaction pegoutTransaction = new BtcTransaction(btcMainnetParams);
// add random input. Just using a federation because it is easier to build.
Federation standardMultisigFederation = new StandardMultiSigFederationBuilder().build();
Script standardMultisigP2SHScript = standardMultisigFederation.getP2SHScript();
pegoutTransaction.addInput(BitcoinTestUtils.createHash(1), 0, standardMultisigP2SHScript.createEmptyInputScript(null, standardMultisigFederation.getRedeemScript()));
randomSignTransactionInputs(pegoutTransaction, activeFederation.getNumberOfSignaturesRequired());
// add output to the active fed
Script activeFederationP2SHScript = activeFederation.getP2SHScript();
pegoutTransaction.addOutput(Coin.COIN.multiply(10), activeFederationP2SHScript);
// save sigHash in pegout index
Optional<Sha256Hash> inputSigHash = BitcoinUtils.getFirstInputSigHash(pegoutTransaction);
bridgeStorageProvider.setPegoutTxSigHash(inputSigHash.get());

// recreate a valid chain that has the tx, so it passes the previous checks in registerBtcTransaction
PartialMerkleTree pmtWithTransactions = createValidPmtWithTransactions(Collections.singletonList(pegoutTransaction.getHash()), btcMainnetParams);
int btcBlockWithPmtHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
int chainHeight = btcBlockWithPmtHeight + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations();
recreateChainAtHeightWithStoredBlockWithPmtAtHeight(btcBlockStoreWithCache, chainHeight, pmtWithTransactions, btcBlockWithPmtHeight, btcMainnetParams);
bridgeStorageProvider.save();
// recreate bridge support to have this chain
bridgeSupport = bridgeSupportBuilder
.withBridgeConstants(bridgeMainNetConstants)
.withProvider(bridgeStorageProvider)
.withActivations(activationsAfterForks)
.withFederationSupport(federationSupport)
.withFeePerKbSupport(feePerKbSupport)
.withExecutionBlock(rskExecutionBlock)
.withBtcBlockStoreFactory(btcBlockStoreFactory)
.withRepository(repository)
.build();

// Act
int activeFederationUtxosSizeBeforeRegisteringTx = federationSupport.getActiveFederationBtcUTXOs().size();
bridgeSupport.registerBtcTransaction(rskTx, svpFundTransaction.bitcoinSerialize(), btcBlockHeight, pmtWithTransactions.bitcoinSerialize());
bridgeSupport.registerBtcTransaction(rskTx, pegoutTransaction.bitcoinSerialize(), btcBlockWithPmtHeight, pmtWithTransactions.bitcoinSerialize());
bridgeStorageProvider.save();

// assert
Expand All @@ -798,19 +877,33 @@ private void assertTransactionWasRegisteredButSignedHashWasNotSavedAndUnsignedHa
}

@Test
void registerBtcTransaction_whenSvpPeriodIsOngoing_shouldRegisterSvpFundTransactionAndSaveTxHashSignedAndClearTxHashUnsigned() throws Exception {
void registerBtcTransaction_forSvpFundTransaction_whenSvpPeriodIsOngoing_shouldRegisterTransactionAndUpdateSvpFundTransactionValues() throws Exception {
// Arrange
processAndSaveSvpFundTransactionUnsigned();
BtcTransaction svpFundTransaction = getSvpFundTransactionFromPegoutsMap(bridgeStorageProvider.getPegoutsWaitingForConfirmations());
randomSignTransactionInputs(svpFundTransaction, activeFederation.getNumberOfSignaturesRequired());
// recreate a valid chain for bridgeSupport so the tx passes the previous checks in registerBtcTransaction

// recreate a valid chain that has the tx, so it passes the previous checks in registerBtcTransaction
PartialMerkleTree pmtWithTransactions = createValidPmtWithTransactions(Collections.singletonList(svpFundTransaction.getHash()), btcMainnetParams);
int btcBlockHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
bridgeSupport = getBridgeSupportWithValidChainThatHasTransactionAtHeight(pmtWithTransactions, btcBlockHeight);
int btcBlockWithPmtHeight = bridgeMainNetConstants.getBtcHeightWhenPegoutTxIndexActivates() + bridgeMainNetConstants.getPegoutTxIndexGracePeriodInBtcBlocks(); // we want pegout tx index to be activated
int chainHeight = btcBlockWithPmtHeight + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations();
recreateChainAtHeightWithStoredBlockWithPmtAtHeight(btcBlockStoreWithCache, chainHeight, pmtWithTransactions, btcBlockWithPmtHeight, btcMainnetParams);
bridgeStorageProvider.save();
// recreate bridge support to have this chain
bridgeSupport = bridgeSupportBuilder
.withBridgeConstants(bridgeMainNetConstants)
.withProvider(bridgeStorageProvider)
.withActivations(activationsAfterForks)
.withFederationSupport(federationSupport)
.withFeePerKbSupport(feePerKbSupport)
.withExecutionBlock(rskExecutionBlock)
.withBtcBlockStoreFactory(btcBlockStoreFactory)
.withRepository(repository)
.build();

// Act
int activeFederationUtxosSizeBeforeRegisteringTx = federationSupport.getActiveFederationBtcUTXOs().size();
bridgeSupport.registerBtcTransaction(rskTx, svpFundTransaction.bitcoinSerialize(), btcBlockHeight, pmtWithTransactions.bitcoinSerialize());
bridgeSupport.registerBtcTransaction(rskTx, svpFundTransaction.bitcoinSerialize(), btcBlockWithPmtHeight, pmtWithTransactions.bitcoinSerialize());
bridgeStorageProvider.save();

// Assert
Expand Down Expand Up @@ -899,29 +992,6 @@ private void assertEventWasEmittedWithExpectedData(byte[] expectedData) {
assertTrue(data.isPresent());
}

private BridgeSupport getBridgeSupportWithValidChainThatHasTransactionAtHeight(PartialMerkleTree pmtWithTransaction, int btcBlockHeight) throws BlockStoreException {
// recreate chain so the transaction can be registered
Repository repository = createRepository();
BtcBlockStoreWithCache.Factory btcBlockStoreFactory = new RepositoryBtcBlockStoreWithCache.Factory(btcMainnetParams, 100, 100);
BtcBlockStoreWithCache btcBlockStoreWithCache = btcBlockStoreFactory.newInstance(repository, bridgeMainNetConstants, bridgeStorageProvider, activationsAfterForks);
bridgeSupport = bridgeSupportBuilder
.withBridgeConstants(bridgeMainNetConstants)
.withProvider(bridgeStorageProvider)
.withActivations(activationsAfterForks)
.withFederationSupport(federationSupport)
.withFeePerKbSupport(feePerKbSupport)
.withExecutionBlock(rskExecutionBlock)
.withBtcBlockStoreFactory(btcBlockStoreFactory)
.withRepository(repository)
.build();

BtcBlock btcBlockWithPmt = createBtcBlockWithPmt(pmtWithTransaction, btcMainnetParams);
recreateValidChainWithBlockStoredAtHeight(btcBlockWithPmt, btcBlockStoreWithCache, btcBlockHeight, btcBlockHeight + bridgeMainNetConstants.getBtc2RskMinimumAcceptableConfirmations(), btcMainnetParams);
bridgeStorageProvider.save();

return bridgeSupport;
}

private void randomSignTransactionInputs(BtcTransaction transaction, int amountOfSignatures) {
List<BtcECKey> keysToSign = new ArrayList<>();
for (int i = 0; i < amountOfSignatures; i++) {
Expand Down

0 comments on commit 2f80201

Please sign in to comment.