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

Add logic to extractWitnessCommitmentHash in the Bridge #2890

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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
Loading