Skip to content

Commit

Permalink
Add logic to extractWitnessCommitmentHash in the Bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
marcos-iov committed Jan 6, 2025
1 parent 87bde23 commit 685c25a
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
24 changes: 20 additions & 4 deletions rskj-core/src/main/java/co/rsk/peg/bitcoin/BitcoinUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
import org.slf4j.LoggerFactory;

public class BitcoinUtils {
public static final byte WITNESS_COMMITMENT_LENGTH = 36; // 4 bytes for header, 32 for hash
public static final Sha256Hash WITNESS_RESERVED_VALUE = Sha256Hash.ZERO_HASH;
protected static final byte[] WITNESS_COMMITMENT_HEADER = Hex.decode("aa21a9ed");
protected static final int WITNESS_COMMITMENT_LENGTH = WITNESS_COMMITMENT_HEADER.length + Sha256Hash.LENGTH;
private static final int MINIMUM_WITNESS_COMMITMENT_SIZE = WITNESS_COMMITMENT_LENGTH + 2; // 1 extra by for OP_RETURN and another one for data length
private static final Logger logger = LoggerFactory.getLogger(BitcoinUtils.class);
private static final int FIRST_INPUT_INDEX = 0;

Expand Down Expand Up @@ -90,7 +90,7 @@ public static Optional<Sha256Hash> findWitnessCommitment(BtcTransaction tx) {
for (TransactionOutput output : outputsReversed) {
Script scriptPubKey = output.getScriptPubKey();
if (isWitnessCommitment(scriptPubKey)) {
Sha256Hash witnessCommitment = ScriptPattern.extractWitnessCommitmentHash(scriptPubKey);
Sha256Hash witnessCommitment = extractWitnessCommitmentHash(scriptPubKey);
return Optional.of(witnessCommitment);
}
}
Expand All @@ -99,7 +99,6 @@ public static Optional<Sha256Hash> findWitnessCommitment(BtcTransaction tx) {
}

private static boolean isWitnessCommitment(Script scriptPubKey) {
final int MINIMUM_WITNESS_COMMITMENT_SIZE = 38;
byte[] scriptPubKeyProgram = scriptPubKey.getProgram();

return scriptPubKeyProgram.length >= MINIMUM_WITNESS_COMMITMENT_SIZE
Expand All @@ -115,4 +114,21 @@ private static boolean hasCommitmentStructure(byte[] scriptPubKeyProgram) {
private static boolean hasWitnessCommitmentHeader(byte[] header) {
return Arrays.equals(header, WITNESS_COMMITMENT_HEADER);
}

/**
* Retrieves the hash from a segwit commitment (in an output of the coinbase transaction).
*/
private static Sha256Hash extractWitnessCommitmentHash(Script scriptPubKey) {
byte[] scriptPubKeyProgram = scriptPubKey.getProgram();
Preconditions.checkState(scriptPubKeyProgram.length >= MINIMUM_WITNESS_COMMITMENT_SIZE);

final int WITNESS_COMMITMENT_HASH_START = 6; // 4 bytes for header + OP_RETURN + data length
byte[] witnessCommitmentHash = Arrays.copyOfRange(
scriptPubKeyProgram,
WITNESS_COMMITMENT_HASH_START,
MINIMUM_WITNESS_COMMITMENT_SIZE
);

return Sha256Hash.wrap(witnessCommitmentHash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.ethereum.util.ByteUtil;

public class BitcoinTestUtils {
public static final Sha256Hash WITNESS_RESERVED_VALUE = Sha256Hash.ZERO_HASH;

public static BtcECKey getBtcEcKeyFromSeed(String seed) {
byte[] serializedSeed = HashUtil.keccak256(seed.getBytes(StandardCharsets.UTF_8));
Expand Down Expand Up @@ -215,7 +216,7 @@ public static BtcTransaction createCoinbaseTransactionWithWrongWitnessCommitment
byte[] wrongWitnessCommitmentWithHeader = ByteUtil.merge(
new byte[]{ScriptOpCodes.OP_RETURN},
new byte[]{ScriptOpCodes.OP_PUSHDATA1},
new byte[]{BitcoinUtils.WITNESS_COMMITMENT_LENGTH},
new byte[]{(byte) BitcoinUtils.WITNESS_COMMITMENT_LENGTH},
BitcoinUtils.WITNESS_COMMITMENT_HEADER,
witnessCommitment.getBytes()
);
Expand All @@ -230,7 +231,7 @@ private static BtcTransaction createCoinbaseTxWithWitnessReservedValue(NetworkPa
BtcTransaction coinbaseTx = createCoinbaseTransaction(networkParameters);

TransactionWitness txWitness = new TransactionWitness(1);
txWitness.setPush(0, BitcoinUtils.WITNESS_RESERVED_VALUE.getBytes());
txWitness.setPush(0, WITNESS_RESERVED_VALUE.getBytes());
coinbaseTx.setWitness(0, txWitness);

return coinbaseTx;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ private boolean isSigHashValid(Sha256Hash sigHash, List<BtcECKey> pubKeys, List<
LinkedList<BtcECKey> keys = new LinkedList<>(pubKeys);
LinkedList<BtcECKey.ECDSASignature> sigs = new LinkedList<>(signatures);

while (sigs.size() > 0){
while (!sigs.isEmpty()){
BtcECKey pubKey = keys.pollFirst();
BtcECKey.ECDSASignature signature = sigs.getFirst();
if(pubKey.verify(sigHash, signature)){
Expand Down Expand Up @@ -272,7 +272,7 @@ void extractRedeemScriptFromInput_p2sh_pegin_v1() {
assertFalse(btcTx.getInputs().isEmpty());

List<ScriptChunk> scriptSigChunks = scriptSig.getChunks();
Script expectedRedeemScript = new Script( scriptSigChunks.get(scriptSigChunks.size()- 1).data);
Script expectedRedeemScript = new Script(scriptSigChunks.get(scriptSigChunks.size()- 1).data);

// Act
Optional<Script> redeemScript = BitcoinUtils.extractRedeemScriptFromInput(btcTx.getInputs().get(FIRST_INPUT_INDEX));
Expand Down Expand Up @@ -512,7 +512,7 @@ void findWitnessCommitment_withDataLargenThanExpected_shouldReturnEmpty() {
BtcTransaction btcTx = BitcoinTestUtils.createCoinbaseTransaction(btcMainnetParams);

TransactionWitness txWitness = new TransactionWitness(1);
txWitness.setPush(0, BitcoinUtils.WITNESS_RESERVED_VALUE.getBytes());
txWitness.setPush(0, BitcoinTestUtils.WITNESS_RESERVED_VALUE.getBytes());
btcTx.setWitness(0, txWitness);

Sha256Hash witnessCommitment = BitcoinTestUtils.createHash(100);
Expand Down

0 comments on commit 685c25a

Please sign in to comment.