Merge pull request #1011 from jl777/FSM

FSM
This commit is contained in:
jl777
2018-12-01 08:43:25 -11:00
committed by GitHub
15 changed files with 334 additions and 114 deletions

View File

@@ -16,6 +16,8 @@
#include <event2/buffer.h> #include <event2/buffer.h>
#include <event2/keyvalq_struct.h> #include <event2/keyvalq_struct.h>
#include "support/events.h" #include "support/events.h"
uint16_t BITCOIND_RPCPORT = 7771;
char ASSETCHAINS_SYMBOL[65];
#include <univalue.h> #include <univalue.h>
@@ -64,27 +66,6 @@ public:
}; };
#define FROM_CLI
#include "uint256.h"
#include "arith_uint256.h"
#include "komodo_structs.h"
#include "komodo_globals.h"
#include "komodo_utils.h"
#include "komodo_cJSON.c"
#include "komodo_notary.h"
void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth)
{
}
uint32_t komodo_heightstamp(int32_t height)
{
return(0);
}
// //
// This function returns either one of EXIT_ codes when it's expected to stop the process or // This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further. // CONTINUE_EXECUTION when it's expected to continue further.
@@ -99,7 +80,11 @@ static int AppInitRPC(int argc, char* argv[])
// Parameters // Parameters
// //
ParseParameters(argc, argv); ParseParameters(argc, argv);
komodo_args(argv[0]); std:string name;
name = GetArg("-ac_name","");
if ( !name.empty() )
strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1);
if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) { if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo(); std::string strUsage = _("Komodo RPC client version") + " " + FormatFullVersion() + "\n" + PrivacyInfo();
if (!mapArgs.count("-version")) { if (!mapArgs.count("-version")) {

View File

@@ -35,7 +35,7 @@ CScript EncodeAssetOpRet(uint8_t funcid,uint256 assetid,uint256 assetid2,int64_t
bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description); bool DecodeAssetCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description);
uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey); uint8_t DecodeAssetOpRet(const CScript &scriptPubKey,uint256 &assetid,uint256 &assetid2,int64_t &price,std::vector<uint8_t> &origpubkey);
bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx); bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx);
int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid); int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid);
bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); bool ValidateBidRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); bool ValidateAskRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice); bool ValidateSwapRemainder(int64_t remaining_price,int64_t remaining_nValue,int64_t orig_nValue,int64_t received_nValue,int64_t paidprice,int64_t totalprice);
@@ -44,7 +44,8 @@ bool SetAskFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValu
bool SetSwapFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice); bool SetSwapFillamounts(int64_t &paid,int64_t &remaining_price,int64_t orig_nValue,int64_t &received,int64_t totalprice);
int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid); int64_t AssetValidateBuyvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 refassetid);
int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid); int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpprice,std::vector<uint8_t> &tmporigpubkey,char *CCaddr,char *origaddr,const CTransaction &tx,uint256 assetid);
bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid); bool AssetExactAmounts(int32_t maxDepth, struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid);
//bool AssetExactAmounts(bool doValidateTx, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid, std::vector<CTransaction> &ccVinsTxs);
// CCassetstx // CCassetstx
int64_t GetAssetBalance(CPubKey pk,uint256 tokenid); int64_t GetAssetBalance(CPubKey pk,uint256 tokenid);

View File

@@ -342,25 +342,54 @@ bool GetAssetorigaddrs(struct CCcontract_info *cp,char *CCaddr,char *destaddr,co
else return(false); else return(false);
} }
int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid)
// Checks if the vout is a really Asset CC vout
// if maxAssetExactAmountDepth > 0, it also validates the vin transaction itself:
// it should be either sum(cc vins) == sum(cc vouts) or the transaction is the 'tokenbase' ('c') tx
int64_t IsAssetvout(int32_t maxAssetExactAmountDepth, struct CCcontract_info *cp, Eval* eval, int64_t &price,std::vector<uint8_t> &origpubkey,const CTransaction& tx,int32_t v,uint256 refassetid)
{ {
uint256 assetid,assetid2; int64_t nValue=0; int32_t n; uint8_t funcid; uint256 assetid,assetid2; int64_t nValue=0; int32_t n; uint8_t funcid;
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too? if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 ) // maybe check address too?
{ {
n = tx.vout.size();
if (maxAssetExactAmountDepth > 0) {
//validate all tx
int64_t myCCVinsAmount = 0, myCCVoutsAmount = 0;
std::vector<CTransaction> ccVinsTxs;
//std::cerr << "IsAssetvout() validate=yes" << std::endl;
const bool validateVinTxs = false;
bool isEqualAmounts = AssetExactAmounts(maxAssetExactAmountDepth, cp, myCCVinsAmount, 0, myCCVoutsAmount, eval, tx, refassetid);
// if ccInputs != ccOutputs and it is not the tokenbase tx means it is possibly fake tx (dimxy):
if (!isEqualAmounts && refassetid != tx.GetHash()) { // checking that this is the true tokenbase tx, by verifying that funcid=c, is done further in this function (dimxy)
std::cerr << "IsAssetvout() detected bad tx=" << tx.GetHash().GetHex() << ": cc inputs != cc outputs and not the 'tokenbase' tx" << std::endl;
return 0;
}
}
n = tx.vout.size();
if (v >= n - 1) { // just moved this up (dimxy)
std::cerr << "isAssetVout() internal err: (v >= n - 1), returning 0" << std::endl;
return(0);
}
nValue = tx.vout[v].nValue; nValue = tx.vout[v].nValue;
//fprintf(stderr,"CC vout v.%d of n.%d %.8f\n",v,n,(double)nValue/COIN);
if ( v >= n-1 ) // fprintf(stderr,"IsAssetvout() CC vout v.%d of n=%d amount=%.8f\n",v,n,(double)nValue/COIN);
return(0);
if ( (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 ) if ( (funcid= DecodeAssetOpRet(tx.vout[n-1].scriptPubKey,assetid,assetid2,price,origpubkey)) == 0 )
{ {
fprintf(stderr,"null decodeopret v.%d\n",v); fprintf(stderr,"IsAssetvout() null decodeopret v.%d\n",v);
return(0); return(0);
} }
else if ( funcid == 'c' ) else if ( funcid == 'c' )
{ {
if ( refassetid == tx.GetHash() && v == 0 ) if (refassetid == tx.GetHash() && v == 0) {
return(nValue); std::cerr << "isAssetVout() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " returning nValue=" << nValue << std::endl;
return(nValue);
}
} }
else if ( (funcid == 'b' || funcid == 'B') && v == 0 ) // critical! 'b'/'B' vout0 is NOT asset else if ( (funcid == 'b' || funcid == 'B') && v == 0 ) // critical! 'b'/'B' vout0 is NOT asset
return(0); return(0);
@@ -368,7 +397,7 @@ int64_t IsAssetvout(int64_t &price,std::vector<uint8_t> &origpubkey,const CTrans
{ {
if ( assetid == refassetid ) if ( assetid == refassetid )
{ {
//fprintf(stderr,"returning %.8f\n",(double)nValue/COIN); fprintf(stderr,"IsAssetvout() returning %.8f\n",(double)nValue/COIN);
return(nValue); return(nValue);
} }
} }
@@ -443,29 +472,37 @@ int64_t AssetValidateSellvin(struct CCcontract_info *cp,Eval* eval,int64_t &tmpp
fprintf(stderr,"AssetValidateSellvin\n"); fprintf(stderr,"AssetValidateSellvin\n");
if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 ) if ( (nValue= AssetValidateCCvin(cp,eval,CCaddr,origaddr,tx,1,vinTx)) == 0 )
return(0); return(0);
if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,vinTx,0,assetid)) == 0 ) if ( (assetoshis= IsAssetvout(1, cp, NULL, tmpprice,tmporigpubkey,vinTx,0,assetid)) == 0 )
return eval->Invalid("invalid missing CC vout0 for sellvin"); return eval->Invalid("invalid missing CC vout0 for sellvin");
else return(assetoshis); else return(assetoshis);
} }
bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti,int64_t &outputs,Eval* eval,const CTransaction &tx,uint256 assetid)
// overload with additional params for deep tx validation (dimxy)
bool AssetExactAmounts(int maxDepth, struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid)
{ {
CTransaction vinTx; uint256 hashBlock,id,id2; int32_t i,flag,numvins,numvouts; int64_t assetoshis; std::vector<uint8_t> tmporigpubkey; int64_t tmpprice; CTransaction vinTx; uint256 hashBlock,id,id2; int32_t i,flag,numvins,numvouts; int64_t assetoshis; std::vector<uint8_t> tmporigpubkey; int64_t tmpprice;
numvins = tx.vin.size(); numvins = tx.vin.size();
numvouts = tx.vout.size(); numvouts = tx.vout.size();
inputs = outputs = 0; inputs = outputs = 0;
maxDepth--;
for (i=starti; i<numvins; i++) for (i=starti; i<numvins; i++)
{ {
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 ) if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
{ {
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) //std::cerr << "AssetExactAmounts() eval is true=" << (eval != NULL) << " ismyvin=ok for_i=" << i << std::endl;
// we are really not inside validation! -- dimxy
if ( (eval && eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0) || (!eval && !myGetTransaction(tx.vin[i].prevout.hash, vinTx, hashBlock)) )
{ {
fprintf(stderr,"i.%d starti.%d numvins.%d\n",i,starti,numvins); fprintf(stderr,"AssetExactAmounts() cannot read vintx i.%d starti.%d numvins.%d\n", i,starti,numvins);
return eval->Invalid("always should find vin, but didnt"); return (!eval) ? false : eval->Invalid("always should find vin, but didnt");
}
else if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,vinTx,tx.vin[i].prevout.n,assetid)) != 0 ) } // false means 'don't go deeper' -- dimxy
else if ( (assetoshis= IsAssetvout( maxDepth, cp, eval, tmpprice,tmporigpubkey,vinTx,tx.vin[i].prevout.n,assetid)) != 0 )
{ {
fprintf(stderr,"vin%d %llu, ",i,(long long)assetoshis); fprintf(stderr,"AssetExactAmounts() vin%d %llu, ",i,(long long)assetoshis);
inputs += assetoshis; inputs += assetoshis;
} }
else else
@@ -473,33 +510,47 @@ bool AssetExactAmounts(struct CCcontract_info *cp,int64_t &inputs,int32_t starti
if ( vinTx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 && DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid ) if ( vinTx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 && DecodeAssetOpRet(vinTx.vout[vinTx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid )
{ {
assetoshis = vinTx.vout[i].nValue; assetoshis = vinTx.vout[i].nValue;
fprintf(stderr,"vin%d %llu special case, ",i,(long long)assetoshis); fprintf(stderr,"AssetExactAmounts() vin%d assetoshis=%llu special case, ",i,(long long)assetoshis);
inputs += assetoshis; inputs += assetoshis;
} }
} }
} }
} }
if ( DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid ) if ( DecodeAssetOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,id,id2,tmpprice,tmporigpubkey) == 't' && id == assetid )
flag = 1; flag = 1;
else flag = 0; else flag = 0;
for (i=0; i<numvouts; i++) for (i=0; i<numvouts; i++)
{ { // 'false' means 'dont go deep' -- dimxy
if ( (assetoshis= IsAssetvout(tmpprice,tmporigpubkey,tx,i,assetid)) != 0 ) if ( (assetoshis= IsAssetvout(maxDepth, cp, eval, tmpprice,tmporigpubkey,tx,i,assetid)) != 0 )
{ {
fprintf(stderr,"vout%d %llu, ",i,(long long)assetoshis); fprintf(stderr,"AssetExactAmounts() vout%d assetoshis=%llu, ",i,(long long)assetoshis);
outputs += assetoshis; outputs += assetoshis;
} }
// Note: account it only if this is 'transfer' tx -- dimxy
else if ( flag != 0 && tx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 ) else if ( flag != 0 && tx.vout[i].scriptPubKey.IsPayToCryptoCondition() != 0 )
{ {
assetoshis = tx.vout[i].nValue; assetoshis = tx.vout[i].nValue;
fprintf(stderr,"vout%d %llu special case, ",i,(long long)assetoshis); fprintf(stderr,"AssetExactAmounts() vout%d assetoshis=%llu special case, ",i,(long long)assetoshis);
outputs += assetoshis; outputs += assetoshis;
} }
} }
//std::cerr << "AssetExactAmounts() inputs=" << inputs << " outputs=" << outputs << " for txid=" << tx.GetHash().GetHex() << std::endl;
if ( inputs != outputs ) if ( inputs != outputs )
{ {
fprintf(stderr,"inputs %.8f vs %.8f outputs\n",(double)inputs/COIN,(double)outputs/COIN); std::cerr << "AssetExactAmounts() incorrect inputs=" << (double)inputs / COIN << " vs outputs=" << (double)outputs/COIN << " for txid=" << tx.GetHash().GetHex() << std::endl;
return(false); return(false);
} }
else return(true); else return(true);
} }
// overload for existing calls of this function (dimxy)
/*bool AssetExactAmounts(struct CCcontract_info *cp, int64_t &inputs, int32_t starti, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 assetid) {
std::vector<CTransaction> ccVinsTxs;
return AssetExactAmounts(true, cp, inputs, starti, outputs, eval, tx, assetid);
}*/

View File

@@ -38,19 +38,22 @@ int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey); Getscriptaddress(destaddr,vintx.vout[vout].scriptPubKey);
if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 ) if ( strcmp(destaddr,coinaddr) != 0 && strcmp(destaddr,cp->unspendableCCaddr) != 0 && strcmp(destaddr,cp->unspendableaddr2) != 0 )
continue; continue;
fprintf(stderr,"check %s %.8f\n",destaddr,(double)vintx.vout[vout].nValue/COIN); fprintf(stderr,"AddAssetInputs() check destaddress=%s vout amount=%.8f\n",destaddr,(double)vintx.vout[vout].nValue/COIN);
if ( (nValue= IsAssetvout(price,origpubkey,vintx,vout,assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) if ( (nValue= IsAssetvout(1, cp, NULL, price,origpubkey,vintx,vout,assetid)) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{ {
if ( total != 0 && maxinputs != 0 ) if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript())); mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis; nValue = it->second.satoshis;
totalinputs += nValue; totalinputs += nValue;
//std::cerr << "AddAssetInputs() adding input nValue=" << nValue << std::endl;
n++; n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break; break;
} }
} }
} }
//std::cerr << "AddAssetInputs() found totalinputs=" << totalinputs << std::endl;
return(totalinputs); return(totalinputs);
} }
@@ -235,6 +238,11 @@ std::string AssetTransfer(int64_t txfee,uint256 assetid,std::vector<uint8_t> des
mask = ~((1LL << mtx.vin.size()) - 1); mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 ) if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,total,60)) > 0 )
{ {
if (inputs < total) { //added dimxy
std::cerr << "AssetTransfer(): insufficient funds" << std::endl;
return ("");
}
if ( inputs > total ) if ( inputs > total )
CCchange = (inputs - total); CCchange = (inputs - total);
//for (i=0; i<n; i++) //for (i=0; i<n; i++)
@@ -310,6 +318,9 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p
{ {
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C; CPubKey mypk; uint64_t mask; int64_t inputs,CCchange; CScript opret; struct CCcontract_info *cp,C;
//std::cerr << "CreateSell() askamount=" << askamount << " pricetotal=" << pricetotal << std::endl;
if ( askamount < 0 || pricetotal < 0 ) if ( askamount < 0 || pricetotal < 0 )
{ {
fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount); fprintf(stderr,"negative askamount %lld, askamount %lld\n",(long long)pricetotal,(long long)askamount);
@@ -324,8 +335,12 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p
mask = ~((1LL << mtx.vin.size()) - 1); mask = ~((1LL << mtx.vin.size()) - 1);
if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 ) if ( (inputs= AddAssetInputs(cp,mtx,mypk,assetid,askamount,60)) > 0 )
{ {
if ( inputs < askamount ) if (inputs < askamount) {
askamount = inputs; //askamount = inputs;
std::cerr << "CreateSell(): insufficient tokens for ask" << std::endl;
return ("");
}
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0))); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,askamount,GetUnspendable(cp,0)));
if ( inputs > askamount ) if ( inputs > askamount )
CCchange = (inputs - askamount); CCchange = (inputs - askamount);
@@ -333,9 +348,14 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk)); mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS,CCchange,mypk));
opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey()); opret = EncodeAssetOpRet('s',assetid,zeroid,pricetotal,Mypubkey());
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"need some assets to place ask\n"); }
else {
fprintf(stderr, "need some assets to place ask\n");
}
} }
fprintf(stderr,"need some native coins to place ask\n"); else { // dimxy added 'else', because it was misleading message before
fprintf(stderr, "need some native coins to place ask\n");
}
return(""); return("");
} }
@@ -373,9 +393,15 @@ std::string CreateSwap(int64_t txfee,int64_t askamount,uint256 assetid,uint256 a
opret = EncodeAssetOpRet('e',assetid,assetid2,pricetotal,Mypubkey()); opret = EncodeAssetOpRet('e',assetid,assetid2,pricetotal,Mypubkey());
} }
return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret)); return(FinalizeCCTx(mask,cp,mtx,mypk,txfee,opret));
} else fprintf(stderr,"need some assets to place ask\n"); }
else {
fprintf(stderr, "need some assets to place ask\n");
}
} }
fprintf(stderr,"need some native coins to place ask\n"); else { // dimxy added 'else', because it was misleading message before
fprintf(stderr,"need some native coins to place ask\n");
}
return(""); return("");
} }

View File

@@ -178,6 +178,7 @@ std::string FinalizeCCTx(uint64_t skipmask,struct CCcontract_info *cp,CMutableTr
void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr); void SetCCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr);
void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr); void SetCCtxids(std::vector<std::pair<CAddressIndexKey, CAmount> > &addressIndex,char *coinaddr);
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs); int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs);
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs);
int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout); int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout);
// curve25519 and sha256 // curve25519 and sha256

View File

@@ -431,3 +431,92 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
#endif #endif
return(0); return(0);
} }
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs)
{
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=64; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));
threshold = total/(maxinputs+1);
if ( maxinputs > maxutxos )
maxutxos = maxinputs;
sum = 0;
Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( it->second.satoshis < threshold )
continue;
if ( myGetTransaction(txid,tx,hashBlock) != 0 && tx.vout.size() > 0 && vout < tx.vout.size() && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() == 0 )
{
//fprintf(stderr,"check %.8f to vins array.%d of %d %s/v%d\n",(double)out.tx->vout[out.i].nValue/COIN,n,maxutxos,txid.GetHex().c_str(),(int32_t)vout);
if ( mtx.vin.size() > 0 )
{
for (i=0; i<mtx.vin.size(); i++)
if ( txid == mtx.vin[i].prevout.hash && vout == mtx.vin[i].prevout.n )
break;
if ( i != mtx.vin.size() )
continue;
}
if ( n > 0 )
{
for (i=0; i<n; i++)
if ( txid == utxos[i].txid && vout == utxos[i].vout )
break;
if ( i != n )
continue;
}
if ( myIsutxo_spentinmempool(txid,vout) == 0 )
{
up = &utxos[n++];
up->txid = txid;
up->nValue = it->second.satoshis;
up->vout = vout;
sum += up->nValue;
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
if ( n >= maxutxos || sum >= total )
break;
}
}
}
remains = total;
for (i=0; i<maxinputs && n>0; i++)
{
below = above = 0;
abovei = belowi = -1;
if ( CC_vinselect(&abovei,&above,&belowi,&below,utxos,n,remains) < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f\n",i,n,(double)remains/COIN,(double)total/COIN);
free(utxos);
return(0);
}
if ( belowi < 0 || abovei >= 0 )
ind = abovei;
else ind = belowi;
if ( ind < 0 )
{
printf("error finding unspent i.%d of %d, %.8f vs %.8f, abovei.%d belowi.%d ind.%d\n",i,n,(double)remains/COIN,(double)total/COIN,abovei,belowi,ind);
free(utxos);
return(0);
}
up = &utxos[ind];
mtx.vin.push_back(CTxIn(up->txid,up->vout,CScript()));
totalinputs += up->nValue;
remains -= up->nValue;
utxos[ind] = utxos[--n];
memset(&utxos[n],0,sizeof(utxos[n]));
//fprintf(stderr,"totalinputs %.8f vs total %.8f i.%d vs max.%d\n",(double)totalinputs/COIN,(double)total/COIN,i,maxinputs);
if ( totalinputs >= total || (i+1) >= maxinputs )
break;
}
free(utxos);
if ( totalinputs >= total )
{
//fprintf(stderr,"return totalinputs %.8f\n",(double)totalinputs/COIN);
return(totalinputs);
}
return(0);
}

View File

@@ -129,6 +129,10 @@
vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey] vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
*/ */
// tx validation
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{ {
static uint256 zero; static uint256 zero;
@@ -155,9 +159,11 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
else starti = 1; else starti = 1;
if ( assetid == zero ) if ( assetid == zero )
return eval->Invalid("illegal assetid"); return eval->Invalid("illegal assetid");
else if ( AssetExactAmounts(cp,inputs,starti,outputs,eval,tx,assetid) == false ) else if ( AssetExactAmounts(2, cp,inputs,starti,outputs,eval,tx,assetid) == false )
return eval->Invalid("asset inputs != outputs"); return eval->Invalid("asset inputs != outputs");
} }
switch ( funcid ) switch ( funcid )
{ {
case 'c': // create wont be called to be verified as it has no CC inputs case 'c': // create wont be called to be verified as it has no CC inputs
@@ -321,7 +327,7 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
} }
fprintf(stderr,"fill validated\n"); fprintf(stderr,"fill validated\n");
break; break;
case 'E': // fillexchange case 'E': // fillexchange
return eval->Invalid("unexpected assets fillexchange funcid"); return eval->Invalid("unexpected assets fillexchange funcid");
break; // disable asset swaps break; // disable asset swaps
//vin.0: normal input //vin.0: normal input
@@ -333,7 +339,7 @@ bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
//vout.3: CC output for asset2 change (if any) //vout.3: CC output for asset2 change (if any)
//vout.3/4: normal output for change (if any) //vout.3/4: normal output for change (if any)
//vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey] //vout.n-1: opreturn [EVAL_ASSETS] ['E'] [assetid vin0+1] [assetid vin2] [remaining asset2 required] [origpubkey]
if ( AssetExactAmounts(cp,inputs,1,outputs,eval,tx,assetid2) == false ) if ( AssetExactAmounts(1, cp,inputs,1,outputs,eval,tx,assetid2) == false )
eval->Invalid("asset2 inputs != outputs"); eval->Invalid("asset2 inputs != outputs");
if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 ) if ( (assetoshis= AssetValidateSellvin(cp,eval,totalunits,tmporigpubkey,CCaddr,origaddr,tx,assetid)) == 0 )
return(false); return(false);

View File

@@ -98,7 +98,7 @@ What is needed is for the dealer node to track the entropy tx that was already b
#include "../compat/endian.h" #include "../compat/endian.h"
#define MAX_ENTROPYUSED 8192 #define MAX_ENTROPYUSED 8192
#define DICE_MINUTXOS 10000 #define DICE_MINUTXOS 15000
extern int32_t KOMODO_INSYNC; extern int32_t KOMODO_INSYNC;
pthread_mutex_t DICE_MUTEX,DICEREVEALED_MUTEX; pthread_mutex_t DICE_MUTEX,DICEREVEALED_MUTEX;
@@ -1392,7 +1392,7 @@ std::string DiceAddfunding(uint64_t txfee,char *planstr,uint256 fundingtxid,int6
} }
if ( scriptPubKey == fundingPubKey ) if ( scriptPubKey == fundingPubKey )
{ {
if ( AddNormalinputs(mtx,mypk,amount+2*txfee,1) > 0 ) if ( AddNormalinputs2(mtx,amount+2*txfee,60) > 0 )
{ {
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1); hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,dicepk)); mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,dicepk));
@@ -1505,7 +1505,7 @@ std::string DiceBetFinish(uint8_t &funcid,uint256 &entropyused,int32_t &entropyv
{ {
if ( vin0txid == zeroid || vin0vout < 0 ) if ( vin0txid == zeroid || vin0vout < 0 )
{ {
if ( AddNormalinputs(mtx,mypk,2*txfee,3) == 0 ) // must be a single vin!! if ( AddNormalinputs2(mtx,2*txfee,3) == 0 ) // must be a single vin!!
{ {
CCerror = "no txfee inputs for win/lose"; CCerror = "no txfee inputs for win/lose";
fprintf(stderr,"%s\n", CCerror.c_str() ); fprintf(stderr,"%s\n", CCerror.c_str() );
@@ -1652,22 +1652,32 @@ static uint256 dealer0_fundingtxid;
void *dealer0_loop(void *_arg) void *dealer0_loop(void *_arg)
{ {
char *planstr = (char *)_arg; char *planstr = (char *)_arg;
CTransaction tx; CPubKey mypk,dicepk; uint64_t entropyval; uint256 entropytxid; int32_t entropytxs,i,n,num; CScript fundingPubKey; struct CCcontract_info *cp,C; char coinaddr[64]; std::string res; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t refsbits,txfee = 10000; CTransaction tx,*entropytxs,entropytx; CPubKey mypk,dicepk; uint64_t entropyval; uint256 hashBlock,entropytxid,txid; int32_t height,lastht,numentropytxs,i,n,m,num; CScript fundingPubKey; struct CCcontract_info *cp,C; char coinaddr[64]; std::string res; int64_t minbet,maxbet,maxodds,timeoutblocks; uint64_t refsbits,txfee = 10000;
if ( (cp= Diceinit(fundingPubKey,dealer0_fundingtxid,&C,planstr,txfee,mypk,dicepk,refsbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 ) if ( (cp= Diceinit(fundingPubKey,dealer0_fundingtxid,&C,planstr,txfee,mypk,dicepk,refsbits,minbet,maxbet,maxodds,timeoutblocks)) == 0 )
{ {
fprintf(stderr,"error initializing dealer0_loop\n"); fprintf(stderr,"error initializing dealer0_loop\n");
exit(-1); exit(-1);
} }
fprintf(stderr,"dealer0 node running\n"); fprintf(stderr,"dealer0 node running\n");
height = lastht = 0;
entropytxs = (CTransaction *)calloc(sizeof(*entropytxs),DICE_MINUTXOS);
while ( 1 ) while ( 1 )
{ {
DicePlanFunds(entropyval,entropytxid,refsbits,cp,dicepk,dealer0_fundingtxid,entropytxs,false); while ( KOMODO_INSYNC == 0 || (height= KOMODO_INSYNC) == lastht )
if ( entropytxs < DICE_MINUTXOS )
{ {
n = sqrt(DICE_MINUTXOS - entropytxs) + 10; sleep(3);
for (i=0; i<DICE_MINUTXOS - entropytxs && i<n; i++) }
lastht = height;
fprintf(stderr,"New height.%d\n",height);
DicePlanFunds(entropyval,entropytxid,refsbits,cp,dicepk,dealer0_fundingtxid,numentropytxs,false);
if ( numentropytxs < DICE_MINUTXOS )
{
n = sqrt(DICE_MINUTXOS - numentropytxs);
//if ( n > 10 )
// n = 10;
for (i=m=0; i<DICE_MINUTXOS - numentropytxs && i<n; i++)
{ {
res = DiceAddfunding(txfee,planstr,dealer0_fundingtxid,COIN/100); res = DiceAddfunding(txfee,planstr,dealer0_fundingtxid,COIN);
if ( res.empty() == 0 && res.size() > 64 && is_hexstr((char *)res.c_str(),0) > 64 ) if ( res.empty() == 0 && res.size() > 64 && is_hexstr((char *)res.c_str(),0) > 64 )
{ {
if ( DecodeHexTx(tx,res) != 0 ) if ( DecodeHexTx(tx,res) != 0 )
@@ -1675,12 +1685,37 @@ void *dealer0_loop(void *_arg)
LOCK(cs_main); LOCK(cs_main);
if ( myAddtomempool(tx) != 0 ) if ( myAddtomempool(tx) != 0 )
{ {
fprintf(stderr,"ENTROPY %s: %d of %d, %d\n",tx.GetHash().GetHex().c_str(),i,n,DICE_MINUTXOS - entropytxs); fprintf(stderr,"ENTROPY %s: %d of %d, %d\n",tx.GetHash().GetHex().c_str(),i,n,DICE_MINUTXOS - numentropytxs);
RelayTransaction(tx); RelayTransaction(tx);
entropytxs[m++] = tx;
} else break; } else break;
} else break; } else break;
} else break; } else break;
} }
for (i=0; i<m; i++)
{
tx = entropytxs[i];
txid = tx.GetHash();
fprintf(stderr,"check %d of %d: %s\n",i,m,txid.GetHex().c_str());
while ( 1 )
{
if ( myGetTransaction(txid,entropytx,hashBlock) == 0 || hashBlock == zeroid )
{
LOCK(cs_main);
if ( myAddtomempool(tx) != 0 )
{
fprintf(stderr,"resend ENTROPY %s: %d of %d\n",txid.GetHex().c_str(),i,m);
RelayTransaction(tx);
}
}
else
{
fprintf(stderr,"found %s in %s\n",txid.GetHex().c_str(),hashBlock.GetHex().c_str());
break;
}
sleep(10);
}
}
} }
pubkey2addr(coinaddr,Mypubkey().data()); pubkey2addr(coinaddr,Mypubkey().data());
dicefinish_utxosget(num,0,0,coinaddr); dicefinish_utxosget(num,0,0,coinaddr);

View File

@@ -1486,7 +1486,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles); pblocktree = new CBlockTreeDB(nBlockTreeDBCache, false, fReindex, dbCompression, dbMaxOpenFiles);
fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX);
pblocktree->ReadFlag("addressindex", checkval); pblocktree->ReadFlag("addressindex", checkval);
if ( checkval != fAddressIndex ) if ( checkval != fAddressIndex && fAddressIndex != 0 )
{ {
pblocktree->WriteFlag("addressindex", fAddressIndex); pblocktree->WriteFlag("addressindex", fAddressIndex);
fprintf(stderr,"set addressindex, will reindex. could take a while.\n"); fprintf(stderr,"set addressindex, will reindex. could take a while.\n");
@@ -1494,7 +1494,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
} }
fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX);
pblocktree->ReadFlag("spentindex", checkval); pblocktree->ReadFlag("spentindex", checkval);
if ( checkval != fSpentIndex ) if ( checkval != fSpentIndex && fSpentIndex != 0 )
{ {
pblocktree->WriteFlag("spentindex", fSpentIndex); pblocktree->WriteFlag("spentindex", fSpentIndex);
fprintf(stderr,"set spentindex, will reindex. could take a while.\n"); fprintf(stderr,"set spentindex, will reindex. could take a while.\n");

View File

@@ -1771,12 +1771,12 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
{ {
if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 ) if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 )
{ {
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64 if ( ASSETCHAINS_STAKED == 100 && height > 100 ) // only PoS allowed! POSTEST64
return(-1); return(-1);
else else
{ {
if ( slowflag == 0 ) // need all past 100 blocks to calculate PoW target
return(0);
if ( slowflag != 0 ) if ( slowflag != 0 )
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED); bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
if ( bhash > bnTarget ) if ( bhash > bnTarget )
@@ -1796,6 +1796,8 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
fprintf(stderr,"unexpected negative is_PoSblock.%d\n",is_PoSblock); fprintf(stderr,"unexpected negative is_PoSblock.%d\n",is_PoSblock);
return(-1); return(-1);
} }
else if ( ASSETCHAINS_STAKED != 0 )
failed = 0;
} }
if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) if ( failed == 0 && ASSETCHAINS_COMMISSION != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
{ {
@@ -1824,7 +1826,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1); return(-1);
} }
} }
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed); //fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
if ( failed != 0 && possible == 0 && notaryid < 0 ) if ( failed != 0 && possible == 0 && notaryid < 0 )
return(-1); return(-1);
else return(0); else return(0);

View File

@@ -13,7 +13,7 @@
#define KOMODO_FIRSTFUNGIBLEID 100 #define KOMODO_FIRSTFUNGIBLEID 100
#define KOMODO_SAPLING_ACTIVATION 1544832000 // Dec 15th, 2018 #define KOMODO_SAPLING_ACTIVATION 1544832000 // Dec 15th, 2018
#define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019 #define KOMODO_SAPLING_DEADLINE 1550188800 // Feb 15th, 2019
extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC; extern uint8_t ASSETCHAINS_TXPOW,ASSETCHAINS_PUBLIC;
int32_t MAX_BLOCK_SIZE(int32_t height); int32_t MAX_BLOCK_SIZE(int32_t height);

View File

@@ -1979,6 +1979,7 @@ bool myAddtomempool(CTransaction &tx, CValidationState *pstate)
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock)
{ {
memset(&hashBlock,0,sizeof(hashBlock));
// need a GetTransaction without lock so the validation code for assets can run without deadlock // need a GetTransaction without lock so the validation code for assets can run without deadlock
{ {
//fprintf(stderr,"check mempool\n"); //fprintf(stderr,"check mempool\n");
@@ -2022,6 +2023,7 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{ {
CBlockIndex *pindexSlow = NULL; CBlockIndex *pindexSlow = NULL;
memset(&hashBlock,0,sizeof(hashBlock));
LOCK(cs_main); LOCK(cs_main);
@@ -5202,11 +5204,11 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
CheckBlockIndex(); CheckBlockIndex();
if (!ret && futureblock == 0) if (!ret && futureblock == 0)
{ {
if ( ASSETCHAINS_SYMBOL[0] == 0 ) /*if ( ASSETCHAINS_SYMBOL[0] == 0 )
{ {
//fprintf(stderr,"request headers from failed process block peer\n"); //fprintf(stderr,"request headers from failed process block peer\n");
pfrom->PushMessage("getheaders", chainActive.GetLocator(chainActive.LastTip()), uint256()); pfrom->PushMessage("getheaders", chainActive.GetLocator(chainActive.LastTip()), uint256());
} }*/
komodo_longestchain(); komodo_longestchain();
return error("%s: AcceptBlock FAILED", __func__); return error("%s: AcceptBlock FAILED", __func__);
} }

View File

@@ -463,8 +463,6 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr; uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight); CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight);
//if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
// blocktime = pindexPrev->GetMedianTimePast() + 60;
if (ASSETCHAINS_LWMAPOS != 0) if (ASSETCHAINS_LWMAPOS != 0)
{ {
uint32_t nBitsPOS; uint32_t nBitsPOS;
@@ -479,6 +477,9 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount,
} }
else else
{ {
blocktime = GetAdjustedTime();
//if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
// blocktime = pindexPrev->GetMedianTimePast() + 60;
siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig); siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig);
} }

View File

@@ -606,9 +606,10 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
return BIP22ValidationResult(state); return BIP22ValidationResult(state);
} }
} }
else
if (strMode != "template") {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); strMode = "template";
}
bool fvNodesEmpty; bool fvNodesEmpty;
{ {

View File

@@ -1319,9 +1319,9 @@ UniValue sendmany(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_); throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
} }
if (destinations.count(dest)) { /*if (destinations.count(dest)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_); throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
} }*/
destinations.insert(dest); destinations.insert(dest);
CScript scriptPubKey = GetScriptForDestination(dest); CScript scriptPubKey = GetScriptForDestination(dest);
@@ -5059,8 +5059,10 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numk
{ {
*maxkp += 1000; *maxkp += 1000;
array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp)); array = (struct komodo_staking *)realloc(array,sizeof(*array) * (*maxkp));
//fprintf(stderr,"realloc max.%d array.%p\n",*maxkp,array);
} }
kp = &array[(*numkp)++]; kp = &array[(*numkp)++];
//fprintf(stderr,"kp.%p num.%d\n",kp,*numkp);
memset(kp,0,sizeof(*kp)); memset(kp,0,sizeof(*kp));
strcpy(kp->address,address); strcpy(kp->address,address);
kp->txid = txid; kp->txid = txid;
@@ -5083,15 +5085,11 @@ arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uin
diff = 3600*24*30; diff = 3600*24*30;
if ( iter > 0 ) if ( iter > 0 )
diff += segid*2; diff += segid*2;
coinage = ((uint64_t)kp->nValue/COIN * diff); coinage = ((uint64_t)kp->nValue * diff);
if ( blocktime+iter+segid*2 > prevtime+480 ) if ( blocktime+iter+segid*2 > prevtime+480 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+400)); coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
//if ( nHeight >= 2500 && blocktime+iter+segid*2 > prevtime+180 )
// coinage *= ((blocktime+iter+segid*2) - (prevtime+60));
coinage256 = arith_uint256(coinage+1); coinage256 = arith_uint256(coinage+1);
hashval = ratio * (kp->hashval / coinage256); hashval = ratio * (kp->hashval / coinage256);
//if ( nHeight >= 900 && nHeight < 916 )
// hashval = (hashval / coinage256);
return(hashval); return(hashval);
} }
@@ -5121,7 +5119,7 @@ uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komod
return(blocktime); return(blocktime);
} }
} }
} } else fprintf(stderr,"maxiters is not good enough\n");
return(0); return(0);
} }
@@ -5148,10 +5146,10 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000; minage = 6000;
komodo_segids(hashbuf,nHeight-101,100); komodo_segids(hashbuf,nHeight-101,100);
if ( *blocktimep > tipindex->nTime+60 ) if ( *blocktimep < tipindex->nTime+60 )
*blocktimep = tipindex->nTime+60; *blocktimep = tipindex->nTime+60;
//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight); //fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
if ( time(NULL) > lasttime+600 ) if ( time(NULL) > lasttime+600 || array == 0 )
{ {
if ( array != 0 ) if ( array != 0 )
{ {
@@ -5170,7 +5168,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
counter++; counter++;
if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
{ {
//fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
continue; continue;
} }
CAmount nValue = out.tx->vout[out.i].nValue; CAmount nValue = out.tx->vout[out.i].nValue;
@@ -5184,12 +5182,14 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 )
{ {
array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk);
//fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp);
} }
} }
} }
lasttime = (uint32_t)time(NULL); lasttime = (uint32_t)time(NULL);
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
} }
//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep);
block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57; block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
for (i=winners=0; i<numkp; i++) for (i=winners=0; i<numkp; i++)
{ {
@@ -5202,7 +5202,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 ) if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 )
continue; continue;
eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address); eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible); //fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
if ( eligible > 0 ) if ( eligible > 0 )
{ {
besttime = m = 0; besttime = m = 0;
@@ -5215,7 +5215,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier if ( eligible < block_from_future_rejecttime ) // nothing gained by going earlier
break; break;
m++; m++;
//fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible); //fprintf(stderr,"m.%d ht.%d validated winning blocktime %u -> %.8f eligible.%u test prior\n",m,nHeight,*blocktimep,(double)kp->nValue/COIN,eligible);
} }
} }
else else
@@ -5225,7 +5225,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
} }
eligible = besttime; eligible = besttime;
winners++; winners++;
//fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible); //fprintf(stderr,"ht.%d validated winning [%d] -> %.8f eligible.%u test prior\n",nHeight,(int32_t)(eligible - tipindex->nTime),(double)kp->nValue/COIN,eligible);
if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) ) if ( earliest == 0 || eligible < earliest || (eligible == earliest && (*utxovaluep == 0 || kp->nValue < *utxovaluep)) )
{ {
earliest = eligible; earliest = eligible;
@@ -5238,7 +5238,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners); fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
} }
} //else fprintf(stderr,"utxo not eligible\n"); } //else fprintf(stderr,"utxo not eligible\n");
} //else fprintf(stderr,"no tipindex\n"); }
if ( numkp < 10000 && array != 0 ) if ( numkp < 10000 && array != 0 )
{ {
free(array); free(array);
@@ -5273,7 +5273,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
for (i=0; i<siglen; i++) for (i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]); utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
//fprintf(stderr," siglen.%d\n",siglen); //fprintf(stderr," siglen.%d\n",siglen);
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep)); //fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest; *blocktimep = earliest;
} }
} //else fprintf(stderr,"no earliest utxo for staking\n"); } //else fprintf(stderr,"no earliest utxo for staking\n");
@@ -5310,6 +5310,7 @@ int32_t ensure_CCrequirements()
#include "../cc/CCOracles.h" #include "../cc/CCOracles.h"
#include "../cc/CCGateways.h" #include "../cc/CCGateways.h"
#include "../cc/CCPrices.h" #include "../cc/CCPrices.h"
#include "../cc/CCHeir.h"
UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned char> &pubkey) UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned char> &pubkey)
{ {
@@ -5531,15 +5532,25 @@ UniValue gatewaysaddress(const UniValue& params, bool fHelp)
UniValue heiraddress(const UniValue& params, bool fHelp) UniValue heiraddress(const UniValue& params, bool fHelp)
{ {
struct CCcontract_info *cp,C; std::vector<unsigned char> pubkey; struct CCcontract_info *cp,C; std::vector<unsigned char> destPubkey;
cp = CCinit(&C,EVAL_HEIR); cp = CCinit(&C,EVAL_HEIR);
if ( fHelp || params.size() > 1 ) if ( fHelp || (params.size() != 4 && params.size() != 3))
throw runtime_error("heiraddress [pubkey]\n"); throw runtime_error("heiraddress func txid amount [destpubkey]\n");
if ( ensure_CCrequirements() < 0 ) if ( ensure_CCrequirements() < 0 )
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
if ( params.size() == 1 ) //if ( params.size() == 1 )
pubkey = ParseHex(params[0].get_str().c_str()); // pubkey = ParseHex(params[0].get_str().c_str());
return(CCaddress(cp,(char *)"Heir",pubkey));
char funcid = ((char *)params[0].get_str().c_str())[0];
uint256 assetid = Parseuint256((char *)params[1].get_str().c_str());
int64_t funds = atof(params[2].get_str().c_str()) * COIN ;
if(params.size() == 4)
destPubkey = ParseHex(params[3].get_str().c_str());
//return HeirFundBad(funcid, assetid, funds, destPubkey);
return(CCaddress(cp,(char *)"Heir",destPubkey));
} }
UniValue lottoaddress(const UniValue& params, bool fHelp) UniValue lottoaddress(const UniValue& params, bool fHelp)
@@ -6837,7 +6848,7 @@ UniValue tokencreate(const UniValue& params, bool fHelp)
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
name = params[0].get_str(); name = params[0].get_str();
supply = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; supply = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; // what for is this '+0.00000000499999'? it will be lost while converting double to int64_t (dimxy)
if ( name.size() == 0 || name.size() > 32) if ( name.size() == 0 || name.size() > 32)
{ {
ERR_RESULT("Token name must not be empty and up to 32 characters"); ERR_RESULT("Token name must not be empty and up to 32 characters");
@@ -6877,7 +6888,8 @@ UniValue tokentransfer(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
tokenid = Parseuint256((char *)params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[0].get_str().c_str());
std::vector<unsigned char> pubkey(ParseHex(params[1].get_str().c_str())); std::vector<unsigned char> pubkey(ParseHex(params[1].get_str().c_str()));
amount = atol(params[2].get_str().c_str()); //amount = atol(params[2].get_str().c_str());
amount = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( tokenid == zeroid ) if ( tokenid == zeroid )
{ {
ERR_RESULT("invalid tokenid"); ERR_RESULT("invalid tokenid");
@@ -6913,7 +6925,8 @@ UniValue tokenconvert(const UniValue& params, bool fHelp)
evalcode = atoi(params[0].get_str().c_str()); evalcode = atoi(params[0].get_str().c_str());
tokenid = Parseuint256((char *)params[1].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str());
std::vector<unsigned char> pubkey(ParseHex(params[2].get_str().c_str())); std::vector<unsigned char> pubkey(ParseHex(params[2].get_str().c_str()));
amount = atol(params[3].get_str().c_str()); //amount = atol(params[3].get_str().c_str());
amount = atoll(params[3].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( tokenid == zeroid ) if ( tokenid == zeroid )
{ {
ERR_RESULT("invalid tokenid"); ERR_RESULT("invalid tokenid");
@@ -6946,7 +6959,8 @@ UniValue tokenbid(const UniValue& params, bool fHelp)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
numtokens = atoi(params[0].get_str().c_str()); //numtokens = atoi(params[0].get_str().c_str());
numtokens = atoll(params[0].get_str().c_str()); // dimxy changed to prevent loss of significance
tokenid = Parseuint256((char *)params[1].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str());
price = atof(params[2].get_str().c_str()); price = atof(params[2].get_str().c_str());
bidamount = (price * numtokens) * COIN + 0.0000000049999; bidamount = (price * numtokens) * COIN + 0.0000000049999;
@@ -7014,7 +7028,8 @@ UniValue tokenfillbid(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
tokenid = Parseuint256((char *)params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[0].get_str().c_str());
bidtxid = Parseuint256((char *)params[1].get_str().c_str()); bidtxid = Parseuint256((char *)params[1].get_str().c_str());
fillamount = atol(params[2].get_str().c_str()); // fillamount = atol(params[2].get_str().c_str());
fillamount = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( fillamount <= 0 ) if ( fillamount <= 0 )
{ {
ERR_RESULT("fillamount must be positive"); ERR_RESULT("fillamount must be positive");
@@ -7043,10 +7058,12 @@ UniValue tokenask(const UniValue& params, bool fHelp)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
numtokens = atoi(params[0].get_str().c_str()); //numtokens = atoi(params[0].get_str().c_str());
numtokens = atoll(params[0].get_str().c_str()); // dimxy changed to prevent loss of significance
tokenid = Parseuint256((char *)params[1].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str());
price = atof(params[2].get_str().c_str()); price = atof(params[2].get_str().c_str());
askamount = (price * numtokens) * COIN + 0.0000000049999; askamount = (price * numtokens) * COIN + 0.0000000049999;
//std::cerr << std::boolalpha << "tokenask(): (tokenid == zeroid) is " << (tokenid == zeroid) << " (numtokens <= 0) is " << (numtokens <= 0) << " (price <= 0) is " << (price <= 0) << " (askamount <= 0) is " << (askamount <= 0) << std::endl;
if ( tokenid == zeroid || numtokens <= 0 || price <= 0 || askamount <= 0 ) if ( tokenid == zeroid || numtokens <= 0 || price <= 0 || askamount <= 0 )
{ {
ERR_RESULT("invalid parameter"); ERR_RESULT("invalid parameter");
@@ -7075,7 +7092,8 @@ UniValue tokenswapask(const UniValue& params, bool fHelp)
throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n");
const CKeyStore& keystore = *pwalletMain; const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
numtokens = atoi(params[0].get_str().c_str()); //numtokens = atoi(params[0].get_str().c_str());
numtokens = atoll(params[0].get_str().c_str()); // dimxy changed to prevent loss of significance
tokenid = Parseuint256((char *)params[1].get_str().c_str()); tokenid = Parseuint256((char *)params[1].get_str().c_str());
otherid = Parseuint256((char *)params[2].get_str().c_str()); otherid = Parseuint256((char *)params[2].get_str().c_str());
price = atof(params[3].get_str().c_str()); price = atof(params[3].get_str().c_str());
@@ -7129,7 +7147,8 @@ UniValue tokenfillask(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet); LOCK2(cs_main, pwalletMain->cs_wallet);
tokenid = Parseuint256((char *)params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[0].get_str().c_str());
asktxid = Parseuint256((char *)params[1].get_str().c_str()); asktxid = Parseuint256((char *)params[1].get_str().c_str());
fillunits = atol(params[2].get_str().c_str()); //fillunits = atol(params[2].get_str().c_str());
fillunits = atoll(params[2].get_str().c_str()); // dimxy changed to prevent loss of significance
if ( fillunits <= 0 ) if ( fillunits <= 0 )
{ {
ERR_RESULT("fillunits must be positive"); ERR_RESULT("fillunits must be positive");
@@ -7169,7 +7188,8 @@ UniValue tokenfillswap(const UniValue& params, bool fHelp)
tokenid = Parseuint256((char *)params[0].get_str().c_str()); tokenid = Parseuint256((char *)params[0].get_str().c_str());
otherid = Parseuint256((char *)params[1].get_str().c_str()); otherid = Parseuint256((char *)params[1].get_str().c_str());
asktxid = Parseuint256((char *)params[2].get_str().c_str()); asktxid = Parseuint256((char *)params[2].get_str().c_str());
fillunits = atol(params[3].get_str().c_str()); //fillunits = atol(params[3].get_str().c_str());
fillunits = atoll(params[3].get_str().c_str()); // dimxy changed to prevent loss of significance
hex = FillSell(0,tokenid,otherid,asktxid,fillunits); hex = FillSell(0,tokenid,otherid,asktxid,fillunits);
if (fillunits > 0) { if (fillunits > 0) {
if ( hex.size() > 0 ) { if ( hex.size() > 0 ) {