2020-04-16 13:14:08 -04:00
// Copyright (c) 2011-2020 The Bitcoin Core developers
2014-10-08 20:29:45 -03:00
// Distributed under the MIT software license, see the accompanying
2014-03-18 06:11:00 -03:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2017-08-15 16:22:09 -03:00
# include <test/data/script_tests.json.h>
2017-11-09 21:57:53 -03:00
# include <core_io.h>
2020-09-16 01:00:43 -03:00
# include <fs.h>
2017-11-09 21:57:53 -03:00
# include <key.h>
2020-04-16 13:11:54 -04:00
# include <rpc/util.h>
2017-11-09 21:57:53 -03:00
# include <script/script.h>
# include <script/script_error.h>
2020-09-16 01:00:43 -03:00
# include <script/sigcache.h>
2017-11-09 21:57:53 -03:00
# include <script/sign.h>
2019-06-06 16:52:24 -04:00
# include <script/signingprovider.h>
2019-06-24 11:22:28 -04:00
# include <streams.h>
2020-04-16 13:11:54 -04:00
# include <test/util/setup_common.h>
# include <test/util/transaction_utils.h>
# include <util/strencodings.h>
# include <util/system.h>
2013-04-13 02:13:08 -03:00
2014-10-14 19:23:46 -03:00
# if defined(HAVE_CONSENSUS_LIB)
2017-11-09 21:57:53 -03:00
# include <script/bitcoinconsensus.h>
2014-10-14 19:23:46 -03:00
# endif
2013-04-13 02:13:08 -03:00
# include <stdint.h>
# include <string>
2011-07-31 14:01:31 -04:00
# include <vector>
2013-04-13 02:13:08 -03:00
2012-04-26 12:20:44 -03:00
# include <boost/test/unit_test.hpp>
2015-05-18 09:02:18 -03:00
2015-09-04 11:11:34 -03:00
# include <univalue.h>
2011-07-31 14:01:31 -04:00
2014-10-06 21:22:47 -03:00
// Uncomment if you want to output updated JSON tests.
// #define UPDATE_JSON_TESTS
2017-03-03 12:20:33 -03:00
static const unsigned int gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC ;
2011-07-31 14:01:31 -04:00
2016-12-05 04:03:53 -03:00
unsigned int ParseScriptFlags ( std : : string strFlags ) ;
std : : string FormatScriptFlags ( unsigned int flags ) ;
2014-09-08 16:15:31 -03:00
2015-05-18 09:02:18 -03:00
UniValue
2013-09-10 16:18:09 -03:00
read_json ( const std : : string & jsondata )
2012-04-17 18:57:06 -03:00
{
2015-05-18 09:02:18 -03:00
UniValue v ;
2013-09-10 16:18:09 -03:00
2014-08-20 15:15:16 -04:00
if ( ! v . read ( jsondata ) | | ! v . isArray ( ) )
2012-04-17 18:57:06 -03:00
{
2013-09-10 16:18:09 -03:00
BOOST_ERROR ( " Parse error. " ) ;
2015-05-18 09:02:18 -03:00
return UniValue ( UniValue : : VARR ) ;
2012-04-17 18:57:06 -03:00
}
return v . get_array ( ) ;
}
2016-02-11 12:38:16 -03:00
struct ScriptErrorDesc
{
ScriptError_t err ;
const char * name ;
} ;
static ScriptErrorDesc script_errors [ ] = {
{ SCRIPT_ERR_OK , " OK " } ,
{ SCRIPT_ERR_UNKNOWN_ERROR , " UNKNOWN_ERROR " } ,
{ SCRIPT_ERR_EVAL_FALSE , " EVAL_FALSE " } ,
{ SCRIPT_ERR_OP_RETURN , " OP_RETURN " } ,
{ SCRIPT_ERR_SCRIPT_SIZE , " SCRIPT_SIZE " } ,
{ SCRIPT_ERR_PUSH_SIZE , " PUSH_SIZE " } ,
{ SCRIPT_ERR_OP_COUNT , " OP_COUNT " } ,
{ SCRIPT_ERR_STACK_SIZE , " STACK_SIZE " } ,
{ SCRIPT_ERR_SIG_COUNT , " SIG_COUNT " } ,
{ SCRIPT_ERR_PUBKEY_COUNT , " PUBKEY_COUNT " } ,
{ SCRIPT_ERR_VERIFY , " VERIFY " } ,
{ SCRIPT_ERR_EQUALVERIFY , " EQUALVERIFY " } ,
{ SCRIPT_ERR_CHECKMULTISIGVERIFY , " CHECKMULTISIGVERIFY " } ,
{ SCRIPT_ERR_CHECKSIGVERIFY , " CHECKSIGVERIFY " } ,
{ SCRIPT_ERR_NUMEQUALVERIFY , " NUMEQUALVERIFY " } ,
{ SCRIPT_ERR_BAD_OPCODE , " BAD_OPCODE " } ,
{ SCRIPT_ERR_DISABLED_OPCODE , " DISABLED_OPCODE " } ,
{ SCRIPT_ERR_INVALID_STACK_OPERATION , " INVALID_STACK_OPERATION " } ,
{ SCRIPT_ERR_INVALID_ALTSTACK_OPERATION , " INVALID_ALTSTACK_OPERATION " } ,
{ SCRIPT_ERR_UNBALANCED_CONDITIONAL , " UNBALANCED_CONDITIONAL " } ,
{ SCRIPT_ERR_NEGATIVE_LOCKTIME , " NEGATIVE_LOCKTIME " } ,
{ SCRIPT_ERR_UNSATISFIED_LOCKTIME , " UNSATISFIED_LOCKTIME " } ,
{ SCRIPT_ERR_SIG_HASHTYPE , " SIG_HASHTYPE " } ,
{ SCRIPT_ERR_SIG_DER , " SIG_DER " } ,
{ SCRIPT_ERR_MINIMALDATA , " MINIMALDATA " } ,
{ SCRIPT_ERR_SIG_PUSHONLY , " SIG_PUSHONLY " } ,
{ SCRIPT_ERR_SIG_HIGH_S , " SIG_HIGH_S " } ,
{ SCRIPT_ERR_SIG_NULLDUMMY , " SIG_NULLDUMMY " } ,
{ SCRIPT_ERR_PUBKEYTYPE , " PUBKEYTYPE " } ,
{ SCRIPT_ERR_CLEANSTACK , " CLEANSTACK " } ,
2016-09-23 02:06:45 -03:00
{ SCRIPT_ERR_MINIMALIF , " MINIMALIF " } ,
2016-09-22 04:06:54 -03:00
{ SCRIPT_ERR_SIG_NULLFAIL , " NULLFAIL " } ,
2016-04-04 11:01:27 -03:00
{ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS , " DISCOURAGE_UPGRADABLE_NOPS " } ,
{ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM , " DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM " } ,
{ SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH , " WITNESS_PROGRAM_WRONG_LENGTH " } ,
{ SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY , " WITNESS_PROGRAM_WITNESS_EMPTY " } ,
{ SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH , " WITNESS_PROGRAM_MISMATCH " } ,
{ SCRIPT_ERR_WITNESS_MALLEATED , " WITNESS_MALLEATED " } ,
{ SCRIPT_ERR_WITNESS_MALLEATED_P2SH , " WITNESS_MALLEATED_P2SH " } ,
{ SCRIPT_ERR_WITNESS_UNEXPECTED , " WITNESS_UNEXPECTED " } ,
2016-10-01 14:19:33 -03:00
{ SCRIPT_ERR_WITNESS_PUBKEYTYPE , " WITNESS_PUBKEYTYPE " } ,
2018-04-26 16:56:29 -03:00
{ SCRIPT_ERR_OP_CODESEPARATOR , " OP_CODESEPARATOR " } ,
{ SCRIPT_ERR_SIG_FINDANDDELETE , " SIG_FINDANDDELETE " } ,
2016-02-11 12:38:16 -03:00
} ;
2020-05-18 04:14:10 -04:00
static std : : string FormatScriptError ( ScriptError_t err )
2016-02-11 12:38:16 -03:00
{
2020-10-26 10:27:46 -03:00
for ( const auto & se : script_errors )
if ( se . err = = err )
return se . name ;
2016-02-11 12:38:16 -03:00
BOOST_ERROR ( " Unknown scripterror enumeration value, update script_errors in script_tests.cpp. " ) ;
return " " ;
}
2020-10-26 10:27:46 -03:00
static ScriptError_t ParseScriptError ( const std : : string & name )
2016-02-11 12:38:16 -03:00
{
2020-10-26 10:27:46 -03:00
for ( const auto & se : script_errors )
if ( se . name = = name )
return se . err ;
2016-02-11 12:38:16 -03:00
BOOST_ERROR ( " Unknown scripterror \" " < < name < < " \" in test description " ) ;
return SCRIPT_ERR_UNKNOWN_ERROR ;
}
2015-03-12 05:34:42 -03:00
BOOST_FIXTURE_TEST_SUITE ( script_tests , BasicTestingSetup )
2011-07-31 14:01:31 -04:00
2016-05-22 07:35:43 -04:00
void DoTest ( const CScript & scriptPubKey , const CScript & scriptSig , const CScriptWitness & scriptWitness , int flags , const std : : string & message , int scriptError , CAmount nValue = 0 )
2014-09-19 22:13:04 -03:00
{
2016-04-05 10:50:17 -03:00
bool expect = ( scriptError = = SCRIPT_ERR_OK ) ;
2015-11-07 21:16:45 -03:00
if ( flags & SCRIPT_VERIFY_CLEANSTACK ) {
flags | = SCRIPT_VERIFY_P2SH ;
flags | = SCRIPT_VERIFY_WITNESS ;
}
2014-11-13 16:27:38 -03:00
ScriptError err ;
2018-05-04 18:38:49 -03:00
const CTransaction txCredit { BuildCreditingTransaction ( scriptPubKey , nValue ) } ;
2016-04-04 11:01:27 -03:00
CMutableTransaction tx = BuildSpendingTransaction ( scriptSig , scriptWitness , txCredit ) ;
2014-10-14 19:23:46 -03:00
CMutableTransaction tx2 = tx ;
2016-04-04 11:01:27 -03:00
BOOST_CHECK_MESSAGE ( VerifyScript ( scriptSig , scriptPubKey , & scriptWitness , flags , MutableTransactionSignatureChecker ( & tx , 0 , txCredit . vout [ 0 ] . nValue ) , & err ) = = expect , message ) ;
2020-05-18 04:14:10 -04:00
BOOST_CHECK_MESSAGE ( err = = scriptError , FormatScriptError ( err ) + " where " + FormatScriptError ( ( ScriptError_t ) scriptError ) + " expected: " + message ) ;
2017-06-28 19:29:14 -04:00
// Verify that removing flags from a passing test or adding flags to a failing test does not change the result.
for ( int i = 0 ; i < 16 ; + + i ) {
int extra_flags = InsecureRandBits ( 16 ) ;
int combined_flags = expect ? ( flags & ~ extra_flags ) : ( flags | extra_flags ) ;
// Weed out some invalid flag combinations.
if ( combined_flags & SCRIPT_VERIFY_CLEANSTACK & & ~ combined_flags & ( SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS ) ) continue ;
if ( combined_flags & SCRIPT_VERIFY_WITNESS & & ~ combined_flags & SCRIPT_VERIFY_P2SH ) continue ;
BOOST_CHECK_MESSAGE ( VerifyScript ( scriptSig , scriptPubKey , & scriptWitness , combined_flags , MutableTransactionSignatureChecker ( & tx , 0 , txCredit . vout [ 0 ] . nValue ) , & err ) = = expect , message + strprintf ( " (with flags %x) " , combined_flags ) ) ;
}
2014-10-14 19:23:46 -03:00
# if defined(HAVE_CONSENSUS_LIB)
2016-04-05 08:37:24 -03:00
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
2014-10-14 19:23:46 -03:00
stream < < tx2 ;
2016-10-20 03:30:03 -03:00
int libconsensus_flags = flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL ;
if ( libconsensus_flags = = flags ) {
2018-09-05 10:08:58 -03:00
int expectedSuccessCode = expect ? 1 : 0 ;
2016-10-20 03:30:03 -03:00
if ( flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS ) {
2018-09-05 10:08:58 -03:00
BOOST_CHECK_MESSAGE ( bitcoinconsensus_verify_script_with_amount ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , txCredit . vout [ 0 ] . nValue , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , 0 , libconsensus_flags , nullptr ) = = expectedSuccessCode , message ) ;
2016-10-20 03:30:03 -03:00
} else {
2018-09-05 10:08:58 -03:00
BOOST_CHECK_MESSAGE ( bitcoinconsensus_verify_script_with_amount ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , 0 , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , 0 , libconsensus_flags , nullptr ) = = expectedSuccessCode , message ) ;
BOOST_CHECK_MESSAGE ( bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , 0 , libconsensus_flags , nullptr ) = = expectedSuccessCode , message ) ;
2016-10-20 03:30:03 -03:00
}
2016-01-24 13:29:39 -03:00
}
2014-10-14 19:23:46 -03:00
# endif
2014-09-19 22:13:04 -03:00
}
2014-11-05 15:53:59 -03:00
void static NegateSignatureS ( std : : vector < unsigned char > & vchSig ) {
// Parse the signature.
std : : vector < unsigned char > r , s ;
r = std : : vector < unsigned char > ( vchSig . begin ( ) + 4 , vchSig . begin ( ) + 4 + vchSig [ 3 ] ) ;
s = std : : vector < unsigned char > ( vchSig . begin ( ) + 6 + vchSig [ 3 ] , vchSig . begin ( ) + 6 + vchSig [ 3 ] + vchSig [ 5 + vchSig [ 3 ] ] ) ;
// Really ugly to implement mod-n negation here, but it would be feature creep to expose such functionality from libsecp256k1.
static const unsigned char order [ 33 ] = {
0x00 ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFE ,
0xBA , 0xAE , 0xDC , 0xE6 , 0xAF , 0x48 , 0xA0 , 0x3B ,
0xBF , 0xD2 , 0x5E , 0x8C , 0xD0 , 0x36 , 0x41 , 0x41
} ;
while ( s . size ( ) < 33 ) {
s . insert ( s . begin ( ) , 0x00 ) ;
}
int carry = 0 ;
for ( int p = 32 ; p > = 1 ; p - - ) {
int n = ( int ) order [ p ] - s [ p ] - carry ;
s [ p ] = ( n + 256 ) & 0xFF ;
carry = ( n < 0 ) ;
}
assert ( carry = = 0 ) ;
if ( s . size ( ) > 1 & & s [ 0 ] = = 0 & & s [ 1 ] < 0x80 ) {
s . erase ( s . begin ( ) ) ;
}
// Reconstruct the signature.
vchSig . clear ( ) ;
vchSig . push_back ( 0x30 ) ;
vchSig . push_back ( 4 + r . size ( ) + s . size ( ) ) ;
vchSig . push_back ( 0x02 ) ;
vchSig . push_back ( r . size ( ) ) ;
vchSig . insert ( vchSig . end ( ) , r . begin ( ) , r . end ( ) ) ;
vchSig . push_back ( 0x02 ) ;
vchSig . push_back ( s . size ( ) ) ;
vchSig . insert ( vchSig . end ( ) , s . begin ( ) , s . end ( ) ) ;
}
2014-09-19 22:13:04 -03:00
namespace
{
const unsigned char vchKey0 [ 32 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 } ;
const unsigned char vchKey1 [ 32 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 } ;
const unsigned char vchKey2 [ 32 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 } ;
struct KeyData
{
CKey key0 , key0C , key1 , key1C , key2 , key2C ;
CPubKey pubkey0 , pubkey0C , pubkey0H ;
CPubKey pubkey1 , pubkey1C ;
CPubKey pubkey2 , pubkey2C ;
KeyData ( )
{
2014-09-29 14:16:24 -03:00
key0 . Set ( vchKey0 , vchKey0 + 32 , false ) ;
key0C . Set ( vchKey0 , vchKey0 + 32 , true ) ;
2014-09-19 22:13:04 -03:00
pubkey0 = key0 . GetPubKey ( ) ;
pubkey0H = key0 . GetPubKey ( ) ;
pubkey0C = key0C . GetPubKey ( ) ;
* const_cast < unsigned char * > ( & pubkey0H [ 0 ] ) = 0x06 | ( pubkey0H [ 64 ] & 1 ) ;
2014-09-29 14:16:24 -03:00
key1 . Set ( vchKey1 , vchKey1 + 32 , false ) ;
key1C . Set ( vchKey1 , vchKey1 + 32 , true ) ;
2014-09-19 22:13:04 -03:00
pubkey1 = key1 . GetPubKey ( ) ;
pubkey1C = key1C . GetPubKey ( ) ;
2014-09-29 14:16:24 -03:00
key2 . Set ( vchKey2 , vchKey2 + 32 , false ) ;
key2C . Set ( vchKey2 , vchKey2 + 32 , true ) ;
2014-09-19 22:13:04 -03:00
pubkey2 = key2 . GetPubKey ( ) ;
pubkey2C = key2C . GetPubKey ( ) ;
}
} ;
2018-03-09 11:03:40 -03:00
enum class WitnessMode {
NONE ,
PKH ,
SH
2016-04-05 08:37:24 -03:00
} ;
2014-09-19 22:13:04 -03:00
class TestBuilder
{
private :
2016-04-05 08:37:24 -03:00
//! Actually executed script
CScript script ;
//! The P2SH redeemscript
CScript redeemscript ;
//! The Witness embedded script
CScript witscript ;
CScriptWitness scriptWitness ;
2016-11-11 21:23:17 -03:00
CTransactionRef creditTx ;
2014-09-19 22:13:04 -03:00
CMutableTransaction spendTx ;
bool havePush ;
std : : vector < unsigned char > push ;
std : : string comment ;
int flags ;
2016-02-11 12:38:16 -03:00
int scriptError ;
2016-05-22 07:35:43 -04:00
CAmount nValue ;
2014-09-19 22:13:04 -03:00
void DoPush ( )
{
if ( havePush ) {
spendTx . vin [ 0 ] . scriptSig < < push ;
havePush = false ;
}
}
void DoPush ( const std : : vector < unsigned char > & data )
{
2020-04-12 23:03:10 -04:00
DoPush ( ) ;
push = data ;
havePush = true ;
2014-09-19 22:13:04 -03:00
}
public :
2018-03-09 11:03:40 -03:00
TestBuilder ( const CScript & script_ , const std : : string & comment_ , int flags_ , bool P2SH = false , WitnessMode wm = WitnessMode : : NONE , int witnessversion = 0 , CAmount nValue_ = 0 ) : script ( script_ ) , havePush ( false ) , comment ( comment_ ) , flags ( flags_ ) , scriptError ( SCRIPT_ERR_OK ) , nValue ( nValue_ )
2014-09-19 22:13:04 -03:00
{
2016-04-05 08:37:24 -03:00
CScript scriptPubKey = script ;
2018-03-09 11:03:40 -03:00
if ( wm = = WitnessMode : : PKH ) {
2016-04-05 08:37:24 -03:00
uint160 hash ;
2020-06-18 20:19:46 -04:00
CHash160 ( ) . Write ( MakeSpan ( script ) . subspan ( 1 ) ) . Finalize ( hash ) ;
2016-04-05 08:37:24 -03:00
script = CScript ( ) < < OP_DUP < < OP_HASH160 < < ToByteVector ( hash ) < < OP_EQUALVERIFY < < OP_CHECKSIG ;
2016-04-08 22:02:24 -03:00
scriptPubKey = CScript ( ) < < witnessversion < < ToByteVector ( hash ) ;
2018-03-09 11:03:40 -03:00
} else if ( wm = = WitnessMode : : SH ) {
2016-04-05 08:37:24 -03:00
witscript = scriptPubKey ;
uint256 hash ;
CSHA256 ( ) . Write ( & witscript [ 0 ] , witscript . size ( ) ) . Finalize ( hash . begin ( ) ) ;
2016-04-08 22:02:24 -03:00
scriptPubKey = CScript ( ) < < witnessversion < < ToByteVector ( hash ) ;
2016-04-05 08:37:24 -03:00
}
2014-09-19 22:13:04 -03:00
if ( P2SH ) {
2016-04-05 08:37:24 -03:00
redeemscript = scriptPubKey ;
scriptPubKey = CScript ( ) < < OP_HASH160 < < ToByteVector ( CScriptID ( redeemscript ) ) < < OP_EQUAL ;
2014-09-19 22:13:04 -03:00
}
2016-11-11 21:23:17 -03:00
creditTx = MakeTransactionRef ( BuildCreditingTransaction ( scriptPubKey , nValue ) ) ;
spendTx = BuildSpendingTransaction ( CScript ( ) , CScriptWitness ( ) , * creditTx ) ;
2014-09-19 22:13:04 -03:00
}
2016-02-11 12:38:16 -03:00
TestBuilder & ScriptError ( ScriptError_t err )
{
scriptError = err ;
return * this ;
}
2020-04-12 23:03:10 -04:00
TestBuilder & Opcode ( const opcodetype & _op )
2014-09-19 22:13:04 -03:00
{
2014-10-08 20:29:45 -03:00
DoPush ( ) ;
2020-04-12 23:03:10 -04:00
spendTx . vin [ 0 ] . scriptSig < < _op ;
2014-09-19 22:13:04 -03:00
return * this ;
}
TestBuilder & Num ( int num )
{
2014-10-08 20:29:45 -03:00
DoPush ( ) ;
2014-10-08 22:48:59 -03:00
spendTx . vin [ 0 ] . scriptSig < < num ;
2014-09-19 22:13:04 -03:00
return * this ;
}
TestBuilder & Push ( const std : : string & hex )
{
DoPush ( ParseHex ( hex ) ) ;
return * this ;
}
2020-04-12 23:03:10 -04:00
TestBuilder & Push ( const CScript & _script )
{
DoPush ( std : : vector < unsigned char > ( _script . begin ( ) , _script . end ( ) ) ) ;
2016-04-08 22:02:24 -03:00
return * this ;
}
2018-03-09 11:03:40 -03:00
TestBuilder & PushSig ( const CKey & key , int nHashType = SIGHASH_ALL , unsigned int lenR = 32 , unsigned int lenS = 32 , SigVersion sigversion = SigVersion : : BASE , CAmount amount = 0 )
2014-09-19 22:13:04 -03:00
{
2016-05-22 07:35:43 -04:00
uint256 hash = SignatureHash ( script , spendTx , 0 , nHashType , amount , sigversion ) ;
2014-09-19 22:13:04 -03:00
std : : vector < unsigned char > vchSig , r , s ;
2014-11-06 11:54:50 -03:00
uint32_t iter = 0 ;
2014-09-19 22:13:04 -03:00
do {
2018-07-14 19:03:28 -04:00
key . Sign ( hash , vchSig , false , iter + + ) ;
2014-11-05 15:53:59 -03:00
if ( ( lenS = = 33 ) ! = ( vchSig [ 5 + vchSig [ 3 ] ] = = 33 ) ) {
NegateSignatureS ( vchSig ) ;
}
2014-09-29 14:16:24 -03:00
r = std : : vector < unsigned char > ( vchSig . begin ( ) + 4 , vchSig . begin ( ) + 4 + vchSig [ 3 ] ) ;
s = std : : vector < unsigned char > ( vchSig . begin ( ) + 6 + vchSig [ 3 ] , vchSig . begin ( ) + 6 + vchSig [ 3 ] + vchSig [ 5 + vchSig [ 3 ] ] ) ;
2014-09-19 22:13:04 -03:00
} while ( lenR ! = r . size ( ) | | lenS ! = s . size ( ) ) ;
vchSig . push_back ( static_cast < unsigned char > ( nHashType ) ) ;
DoPush ( vchSig ) ;
return * this ;
}
2018-03-09 11:03:40 -03:00
TestBuilder & PushWitSig ( const CKey & key , CAmount amount = - 1 , int nHashType = SIGHASH_ALL , unsigned int lenR = 32 , unsigned int lenS = 32 , SigVersion sigversion = SigVersion : : WITNESS_V0 )
2016-04-05 08:37:24 -03:00
{
2016-05-22 07:35:43 -04:00
if ( amount = = - 1 )
amount = nValue ;
return PushSig ( key , nHashType , lenR , lenS , sigversion , amount ) . AsWit ( ) ;
2016-04-05 08:37:24 -03:00
}
2014-09-19 22:13:04 -03:00
TestBuilder & Push ( const CPubKey & pubkey )
{
DoPush ( std : : vector < unsigned char > ( pubkey . begin ( ) , pubkey . end ( ) ) ) ;
return * this ;
}
TestBuilder & PushRedeem ( )
{
2016-04-05 08:37:24 -03:00
DoPush ( std : : vector < unsigned char > ( redeemscript . begin ( ) , redeemscript . end ( ) ) ) ;
2014-09-19 22:13:04 -03:00
return * this ;
}
2016-04-05 08:37:24 -03:00
TestBuilder & PushWitRedeem ( )
{
DoPush ( std : : vector < unsigned char > ( witscript . begin ( ) , witscript . end ( ) ) ) ;
return AsWit ( ) ;
}
2014-09-19 22:13:04 -03:00
TestBuilder & EditPush ( unsigned int pos , const std : : string & hexin , const std : : string & hexout )
{
assert ( havePush ) ;
std : : vector < unsigned char > datain = ParseHex ( hexin ) ;
std : : vector < unsigned char > dataout = ParseHex ( hexout ) ;
assert ( pos + datain . size ( ) < = push . size ( ) ) ;
BOOST_CHECK_MESSAGE ( std : : vector < unsigned char > ( push . begin ( ) + pos , push . begin ( ) + pos + datain . size ( ) ) = = datain , comment ) ;
push . erase ( push . begin ( ) + pos , push . begin ( ) + pos + datain . size ( ) ) ;
push . insert ( push . begin ( ) + pos , dataout . begin ( ) , dataout . end ( ) ) ;
return * this ;
}
TestBuilder & DamagePush ( unsigned int pos )
{
assert ( havePush ) ;
assert ( pos < push . size ( ) ) ;
push [ pos ] ^ = 1 ;
return * this ;
}
2016-04-05 10:50:17 -03:00
TestBuilder & Test ( )
2014-09-19 22:13:04 -03:00
{
TestBuilder copy = * this ; // Make a copy so we can rollback the push.
DoPush ( ) ;
2016-11-11 21:23:17 -03:00
DoTest ( creditTx - > vout [ 0 ] . scriptPubKey , spendTx . vin [ 0 ] . scriptSig , scriptWitness , flags , comment , scriptError , nValue ) ;
2014-09-19 22:13:04 -03:00
* this = copy ;
return * this ;
}
2016-04-05 08:37:24 -03:00
TestBuilder & AsWit ( )
{
assert ( havePush ) ;
scriptWitness . stack . push_back ( push ) ;
havePush = false ;
return * this ;
}
2015-05-13 16:29:19 -03:00
UniValue GetJSON ( )
2014-09-19 22:13:04 -03:00
{
2014-10-06 21:22:47 -03:00
DoPush ( ) ;
2015-05-10 09:48:35 -03:00
UniValue array ( UniValue : : VARR ) ;
2016-04-05 08:37:24 -03:00
if ( ! scriptWitness . stack . empty ( ) ) {
UniValue wit ( UniValue : : VARR ) ;
for ( unsigned i = 0 ; i < scriptWitness . stack . size ( ) ; i + + ) {
wit . push_back ( HexStr ( scriptWitness . stack [ i ] ) ) ;
}
2016-05-22 07:35:43 -04:00
wit . push_back ( ValueFromAmount ( nValue ) ) ;
2016-04-05 08:37:24 -03:00
array . push_back ( wit ) ;
}
2014-10-06 21:22:47 -03:00
array . push_back ( FormatScript ( spendTx . vin [ 0 ] . scriptSig ) ) ;
2016-11-11 21:23:17 -03:00
array . push_back ( FormatScript ( creditTx - > vout [ 0 ] . scriptPubKey ) ) ;
2014-10-06 21:22:47 -03:00
array . push_back ( FormatScriptFlags ( flags ) ) ;
2016-04-05 10:45:10 -03:00
array . push_back ( FormatScriptError ( ( ScriptError_t ) scriptError ) ) ;
2014-10-06 21:22:47 -03:00
array . push_back ( comment ) ;
return array ;
2014-09-19 22:13:04 -03:00
}
2017-03-09 09:34:54 -03:00
std : : string GetComment ( ) const
2014-09-19 22:13:04 -03:00
{
return comment ;
}
} ;
2016-04-05 09:54:18 -03:00
std : : string JSONPrettyPrint ( const UniValue & univalue )
{
std : : string ret = univalue . write ( 4 ) ;
2017-01-13 12:05:16 -03:00
// Workaround for libunivalue pretty printer, which puts a space between commas and newlines
2016-04-05 09:54:18 -03:00
size_t pos = 0 ;
while ( ( pos = ret . find ( " \n " , pos ) ) ! = std : : string : : npos ) {
ret . replace ( pos , 2 , " \n " ) ;
pos + + ;
}
return ret ;
}
2017-05-31 16:21:25 -04:00
} // namespace
2014-09-19 22:13:04 -03:00
BOOST_AUTO_TEST_CASE ( script_build )
{
2014-11-05 14:43:44 -03:00
const KeyData keys ;
2016-04-05 11:11:47 -03:00
std : : vector < TestBuilder > tests ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2PK " , 0
) . PushSig ( keys . key0 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2PK, bad sig " , 0
) . PushSig ( keys . key0 ) . DamagePush ( 10 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_DUP < < OP_HASH160 < < ToByteVector ( keys . pubkey1C . GetID ( ) ) < < OP_EQUALVERIFY < < OP_CHECKSIG ,
" P2PKH " , 0
) . PushSig ( keys . key1 ) . Push ( keys . pubkey1C ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_DUP < < OP_HASH160 < < ToByteVector ( keys . pubkey2C . GetID ( ) ) < < OP_EQUALVERIFY < < OP_CHECKSIG ,
" P2PKH, bad pubkey " , 0
) . PushSig ( keys . key2 ) . Push ( keys . pubkey2C ) . DamagePush ( 5 ) . ScriptError ( SCRIPT_ERR_EQUALVERIFY ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
" P2PK anyonecanpay " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL | SIGHASH_ANYONECANPAY ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
" P2PK anyonecanpay marked with normal hashtype " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL | SIGHASH_ANYONECANPAY ) . EditPush ( 70 , " 81 " , " 01 " ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0C ) < < OP_CHECKSIG ,
" P2SH(P2PK) " , SCRIPT_VERIFY_P2SH , true
) . PushSig ( keys . key0 ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0C ) < < OP_CHECKSIG ,
" P2SH(P2PK), bad redeemscript " , SCRIPT_VERIFY_P2SH , true
) . PushSig ( keys . key0 ) . PushRedeem ( ) . DamagePush ( 10 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
2018-07-24 11:59:49 -04:00
2016-05-23 15:23:07 -04:00
tests . push_back ( TestBuilder ( CScript ( ) < < OP_DUP < < OP_HASH160 < < ToByteVector ( keys . pubkey0 . GetID ( ) ) < < OP_EQUALVERIFY < < OP_CHECKSIG ,
" P2SH(P2PKH) " , SCRIPT_VERIFY_P2SH , true
) . PushSig ( keys . key0 ) . Push ( keys . pubkey0 ) . PushRedeem ( ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < OP_DUP < < OP_HASH160 < < ToByteVector ( keys . pubkey1 . GetID ( ) ) < < OP_EQUALVERIFY < < OP_CHECKSIG ,
" P2SH(P2PKH), bad sig but no VERIFY_P2SH " , 0 , true
) . PushSig ( keys . key0 ) . DamagePush ( 10 ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_DUP < < OP_HASH160 < < ToByteVector ( keys . pubkey1 . GetID ( ) ) < < OP_EQUALVERIFY < < OP_CHECKSIG ,
" P2SH(P2PKH), bad sig " , SCRIPT_VERIFY_P2SH , true
) . PushSig ( keys . key0 ) . DamagePush ( 10 ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EQUALVERIFY ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_3 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG ,
" 3-of-3 " , 0
) . Num ( 0 ) . PushSig ( keys . key0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key2 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_3 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG ,
" 3-of-3, 2 sigs " , 0
) . Num ( 0 ) . PushSig ( keys . key0 ) . PushSig ( keys . key1 ) . Num ( 0 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG ,
" P2SH(2-of-3) " , SCRIPT_VERIFY_P2SH , true
) . Num ( 0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key2 ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG ,
" P2SH(2-of-3), 1 sig " , SCRIPT_VERIFY_P2SH , true
) . Num ( 0 ) . PushSig ( keys . key1 ) . Num ( 0 ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" P2PK with too much R padding but no DERSIG " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL , 31 , 32 ) . EditPush ( 1 , " 43021F " , " 44022000 " ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" P2PK with too much R padding " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key1 , SIGHASH_ALL , 31 , 32 ) . EditPush ( 1 , " 43021F " , " 44022000 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" P2PK with too much S padding but no DERSIG " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL ) . EditPush ( 1 , " 44 " , " 45 " ) . EditPush ( 37 , " 20 " , " 2100 " ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" P2PK with too much S padding " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key1 , SIGHASH_ALL ) . EditPush ( 1 , " 44 " , " 45 " ) . EditPush ( 37 , " 20 " , " 2100 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" P2PK with too little R padding but no DERSIG " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" P2PK with too little R padding " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with bad sig with too much R padding but no DERSIG " , 0
) . PushSig ( keys . key2 , SIGHASH_ALL , 31 , 32 ) . EditPush ( 1 , " 43021F " , " 44022000 " ) . DamagePush ( 10 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with bad sig with too much R padding " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key2 , SIGHASH_ALL , 31 , 32 ) . EditPush ( 1 , " 43021F " , " 44022000 " ) . DamagePush ( 10 ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with too much R padding but no DERSIG " , 0
) . PushSig ( keys . key2 , SIGHASH_ALL , 31 , 32 ) . EditPush ( 1 , " 43021F " , " 44022000 " ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with too much R padding " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key2 , SIGHASH_ALL , 31 , 32 ) . EditPush ( 1 , " 43021F " , " 44022000 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" BIP66 example 1, without DERSIG " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" BIP66 example 1, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG < < OP_NOT ,
" BIP66 example 2, without DERSIG " , 0
) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG < < OP_NOT ,
" BIP66 example 2, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" BIP66 example 3, without DERSIG " , 0
) . Num ( 0 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" BIP66 example 3, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG < < OP_NOT ,
" BIP66 example 4, without DERSIG " , 0
) . Num ( 0 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG < < OP_NOT ,
" BIP66 example 4, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" BIP66 example 5, without DERSIG " , 0
) . Num ( 1 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG ,
" BIP66 example 5, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 1 ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG < < OP_NOT ,
" BIP66 example 6, without DERSIG " , 0
) . Num ( 1 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1C ) < < OP_CHECKSIG < < OP_NOT ,
" BIP66 example 6, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 1 ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG ,
" BIP66 example 7, without DERSIG " , 0
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . PushSig ( keys . key2 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG ,
" BIP66 example 7, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . PushSig ( keys . key2 ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG < < OP_NOT ,
" BIP66 example 8, without DERSIG " , 0
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . PushSig ( keys . key2 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG < < OP_NOT ,
" BIP66 example 8, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . PushSig ( keys . key2 ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG ,
" BIP66 example 9, without DERSIG " , 0
) . Num ( 0 ) . Num ( 0 ) . PushSig ( keys . key2 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG ,
" BIP66 example 9, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . Num ( 0 ) . PushSig ( keys . key2 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG < < OP_NOT ,
" BIP66 example 10, without DERSIG " , 0
) . Num ( 0 ) . Num ( 0 ) . PushSig ( keys . key2 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG < < OP_NOT ,
" BIP66 example 10, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . Num ( 0 ) . PushSig ( keys . key2 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG ,
" BIP66 example 11, without DERSIG " , 0
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . Num ( 0 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG ,
" BIP66 example 11, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . Num ( 0 ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG < < OP_NOT ,
" BIP66 example 12, without DERSIG " , 0
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . Num ( 0 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_2 < < OP_CHECKMULTISIG < < OP_NOT ,
" BIP66 example 12, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL , 33 , 32 ) . EditPush ( 1 , " 45022100 " , " 440220 " ) . Num ( 0 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2PK with multi-byte hashtype, without DERSIG " , 0
) . PushSig ( keys . key2 , SIGHASH_ALL ) . EditPush ( 70 , " 01 " , " 0101 " ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2PK with multi-byte hashtype, with DERSIG " , SCRIPT_VERIFY_DERSIG
) . PushSig ( keys . key2 , SIGHASH_ALL ) . EditPush ( 70 , " 01 " , " 0101 " ) . ScriptError ( SCRIPT_ERR_SIG_DER ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2PK with high S but no LOW_S " , 0
) . PushSig ( keys . key2 , SIGHASH_ALL , 32 , 33 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2PK with high S " , SCRIPT_VERIFY_LOW_S
) . PushSig ( keys . key2 , SIGHASH_ALL , 32 , 33 ) . ScriptError ( SCRIPT_ERR_SIG_HIGH_S ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0H ) < < OP_CHECKSIG ,
" P2PK with hybrid pubkey but no STRICTENC " , 0
) . PushSig ( keys . key0 , SIGHASH_ALL ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0H ) < < OP_CHECKSIG ,
" P2PK with hybrid pubkey " , SCRIPT_VERIFY_STRICTENC
) . PushSig ( keys . key0 , SIGHASH_ALL ) . ScriptError ( SCRIPT_ERR_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0H ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with hybrid pubkey but no STRICTENC " , 0
) . PushSig ( keys . key0 , SIGHASH_ALL ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0H ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with hybrid pubkey " , SCRIPT_VERIFY_STRICTENC
) . PushSig ( keys . key0 , SIGHASH_ALL ) . ScriptError ( SCRIPT_ERR_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0H ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with invalid hybrid pubkey but no STRICTENC " , 0
) . PushSig ( keys . key0 , SIGHASH_ALL ) . DamagePush ( 10 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0H ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with invalid hybrid pubkey " , SCRIPT_VERIFY_STRICTENC
) . PushSig ( keys . key0 , SIGHASH_ALL ) . DamagePush ( 10 ) . ScriptError ( SCRIPT_ERR_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey0H ) < < ToByteVector ( keys . pubkey1C ) < < OP_2 < < OP_CHECKMULTISIG ,
" 1-of-2 with the second 1 hybrid pubkey and no STRICTENC " , 0
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey0H ) < < ToByteVector ( keys . pubkey1C ) < < OP_2 < < OP_CHECKMULTISIG ,
" 1-of-2 with the second 1 hybrid pubkey " , SCRIPT_VERIFY_STRICTENC
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0H ) < < OP_2 < < OP_CHECKMULTISIG ,
" 1-of-2 with the first 1 hybrid pubkey " , SCRIPT_VERIFY_STRICTENC
) . Num ( 0 ) . PushSig ( keys . key1 , SIGHASH_ALL ) . ScriptError ( SCRIPT_ERR_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
" P2PK with undefined hashtype but no STRICTENC " , 0
) . PushSig ( keys . key1 , 5 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
" P2PK with undefined hashtype " , SCRIPT_VERIFY_STRICTENC
) . PushSig ( keys . key1 , 5 ) . ScriptError ( SCRIPT_ERR_SIG_HASHTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with invalid sig and undefined hashtype but no STRICTENC " , 0
) . PushSig ( keys . key1 , 5 ) . DamagePush ( 10 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG < < OP_NOT ,
" P2PK NOT with invalid sig and undefined hashtype " , SCRIPT_VERIFY_STRICTENC
) . PushSig ( keys . key1 , 5 ) . DamagePush ( 10 ) . ScriptError ( SCRIPT_ERR_SIG_HASHTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_3 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG ,
" 3-of-3 with nonzero dummy but no NULLDUMMY " , 0
) . Num ( 1 ) . PushSig ( keys . key0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key2 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_3 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG ,
" 3-of-3 with nonzero dummy " , SCRIPT_VERIFY_NULLDUMMY
) . Num ( 1 ) . PushSig ( keys . key0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key2 ) . ScriptError ( SCRIPT_ERR_SIG_NULLDUMMY ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_3 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG < < OP_NOT ,
" 3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY " , 0
) . Num ( 1 ) . PushSig ( keys . key0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key2 ) . DamagePush ( 10 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_3 < < ToByteVector ( keys . pubkey0C ) < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey2C ) < < OP_3 < < OP_CHECKMULTISIG < < OP_NOT ,
" 3-of-3 NOT with invalid sig with nonzero dummy " , SCRIPT_VERIFY_NULLDUMMY
) . Num ( 1 ) . PushSig ( keys . key0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key2 ) . DamagePush ( 10 ) . ScriptError ( SCRIPT_ERR_SIG_NULLDUMMY ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey1C ) < < OP_2 < < OP_CHECKMULTISIG ,
" 2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY " , 0
2020-04-12 23:03:10 -04:00
) . Num ( 0 ) . PushSig ( keys . key1 ) . Opcode ( OP_DUP ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey1C ) < < OP_2 < < OP_CHECKMULTISIG ,
" 2-of-2 with two identical keys and sigs pushed using OP_DUP " , SCRIPT_VERIFY_SIGPUSHONLY
2020-04-12 23:03:10 -04:00
) . Num ( 0 ) . PushSig ( keys . key1 ) . Opcode ( OP_DUP ) . ScriptError ( SCRIPT_ERR_SIG_PUSHONLY ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY " , 0 , true
2020-04-12 23:03:10 -04:00
) . PushSig ( keys . key2 ) . Opcode ( OP_NOP8 ) . PushRedeem ( ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2PK with non-push scriptSig but with P2SH validation " , 0
2020-04-12 23:03:10 -04:00
) . PushSig ( keys . key2 ) . Opcode ( OP_NOP8 ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY " , SCRIPT_VERIFY_P2SH , true
2020-04-12 23:03:10 -04:00
) . PushSig ( keys . key2 ) . Opcode ( OP_NOP8 ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_SIG_PUSHONLY ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey2C ) < < OP_CHECKSIG ,
" P2SH(P2PK) with non-push scriptSig but not P2SH " , SCRIPT_VERIFY_SIGPUSHONLY , true
2020-04-12 23:03:10 -04:00
) . PushSig ( keys . key2 ) . Opcode ( OP_NOP8 ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_SIG_PUSHONLY ) ) ;
2016-04-05 11:11:47 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < OP_2 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey1C ) < < OP_2 < < OP_CHECKMULTISIG ,
" 2-of-2 with two identical keys and sigs pushed " , SCRIPT_VERIFY_SIGPUSHONLY
) . Num ( 0 ) . PushSig ( keys . key1 ) . PushSig ( keys . key1 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2PK with unnecessary input but no CLEANSTACK " , SCRIPT_VERIFY_P2SH
) . Num ( 11 ) . PushSig ( keys . key0 ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2PK with unnecessary input " , SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH
) . Num ( 11 ) . PushSig ( keys . key0 ) . ScriptError ( SCRIPT_ERR_CLEANSTACK ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2SH with unnecessary input but no CLEANSTACK " , SCRIPT_VERIFY_P2SH , true
) . Num ( 11 ) . PushSig ( keys . key0 ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2SH with unnecessary input " , SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH , true
) . Num ( 11 ) . PushSig ( keys . key0 ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_CLEANSTACK ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2SH with CLEANSTACK " , SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH , true
) . PushSig ( keys . key0 ) . PushRedeem ( ) ) ;
2016-04-05 08:37:24 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2WSH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH ,
2016-05-22 07:35:43 -04:00
0 , 1 ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) ) ;
2016-04-05 08:37:24 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2WPKH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : PKH ,
2016-05-22 07:35:43 -04:00
0 , 1 ) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) ) ;
2016-04-05 08:37:24 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WSH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH ,
2016-05-22 07:35:43 -04:00
0 , 1 ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
2016-04-05 08:37:24 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WPKH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : PKH ,
2016-05-22 07:35:43 -04:00
0 , 1 ) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . PushRedeem ( ) ) ;
2016-04-05 08:37:24 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2WSH with the wrong key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2WPKH with the wrong key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : PKH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WSH) with the wrong key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WPKH) with the wrong key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : PKH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2WSH with the wrong key but no WITNESS " , SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2WPKH with the wrong key but no WITNESS " , SCRIPT_VERIFY_P2SH , false , WitnessMode : : PKH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WSH) with the wrong key but no WITNESS " , SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WPKH) with the wrong key but no WITNESS " , SCRIPT_VERIFY_P2SH , true , WitnessMode : : PKH
2016-04-05 08:37:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) . PushRedeem ( ) ) ;
2016-05-22 07:35:43 -04:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2WSH with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH ,
2016-05-22 07:35:43 -04:00
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2WPKH with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : PKH ,
2016-05-22 07:35:43 -04:00
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . Push ( keys . pubkey0 ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WSH) with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH ,
2016-05-22 07:35:43 -04:00
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WPKH) with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : PKH ,
2016-05-22 07:35:43 -04:00
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . Push ( keys . pubkey0 ) . AsWit ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
2016-04-05 11:11:47 -03:00
2016-04-08 22:02:24 -03:00
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
" P2WPKH with future witness version " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
2018-03-09 11:03:40 -03:00
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM , false , WitnessMode : : PKH , 1
2016-04-08 22:02:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM ) ) ;
{
CScript witscript = CScript ( ) < < ToByteVector ( keys . pubkey0 ) ;
uint256 hash ;
CSHA256 ( ) . Write ( & witscript [ 0 ] , witscript . size ( ) ) . Finalize ( hash . begin ( ) ) ;
2016-12-05 04:03:53 -03:00
std : : vector < unsigned char > hashBytes = ToByteVector ( hash ) ;
2016-04-08 22:02:24 -03:00
hashBytes . pop_back ( ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_0 < < hashBytes ,
" P2WPKH with wrong witness program length " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH ) ) ;
}
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" P2WSH with empty witness " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH
2016-04-08 22:02:24 -03:00
) . ScriptError ( SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY ) ) ;
{
CScript witscript = CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ;
tests . push_back ( TestBuilder ( witscript ,
2018-03-09 11:03:40 -03:00
" P2WSH with witness program mismatch " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH
2016-04-08 22:02:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( witscript ) . DamagePush ( 0 ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH ) ) ;
}
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" P2WPKH with witness program mismatch " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : PKH
2016-04-08 22:02:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . Push ( " 0 " ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" P2WPKH with non-empty scriptSig " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : PKH
2016-04-08 22:02:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . Num ( 11 ) . ScriptError ( SCRIPT_ERR_WITNESS_MALLEATED ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WPKH) with superfluous push in scriptSig " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : PKH
2016-04-08 22:02:24 -03:00
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) . Num ( 11 ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_MALLEATED_P2SH ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" P2PK with witness " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH
) . PushSig ( keys . key0 ) . Push ( " 0 " ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_WITNESS_UNEXPECTED ) ) ;
2016-10-14 15:29:39 -03:00
// Compressed keys should pass SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0C ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2WSH with compressed key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0C ) ,
2018-03-09 11:03:40 -03:00
" Basic P2WPKH with compressed key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : PKH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0C ) . Push ( keys . pubkey0C ) . AsWit ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0C ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WSH) with compressed key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0C ) ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WPKH) with compressed key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : PKH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0C ) . Push ( keys . pubkey0C ) . AsWit ( ) . PushRedeem ( ) ) ;
// Testing uncompressed key in witness with SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2WSH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2WPKH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : PKH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WSH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
2018-03-09 11:03:40 -03:00
" Basic P2SH(P2WPKH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : PKH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
// P2WSH 1-of-2 multisig with compressed keys
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with compressed keys " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with compressed keys " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with compressed keys " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1C ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with compressed keys " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1C ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
// P2WSH 1-of-2 multisig with first key uncompressed
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1C ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1C ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1C ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1C ) < < ToByteVector ( keys . pubkey0 ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1C ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
// P2WSH 1-of-2 multisig with second key uncompressed
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key0C ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1 ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1 ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , false , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < OP_1 < < ToByteVector ( keys . pubkey1 ) < < ToByteVector ( keys . pubkey0C ) < < OP_2 < < OP_CHECKMULTISIG ,
2018-03-09 11:03:40 -03:00
" P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE , true , WitnessMode : : SH ,
2016-10-14 15:29:39 -03:00
0 , 1 ) . Push ( CScript ( ) ) . AsWit ( ) . PushWitSig ( keys . key1 ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_WITNESS_PUBKEYTYPE ) ) ;
2016-04-05 11:11:47 -03:00
std : : set < std : : string > tests_set ;
2014-09-19 22:13:04 -03:00
{
2016-04-05 11:11:47 -03:00
UniValue json_tests = read_json ( std : : string ( json_tests : : script_tests , json_tests : : script_tests + sizeof ( json_tests : : script_tests ) ) ) ;
2014-09-19 22:13:04 -03:00
2016-04-05 11:11:47 -03:00
for ( unsigned int idx = 0 ; idx < json_tests . size ( ) ; idx + + ) {
const UniValue & tv = json_tests [ idx ] ;
tests_set . insert ( JSONPrettyPrint ( tv . get_array ( ) ) ) ;
2014-09-19 22:13:04 -03:00
}
}
2018-07-26 10:33:45 -04:00
# ifdef UPDATE_JSON_TESTS
2016-04-05 11:11:47 -03:00
std : : string strGen ;
2018-07-26 10:33:45 -04:00
# endif
2017-06-01 21:18:57 -04:00
for ( TestBuilder & test : tests ) {
2016-04-05 10:50:17 -03:00
test . Test ( ) ;
2016-04-05 09:54:18 -03:00
std : : string str = JSONPrettyPrint ( test . GetJSON ( ) ) ;
2018-07-26 10:33:45 -04:00
# ifdef UPDATE_JSON_TESTS
strGen + = str + " , \n " ;
# else
2016-04-05 11:11:47 -03:00
if ( tests_set . count ( str ) = = 0 ) {
2014-10-06 21:22:47 -03:00
BOOST_CHECK_MESSAGE ( false , " Missing auto script_valid test: " + test . GetComment ( ) ) ;
}
2014-12-01 17:26:51 -03:00
# endif
2014-09-19 22:13:04 -03:00
}
2014-10-06 21:22:47 -03:00
# ifdef UPDATE_JSON_TESTS
2016-04-05 11:11:47 -03:00
FILE * file = fopen ( " script_tests.json.gen " , " w " ) ;
fputs ( strGen . c_str ( ) , file ) ;
fclose ( file ) ;
2014-09-19 22:13:04 -03:00
# endif
}
2016-04-05 11:11:47 -03:00
BOOST_AUTO_TEST_CASE ( script_json_test )
2012-04-17 18:57:06 -03:00
{
2016-04-05 11:11:47 -03:00
// Read tests from test/data/script_tests.json
2012-04-17 18:57:06 -03:00
// Format is an array of arrays
2016-05-22 07:35:43 -04:00
// Inner arrays are [ ["wit"..., nValue]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
2012-04-17 18:57:06 -03:00
// ... where scriptSig and scriptPubKey are stringified
// scripts.
2016-05-22 07:35:43 -04:00
// If a witness is given, then the last value in the array should be the
// amount (nValue) to use in the crediting tx
2016-04-05 11:11:47 -03:00
UniValue tests = read_json ( std : : string ( json_tests : : script_tests , json_tests : : script_tests + sizeof ( json_tests : : script_tests ) ) ) ;
2012-04-17 18:57:06 -03:00
2014-08-20 15:15:16 -04:00
for ( unsigned int idx = 0 ; idx < tests . size ( ) ; idx + + ) {
2015-05-13 16:29:19 -03:00
UniValue test = tests [ idx ] ;
2016-12-05 04:03:53 -03:00
std : : string strTest = test . write ( ) ;
2016-04-04 11:01:27 -03:00
CScriptWitness witness ;
2016-05-22 07:35:43 -04:00
CAmount nValue = 0 ;
2016-04-04 11:01:27 -03:00
unsigned int pos = 0 ;
if ( test . size ( ) > 0 & & test [ pos ] . isArray ( ) ) {
2016-05-22 07:35:43 -04:00
unsigned int i = 0 ;
for ( i = 0 ; i < test [ pos ] . size ( ) - 1 ; i + + ) {
2016-04-04 11:01:27 -03:00
witness . stack . push_back ( ParseHex ( test [ pos ] [ i ] . get_str ( ) ) ) ;
}
2016-05-22 07:35:43 -04:00
nValue = AmountFromValue ( test [ pos ] [ i ] ) ;
2016-04-04 11:01:27 -03:00
pos + + ;
}
if ( test . size ( ) < 4 + pos ) // Allow size > 3; extra stuff ignored (useful for comments)
2012-04-17 18:57:06 -03:00
{
2014-09-19 19:20:53 -03:00
if ( test . size ( ) ! = 1 ) {
BOOST_ERROR ( " Bad test: " < < strTest ) ;
}
2012-04-17 18:57:06 -03:00
continue ;
}
2016-12-05 04:03:53 -03:00
std : : string scriptSigString = test [ pos + + ] . get_str ( ) ;
2012-04-17 18:57:06 -03:00
CScript scriptSig = ParseScript ( scriptSigString ) ;
2016-12-05 04:03:53 -03:00
std : : string scriptPubKeyString = test [ pos + + ] . get_str ( ) ;
2012-04-17 18:57:06 -03:00
CScript scriptPubKey = ParseScript ( scriptPubKeyString ) ;
2016-04-04 11:01:27 -03:00
unsigned int scriptflags = ParseScriptFlags ( test [ pos + + ] . get_str ( ) ) ;
int scriptError = ParseScriptError ( test [ pos + + ] . get_str ( ) ) ;
2012-04-17 18:57:06 -03:00
2016-05-22 07:35:43 -04:00
DoTest ( scriptPubKey , scriptSig , witness , scriptflags , strTest , scriptError , nValue ) ;
2012-04-17 18:57:06 -03:00
}
}
2011-07-31 14:01:31 -04:00
BOOST_AUTO_TEST_CASE ( script_PushData )
{
// Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
// the stack as the 1-75 opcodes do.
static const unsigned char direct [ ] = { 1 , 0x5a } ;
static const unsigned char pushdata1 [ ] = { OP_PUSHDATA1 , 1 , 0x5a } ;
static const unsigned char pushdata2 [ ] = { OP_PUSHDATA2 , 1 , 0 , 0x5a } ;
static const unsigned char pushdata4 [ ] = { OP_PUSHDATA4 , 1 , 0 , 0 , 0 , 0x5a } ;
2014-11-13 16:27:38 -03:00
ScriptError err ;
2016-12-05 04:03:53 -03:00
std : : vector < std : : vector < unsigned char > > directStack ;
2018-10-05 04:43:09 -03:00
BOOST_CHECK ( EvalScript ( directStack , CScript ( direct , direct + sizeof ( direct ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-07-31 14:01:31 -04:00
2016-12-05 04:03:53 -03:00
std : : vector < std : : vector < unsigned char > > pushdata1Stack ;
2018-10-05 04:43:09 -03:00
BOOST_CHECK ( EvalScript ( pushdata1Stack , CScript ( pushdata1 , pushdata1 + sizeof ( pushdata1 ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
2011-07-31 14:01:31 -04:00
BOOST_CHECK ( pushdata1Stack = = directStack ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-07-31 14:01:31 -04:00
2016-12-05 04:03:53 -03:00
std : : vector < std : : vector < unsigned char > > pushdata2Stack ;
2018-10-05 04:43:09 -03:00
BOOST_CHECK ( EvalScript ( pushdata2Stack , CScript ( pushdata2 , pushdata2 + sizeof ( pushdata2 ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
2011-07-31 14:01:31 -04:00
BOOST_CHECK ( pushdata2Stack = = directStack ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-07-31 14:01:31 -04:00
2016-12-05 04:03:53 -03:00
std : : vector < std : : vector < unsigned char > > pushdata4Stack ;
2018-10-05 04:43:09 -03:00
BOOST_CHECK ( EvalScript ( pushdata4Stack , CScript ( pushdata4 , pushdata4 + sizeof ( pushdata4 ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
2011-07-31 14:01:31 -04:00
BOOST_CHECK ( pushdata4Stack = = directStack ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2018-12-12 17:33:35 -03:00
const std : : vector < unsigned char > pushdata1_trunc { OP_PUSHDATA1 , 1 } ;
const std : : vector < unsigned char > pushdata2_trunc { OP_PUSHDATA2 , 1 , 0 } ;
const std : : vector < unsigned char > pushdata4_trunc { OP_PUSHDATA4 , 1 , 0 , 0 , 0 } ;
std : : vector < std : : vector < unsigned char > > stack_ignore ;
BOOST_CHECK ( ! EvalScript ( stack_ignore , CScript ( pushdata1_trunc . begin ( ) , pushdata1_trunc . end ( ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
BOOST_CHECK_EQUAL ( err , SCRIPT_ERR_BAD_OPCODE ) ;
BOOST_CHECK ( ! EvalScript ( stack_ignore , CScript ( pushdata2_trunc . begin ( ) , pushdata2_trunc . end ( ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
BOOST_CHECK_EQUAL ( err , SCRIPT_ERR_BAD_OPCODE ) ;
BOOST_CHECK ( ! EvalScript ( stack_ignore , CScript ( pushdata4_trunc . begin ( ) , pushdata4_trunc . end ( ) ) , SCRIPT_VERIFY_P2SH , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
BOOST_CHECK_EQUAL ( err , SCRIPT_ERR_BAD_OPCODE ) ;
}
BOOST_AUTO_TEST_CASE ( script_cltv_truncated )
{
const auto script_cltv_trunc = CScript ( ) < < OP_CHECKLOCKTIMEVERIFY ;
std : : vector < std : : vector < unsigned char > > stack_ignore ;
ScriptError err ;
BOOST_CHECK ( ! EvalScript ( stack_ignore , script_cltv_trunc , SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY , BaseSignatureChecker ( ) , SigVersion : : BASE , & err ) ) ;
BOOST_CHECK_EQUAL ( err , SCRIPT_ERR_INVALID_STACK_OPERATION ) ;
2011-07-31 14:01:31 -04:00
}
2018-05-02 12:14:48 -03:00
static CScript
2018-04-11 14:51:28 -03:00
sign_multisig ( const CScript & scriptPubKey , const std : : vector < CKey > & keys , const CTransaction & transaction )
2011-08-26 19:41:22 -03:00
{
2018-03-09 11:03:40 -03:00
uint256 hash = SignatureHash ( scriptPubKey , transaction , 0 , SIGHASH_ALL , 0 , SigVersion : : BASE ) ;
2011-08-26 19:41:22 -03:00
CScript result ;
//
// NOTE: CHECKMULTISIG has an unfortunate bug; it requires
// one extra item on the stack, before the signatures.
// Putting OP_0 on the stack is the workaround;
2012-10-05 14:22:21 -03:00
// fixing the bug would mean splitting the block chain (old
2011-08-26 19:41:22 -03:00
// clients would not accept new CHECKMULTISIG transactions,
// and vice-versa)
//
result < < OP_0 ;
2017-06-01 21:18:57 -04:00
for ( const CKey & key : keys )
2011-08-26 19:41:22 -03:00
{
2016-12-05 04:03:53 -03:00
std : : vector < unsigned char > vchSig ;
2011-08-26 19:41:22 -03:00
BOOST_CHECK ( key . Sign ( hash , vchSig ) ) ;
vchSig . push_back ( ( unsigned char ) SIGHASH_ALL ) ;
result < < vchSig ;
}
return result ;
}
2018-05-02 12:14:48 -03:00
static CScript
2018-04-11 14:51:28 -03:00
sign_multisig ( const CScript & scriptPubKey , const CKey & key , const CTransaction & transaction )
2011-08-26 19:41:22 -03:00
{
std : : vector < CKey > keys ;
keys . push_back ( key ) ;
return sign_multisig ( scriptPubKey , keys , transaction ) ;
}
BOOST_AUTO_TEST_CASE ( script_CHECKMULTISIG12 )
{
2014-11-13 16:27:38 -03:00
ScriptError err ;
2011-08-26 19:41:22 -03:00
CKey key1 , key2 , key3 ;
2012-02-20 14:32:33 -03:00
key1 . MakeNewKey ( true ) ;
key2 . MakeNewKey ( false ) ;
key3 . MakeNewKey ( true ) ;
2011-08-26 19:41:22 -03:00
CScript scriptPubKey12 ;
2014-09-24 23:54:08 -03:00
scriptPubKey12 < < OP_1 < < ToByteVector ( key1 . GetPubKey ( ) ) < < ToByteVector ( key2 . GetPubKey ( ) ) < < OP_2 < < OP_CHECKMULTISIG ;
2011-08-26 19:41:22 -03:00
2018-05-04 18:38:49 -03:00
const CTransaction txFrom12 { BuildCreditingTransaction ( scriptPubKey12 ) } ;
2016-04-04 11:01:27 -03:00
CMutableTransaction txTo12 = BuildSpendingTransaction ( CScript ( ) , CScriptWitness ( ) , txFrom12 ) ;
2011-08-26 19:41:22 -03:00
2018-12-08 20:38:12 -03:00
CScript goodsig1 = sign_multisig ( scriptPubKey12 , key1 , CTransaction ( txTo12 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( VerifyScript ( goodsig1 , scriptPubKey12 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo12 , 0 , txFrom12 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
txTo12 . vout [ 0 ] . nValue = 2 ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( goodsig1 , scriptPubKey12 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo12 , 0 , txFrom12 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
2018-12-08 20:38:12 -03:00
CScript goodsig2 = sign_multisig ( scriptPubKey12 , key2 , CTransaction ( txTo12 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( VerifyScript ( goodsig2 , scriptPubKey12 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo12 , 0 , txFrom12 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
2018-12-08 20:38:12 -03:00
CScript badsig1 = sign_multisig ( scriptPubKey12 , key3 , CTransaction ( txTo12 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig1 , scriptPubKey12 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo12 , 0 , txFrom12 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
}
BOOST_AUTO_TEST_CASE ( script_CHECKMULTISIG23 )
{
2014-11-13 16:27:38 -03:00
ScriptError err ;
2011-08-26 19:41:22 -03:00
CKey key1 , key2 , key3 , key4 ;
2012-02-20 14:32:33 -03:00
key1 . MakeNewKey ( true ) ;
key2 . MakeNewKey ( false ) ;
key3 . MakeNewKey ( true ) ;
key4 . MakeNewKey ( false ) ;
2011-08-26 19:41:22 -03:00
CScript scriptPubKey23 ;
2014-09-24 23:54:08 -03:00
scriptPubKey23 < < OP_2 < < ToByteVector ( key1 . GetPubKey ( ) ) < < ToByteVector ( key2 . GetPubKey ( ) ) < < ToByteVector ( key3 . GetPubKey ( ) ) < < OP_3 < < OP_CHECKMULTISIG ;
2011-08-26 19:41:22 -03:00
2018-05-04 18:38:49 -03:00
const CTransaction txFrom23 { BuildCreditingTransaction ( scriptPubKey23 ) } ;
2016-04-04 11:01:27 -03:00
CMutableTransaction txTo23 = BuildSpendingTransaction ( CScript ( ) , CScriptWitness ( ) , txFrom23 ) ;
2011-08-26 19:41:22 -03:00
std : : vector < CKey > keys ;
keys . push_back ( key1 ) ; keys . push_back ( key2 ) ;
2018-12-08 20:38:12 -03:00
CScript goodsig1 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( VerifyScript ( goodsig1 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key1 ) ; keys . push_back ( key3 ) ;
2018-12-08 20:38:12 -03:00
CScript goodsig2 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( VerifyScript ( goodsig2 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key2 ) ; keys . push_back ( key3 ) ;
2018-12-08 20:38:12 -03:00
CScript goodsig3 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( VerifyScript ( goodsig3 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key2 ) ; keys . push_back ( key2 ) ; // Can't re-use sig
2018-12-08 20:38:12 -03:00
CScript badsig1 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig1 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key2 ) ; keys . push_back ( key1 ) ; // sigs must be in correct order
2018-12-08 20:38:12 -03:00
CScript badsig2 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig2 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key3 ) ; keys . push_back ( key2 ) ; // sigs must be in correct order
2018-12-08 20:38:12 -03:00
CScript badsig3 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig3 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key4 ) ; keys . push_back ( key2 ) ; // sigs must match pubkeys
2018-12-08 20:38:12 -03:00
CScript badsig4 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig4 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ;
keys . push_back ( key1 ) ; keys . push_back ( key4 ) ; // sigs must match pubkeys
2018-12-08 20:38:12 -03:00
CScript badsig5 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig5 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_EVAL_FALSE , ScriptErrorString ( err ) ) ;
2011-08-26 19:41:22 -03:00
keys . clear ( ) ; // Must have signatures
2018-12-08 20:38:12 -03:00
CScript badsig6 = sign_multisig ( scriptPubKey23 , keys , CTransaction ( txTo23 ) ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK ( ! VerifyScript ( badsig6 , scriptPubKey23 , nullptr , gFlags , MutableTransactionSignatureChecker ( & txTo23 , 0 , txFrom23 . vout [ 0 ] . nValue ) , & err ) ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_INVALID_STACK_OPERATION , ScriptErrorString ( err ) ) ;
2015-07-30 20:56:00 -03:00
}
2011-08-26 19:41:22 -03:00
2018-06-08 17:39:36 -04:00
/* Wrapper around ProduceSignature to combine two scriptsigs */
SignatureData CombineSignatures ( const CTxOut & txout , const CMutableTransaction & tx , const SignatureData & scriptSig1 , const SignatureData & scriptSig2 )
{
SignatureData data ;
data . MergeSignatureData ( scriptSig1 ) ;
data . MergeSignatureData ( scriptSig2 ) ;
ProduceSignature ( DUMMY_SIGNING_PROVIDER , MutableTransactionSignatureCreator ( & tx , 0 , txout . nValue ) , txout . scriptPubKey , data ) ;
return data ;
}
2012-05-31 16:01:16 -04:00
BOOST_AUTO_TEST_CASE ( script_combineSigs )
{
2018-06-08 17:39:36 -04:00
// Test the ProduceSignature's ability to combine signatures function
2019-06-06 10:33:23 -04:00
FillableSigningProvider keystore ;
2016-12-05 04:03:53 -03:00
std : : vector < CKey > keys ;
std : : vector < CPubKey > pubkeys ;
2012-05-31 16:01:16 -04:00
for ( int i = 0 ; i < 3 ; i + + )
{
CKey key ;
key . MakeNewKey ( i % 2 = = 1 ) ;
keys . push_back ( key ) ;
2013-05-01 00:52:05 -04:00
pubkeys . push_back ( key . GetPubKey ( ) ) ;
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( keystore . AddKey ( key ) ) ;
2012-05-31 16:01:16 -04:00
}
2019-02-19 19:00:45 -03:00
CMutableTransaction txFrom = BuildCreditingTransaction ( GetScriptForDestination ( PKHash ( keys [ 0 ] . GetPubKey ( ) ) ) ) ;
2018-12-08 20:38:12 -03:00
CMutableTransaction txTo = BuildSpendingTransaction ( CScript ( ) , CScriptWitness ( ) , CTransaction ( txFrom ) ) ;
2012-05-31 16:01:16 -04:00
CScript & scriptPubKey = txFrom . vout [ 0 ] . scriptPubKey ;
2018-06-08 17:39:36 -04:00
SignatureData scriptSig ;
2012-05-31 16:01:16 -04:00
2016-03-31 09:54:58 -03:00
SignatureData empty ;
2018-06-08 17:39:36 -04:00
SignatureData combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , empty , empty ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig . empty ( ) ) ;
2012-05-31 16:01:16 -04:00
// Single signature case:
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( SignSignature ( keystore , CTransaction ( txFrom ) , txTo , 0 , SIGHASH_ALL ) ) ; // changes scriptSig
2018-06-08 17:39:36 -04:00
scriptSig = DataFromTransaction ( txTo , 0 , txFrom . vout [ 0 ] ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , scriptSig , empty ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSig . scriptSig ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , empty , scriptSig ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSig . scriptSig ) ;
SignatureData scriptSigCopy = scriptSig ;
2012-05-31 16:01:16 -04:00
// Signing again will give a different, valid signature:
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( SignSignature ( keystore , CTransaction ( txFrom ) , txTo , 0 , SIGHASH_ALL ) ) ;
2018-06-08 17:39:36 -04:00
scriptSig = DataFromTransaction ( txTo , 0 , txFrom . vout [ 0 ] ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , scriptSigCopy , scriptSig ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSigCopy . scriptSig | | combined . scriptSig = = scriptSig . scriptSig ) ;
2012-05-31 16:01:16 -04:00
// P2SH, single-signature case:
2014-09-24 23:54:08 -03:00
CScript pkSingle ; pkSingle < < ToByteVector ( keys [ 0 ] . GetPubKey ( ) ) < < OP_CHECKSIG ;
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( keystore . AddCScript ( pkSingle ) ) ;
2019-02-19 19:00:45 -03:00
scriptPubKey = GetScriptForDestination ( ScriptHash ( pkSingle ) ) ;
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( SignSignature ( keystore , CTransaction ( txFrom ) , txTo , 0 , SIGHASH_ALL ) ) ;
2018-06-08 17:39:36 -04:00
scriptSig = DataFromTransaction ( txTo , 0 , txFrom . vout [ 0 ] ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , scriptSig , empty ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSig . scriptSig ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , empty , scriptSig ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSig . scriptSig ) ;
2012-05-31 16:01:16 -04:00
scriptSigCopy = scriptSig ;
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( SignSignature ( keystore , CTransaction ( txFrom ) , txTo , 0 , SIGHASH_ALL ) ) ;
2018-06-08 17:39:36 -04:00
scriptSig = DataFromTransaction ( txTo , 0 , txFrom . vout [ 0 ] ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , scriptSigCopy , scriptSig ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSigCopy . scriptSig | | combined . scriptSig = = scriptSig . scriptSig ) ;
2012-05-31 16:01:16 -04:00
// Hardest case: Multisig 2-of-3
2014-09-11 14:15:29 -03:00
scriptPubKey = GetScriptForMultisig ( 2 , pubkeys ) ;
2018-12-12 10:31:38 -03:00
BOOST_CHECK ( keystore . AddCScript ( scriptPubKey ) ) ;
BOOST_CHECK ( SignSignature ( keystore , CTransaction ( txFrom ) , txTo , 0 , SIGHASH_ALL ) ) ;
2018-06-08 17:39:36 -04:00
scriptSig = DataFromTransaction ( txTo , 0 , txFrom . vout [ 0 ] ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , scriptSig , empty ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSig . scriptSig ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , empty , scriptSig ) ;
BOOST_CHECK ( combined . scriptSig = = scriptSig . scriptSig ) ;
2012-05-31 16:01:16 -04:00
// A couple of partially-signed versions:
2016-12-05 04:03:53 -03:00
std : : vector < unsigned char > sig1 ;
2018-03-09 11:03:40 -03:00
uint256 hash1 = SignatureHash ( scriptPubKey , txTo , 0 , SIGHASH_ALL , 0 , SigVersion : : BASE ) ;
2012-05-31 16:01:16 -04:00
BOOST_CHECK ( keys [ 0 ] . Sign ( hash1 , sig1 ) ) ;
sig1 . push_back ( SIGHASH_ALL ) ;
2016-12-05 04:03:53 -03:00
std : : vector < unsigned char > sig2 ;
2018-03-09 11:03:40 -03:00
uint256 hash2 = SignatureHash ( scriptPubKey , txTo , 0 , SIGHASH_NONE , 0 , SigVersion : : BASE ) ;
2012-05-31 16:01:16 -04:00
BOOST_CHECK ( keys [ 1 ] . Sign ( hash2 , sig2 ) ) ;
sig2 . push_back ( SIGHASH_NONE ) ;
2016-12-05 04:03:53 -03:00
std : : vector < unsigned char > sig3 ;
2018-03-09 11:03:40 -03:00
uint256 hash3 = SignatureHash ( scriptPubKey , txTo , 0 , SIGHASH_SINGLE , 0 , SigVersion : : BASE ) ;
2012-05-31 16:01:16 -04:00
BOOST_CHECK ( keys [ 2 ] . Sign ( hash3 , sig3 ) ) ;
sig3 . push_back ( SIGHASH_SINGLE ) ;
// Not fussy about order (or even existence) of placeholders or signatures:
CScript partial1a = CScript ( ) < < OP_0 < < sig1 < < OP_0 ;
CScript partial1b = CScript ( ) < < OP_0 < < OP_0 < < sig1 ;
CScript partial2a = CScript ( ) < < OP_0 < < sig2 ;
CScript partial2b = CScript ( ) < < sig2 < < OP_0 ;
CScript partial3a = CScript ( ) < < sig3 ;
CScript partial3b = CScript ( ) < < OP_0 < < OP_0 < < sig3 ;
CScript partial3c = CScript ( ) < < OP_0 < < sig3 < < OP_0 ;
CScript complete12 = CScript ( ) < < OP_0 < < sig1 < < sig2 ;
CScript complete13 = CScript ( ) < < OP_0 < < sig1 < < sig3 ;
CScript complete23 = CScript ( ) < < OP_0 < < sig2 < < sig3 ;
2018-06-08 17:39:36 -04:00
SignatureData partial1_sigs ;
partial1_sigs . signatures . emplace ( keys [ 0 ] . GetPubKey ( ) . GetID ( ) , SigPair ( keys [ 0 ] . GetPubKey ( ) , sig1 ) ) ;
SignatureData partial2_sigs ;
partial2_sigs . signatures . emplace ( keys [ 1 ] . GetPubKey ( ) . GetID ( ) , SigPair ( keys [ 1 ] . GetPubKey ( ) , sig2 ) ) ;
SignatureData partial3_sigs ;
partial3_sigs . signatures . emplace ( keys [ 2 ] . GetPubKey ( ) . GetID ( ) , SigPair ( keys [ 2 ] . GetPubKey ( ) , sig3 ) ) ;
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial1_sigs , partial1_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = partial1a ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial1_sigs , partial2_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = complete12 ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial2_sigs , partial1_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = complete12 ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial1_sigs , partial2_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = complete12 ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial3_sigs , partial1_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = complete13 ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial2_sigs , partial3_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = complete23 ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial3_sigs , partial2_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = complete23 ) ;
2018-06-08 17:39:36 -04:00
combined = CombineSignatures ( txFrom . vout [ 0 ] , txTo , partial3_sigs , partial3_sigs ) ;
2016-03-31 09:54:58 -03:00
BOOST_CHECK ( combined . scriptSig = = partial3c ) ;
2012-05-31 16:01:16 -04:00
}
2011-08-26 19:41:22 -03:00
2013-09-23 19:48:00 -03:00
BOOST_AUTO_TEST_CASE ( script_standard_push )
{
2014-11-13 16:27:38 -03:00
ScriptError err ;
2014-10-08 22:48:59 -03:00
for ( int i = 0 ; i < 67000 ; i + + ) {
2013-09-23 19:48:00 -03:00
CScript script ;
script < < i ;
BOOST_CHECK_MESSAGE ( script . IsPushOnly ( ) , " Number " < < i < < " is not pure push. " ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK_MESSAGE ( VerifyScript ( script , CScript ( ) < < OP_1 , nullptr , SCRIPT_VERIFY_MINIMALDATA , BaseSignatureChecker ( ) , & err ) , " Number " < < i < < " push is not minimal data. " ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2013-09-23 19:48:00 -03:00
}
2014-10-08 22:48:59 -03:00
for ( unsigned int i = 0 ; i < = MAX_SCRIPT_ELEMENT_SIZE ; i + + ) {
2013-09-23 19:48:00 -03:00
std : : vector < unsigned char > data ( i , ' \111 ' ) ;
CScript script ;
script < < data ;
BOOST_CHECK_MESSAGE ( script . IsPushOnly ( ) , " Length " < < i < < " is not pure push. " ) ;
2017-08-07 01:36:37 -04:00
BOOST_CHECK_MESSAGE ( VerifyScript ( script , CScript ( ) < < OP_1 , nullptr , SCRIPT_VERIFY_MINIMALDATA , BaseSignatureChecker ( ) , & err ) , " Length " < < i < < " push is not minimal data. " ) ;
2014-11-13 16:27:38 -03:00
BOOST_CHECK_MESSAGE ( err = = SCRIPT_ERR_OK , ScriptErrorString ( err ) ) ;
2013-09-23 19:48:00 -03:00
}
}
2014-08-24 21:16:51 -04:00
BOOST_AUTO_TEST_CASE ( script_IsPushOnly_on_invalid_scripts )
{
// IsPushOnly returns false when given a script containing only pushes that
// are invalid due to truncation. IsPushOnly() is consensus critical
// because P2SH evaluation uses it, although this specific behavior should
// not be consensus critical as the P2SH evaluation would fail first due to
// the invalid push. Still, it doesn't hurt to test it explicitly.
static const unsigned char direct [ ] = { 1 } ;
BOOST_CHECK ( ! CScript ( direct , direct + sizeof ( direct ) ) . IsPushOnly ( ) ) ;
}
2015-07-30 20:56:00 -03:00
BOOST_AUTO_TEST_CASE ( script_GetScriptAsm )
{
2015-12-14 16:21:34 -03:00
BOOST_CHECK_EQUAL ( " OP_CHECKLOCKTIMEVERIFY " , ScriptToAsmStr ( CScript ( ) < < OP_NOP2 , true ) ) ;
BOOST_CHECK_EQUAL ( " OP_CHECKLOCKTIMEVERIFY " , ScriptToAsmStr ( CScript ( ) < < OP_CHECKLOCKTIMEVERIFY , true ) ) ;
BOOST_CHECK_EQUAL ( " OP_CHECKLOCKTIMEVERIFY " , ScriptToAsmStr ( CScript ( ) < < OP_NOP2 ) ) ;
BOOST_CHECK_EQUAL ( " OP_CHECKLOCKTIMEVERIFY " , ScriptToAsmStr ( CScript ( ) < < OP_CHECKLOCKTIMEVERIFY ) ) ;
2015-07-30 20:56:00 -03:00
2016-12-05 04:03:53 -03:00
std : : string derSig ( " 304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c5090 " ) ;
std : : string pubKey ( " 03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2 " ) ;
std : : vector < unsigned char > vchPubKey = ToByteVector ( ParseHex ( pubKey ) ) ;
2015-07-30 20:56:00 -03:00
BOOST_CHECK_EQUAL ( derSig + " 00 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 00 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 80 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 80 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " [ALL] " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 01 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " [NONE] " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 02 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " [SINGLE] " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 03 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " [ALL|ANYONECANPAY] " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 81 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " [NONE|ANYONECANPAY] " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 82 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " [SINGLE|ANYONECANPAY] " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 83 " ) ) < < vchPubKey , true ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 00 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 00 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 80 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 80 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 01 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 01 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 02 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 02 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 03 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 03 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 81 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 81 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 82 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 82 " ) ) < < vchPubKey ) ) ;
BOOST_CHECK_EQUAL ( derSig + " 83 " + pubKey , ScriptToAsmStr ( CScript ( ) < < ToByteVector ( ParseHex ( derSig + " 83 " ) ) < < vchPubKey ) ) ;
}
2020-09-16 01:00:43 -03:00
static CScript ScriptFromHex ( const std : : string & str )
2016-02-03 18:15:18 -03:00
{
2020-09-16 01:00:43 -03:00
std : : vector < unsigned char > data = ParseHex ( str ) ;
2016-02-03 18:15:18 -03:00
return CScript ( data . begin ( ) , data . end ( ) ) ;
}
BOOST_AUTO_TEST_CASE ( script_FindAndDelete )
{
// Exercise the FindAndDelete functionality
CScript s ;
CScript d ;
CScript expect ;
s = CScript ( ) < < OP_1 < < OP_2 ;
d = CScript ( ) ; // delete nothing should be a no-op
expect = s ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 0 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = CScript ( ) < < OP_1 < < OP_2 < < OP_3 ;
d = CScript ( ) < < OP_2 ;
expect = CScript ( ) < < OP_1 < < OP_3 ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = CScript ( ) < < OP_3 < < OP_1 < < OP_3 < < OP_3 < < OP_4 < < OP_3 ;
d = CScript ( ) < < OP_3 ;
expect = CScript ( ) < < OP_1 < < OP_4 ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 4 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 0302ff03 " ) ; // PUSH 0x02ff03 onto stack
d = ScriptFromHex ( " 0302ff03 " ) ;
expect = CScript ( ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 0302ff030302ff03 " ) ; // PUSH 0x2ff03 PUSH 0x2ff03
d = ScriptFromHex ( " 0302ff03 " ) ;
expect = CScript ( ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 2 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 0302ff030302ff03 " ) ;
d = ScriptFromHex ( " 02 " ) ;
expect = s ; // FindAndDelete matches entire opcodes
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 0 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 0302ff030302ff03 " ) ;
d = ScriptFromHex ( " ff " ) ;
expect = s ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 0 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
// This is an odd edge case: strip of the push-three-bytes
// prefix, leaving 02ff03 which is push-two-bytes:
s = ScriptFromHex ( " 0302ff030302ff03 " ) ;
d = ScriptFromHex ( " 03 " ) ;
expect = CScript ( ) < < ParseHex ( " ff03 " ) < < ParseHex ( " ff03 " ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 2 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
// Byte sequence that spans multiple opcodes:
s = ScriptFromHex ( " 02feed5169 " ) ; // PUSH(0xfeed) OP_1 OP_VERIFY
d = ScriptFromHex ( " feed51 " ) ;
expect = s ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 0 ) ; // doesn't match 'inside' opcodes
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 02feed5169 " ) ; // PUSH(0xfeed) OP_1 OP_VERIFY
d = ScriptFromHex ( " 02feed51 " ) ;
expect = ScriptFromHex ( " 69 " ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 516902feed5169 " ) ;
d = ScriptFromHex ( " feed51 " ) ;
expect = s ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 0 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 516902feed5169 " ) ;
d = ScriptFromHex ( " 02feed51 " ) ;
expect = ScriptFromHex ( " 516969 " ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = CScript ( ) < < OP_0 < < OP_0 < < OP_1 < < OP_1 ;
d = CScript ( ) < < OP_0 < < OP_1 ;
expect = CScript ( ) < < OP_0 < < OP_1 ; // FindAndDelete is single-pass
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = CScript ( ) < < OP_0 < < OP_0 < < OP_1 < < OP_0 < < OP_1 < < OP_1 ;
d = CScript ( ) < < OP_0 < < OP_1 ;
expect = CScript ( ) < < OP_0 < < OP_1 ; // FindAndDelete is single-pass
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 2 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
// Another weird edge case:
// End with invalid push (not enough data)...
s = ScriptFromHex ( " 0003feed " ) ;
d = ScriptFromHex ( " 03feed " ) ; // ... can remove the invalid push
expect = ScriptFromHex ( " 00 " ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
s = ScriptFromHex ( " 0003feed " ) ;
d = ScriptFromHex ( " 00 " ) ;
expect = ScriptFromHex ( " 03feed " ) ;
2018-04-04 13:02:24 -03:00
BOOST_CHECK_EQUAL ( FindAndDelete ( s , d ) , 1 ) ;
2016-02-03 18:15:18 -03:00
BOOST_CHECK ( s = = expect ) ;
}
2017-05-30 18:42:10 -04:00
BOOST_AUTO_TEST_CASE ( script_HasValidOps )
{
// Exercise the HasValidOps functionality
CScript script ;
script = ScriptFromHex ( " 76a9141234567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac " ) ; // Normal script
BOOST_CHECK ( script . HasValidOps ( ) ) ;
script = ScriptFromHex ( " 76a914ff34567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac " ) ;
BOOST_CHECK ( script . HasValidOps ( ) ) ;
script = ScriptFromHex ( " ff88ac " ) ; // Script with OP_INVALIDOPCODE explicit
BOOST_CHECK ( ! script . HasValidOps ( ) ) ;
script = ScriptFromHex ( " 88acc0 " ) ; // Script with undefined opcode
BOOST_CHECK ( ! script . HasValidOps ( ) ) ;
}
2020-10-18 13:03:57 -03:00
static CMutableTransaction TxFromHex ( const std : : string & str )
{
CMutableTransaction tx ;
VectorReader ( SER_DISK , SERIALIZE_TRANSACTION_NO_WITNESS , ParseHex ( str ) , 0 ) > > tx ;
return tx ;
}
static std : : vector < CTxOut > TxOutsFromJSON ( const UniValue & univalue )
{
assert ( univalue . isArray ( ) ) ;
std : : vector < CTxOut > prevouts ;
for ( size_t i = 0 ; i < univalue . size ( ) ; + + i ) {
CTxOut txout ;
VectorReader ( SER_DISK , 0 , ParseHex ( univalue [ i ] . get_str ( ) ) , 0 ) > > txout ;
prevouts . push_back ( std : : move ( txout ) ) ;
}
return prevouts ;
}
static CScriptWitness ScriptWitnessFromJSON ( const UniValue & univalue )
{
assert ( univalue . isArray ( ) ) ;
CScriptWitness scriptwitness ;
for ( size_t i = 0 ; i < univalue . size ( ) ; + + i ) {
auto bytes = ParseHex ( univalue [ i ] . get_str ( ) ) ;
scriptwitness . stack . push_back ( std : : move ( bytes ) ) ;
}
return scriptwitness ;
}
2020-10-26 09:54:21 -03:00
# if defined(HAVE_CONSENSUS_LIB)
2018-07-13 07:47:07 -04:00
/* Test simple (successful) usage of bitcoinconsensus_verify_script */
BOOST_AUTO_TEST_CASE ( bitcoinconsensus_verify_script_returns_true )
{
unsigned int libconsensus_flags = 0 ;
int nIn = 0 ;
CScript scriptPubKey ;
CScript scriptSig ;
CScriptWitness wit ;
scriptPubKey < < OP_1 ;
CTransaction creditTx = BuildCreditingTransaction ( scriptPubKey , 1 ) ;
CTransaction spendTx = BuildSpendingTransaction ( scriptSig , wit , creditTx ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < spendTx ;
bitcoinconsensus_error err ;
int result = bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , nIn , libconsensus_flags , & err ) ;
BOOST_CHECK_EQUAL ( result , 1 ) ;
BOOST_CHECK_EQUAL ( err , bitcoinconsensus_ERR_OK ) ;
}
/* Test bitcoinconsensus_verify_script returns invalid tx index err*/
BOOST_AUTO_TEST_CASE ( bitcoinconsensus_verify_script_tx_index_err )
{
unsigned int libconsensus_flags = 0 ;
int nIn = 3 ;
CScript scriptPubKey ;
CScript scriptSig ;
CScriptWitness wit ;
scriptPubKey < < OP_EQUAL ;
CTransaction creditTx = BuildCreditingTransaction ( scriptPubKey , 1 ) ;
CTransaction spendTx = BuildSpendingTransaction ( scriptSig , wit , creditTx ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < spendTx ;
bitcoinconsensus_error err ;
int result = bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , nIn , libconsensus_flags , & err ) ;
BOOST_CHECK_EQUAL ( result , 0 ) ;
BOOST_CHECK_EQUAL ( err , bitcoinconsensus_ERR_TX_INDEX ) ;
}
/* Test bitcoinconsensus_verify_script returns tx size mismatch err*/
BOOST_AUTO_TEST_CASE ( bitcoinconsensus_verify_script_tx_size )
{
unsigned int libconsensus_flags = 0 ;
int nIn = 0 ;
CScript scriptPubKey ;
CScript scriptSig ;
CScriptWitness wit ;
scriptPubKey < < OP_EQUAL ;
CTransaction creditTx = BuildCreditingTransaction ( scriptPubKey , 1 ) ;
CTransaction spendTx = BuildSpendingTransaction ( scriptSig , wit , creditTx ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < spendTx ;
bitcoinconsensus_error err ;
int result = bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) * 2 , nIn , libconsensus_flags , & err ) ;
BOOST_CHECK_EQUAL ( result , 0 ) ;
BOOST_CHECK_EQUAL ( err , bitcoinconsensus_ERR_TX_SIZE_MISMATCH ) ;
}
/* Test bitcoinconsensus_verify_script returns invalid tx serialization error */
BOOST_AUTO_TEST_CASE ( bitcoinconsensus_verify_script_tx_serialization )
{
unsigned int libconsensus_flags = 0 ;
int nIn = 0 ;
CScript scriptPubKey ;
CScript scriptSig ;
CScriptWitness wit ;
scriptPubKey < < OP_EQUAL ;
CTransaction creditTx = BuildCreditingTransaction ( scriptPubKey , 1 ) ;
CTransaction spendTx = BuildSpendingTransaction ( scriptSig , wit , creditTx ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < 0xffffffff ;
bitcoinconsensus_error err ;
int result = bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , nIn , libconsensus_flags , & err ) ;
BOOST_CHECK_EQUAL ( result , 0 ) ;
BOOST_CHECK_EQUAL ( err , bitcoinconsensus_ERR_TX_DESERIALIZE ) ;
}
/* Test bitcoinconsensus_verify_script returns amount required error */
BOOST_AUTO_TEST_CASE ( bitcoinconsensus_verify_script_amount_required_err )
{
unsigned int libconsensus_flags = bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS ;
int nIn = 0 ;
CScript scriptPubKey ;
CScript scriptSig ;
CScriptWitness wit ;
scriptPubKey < < OP_EQUAL ;
CTransaction creditTx = BuildCreditingTransaction ( scriptPubKey , 1 ) ;
CTransaction spendTx = BuildSpendingTransaction ( scriptSig , wit , creditTx ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < spendTx ;
bitcoinconsensus_error err ;
int result = bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , nIn , libconsensus_flags , & err ) ;
BOOST_CHECK_EQUAL ( result , 0 ) ;
BOOST_CHECK_EQUAL ( err , bitcoinconsensus_ERR_AMOUNT_REQUIRED ) ;
}
/* Test bitcoinconsensus_verify_script returns invalid flags err */
BOOST_AUTO_TEST_CASE ( bitcoinconsensus_verify_script_invalid_flags )
{
unsigned int libconsensus_flags = 1 < < 3 ;
int nIn = 0 ;
CScript scriptPubKey ;
CScript scriptSig ;
CScriptWitness wit ;
scriptPubKey < < OP_EQUAL ;
CTransaction creditTx = BuildCreditingTransaction ( scriptPubKey , 1 ) ;
CTransaction spendTx = BuildSpendingTransaction ( scriptSig , wit , creditTx ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
stream < < spendTx ;
bitcoinconsensus_error err ;
int result = bitcoinconsensus_verify_script ( scriptPubKey . data ( ) , scriptPubKey . size ( ) , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , nIn , libconsensus_flags , & err ) ;
BOOST_CHECK_EQUAL ( result , 0 ) ;
BOOST_CHECK_EQUAL ( err , bitcoinconsensus_ERR_INVALID_FLAGS ) ;
}
2020-10-26 09:54:21 -03:00
# endif // defined(HAVE_CONSENSUS_LIB)
2020-09-16 01:00:43 -03:00
static std : : vector < unsigned int > AllConsensusFlags ( )
{
std : : vector < unsigned int > ret ;
for ( unsigned int i = 0 ; i < 128 ; + + i ) {
unsigned int flag = 0 ;
if ( i & 1 ) flag | = SCRIPT_VERIFY_P2SH ;
if ( i & 2 ) flag | = SCRIPT_VERIFY_DERSIG ;
if ( i & 4 ) flag | = SCRIPT_VERIFY_NULLDUMMY ;
if ( i & 8 ) flag | = SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY ;
if ( i & 16 ) flag | = SCRIPT_VERIFY_CHECKSEQUENCEVERIFY ;
if ( i & 32 ) flag | = SCRIPT_VERIFY_WITNESS ;
if ( i & 64 ) flag | = SCRIPT_VERIFY_TAPROOT ;
// SCRIPT_VERIFY_WITNESS requires SCRIPT_VERIFY_P2SH
if ( flag & SCRIPT_VERIFY_WITNESS & & ! ( flag & SCRIPT_VERIFY_P2SH ) ) continue ;
// SCRIPT_VERIFY_TAPROOT requires SCRIPT_VERIFY_WITNESS
if ( flag & SCRIPT_VERIFY_TAPROOT & & ! ( flag & SCRIPT_VERIFY_WITNESS ) ) continue ;
ret . push_back ( flag ) ;
}
return ret ;
}
/** Precomputed list of all valid combinations of consensus-relevant script validation flags. */
static const std : : vector < unsigned int > ALL_CONSENSUS_FLAGS = AllConsensusFlags ( ) ;
static void AssetTest ( const UniValue & test )
{
BOOST_CHECK ( test . isObject ( ) ) ;
CMutableTransaction mtx = TxFromHex ( test [ " tx " ] . get_str ( ) ) ;
const std : : vector < CTxOut > prevouts = TxOutsFromJSON ( test [ " prevouts " ] ) ;
BOOST_CHECK ( prevouts . size ( ) = = mtx . vin . size ( ) ) ;
size_t idx = test [ " index " ] . get_int64 ( ) ;
unsigned int test_flags = ParseScriptFlags ( test [ " flags " ] . get_str ( ) ) ;
bool fin = test . exists ( " final " ) & & test [ " final " ] . get_bool ( ) ;
if ( test . exists ( " success " ) ) {
mtx . vin [ idx ] . scriptSig = ScriptFromHex ( test [ " success " ] [ " scriptSig " ] . get_str ( ) ) ;
mtx . vin [ idx ] . scriptWitness = ScriptWitnessFromJSON ( test [ " success " ] [ " witness " ] ) ;
CTransaction tx ( mtx ) ;
PrecomputedTransactionData txdata ;
txdata . Init ( tx , std : : vector < CTxOut > ( prevouts ) ) ;
CachingTransactionSignatureChecker txcheck ( & tx , idx , prevouts [ idx ] . nValue , true , txdata ) ;
for ( const auto flags : ALL_CONSENSUS_FLAGS ) {
// "final": true tests are valid for all flags. Others are only valid with flags that are
// a subset of test_flags.
if ( fin | | ( ( flags & test_flags ) = = flags ) ) {
bool ret = VerifyScript ( tx . vin [ idx ] . scriptSig , prevouts [ idx ] . scriptPubKey , & tx . vin [ idx ] . scriptWitness , flags , txcheck , nullptr ) ;
BOOST_CHECK ( ret ) ;
}
}
}
if ( test . exists ( " failure " ) ) {
mtx . vin [ idx ] . scriptSig = ScriptFromHex ( test [ " failure " ] [ " scriptSig " ] . get_str ( ) ) ;
mtx . vin [ idx ] . scriptWitness = ScriptWitnessFromJSON ( test [ " failure " ] [ " witness " ] ) ;
CTransaction tx ( mtx ) ;
PrecomputedTransactionData txdata ;
txdata . Init ( tx , std : : vector < CTxOut > ( prevouts ) ) ;
CachingTransactionSignatureChecker txcheck ( & tx , idx , prevouts [ idx ] . nValue , true , txdata ) ;
for ( const auto flags : ALL_CONSENSUS_FLAGS ) {
// If a test is supposed to fail with test_flags, it should also fail with any superset thereof.
if ( ( flags & test_flags ) = = test_flags ) {
bool ret = VerifyScript ( tx . vin [ idx ] . scriptSig , prevouts [ idx ] . scriptPubKey , & tx . vin [ idx ] . scriptWitness , flags , txcheck , nullptr ) ;
BOOST_CHECK ( ! ret ) ;
}
}
}
}
BOOST_AUTO_TEST_CASE ( script_assets_test )
{
2020-10-02 03:24:00 -03:00
// See src/test/fuzz/script_assets_test_minimizer.cpp for information on how to generate
// the script_assets_test.json file used by this test.
2020-09-16 01:00:43 -03:00
const char * dir = std : : getenv ( " DIR_UNIT_TEST_DATA " ) ;
BOOST_WARN_MESSAGE ( dir ! = nullptr , " Variable DIR_UNIT_TEST_DATA unset, skipping script_assets_test " ) ;
if ( dir = = nullptr ) return ;
auto path = fs : : path ( dir ) / " script_assets_test.json " ;
bool exists = fs : : exists ( path ) ;
BOOST_WARN_MESSAGE ( exists , " File $DIR_UNIT_TEST_DATA/script_assets_test.json not found, skipping script_assets_test " ) ;
if ( ! exists ) return ;
fs : : ifstream file ( path ) ;
BOOST_CHECK ( file . is_open ( ) ) ;
file . seekg ( 0 , std : : ios : : end ) ;
size_t length = file . tellg ( ) ;
file . seekg ( 0 , std : : ios : : beg ) ;
std : : string data ( length , ' \0 ' ) ;
file . read ( & data [ 0 ] , data . size ( ) ) ;
UniValue tests = read_json ( data ) ;
BOOST_CHECK ( tests . isArray ( ) ) ;
BOOST_CHECK ( tests . size ( ) > 0 ) ;
for ( size_t i = 0 ; i < tests . size ( ) ; i + + ) {
AssetTest ( tests [ i ] ) ;
}
file . close ( ) ;
}
2011-07-31 14:01:31 -04:00
BOOST_AUTO_TEST_SUITE_END ( )