Add script verification flags for DER format

Add script verification flags for DER format encoding, low-S signatures
and strict encoding.
Pass script verification flags through to signature parser.
Convert block verification flags to a sub-enum of Block.
Remove DER signature format verification flag from block flags.
Add test transaction with a non-standard DER signature, with the verify
flag set/unset accordingly, to tx_invalid.json and tx_valid.json
This commit is contained in:
Ross Nicoll
2015-09-13 12:19:57 +01:00
committed by Andreas Schildbach
parent 1c74aac27e
commit 829e147ec7
13 changed files with 135 additions and 75 deletions

View File

@@ -451,7 +451,7 @@ public abstract class AbstractBlockChain {
final StoredBlock storedPrev;
final int height;
final EnumSet<VerificationFlags> flags;
final EnumSet<Block.VerifyFlag> flags;
// Prove the block is internally valid: hash is lower than target, etc. This only checks the block contents
// if there is a tx sending or receiving coins using an address in one of our wallets. And those transactions
@@ -465,7 +465,7 @@ public abstract class AbstractBlockChain {
} else {
height = Block.BLOCK_HEIGHT_UNKNOWN;
}
flags = params.getValidationFlags(block, versionTally, height);
flags = params.getBlockVerificationFlags(block, versionTally, height);
if (shouldVerifyTransactions())
block.verifyTransactions(height, flags);
} catch (VerificationException e) {
@@ -1073,4 +1073,8 @@ public abstract class AbstractBlockChain {
falsePositiveTrend = 0;
previousFalsePositiveRate = 0;
}
protected VersionTally getVersionTally() {
return versionTally;
}
}

View File

@@ -42,6 +42,15 @@ import static org.bitcoinj.core.Sha256Hash.*;
* specifically using {@link Peer#getBlock(Sha256Hash)}, or grab one from a downloaded {@link BlockChain}.
*/
public class Block extends Message {
/**
* Flags used to control which elements of block validation are done on
* received blocks.
*/
public enum VerifyFlag {
/** Check that block height is in coinbase transaction (BIP 34). */
HEIGHT_IN_COINBASE
}
private static final Logger log = LoggerFactory.getLogger(Block.class);
/** How many bytes are required to represent a block header WITHOUT the trailing 00 length byte. */
@@ -631,12 +640,12 @@ public class Block extends Message {
* to validate the coinbase input script of v2 and above blocks.
* @throws VerificationException if there was an error verifying the block.
*/
private void checkTransactions(final int height, final EnumSet<VerificationFlags> flags)
private void checkTransactions(final int height, final EnumSet<VerifyFlag> flags)
throws VerificationException {
// The first transaction in a block must always be a coinbase transaction.
if (!transactions.get(0).isCoinBase())
throw new VerificationException("First tx is not coinbase");
if (flags.contains(VerificationFlags.HEIGHT_IN_COINBASE) && height >= BLOCK_HEIGHT_GENESIS) {
if (flags.contains(Block.VerifyFlag.HEIGHT_IN_COINBASE) && height >= BLOCK_HEIGHT_GENESIS) {
transactions.get(0).checkCoinBaseHeight(height);
}
// The rest must not be.
@@ -673,7 +682,7 @@ public class Block extends Message {
* whether to test for height in the coinbase transaction).
* @throws VerificationException if there was an error verifying the block.
*/
public void verifyTransactions(final int height, final EnumSet<VerificationFlags> flags) throws VerificationException {
public void verifyTransactions(final int height, final EnumSet<VerifyFlag> flags) throws VerificationException {
// Now we need to check that the body of the block actually matches the headers. The network won't generate
// an invalid block, but if we didn't validate this then an untrusted man-in-the-middle could obtain the next
// valid block from the network and simply replace the transactions in it with their own fictional
@@ -697,7 +706,7 @@ public class Block extends Message {
* whether to test for height in the coinbase transaction).
* @throws VerificationException if there was an error verifying the block.
*/
public void verify(final int height, final EnumSet<VerificationFlags> flags) throws VerificationException {
public void verify(final int height, final EnumSet<VerifyFlag> flags) throws VerificationException {
verifyHeader();
verifyTransactions(height, flags);
}

View File

@@ -17,7 +17,6 @@
package org.bitcoinj.core;
import org.bitcoinj.core.listeners.TransactionReceivedInBlockListener;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.Script.VerifyFlag;
import org.bitcoinj.store.BlockStoreException;
@@ -28,7 +27,6 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -221,9 +219,6 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
LinkedList<UTXO> txOutsSpent = new LinkedList<UTXO>();
LinkedList<UTXO> txOutsCreated = new LinkedList<UTXO>();
long sigOps = 0;
final Set<VerifyFlag> verifyFlags = EnumSet.noneOf(VerifyFlag.class);
if (block.getTimeSeconds() >= NetworkParameters.BIP16_ENFORCE_TIME)
verifyFlags.add(VerifyFlag.P2SH);
if (scriptVerificationExecutor.isShutdown())
scriptVerificationExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
@@ -235,6 +230,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
// checkpoints list and we therefore only check non-checkpoints for duplicated transactions here. See the
// BIP30 document for more details on this: https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki
for (Transaction tx : block.transactions) {
final Set<VerifyFlag> verifyFlags = params.getTransactionVerificationFlags(block, tx, getVersionTally(), height);
Sha256Hash hash = tx.getHash();
// If we already have unspent outputs for this hash, we saw the tx already. Either the block is
// being added twice (bug) or the block is a BIP30 violator.
@@ -251,6 +247,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
Coin valueIn = Coin.ZERO;
Coin valueOut = Coin.ZERO;
final List<Script> prevOutScripts = new LinkedList<Script>();
final Set<VerifyFlag> verifyFlags = params.getTransactionVerificationFlags(block, tx, getVersionTally(), height);
if (!isCoinBase) {
// For each input of the transaction remove the corresponding output from the set of unspent
// outputs.
@@ -366,9 +363,7 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
LinkedList<UTXO> txOutsSpent = new LinkedList<UTXO>();
LinkedList<UTXO> txOutsCreated = new LinkedList<UTXO>();
long sigOps = 0;
final Set<VerifyFlag> verifyFlags = EnumSet.noneOf(VerifyFlag.class);
if (newBlock.getHeader().getTimeSeconds() >= NetworkParameters.BIP16_ENFORCE_TIME)
verifyFlags.add(VerifyFlag.P2SH);
if (!params.isCheckpoint(newBlock.getHeight())) {
for (Transaction tx : transactions) {
Sha256Hash hash = tx.getHash();
@@ -383,10 +378,13 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
scriptVerificationExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<Future<VerificationException>> listScriptVerificationResults = new ArrayList<Future<VerificationException>>(transactions.size());
for (final Transaction tx : transactions) {
final Set<VerifyFlag> verifyFlags =
params.getTransactionVerificationFlags(newBlock.getHeader(), tx, getVersionTally(), Integer.SIZE);
boolean isCoinBase = tx.isCoinBase();
Coin valueIn = Coin.ZERO;
Coin valueOut = Coin.ZERO;
final List<Script> prevOutScripts = new LinkedList<Script>();
if (!isCoinBase) {
for (int index = 0; index < tx.getInputs().size(); index++) {
final TransactionInput in = tx.getInputs().get(index);
@@ -404,6 +402,8 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
throw new VerificationException("Too many P2SH SigOps in block");
}
// TODO: Enforce DER signature format
prevOutScripts.add(prevOut.getScript());
blockStore.removeUnspentTransactionOutput(prevOut);

View File

@@ -487,22 +487,34 @@ public abstract class NetworkParameters {
* @param height height of the block, if known, null otherwise. Returned
* tests should be a safe subset if block height is unknown.
*/
public EnumSet<VerificationFlags> getValidationFlags(final Block block,
public EnumSet<Block.VerifyFlag> getBlockVerificationFlags(final Block block,
final VersionTally tally, final Integer height) {
final EnumSet<VerificationFlags> flags = EnumSet.noneOf(VerificationFlags.class);
final EnumSet<Block.VerifyFlag> flags = EnumSet.noneOf(Block.VerifyFlag.class);
if (block.getVersion() >= Block.BLOCK_VERSION_BIP34) {
final Integer count = tally.getCountAtOrAbove(Block.BLOCK_VERSION_BIP34);
if (null != count && count >= getMajorityEnforceBlockUpgrade()) {
flags.add(VerificationFlags.HEIGHT_IN_COINBASE);
}
}
if (block.getVersion() >= Block.BLOCK_VERSION_BIP66) {
final Integer count = tally.getCountAtOrAbove(Block.BLOCK_VERSION_BIP66);
if (null != count && count >= getMajorityEnforceBlockUpgrade()) {
flags.add(VerificationFlags.DER_SIGNATURE_FORMAT);
flags.add(Block.VerifyFlag.HEIGHT_IN_COINBASE);
}
}
return flags;
}
/**
* The flags indicating which script validation tests should be applied to
* the given transaction. Enables support for alternative blockchains which enable
* tests based on different criteria.
*
* @param block block the transaction belongs to.
* @param transaction to determine flags for.
* @param height height of the block, if known, null otherwise. Returned
* tests should be a safe subset if block height is unknown.
*/
public EnumSet<Script.VerifyFlag> getTransactionVerificationFlags(final Block block,
final Transaction transaction, final VersionTally tally, final Integer height) {
final EnumSet<Script.VerifyFlag> verifyFlags = EnumSet.noneOf(Script.VerifyFlag.class);
if (block.getTimeSeconds() >= NetworkParameters.BIP16_ENFORCE_TIME)
verifyFlags.add(Script.VerifyFlag.P2SH);
return verifyFlags;
}
}

View File

@@ -1,27 +0,0 @@
/*
* Copyright 2015 Ross Nicoll
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bitcoinj.core;
/**
* Flags used to control which elements of block validation are performed on
* received blocks.
*/
public enum VerificationFlags {
/** Check that block height is in coinbase transaction (BIP 34) */
HEIGHT_IN_COINBASE,
/** Check DER signature format is exact (BIP 66) */
DER_SIGNATURE_FORMAT
}

View File

@@ -18,8 +18,6 @@
package org.bitcoinj.params;
import java.math.BigInteger;
import java.util.EnumSet;
import java.util.Set;
import org.bitcoinj.core.Block;
import org.bitcoinj.core.Coin;
@@ -35,8 +33,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.bitcoinj.core.BitcoinSerializer;
import org.bitcoinj.core.VerificationFlags;
import org.bitcoinj.utils.VersionTally;
/**
* Parameters for Bitcoin-like networks.

View File

@@ -62,10 +62,19 @@ public class Script {
P2SH
}
/** Flags to pass to {@link Script#correctlySpends(Transaction, long, Script, Set)}. */
/** Flags to pass to {@link Script#correctlySpends(Transaction, long, Script, Set)}.
* Note currently only P2SH, DERSIG and NULLDUMMY are actually supported.
*/
public enum VerifyFlag {
P2SH, // Enable BIP16-style subscript evaluation.
NULLDUMMY // Verify dummy stack item consumed by CHECKMULTISIG is of zero-length.
STRICTENC, // Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
DERSIG, // Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP66 rule 1)
LOW_S, // Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
NULLDUMMY, // Verify dummy stack item consumed by CHECKMULTISIG is of zero-length.
SIGPUSHONLY, // Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
MINIMALDATA, // Require minimal encodings for all push operations
DISCOURAGE_UPGRADABLE_NOPS, // Discourage use of NOPs reserved for upgrades (NOP1-10)
CLEANSTACK // Require that only a single stack element remains after evaluation.
}
public static final EnumSet<VerifyFlag> ALL_VERIFY_FLAGS = EnumSet.allOf(VerifyFlag.class);
@@ -759,9 +768,29 @@ public class Script {
* {@link org.bitcoinj.script.Script#correctlySpends(org.bitcoinj.core.Transaction, long, Script)}. This method
* is useful if you need more precise control or access to the final state of the stack. This interface is very
* likely to change in future.
*
* @deprecated Use {@link #executeScript(org.bitcoinj.core.Transaction, long, org.bitcoinj.script.Script, java.util.LinkedList, java.util.Set)}
* instead.
*/
@Deprecated
public static void executeScript(@Nullable Transaction txContainingThis, long index,
Script script, LinkedList<byte[]> stack, boolean enforceNullDummy) throws ScriptException {
final EnumSet<VerifyFlag> flags = enforceNullDummy
? EnumSet.of(VerifyFlag.NULLDUMMY)
: EnumSet.noneOf(VerifyFlag.class);
executeScript(txContainingThis, index, script, stack, flags);
}
/**
* Exposes the script interpreter. Normally you should not use this directly, instead use
* {@link org.bitcoinj.core.TransactionInput#verify(org.bitcoinj.core.TransactionOutput)} or
* {@link org.bitcoinj.script.Script#correctlySpends(org.bitcoinj.core.Transaction, long, Script)}. This method
* is useful if you need more precise control or access to the final state of the stack. This interface is very
* likely to change in future.
*/
public static void executeScript(@Nullable Transaction txContainingThis, long index,
Script script, LinkedList<byte[]> stack, Set<VerifyFlag> verifyFlags) throws ScriptException {
int opCount = 0;
int lastCodeSepLocation = 0;
@@ -1233,13 +1262,13 @@ public class Script {
case OP_CHECKSIGVERIFY:
if (txContainingThis == null)
throw new IllegalStateException("Script attempted signature check but no tx was provided");
executeCheckSig(txContainingThis, (int) index, script, stack, lastCodeSepLocation, opcode);
executeCheckSig(txContainingThis, (int) index, script, stack, lastCodeSepLocation, opcode, verifyFlags);
break;
case OP_CHECKMULTISIG:
case OP_CHECKMULTISIGVERIFY:
if (txContainingThis == null)
throw new IllegalStateException("Script attempted signature check but no tx was provided");
opCount = executeMultiSig(txContainingThis, (int) index, script, stack, opCount, lastCodeSepLocation, opcode, enforceNullDummy);
opCount = executeMultiSig(txContainingThis, (int) index, script, stack, opCount, lastCodeSepLocation, opcode, verifyFlags);
break;
case OP_NOP1:
case OP_NOP2:
@@ -1267,7 +1296,11 @@ public class Script {
}
private static void executeCheckSig(Transaction txContainingThis, int index, Script script, LinkedList<byte[]> stack,
int lastCodeSepLocation, int opcode) throws ScriptException {
int lastCodeSepLocation, int opcode,
Set<VerifyFlag> verifyFlags) throws ScriptException {
final boolean requireCanonical = verifyFlags.contains(VerifyFlag.STRICTENC)
|| verifyFlags.contains(VerifyFlag.DERSIG)
|| verifyFlags.contains(VerifyFlag.LOW_S);
if (stack.size() < 2)
throw new ScriptException("Attempted OP_CHECKSIG(VERIFY) on a stack with size < 2");
byte[] pubKey = stack.pollLast();
@@ -1287,7 +1320,10 @@ public class Script {
// TODO: Use int for indexes everywhere, we can't have that many inputs/outputs
boolean sigValid = false;
try {
TransactionSignature sig = TransactionSignature.decodeFromBitcoin(sigBytes, false);
// TODO: Should pass through LOW_S verification flag
TransactionSignature sig = TransactionSignature.decodeFromBitcoin(sigBytes, requireCanonical);
// TODO: Should check hash type is known
Sha256Hash hash = txContainingThis.hashForSignature(index, connectedScript, (byte) sig.sighashFlags);
sigValid = ECKey.verify(hash.getBytes(), sig, pubKey);
} catch (Exception e1) {
@@ -1297,7 +1333,7 @@ public class Script {
// This RuntimeException occurs when signing as we run partial/invalid scripts to see if they need more
// signing work to be done inside LocalTransactionSigner.signInputs.
if (!e1.getMessage().contains("Reached past end of ASN.1 stream"))
log.warn("Signature checking failed! {}", e1.toString());
log.warn("Signature checking failed!", e1);
}
if (opcode == OP_CHECKSIG)
@@ -1308,7 +1344,11 @@ public class Script {
}
private static int executeMultiSig(Transaction txContainingThis, int index, Script script, LinkedList<byte[]> stack,
int opCount, int lastCodeSepLocation, int opcode, boolean enforceNullDummy) throws ScriptException {
int opCount, int lastCodeSepLocation, int opcode,
Set<VerifyFlag> verifyFlags) throws ScriptException {
final boolean requireCanonical = verifyFlags.contains(VerifyFlag.STRICTENC)
|| verifyFlags.contains(VerifyFlag.DERSIG)
|| verifyFlags.contains(VerifyFlag.LOW_S);
if (stack.size() < 2)
throw new ScriptException("Attempted OP_CHECKMULTISIG(VERIFY) on a stack with size < 2");
int pubKeyCount = castToBigInteger(stack.pollLast()).intValue();
@@ -1357,7 +1397,7 @@ public class Script {
// We could reasonably move this out of the loop, but because signature verification is significantly
// more expensive than hashing, its not a big deal.
try {
TransactionSignature sig = TransactionSignature.decodeFromBitcoin(sigs.getFirst(), false);
TransactionSignature sig = TransactionSignature.decodeFromBitcoin(sigs.getFirst(), requireCanonical);
Sha256Hash hash = txContainingThis.hashForSignature(index, connectedScript, (byte) sig.sighashFlags);
if (ECKey.verify(hash.getBytes(), sig, pubKey))
sigs.pollFirst();
@@ -1374,7 +1414,7 @@ public class Script {
// We uselessly remove a stack object to emulate a reference client bug.
byte[] nullDummy = stack.pollLast();
if (enforceNullDummy && nullDummy.length > 0)
if (verifyFlags.contains(VerifyFlag.NULLDUMMY) && nullDummy.length > 0)
throw new ScriptException("OP_CHECKMULTISIG(VERIFY) with non-null nulldummy: " + Arrays.toString(nullDummy));
if (opcode == OP_CHECKMULTISIG) {
@@ -1393,7 +1433,11 @@ public class Script {
* Accessing txContainingThis from another thread while this method runs results in undefined behavior.
* @param scriptSigIndex The index in txContainingThis of the scriptSig (note: NOT the index of the scriptPubKey).
* @param scriptPubKey The connected scriptPubKey containing the conditions needed to claim the value.
* @deprecated Use {@link #correctlySpends(org.bitcoinj.core.Transaction, long, org.bitcoinj.script.Script, java.util.Set)}
* instead so that verification flags do not change as new verification options
* are added.
*/
@Deprecated
public void correctlySpends(Transaction txContainingThis, long scriptSigIndex, Script scriptPubKey)
throws ScriptException {
correctlySpends(txContainingThis, scriptSigIndex, scriptPubKey, ALL_VERIFY_FLAGS);
@@ -1423,10 +1467,10 @@ public class Script {
LinkedList<byte[]> stack = new LinkedList<byte[]>();
LinkedList<byte[]> p2shStack = null;
executeScript(txContainingThis, scriptSigIndex, this, stack, verifyFlags.contains(VerifyFlag.NULLDUMMY));
executeScript(txContainingThis, scriptSigIndex, this, stack, verifyFlags);
if (verifyFlags.contains(VerifyFlag.P2SH))
p2shStack = new LinkedList<byte[]>(stack);
executeScript(txContainingThis, scriptSigIndex, scriptPubKey, stack, verifyFlags.contains(VerifyFlag.NULLDUMMY));
executeScript(txContainingThis, scriptSigIndex, scriptPubKey, stack, verifyFlags);
if (stack.size() == 0)
throw new ScriptException("Stack empty at end of script execution.");
@@ -1455,7 +1499,7 @@ public class Script {
byte[] scriptPubKeyBytes = p2shStack.pollLast();
Script scriptPubKeyP2SH = new Script(scriptPubKeyBytes);
executeScript(txContainingThis, scriptSigIndex, scriptPubKeyP2SH, p2shStack, verifyFlags.contains(VerifyFlag.NULLDUMMY));
executeScript(txContainingThis, scriptSigIndex, scriptPubKeyP2SH, p2shStack, verifyFlags);
if (p2shStack.size() == 0)
throw new ScriptException("P2SH stack empty at end of script execution.");

View File

@@ -15,6 +15,7 @@
*/
package org.bitcoinj.signers;
import java.util.EnumSet;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.ScriptException;
import org.bitcoinj.core.Transaction;
@@ -22,6 +23,7 @@ import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.Script.VerifyFlag;
import org.bitcoinj.wallet.KeyBag;
import org.bitcoinj.wallet.RedeemData;
import org.slf4j.Logger;
@@ -42,6 +44,13 @@ import org.slf4j.LoggerFactory;
public class LocalTransactionSigner extends StatelessTransactionSigner {
private static final Logger log = LoggerFactory.getLogger(LocalTransactionSigner.class);
/**
* Verify flags that are safe to use when testing if an input is already
* signed.
*/
private static final EnumSet<VerifyFlag> MINIMUM_VERIFY_FLAGS = EnumSet.of(VerifyFlag.P2SH,
VerifyFlag.NULLDUMMY);
@Override
public boolean isReady() {
return true;
@@ -62,7 +71,7 @@ public class LocalTransactionSigner extends StatelessTransactionSigner {
// We assume if its already signed, its hopefully got a SIGHASH type that will not invalidate when
// we sign missing pieces (to check this would require either assuming any signatures are signing
// standard output types or a way to get processed signatures out of script execution)
txIn.getScriptSig().correctlySpends(tx, i, txIn.getConnectedOutput().getScriptPubKey());
txIn.getScriptSig().correctlySpends(tx, i, txIn.getConnectedOutput().getScriptPubKey(), MINIMUM_VERIFY_FLAGS);
log.warn("Input {} already correctly spends output, assuming SIGHASH type used will be safe and skipping signing.", i);
continue;
} catch (ScriptException e) {

View File

@@ -58,7 +58,7 @@ public class BlockTest {
@Test
public void testBlockVerification() throws Exception {
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(Block.VerifyFlag.class));
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
}
@@ -76,7 +76,7 @@ public class BlockTest {
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
block.setNonce(12346);
try {
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(Block.VerifyFlag.class));
fail();
} catch (VerificationException e) {
// Expected.
@@ -85,18 +85,18 @@ public class BlockTest {
// from containing artificially weak difficulties.
block.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
// Now it should pass.
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(Block.VerifyFlag.class));
// Break the nonce again at the lower difficulty level so we can try solving for it.
block.setNonce(1);
try {
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(Block.VerifyFlag.class));
fail();
} catch (VerificationException e) {
// Expected to fail as the nonce is no longer correct.
}
// Should find an acceptable nonce.
block.solve();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(Block.VerifyFlag.class));
assertEquals(block.getNonce(), 2);
}
@@ -109,7 +109,7 @@ public class BlockTest {
block.transactions.set(0, tx2);
block.transactions.set(1, tx1);
try {
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(Block.VerifyFlag.class));
fail();
} catch (VerificationException e) {
// We should get here.

View File

@@ -64,7 +64,7 @@ public class CoinbaseBlockTest {
// Check block.
assertNotNull(block);
block.verify(169482, EnumSet.noneOf(VerificationFlags.class));
block.verify(169482, EnumSet.noneOf(Block.VerifyFlag.class));
assertEquals(BLOCK_NONCE, block.getNonce());
StoredBlock storedBlock = new StoredBlock(block, BigInteger.ONE, BLOCK_OF_INTEREST); // Nonsense work - not used in test.

View File

@@ -46,6 +46,7 @@ import static org.bitcoinj.script.ScriptOpCodes.OP_0;
import static org.bitcoinj.script.ScriptOpCodes.OP_INVALIDOPCODE;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.*;
import org.junit.Before;
public class ScriptTest {
// From tx 05e04c26c12fe408a3c1b71aa7996403f6acad1045252b1c62e055496f4d2cb1 on the testnet.
@@ -58,6 +59,11 @@ public class ScriptTest {
private static final Logger log = LoggerFactory.getLogger(ScriptTest.class);
@Before
public void setUp() throws Exception {
Context context = new Context(params);
}
@Test
public void testScriptSig() throws Exception {
byte[] sigProgBytes = HEX.decode(sigProg);

View File

@@ -109,5 +109,9 @@
[[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]],
"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"],
["A transaction with a non-standard DER signature."],
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
["Make diffs cleaner by leaving a comment here without comma at the end"]
]

View File

@@ -177,6 +177,9 @@
["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]],
"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"],
["A transaction with a non-standard DER signature."],
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
["Make diffs cleaner by leaving a comment here without comma at the end"]
]