mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-24 22:58:32 +01:00
ScriptPattern: Add pattern matcher for segwit commitment (in an output of the coinbase transaction).
Adds a test for parsing block 481815, which contains a segwit commitment in its coinbase.
This commit is contained in:
parent
d30d83c616
commit
b976205716
3 changed files with 45 additions and 0 deletions
|
@ -19,8 +19,11 @@ package org.bitcoinj.script;
|
||||||
|
|
||||||
import org.bitcoinj.core.LegacyAddress;
|
import org.bitcoinj.core.LegacyAddress;
|
||||||
import org.bitcoinj.core.SegwitAddress;
|
import org.bitcoinj.core.SegwitAddress;
|
||||||
|
import org.bitcoinj.core.Sha256Hash;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.bitcoinj.script.Script.decodeFromOpN;
|
import static org.bitcoinj.script.Script.decodeFromOpN;
|
||||||
|
@ -274,4 +277,31 @@ public class ScriptPattern {
|
||||||
List<ScriptChunk> chunks = script.chunks;
|
List<ScriptChunk> chunks = script.chunks;
|
||||||
return chunks.size() > 0 && chunks.get(0).equalsOpCode(ScriptOpCodes.OP_RETURN);
|
return chunks.size() > 0 && chunks.get(0).equalsOpCode(ScriptOpCodes.OP_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final byte[] SEGWIT_COMMITMENT_HEADER = Hex.decode("aa21a9ed");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this script matches the pattern for a segwit commitment (in an output of the coinbase
|
||||||
|
* transaction).
|
||||||
|
*/
|
||||||
|
public static boolean isSegwitCommitment(Script script) {
|
||||||
|
List<ScriptChunk> chunks = script.chunks;
|
||||||
|
if (chunks.size() < 2)
|
||||||
|
return false;
|
||||||
|
if (!chunks.get(0).equalsOpCode(ScriptOpCodes.OP_RETURN))
|
||||||
|
return false;
|
||||||
|
byte[] chunkData = chunks.get(1).data;
|
||||||
|
if (chunkData == null || chunkData.length != 36)
|
||||||
|
return false;
|
||||||
|
if (!Arrays.equals(Arrays.copyOfRange(chunkData, 0, 4), SEGWIT_COMMITMENT_HEADER))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the hash from a segwit commitment (in an output of the coinbase transaction).
|
||||||
|
*/
|
||||||
|
public static Sha256Hash extractSegwitCommitmentHash(Script script) {
|
||||||
|
return Sha256Hash.wrap(Arrays.copyOfRange(script.chunks.get(1).data, 4, 36));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,15 @@ import org.bitcoinj.params.MainNetParams;
|
||||||
import org.bitcoinj.params.TestNet2Params;
|
import org.bitcoinj.params.TestNet2Params;
|
||||||
import org.bitcoinj.params.TestNet3Params;
|
import org.bitcoinj.params.TestNet3Params;
|
||||||
import org.bitcoinj.params.UnitTestParams;
|
import org.bitcoinj.params.UnitTestParams;
|
||||||
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptOpCodes;
|
import org.bitcoinj.script.ScriptOpCodes;
|
||||||
|
import org.bitcoinj.script.ScriptPattern;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.bitcoinj.wallet.Wallet.BalanceType;
|
import org.bitcoinj.wallet.Wallet.BalanceType;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
@ -242,6 +245,18 @@ public class BlockTest {
|
||||||
assertEquals(Coin.ZERO, wallet.getBalance(BalanceType.AVAILABLE));
|
assertEquals(Coin.ZERO, wallet.getBalance(BalanceType.AVAILABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBlock481815_segwitCommitmentInCoinbase() throws Exception {
|
||||||
|
Block block481815 = MAINNET.getDefaultSerializer().makeBlock(ByteStreams.toByteArray(
|
||||||
|
getClass().getResourceAsStream("block481815.dat")));
|
||||||
|
assertEquals(2097, block481815.getTransactions().size());
|
||||||
|
Transaction coinbase = block481815.getTransactions().get(0);
|
||||||
|
final Script segwitCommitment = coinbase.getOutput(1).getScriptPubKey();
|
||||||
|
assertTrue(ScriptPattern.isSegwitCommitment(segwitCommitment));
|
||||||
|
assertEquals("3d03076733467c45b08ec503a0c5d406647b073e1914d35b5111960ed625f3b7",
|
||||||
|
ScriptPattern.extractSegwitCommitmentHash(segwitCommitment).toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isBIPs() throws Exception {
|
public void isBIPs() throws Exception {
|
||||||
final Block genesis = MAINNET.getGenesisBlock();
|
final Block genesis = MAINNET.getGenesisBlock();
|
||||||
|
|
BIN
core/src/test/resources/org/bitcoinj/core/block481815.dat
Normal file
BIN
core/src/test/resources/org/bitcoinj/core/block481815.dat
Normal file
Binary file not shown.
Loading…
Add table
Reference in a new issue