@ -88,7 +88,14 @@ static ScriptErrorDesc script_errors[]={
{ SCRIPT_ERR_SIG_NULLDUMMY , " SIG_NULLDUMMY " } ,
{ SCRIPT_ERR_PUBKEYTYPE , " PUBKEYTYPE " } ,
{ SCRIPT_ERR_CLEANSTACK , " CLEANSTACK " } ,
{ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS , " DISCOURAGE_UPGRADABLE_NOPS " }
{ 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 " } ,
} ;
const char * FormatScriptError ( ScriptError_t err )
@ -127,13 +134,15 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
return txCredit ;
}
CMutableTransaction BuildSpendingTransaction ( const CScript & scriptSig , const C MutableTransaction& txCredit )
CMutableTransaction BuildSpendingTransaction ( const CScript & scriptSig , const C ScriptWitness& scriptWitness , const C MutableTransaction& txCredit )
{
CMutableTransaction txSpend ;
txSpend . nVersion = 1 ;
txSpend . nLockTime = 0 ;
txSpend . vin . resize ( 1 ) ;
txSpend . vout . resize ( 1 ) ;
txSpend . wit . vtxinwit . resize ( 1 ) ;
txSpend . wit . vtxinwit [ 0 ] . scriptWitness = scriptWitness ;
txSpend . vin [ 0 ] . prevout . hash = txCredit . GetHash ( ) ;
txSpend . vin [ 0 ] . prevout . n = 0 ;
txSpend . vin [ 0 ] . scriptSig = scriptSig ;
@ -144,7 +153,7 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu
return txSpend ;
}
void DoTest ( const CScript & scriptPubKey , const CScript & scriptSig , int flags , const std : : string & message , int scriptError )
void DoTest ( const CScript & scriptPubKey , const CScript & scriptSig , const CScriptWitness & scriptWitness , int flags , const std : : string & message , int scriptError )
{
bool expect = ( scriptError = = SCRIPT_ERR_OK ) ;
if ( flags & SCRIPT_VERIFY_CLEANSTACK ) {
@ -153,12 +162,12 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, co
}
ScriptError err ;
CMutableTransaction txCredit = BuildCreditingTransaction ( scriptPubKey ) ;
CMutableTransaction tx = BuildSpendingTransaction ( scriptSig , txCredit) ;
CMutableTransaction tx = BuildSpendingTransaction ( scriptSig , scriptWitness, txCredit) ;
CMutableTransaction tx2 = tx ;
BOOST_CHECK_MESSAGE ( VerifyScript ( scriptSig , scriptPubKey , NULL , flags , MutableTransactionSignatureChecker ( & tx , 0 , txCredit . vout [ 0 ] . nValue ) , & err ) = = expect , message ) ;
BOOST_CHECK_MESSAGE ( VerifyScript ( scriptSig , scriptPubKey , & scriptWitness , flags , MutableTransactionSignatureChecker ( & tx , 0 , txCredit . vout [ 0 ] . nValue ) , & err ) = = expect , message ) ;
BOOST_CHECK_MESSAGE ( err = = scriptError , std : : string ( FormatScriptError ( err ) ) + " where " + std : : string ( FormatScriptError ( ( ScriptError_t ) scriptError ) ) + " expected: " + message ) ;
# if defined(HAVE_CONSENSUS_LIB)
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION ) ;
CDataStream stream ( SER_NETWORK , PROTOCOL_VERSION | SERIALIZE_TRANSACTION_WITNESS ) ;
stream < < tx2 ;
if ( flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS ) {
BOOST_CHECK_MESSAGE ( bitcoinconsensus_verify_script_with_amount ( begin_ptr ( scriptPubKey ) , scriptPubKey . size ( ) , txCredit . vout [ 0 ] . nValue , ( const unsigned char * ) & stream [ 0 ] , stream . size ( ) , 0 , flags , NULL ) = = expect , message ) ;
@ -280,7 +289,7 @@ public:
} else {
creditTx = BuildCreditingTransaction ( redeemScript ) ;
}
spendTx = BuildSpendingTransaction ( CScript ( ) , creditTx) ;
spendTx = BuildSpendingTransaction ( CScript ( ) , CScriptWitness( ) , creditTx) ;
}
TestBuilder & ScriptError ( ScriptError_t err )
@ -363,7 +372,7 @@ public:
{
TestBuilder copy = * this ; // Make a copy so we can rollback the push.
DoPush ( ) ;
DoTest ( creditTx . vout [ 0 ] . scriptPubKey , spendTx . vin [ 0 ] . scriptSig , flags, comment , scriptError ) ;
DoTest ( creditTx . vout [ 0 ] . scriptPubKey , spendTx . vin [ 0 ] . scriptSig , CScriptWitness( ) , flags, comment , scriptError ) ;
* this = copy ;
return * this ;
}
@ -706,7 +715,7 @@ BOOST_AUTO_TEST_CASE(script_json_test)
{
// Read tests from test/data/script_tests.json
// Format is an array of arrays
// Inner arrays are [ "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
// Inner arrays are [ ["wit"...]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
UniValue tests = read_json ( std : : string ( json_tests : : script_tests , json_tests : : script_tests + sizeof ( json_tests : : script_tests ) ) ) ;
@ -714,21 +723,29 @@ BOOST_AUTO_TEST_CASE(script_json_test)
for ( unsigned int idx = 0 ; idx < tests . size ( ) ; idx + + ) {
UniValue test = tests [ idx ] ;
string strTest = test . write ( ) ;
if ( test . size ( ) < 4 ) // Allow size > 3; extra stuff ignored (useful for comments)
CScriptWitness witness ;
unsigned int pos = 0 ;
if ( test . size ( ) > 0 & & test [ pos ] . isArray ( ) ) {
for ( unsigned int i = 0 ; i < test [ pos ] . size ( ) ; i + + ) {
witness . stack . push_back ( ParseHex ( test [ pos ] [ i ] . get_str ( ) ) ) ;
}
pos + + ;
}
if ( test . size ( ) < 4 + pos ) // Allow size > 3; extra stuff ignored (useful for comments)
{
if ( test . size ( ) ! = 1 ) {
BOOST_ERROR ( " Bad test: " < < strTest ) ;
}
continue ;
}
string scriptSigString = test [ 0 ] . get_str ( ) ;
string scriptSigString = test [ pos + + ] . get_str ( ) ;
CScript scriptSig = ParseScript ( scriptSigString ) ;
string scriptPubKeyString = test [ 1 ] . get_str ( ) ;
string scriptPubKeyString = test [ pos + + ] . get_str ( ) ;
CScript scriptPubKey = ParseScript ( scriptPubKeyString ) ;
unsigned int scriptflags = ParseScriptFlags ( test [ 2 ] . get_str ( ) ) ;
int scriptError = ParseScriptError ( test [ 3 ] . get_str ( ) ) ;
unsigned int scriptflags = ParseScriptFlags ( test [ pos + + ] . get_str ( ) ) ;
int scriptError = ParseScriptError ( test [ pos + + ] . get_str ( ) ) ;
DoTest ( scriptPubKey , scriptSig , scriptflags, strTest , scriptError ) ;
DoTest ( scriptPubKey , scriptSig , witness, scriptflags, strTest , scriptError ) ;
}
}
@ -806,7 +823,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
scriptPubKey12 < < OP_1 < < ToByteVector ( key1 . GetPubKey ( ) ) < < ToByteVector ( key2 . GetPubKey ( ) ) < < OP_2 < < OP_CHECKMULTISIG ;
CMutableTransaction txFrom12 = BuildCreditingTransaction ( scriptPubKey12 ) ;
CMutableTransaction txTo12 = BuildSpendingTransaction ( CScript ( ) , txFrom12) ;
CMutableTransaction txTo12 = BuildSpendingTransaction ( CScript ( ) , CScriptWitness( ) , txFrom12) ;
CScript goodsig1 = sign_multisig ( scriptPubKey12 , key1 , txTo12 ) ;
BOOST_CHECK ( VerifyScript ( goodsig1 , scriptPubKey12 , NULL , flags , MutableTransactionSignatureChecker ( & txTo12 , 0 , txFrom12 . vout [ 0 ] . nValue ) , & err ) ) ;
@ -837,7 +854,7 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
scriptPubKey23 < < OP_2 < < ToByteVector ( key1 . GetPubKey ( ) ) < < ToByteVector ( key2 . GetPubKey ( ) ) < < ToByteVector ( key3 . GetPubKey ( ) ) < < OP_3 < < OP_CHECKMULTISIG ;
CMutableTransaction txFrom23 = BuildCreditingTransaction ( scriptPubKey23 ) ;
CMutableTransaction txTo23 = BuildSpendingTransaction ( CScript ( ) , txFrom23) ;
CMutableTransaction txTo23 = BuildSpendingTransaction ( CScript ( ) , CScriptWitness( ) , txFrom23) ;
std : : vector < CKey > keys ;
keys . push_back ( key1 ) ; keys . push_back ( key2 ) ;
@ -910,7 +927,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
}
CMutableTransaction txFrom = BuildCreditingTransaction ( GetScriptForDestination ( keys [ 0 ] . GetPubKey ( ) . GetID ( ) ) ) ;
CMutableTransaction txTo = BuildSpendingTransaction ( CScript ( ) , txFrom) ;
CMutableTransaction txTo = BuildSpendingTransaction ( CScript ( ) , CScriptWitness( ) , txFrom) ;
CScript & scriptPubKey = txFrom . vout [ 0 ] . scriptPubKey ;
CScript & scriptSig = txTo . vin [ 0 ] . scriptSig ;