diff options
-rw-r--r-- | doc/release-notes.md | 29 | ||||
-rwxr-xr-x | qa/pull-tester/rpc-tests.sh | 1 | ||||
-rwxr-xr-x | qa/rpc-tests/mempool_resurrect_test.py | 88 | ||||
-rw-r--r-- | src/init.cpp | 10 | ||||
-rw-r--r-- | src/init.h | 6 | ||||
-rw-r--r-- | src/main.cpp | 149 | ||||
-rw-r--r-- | src/main.h | 184 | ||||
-rw-r--r-- | src/rpcblockchain.cpp | 6 | ||||
-rw-r--r-- | src/rpcserver.cpp | 2 | ||||
-rw-r--r-- | src/test/data/script_invalid.json | 98 | ||||
-rw-r--r-- | src/test/data/script_valid.json | 94 | ||||
-rw-r--r-- | src/test/script_tests.cpp | 34 |
12 files changed, 422 insertions, 279 deletions
diff --git a/doc/release-notes.md b/doc/release-notes.md index 6aaea67790..f804e8c11b 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -95,3 +95,32 @@ are done, it always returns an immediate error with code -28 to all calls. This new behaviour can be useful for clients to know that a server is already started and will be available soon (for instance, so that they do not have to start it themselves). + +Improved signing security +========================= + +For 0.10 the security of signing against unusual attacks has been +improved by making the signatures constant time and deterministic. + +This change is a result of switching signing to use libsecp256k1 +instead of OpenSSL. Libsecp256k1 is a cryptographic library +optimized for the curve Bitcoin uses which was created by Bitcoin +Core developer Pieter Wuille. + +There exist attacks[1] against most ECC implementations where an +attacker on shared virtual machine hardware could extract a private +key if they could cause a target to sign using the same key hundreds +of times. While using shared hosts and reusing keys are inadvisable +for other reasons, it's a better practice to avoid the exposure. + +OpenSSL has code in their source repository for derandomization +and reduction in timing leaks, and we've eagerly wanted to use +it for a long time but this functionality has still not made its +way into a released version of OpenSSL. Libsecp256k1 achieves +significantly stronger protection: As far as we're aware this is +the only deployed implementation of constant time signing for +the curve Bitcoin uses and we have reason to believe that +libsecp256k1 is better tested and more thoroughly reviewed +than the implementation in OpenSSL. + +[1] https://eprint.iacr.org/2014/161.pdf diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 9587d90dfe..a93b80686b 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -18,6 +18,7 @@ fi if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then ${BUILDDIR}/qa/rpc-tests/wallet.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/listtransactions.py --srcdir "${BUILDDIR}/src" + ${BUILDDIR}/qa/rpc-tests/mempool_resurrect_test.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --mineblock --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/getchaintips.py --srcdir "${BUILDDIR}/src" diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py new file mode 100755 index 0000000000..907cbf98f9 --- /dev/null +++ b/qa/rpc-tests/mempool_resurrect_test.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test resurrection of mined transactions when +# the blockchain is re-organized. +# + +from test_framework import BitcoinTestFramework +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from util import * +import os +import shutil + +# Create one-input, one-output, no-fee transaction: +class MempoolCoinbaseTest(BitcoinTestFramework): + + def setup_network(self): + # Just need one node for this test + args = ["-checkmempool", "-debug=mempool"] + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, args)) + self.is_network_split = False + + def create_tx(self, from_txid, to_address, amount): + inputs = [{ "txid" : from_txid, "vout" : 0}] + outputs = { to_address : amount } + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + signresult = self.nodes[0].signrawtransaction(rawtx) + assert_equal(signresult["complete"], True) + return signresult["hex"] + + def run_test(self): + node0_address = self.nodes[0].getnewaddress() + + # Spend block 1/2/3's coinbase transactions + # Mine a block. + # Create three more transactions, spending the spends + # Mine another block. + # ... make sure all the transactions are confirmed + # Invalidate both blocks + # ... make sure all the transactions are put back in the mempool + # Mine a new block + # ... make sure all the transactions are confirmed again. + + b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ] + coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ] + spends1_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ] + spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ] + + blocks = [] + blocks.extend(self.nodes[0].setgenerate(True, 1)) + + spends2_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in spends1_id ] + spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ] + + blocks.extend(self.nodes[0].setgenerate(True, 1)) + + # mempool should be empty, all txns confirmed + assert_equal(set(self.nodes[0].getrawmempool()), set()) + for txid in spends1_id+spends2_id: + tx = self.nodes[0].gettransaction(txid) + assert(tx["confirmations"] > 0) + + # Use invalidateblock to re-org back; all transactions should + # end up unconfirmed and back in the mempool + for node in self.nodes: + node.invalidateblock(blocks[0]) + + # mempool should be empty, all txns confirmed + assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id)) + for txid in spends1_id+spends2_id: + tx = self.nodes[0].gettransaction(txid) + assert(tx["confirmations"] == 0) + + # Generate another block, they should all get mined + self.nodes[0].setgenerate(True, 1) + # mempool should be empty, all txns confirmed + assert_equal(set(self.nodes[0].getrawmempool()), set()) + for txid in spends1_id+spends2_id: + tx = self.nodes[0].gettransaction(txid) + assert(tx["confirmations"] > 0) + + +if __name__ == '__main__': + MempoolCoinbaseTest().main() diff --git a/src/init.cpp b/src/init.cpp index 7b6ebb1b30..11329c16aa 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #if defined(HAVE_CONFIG_H) @@ -60,7 +60,7 @@ bool fFeeEstimatesInitialized = false; #define MIN_CORE_FILEDESCRIPTORS 150 #endif -// Used to pass flags to the Bind() function +/** Used to pass flags to the Bind() function */ enum BindFlags { BF_NONE = 0, BF_EXPLICIT = (1U << 0), @@ -175,9 +175,9 @@ void Shutdown() LogPrintf("%s: done\n", __func__); } -// -// Signal handlers are very limited in what they are allowed to do, so: -// +/** + * Signal handlers are very limited in what they are allowed to do, so: + */ void HandleSIGTERM(int) { fRequestShutdown = true; diff --git a/src/init.h b/src/init.h index aaf8c07e6e..f2f7ac6747 100644 --- a/src/init.h +++ b/src/init.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2013 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_INIT_H @@ -22,7 +22,7 @@ bool ShutdownRequested(); void Shutdown(); bool AppInit2(boost::thread_group& threadGroup); -/* The help message mode determines what help message to show */ +/** The help message mode determines what help message to show */ enum HelpMessageMode { HMM_BITCOIND, HMM_BITCOIN_QT diff --git a/src/main.cpp b/src/main.cpp index 0515eeb156..451d6c8cd9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "main.h" @@ -33,9 +33,9 @@ using namespace std; # error "Bitcoin cannot be compiled without assertions." #endif -// -// Global state -// +/** + * Global state + */ CCriticalSection cs_main; @@ -66,7 +66,7 @@ map<uint256, COrphanTx> mapOrphanTransactions; map<uint256, set<uint256> > mapOrphanTransactionsByPrev; void EraseOrphansFor(NodeId peer); -// Constant stuff for coinbase transactions we create: +/** Constant stuff for coinbase transactions we create: */ CScript COINBASE_FLAGS; const string strMessageMagic = "Bitcoin Signed Message:\n"; @@ -97,44 +97,49 @@ namespace { CBlockIndex *pindexBestInvalid; - // The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least - // as good as our current tip. Entries may be failed, though. + /** + * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least + * as good as our current tip. Entries may be failed, though. + */ set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; - // Number of nodes with fSyncStarted. + /** Number of nodes with fSyncStarted. */ int nSyncStarted = 0; - // All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. + /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. */ multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; CCriticalSection cs_LastBlockFile; std::vector<CBlockFileInfo> vinfoBlockFile; int nLastBlockFile = 0; - // Every received block is assigned a unique and increasing identifier, so we - // know which one to give priority in case of a fork. + /** + * Every received block is assigned a unique and increasing identifier, so we + * know which one to give priority in case of a fork. + */ CCriticalSection cs_nBlockSequenceId; - // Blocks loaded from disk are assigned id 0, so start the counter at 1. + /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ uint32_t nBlockSequenceId = 1; - // Sources of received blocks, to be able to send them reject messages or ban - // them, if processing happens afterwards. Protected by cs_main. + /** + * Sources of received blocks, to be able to send them reject messages or ban + * them, if processing happens afterwards. Protected by cs_main. + */ map<uint256, NodeId> mapBlockSource; - // Blocks that are in flight, and that are in the queue to be downloaded. - // Protected by cs_main. + /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */ struct QueuedBlock { uint256 hash; - CBlockIndex *pindex; // Optional. - int64_t nTime; // Time of "getdata" request in microseconds. + CBlockIndex *pindex; //! Optional. + int64_t nTime; //! Time of "getdata" request in microseconds. }; map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight; - // Number of preferrable block download peers. + /** Number of preferable block download peers. */ int nPreferredDownload = 0; - // Dirty block index entries. + /** Dirty block index entries. */ set<CBlockIndex*> setDirtyBlockIndex; - // Dirty block file entries. + /** Dirty block file entries. */ set<int> setDirtyFileInfo; } // anon namespace @@ -148,19 +153,19 @@ namespace { namespace { struct CMainSignals { - // Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. + /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */ boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction; - // Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). + /** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */ boost::signals2::signal<void (const uint256 &)> EraseTransaction; - // Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). + /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */ boost::signals2::signal<void (const uint256 &)> UpdatedTransaction; - // Notifies listeners of a new active block chain. + /** Notifies listeners of a new active block chain. */ boost::signals2::signal<void (const CBlockLocator &)> SetBestChain; - // Notifies listeners about an inventory item being seen on the network. + /** Notifies listeners about an inventory item being seen on the network. */ boost::signals2::signal<void (const uint256 &)> Inventory; - // Tells listeners to broadcast their data. + /** Tells listeners to broadcast their data. */ boost::signals2::signal<void ()> Broadcast; - // Notifies listeners of a block validation result + /** Notifies listeners of a block validation result */ boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; } g_signals; @@ -213,32 +218,34 @@ struct CBlockReject { uint256 hashBlock; }; -// Maintain validation-specific state about nodes, protected by cs_main, instead -// by CNode's own locks. This simplifies asynchronous operation, where -// processing of incoming data is done after the ProcessMessage call returns, -// and we're no longer holding the node's locks. +/** + * Maintain validation-specific state about nodes, protected by cs_main, instead + * by CNode's own locks. This simplifies asynchronous operation, where + * processing of incoming data is done after the ProcessMessage call returns, + * and we're no longer holding the node's locks. + */ struct CNodeState { - // Accumulated misbehaviour score for this peer. + //! Accumulated misbehaviour score for this peer. int nMisbehavior; - // Whether this peer should be disconnected and banned (unless whitelisted). + //! Whether this peer should be disconnected and banned (unless whitelisted). bool fShouldBan; - // String name of this peer (debugging/logging purposes). + //! String name of this peer (debugging/logging purposes). std::string name; - // List of asynchronously-determined block rejections to notify this peer about. + //! List of asynchronously-determined block rejections to notify this peer about. std::vector<CBlockReject> rejects; - // The best known block we know this peer has announced. + //! The best known block we know this peer has announced. CBlockIndex *pindexBestKnownBlock; - // The hash of the last unknown block this peer has announced. + //! The hash of the last unknown block this peer has announced. uint256 hashLastUnknownBlock; - // The last full block we both have. + //! The last full block we both have. CBlockIndex *pindexLastCommonBlock; - // Whether we've started headers synchronization with this peer. + //! Whether we've started headers synchronization with this peer. bool fSyncStarted; - // Since when we're stalling block download progress (in microseconds), or 0. + //! Since when we're stalling block download progress (in microseconds), or 0. int64_t nStallingSince; list<QueuedBlock> vBlocksInFlight; int nBlocksInFlight; - // Whether we consider this a preferred download peer. + //! Whether we consider this a preferred download peer. bool fPreferredDownload; CNodeState() { @@ -254,7 +261,7 @@ struct CNodeState { } }; -// Map maintaining per-node state. Requires cs_main. +/** Map maintaining per-node state. Requires cs_main. */ map<NodeId, CNodeState> mapNodeState; // Requires cs_main. @@ -708,15 +715,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) return true; } -// -// Check transaction inputs to mitigate two -// potential denial-of-service attacks: -// -// 1. scriptSigs with extra data stuffed into them, -// not consumed by scriptPubKey (or P2SH script) -// 2. P2SH scripts with a crazy number of expensive -// CHECKSIG/CHECKMULTISIG operations -// +/** + * Check transaction inputs to mitigate two + * potential denial-of-service attacks: + * + * 1. scriptSigs with extra data stuffed into them, + * not consumed by scriptPubKey (or P2SH script) + * 2. P2SH scripts with a crazy number of expensive + * CHECKSIG/CHECKMULTISIG operations + */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) { if (tx.IsCoinBase()) @@ -1054,7 +1061,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return true; } -// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock +/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) { CBlockIndex *pindexSlow = NULL; @@ -1818,7 +1825,7 @@ void FlushStateToDisk() { FlushStateToDisk(state, FLUSH_STATE_ALWAYS); } -// Update chainActive and related internal data structures. +/** Update chainActive and related internal data structures. */ void static UpdateTip(CBlockIndex *pindexNew) { chainActive.SetTip(pindexNew); @@ -1857,7 +1864,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { } } -// Disconnect chainActive's tip. +/** Disconnect chainActive's tip. */ bool static DisconnectTip(CValidationState &state) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); @@ -1904,8 +1911,10 @@ static int64_t nTimeFlush = 0; static int64_t nTimeChainState = 0; static int64_t nTimePostConnect = 0; -// Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock -// corresponding to pindexNew, to bypass loading it again from disk. +/** + * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock + * corresponding to pindexNew, to bypass loading it again from disk. + */ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { assert(pindexNew->pprev == chainActive.Tip()); mempool.check(pcoinsTip); @@ -1965,8 +1974,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * return true; } -// Return the tip of the chain with the most work in it, that isn't -// known to be invalid (it's however far from certain to be valid). +/** + * Return the tip of the chain with the most work in it, that isn't + * known to be invalid (it's however far from certain to be valid). + */ static CBlockIndex* FindMostWorkChain() { do { CBlockIndex *pindexNew = NULL; @@ -2007,7 +2018,7 @@ static CBlockIndex* FindMostWorkChain() { } while(true); } -// Delete all entries in setBlockIndexCandidates that are worse than the current tip. +/** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */ static void PruneBlockIndexCandidates() { // Note that we can't delete the current block itself, as we may need to return to it later in case a // reorganization to a better block fails. @@ -2019,8 +2030,10 @@ static void PruneBlockIndexCandidates() { assert(!setBlockIndexCandidates.empty()); } -// Try to make some progress towards making pindexMostWork the active block. -// pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. +/** + * Try to make some progress towards making pindexMostWork the active block. + * pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. + */ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) { AssertLockHeld(cs_main); bool fInvalidFound = false; @@ -2085,9 +2098,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo return true; } -// Make the best chain active, in multiple steps. The result is either failure -// or an activated best chain. pblock is either NULL or a pointer to a block -// that is already loaded (to avoid loading it again from disk). +/** + * Make the best chain active, in multiple steps. The result is either failure + * or an activated best chain. pblock is either NULL or a pointer to a block + * that is already loaded (to avoid loading it again from disk). + */ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexMostWork = NULL; @@ -2236,7 +2251,7 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block) return pindexNew; } -// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). +/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) { pindexNew->nTx = block.vtx.size(); @@ -2745,7 +2760,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve } else { // calculate left hash uint256 left = CalcHash(height-1, pos*2, vTxid), right; - // calculate right hash if not beyong the end of the array - copy left hash otherwise1 + // calculate right hash if not beyond the end of the array - copy left hash otherwise1 if (pos*2+1 < CalcTreeWidth(height-1)) right = CalcHash(height-1, pos*2+1, vTxid); else diff --git a/src/main.h b/src/main.h index caf8331ee1..ecf5489718 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2014 The Bitcoin developers -// Distributed under the MIT/X11 software license, see the accompanying +// Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_MAIN_H @@ -60,7 +60,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** The maximum allowed number of signature check operations in a block (network rule) */ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; -/** Maxiumum number of signature check operations in an IsStandard() P2SH script */ +/** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; @@ -97,7 +97,7 @@ static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024; /** Time to wait (in seconds) between writing blockchain state to disk. */ static const unsigned int DATABASE_WRITE_INTERVAL = 3600; -/** "reject" message codes **/ +/** "reject" message codes */ static const unsigned char REJECT_MALFORMED = 0x01; static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_OBSOLETE = 0x11; @@ -131,10 +131,10 @@ extern bool fIsBareMultisigStd; extern unsigned int nCoinCacheSize; extern CFeeRate minRelayTxFee; -// Best header we've seen so far (used for getheaders queries' starting points). +/** Best header we've seen so far (used for getheaders queries' starting points). */ extern CBlockIndex *pindexBestHeader; -// Minimum disk space required - used in CheckDiskSpace() +/** Minimum disk space required - used in CheckDiskSpace() */ static const uint64_t nMinDiskSpace = 52428800; /** Register a wallet to receive updates from core */ @@ -151,15 +151,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals); /** Unregister a network node */ void UnregisterNodeSignals(CNodeSignals& nodeSignals); -/** Process an incoming block. This only returns after the best known valid - block is made active. Note that it does not, however, guarantee that the - specific block passed to it has been checked for validity! - @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. - @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. - @param[in] pblock The block we want to process. - @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. - @return True if state.IsValid() -*/ +/** + * Process an incoming block. This only returns after the best known valid + * block is made active. Note that it does not, however, guarantee that the + * specific block passed to it has been checked for validity! + * + * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. + * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. + * @param[in] pblock The block we want to process. + * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. + * @return True if state.IsValid() + */ bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL); /** Check whether enough disk space is available for an incoming block */ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); @@ -245,54 +247,59 @@ struct CDiskTxPos : public CDiskBlockPos CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); -// -// Check transaction inputs, and make sure any -// pay-to-script-hash transactions are evaluating IsStandard scripts -// -// Why bother? To avoid denial-of-service attacks; an attacker -// can submit a standard HASH... OP_EQUAL transaction, -// which will get accepted into blocks. The redemption -// script can be anything; an attacker could use a very -// expensive-to-check-upon-redemption script like: -// DUP CHECKSIG DROP ... repeated 100 times... OP_1 -// +/** + * Check transaction inputs, and make sure any + * pay-to-script-hash transactions are evaluating IsStandard scripts + * + * Why bother? To avoid denial-of-service attacks; an attacker + * can submit a standard HASH... OP_EQUAL transaction, + * which will get accepted into blocks. The redemption + * script can be anything; an attacker could use a very + * expensive-to-check-upon-redemption script like: + * DUP CHECKSIG DROP ... repeated 100 times... OP_1 + */ -/** Check for standard transaction types - @param[in] mapInputs Map of previous transactions that have outputs we're spending - @return True if all inputs (scriptSigs) use only standard transaction forms -*/ +/** + * Check for standard transaction types + * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @return True if all inputs (scriptSigs) use only standard transaction forms + */ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); -/** Count ECDSA signature operations the old-fashioned (pre-0.6) way - @return number of sigops this transaction's outputs will produce when spent - @see CTransaction::FetchInputs -*/ +/** + * Count ECDSA signature operations the old-fashioned (pre-0.6) way + * @return number of sigops this transaction's outputs will produce when spent + * @see CTransaction::FetchInputs + */ unsigned int GetLegacySigOpCount(const CTransaction& tx); -/** Count ECDSA signature operations in pay-to-script-hash inputs. - - @param[in] mapInputs Map of previous transactions that have outputs we're spending - @return maximum number of sigops required to validate this transaction's inputs - @see CTransaction::FetchInputs +/** + * Count ECDSA signature operations in pay-to-script-hash inputs. + * + * @param[in] mapInputs Map of previous transactions that have outputs we're spending + * @return maximum number of sigops required to validate this transaction's inputs + * @see CTransaction::FetchInputs */ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); -// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) -// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it -// instead of being performed inline. +/** + * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) + * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it + * instead of being performed inline. + */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); -// Apply the effects of this transaction on the UTXO set represented by view +/** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); -// Context-independent validity checks +/** Context-independent validity checks */ bool CheckTransaction(const CTransaction& tx, CValidationState& state); /** Check for standard transaction types - @return True if all outputs (scriptPubKeys) use only standard transaction forms -*/ + * @return True if all outputs (scriptPubKeys) use only standard transaction forms + */ bool IsStandardTx(const CTransaction& tx, std::string& reason); bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); @@ -315,8 +322,10 @@ public: }; -/** Closure representing one script verification - * Note that this stores references to the spending transaction */ +/** + * Closure representing one script verification + * Note that this stores references to the spending transaction + */ class CScriptCheck { private: @@ -345,7 +354,7 @@ public: /** Data structure that represents a partial merkle tree. * - * It respresents a subset of the txid's of a known block, in a way that + * It represents a subset of the txid's of a known block, in a way that * allows recovery of the list of txid's and the merkle root, in an * authenticated way. * @@ -380,36 +389,38 @@ public: class CPartialMerkleTree { protected: - // the total number of transactions in the block + /** the total number of transactions in the block */ unsigned int nTransactions; - // node-is-parent-of-matched-txid bits + /** node-is-parent-of-matched-txid bits */ std::vector<bool> vBits; - // txids and internal hashes + /** txids and internal hashes */ std::vector<uint256> vHash; - // flag set when encountering invalid data + /** flag set when encountering invalid data */ bool fBad; - // helper function to efficiently calculate the number of nodes at given height in the merkle tree + /** helper function to efficiently calculate the number of nodes at given height in the merkle tree */ unsigned int CalcTreeWidth(int height) { return (nTransactions+(1 << height)-1) >> height; } - // calculate the hash of a node in the merkle tree (at leaf level: the txid's themself) + /** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */ uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid); - // recursive function that traverses tree nodes, storing the data as bits and hashes + /** recursive function that traverses tree nodes, storing the data as bits and hashes */ void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); - // recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild. - // it returns the hash of the respective node. + /** + * recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild. + * it returns the hash of the respective node. + */ uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch); public: - // serialization implementation + /** serialization implementation */ ADD_SERIALIZE_METHODS; template <typename Stream, typename Operation> @@ -432,13 +443,15 @@ public: } } - // Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them + /** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */ CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); CPartialMerkleTree(); - // extract the matching txid's represented by this partial merkle tree. - // returns the merkle root, or 0 in case of failure + /** + * extract the matching txid's represented by this partial merkle tree. + * returns the merkle root, or 0 in case of failure + */ uint256 ExtractMatches(std::vector<uint256> &vMatch); }; @@ -458,22 +471,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex); * of problems. Note that in any case, coins may be modified. */ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); -// Apply the effects of this block (with given index) on the UTXO set represented by coins +/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); -// Context-independent validity checks +/** Context-independent validity checks */ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -// Context-dependent validity checks +/** Context-dependent validity checks */ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); -// Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) +/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -// Store block on disk -// if dbp is provided, the file is known to already reside on disk +/** Store block on disk. If dbp is provided, the file is known to already reside on disk */ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); @@ -482,13 +494,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc class CBlockFileInfo { public: - unsigned int nBlocks; // number of blocks stored in file - unsigned int nSize; // number of used bytes of block file - unsigned int nUndoSize; // number of used bytes in the undo file - unsigned int nHeightFirst; // lowest height of block in file - unsigned int nHeightLast; // highest height of block in file - uint64_t nTimeFirst; // earliest time of block in file - uint64_t nTimeLast; // latest time of block in file + unsigned int nBlocks; //! number of blocks stored in file + unsigned int nSize; //! number of used bytes of block file + unsigned int nUndoSize; //! number of used bytes in the undo file + unsigned int nHeightFirst; //! lowest height of block in file + unsigned int nHeightLast; //! highest height of block in file + uint64_t nTimeFirst; //! earliest time of block in file + uint64_t nTimeLast; //! latest time of block in file ADD_SERIALIZE_METHODS; @@ -519,7 +531,7 @@ public: std::string ToString() const; - // update statistics (does not update nSize) + /** update statistics (does not update nSize) */ void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { if (nBlocks==0 || nHeightFirst > nHeightIn) nHeightFirst = nHeightIn; @@ -537,9 +549,9 @@ public: class CValidationState { private: enum mode_state { - MODE_VALID, // everything ok - MODE_INVALID, // network rule violation (DoS value may be set) - MODE_ERROR, // run-time error + MODE_VALID, //! everything ok + MODE_INVALID, //! network rule violation (DoS value may be set) + MODE_ERROR, //! run-time error } mode; int nDoS; std::string strRejectReason; @@ -634,24 +646,26 @@ struct CBlockTemplate -/** Used to relay blocks as header + vector<merkle branch> +/** + * Used to relay blocks as header + vector<merkle branch> * to filtered nodes. */ class CMerkleBlock { public: - // Public only for unit testing + /** Public only for unit testing */ CBlockHeader header; CPartialMerkleTree txn; public: - // Public only for unit testing and relay testing - // (not relayed) + /** Public only for unit testing and relay testing (not relayed) */ std::vector<std::pair<unsigned int, uint256> > vMatchedTxn; - // Create from a CBlock, filtering transactions according to filter - // Note that this will call IsRelevantAndUpdate on the filter for each transaction, - // thus the filter will likely be modified. + /** + * Create from a CBlock, filtering transactions according to filter + * Note that this will call IsRelevantAndUpdate on the filter for each transaction, + * thus the filter will likely be modified. + */ CMerkleBlock(const CBlock& block, CBloomFilter& filter); ADD_SERIALIZE_METHODS; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 045cd90ef6..924f416904 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -505,6 +505,12 @@ Value getchaintips(const Array& params, bool fHelp) " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" " }\n" "]\n" + "Possible values for status:\n" + "1. \"invalid\" This branch contains at least one invalid block\n" + "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" + "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" + "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" + "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" "\nExamples:\n" + HelpExampleCli("getchaintips", "") + HelpExampleRpc("getchaintips", "") diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 8512212185..90695611f2 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -269,6 +269,8 @@ static const CRPCCommand vRPCCommands[] = { "blockchain", "gettxout", &gettxout, true, false, false }, { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false, false }, { "blockchain", "verifychain", &verifychain, true, false, false }, + { "blockchain", "invalidateblock", &invalidateblock, true, true, false }, + { "blockchain", "reconsiderblock", &reconsiderblock, true, true, false }, /* Mining */ { "mining", "getblocktemplate", &getblocktemplate, true, false, false }, diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 71e757714c..c454b52976 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -496,177 +496,177 @@ nSequences are max. ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"], +[" +Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of +pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded +signatures and pubkeys. +"], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." +], [ - "0x47 0x30440220304eff7556bba9560df47873275e64db45f3cd735998ce3f00d2e57b1bb5f31302205c0c9d14b8b80d43e2ac9b87532f1af6d8a3271262bc694ec4e14068392bb0a001", + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." +], + +["Automatically generated test cases"], +[ + "0x47 0x3044022053205076a7bb12d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK, bad sig" ], [ - "0x47 0x3044022037fcdb8e08f41e27588de8bc036d2c4b16eb3d09c1ba53b8f47a0a9c27722a39022058664b7a53b507e71dfafb77193e3786c3f0c119d78ce9104480ee7ece04f09301 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", + "0x47 0x30440220151ea78fa148b59f399b23731b634645ebc142f299ee9838d46fb78cf7e0bc0102200d62327dcd54ac6bcfb1516b035b1bf8eaea438c52c62d3450d1f3a8f030e0de01 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", "", "P2PKH, bad pubkey" ], [ - "0x47 0x3044022035e5b6742d299861c84cebaf2ea64145ee427a95facab39e2594d6deebb0c1d602200acb16778faa2e467a59006f342f2535b1418d55ba63a8605b387b7f9ac86d9a01", + "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK anyonecanpay marked with normal hashtype" ], [ - "0x47 0x3044022029b2b8765ca950cf75a69e80b73b7ddfcaa8b27080c2db4c23b36aae60688e790220598ff368e17872ee065aa54d7d3a590682ca5204325b23b31d7da3c4a21ae67901 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "P2SH(P2PK), bad redeemscript" ], [ - "0x47 0x30440220647f906e63890df5ef1d3fed47ba892b31976c634281079e2bd38504fb54a1fb022021e8811f38fbe90efb6b74cb78da01d9badbac3bafdf70a861d7538a220d0b2601 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", + "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "P2SH", "P2SH(P2PKH), bad sig" ], [ - "0 0x47 0x304402203ef170402f8887f2ac183f31b1f503b0bc60bfc968dd469b097ea6124aefac5002200612febadc4e4cacc086982cb85830a17af3680c1b6a3cf77c1708af7621cf1301 0 0x47 0x304402207821838251a24a2234844f68e7169e6d11945cdf052ea12bd3e4e37457aceb4402200b6b46c81361e314c740ae5133c072af5fa5c209d65d2db1679e1716f19a538101", + "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3, 2 sigs" ], [ - "0 0 0x47 0x304402204661f7795e8db7be3132e8974e9a76d1d24b31f23df94c6fbcea07d1c205789102203f5e45a1c0b085279b58d11b36d5fea5449c3cf16f844ad10124e9b65e8777d201 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", + "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "P2SH(2-of-3), 1 sig" ], [ - "0x47 0x304402200052bc1600ca45c71f3538720fe62a5e8548dffd137af04467598c98466e9c0a0220789318ddbc9991ee477974089220a2feb6a6298a7c93d5ff6c25a92a2f4b48d501", + "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "STRICTENC", + "DERSIG", "P2PK with too much R padding" ], [ - "0x48 0x304502206eb7b92628bfb3c4d2a04b65b986987bcbb1af4fceedb144d5a0437b7ee410590221005f57a52df4aa26366742eed0db182fce51fbcd7159011b0644a7c05943eb228901", + "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "STRICTENC", + "DERSIG", "P2PK with too much S padding" ], [ - "0x47 0x30440220d8ad1efd55a3d2b8896495c38aba72056e1b3ca4a6ca15760e843eb1a9b9907602203eb0e8f3d6bec998262dfd03eaeb0f31c4e5105965436dec77550724b3771f3201", + "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", - "STRICTENC", + "DERSIG", "P2PK with too little R padding" ], [ - "0x47 0x30440220001d0f82c127470cb38316c96b1719b33382353687a1146a776dee8259606905022062cd1fc8eacef819d68f0f41cc9ae9fdc2e29b70c3c7ad2c6c18f39b4e35c42701", + "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", "P2PK NOT with bad sig with too much R padding" ], [ - "0x47 0x30440220005d727e2a82d6e8a98a6da6fbc281325644d1a40455e386fdb17883a8e6bc4d02202d15cca42ce136047a980d288e60c679d7e84cce18c3ceffb6bc81b9e9ba517801", + "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", "P2PK NOT with too much R padding but no DERSIG" ], [ - "0x47 0x30440220006e8bc4f82032b12bd594847c16d8b2986de734aa3b0528bd89d664d41e6d1c02200cfd582694891bcfa2e630e899bda257486eba00a007222fae71144dba07dc2901", + "0x47 0x30440220003040725f724a0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "DERSIG", "P2PK NOT with too much R padding" ], [ - "0x48 0x304502206c43e065c8a8db3bbe69015afb86a51fb2fc8870defd41d436da2a197d9d6c12022100fcec35816ee2d84ec271ad159fcabf5dd712157051169e48ac328a7818cdb51e01", + "0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "LOW_S,STRICTENC", + "LOW_S", "P2PK with high S" ], [ - "0x47 0x304402203aab50cd7c30cc1e1475dee615b295bcee6ccf8aa8a7f6cda6b696c70d79cbb40220558e43fe7596c31146e2d077698d5a9c38351d8ba567549a2ae43ca97231c39501", + "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "STRICTENC", "P2PK with hybrid pubkey" ], [ - "0x47 0x304402205745e8f846110c185ee1185c01843a108588b81463d2c34d4a3f2445529f12fe02206ee6a2657bbc4e2bb74bfc44c3a5c4f410ed6356ca68982465de6ca807c807c201", + "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", "P2PK NOT with hybrid pubkey but no STRICTENC" ], [ - "0x47 0x3044022078033e4227aa05ded69d8da579966578e230d8a7fb44d5f1a0620c3853c24f78022006a2e3f4d872ac8dfdc529110aa37301d65a76255a4b6cce2992adacd4d2c4e201", + "0x47 0x30440220606f6f9f6cebc94ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "STRICTENC", "P2PK NOT with hybrid pubkey" ], [ - "0x47 0x304402207592427de20e315d644839754f2a5cca5b978b983a15e6da82109ede01722baa022032ceaf78590faa3f7743821e1b47b897ed1a57f6ee1c8a7519d23774d8de3c4401", + "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "STRICTENC", "P2PK NOT with invalid hybrid pubkey" ], [ - "0 0x47 0x304402206797289d3dc81692edae58430276d04641ea5d86967be557163f8494da32fd78022006fc6ab77aaed4ac11ea69cd878ab26e3e24290f47a43e9adf34075d52b7142c01", + "0 0x47 0x304402203cdcf66792fe97e3955655ede5dad004950e58b369831ffa7743132c507b272c022031fbcfb4a72b3e00217abf2f5557585f1f9891f12827d2f0a2ae2978e7f9f11001", "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG", "STRICTENC", "1-of-2 with the first 1 hybrid pubkey" ], [ - "0x47 0x304402201f82b99a813c9c48c8dee8d2c43b8f637b72353fe9bdcc084537bc17e2ab770402200c43b96a5f7e115f0114eabda32e068145965cb6c7b5ef64833bb4fcf9fc1b3b05", + "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "STRICTENC", "P2PK with undefined hashtype" ], - -[" -Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of -pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded -signatures and pubkeys. -"], -[ - "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", - "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT", - "STRICTENC", - "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded." -], -[ - "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0", - "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", - "STRICTENC", - "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid." -], - [ - "0x47 0x30440220166848cd5b82a32b5944d90de3c35249354b43773c2ece1844ee8d1103e2f6c602203b6b046da4243c77adef80ada9201b27bbfdf7f9d5428f40434b060432afd62005", + "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "STRICTENC", "P2PK NOT with invalid sig and undefined hashtype" ], [ - "0x01 0x01 0x47 0x304402200e48ba1cf4d7182db94ffb57bd72ea31b5545dc0d1c512e665779b4fb2badc52022054b8388dfc074c708a75b62359b7be46402751ee40c0a111aef38a837b6ed09801 0x47 0x304402201c9820f59c49107bb30e6175cfc9ec95f897b03beb628b4bc854d2b80392aa0602200235d986ae418bcd111b8814f4c26a0ab5f475fb542a44884fc14912a97a252301 0x47 0x304402204cd7894c6f10a871f5b0c1f9c13228f8cdd4050248f0d0f498ee86be69ee3080022051bd2932c7d585eb600c7194235c74da820935f0d67972fd9545673aa1fd023301", + "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "NULLDUMMY", "3-of-3 with nonzero dummy" ], [ - "0x01 0x01 0x47 0x304402201847fc3b8f7597768e7f543c58da1fca6e8e35eb28979431e6b637572ce6eaa4022048dd58608e040841d0bf52a70cfb70e1a9c8d2826fad068f4e9d2bf5c87766a501 0x47 0x30440220711311a72516affed73363763983d05c3d6a06a2eadf5d76b90b4354162ba94302204841a69e5955a7dc8e4ab3105fd0c86040c1dac6016297a51ddbf5079c28756801 0x47 0x30440220267e331a378191e7282fd10d61c97bf74bc97c233c5833d677936424ac08dee502201eee83d88b91988e1c4d9b979df2404aa190e0987a8ca09c4e5cd61da1d48ecc01", + "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "NULLDUMMY", "3-of-3 NOT with invalid sig with nonzero dummy" ], [ - "0 0x47 0x3044022035341cc377b19138f944f90c45772cb06338c6d56a4c0c31a65bf1a8a105fadc022046dd232850b6bacb25879c9da82a7a628982aa19d055f1753468f68047662e0301 DUP", + "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", "2-of-2 with two identical keys and sigs pushed using OP_DUP" ], [ - "0x47 0x304402204d8b99eea2f53382fd67e0dbc8ed0596bd614aa0dad6bc6843c7860c79b901c3022062f022a71993013e3d9b22302a8e4b40109d7bb057aeb250b9aab2197b3e96b801 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "", "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY" ], [ - "0x47 0x30440220078c887c33abc67fbbd827ceb3f661c1c459e78218161b652f23e3ca76cfabbd022047df245eacb8a88d8c5ca7b5228e3b4d070c102d2f542433362d3f443cd24eda01 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", + "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", "SIGPUSHONLY", "P2SH(P2PK) with non-push scriptSig" diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index ada45a64ed..af0f6939c6 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -664,160 +664,158 @@ nSequences are max. ["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""], ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""], +[" +CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and +pubkeys in a specific order, and will exit early if the number of signatures +left to check is greater than the number of keys left. As STRICTENC fails the +script when it reaches an invalidly encoded signature or pubkey, we can use it +to test the exact order in which signatures and pubkeys are evaluated by +distinguishing CHECKMULTISIG returning false on the stack and the script as a +whole failing. +See also the corresponding inverted versions of these tests in script_invalid.json +"], +[ + "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey." +], +[ + "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", + "STRICTENC", + "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature." +], +["Automatically generated test cases"], [ - "0x47 0x3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501", + "0x47 0x3044022053205076a7bb13d2db3162a2d97d8197631f829b065948b7019b15482af819a902204328dcc02c994ca086b1226d0d5f1674d23cfae0d846143df812b81cab3391e801", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK" ], [ - "0x47 0x3044022069d40999786aeb2fd874f9eb2636461a062dc963471627ed8390a3a5f9556f640220350132a52415ce622f2aadd07f791c591500917ec1f8c5edbc5381ef7942534d01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", + "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", "", "P2PKH" ], [ - "0x47 0x30440220519f2a6632ffa134c7811ea2819e9dcc951f0c7baf461f2dffdd09133f3b080a02203ec6bab5eb6619ed7f41b8701d7c6d70cfc83bb26c5c97f54b2ca6e304fc2bb581", + "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK anyonecanpay" ], [ - "0x47 0x30440220279dad2170ffb5639f0a1ea71fc462ee37d75d420d86f84c978bac523c09b7f20220683b2789f5c5528a9e0a0d78f6e40db3f616cf1adb5a5fdef117d5974795cfe201 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "0x47 0x304402202166fcd5e607de452d3c6f15e059505cf21654346592f9650ba906b9e8be88fa022005d976d28eb8de477102feba28807b3ad361e7fa24796d259c9d61452f7c318c01 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", "P2SH", "P2SH(P2PK)" ], [ - "0x47 0x3044022066acbfb5ac96b7cbf3f05a2aaf358c32438c45d1d7359dee9fc1ee636940735f02205606a03fd8cbf6a6fcbcba60c8abb1e385c0b5753cb57a97538159106fd3684e01 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", + "0x47 0x3044022064cc90ca89ad721384b231653b945579359a24b928ef8539b331172628c9cc6102203e238869ab5dac3fc293db53c12e7dd3079e86cfde9024b689efc7227e4d671001 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac", "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL", "", "P2SH(P2PKH), bad sig but no VERIFY_P2SH" ], [ - "0 0x47 0x3044022004e791dd30a64c70e55e84e150c002af9feb3ce0ab1f20e86c53d1209003927502205a60453987fcd72aebaaacebc8ce4b15449cdd79e54cc82cefb83e69dbcfeabf01 0x47 0x304402201d021808ce93dd8574cc4f99ae4f11b44305528b0aecbd9f156f08315173643802200944a0ea5c884bd86180aef76d8b1e444860776b251e47d2d6c651a1c6f9930801 0x47 0x30440220446336d7b7de05ebb5683b82b05248ec7d78e88ae8d6125985f5776c887a4cf90220674ab2b2c2f954ba1cf35457d273c90d0c0c1c224d0ae128628740e81129486801", + "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3" ], [ - "0 0x47 0x30440220288b06d057cf0eac434ed0c3be9257cc0ca144dd99c11cc8f1a49467a37d8e8002203c496c72253c528e6bc81c42e683aba974d46041a96ef7b00915c863eb2a702901 0x47 0x304402207ffb4da33f40cac839a43000a187bd76a1ee5bf95e46dc1534b38bb7bd0321db022038c078f29d1831f8eb68ffdc2634c654fb01c3467b6457b98ad220653bb2478501 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", + "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x304402204511cf05e85c2be07c6c176c5338a08ed3cb34212667f39613340881169986c002207cc48b27aa3691a20706a5773ec9923cadd20fedffd00c24457d85f83f0b51fe01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", "P2SH", "P2SH(2-of-3)" ], [ - "0x47 0x30440220001fff8863c84c0efc8eea5bffb7f388313f966f23a00ad3c0acc30ff5339684022016e6d78f51a3a1c362745931ca40b24f71cba2903dbfe5a6d392a9189127d83701", + "0x47 0x30440220001d6702bfa4f49c3a2542af9b1c2844a2eaac55f86f310f42d26a5dd17d6a8002202cdadbe608c00b50dd951c6ba0877d5b07a970f3e265c18697bc413a0a86f69901", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too much R padding but no DERSIG" ], [ - "0x48 0x304502202323d56f293842b544cacedd06baafb999196dfa1c2975314848c158ac606655022100514bd98186b8a3a1cc87f4aff76aed797781389f13f50d87bf95b2df6e488fcc01", + "0x48 0x304502207d2b258e959605e2ea50b46fea1325b7391ffb0c14a5b58ef8ad3851da3644380221007e75136df5f2e38216c4338b31c97e8307102edb97d611e06914e1f8fba68ead01", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too much S padding but no DERSIG" ], [ - "0x47 0x30440220d31c24bb6c08a496e7698a08fd41975115d7b55bfaa31cb2d573e09481e59a6702206a691239996434076b78a4e1cf46fc8e993b468a9c77fb1832186aa8040a61a201", + "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "", "P2PK with too little R padding but no DERSIG" ], [ - "0x47 0x30440220007c2cc7aef1801c2937447703c87ef2a3744209ad98da2abadd4ba8bb2e3ea00220503a275582c9f9e9ff30260c81b7f64b8b696f22105605cc8241fb76a797316201", + "0x47 0x30440220003040725f724b0e2142fc44ac71f6e13161f6410aeb6dee477952ede3b6a6ca022041ff4940ee3d88116ad281d7cc556e1f2c9427d82290bd7974a25addbcd5bede01", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT", "", "P2PK NOT with bad sig with too much R padding but no DERSIG" ], [ - "0x48 0x3045022021bf9184d94f208ac9f4757ebca9b1cbebf008cfc244fe5be1360b1b9aba0e92022100e55074f72f3a1bfddf2ea4ea7ba984f78822e136fe04c8f9c1363238e0233bd801", + "0x49 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef05101", "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG", - "STRICTENC", + "", "P2PK with high S but no LOW_S" ], [ - "0x47 0x304402202163bc732c21b7de0251297d3c6c2ece182782e85fc5e19d6036f1130a79051e022033827811634924ebba68767537d78dd7bd9109ae2a89a60587927abdc25eb06401", + "0x47 0x30440220745d63eb70d45652128b450aa5ca7d9b513439963f261cb1c40a60f0785e7ee402204877785b38945ca9dbec78e1c1d4dd12148cc25c868bd27480023b49ae0f310501", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "", "P2PK with hybrid pubkey but no STRICTENC" ], [ - "0x47 0x3044022078d6c447887e88dcbe1bc5b613645280df6f4e5935648bc226e9d91da71b3216022047d6b7ef0949b228fc1b359afb8d50500268711354298217b983c26970790c7601", + "0x47 0x30440220606f6f9f6cebc84ebfb6a4bff0b682bd99f05511295545ce9b275e98be3c946102206871d6a76f4e1b43d9763cfc5647844e4811682b1cab0325f060f44ddf44002201", "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", "", "P2PK NOT with invalid hybrid pubkey but no STRICTENC" ], [ - "0 0x47 0x304402203b269b9fbc0936877bf855b5fb41757218d9548b246370d991442a5f5bd1c3440220235268a4eaa8c67e543c6e37da81dd36d3b1be2de6b4fef04113389ca6ddc04501", + "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", "1-of-2 with the second 1 hybrid pubkey and no STRICTENC" ], [ - "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", + "0 0x47 0x304402203a5ee39032637c431af0a3ac42e32e0627390bd44f6f98c9c04e6d714635ad0202207b42fcd889c3ae8a1b515608f38535f1f9be815176ee8d1b65a27c767cf37aed01", "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "STRICTENC", "1-of-2 with the second 1 hybrid pubkey" ], - -[" -CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and -pubkeys in a specific order, and will exit early if the number of signatures -left to check is greater than the number of keys left. As STRICTENC fails the -script when it reaches an invalidly encoded signature or pubkey, we can use it -to test the exact order in which signatures and pubkeys are evaluated by -distinguishing CHECKMULTISIG returning false on the stack and the script as a -whole failing. - -See also the corresponding inverted versions of these tests in script_invalid.json -"], -[ - "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", - "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", - "STRICTENC", - "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey." -], -[ - "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501", - "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT", - "STRICTENC", - "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature." -], - [ - "0x47 0x304402204649e9517ef0377a8f8270bd423053fd98ddff62d74ea553e9579558abbb75e4022044a2b2344469c12e35ed898987711272b634733dd0f5e051288eceb04bd4669e05", + "0x47 0x304402201c215cb13e4954e60ce4f6de74941904c771f998de7b1d9627e82a1949fde517022031c2197455f3dbecbb78321201308d7b039424e38d480772d7cd4eb465a083f405", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", "", "P2PK with undefined hashtype but no STRICTENC" ], [ - "0x47 0x304402207f1cf1866a2df0bb4b8d84d0ade72aa3abb6aaab0639d608b23d9e10ead0c48202203caa97f22c3439443eea4b89f7f6729854df0f567a8184d6ecc6e8b6c68c3e9d05", + "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05", "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT", "", "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC" ], [ - "1 0x47 0x3044022046ce33d1771b0127dd4c4cef8fdc3218ebdfa60e3793ed700292d8ebd93fb1f402201029d47a414db83e96e31443c2d8b552f971469c4800f5eff7df2f0648521aed01 0x47 0x304402205c53911ad55b054920043962bbda98cf6e57e2db1cd5611138251490baabaa8702201dc80dfceae6007e7772dc13ff6e7ca66a983cb017fe5d46d30118462d83bcf801 0x47 0x304402201937e44a4ec12364f9d32f9d25e7ecbc68aee9ef90069af80efef4c05f6ace9602206c515101c00c75710b32ff7ff8dbaf7c9a0be6e86ed14a0755b47626604f31fd01", + "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402206d32e6d6b131ef2fe77b6a9b90b120d74e3e238e79dcffb10523a6ec94f93d65022067ae8772632ddf4c389258c6b70ed0ff94f20ee8f60207aa192a52a2469cddd901 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", "", "3-of-3 with nonzero dummy but no NULLDUMMY" ], [ - "1 0x47 0x30440220195038dbc6b2ae1199f86a6777824f7c5149789d85f655a3534a4422b8fba38c02204df9db87d2eb9fe06edc66870d9ac4c9ce673459f9d43cee0347ce4ffb02ee5a01 0x47 0x3044022010a45f30c6fa97a186eba9e6b595ab87d3dfcbf05dcaf1f1b8e3e7bf39515bb802203474e78d3d372e5f5c0f8c257ce8300c4bb8f37c51d4a894e11a91b5817da6ed01 0x47 0x30440220039cffd8e39850f95112662b1220b14b3c0d3d8a2772e13c947bfbf96345a64e02204154bfa77e2c0134d5434353bed82141e5da1cc479954aa288d5f0671480a04b01", + "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01", "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT", "", "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY" ], [ - "0 0x47 0x3044022002a27769ee33db258bdf7a3792e7da4143ec4001b551f73e6a190b8d1bde449d02206742c56ccd94a7a2e16ca52fc1ae4a0aa122b0014a867a80de104f9cb18e472c01 DUP", + "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 DUP", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "", "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY" ], [ - "0 0x47 0x304402203acf75dd59bbef171aeeedae4f1020b824195820db82575c2b323b8899f95de9022067df297d3a5fad049ba0bb81255d0e495643cbcf9abae9e396988618bc0c6dfe01 0x47 0x304402205f8b859230c1cab7d4e8de38ff244d2ebe046b64e8d3f4219b01e483c203490a022071bdc488e31b557f7d9e5c8a8bec90dc92289ca70fa317685f4f140e38b30c4601", + "0 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01 0x47 0x304402206cb053202e1501e6faa24e6e309bf46a2f9255aa9484ff4a26efb7434f78a58a0220132b10419c3b99601f154bf86cf12259aacd8c6f363a73dacb1d0b941680bb4c01", "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG", "SIGPUSHONLY", "2-of-2 with two identical keys and sigs pushed" diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 53411190eb..4d2a9aff45 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -491,24 +491,18 @@ BOOST_AUTO_TEST_CASE(script_build) ).Num(0).PushSig(keys.key1).PushSig(keys.key1)); - std::map<std::string, Array> tests_good; - std::map<std::string, Array> tests_bad; + std::set<std::string> tests_good; + std::set<std::string> tests_bad; { Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); BOOST_FOREACH(Value& tv, json_good) { - Array test = tv.get_array(); - if (test.size() >= 4) { - tests_good[test[3].get_str()] = test; - } + tests_good.insert(write_string(Value(tv.get_array()), true)); } BOOST_FOREACH(Value& tv, json_bad) { - Array test = tv.get_array(); - if (test.size() >= 4) { - tests_bad[test[3].get_str()] = test; - } + tests_bad.insert(write_string(Value(tv.get_array()), true)); } } @@ -517,27 +511,23 @@ BOOST_AUTO_TEST_CASE(script_build) BOOST_FOREACH(TestBuilder& test, good) { test.Test(true); - if (tests_good.count(test.GetComment()) == 0) { + std::string str = write_string(Value(test.GetJSON()), true); #ifndef UPDATE_JSON_TESTS + if (tests_good.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment()); -#endif - strGood += write_string(Value(test.GetJSON()), true) + ",\n"; - } else { - BOOST_CHECK_MESSAGE(ParseScript(tests_good[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_valid test: " + test.GetComment()); - strGood += write_string(Value(tests_good[test.GetComment()]), true) + ",\n"; } +#endif + strGood += str + ",\n"; } BOOST_FOREACH(TestBuilder& test, bad) { test.Test(false); - if (tests_bad.count(test.GetComment()) == 0) { + std::string str = write_string(Value(test.GetJSON()), true); #ifndef UPDATE_JSON_TESTS + if (tests_bad.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment()); -#endif - strBad += write_string(Value(test.GetJSON()), true) + ",\n"; - } else { - BOOST_CHECK_MESSAGE(ParseScript(tests_bad[test.GetComment()][1].get_str()) == test.GetScriptPubKey(), "ScriptPubKey mismatch in auto script_invalid test: " + test.GetComment()); - strBad += write_string(Value(tests_bad[test.GetComment()]), true) + ",\n"; } +#endif + strBad += str + ",\n"; } #ifdef UPDATE_JSON_TESTS |