@ -157,22 +157,41 @@ uint8_t DecodePaymentsOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &
return ( 0 ) ;
}
CScript EncodePaymentsSnapsShotOpRet ( int32_t lockedblocks , int32_t minrelease , int32_t top , int32_t bottom , int8_t fixedAmount , std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys )
CScript EncodePaymentsSnapsShotOpRet ( int32_t lockedblocks , int32_t minrelease , int32_t minimum , int32_t top , int32_t bottom , int8_t fixedAmount , std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys )
{
CScript opret ; uint8_t evalcode = EVAL_PAYMENTS ;
opret < < OP_RETURN < < E_MARSHAL ( ss < < evalcode < < ' S ' < < lockedblocks < < minrelease < < top < < bottom < < fixedAmount < < excludeScriptPubKeys ) ;
if ( ( strcmp ( ASSETCHAINS_SYMBOL , " CFEKPAY " ) = = 0 ) ) // exempt for now, remove this after game completed.
{
minimum = 10000 ;
opret < < OP_RETURN < < E_MARSHAL ( ss < < evalcode < < ' S ' < < lockedblocks < < minrelease < < top < < bottom < < fixedAmount < < excludeScriptPubKeys ) ;
}
else
opret < < OP_RETURN < < E_MARSHAL ( ss < < evalcode < < ' S ' < < lockedblocks < < minrelease < < minimum < < top < < bottom < < fixedAmount < < excludeScriptPubKeys ) ;
return ( opret ) ;
}
uint8_t DecodePaymentsSnapsShotOpRet ( CScript scriptPubKey , int32_t & lockedblocks , int32_t & minrelease , int32_t & top , int32_t & bottom , int8_t & fixedAmount , std : : vector < std : : vector < uint8_t > > & excludeScriptPubKeys )
uint8_t DecodePaymentsSnapsShotOpRet ( CScript scriptPubKey , int32_t & lockedblocks , int32_t & minrelease , int32_t & minimum , int32_t & top , int32_t & bottom , int8_t & fixedAmount , std : : vector < std : : vector < uint8_t > > & excludeScriptPubKeys )
{
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 > > lockedblocks ; ss > > minrelease ; ss > > top ; ; ss > > bottom ; ss > > fixedAmount ; ss > > excludeScriptPubKeys ) ! = 0 )
if ( ( strcmp ( ASSETCHAINS_SYMBOL , " CFEKPAY " ) = = 0 ) ) // exempt for now, remove this after game completed.
{
if ( e = = EVAL_PAYMENTS & & f = = ' S ' )
return ( f ) ;
minimum = 10000 ;
if ( vopret . size ( ) > 2 & & E_UNMARSHAL ( vopret , ss > > e ; ss > > f ; ss > > lockedblocks ; ss > > minrelease ; ss > > top ; ; ss > > bottom ; ss > > fixedAmount ; ss > > excludeScriptPubKeys ) ! = 0 )
{
if ( e = = EVAL_PAYMENTS & & f = = ' S ' )
return ( f ) ;
}
}
else
{
if ( vopret . size ( ) > 2 & & E_UNMARSHAL ( vopret , ss > > e ; ss > > f ; ss > > lockedblocks ; ss > > minrelease ; ss > > minimum ; ss > > top ; ; ss > > bottom ; ss > > fixedAmount ; ss > > excludeScriptPubKeys ) ! = 0 )
{
if ( e = = EVAL_PAYMENTS & & f = = ' S ' )
return ( f ) ;
}
}
return ( 0 ) ;
}
@ -197,10 +216,11 @@ uint8_t DecodePaymentsTokensOpRet(CScript scriptPubKey,int32_t &lockedblocks,int
return ( 0 ) ;
}
int64_t IsPaymentsvout ( struct CCcontract_info * cp , const CTransaction & tx , int32_t v , char * cmpaddr )
int64_t IsPaymentsvout ( struct CCcontract_info * cp , const CTransaction & tx , int32_t v , char * cmpaddr , CScript & ccopret )
{
char destaddr [ 64 ] ;
if ( tx . vout [ v ] . scriptPubKey . IsPayToCryptoCondition ( ) ! = 0 )
//if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
if ( getCCopret ( tx . vout [ v ] . scriptPubKey , ccopret ) )
{
if ( Getscriptaddress ( destaddr , tx . vout [ v ] . scriptPubKey ) > 0 & & ( cmpaddr [ 0 ] = = 0 | | strcmp ( destaddr , cmpaddr ) = = 0 ) )
return ( tx . vout [ v ] . nValue ) ;
@ -259,197 +279,216 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
// change is/must be in vout[0]
// only 'F' or 1of2 txidaddr can be spent
// all vouts must match exactly
char temp [ 128 ] , coinaddr [ 64 ] , txidaddr [ 64 ] ; std : : string scriptpubkey ; uint256 createtxid , blockhash , tokenid ; CTransaction plantx ; int8_t funcid = 0 , fixedAmount = 0 ;
int32_t i , lockedblocks , minrelease ; int64_t change , totalallocations ; std : : vector < uint256 > txidoprets ; bool fHasOpret = false ; CPubKey txidpk , Paymentspk ;
int32_t top , bottom = 0 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; bool fFixedAmount = false ;
char temp [ 128 ] , coinaddr [ 64 ] = { 0 } , txidaddr [ 64 ] ; std : : string scriptpubkey ; uint256 createtxid , blockhash , tokenid ; CTransaction plantx ; int8_t funcid = 0 , fixedAmount = 0 ;
int32_t i , lockedblocks , minrelease ; int64_t change , totalallocations ; std : : vector < uint256 > txidoprets ; bool fHasOpret = false , fIsMerge = false ; CPubKey txidpk , Paymentspk ;
int32_t top , bottom = 0 , minimum = 10000 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; bool fFixedAmount = false ; CScript ccopret ;
mpz_t mpzTotalAllocations , mpzAllocation ; ; mpz_init ( mpzTotalAllocations ) ;
// user marker vout to get the createtxid
if ( tx . vout . size ( ) < 2 )
return ( eval - > Invalid ( " not enough vouts " ) ) ;
if ( tx . vout . back ( ) . scriptPubKey [ 0 ] = = OP_RETURN )
if ( tx . vout . size ( ) = = 1 )
{
if ( IsPaymentsvout ( cp , tx , 0 , coinaddr , ccopret ) ! = 0 & & ccopret . size ( ) > 2 & & DecodePaymentsMergeOpRet ( ccopret , createtxid ) )
{
fIsMerge = true ;
} else return ( eval - > Invalid ( " not enough vouts " ) ) ;
}
else if ( tx . vout . back ( ) . scriptPubKey [ 0 ] = = OP_RETURN )
{
scriptpubkey = HexStr ( tx . vout [ tx . vout . size ( ) - 2 ] . scriptPubKey . begin ( ) + 2 , tx . vout [ tx . vout . size ( ) - 2 ] . scriptPubKey . end ( ) - 1 ) ;
fHasOpret = true ;
} else scriptpubkey = HexStr ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . begin ( ) + 2 , tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . end ( ) - 1 ) ;
strcpy ( temp , scriptpubkey . c_str ( ) ) ;
pub2createtxid ( temp ) ;
createtxid = Parseuint256 ( temp ) ;
}
else scriptpubkey = HexStr ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . begin ( ) + 2 , tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . end ( ) - 1 ) ;
if ( ! fIsMerge )
{
strcpy ( temp , scriptpubkey . c_str ( ) ) ;
pub2createtxid ( temp ) ;
createtxid = Parseuint256 ( temp ) ;
}
//printf("createtxid.%s\n",createtxid.ToString().c_str());
// use the createtxid to fetch the tx and all of the plans info.
if ( myGetTransaction ( createtxid , plantx , blockhash ) ! = 0 & & plantx . vout . size ( ) > 0 )
{
if ( ( ( funcid = DecodePaymentsOpRet ( plantx . vout [ plantx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) ) = = ' C ' | | ( funcid = DecodePaymentsSnapsShotOpRet ( plantx . vout [ plantx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , bottom , fixedAmount , excludeScriptPubKeys ) ) = = ' S ' | | ( funcid = DecodePaymentsTokensOpRet ( plantx . vout [ plantx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) ) = = ' O ' ) )
if ( ( ( funcid = DecodePaymentsOpRet ( plantx . vout [ plantx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) ) = = ' C ' | | ( funcid = DecodePaymentsSnapsShotOpRet ( plantx . vout [ plantx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) ) = = ' S ' | | ( funcid = DecodePaymentsTokensOpRet ( plantx . vout [ plantx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) ) = = ' O ' ) )
{
if ( lockedblocks < 0 | | minrelease < 0 | | ( totalallocations < = 0 & & top < = 0 ) )
return ( eval - > Invalid ( " negative values " ) ) ;
return ( eval - > Invalid ( " negative values " ) ) ;
if ( minimum < 10000 )
return ( eval - > Invalid ( " minimum must be over 10000 " ) ) ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
txidpk = CCtxidaddr ( txidaddr , createtxid ) ;
GetCCaddress1of2 ( cp , coinaddr , Paymentspk , txidpk ) ;
//fprintf(stderr, "lockedblocks.%i minrelease.%i totalallocations.%i txidopret1.%s txidopret2.%s\n",lockedblocks, minrelease, totalallocations, txidoprets[0].ToString().c_str(), txidoprets[1].ToString().c_str() );
if ( ! CheckTxFee ( tx , PAYMENTS_TXFEE + 1 , chainActive . LastTip ( ) - > GetHeight ( ) , chainActive . LastTip ( ) - > nTime ) )
return eval - > Invalid ( " txfee is too high " ) ;
// Get all the script pubkeys and allocations
std : : vector < int64_t > allocations ;
std : : vector < CScript > scriptPubKeys ;
int64_t checkallocations = 0 ;
i = 0 ;
if ( funcid = = ' C ' )
// make sure change is in vout 0 and is paying to the contract address.
if ( ( change = IsPaymentsvout ( cp , tx , 0 , coinaddr , ccopret ) ) = = 0 )
return ( eval - > Invalid ( " change is in wrong vout or is wrong tx type " ) ) ;
if ( ! fIsMerge )
{
// normal payment
for ( const uint256 & txidopret : txidoprets )
// Get all the script pubkeys and allocations
std : : vector < int64_t > allocations ;
std : : vector < CScript > scriptPubKeys ;
int64_t checkallocations = 0 ;
i = 0 ;
if ( funcid = = ' C ' )
{
CTransaction tx0 ; std : : vector < uint8_t > scriptPubKey , opret ; int64_t allocation ;
if ( myGetTransaction ( txidopret , tx0 , blockhash ) ! = 0 & & tx0 . vout . size ( ) > 1 & & DecodePaymentsTxidOpRet ( tx0 . vout [ tx0 . vout . size ( ) - 1 ] . scriptPubKey , allocation , scriptPubKey , opret ) = = ' T ' )
// normal payment
for ( const uint256 & txidopret : txidoprets )
{
scriptPubKeys . push_back ( CScript ( scriptPubKey . begin ( ) , scriptPubKey . end ( ) ) ) ;
allocations . push_back ( allocation ) ;
//fprintf(stderr, "i.%i scriptpubkey.%s allocation.%li\n",i,scriptPubKeys[i].ToString().c_str(),allocation);
checkallocations + = allocation ;
// if we have an op_return to pay to need to check it exists and is paying the correct opret.
if ( ! opret . empty ( ) )
CTransaction tx0 ; std : : vector < uint8_t > scriptPubKey , opret ; int64_t allocation ;
if ( myGetTransaction ( txidopret , tx0 , blockhash ) ! = 0 & & tx0 . vout . size ( ) > 1 & & DecodePaymentsTxidOpRet ( tx0 . vout [ tx0 . vout . size ( ) - 1 ] . scriptPubKey , allocation , scriptPubKey , opret ) = = ' T ' )
{
if ( ! fHasOpret )
{
fprintf ( stderr , " missing opret.%s in payments release. \n " , HexStr ( opret . begin ( ) , opret . end ( ) ) . c_str ( ) ) ;
return ( eval - > Invalid ( " missing opret in payments release " ) ) ;
}
else if ( CScript ( opret . begin ( ) , opret . end ( ) ) ! = tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey )
scriptPubKeys . push_back ( CScript ( scriptPubKey . begin ( ) , scriptPubKey . end ( ) ) ) ;
allocations . push_back ( allocation ) ;
//fprintf(stderr, "i.%i scriptpubkey.%s allocation.%li\n",i,scriptPubKeys[i].ToString().c_str(),allocation);
checkallocations + = allocation ;
// if we have an op_return to pay to need to check it exists and is paying the correct opret.
if ( ! opret . empty ( ) )
{
fprintf ( stderr , " opret.%s vs opret.%s \n " , HexStr ( opret . begin ( ) , opret . end ( ) ) . c_str ( ) , HexStr ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . begin ( ) , tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . end ( ) ) . c_str ( ) ) ;
return ( eval - > Invalid ( " pays incorrect opret " ) ) ;
if ( ! fHasOpret )
{
fprintf ( stderr , " missing opret.%s in payments release. \n " , HexStr ( opret . begin ( ) , opret . end ( ) ) . c_str ( ) ) ;
return ( eval - > Invalid ( " missing opret in payments release " ) ) ;
}
else if ( CScript ( opret . begin ( ) , opret . end ( ) ) ! = tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey )
{
fprintf ( stderr , " opret.%s vs opret.%s \n " , HexStr ( opret . begin ( ) , opret . end ( ) ) . c_str ( ) , HexStr ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . begin ( ) , tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey . end ( ) ) . c_str ( ) ) ;
return ( eval - > Invalid ( " pays incorrect opret " ) ) ;
}
}
}
i + + ;
}
i + + ;
mpz_set_si ( mpzTotalAllocations , totalallocations ) ;
}
mpz_set_si ( mpzTotalAllocations , totalallocations ) ;
}
else if ( funcid = = ' S ' )
{
if ( KOMODO_SNAPSHOT_INTERVAL = = 0 )
return ( eval - > Invalid ( " snapshots not activated on this chain " ) ) ;
if ( vAddressSnapshot . size ( ) = = 0 )
return ( eval - > Invalid ( " need first snapshot " ) ) ;
// need time for TX to me mined before the next snapshot.
if ( top > 3999 )
return ( eval - > Invalid ( " transaction too big " ) ) ;
if ( fixedAmount = = 7 )
else if ( funcid = = ' S ' )
{
// game setting, randomise bottom and top values
fFixedAmount = payments_game ( top , bottom ) ;
if ( KOMODO_SNAPSHOT_INTERVAL = = 0 )
return ( eval - > Invalid ( " snapshots not activated on this chain " ) ) ;
if ( vAddressSnapshot . size ( ) = = 0 )
return ( eval - > Invalid ( " need first snapshot " ) ) ;
if ( top > 3999 )
return ( eval - > Invalid ( " transaction too big " ) ) ;
if ( fixedAmount = = 7 )
{
// game setting, randomise bottom and top values
fFixedAmount = payments_game ( top , bottom ) ;
}
else if ( fixedAmount ! = 0 )
{
fFixedAmount = true ;
}
for ( int32_t j = bottom ; j < vAddressSnapshot . size ( ) ; j + + )
{
auto & address = vAddressSnapshot [ j ] ;
CScript scriptPubKey = GetScriptForDestination ( address . second ) ; bool skip = false ;
for ( auto skipkey : excludeScriptPubKeys )
{
if ( scriptPubKey = = CScript ( skipkey . begin ( ) , skipkey . end ( ) ) )
{
skip = true ;
//fprintf(stderr, "SKIPPED::: %s\n", CBitcoinAddress(address.second).ToString().c_str());
}
}
if ( ! skip )
{
mpz_init ( mpzAllocation ) ;
i + + ;
scriptPubKeys . push_back ( scriptPubKey ) ;
allocations . push_back ( address . first ) ;
mpz_set_si ( mpzAllocation , address . first ) ;
mpz_add ( mpzTotalAllocations , mpzTotalAllocations , mpzAllocation ) ;
mpz_clear ( mpzAllocation ) ;
}
if ( i + bottom = = top ) // we reached top amount to pay, it can be less than this!
break ;
}
if ( i ! = tx . vout . size ( ) - 2 )
return ( eval - > Invalid ( " pays wrong amount of recipients " ) ) ;
}
else if ( fixedAmount ! = 0 )
else if ( funcid = = ' O ' )
{
fFixedAmount = true ;
// tokens snapshot.
}
for ( int32_t j = bottom ; j < vAddressSnapshot . size ( ) ; j + + )
// sanity check to make sure we got all the required info, skip for merge type tx
//fprintf(stderr, " allocations.size().%li scriptPubKeys.size.%li\n",allocations.size(), scriptPubKeys.size());
if ( ( allocations . size ( ) = = 0 | | scriptPubKeys . size ( ) = = 0 | | allocations . size ( ) ! = scriptPubKeys . size ( ) ) )
return ( eval - > Invalid ( " missing data cannot validate " ) ) ;
//fprintf(stderr, "totalallocations.%li checkallocations.%li\n",totalallocations, checkallocations);
if ( funcid = = ' C ' & & totalallocations ! = checkallocations ) // only check for normal payments release.
return ( eval - > Invalid ( " allocation missmatch " ) ) ;
// Check vouts go to the right place and pay the right amounts.
int64_t amount = 0 , checkamount ; int32_t n = 0 ;
checkamount = tx . GetValueOut ( ) - change - PAYMENTS_TXFEE ;
mpz_t mpzCheckamount ; mpz_init ( mpzCheckamount ) ; mpz_set_si ( mpzCheckamount , checkamount ) ;
for ( i = 1 ; i < ( fHasOpret ? tx . vout . size ( ) - 2 : tx . vout . size ( ) - 1 ) ; i + + )
{
auto & address = vAddressSnapshot [ j ] ;
CScript scriptPubKey = GetScriptForDestination ( address . second ) ; bool skip = false ;
for ( auto skipkey : excludeScriptPubKeys )
if ( scriptPubKeys [ n ] ! = tx . vout [ i ] . scriptPubKey )
{
if ( scriptPubKey = = CScript ( skipkey . begin ( ) , skipkey . end ( ) ) )
{
skip = true ;
//fprintf(stderr, "SKIPPED::: %s\n", CBitcoinAddress(address.second).ToString().c_str());
}
fprintf ( stderr , " pays wrong destination destscriptPubKey.%s voutscriptPubKey.%s \n " , HexStr ( scriptPubKeys [ n ] . begin ( ) , scriptPubKeys [ n ] . end ( ) ) . c_str ( ) , HexStr ( tx . vout [ i ] . scriptPubKey . begin ( ) , tx . vout [ i ] . scriptPubKey . end ( ) ) . c_str ( ) ) ;
return ( eval - > Invalid ( " pays wrong address " ) ) ;
}
if ( ! skip )
int64_t test ;
if ( fFixedAmount )
{
test = checkamount / ( top - bottom ) ;
}
else
{
mpz_init ( mpzAllocation ) ;
i + + ;
scriptPubKeys . push_back ( scriptPubKey ) ;
allocations . push_back ( address . first ) ;
mpz_set_si ( mpzAllocation , address . first ) ;
mpz_add ( mpzTotalAllocations , mpzTotalAllocations , mpzAllocation ) ;
mpz_set_si ( mpzAllocation , allocations [ n ] ) ;
mpz_mul ( mpzAllocation , mpzAllocation , mpzCheckamount ) ;
mpz_cdiv_q ( mpzAllocation , mpzAllocation , mpzTotalAllocations ) ;
test = mpz_get_si ( mpzAllocation ) ;
mpz_clear ( mpzAllocation ) ;
}
if ( i + bottom = = top ) // we reached top amount to pay, it can be less than this!
break ;
// Vairance of 1 sat is allowed, for rounding errors.
if ( test > = tx . vout [ i ] . nValue + 1 & & test < = tx . vout [ i ] . nValue - 1 )
{
fprintf ( stderr , " vout.%i test.%li vs nVlaue.%li \n " , i , test , tx . vout [ i ] . nValue ) ;
return ( eval - > Invalid ( " amounts do not match " ) ) ;
}
if ( test < minimum )
{
fprintf ( stderr , " vout.%i test.%li vs minimum.%i \n " , i , test , minimum ) ;
return ( eval - > Invalid ( " under minimum size " ) ) ;
}
amount + = tx . vout [ i ] . nValue ;
n + + ;
}
if ( i ! = tx . vout . size ( ) - 2 )
return ( eval - > Invalid ( " pays wrong amount of recipients " ) ) ;
}
else if ( funcid = = ' O ' )
{
// tokens snapshot.
}
// sanity check to make sure we got all the required info
//fprintf(stderr, " allocations.size().%li scriptPubKeys.size.%li\n",allocations.size(), scriptPubKeys.size());
if ( allocations . size ( ) = = 0 | | scriptPubKeys . size ( ) = = 0 | | allocations . size ( ) ! = scriptPubKeys . size ( ) )
return ( eval - > Invalid ( " missing data cannot validate " ) ) ;
mpz_clear ( mpzTotalAllocations ) ;
// This is a backup check to make sure there are no extra vouts paying something else!
if ( checkamount ! = amount )
return ( eval - > Invalid ( " amounts do not match " ) ) ;
//fprintf(stderr, "totalallocations.%li checkallocations.%li\n",totalallocations, checkallocations);
if ( funcid = = ' C ' & & totalallocations ! = checkallocations ) // only check for normal payments release.
return ( eval - > Invalid ( " allocation missmatch " ) ) ;
// make sure change is in vout 0 and is paying to the contract address.
if ( ( change = IsPaymentsvout ( cp , tx , 0 , coinaddr ) ) = = 0 )
return ( eval - > Invalid ( " change is in wrong vout or is wrong tx type " ) ) ;
// Check vouts go to the right place and pay the right amounts.
int64_t amount = 0 , checkamount ; int32_t n = 0 ;
checkamount = tx . GetValueOut ( ) - change - PAYMENTS_TXFEE ;
mpz_t mpzCheckamount ; mpz_init ( mpzCheckamount ) ; mpz_set_si ( mpzCheckamount , checkamount ) ;
for ( i = 1 ; i < ( fHasOpret ? tx . vout . size ( ) - 2 : tx . vout . size ( ) - 1 ) ; i + + )
{
if ( scriptPubKeys [ n ] ! = tx . vout [ i ] . scriptPubKey )
{
fprintf ( stderr , " pays wrong destination destscriptPubKey.%s voutscriptPubKey.%s \n " , HexStr ( scriptPubKeys [ n ] . begin ( ) , scriptPubKeys [ n ] . end ( ) ) . c_str ( ) , HexStr ( tx . vout [ i ] . scriptPubKey . begin ( ) , tx . vout [ i ] . scriptPubKey . end ( ) ) . c_str ( ) ) ;
return ( eval - > Invalid ( " pays wrong address " ) ) ;
}
int64_t test ;
if ( fFixedAmount )
{
test = checkamount / ( top - bottom ) ;
}
else
if ( amount < minrelease * COIN )
{
mpz_init ( mpzAllocation ) ;
mpz_set_si ( mpzAllocation , allocations [ n ] ) ;
mpz_mul ( mpzAllocation , mpzAllocation , mpzCheckamount ) ;
mpz_cdiv_q ( mpzAllocation , mpzAllocation , mpzTotalAllocations ) ;
test = mpz_get_si ( mpzAllocation ) ;
mpz_clear ( mpzAllocation ) ;
fprintf ( stderr , " does not meet minrelease amount.%li minrelease.%li \n " , amount , ( int64_t ) minrelease * COIN ) ;
return ( eval - > Invalid ( " amount is too small " ) ) ;
}
// Vairance of 1 sat is allowed, for rounding errors.
if ( test > = tx . vout [ i ] . nValue + 1 & & test < = tx . vout [ i ] . nValue - 1 )
{
fprintf ( stderr , " vout.%i test.%li vs nVlaue.%li \n " , i , test , tx . vout [ i ] . nValue ) ;
return ( eval - > Invalid ( " amounts do not match " ) ) ;
}
amount + = tx . vout [ i ] . nValue ;
n + + ;
}
mpz_clear ( mpzTotalAllocations ) ;
// This is a backup check to make sure there are no extra vouts paying something else!
if ( checkamount ! = amount )
return ( eval - > Invalid ( " amounts do not match " ) ) ;
if ( amount < minrelease * COIN )
{
fprintf ( stderr , " does not meet minrelease amount.%li minrelease.%li \n " , amount , ( int64_t ) minrelease * COIN ) ;
return ( eval - > Invalid ( " amount is too small " ) ) ;
}
// Check vins
i = 0 ;
i = 0 ; int32_t dust = 0 ;
int32_t blocksleft ;
BOOST_FOREACH ( const CTxIn & vin , tx . vin )
{
CTransaction txin ;
CTransaction txin ;
if ( myGetTransaction ( vin . prevout . hash , txin , blockhash ) )
{
// check the vin comes from the CC address's
char destaddr [ 64 ] ;
char destaddr [ 64 ] ; int32_t mergeoffset = 0 ; CScript opret ; uint256 checktxid ;
Getscriptaddress ( destaddr , txin . vout [ vin . prevout . n ] . scriptPubKey ) ;
if ( fIsMerge & & txin . vout [ vin . prevout . n ] . nValue < COIN )
dust + + ;
if ( strcmp ( destaddr , coinaddr ) ! = 0 )
{
// if does not come from address its in the global payments adddress and we need to check the opreturn.
CScript opret ; uint256 checktxid ; int32_t opret_ind ;
uint256 checktxid ; int32_t opret_ind ;
if ( ( opret_ind = has_opret ( txin , EVAL_PAYMENTS ) ) = = 0 )
opret = getCCopret ( txin . vout [ vin . prevout . n ] . scriptPubKey ) ; // get op_return from CCvout,
getCCopret ( txin . vout [ vin . prevout . n ] . scriptPubKey , opret ) ; // get op_return from CCvout,
else
opret = txin . vout [ opret_ind ] . scriptPubKey ;
if ( DecodePaymentsFundOpRet ( opret , checktxid ) ! = ' F ' | | checktxid ! = createtxid )
@ -457,13 +496,25 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
fprintf ( stderr , " vin.%i is not a payments CC vout: txid.%s \n " , i , txin . GetHash ( ) . ToString ( ) . c_str ( ) ) ;
return ( eval - > Invalid ( " vin is not paymentsCC type " ) ) ;
}
}
else if ( fIsMerge & & getCCopret ( txin . vout [ vin . prevout . n ] . scriptPubKey , opret ) & & opret . size ( ) > 2 & & DecodePaymentsMergeOpRet ( opret , checktxid ) = = ' M ' )
{
mergeoffset = PAYMENTS_MERGEOFSET ;
}
fprintf ( stderr , " mergeoffset.%i \n " , mergeoffset ) ;
// check the chain depth vs locked blocks requirement.
if ( ! payments_lockedblocks ( blockhash , lockedblocks , blocksleft ) )
if ( ! payments_lockedblocks ( blockhash , lockedblocks + mergeoffset , blocksleft ) )
return ( eval - > Invalid ( " vin not elegible " ) ) ;
i + + ;
} else return ( eval - > Invalid ( " cant get vin transaction " ) ) ;
i + + ;
}
if ( fIsMerge )
{
if ( i < 2 )
return ( eval - > Invalid ( " must have at least 2 vins to carry out merge " ) ) ;
else if ( i = = dust + 1 )
return ( eval - > Invalid ( " cannot merge only dust " ) ) ;
}
} else return ( eval - > Invalid ( " create transaction cannot decode " ) ) ;
} else return ( eval - > Invalid ( " Could not get contract transaction " ) ) ;
return ( true ) ;
@ -474,7 +525,7 @@ bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &
int64_t AddPaymentsInputs ( bool fLockedBlocks , int8_t GetBalance , struct CCcontract_info * cp , CMutableTransaction & mtx , CPubKey txidpk , int64_t total , int32_t maxinputs , uint256 createtxid , int32_t lockedblocks , int64_t minrelease , int32_t & blocksleft )
{
char coinaddr [ 64 ] ; CPubKey Paymentspk ; int64_t nValue , threshold , price , totalinputs = 0 ; uint256 txid , checktxid , hashBlock ; std : : vector < uint8_t > origpubkey ; CTransaction vintx ; int32_t iter , vout , ht , n = 0 ;
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > unspentOutputs ;
std : : vector < std : : pair < CAddressUnspentKey , CAddressUnspentValue > > unspentOutputs ; CScript ccopret ;
std : : vector < std : : pair < int32_t , CAmount > > blocksleft_balance ;
if ( GetBalance = = 0 )
{
@ -509,7 +560,7 @@ int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract
if ( ( opret_ind = has_opret ( vintx , EVAL_PAYMENTS ) ) = = 0 )
{
// get op_return from CCvout
opret = getCCopret ( vintx . vout [ vout ] . scriptPubKey ) ;
getCCopret ( vintx . vout [ vout ] . scriptPubKey , opret ) ;
}
else
{
@ -522,13 +573,15 @@ int64_t AddPaymentsInputs(bool fLockedBlocks,int8_t GetBalance,struct CCcontract
continue ;
}
}
if ( ( nValue = IsPaymentsvout ( cp , vintx , vout , coinaddr ) ) > PAYMENTS_TXFEE & & nValue > = threshold & & myIsutxo_spentinmempool ( ignoretxid , ignorevin , txid , vout ) = = 0 )
if ( ( nValue = IsPaymentsvout ( cp , vintx , vout , coinaddr , ccopret ) ) > PAYMENTS_TXFEE & & nValue > = threshold & & myIsutxo_spentinmempool ( ignoretxid , ignorevin , txid , vout ) = = 0 )
{
int32_t tmpblocksleft = 0 ;
if ( GetBalance = = 0 & & total ! = 0 & & maxinputs ! = 0 )
if ( ( GetBalance = = 0 & & total ! = 0 & & maxinputs ! = 0 ) | | GetBalance = = 4 )
mtx . vin . push_back ( CTxIn ( txid , vout , CScript ( ) ) ) ;
nValue = it - > second . satoshis ;
if ( fLockedBlocks & & ! payments_lockedblocks ( hashBlock , lockedblocks , tmpblocksleft ) )
if ( nValue < COIN )
blocksleft + + ; // count dust with unused variable.
if ( fLockedBlocks & & ! payments_lockedblocks ( hashBlock , lockedblocks + ( GetBalance = = 4 ? PAYMENTS_MERGEOFSET : 0 ) , tmpblocksleft ) )
{
blocksleft_balance . push_back ( std : : make_pair ( tmpblocksleft , nValue ) ) ;
continue ;
@ -636,7 +689,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
//int32_t latestheight,nextheight = komodo_nextheight();
CMutableTransaction tmpmtx , mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , nextheight ) ; UniValue result ( UniValue : : VOBJ ) ; uint256 createtxid , hashBlock , tokenid ;
CTransaction tx , txO ; CPubKey mypk , txidpk , Paymentspk ; int32_t i , n , m , numoprets = 0 , lockedblocks , minrelease ; int64_t newamount , inputsum , amount , CCchange = 0 , totalallocations = 0 , checkallocations = 0 , allocation ; CTxOut vout ; CScript onlyopret ; char txidaddr [ 64 ] , destaddr [ 64 ] ; std : : vector < uint256 > txidoprets ;
int32_t top , bottom = 0 , blocksleft = 0 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; int8_t funcid , fixedAmount = 0 ; bool fFixedAmount = false ;
int32_t top , bottom = 0 , blocksleft = 0 , minimum = 10000 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; int8_t funcid , fixedAmount = 0 ; bool fFixedAmount = false ;
mpz_t mpzTotalAllocations ; mpz_init ( mpzTotalAllocations ) ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
mypk = pubkey2pk ( Mypubkey ( ) ) ;
@ -647,7 +700,7 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
amount = jdouble ( jitem ( params , 1 ) , 0 ) * SATOSHIDEN + 0.0000000049 ;
if ( myGetTransaction ( createtxid , tx , hashBlock ) ! = 0 & & tx . vout . size ( ) > 0 )
{
if ( ( ( funcid = DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) ) = = ' C ' | | ( funcid = DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , bottom , fixedAmount , excludeScriptPubKeys ) ) = = ' S ' | | ( funcid = DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) ) = = ' O ' ) )
if ( ( ( funcid = DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) ) = = ' C ' | | ( funcid = DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) ) = = ' S ' | | ( funcid = DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) ) = = ' O ' ) )
{
if ( lockedblocks < 0 | | minrelease < 0 | | ( totalallocations < = 0 & & top < = 0 ) )
{
@ -657,6 +710,9 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
free_json ( params ) ;
return ( result ) ;
}
// set minimum size to 10k sat otherwise the tx will be invalid.
if ( minimum < 10000 )
minimum = 10000 ;
//latestheight = (nextheight - lockedblocks - 1);
if ( amount < minrelease * COIN )
{
@ -817,13 +873,14 @@ UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
}
//fprintf(stderr, "nValue.%li \n", mtx.vout[i+1].nValue);
mpz_clear ( mpzValue ) ;
/*
replace this with default dust threshold of 10 ksat
if ( mtx . vout [ i + 1 ] . nValue < PAYMENTS_TXFEE )
if ( mtx . vout [ i + 1 ] . nValue < minimum )
{
newamount + = ( PAYMENTS_TXFEE - mtx . vout [ i + 1 ] . nValue ) ;
mtx . vout [ i + 1 ] . nValue = PAYMENTS_TXFEE ;
} */
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " value too small, try releasing a larger amount " ) ) ;
if ( params ! = 0 )
free_json ( params ) ;
return ( result ) ;
}
totalamountsent + = mtx . vout [ i + 1 ] . nValue ;
}
if ( totalamountsent < amount ) newamount = totalamountsent ;
@ -879,7 +936,7 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ; UniValue result ( UniValue : : VOBJ ) ;
CPubKey Paymentspk , mypk , txidpk ; uint256 txid , hashBlock ; int64_t amount , totalallocations ; CScript opret ; CTransaction tx ; char txidaddr [ 64 ] ; std : : string rawtx ; int32_t n , useopret = 0 , lockedblocks , minrelease ; std : : vector < uint256 > txidoprets ;
int32_t top , bottom ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; // snapshot
int32_t top , bottom , minimum = 10000 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; // snapshot
uint256 tokenid ; int8_t fixedAmount ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
mypk = pubkey2pk ( Mypubkey ( ) ) ;
@ -890,7 +947,7 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
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 , lockedblocks , minrelease , totalallocations , txidoprets ) = = 0 & & DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , bottom , fixedAmount , excludeScriptPubKeys ) = = 0 & & DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) = = 0 ) )
if ( myGetTransaction ( txid , tx , hashBlock ) = = 0 | | tx . vout . size ( ) = = 1 | | ( DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) = = 0 & & DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) = = 0 & & DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) = = 0 ) )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " invalid createtxid " ) ) ;
@ -942,6 +999,64 @@ UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
return ( result ) ;
}
UniValue PaymentsMerge ( struct CCcontract_info * cp , char * jsonstr )
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ; UniValue result ( UniValue : : VOBJ ) ;
CPubKey Paymentspk , mypk , txidpk ; uint256 createtxid , hashBlock ; int64_t totalallocations , inputsum ; CScript opret ; CTransaction tx ; char txidaddr [ 64 ] , destaddr [ 64 ] ; std : : string rawtx ;
int32_t n , useopret = 0 , lockedblocks , minrelease , top , bottom , minimum = 10000 , blocksleft ; std : : vector < uint256 > txidoprets ;
std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; // snapshot
uint256 tokenid ; int8_t fixedAmount ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
mypk = pubkey2pk ( Mypubkey ( ) ) ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
if ( params ! = 0 & & n = = 1 )
{
createtxid = payments_juint256 ( jitem ( params , 0 ) ) ;
txidpk = CCtxidaddr ( txidaddr , createtxid ) ;
if ( myGetTransaction ( createtxid , tx , hashBlock ) = = 0 | | tx . vout . size ( ) = = 1 | | ( DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) = = 0 & & DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) = = 0 & & DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) = = 0 ) )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " invalid createtxid " ) ) ;
}
else if ( ( inputsum = AddPaymentsInputs ( true , 4 , cp , mtx , txidpk , 0 , CC_MAXVINS , createtxid , lockedblocks , minrelease , blocksleft ) ) > 0 & & mtx . vin . size ( ) > 1 )
{
int32_t dust = blocksleft ;
if ( mtx . vin . size ( ) ! = dust + 1 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " cannot merge only dust " ) ) ;
}
else
{
// encode the checktxid into the end of the ccvout, along with 'M' to flag merge type tx.
opret = EncodePaymentsMergeOpRet ( createtxid ) ;
std : : vector < std : : vector < unsigned char > > vData = std : : vector < std : : vector < unsigned char > > ( ) ;
if ( makeCCopret ( opret , vData ) )
mtx . vout . push_back ( MakeCC1vout ( EVAL_PAYMENTS , inputsum - PAYMENTS_TXFEE , Paymentspk , & vData ) ) ;
GetCCaddress1of2 ( cp , destaddr , Paymentspk , txidpk ) ;
CCaddr1of2set ( cp , Paymentspk , txidpk , cp - > CCpriv , destaddr ) ;
rawtx = FinalizeCCTx ( 0 , cp , mtx , mypk , PAYMENTS_TXFEE , CScript ( ) ) ;
if ( params ! = 0 )
free_json ( params ) ;
return ( payments_rawtxresult ( result , rawtx , 1 ) ) ;
}
}
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 " ) ) ;
}
if ( params ! = 0 )
free_json ( params ) ;
return ( result ) ;
}
UniValue PaymentsTxidopret ( struct CCcontract_info * cp , char * jsonstr )
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ; UniValue result ( UniValue : : VOBJ ) ; CPubKey mypk ; std : : string rawtx ;
@ -1062,7 +1177,7 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ;
UniValue result ( UniValue : : VOBJ ) ;
uint256 hashBlock ; CTransaction tx ; CPubKey Paymentspk , mypk ; char markeraddr [ 64 ] ; std : : string rawtx ;
int32_t lockedblocks , minrelease , top , bottom , n , i ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; int8_t fixedAmount ;
int32_t lockedblocks , minrelease , top , bottom , n , i , minimum = 10000 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; int8_t fixedAmount ;
if ( KOMODO_SNAPSHOT_INTERVAL = = 0 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
@ -1074,10 +1189,11 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
{
lockedblocks = juint ( jitem ( params , 0 ) , 0 ) ;
minrelease = juint ( jitem ( params , 1 ) , 0 ) ;
top = juint ( jitem ( params , 2 ) , 0 ) ;
bottom = juint ( jitem ( params , 3 ) , 0 ) ;
fixedAmount = juint ( jitem ( params , 4 ) , 0 ) ; // fixed amount is a flag set to 0 or 1. It means allocations are equal rather than weighted by address balance.
if ( lockedblocks < 0 | | minrelease < 0 | | top < = 0 | | bottom < 0 | | fixedAmount < 0 | | top > 3999 )
minimum = juint ( jitem ( params , 2 ) , 0 ) ;
top = juint ( jitem ( params , 3 ) , 0 ) ;
bottom = juint ( jitem ( params , 4 ) , 0 ) ;
fixedAmount = juint ( jitem ( params , 5 ) , 0 ) ; // fixed amount is a flag, set to 7 does game mode, 0 normal snapshot, anything else fixed allocations.
if ( lockedblocks < 0 | | minrelease < 0 | | top < = 0 | | bottom < 0 | | minimum < 0 | | fixedAmount < 0 | | top > 3999 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " negative parameter, or top over 3999 " ) ) ;
@ -1085,15 +1201,15 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
free_json ( params ) ;
return ( result ) ;
}
if ( n > 5 )
if ( n > 6 )
{
for ( i = 0 ; i < n - 5 ; i + + )
for ( i = 0 ; i < n - 6 ; i + + )
{
/* TODO: Change this RPC to take an address. Because a tokens airdrop needs its own RPC anyway.
CTxDestination destination = DecodeDestination ( name_ ) ;
CScript scriptPubKey = GetScriptForDestination ( destination ) ;
*/
char * inputhex = jstri ( params , 3 + i ) ;
char * inputhex = jstri ( params , 6 + i ) ;
std : : vector < uint8_t > scriptPubKey ;
int32_t len = strlen ( inputhex ) / 2 ;
scriptPubKey . resize ( len ) ;
@ -1106,7 +1222,16 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
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 , EncodePaymentsSnapsShotOpRet ( lockedblocks , minrelease , top , bottom , fixedAmount , excludeScriptPubKeys ) ) ;
CScript tempopret = EncodePaymentsSnapsShotOpRet ( lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) ;
if ( tempopret . size ( ) > 10000 ) // TODO: Check this!
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " op_return is too big, try with less exclude addresses. " ) ) ;
if ( params ! = 0 )
free_json ( params ) ;
return ( result ) ;
}
rawtx = FinalizeCCTx ( 0 , cp , mtx , mypk , PAYMENTS_TXFEE , tempopret ) ;
if ( params ! = 0 )
free_json ( params ) ;
return ( payments_rawtxresult ( result , rawtx , 1 ) ) ;
@ -1127,7 +1252,7 @@ UniValue PaymentsAirdrop(struct CCcontract_info *cp,char *jsonstr)
UniValue PaymentsInfo ( struct CCcontract_info * cp , char * jsonstr )
{
UniValue result ( UniValue : : VOBJ ) , a ( UniValue : : VARR ) ; CTransaction tx , txO ; CPubKey Paymentspk , txidpk ; int32_t i , j , n , flag = 0 , numoprets = 0 , lockedblocks , minrelease , blocksleft = 0 ; std : : vector < uint256 > txidoprets ; int64_t funds , fundsopret , elegiblefunds , totalallocations = 0 , allocation ; char fundsaddr [ 64 ] , fundsopretaddr [ 64 ] , txidaddr [ 64 ] , * outstr ; uint256 createtxid , hashBlock ;
int32_t top , bottom ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; // snapshot
int32_t top , bottom , minimum = 10000 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; // snapshot
uint256 tokenid ; int8_t fixedAmount ; CMutableTransaction mtx = CreateNewContextualCMutableTransaction ( Params ( ) . GetConsensus ( ) , komodo_nextheight ( ) ) ;
cJSON * params = payments_reparse ( & n , jsonstr ) ;
if ( params ! = 0 & & n = = 1 )
@ -1183,9 +1308,9 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
result . push_back ( Pair ( " error " , " too many opreturns " ) ) ;
} else result . push_back ( Pair ( " txidoprets " , a ) ) ;
}
else if ( DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , bottom , fixedAmount , excludeScriptPubKeys ) ! = 0 )
else if ( DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) ! = 0 )
{
if ( lockedblocks < 0 | | minrelease < 0 | | top < = 0 | | bottom < 0 | | fixedAmount < 0 | | top > 3999 )
if ( lockedblocks < 0 | | minrelease < 0 | | top < = 0 | | bottom < 0 | | fixedAmount < 0 | | top > 3999 | | minimum < 10000 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " negative parameter " ) ) ;
@ -1198,7 +1323,8 @@ UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
else
result . push_back ( Pair ( " plan_type " , " snapshot " ) ) ;
result . push_back ( Pair ( " lockedblocks " , ( int64_t ) lockedblocks ) ) ;
result . push_back ( Pair ( " minrelease " , ( int64_t ) minrelease ) ) ;
result . push_back ( Pair ( " minrelease " , ( int64_t ) minrelease ) ) ;
result . push_back ( Pair ( " minimum " , ( int64_t ) minimum ) ) ;
result . push_back ( Pair ( " bottom " , ( int64_t ) bottom ) ) ;
result . push_back ( Pair ( " top " , ( int64_t ) top ) ) ;
result . push_back ( Pair ( " fixedFlag " , ( int64_t ) fixedAmount ) ) ;
@ -1272,7 +1398,7 @@ UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr)
{
std : : vector < std : : pair < CAddressIndexKey , CAmount > > addressIndex ; uint256 txid , hashBlock , tokenid ;
UniValue result ( UniValue : : VOBJ ) , a ( UniValue : : VARR ) ; char markeraddr [ 64 ] , str [ 65 ] ; CPubKey Paymentspk ; CTransaction tx ; int32_t lockedblocks , minrelease ; std : : vector < uint256 > txidoprets ; int64_t totalallocations = 0 ;
int32_t top = 0 , bottom = 0 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; int8_t fixedAmount = 0 ;
int32_t top = 0 , bottom = 0 , minimum = 10000 ; std : : vector < std : : vector < uint8_t > > excludeScriptPubKeys ; int8_t fixedAmount = 0 ;
Paymentspk = GetUnspendable ( cp , 0 ) ;
GetCCaddress1of2 ( cp , markeraddr , Paymentspk , Paymentspk ) ;
SetCCtxids ( addressIndex , markeraddr , true ) ;
@ -1281,9 +1407,9 @@ UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr)
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 , lockedblocks , minrelease , totalallocations , txidoprets ) = = ' C ' | | DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , bottom , fixedAmount , excludeScriptPubKeys ) = = ' S ' | | DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) = = ' O ' ) )
if ( tx . vout . size ( ) > 0 & & ( DecodePaymentsOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , totalallocations , txidoprets ) = = ' C ' | | DecodePaymentsSnapsShotOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , minimum , top , bottom , fixedAmount , excludeScriptPubKeys ) = = ' S ' | | DecodePaymentsTokensOpRet ( tx . vout [ tx . vout . size ( ) - 1 ] . scriptPubKey , lockedblocks , minrelease , top , excludeScriptPubKeys , tokenid ) = = ' O ' ) )
{
if ( lockedblocks < 0 | | minrelease < 0 | | ( totalallocations < = 0 & & top < = 0 ) | | bottom < 0 | | fixedAmount < 0 )
if ( lockedblocks < 0 | | minrelease < 0 | | ( totalallocations < = 0 & & top < = 0 ) | | bottom < 0 | | fixedAmount < 0 | | minimum < 10000 )
{
result . push_back ( Pair ( " result " , " error " ) ) ;
result . push_back ( Pair ( " error " , " negative parameter " ) ) ;