Skip to content

Commit

Permalink
- Add pegout transaction created event assertions for rejected pegin …
Browse files Browse the repository at this point in the history
…test cases

- Moved logic to decode and encode utxo outpoint values to a util function.
- Moved pegout event names to a constant file.
  • Loading branch information
nathanieliov committed Jun 11, 2024
1 parent 13ea2e4 commit 27f37a1
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 23 deletions.
22 changes: 21 additions & 1 deletion lib/2wp-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
waitForRskMempoolToGetNewTxs,
waitAndUpdateBridge
} = require('./rsk-utils');
const { retryWithCheck } = require('./utils');
const { retryWithCheck, removePrefix0x } = require('./utils');
const { waitForBitcoinTxToBeInMempool, waitForBitcoinMempoolToGetTxs } = require('./btc-utils');
const { getBridge, getLatestActiveForkName } = require('./precompiled-abi-forks-util');
const { getBridgeState } = require('@rsksmart/bridge-state-data-parser');
Expand All @@ -17,6 +17,9 @@ const peginVerifier = require('pegin-address-verificator');
const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider');
const { WHITELIST_CHANGE_PK, WHITELIST_CHANGE_ADDR} = require('../lib/assertions/whitelisting');
const { getLogger } = require('../logger');
const rskUtils = require("./rsk-utils");
const {PEGOUT_EVENTS} = require("./constants");
const {encodeOutpointValuesAsMap, decodeOutpointValues} = require("./varint");

const BTC_TO_RSK_MINIMUM_CONFIRMATIONS = 3;
const TO_BRIDGE_GAS_PRICE = 2;
Expand All @@ -25,6 +28,22 @@ const MIN_PEGOUT_VALUE_IN_RBTC = 0.0025;

const logger = getLogger();

const findPegoutCreatedEventAndAssertRefundUtxo = async(rskTxHelper, btcTxHelper, refundAddress, fromBlock, toBlock, amountSentInSatoshis) => {
const refundAddressUtxos = await btcTxHelper.getUtxos(refundAddress);
const refundTxHash = refundAddressUtxos[0].txid;

const pegoutTransactionCreatedEvent = await rskUtils.findEventInBlock(rskTxHelper, PEGOUT_EVENTS.PEGOUT_TRANSACTION_CREATED, refundAddress, toBlock, (event) => {
return event.arguments.btcTxHash === refundTxHash;
});

expect(pegoutTransactionCreatedEvent).to.not.be.null;
expect(pegoutTransactionCreatedEvent.arguments.btcTxHash).to.equal(refundTxHash);
const encodedUtxoOutpointValues = Buffer.from(removePrefix0x(pegoutTransactionCreatedEvent.arguments.utxoOutpointValues), 'hex');
const federationUtxoValues = encodeOutpointValuesAsMap({ "valueInSatoshis": Number(btcEthUnitConverter.btcToSatoshis(amountSentInSatoshis))});
const outpointValues = decodeOutpointValues(encodedUtxoOutpointValues);
expect(outpointValues.every(value => value in federationUtxoValues)).to.be.true;
}

/**
*
* @param {RskTransactionHelper} rskTxHelper
Expand Down Expand Up @@ -230,6 +249,7 @@ const disableWhitelisting = async (rskTxHelper, btcTxHelper, blockDelay = 1) =>
module.exports = {
sendTxToBridge,
assertRefundUtxosSameAsPeginUtxos,
findPegoutCreatedEventAndAssertRefundUtxo,
createPegoutRequest,
sendPegin,
ensurePeginIsRegistered,
Expand Down
10 changes: 10 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ const PEGIN_REJECTION_REASONS = {
PEGIN_V1_INVALID_PAYLOAD_REASON: '4'
};

const PEGOUT_EVENTS = {
RELEASE_REQUEST_RECEIVED: "release_request_received",
RELEASE_REQUEST_REJECTED: "release_request_rejected",
RELEASE_REQUESTED: "release_requested",
BATCH_PEGOUT_CREATED: "batch_pegout_created",
PEGOUT_TRANSACTION_CREATED: "pegout_transaction_created",
PEGOUT_CONFIRMED: "pegout_confirmed"
}

module.exports = {
KEY_TYPE_BTC,
KEY_TYPE_RSK,
Expand All @@ -63,4 +72,5 @@ module.exports = {
GENESIS_FEDERATION_REDEEM_SCRIPT,
FEDERATION_ACTIVATION_AGE,
PEGIN_REJECTION_REASONS,
PEGOUT_EVENTS
};
30 changes: 11 additions & 19 deletions lib/tests/2wp.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ const { getDerivedRSKAddressInformation } = require('@rsksmart/btc-rsk-derivatio
const btcEthUnitConverter = require('@rsksmart/btc-eth-unit-converter');
const { sendTxToBridge, sendPegin, ensurePeginIsRegistered, donateToBridge } = require('../2wp-utils');
const { waitAndUpdateBridge } = require('../rsk-utils');
const {VarInt} = require("../varint");
const { decodeOutpointValues, encodeOutpointValuesAsMap } = require("../varint");
const {getBridgeState} = require("@rsksmart/bridge-state-data-parser");
const {PEGOUT_EVENTS} = require("../constants");

const DONATION_AMOUNT = 250;
const REJECTED_REASON = 1;
Expand Down Expand Up @@ -153,7 +154,7 @@ const execute = (description, getRskHost) => {

const isIris300AlreadyActive = await Runners.common.forks.iris300.isAlreadyActive();
if (isIris300AlreadyActive) {
const pegoutRequestReceivedEvent = await rskUtils.findEventInBlock(rskTxHelper, 'release_request_received');
const pegoutRequestReceivedEvent = await rskUtils.findEventInBlock(rskTxHelper, PEGOUT_EVENTS.RELEASE_REQUEST_RECEIVED);
expect(pegoutRequestReceivedEvent).to.not.be.null;
const btcDestinationAddress = pegoutRequestReceivedEvent.arguments.btcDestinationAddress;
expect(pegoutRequestReceivedEvent.arguments.sender.toLowerCase()).to.equal(ensure0x(recipientRskAddressInfo.address));
Expand All @@ -169,43 +170,34 @@ const execute = (description, getRskHost) => {
const pegoutCreatedValidations = async (localRskTxHelper) => {
const isPapyrus200AlreadyActive = await Runners.common.forks.papyrus200.isAlreadyActive();
if (isPapyrus200AlreadyActive) {
const pegoutRequestedEvent = await rskUtils.findEventInBlock(localRskTxHelper, 'release_requested');
const pegoutRequestedEvent = await rskUtils.findEventInBlock(localRskTxHelper, PEGOUT_EVENTS.RELEASE_REQUESTED);
expect(pegoutRequestedEvent).to.not.be.null;
expect(Number(pegoutRequestedEvent.arguments.amount)).to.equal(pegoutValueInSatoshis);
}
const isHop400AlreadyActive = await Runners.common.forks.hop400.isAlreadyActive();
if (isHop400AlreadyActive) {
const batchPegoutCreatedEvent = await rskUtils.findEventInBlock(localRskTxHelper, 'batch_pegout_created');
const batchPegoutCreatedEvent = await rskUtils.findEventInBlock(localRskTxHelper, PEGOUT_EVENTS.BATCH_PEGOUT_CREATED);
expect(batchPegoutCreatedEvent).to.not.be.null;
expect(batchPegoutCreatedEvent.arguments.releaseRskTxHashes.includes(pegoutTransaction.transactionHash)).to.be.true;
}

const isLovell700AlreadyActive = await Runners.common.forks.lovell700.isAlreadyActive();
if (isLovell700AlreadyActive) {
const pegoutTransactionCreatedEvent = await rskUtils.findEventInBlock(localRskTxHelper, 'pegout_transaction_created');
const pegoutTransactionCreatedEvent = await rskUtils.findEventInBlock(localRskTxHelper, PEGOUT_EVENTS.PEGOUT_TRANSACTION_CREATED);
expect(pegoutTransactionCreatedEvent).to.not.be.null;
const encodedUtxoOutpointValues = Buffer.from(removePrefix0x(pegoutTransactionCreatedEvent.arguments.utxoOutpointValues), 'hex');

const federationUtxoValues = activeFederationUtxosBeforePegout.reduce((map, utxo) => {
map[utxo.valueInSatoshis] = Buffer.from(new VarInt(utxo.valueInSatoshis).encode()).toString("hex");
return map;
}, {});
const federationUtxoValues = encodeOutpointValuesAsMap(activeFederationUtxosBeforePegout);

let offset = 0;
let idx = 0;
while (encodedUtxoOutpointValues.length > offset) {
let utxoOutpointValue = new VarInt(encodedUtxoOutpointValues, offset);
expect(utxoOutpointValue.value in federationUtxoValues).to.be.true
const outpointValues = decodeOutpointValues(encodedUtxoOutpointValues);

offset += utxoOutpointValue.getSizeInBytes();
idx++;
}
expect(outpointValues.every(value => value in federationUtxoValues)).to.be.true;
}
};

const pegoutConfirmedValidations = async (localRskTxHelper) => {
if (isFingerroot500AlreadyActive) {
const pegoutConfirmedEvent = await rskUtils.findEventInBlock(localRskTxHelper, 'pegout_confirmed');
const pegoutConfirmedEvent = await rskUtils.findEventInBlock(localRskTxHelper, PEGOUT_EVENTS.PEGOUT_CONFIRMED);
expect(pegoutConfirmedEvent).to.not.be.null;
}
};
Expand Down Expand Up @@ -243,7 +235,7 @@ const execute = (description, getRskHost) => {
const pegoutTransaction = await sendTxToBridge(rskTxHelper, PEGOUT_UNDER_MINIMUM_VALUE_IN_BTC, recipientRskAddressInfo.address);
const isIris300AlreadyActive = await Runners.common.forks.iris300.isAlreadyActive();
if (isIris300AlreadyActive) {
const pegoutRejectedEvent = await rskUtils.findEventInBlock(rskTxHelper, 'release_request_rejected');
const pegoutRejectedEvent = await rskUtils.findEventInBlock(rskTxHelper, PEGOUT_EVENTS.RELEASE_REQUEST_REJECTED);
expect(pegoutRejectedEvent).to.not.be.null;
const pegoutValueInSatoshis = Number(btcEthUnitConverter.btcToSatoshis(PEGOUT_UNDER_MINIMUM_VALUE_IN_BTC));
expect(Number(pegoutRejectedEvent.arguments.amount)).to.equal(pegoutValueInSatoshis);
Expand Down
23 changes: 22 additions & 1 deletion lib/varint.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,25 @@ class VarInt {
}
}

module.exports = { VarInt };
const decodeOutpointValues = (encodedUtxoOutpointValues) => {
let offset = 0;
let idx = 0;
const outpointValues = [];
while (encodedUtxoOutpointValues.length > offset) {
let utxoOutpointValue = new VarInt(encodedUtxoOutpointValues, offset);
outpointValues.push(utxoOutpointValue.value);
offset += utxoOutpointValue.getSizeInBytes();
idx++;
}
return outpointValues;
}

const encodeOutpointValuesAsMap = (utxos) => {
const encodeOutpointValues = utxos.reduce((map, utxo) => {
map[utxo.valueInSatoshis] = Buffer.from(new VarInt(utxo.valueInSatoshis).encode()).toString("hex");
return map;
}, {});
return encodeOutpointValues;
}

module.exports = { VarInt, decodeOutpointValues, encodeOutpointValuesAsMap };
12 changes: 10 additions & 2 deletions tests/02_00_05-2wp_version1.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
const { expect } = require('chai');
const peginVerifier = require('pegin-address-verificator');
const rskUtils = require('../lib/rsk-utils');
const { sendPegin, ensurePeginIsRegistered, assertRefundUtxosSameAsPeginUtxos } = require('../lib/2wp-utils');
const { sendPegin, ensurePeginIsRegistered, assertRefundUtxosSameAsPeginUtxos,
findPegoutCreatedEventAndAssertRefundUtxo
} = require('../lib/2wp-utils');
const { getBtcClient } = require('../lib/btc-client-provider');
const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider');
const { getDerivedRSKAddressInformation } = require('@rsksmart/btc-rsk-derivation');
const btcEthUnitConverter = require('@rsksmart/btc-eth-unit-converter');
const { ensure0x } = require('../lib/utils');
const {
PEGIN_REJECTION_REASONS: { PEGIN_V1_INVALID_PAYLOAD_REASON }
} = require('../lib/constants');
} = require('../lib/constants');

const AMOUNT_TO_LOCK_IN_BTC = 2;

Expand Down Expand Up @@ -163,6 +165,8 @@ describe('Lock funds using peg-in protocol version 1', () => {
expect(rejectedPeginEvent.arguments.btcTxHash).to.equal(peginBtcTxHashWith0xPrefix);
expect(rejectedPeginEvent.arguments.reason).to.equal(PEGIN_V1_INVALID_PAYLOAD_REASON);

const amountSentInSatoshis = Number(btcEthUnitConverter.btcToSatoshis(AMOUNT_TO_LOCK_IN_BTC));
await findPegoutCreatedEventAndAssertRefundUtxo(rskTxHelper, btcTxHelper, senderAddressInformation.address, searchRejectedPeginEventFromBlock, latestBlock, amountSentInSatoshis);
});

it('should lock with multiple OP_RETURN outputs but only one for RSK', async () => {
Expand Down Expand Up @@ -239,6 +243,8 @@ describe('Lock funds using peg-in protocol version 1', () => {
expect(rejectedPeginEvent.arguments.btcTxHash).to.equal(peginBtcTxHashWith0xPrefix);
expect(rejectedPeginEvent.arguments.reason).to.equal(PEGIN_V1_INVALID_PAYLOAD_REASON);

const amountSentInSatoshis = Number(btcEthUnitConverter.btcToSatoshis(AMOUNT_TO_LOCK_IN_BTC));
await findPegoutCreatedEventAndAssertRefundUtxo(rskTxHelper, btcTxHelper, peginBtcTxHash, senderAddressInformation.address, searchRejectedPeginEventFromBlock, latestBlock, amountSentInSatoshis);
});

it('should refund lock with OP_RETURN output for RSK with invalid version number', async () => {
Expand Down Expand Up @@ -293,5 +299,7 @@ describe('Lock funds using peg-in protocol version 1', () => {
expect(rejectedPeginEvent.arguments.btcTxHash).to.equal(peginBtcTxHashWith0xPrefix);
expect(rejectedPeginEvent.arguments.reason).to.equal(PEGIN_V1_INVALID_PAYLOAD_REASON);

const amountSentInSatoshis = Number(btcEthUnitConverter.btcToSatoshis(AMOUNT_TO_LOCK_IN_BTC));
await findPegoutCreatedEventAndAssertRefundUtxo(rskTxHelper, btcTxHelper, peginBtcTxHash, senderAddressInformation.address, searchRejectedPeginEventFromBlock, latestBlock, amountSentInSatoshis);
});
});

0 comments on commit 27f37a1

Please sign in to comment.