@ -15,14 +15,81 @@
# include "CCPayments.h"
/*
Payments CC is a catchall CC , supported invoices , zpayments , automated funds allocation , including token based revshare
/*
0 ) create < - update_allowed flag , locked_blocks , minrelease , list of scriptPubKeys , allocations
1 ) lock amount < create txid > to global CC address
2 ) release amount - > vout [ i ] will be scriptPubKeys [ i ] and ( amount * allocations [ i ] ) / sumallocations [ ] ( only using vins that have been locked for locked_blocks + ) . will make a tx with less than amount if it can find enough vins for minrelease amount
3 ) update ( vins from all scriptPubkeys ) new update_allowed flag , locked_blocks , minrelease , list of scriptPubKeys , allocations ( only if update_allowed )
4 ) info txid - > display parameters , funds
5 ) list - > all txids
*/
// start of consensus code
CScript EncodePaymentsTxidOpRet ( int32_t allocation , std : : vector < uint8_t > scriptPubKey , std : : vector < uint8_t > opret )
{
CScript opret ; uint8_t evalcode = EVAL_PAYMENTS ;
opret < < OP_RETURN < < E_MARSHAL ( ss < < evalcode < < ' T ' < < allocation < < scriptPubKey < < opret ) ;
return ( opret ) ;
}
uint8_t DecodePaymentsTxidOpRet ( CScript scriptPubKey , int32_t & allocation , std : : vector < uint8_t > & scriptPubKey , std : : vector < uint8_t > & opret )
{
std : : vector < uint8_t > vopret ; uint8_t * script , e , f ;
GetOpReturnData ( scriptPubKey , vopret ) ;
script = ( uint8_t * ) vopret . data ( ) ;
if ( vopret . size ( ) > 2 & & E_UNMARSHAL ( vopret , ss > > e ; ss > > f ; ss > > allocation ; ss > > scriptPubKey ; ss > > opret ) ! = 0 )
{
if ( e = = EVAL_PAYMENTS & & f = = ' T ' )
return ( f ) ;
}
return ( 0 ) ;
}
CScript EncodePaymentsFundOpRet ( uint256 checktxid )
{
CScript opret ; uint8_t evalcode = EVAL_PAYMENTS ;
opret < < OP_RETURN < < E_MARSHAL ( ss < < evalcode < < ' F ' < < checktxid ) ;
return ( opret ) ;
}
uint8_t DecodePaymentsFundOpRet ( CScript scriptPubKey , uint256 & checktxid )
{
std : : vector < uint8_t > vopret ; uint8_t * script , e , f ;
GetOpReturnData ( scriptPubKey , vopret ) ;
script = ( uint8_t * ) vopret . data ( ) ;
if ( vopret . size ( ) > 2 & & E_UNMARSHAL ( vopret , ss > > e ; ss > > f ; ss > > checktxid ) ! = 0 )
{
if ( e = = EVAL_PAYMENTS & & f = = ' F ' )
return ( f ) ;
}
return ( 0 ) ;
}
CScript EncodePaymentsOpRet ( int32_t updateflag , int32_t lockedblocks , int32_t minrelease , int32_t totalallocations , std : : vector < uint256 > txidoprets )
{
CScript opret ; uint8_t evalcode = EVAL_PAYMENTS ;
opret < < OP_RETURN < < E_MARSHAL ( ss < < evalcode < < ' C ' < < updateflag < < lockedblocks < < minrelease < < totalallocations < < txidoprets ) ;
return ( opret ) ;
}
uint8_t DecodePaymentsOpRet ( CScript scriptPubKey , int32_t & updateflag , int32_t & lockedblocks , int32_t & minrelease , int32_t & totalallocations , std : : vector < uint256 > & txidoprets )
{
std : : vector < uint8_t > vopret ; uint8_t * script , e , f ;
GetOpReturnData ( scriptPubKey , vopret ) ;
script = ( uint8_t * ) vopret . data ( ) ;
if ( vopret . size ( ) > 2 & & E_UNMARSHAL ( vopret , ss > > e ; ss > > f ; ss > > updateflag ; ss > > lockedblocks ; ss > > minrelease ; ss > > totalallocations ; ss > > txidoprets ) ! = 0 )
{
if ( e = = EVAL_PAYMENTS & & f = = ' C ' )
return ( f ) ;
}
return ( 0 ) ;
}
int64_t IsPaymentsvout ( struct CCcontract_info * cp , const CTransaction & tx , int32_t v )
{
char destaddr [ 64 ] ;
@ -74,144 +141,434 @@ bool PaymentsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
bool PaymentsValidate ( struct CCcontract_info * cp , Eval * eval , const CTransaction & tx , uint32_t nIn )
{
int32_t numvins , numvouts , preventCCvins , preventCCvouts , i , numblocks ; bool retval ; uint256 txid ; uint8_t hash [ 32 ] ; char str [ 65 ] , destaddr [ 64 ] ;
return eval - > Invalid ( " no validation yet " ) ;
std : : vector < std : : pair < CAddressIndexKey , CAmount > > txids ;
numvins = tx . vin . size ( ) ;
numvouts = tx . vout . size ( ) ;
preventCCvins = preventCCvouts = - 1 ;
if ( numvouts < 1 )
return eval - > Invalid ( " no vouts " ) ;
else
return ( true ) ;
}
// end of consensus code
// helper functions for rpc calls in rpcwallet.cpp
int64_t AddPaymentsInputs ( struct CCcontract_info * cp , CMutableTransaction & mtx , CPubKey txidpk , int64_t total , int32_t maxinputs , uint256 createtxid )
{
char coinaddr [ 64 ] ; int64_t nValue , threshold , price , totalinputs = 0 ; uint256 txid , checktxid , hashBlock ; std : : vector < uint8_t > origpubkey ; CTransaction vintx , tx ; int32_t iter , vout , n = 0 ;
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > unspentOutputs ;
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS ;
if ( maxinputs > 0 )
threshold = total / maxinputs ;
else threshold = total ;
for ( iter = 0 ; iter < 2 ; iter + + )
{
for ( i = 0 ; i < numvins ; i + + )
if ( iter = = 0 )
GetCCaddress ( cp , coinaddr , Paymentspk ) ;
else GetCCaddress1of2 ( cp , coinaddr , Paymentspk , txidpk ) ;
SetCCunspents ( unspentOutputs , coinaddr ) ;
for ( std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > : : const_iterator it = unspentOutputs . begin ( ) ; it ! = unspentOutputs . end ( ) ; it + + )
{
if ( IsCCInput ( tx . vin [ 0 ] . scriptSig ) = = 0 )
txid = it - > first . txhash ;
vout = ( int32_t ) it - > first . index ;
if ( GetTransaction ( txid , vintx , hashBlock , false ) ! = 0 )
{
return eval - > Invalid ( " illegal normal vini " ) ;
if ( iter = = 0 )
{
std : : vector < uint8_t > scriptPubKey , opret ;
if ( myGetTransaction ( txid , tx , hashBlock ) = = 0 | | tx . vout . size ( ) < 2 | | DecodePaymentsFundOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , checktxid ) ! = ' F ' | | checktxid ! = createtxid )
continue ;
}
if ( ( nValue = IsPaymentsvout ( cp , vintx , vout ) ) > PAYMENTS_TXFEE & & nValue > = threshold & & myIsutxo_spentinmempool ( ignoretxid , ignorevin , txid , vout ) = = 0 )
{
if ( total ! = 0 & & maxinputs ! = 0 )
mtx . vin . push_back ( CTxIn ( txid , vout , CScript ( ) ) ) ;
nValue = it - > second . satoshis ;
totalinputs + = nValue ;
n + + ;
if ( ( total > 0 & & totalinputs > = total ) | | ( maxinputs > 0 & & n > = maxinputs ) )
break ;
}
}
}
//fprintf(stderr,"check amounts\n");
if ( PaymentsExactAmounts ( cp , eval , tx , 1 , 10000 ) = = false )
}
return ( totalinputs ) ;
}
UniValue payments_rawtxresult ( UniValue & result , std : : string rawtx , int32_t broadcastflag )
{
CTransaction tx ;
if ( rawtx . size ( ) > 0 )
{
result . push_back ( Pair ( " hex " , rawtx ) ) ;
if ( DecodeHexTx ( tx , rawtx ) ! = 0 )
{
if ( broadcastflag ! = 0 & & myAddtomempool ( tx ) ! = 0 )
RelayTransaction ( tx ) ;
result . push_back ( Pair ( " txid " , tx . GetHash ( ) . ToString ( ) ) ) ;
result . push_back ( Pair ( " result " , " success " ) ) ;
} else result . push_back ( Pair ( " error " , " decode hex " ) ) ;
} else result . push_back ( Pair ( " error " , " couldnt finalize payments CCtx " ) ) ;
return ( result ) ;
}
cJSON * payments_reparse ( int32_t * nump , char * jsonstr )
{
cJSON * params ; char * newstr ; int32_t i , j ;
* nump = 0 ;
if ( jsonstr ! = 0 )
{
if ( jsonstr [ 0 ] = = ' " ' & & jsonstr [ strlen ( jsonstr ) - 1 ] = = ' " ' )
{
fprintf ( stderr , " Paymentsget invalid amount \n " ) ;
return false ;
jsonstr [ strlen ( jsonstr ) - 1 ] = 0 ;
jsonstr + + ;
}
else
newstr = ( char * ) malloc ( strlen ( jsonstr ) + 1 ) ;
for ( i = j = 0 ; jsonstr [ i ] ! = 0 ; i + + )
{
txid = tx . GetHash ( ) ;
memcpy ( hash , & txid , sizeof ( hash ) ) ;
retval = PreventCC ( eval , tx , preventCCvins , numvins , preventCCvouts , numvouts ) ;
if ( retval ! = 0 )
fprintf ( stderr , " Paymentsget validated \n " ) ;
else fprintf ( stderr , " Paymentsget invalid \n " ) ;
return ( retval ) ;
if ( jsonstr [ i ] = = ' % ' & & jsonstr [ i + 1 ] = = ' 2 ' & & jsonstr [ i + 2 ] = = ' 2 ' )
{
newstr [ j + + ] = ' " ' ;
i + = 2 ;
}
else if ( jsonstr [ i ] = = ' \' ' )
newstr [ j + + ] = ' " ' ;
else newstr [ j + + ] = jsonstr [ i ] ;
}
}
newstr [ j ] = 0 ;
params = cJSON_Parse ( newstr ) ;
if ( 0 & & params ! = 0 )
printf ( " new.(%s) -> %s \n " , newstr , jprint ( params , 0 ) ) ;
free ( newstr ) ;
* nump = cJSON_GetArraySize ( params ) ;
} else params = 0 ;
return ( params ) ;
}
// end of consensus code
// helper functions for rpc calls in rpcwallet.cpp
uint256 payments_juint256 ( cJSON * obj )
{
uint256 tmp ; bits256 t = jbits256 ( obj , 0 ) ;
memcpy ( & tmp , & t , sizeof ( tmp ) ) ;
return ( revuint256 ( tmp ) ) ;
}
int64_t AddPaymentsInputs ( struct CCcontract_info * cp , CMutableTransaction & mtx , CPubKey pk , int64_t total , int32_t maxinputs )
int32_t payments_parsehexdata ( std : : vector < uint8_t > & hexdata , cJSON * item , int32_t len )
{
// add threshold check
char coinaddr [ 64 ] ; int64_t nValue , price , totalinputs = 0 ; uint256 txid , hashBlock ; std : : vector < uint8_t > origpubkey ; CTransaction vintx ; int32_t vout , n = 0 ;
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > unspentOutputs ;
GetCCaddress ( cp , coinaddr , pk ) ;
SetCCunspents ( unspentOutputs , coinaddr ) ;
for ( std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > : : const_iterator it = unspentOutputs . begin ( ) ; it ! = unspentOutputs . end ( ) ; it + + )
char * hexstr ; int32_t val ;
if ( ( hexstr = jstr ( item , 0 ) ) ! = 0 & & ( ( val = is_hexstr ( hexstr , 0 ) ) = = len * 2 | | ( val > 0 & & len = = 0 ) ) )
{
txid = it - > first . txhash ;
vout = ( int32_t ) it - > first . index ;
// no need to prevent dup
if ( GetTransaction ( txid , vintx , hashBlock , false ) ! = 0 )
val > > = 1 ;
hexdata . resize ( val ) ;
decode_hex ( hexdata , val , hexstr ) ;
return ( 0 ) ;
} else return ( - 1 ) ;
}
UniValue PaymentsRelease ( struct CCcontract_info * cp , char * jsonstr )
{
CMutableTransaction tmpmtx , mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ; UniValue result ( UniValue : : VOBJ ) ; uint256 createtxid , hashBlock ;
CTransaction tx , txO ; CPubKey mypk , txidpk , Paymentspk ; int32_t i , n , numoprets = 0 , updateflag , lockedblocks , minrelease , totalallocations , checkallocations = 0 , allocation ; int64_t inputsum , amount , CCchange = 0 ; CTxOut vout ; CScript onlyopret ; char txidaddr [ 64 ] ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
mypk = pubkey2pk ( Mypubkey ( ) ) ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
if ( params ! = 0 & & n = = 2 )
{
createtxid = payments_juint256 ( jitem ( params , 0 ) ) ;
amount = jdouble ( jitem ( params , 1 ) , 0 ) * SATOSHIDEN + 0.0000000049 ;
if ( myGetTransaction ( createtxid , tx , hashBlock ) ! = 0 )
{
if ( ( nValue = IsPaymentsvout ( cp , vintx , vout ) ) > 1000000 & & myIsutxo_spentinmempool ( ignoretxid , ignorevin , txid , vout ) = = 0 )
if ( tx . vout . size ( ) > 0 & & DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , updateflag , lockedblocks , minrelease , totalallocations , txidoprets ) ! = 0 )
{
for ( i = 0 ; i < txidoprets . size ( ) ; i + + )
{
std : : vector < uint8_t > scriptPubKey , opret ;
vout . nValue = 0 ;
if ( myGetTransaction ( txidoprets [ i ] , txO , hashBlock ) ! = 0 & & txO . vout . size ( ) > 1 & & DecodePaymentsTxidOpRet ( txO . vout [ txO . vout . size ( ) - 1 ] . scriptPubKey , allocation , scriptPubKey , opret ) = = ' T ' )
{
vout . nValue = allocation ;
vout . scriptPubKey . resize ( scriptPubKey . size ( ) ) ;
memcpy ( & vout . scriptPubKey [ 0 ] , & scriptPubKey [ 0 ] , scriptPubKey . size ( ) ) ;
checkallocations + = allocation ;
if ( opret . size ( ) > 0 )
{
scriptPubKey . resize ( opret . size ) ;
memcpy ( & onlyopret [ 0 ] , & opret [ 0 ] , opret . size ) ;
numoprets + + ;
}
} else break ;
mtx . vout . push_back ( vout ) ;
}
if ( i ! = txidoprets . size ( ) )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " invalid txidoprets[i] " ) ) ;
result . push_back ( Pair ( " txi " , ( int64_t ) i ) ) ;
return ( result ) ;
}
else if ( checkallocations ! = totalallocations )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " totalallocations mismatch " ) ) ;
result . push_back ( Pair ( " checkallocations " , ( int64_t ) checkallocations ) ) ;
result . push_back ( Pair ( " totalallocations " , ( int64_t ) totalallocations ) ) ;
return ( result ) ;
}
else if ( numoprets > 0 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " too many oprets " ) ) ;
result . push_back ( Pair ( " numoprets " , ( int64_t ) numoprets ) ) ;
return ( result ) ;
}
for ( i = 0 ; i < txidoprets . size ( ) ; i + + )
{
mtx . vout [ i ] . nValue * = amount ;
mtx . vout [ i ] . nValue / = totalallocations ;
}
txidpk = CCtxidaddr ( txidaddr , createtxid ) ;
if ( ( inputsum = AddPaymentsInputs ( cp , mtx , txidpk , amount , 60 , createtxid ) ) > = amount )
{
if ( ( CCchange = ( inputsum - amount ) ) > TRANSACTIONS_TXFEE )
mtx . vout . push_back ( MakeCC1of2vout ( EVAL_PAYMENTS , CCchange , Paymentspk , txidpk ) ) ;
rawtx = FinalizeCCTx ( 0 , cp , mtx , mypk , PAYMENTS_TXFEE , onlyopret ) ;
return ( payments_rawtxresult ( result , rawtx , 0 ) ) ;
}
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " couldnt find enough locked funds " ) ) ;
}
}
else
{
if ( total ! = 0 & & maxinputs ! = 0 )
mtx . vin . push_back ( CTxIn ( txid , vout , CScript ( ) ) ) ;
nValue = it - > second . satoshis ;
totalinputs + = nValue ;
n + + ;
if ( ( total > 0 & & totalinputs > = total ) | | ( maxinputs > 0 & & n > = maxinputs ) )
break ;
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " couldnt decode paymentscreate txid opret " ) ) ;
}
}
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " couldnt find paymentscreate txid " ) ) ;
}
}
return ( totalinputs ) ;
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " parameters error " ) ) ;
}
return ( result ) ;
}
std : : string PaymentsGet ( uint64_t txfee , int64_t nValue )
UniValue PaymentsFund ( struct CCcontract_info * cp , char * jsonstr )
{
CMutableTransaction tmpmtx , mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ;
CPubKey mypk , Paymentspk ; int64_t inputs , CCchange = 0 ; struct CCcontract_info * cp , C ; std : : string rawhex ; uint32_t j ; int32_t i , len ; uint8_t buf [ 32768 ] ; bits256 hash ;
cp = CCinit ( & C , EVAL_PAYMENTS ) ;
if ( txfee = = 0 )
txfee = 10000 ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ; UniValue result ( UniValue : : VOBJ ) ;
CPubKey Paymentspk , mypk , txidpk ; uint256 txid , hashBlock ; int64_t amount ; CScript opret ; CTransaction tx ; char txidaddr [ 64 ] ; std : : string rawtx ; int32_t n , useopret = 0 , updateflag , lockedblocks , minrelease , totalallocations ; std : : vector < uint256 > txidoprets ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
mypk = pubkey2pk ( Mypubkey ( ) ) ;
if ( ( inputs = AddPaymentsInputs ( cp , mtx , Paymentspk , nValue + txfee , 60 ) ) > 0 )
{
if ( inputs > nValue )
CCchange = ( inputs - nValue - txfee ) ;
if ( CCchange ! = 0 )
mtx . vout . push_back ( MakeCC1vout ( EVAL_PAYMENTS , CCchange , Paymentspk ) ) ;
mtx . vout . push_back ( CTxOut ( nValue , CScript ( ) < < ParseHex ( HexStr ( mypk ) ) < < OP_CHECKSIG ) ) ;
fprintf ( stderr , " start at %u \n " , ( uint32_t ) time ( NULL ) ) ;
j = rand ( ) & 0xfffffff ;
for ( i = 0 ; i < 1000000 ; i + + , j + + )
{
tmpmtx = mtx ;
rawhex = FinalizeCCTx ( - 1LL , cp , tmpmtx , mypk , txfee , CScript ( ) < < OP_RETURN < < E_MARSHAL ( ss < < ( uint8_t ) EVAL_PAYMENTS < < ( uint8_t ) ' G ' < < j ) ) ;
if ( ( len = ( int32_t ) rawhex . size ( ) ) > 0 & & len < 65536 )
Paymentspk = GetUnspendable ( cp , 0 ) ;
if ( params ! = 0 & & n > 1 & & n < = 3 )
{
txid = payments_juint256 ( jitem ( params , 0 ) ) ;
amount = jdouble ( jitem ( params , 1 ) , 0 ) * SATOSHIDEN + 0.0000000049 ;
if ( n = = 3 )
useopret = jint ( jitem ( params , 2 ) , 0 ) ! = 0 ;
if ( myGetTransaction ( txid , tx , hashBlock ) = = 0 | | tx . vout . size ( ) = = 1 | | DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , updateflag , lockedblocks , minrelease , totalallocations , txidoprets ) = = 0 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " invalid createtxid " ) ) ;
}
else if ( AddNormalinputs ( mtx , mypk , amount + PAYMENTS_TXFEE , 60 ) > 0 )
{
if ( useopret = = 0 )
{
len > > = 1 ;
decode_hex ( buf , len , ( char * ) rawhex . c_str ( ) ) ;
hash = bits256_doublesha256 ( 0 , buf , len ) ;
if ( ( hash . bytes [ 0 ] & 0xff ) = = 0 & & ( hash . bytes [ 31 ] & 0xff ) = = 0 )
{
fprintf ( stderr , " found valid txid after %d iterations %u \n " , i , ( uint32_t ) time ( NULL ) ) ;
return ( rawhex ) ;
}
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
txidpk = CCtxidaddr ( txidaddr , txid ) ;
mtx . vout . push_back ( MakeCC1of2vout ( EVAL_PAYMENTS , funds , Paymentspk , txidpk ) ) ;
}
else
{
mtx . vout . push_back ( MakeCCvout ( EVAL_PAYMENTS , funds , Paymentspk ) ) ;
opret = EncodePaymentsFundOpRet ( txid ) ;
}
rawtx = FinalizeCCTx ( 0 , cp , mtx , mypk , PAYMENTS_TXFEE , opret ) ;
return ( payments_rawtxresult ( result , rawtx , 0 ) ) ;
}
fprintf ( stderr , " couldnt generate valid txid %u \n " , ( uint32_t ) time ( NULL ) ) ;
return ( " " ) ;
} else fprintf ( stderr , " cant find Payments inputs \n " ) ;
return ( " " ) ;
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " couldnt find enough funds " ) ) ;
}
}
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " parameters error " ) ) ;
}
return ( result ) ;
}
std : : string PaymentsFund ( uint64_t txfee , int64_t funds )
UniValue PaymentsTxidopret ( struct CCcontract_info * cp , char * jsonstr )
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ;
CPubKey mypk , Paymentspk ; CScript opret ; struct CCcontract_info * cp , C ;
cp = CCinit ( & C , EVAL_PAYMENTS ) ;
if ( txfee = = 0 )
txfee = 10000 ;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ; UniValue result ( UniValue : : VOBJ ) ; CPubKey mypk ; std : : string rawtx ;
std : : vector < uint8_t > scriptPubKey , opret ; int32_t allocation , n , retval0 , retval1 = 0 ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
mypk = pubkey2pk ( Mypubkey ( ) ) ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
if ( AddNormalinputs ( mtx , mypk , funds + txfee , 64 ) > 0 )
if ( params ! = 0 & & n > 1 & & n < = 3 )
{
mtx . vout . push_back ( MakeCC1vout ( EVAL_PAYMENTS , funds , Paymentspk ) ) ;
return ( FinalizeCCTx ( 0 , cp , mtx , mypk , txfee , opret ) ) ;
allocation = juint ( jitem ( params , 0 ) , 0 ) ;
retval0 = payments_parsehexdata ( scriptPubKey , jitem ( params , 1 ) ) ;
if ( m = = 3 )
retval1 = payments_parsehexdata ( opret , jitem ( params , 2 ) ) ;
if ( allocation > 0 & & retval = = 0 & & retval1 = = 0 & & AddNormalinputs ( mtx , mypk , PAYMENTS_TXFEE , 10 ) > 0 )
{
rawtx = FinalizeCCTx ( 0 , cp , mtx , mypk , PAYMENTS_TXFEE , EncodePaymentsTxidOpRet ( allocation , scriptPubKey , opret ) ) ;
return ( payments_rawtxresult ( result , rawtx , 0 ) ) ;
}
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " invalid params or cant find txfee " ) ) ;
}
return ( " " ) ;
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " parameters error " ) ) ;
}
return ( result ) ;
}
UniValue PaymentsInfo ( )
UniValue PaymentsCreate ( struct CCcontract_info * cp , char * jsonstr )
{
UniValue result ( UniValue : : VOBJ ) ; char numstr [ 64 ] ;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ;
CPubKey Paymentspk ; struct CCcontract_info * cp , C ; int64_t funding ;
UniValue result ( UniValue : : VOBJ ) ; CTransaction tx ; CPubKey Paymentspk ; char markeraddr [ 64 ] ; std : : vector < uint256 > txidoprets ; uint256 hashBlock ; int32_t i , n , numoprets = 0 , updateflag , lockedblocks , minrelease , totalallocations = 0 ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
if ( params ! = 0 & & n > = 4 )
{
updateflag = juint ( jitem ( params , 0 ) , 0 ) ;
lockedblocks = juint ( jitem ( params , 1 ) , 0 ) ;
minrelease = juint ( jitem ( params , 2 ) , 0 ) ;
for ( i = 0 ; i < n - 3 ; i + + )
txidoprets . push_back ( payments_juint256 ( jitem ( params , 3 + i ) ) ) ;
for ( i = 0 ; i < txidoprets . size ( ) ; i + + )
{
std : : vector < uint8_t > scriptPubKey , opret ; int32_t allocation ;
if ( myGetTransaction ( txidoprets [ i ] , tx , hashBlock ) ! = 0 & & tx . vout . size ( ) > 1 & & DecodePaymentsTxidOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , allocation , scriptPubKey , opret ) = = ' T ' )
{
totalallocations + = allocation ;
if ( opret . size ( ) > 0 )
numoprets + + ;
}
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " invalid txidopret " ) ) ;
result . push_back ( Pair ( " txid " , txidoprets [ i ] . GetHex ( ) ) ) ;
result . push_back ( Pair ( " txi " , ( int64_t ) i ) ) ;
return ( result ) ;
}
}
if ( numoprets > 1 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " too many opreturns " ) ) ;
result . push_back ( Pair ( " numoprets " , ( int64_t ) numoprets ) ) ;
return ( result ) ;
}
mypk = pubkey2pk ( Mypubkey ( ) ) ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
if ( AddNormalinputs ( mtx , mypk , 2 * PAYMENTS_TXFEE , 60 ) > 0 )
{
mtx . vout . push_back ( MakeCC1of2vout ( cp - > evalcode , PAYMENTS_TXFEE , Paymentspk , Paymentspk ) ) ;
rawtx = FinalizeCCTx ( 0 , cp , mtx , mypk , PAYMENTS_TXFEE , EncodePaymentsOpRet ( updateflag , lockedblocks , minrelease , totalallocations , txidoprets ) ) ;
return ( payments_rawtxresult ( result , rawtx , 0 ) ) ;
}
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " not enough normal funds " ) ) ;
}
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " parameters error " ) ) ;
}
return ( result ) ;
}
UniValue PaymentsInfo ( struct CCcontract_info * cp , char * jsonstr )
{
UniValue result ( UniValue : : VOBJ ) , a ( UniValue : VARR ) ; CTransaction tx , txO ; CPubKey Paymentspk , txidpk ; int32_t i , n , flag = 0 , allocation , numoprets = 0 , updateflag , lockedblocks , minrelease , totalallocations ; std : : vector < uint256 > txidoprets ; int64_t funds , fundsopret ; char fundsaddr [ 64 ] , fundsopretaddr [ 64 ] , txidaddr [ 64 ] ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
if ( params ! = 0 & & n = = 1 )
{
Paymentspk = GetUnspendable ( cp , 0 ) ;
txid = payments_juint256 ( jitem ( params , 0 ) ) ;
if ( myGetTransaction ( txid , tx , hashBlock ) ! = 0 )
{
if ( tx . vout . size ( ) > 0 & & DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , updateflag , lockedblocks , minrelease , totalallocations , txidoprets ) ! = 0 )
{
result . push_back ( Pair ( " updateable " , updateflag ! = 0 ? " yes " : " no " ) ) ;
result . push_back ( Pair ( " lockedblocks " , ( int64_t ) lockedblocks ) ) ;
result . push_back ( Pair ( " totalallocations " , ( int64_t ) totalallocations ) ) ;
result . push_back ( Pair ( " minrelease " , ( int64_t ) minrelease ) ) ;
for ( i = 0 ; i < txidoprets . size ( ) ; i + + )
{
UniValue obj ( UniValue : : VOBJ ) ; std : : vector < uint8_t > scriptPubKey , opret ;
obj . push_back ( Pair ( " txidopret " , txidoprets [ i ] ) ) ;
if ( myGetTransaction ( txidoprets [ i ] , txO , hashBlock ) ! = 0 & & txO . vout . size ( ) > 1 & & DecodePaymentsTxidOpRet ( txO . vout [ txO . vout . size ( ) - 1 ] . scriptPubKey , allocation , scriptPubKey , opret ) = = ' T ' )
{
obj . push_back ( Pair ( " scriptPubKey " , scriptPubKey ) ) ;
if ( opret . size ( ) ! = 0 )
{
obj . push_back ( Pair ( " opreturn " , opret ) ) ;
numoprets + + ;
}
}
}
flag + + ;
if ( numoprets > 1 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " too many opreturns " ) ) ;
result . push_back ( Pair ( " numoprets " , ( int64_t ) numoprets ) ) ;
}
else
{
txidpk = CCtxidaddr ( txidaddr , txid ) ;
GetCCaddress1of2 ( cp , fundsaddr , Paymentspk , txidpk ) ;
funds = CCaddress_balance ( fundsaddr ) ;
result . push_back ( Pair ( fundsaddr , ValueFromAmount ( funds ) ) ) ;
GetCCaddress ( cp , fundsopretaddr , Paymentspk ) ;
fundsopret = CCaddress_balance ( fundsopretaddr ) ;
result . push_back ( Pair ( fundsopretaddr , ValueFromAmount ( fundsopret ) ) ) ;
result . push_back ( Pair ( " totalfunds " , ValueFromAmount ( funds + fundsopret ) ) ) ;
result . push_back ( Pair ( " result " , " success " ) ) ;
}
}
}
if ( flag = = 0 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " couldnt find valid payments create txid " ) ) ;
}
}
else
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " parameters error " ) ) ;
}
return ( result ) ;
}
UniValue PaymentsList ( struct CCcontract_info * cp , char * jsonstr )
{
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ; uint256 txid , hashBlock ;
UniValue result ( UniValue : : VOBJ ) , a ( UniValue : VARR ) ; char markeraddr [ 64 ] , str [ 65 ] ; CPubKey Paymentspk ; CTransaction tx ; int32_t updateflag , lockedblocks , minrelease , totalallocations ; std : : vector < uint256 > txidoprets ;
result . push_back ( Pair ( " result " , " success " ) ) ;
result . push_back ( Pair ( " name " , " Payments " ) ) ;
cp = CCinit ( & C , EVAL_PAYMENTS ) ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
funding = AddPaymentsInputs ( cp , mtx , Paymentspk , 0 , 0 ) ;
sprintf ( numstr , " %.8f " , ( double ) funding / COIN ) ;
result . push_back ( Pair ( " funding " , numstr ) ) ;
GetCCaddress1of2 ( cp , markeraddr , Paymentspk , Paymentspk ) ;
SetCCtxids ( addressIndex , markeraddr ) ;
for ( std : : vector < std : : pair < CAddressIndexKey , CAmount > > : : const_iterator it = addressIndex . begin ( ) ; it ! = addressIndex . end ( ) ; it + + )
{
txid = it - > first . txhash ;
if ( it - > first . index = = 0 & & myGetTransaction ( txid , tx , hashBlock ) ! = 0 )
{
if ( tx . vout . size ( ) > 0 & & DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , updateflag , lockedblocks , minrelease , totalallocations , txidoprets ) = = ' C ' )
{
a . push_back ( uint256_str ( str , txid ) ) ;
}
}
}
result . push_back ( Pair ( " createtxids " , a ) ) ;
return ( result ) ;
}