Skip to content

Commit

Permalink
Expose revealDepositWithExtraData from the Bridge contract
Browse files Browse the repository at this point in the history
Here we expose the `revealDepositWithExtraData` function that
allows revealing deposits with embedded 32-byte extra data.
  • Loading branch information
lukasz-zimnoch committed Dec 15, 2023
1 parent cadead9 commit 727e669
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 30 deletions.
12 changes: 11 additions & 1 deletion solidity/contracts/bridge/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ contract Bridge is
bytes20 indexed walletPubKeyHash,
bytes20 refundPubKeyHash,
bytes4 refundLocktime,
address vault
address vault,
bytes32 extraData
);

event DepositsSwept(bytes20 walletPubKeyHash, bytes32 sweepTxHash);
Expand Down Expand Up @@ -376,6 +377,15 @@ contract Bridge is
self.revealDeposit(fundingTx, reveal);
}

// TODO: Documentation and tests.
function revealDepositWithExtraData(
BitcoinTx.Info calldata fundingTx,
Deposit.DepositRevealInfo calldata reveal,
bytes32 extraData
) external {
self.revealDepositWithExtraData(fundingTx, reveal, extraData);
}

/// @notice Used by the wallet to prove the BTC deposit sweep transaction
/// and to update Bank balances accordingly. Sweep is only accepted
/// if it satisfies SPV proof.
Expand Down
121 changes: 92 additions & 29 deletions solidity/contracts/bridge/Deposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ library Deposit {
bytes20 indexed walletPubKeyHash,
bytes20 refundPubKeyHash,
bytes4 refundLocktime,
address vault
address vault,
bytes32 extraData
);

/// @notice Used by the depositor to reveal information about their P2(W)SH
Expand Down Expand Up @@ -152,6 +153,16 @@ library Deposit {
BitcoinTx.Info calldata fundingTx,
DepositRevealInfo calldata reveal
) external {
revealDeposit(self, fundingTx, reveal, bytes32(0));
}

// TODO: Documentation and think about better name.
function revealDeposit(
BridgeState.Storage storage self,
BitcoinTx.Info calldata fundingTx,
DepositRevealInfo calldata reveal,
bytes32 extraData
) internal {
require(
self.registeredWallets[reveal.walletPubKeyHash].state ==
Wallets.WalletState.Live,
Expand All @@ -167,33 +178,70 @@ library Deposit {
validateDepositRefundLocktime(self, reveal.refundLocktime);
}

bytes memory expectedScript = abi.encodePacked(
hex"14", // Byte length of depositor Ethereum address.
msg.sender,
hex"75", // OP_DROP
hex"08", // Byte length of blinding factor value.
reveal.blindingFactor,
hex"75", // OP_DROP
hex"76", // OP_DUP
hex"a9", // OP_HASH160
hex"14", // Byte length of a compressed Bitcoin public key hash.
reveal.walletPubKeyHash,
hex"87", // OP_EQUAL
hex"63", // OP_IF
hex"ac", // OP_CHECKSIG
hex"67", // OP_ELSE
hex"76", // OP_DUP
hex"a9", // OP_HASH160
hex"14", // Byte length of a compressed Bitcoin public key hash.
reveal.refundPubKeyHash,
hex"88", // OP_EQUALVERIFY
hex"04", // Byte length of refund locktime value.
reveal.refundLocktime,
hex"b1", // OP_CHECKLOCKTIMEVERIFY
hex"75", // OP_DROP
hex"ac", // OP_CHECKSIG
hex"68" // OP_ENDIF
);
bytes memory expectedScript;

if (extraData == bytes32(0)) {
// Regular deposit without 32-byte extra data.
expectedScript = abi.encodePacked(
hex"14", // Byte length of depositor Ethereum address.
msg.sender,
hex"75", // OP_DROP
hex"08", // Byte length of blinding factor value.
reveal.blindingFactor,
hex"75", // OP_DROP
hex"76", // OP_DUP
hex"a9", // OP_HASH160
hex"14", // Byte length of a compressed Bitcoin public key hash.
reveal.walletPubKeyHash,
hex"87", // OP_EQUAL
hex"63", // OP_IF
hex"ac", // OP_CHECKSIG
hex"67", // OP_ELSE
hex"76", // OP_DUP
hex"a9", // OP_HASH160
hex"14", // Byte length of a compressed Bitcoin public key hash.
reveal.refundPubKeyHash,
hex"88", // OP_EQUALVERIFY
hex"04", // Byte length of refund locktime value.
reveal.refundLocktime,
hex"b1", // OP_CHECKLOCKTIMEVERIFY
hex"75", // OP_DROP
hex"ac", // OP_CHECKSIG
hex"68" // OP_ENDIF
);
} else {
// Deposit with 32-byte extra data.
expectedScript = abi.encodePacked(
hex"14", // Byte length of depositor Ethereum address.
msg.sender,
hex"75", // OP_DROP
hex"20", // Byte length of extra data.
extraData,
hex"75", // OP_DROP
hex"08", // Byte length of blinding factor value.
reveal.blindingFactor,
hex"75", // OP_DROP
hex"76", // OP_DUP
hex"a9", // OP_HASH160
hex"14", // Byte length of a compressed Bitcoin public key hash.
reveal.walletPubKeyHash,
hex"87", // OP_EQUAL
hex"63", // OP_IF
hex"ac", // OP_CHECKSIG
hex"67", // OP_ELSE
hex"76", // OP_DUP
hex"a9", // OP_HASH160
hex"14", // Byte length of a compressed Bitcoin public key hash.
reveal.refundPubKeyHash,
hex"88", // OP_EQUALVERIFY
hex"04", // Byte length of refund locktime value.
reveal.refundLocktime,
hex"b1", // OP_CHECKLOCKTIMEVERIFY
hex"75", // OP_DROP
hex"ac", // OP_CHECKSIG
hex"68" // OP_ENDIF
);
}

bytes memory fundingOutput = fundingTx
.outputVector
Expand Down Expand Up @@ -268,10 +316,25 @@ library Deposit {
reveal.walletPubKeyHash,
reveal.refundPubKeyHash,
reveal.refundLocktime,
reveal.vault
reveal.vault,
extraData
);
}

// TODO: Documentation and tests.
function revealDepositWithExtraData(
BridgeState.Storage storage self,
BitcoinTx.Info calldata fundingTx,
DepositRevealInfo calldata reveal,
bytes32 extraData
) external {
// Strong requirement in order to differentiate from the regular
// reveal flow and reduce potential attack surface.
require(extraData != bytes32(0), "Extra data must not be empty");

revealDeposit(self, fundingTx, reveal, extraData);
}

/// @notice Validates the deposit refund locktime. The validation passes
/// successfully only if the deposit reveal is done respectively
/// earlier than the moment when the deposit refund locktime is
Expand Down

0 comments on commit 727e669

Please sign in to comment.