@ -13,6 +13,7 @@
# include "util.h"
# include "util.h"
# include "utilstrencodings.h"
# include "utilstrencodings.h"
# include "test/test_bitcoin.h"
# include "test/test_bitcoin.h"
# include "rpc/server.h"
# if defined(HAVE_CONSENSUS_LIB)
# if defined(HAVE_CONSENSUS_LIB)
# include "script/bitcoinconsensus.h"
# include "script/bitcoinconsensus.h"
@ -118,7 +119,7 @@ ScriptError_t ParseScriptError(const std::string &name)
BOOST_FIXTURE_TEST_SUITE ( script_tests , BasicTestingSetup )
BOOST_FIXTURE_TEST_SUITE ( script_tests , BasicTestingSetup )
CMutableTransaction BuildCreditingTransaction ( const CScript & scriptPubKey )
CMutableTransaction BuildCreditingTransaction ( const CScript & scriptPubKey , int nValue = 0 )
{
{
CMutableTransaction txCredit ;
CMutableTransaction txCredit ;
txCredit . nVersion = 1 ;
txCredit . nVersion = 1 ;
@ -129,7 +130,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
txCredit . vin [ 0 ] . scriptSig = CScript ( ) < < CScriptNum ( 0 ) < < CScriptNum ( 0 ) ;
txCredit . vin [ 0 ] . scriptSig = CScript ( ) < < CScriptNum ( 0 ) < < CScriptNum ( 0 ) ;
txCredit . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_FINAL ;
txCredit . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_FINAL ;
txCredit . vout [ 0 ] . scriptPubKey = scriptPubKey ;
txCredit . vout [ 0 ] . scriptPubKey = scriptPubKey ;
txCredit . vout [ 0 ] . nValue = 0 ;
txCredit . vout [ 0 ] . nValue = nValue ;
return txCredit ;
return txCredit ;
}
}
@ -148,12 +149,12 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CSc
txSpend . vin [ 0 ] . scriptSig = scriptSig ;
txSpend . vin [ 0 ] . scriptSig = scriptSig ;
txSpend . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_FINAL ;
txSpend . vin [ 0 ] . nSequence = CTxIn : : SEQUENCE_FINAL ;
txSpend . vout [ 0 ] . scriptPubKey = CScript ( ) ;
txSpend . vout [ 0 ] . scriptPubKey = CScript ( ) ;
txSpend . vout [ 0 ] . nValue = 0 ;
txSpend . vout [ 0 ] . nValue = txCredit . vout [ 0 ] . nValue ;
return txSpend ;
return txSpend ;
}
}
void DoTest ( const CScript & scriptPubKey , const CScript & scriptSig , const CScriptWitness & scriptWitness , 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 , CAmount nValue = 0 )
{
{
bool expect = ( scriptError = = SCRIPT_ERR_OK ) ;
bool expect = ( scriptError = = SCRIPT_ERR_OK ) ;
if ( flags & SCRIPT_VERIFY_CLEANSTACK ) {
if ( flags & SCRIPT_VERIFY_CLEANSTACK ) {
@ -161,7 +162,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript
flags | = SCRIPT_VERIFY_WITNESS ;
flags | = SCRIPT_VERIFY_WITNESS ;
}
}
ScriptError err ;
ScriptError err ;
CMutableTransaction txCredit = BuildCreditingTransaction ( scriptPubKey ) ;
CMutableTransaction txCredit = BuildCreditingTransaction ( scriptPubKey , nValue ) ;
CMutableTransaction tx = BuildSpendingTransaction ( scriptSig , scriptWitness , txCredit ) ;
CMutableTransaction tx = BuildSpendingTransaction ( scriptSig , scriptWitness , txCredit ) ;
CMutableTransaction tx2 = tx ;
CMutableTransaction tx2 = tx ;
BOOST_CHECK_MESSAGE ( VerifyScript ( scriptSig , scriptPubKey , & scriptWitness , 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 ) ;
@ -276,6 +277,7 @@ private:
std : : string comment ;
std : : string comment ;
int flags ;
int flags ;
int scriptError ;
int scriptError ;
CAmount nValue ;
void DoPush ( )
void DoPush ( )
{
{
@ -293,7 +295,7 @@ private:
}
}
public :
public :
TestBuilder ( const CScript & script_ , const std : : string & comment_ , int flags_ , bool P2SH = false , WitnessMode wm = WITNESS_NONE , int witnessversion = 0 ) : script ( script_ ) , havePush ( false ) , comment ( comment_ ) , flags ( flags_ ) , scriptError ( SCRIPT_ERR_OK )
TestBuilder ( const CScript & script_ , const std : : string & comment_ , int flags_ , bool P2SH = false , WitnessMode wm = WITNESS_NONE , int witnessversion = 0 , CAmount nValue_ = 0 ) : script ( script_ ) , havePush ( false ) , comment ( comment_ ) , flags ( flags_ ) , scriptError ( SCRIPT_ERR_OK ) , nValue ( nValue_ )
{
{
CScript scriptPubKey = script ;
CScript scriptPubKey = script ;
if ( wm = = WITNESS_PKH ) {
if ( wm = = WITNESS_PKH ) {
@ -311,7 +313,7 @@ public:
redeemscript = scriptPubKey ;
redeemscript = scriptPubKey ;
scriptPubKey = CScript ( ) < < OP_HASH160 < < ToByteVector ( CScriptID ( redeemscript ) ) < < OP_EQUAL ;
scriptPubKey = CScript ( ) < < OP_HASH160 < < ToByteVector ( CScriptID ( redeemscript ) ) < < OP_EQUAL ;
}
}
creditTx = BuildCreditingTransaction ( scriptPubKey ) ;
creditTx = BuildCreditingTransaction ( scriptPubKey , nValue ) ;
spendTx = BuildSpendingTransaction ( CScript ( ) , CScriptWitness ( ) , creditTx ) ;
spendTx = BuildSpendingTransaction ( CScript ( ) , CScriptWitness ( ) , creditTx ) ;
}
}
@ -346,9 +348,9 @@ public:
return * this ;
return * this ;
}
}
TestBuilder & PushSig ( const CKey & key , int nHashType = SIGHASH_ALL , unsigned int lenR = 32 , unsigned int lenS = 32 , SigVersion sigversion = SIGVERSION_BASE )
TestBuilder & PushSig ( const CKey & key , int nHashType = SIGHASH_ALL , unsigned int lenR = 32 , unsigned int lenS = 32 , SigVersion sigversion = SIGVERSION_BASE , CAmount amount = 0 )
{
{
uint256 hash = SignatureHash ( script , spendTx , 0 , nHashType , 0 , sigversion ) ;
uint256 hash = SignatureHash ( script , spendTx , 0 , nHashType , amount , sigversion ) ;
std : : vector < unsigned char > vchSig , r , s ;
std : : vector < unsigned char > vchSig , r , s ;
uint32_t iter = 0 ;
uint32_t iter = 0 ;
do {
do {
@ -364,9 +366,11 @@ public:
return * this ;
return * this ;
}
}
TestBuilder & PushWitSig ( const CKey & key , int nHashType = SIGHASH_ALL , unsigned int lenR = 32 , unsigned int lenS = 32 , SigVersion sigversion = SIGVERSION_WITNESS_V0 )
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 )
{
{
return PushSig ( key , nHashType , lenR , lenS , sigversion ) . AsWit ( ) ;
if ( amount = = - 1 )
amount = nValue ;
return PushSig ( key , nHashType , lenR , lenS , sigversion , amount ) . AsWit ( ) ;
}
}
TestBuilder & Push ( const CPubKey & pubkey )
TestBuilder & Push ( const CPubKey & pubkey )
@ -411,7 +415,7 @@ public:
{
{
TestBuilder copy = * this ; // Make a copy so we can rollback the push.
TestBuilder copy = * this ; // Make a copy so we can rollback the push.
DoPush ( ) ;
DoPush ( ) ;
DoTest ( creditTx . vout [ 0 ] . scriptPubKey , spendTx . vin [ 0 ] . scriptSig , scriptWitness , flags , comment , scriptError ) ;
DoTest ( creditTx . vout [ 0 ] . scriptPubKey , spendTx . vin [ 0 ] . scriptSig , scriptWitness , flags , comment , scriptError , nValue ) ;
* this = copy ;
* this = copy ;
return * this ;
return * this ;
}
}
@ -433,6 +437,7 @@ public:
for ( unsigned i = 0 ; i < scriptWitness . stack . size ( ) ; i + + ) {
for ( unsigned i = 0 ; i < scriptWitness . stack . size ( ) ; i + + ) {
wit . push_back ( HexStr ( scriptWitness . stack [ i ] ) ) ;
wit . push_back ( HexStr ( scriptWitness . stack [ i ] ) ) ;
}
}
wit . push_back ( ValueFromAmount ( nValue ) ) ;
array . push_back ( wit ) ;
array . push_back ( wit ) ;
}
}
array . push_back ( FormatScript ( spendTx . vin [ 0 ] . scriptSig ) ) ;
array . push_back ( FormatScript ( spendTx . vin [ 0 ] . scriptSig ) ) ;
@ -734,17 +739,17 @@ BOOST_AUTO_TEST_CASE(script_build)
) . PushSig ( keys . key0 ) . PushRedeem ( ) ) ;
) . PushSig ( keys . key0 ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" Basic P2WSH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_SH
" Basic P2WSH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_SH ,
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) ) ;
0 , 1 ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
" Basic P2WPKH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_PKH
" Basic P2WPKH " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_PKH ,
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) ) ;
0 , 1 ) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" Basic P2SH(P2WSH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WITNESS_SH
" Basic P2SH(P2WSH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WITNESS_SH ,
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
0 , 1 ) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
" Basic P2SH(P2WPKH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WITNESS_PKH
" Basic P2SH(P2WPKH) " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WITNESS_PKH ,
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . PushRedeem ( ) ) ;
0 , 1 ) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey0 ) . AsWit ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) < < OP_CHECKSIG ,
" Basic P2WSH with the wrong key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_SH
" Basic P2WSH with the wrong key " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_SH
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
) . PushWitSig ( keys . key0 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
@ -769,6 +774,18 @@ BOOST_AUTO_TEST_CASE(script_build)
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey1 ) ,
" Basic P2SH(P2WPKH) with the wrong key but no WITNESS " , SCRIPT_VERIFY_P2SH , true , WITNESS_PKH
" Basic P2SH(P2WPKH) with the wrong key but no WITNESS " , SCRIPT_VERIFY_P2SH , true , WITNESS_PKH
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) . PushRedeem ( ) ) ;
) . PushWitSig ( keys . key0 ) . Push ( keys . pubkey1 ) . AsWit ( ) . PushRedeem ( ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) < < OP_CHECKSIG ,
" Basic P2WSH with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_SH ,
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . PushWitRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
" Basic P2WPKH with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , false , WITNESS_PKH ,
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 ,
" Basic P2SH(P2WSH) with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WITNESS_SH ,
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . PushWitRedeem ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
" Basic P2SH(P2WPKH) with wrong value " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH , true , WITNESS_PKH ,
0 , 0 ) . PushWitSig ( keys . key0 , 1 ) . Push ( keys . pubkey0 ) . AsWit ( ) . PushRedeem ( ) . ScriptError ( SCRIPT_ERR_EVAL_FALSE ) ) ;
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
tests . push_back ( TestBuilder ( CScript ( ) < < ToByteVector ( keys . pubkey0 ) ,
" P2WPKH with future witness version " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
" P2WPKH with future witness version " , SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
@ -841,20 +858,25 @@ BOOST_AUTO_TEST_CASE(script_json_test)
{
{
// Read tests from test/data/script_tests.json
// Read tests from test/data/script_tests.json
// Format is an array of arrays
// Format is an array of arrays
// Inner arrays are [ ["wit"...]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
// Inner arrays are [ ["wit"..., nValue ]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
// ... where scriptSig and scriptPubKey are stringified
// ... where scriptSig and scriptPubKey are stringified
// scripts.
// scripts.
// If a witness is given, then the last value in the array should be the
// amount (nValue) to use in the crediting tx
UniValue tests = read_json ( std : : string ( json_tests : : script_tests , json_tests : : script_tests + sizeof ( json_tests : : script_tests ) ) ) ;
UniValue tests = read_json ( std : : string ( json_tests : : script_tests , json_tests : : script_tests + sizeof ( json_tests : : script_tests ) ) ) ;
for ( unsigned int idx = 0 ; idx < tests . size ( ) ; idx + + ) {
for ( unsigned int idx = 0 ; idx < tests . size ( ) ; idx + + ) {
UniValue test = tests [ idx ] ;
UniValue test = tests [ idx ] ;
string strTest = test . write ( ) ;
string strTest = test . write ( ) ;
CScriptWitness witness ;
CScriptWitness witness ;
CAmount nValue = 0 ;
unsigned int pos = 0 ;
unsigned int pos = 0 ;
if ( test . size ( ) > 0 & & test [ pos ] . isArray ( ) ) {
if ( test . size ( ) > 0 & & test [ pos ] . isArray ( ) ) {
for ( unsigned int i = 0 ; i < test [ pos ] . size ( ) ; i + + ) {
unsigned int i = 0 ;
for ( i = 0 ; i < test [ pos ] . size ( ) - 1 ; i + + ) {
witness . stack . push_back ( ParseHex ( test [ pos ] [ i ] . get_str ( ) ) ) ;
witness . stack . push_back ( ParseHex ( test [ pos ] [ i ] . get_str ( ) ) ) ;
}
}
nValue = AmountFromValue ( test [ pos ] [ i ] ) ;
pos + + ;
pos + + ;
}
}
if ( test . size ( ) < 4 + pos ) // Allow size > 3; extra stuff ignored (useful for comments)
if ( test . size ( ) < 4 + pos ) // Allow size > 3; extra stuff ignored (useful for comments)
@ -871,7 +893,7 @@ BOOST_AUTO_TEST_CASE(script_json_test)
unsigned int scriptflags = ParseScriptFlags ( test [ pos + + ] . get_str ( ) ) ;
unsigned int scriptflags = ParseScriptFlags ( test [ pos + + ] . get_str ( ) ) ;
int scriptError = ParseScriptError ( test [ pos + + ] . get_str ( ) ) ;
int scriptError = ParseScriptError ( test [ pos + + ] . get_str ( ) ) ;
DoTest ( scriptPubKey , scriptSig , witness , scriptflags , strTest , scriptError ) ;
DoTest ( scriptPubKey , scriptSig , witness , scriptflags , strTest , scriptError , nValue ) ;
}
}
}
}