Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change updateBridgeBtcTransactions in order to skip bech32 transactions #256

Draft
wants to merge 1 commit into
base: improvements-integration
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/main/java/co/rsk/federate/BtcToRskClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -571,14 +571,15 @@ protected void updateBridgeBtcTransactions() {
btcTx.getHash()
);
logger.warn("[updateBridgeBtcTransactions] {}", message);
// If tx sender could be retrieved then let the Bridge process the tx and refund the sender
if (peginInformation.getSenderBtcAddress() != null) {
logger.warn("[updateBridgeBtcTransactions] Funds will be refunded to sender.");
} else {
// Remove the tx from the set to be sent to the Bridge since it's not processable
txsToSendToRskHashes.remove(txHash);
continue;
}
}

// If tx sender could be retrieved then let the Bridge process the tx and refund the sender
if (canSenderBeRetrieved(peginInformation)) {
logger.warn("[updateBridgeBtcTransactions] Funds will be refunded to sender.");
} else {
// Remove the tx from the set to be sent to the Bridge since it's not processable
txsToSendToRskHashes.remove(txHash);
continue;
}

// Check if the tx can be processed by the Bridge
Expand Down Expand Up @@ -668,6 +669,10 @@ protected void updateBridgeBtcTransactions() {
}
}

private static boolean canSenderBeRetrieved(PeginInformation peginInformation) {
return !(peginInformation.getSenderBtcAddress() == null && peginInformation.getSenderBtcAddressType() == TxSenderAddressType.UNKNOWN);
}

/**
* Gets the first ready to be informed coinbase transaction and informs it
*/
Expand Down
95 changes: 89 additions & 6 deletions src/test/java/co/rsk/federate/BtcToRskClientTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package co.rsk.federate;

import static org.bitcoinj.core.Coin.COIN;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -38,7 +39,6 @@
import co.rsk.federate.mock.SimpleBtcTransaction;
import co.rsk.federate.mock.SimpleFederatorSupport;
import co.rsk.net.NodeBlockProcessor;
import co.rsk.peg.BridgeUtils;
import co.rsk.peg.PegUtilsLegacy;
import co.rsk.peg.federation.Federation;
import co.rsk.peg.federation.FederationMember;
Expand Down Expand Up @@ -1932,7 +1932,7 @@ void updateTransactionWithSenderUnknown_after_rskip170() throws Exception {
federatorSupport.getTxsSentToRegisterBtcTransaction();

assertNotNull(txsSentToRegisterBtcTransaction);
assertFalse(txsSentToRegisterBtcTransaction.isEmpty());
assertTrue(txsSentToRegisterBtcTransaction.isEmpty());
}

@Test
Expand Down Expand Up @@ -2486,6 +2486,78 @@ void updateBridgeBtcTransactions_tx_with_witness_already_informed() throws Excep
verify(federatorSupport, never()).sendRegisterBtcTransaction(any(Transaction.class), anyInt(), any(PartialMerkleTree.class));
}

@Test
void updateBridgeBtcTransactions_bech32_sender_should_not_be_sent() throws Exception {
ActivationConfig activationConfig = mock(ActivationConfig.class);
ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class);
when(activations.isActive(ConsensusRule.RSKIP170)).thenReturn(true);
when(activations.isActive(ConsensusRule.RSKIP379)).thenReturn(true);
when(activationConfig.forBlock(anyLong())).thenReturn(activations);

NodeBlockProcessor nodeBlockProcessor = mock(NodeBlockProcessor.class);
when(nodeBlockProcessor.hasBetterBlockToSync()).thenReturn(false);

SimpleBtcTransaction fundingTx = new SimpleBtcTransaction(networkParameters, createHash(), createHash(), false);

int outputIndex = 0;
fundingTx.addInput(createHash(), outputIndex, new Script(new byte[]{}));
fundingTx.addOutput(createBech32Output(networkParameters, COIN));

SimpleBtcTransaction bech32PeginTx = new SimpleBtcTransaction(networkParameters, createHash(), createHash(), false);
bech32PeginTx.addInput(fundingTx.getOutput(outputIndex));
bech32PeginTx.addOutput(COIN.div(2), Address.fromString(networkParameters, genesisFederation.getAddress().toBase58()));

FederatorSupport federatorSupport = mock(FederatorSupport.class);
when(federatorSupport.getBtcBestBlockChainHeight()).thenReturn(1);
when(federatorSupport.isBtcTxHashAlreadyProcessed(bech32PeginTx.getTxId())).thenReturn(false);
when(federatorSupport.getBtcTxHashProcessedHeight(bech32PeginTx.getTxId())).thenReturn(-1L);
when(federatorSupport.getFederationMember()).thenReturn(fakeMember);

BtcToRskClient btcToRskClient = new BtcToRskClient.Factory(federatorSupport, nodeBlockProcessor).build();

BitcoinWrapper bitcoinWrapper = mock(BitcoinWrapper.class);

Map<Sha256Hash, Transaction> txsInWallet = new HashMap<>();
txsInWallet.put(bech32PeginTx.getWTxId(), bech32PeginTx);
when(
bitcoinWrapper.getTransactionMap(
bridgeRegTestConstants.getBtc2RskMinimumAcceptableConfirmations()
)
).thenReturn(txsInWallet);

BtcToRskClientFileStorage btcToRskClientFileStorageMock = mock(BtcToRskClientFileStorage.class);
BtcToRskClientFileData btcToRskClientFileData = mock(BtcToRskClientFileData.class);
when(btcToRskClientFileStorageMock.read(any())).thenReturn(new BtcToRskClientFileReadResult(true, btcToRskClientFileData));

HashMap<Sha256Hash, List<Proof>> transactionProofs = new HashMap<>();
when(btcToRskClientFileData.getTransactionProofs()).thenReturn(transactionProofs);

List<Proof> proofs = new ArrayList<>();
Proof proof = mock(Proof.class);
proofs.add(proof);
btcToRskClientFileData.getTransactionProofs().put(bech32PeginTx.getWTxId(), proofs);

BtcLockSenderProvider btcLockSender = new BtcLockSenderProvider();
PeginInstructionsProvider peginInstructionsProvider = new PeginInstructionsProvider();

btcToRskClient.setup(
activationConfig,
bitcoinWrapper,
bridgeRegTestConstants,
btcToRskClientFileStorageMock,
btcLockSender,
peginInstructionsProvider,
false,
100
);
btcToRskClient.start(genesisFederation);
btcToRskClient.updateBridgeBtcTransactions();

assertTrue(transactionProofs.isEmpty());
verify(federatorSupport, never()).isBtcTxHashAlreadyProcessed(bech32PeginTx.getTxId());
verify(federatorSupport, never()).sendRegisterBtcTransaction(any(Transaction.class), anyInt(), any(PartialMerkleTree.class));
}

private static co.rsk.bitcoinj.script.Script createBaseInputScriptThatSpendsFromTheFederation(Federation federation) {
co.rsk.bitcoinj.script.Script scriptPubKey = federation.getP2SHScript();

Expand Down Expand Up @@ -2558,19 +2630,30 @@ private Block createBlock(Sha256Hash blockHash, Transaction... txs) {
private Transaction createTransaction() {
Transaction tx = new SimpleBtcTransaction(networkParameters, createHash(), createHash(), false);
tx.addInput(Sha256Hash.ZERO_HASH, 0, org.bitcoinj.script.ScriptBuilder.createInputScript(null, new ECKey()));
tx.addOutput(Coin.COIN, Address.fromString(networkParameters, genesisFederation.getAddress().toBase58()));
tx.addOutput(COIN, Address.fromString(networkParameters, genesisFederation.getAddress().toBase58()));

return tx;
}

private Transaction createSegwitTransaction() {
Transaction tx = new SimpleBtcTransaction(networkParameters, createHash(), createHash(), true);
tx.addInput(Sha256Hash.ZERO_HASH, 0, org.bitcoinj.script.ScriptBuilder.createInputScript(null, new ECKey()));
tx.addOutput(Coin.COIN, Address.fromString(networkParameters, genesisFederation.getAddress().toBase58()));
tx.addOutput(COIN, Address.fromString(networkParameters, genesisFederation.getAddress().toBase58()));

return tx;
}

private TransactionOutput createBech32Output(NetworkParameters networkParameters, Coin valuesToSend) {
byte[] scriptBytes = networkParameters.getId().equals(
NetworkParameters.ID_MAINNET)?
Hex.decode("001437c383ea78269585c73289daa36d7b7014b65294") :
Hex.decode("0014ef57424d0d625cf82fabe4fd7657d24a5f13dfb2");
return new TransactionOutput(networkParameters, null,
valuesToSend,
scriptBytes
);
}

private Sha256Hash createHash() {
byte[] bytes = new byte[32];
bytes[0] = (byte) ++nhash;
Expand Down Expand Up @@ -2656,7 +2739,7 @@ private Transaction getCoinbaseTx(boolean hasWitness, Sha256Hash witnessRoot, by
}
input.setScriptSig(new Script(new byte[]{0,0}));
tx.addInput(input);
TransactionOutput output = new TransactionOutput(networkParameters, null, Coin.COIN, Address.fromString(networkParameters, "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou"));
TransactionOutput output = new TransactionOutput(networkParameters, null, COIN, Address.fromString(networkParameters, "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou"));
tx.addOutput(output);

byte[] witnessCommitment = Sha256Hash.twiceOf(witnessRoot.getReversedBytes(), witnessReservedValue).getBytes();
Expand All @@ -2683,7 +2766,7 @@ private Transaction getTx(boolean hasWitness) {
input.setWitness(witness);
}
tx.addInput(input);
TransactionOutput output = new TransactionOutput(networkParameters, null, Coin.COIN, Address.fromString(networkParameters, "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou"));
TransactionOutput output = new TransactionOutput(networkParameters, null, COIN, Address.fromString(networkParameters, "mvbnrCX3bg1cDRUu8pkecrvP6vQkSLDSou"));
tx.addOutput(output);

return tx;
Expand Down