Browse Source

Add src/cc upstream changes

pull/51/head
Duke Leto 5 years ago
parent
commit
8811b8633f
  1. 20
      src/cc/CCGateways.h
  2. 10
      src/cc/CCOracles.h
  3. 16
      src/cc/CCPegs.h
  4. 1
      src/cc/CCPrices.h
  5. 16
      src/cc/CCassetstx.cpp
  6. 12
      src/cc/CCchannels.h
  7. 4
      src/cc/CCfaucet.h
  8. 914
      src/cc/CCinclude.h
  9. 1
      src/cc/CCrewards.h
  10. 3
      src/cc/CCtokens.cpp
  11. 143
      src/cc/CCtx.cpp
  12. 26
      src/cc/CCutilbits.cpp
  13. 13
      src/cc/CCutils.cpp
  14. 116
      src/cc/COptCCParams.cpp
  15. 2
      src/cc/cclib.cpp
  16. 239
      src/cc/channels.cpp
  17. 2
      src/cc/customcc.cpp
  18. 108
      src/cc/dapps/oraclefeed.c
  19. 2
      src/cc/eval.h
  20. 34
      src/cc/faucet.cpp
  21. 487
      src/cc/gateways.cpp
  22. 274
      src/cc/heir.cpp
  23. 215
      src/cc/oracles.cpp
  24. 7
      src/cc/payments.cpp
  25. 500
      src/cc/pegs.cpp
  26. 54
      src/cc/rewards.cpp

20
src/cc/CCGateways.h

@ -20,16 +20,16 @@
#include "CCinclude.h"
bool GatewaysValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
std::string GatewaysPartialSign(uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex);
std::string GatewaysCompleteSigning(uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex);
std::string GatewaysMarkDone(uint64_t txfee,uint256 withdrawtxid,std::string refcoin);
UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin);
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin);
UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin);
UniValue GatewaysBind(const CPubKey& pk, uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4);
UniValue GatewaysDeposit(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount);
UniValue GatewaysClaim(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount);
UniValue GatewaysWithdraw(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount);
UniValue GatewaysPartialSign(const CPubKey& pk, uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex);
UniValue GatewaysCompleteSigning(const CPubKey& pk, uint64_t txfee,uint256 txidaddr,std::string refcoin,std::string hex);
UniValue GatewaysMarkDone(const CPubKey& pk, uint64_t txfee,uint256 withdrawtxid,std::string refcoin);
UniValue GatewaysPendingDeposits(const CPubKey& pk, uint256 bindtxid,std::string refcoin);
UniValue GatewaysPendingWithdraws(const CPubKey& pk, uint256 bindtxid,std::string refcoin);
UniValue GatewaysProcessedWithdraws(const CPubKey& pk, uint256 bindtxid,std::string refcoin);
// CCcustom
UniValue GatewaysInfo(uint256 bindtxid);

10
src/cc/CCOracles.h

@ -20,11 +20,11 @@
#include "CCinclude.h"
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format);
std::string OracleFund(int64_t txfee,uint256 oracletxid);
std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee);
std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount);
std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector <uint8_t> data);
UniValue OracleCreate(const CPubKey& pk, int64_t txfee,std::string name,std::string description,std::string format);
UniValue OracleFund(const CPubKey& pk, int64_t txfee,uint256 oracletxid);
UniValue OracleRegister(const CPubKey& pk, int64_t txfee,uint256 oracletxid,int64_t datafee);
UniValue OracleSubscribe(const CPubKey& pk, int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount);
UniValue OracleData(const CPubKey& pk, int64_t txfee,uint256 oracletxid,std::vector <uint8_t> data);
// CCcustom
UniValue OracleDataSample(uint256 reforacletxid,uint256 txid);
UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num);

16
src/cc/CCPegs.h

@ -22,14 +22,14 @@
bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
// CCcustom
std::string PegsCreate(uint64_t txfee,int64_t amount,std::vector<uint256> bindtxids);
std::string PegsFund(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
std::string PegsGet(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid);
std::string PegsLiquidate(uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid);
std::string PegsExchange(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
UniValue PegsAccountHistory(uint256 pegstxid);
UniValue PegsAccountInfo(uint256 pegstxid);
UniValue PegsCreate(const CPubKey& pk,uint64_t txfee,int64_t amount,std::vector<uint256> bindtxids);
UniValue PegsFund(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
UniValue PegsGet(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
UniValue PegsRedeem(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid);
UniValue PegsLiquidate(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid);
UniValue PegsExchange(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount);
UniValue PegsAccountHistory(const CPubKey& pk,uint256 pegstxid);
UniValue PegsAccountInfo(const CPubKey& pk,uint256 pegstxid);
UniValue PegsWorstAccounts(uint256 pegstxid);
UniValue PegsInfo(uint256 pegstxid);

1
src/cc/CCPrices.h

@ -19,6 +19,7 @@
#include "komodo_defs.h"
#include "CCinclude.h"
int32_t komodo_priceget(int64_t *buf64,int32_t ind,int32_t height,int32_t numblocks);
extern void GetKomodoEarlytxidScriptPub();
extern CScript KOMODO_EARLYTXID_SCRIPTPUB;

16
src/cc/CCassetstx.cpp

@ -19,7 +19,6 @@
UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode)
{
static uint256 zero;
UniValue result(UniValue::VARR);
struct CCcontract_info *cpAssets, assetsC;
@ -35,7 +34,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode)
std::vector<uint8_t> origpubkey;
CTransaction ordertx;
uint8_t funcid, evalCode;
char numstr[32], funcidstr[16], origaddr[64], origtokenaddr[64], assetidstr[65];
char numstr[32], funcidstr[16], origaddr[64], origtokenaddr[64];
txid = it->first.txhash;
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() checking txid=" << txid.GetHex() << std::endl);
@ -46,8 +45,8 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode)
{
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() checking ordertx.vout.size()=" << ordertx.vout.size() << " funcid=" << (char)(funcid ? funcid : ' ') << " assetid=" << assetid.GetHex() << std::endl);
if (refassetid != zero && assetid == refassetid ||
pk != CPubKey() && pk == pubkey2pk(origpubkey) && (funcid == 'S' || funcid == 's'))
if (pk == CPubKey() && (refassetid == zeroid || assetid == refassetid) // tokenorders
|| pk != CPubKey() && pk == pubkey2pk(origpubkey) && (funcid == 'S' || funcid == 's')) // mytokenorders, returns only asks (is this correct?)
{
LOGSTREAM("ccassets", CCLOG_DEBUG2, stream << "addOrders() it->first.index=" << it->first.index << " ordertx.vout[it->first.index].nValue=" << ordertx.vout[it->first.index].nValue << std::endl);
@ -61,7 +60,7 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode)
funcidstr[0] = funcid;
funcidstr[1] = 0;
item.push_back(Pair("funcid", funcidstr));
item.push_back(Pair("txid", uint256_str(assetidstr, txid)));
item.push_back(Pair("txid", txid.GetHex()));
item.push_back(Pair("vout", (int64_t)it->first.index));
if (funcid == 'b' || funcid == 'B')
{
@ -77,18 +76,17 @@ UniValue AssetOrders(uint256 refassetid, CPubKey pk, uint8_t additionalEvalCode)
sprintf(numstr, "%llu", (long long)ordertx.vout[0].nValue);
item.push_back(Pair("askamount", numstr));
}
if (origpubkey.size() == 33)
if (origpubkey.size() == CPubKey::COMPRESSED_PUBLIC_KEY_SIZE)
{
GetCCaddress(cp, origaddr, pubkey2pk(origpubkey));
item.push_back(Pair("origaddress", origaddr));
GetTokensCCaddress(cpTokens, origtokenaddr, pubkey2pk(origpubkey));
item.push_back(Pair("origtokenaddress", origtokenaddr));
}
if (assetid != zeroid)
item.push_back(Pair("tokenid", uint256_str(assetidstr, assetid)));
item.push_back(Pair("tokenid", assetid.GetHex()));
if (assetid2 != zeroid)
item.push_back(Pair("otherid", uint256_str(assetidstr, assetid2)));
item.push_back(Pair("otherid", assetid2.GetHex()));
if (price > 0)
{
if (funcid == 's' || funcid == 'S' || funcid == 'e' || funcid == 'e')

12
src/cc/CCchannels.h

@ -21,12 +21,12 @@
#define CHANNELS_MAXPAYMENTS 1000
bool ChannelsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 tokenid);
std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret);
std::string ChannelClose(uint64_t txfee,uint256 opentxid);
std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid);
UniValue ChannelsList();
UniValue ChannelOpen(const CPubKey& pk,uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 tokenid);
UniValue ChannelPayment(const CPubKey& pk,uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret);
UniValue ChannelClose(const CPubKey& pk,uint64_t txfee,uint256 opentxid);
UniValue ChannelRefund(const CPubKey& pk,uint64_t txfee,uint256 opentxid,uint256 closetxid);
UniValue ChannelsList(const CPubKey& pk);
// CCcustom
UniValue ChannelsInfo(uint256 opentxid);
UniValue ChannelsInfo(const CPubKey& pk,uint256 opentxid);
#endif

4
src/cc/CCfaucet.h

@ -25,8 +25,8 @@
bool FaucetValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
// CCcustom
std::string FaucetFund(uint64_t txfee,int64_t funds);
std::string FaucetGet(uint64_t txfee);
UniValue FaucetFund(const CPubKey& mypk,uint64_t txfee,int64_t funds);
UniValue FaucetGet(const CPubKey& mypk,uint64_t txfee);
UniValue FaucetInfo();
#endif

914
src/cc/CCinclude.h

File diff suppressed because it is too large

1
src/cc/CCrewards.h

@ -18,6 +18,7 @@
#define CC_REWARDS_H
#include "CCinclude.h"
#include <gmp.h>
#define EVAL_REWARDS 0xe5
#define REWARDSCC_MAXAPR (COIN * 25)

3
src/cc/CCtokens.cpp

@ -824,9 +824,8 @@ std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, st
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, mypk, tokensupply + 2 * txfee, 64) > 0)
if (AddNormalinputs2(mtx, tokensupply + 2 * txfee, 64) > 0) // add normal inputs only from mypk
{
int64_t mypkInputs = TotalPubkeyNormalInputs(mtx, mypk);
if (mypkInputs < tokensupply) { // check that tokens amount are really issued with mypk (because in the wallet there maybe other privkeys)
CCerror = "some inputs signed not with -pubkey=pk";

143
src/cc/CCtx.cpp

@ -19,14 +19,7 @@
std::vector<CPubKey> NULL_pubkeys;
struct NSPV_CCmtxinfo NSPV_U;
/*
FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and the opreturn.
This allows the contract transaction functions to create the appropriate vins and vouts and have FinalizeCCTx create a properly signed transaction.
By using -addressindex=1, it allows tracking of all the CC addresses
*/
/* see description to function definition in CCinclude.h */
bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScript scriptPubKey)
{
#ifdef ENABLE_WALLET
@ -41,17 +34,35 @@ bool SignTx(CMutableTransaction &mtx,int32_t vini,int64_t utxovalue,const CScrip
return(false);
}
std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey mypk,uint64_t txfee,CScript opret,std::vector<CPubKey> pubkeys)
/*
FinalizeCCTx is a very useful function that will properly sign both CC and normal inputs, adds normal change and the opreturn.
This allows the contract transaction functions to create the appropriate vins and vouts and have FinalizeCCTx create a properly signed transaction.
By using -addressindex=1, it allows tracking of all the CC addresses
*/
std::string FinalizeCCTx(uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector<CPubKey> pubkeys)
{
UniValue sigData = FinalizeCCTxExt(false, CCmask, cp, mtx, mypk, txfee, opret, pubkeys);
return sigData[JSON_HEXTX].getValStr();
}
// extended version that supports signInfo object with conds to vins map for remote cc calls
UniValue FinalizeCCTxExt(bool remote, uint64_t CCmask, struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey mypk, uint64_t txfee, CScript opret, std::vector<CPubKey> pubkeys)
{
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
CTransaction vintx; std::string hex; CPubKey globalpk; uint256 hashBlock; uint64_t mask=0,nmask=0,vinimask=0;
int64_t utxovalues[CC_MAXVINS],change,normalinputs=0,totaloutputs=0,normaloutputs=0,totalinputs=0,normalvins=0,ccvins=0;
int32_t i,flag,mgret,utxovout,n,err = 0;
char myaddr[64], destaddr[64], unspendable[64], mytokensaddr[64], mysingletokensaddr[64], unspendabletokensaddr[64],CC1of2CCaddr[64];
uint8_t *privkey, myprivkey[32], unspendablepriv[32], /*tokensunspendablepriv[32],*/ *msg32 = 0;
uint8_t *privkey = NULL, myprivkey[32] = { '\0' }, unspendablepriv[32] = { '\0' }, /*tokensunspendablepriv[32],*/ *msg32 = 0;
CC *mycond=0, *othercond=0, *othercond2=0,*othercond4=0, *othercond3=0, *othercond1of2=NULL, *othercond1of2tokens = NULL, *cond=0, *condCC2=0,*mytokenscond = NULL, *mysingletokenscond = NULL, *othertokenscond = NULL;
CPubKey unspendablepk /*, tokensunspendablepk*/;
struct CCcontract_info *cpTokens, tokensC;
UniValue sigData(UniValue::VARR),result(UniValue::VOBJ);
const UniValue sigDataNull = NullUniValue;
globalpk = GetUnspendable(cp,0);
n = mtx.vout.size();
for (i=0; i<n; i++)
@ -63,9 +74,18 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
if ( (n= mtx.vin.size()) > CC_MAXVINS )
{
fprintf(stderr,"FinalizeCCTx: %d is too many vins\n",n);
return("0");
result.push_back(Pair(JSON_HEXTX, "0"));
return result;
}
Myprivkey(myprivkey);
//Myprivkey(myprivkey); // for NSPV mode we need to add myprivkey for the explicitly defined mypk param
#ifdef ENABLE_WALLET
// get privkey for mypk
CKeyID keyID = mypk.GetID();
CKey vchSecret;
if (pwalletMain->GetKey(keyID, vchSecret))
memcpy(myprivkey, vchSecret.begin(), sizeof(myprivkey));
#endif
GetCCaddress(cp,myaddr,mypk);
mycond = MakeCCcond1(cp->evalcode,mypk);
@ -109,7 +129,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
{
fprintf(stderr,"vin.%d vout.%d is bigger than vintx.%d\n",i,mtx.vin[i].prevout.n,(int32_t)vintx.vout.size());
memset(myprivkey,0,32);
return("");
return UniValue(UniValue::VOBJ);
}
}
if (normalvins>1 && ccvins)
@ -164,8 +184,18 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
{
if ( KOMODO_NSPV_FULLNODE )
{
if ( SignTx(mtx,i,vintx.vout[utxovout].nValue,vintx.vout[utxovout].scriptPubKey) == 0 )
fprintf(stderr,"signing error for vini.%d of %llx\n",i,(long long)vinimask);
if (!remote)
{
if (SignTx(mtx, i, vintx.vout[utxovout].nValue, vintx.vout[utxovout].scriptPubKey) == 0)
fprintf(stderr, "signing error for vini.%d of %llx\n", i, (long long)vinimask);
}
else
{
// if no myprivkey for mypk it means remote call from nspv superlite client
// add sigData for superlite client
UniValue cc(UniValue::VNULL);
AddSigData2UniValue(sigData, i, cc, HexStr(vintx.vout[utxovout].scriptPubKey), vintx.vout[utxovout].nValue ); // store vin i with scriptPubKey
}
}
else
{
@ -282,7 +312,7 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
{
fprintf(stderr,"CC signing error: vini.%d has unknown CC address.(%s)\n",i,destaddr);
memset(myprivkey,0,32);
return("");
return sigDataNull;
}
}
uint256 sighash = SignatureHash(CCPubKey(cond), mtx, i, SIGHASH_ALL,utxovalues[i],consensusBranchId, &txdata);
@ -296,15 +326,33 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
fprintf(stderr,"%02x",((uint8_t *)sighash.begin())[z]);
fprintf(stderr," sighash [%d] %.8f %x\n",i,(double)utxovalues[i]/COIN,consensusBranchId);
}
if ( cc_signTreeSecp256k1Msg32(cond,privkey,sighash.begin()) != 0 )
if (!remote) // we have privkey in the wallet
{
mtx.vin[i].scriptSig = CCSig(cond);
if (cc_signTreeSecp256k1Msg32(cond, privkey, sighash.begin()) != 0)
{
mtx.vin[i].scriptSig = CCSig(cond);
}
else
{
fprintf(stderr, "vini.%d has CC signing error address.(%s) %s\n", i, destaddr, EncodeHexTx(mtx).c_str());
memset(myprivkey, 0, sizeof(myprivkey));
return sigDataNull;
}
}
else
else // no privkey locally - remote call
{
fprintf(stderr,"vini.%d has CC signing error address.(%s) %s\n",i,destaddr,EncodeHexTx(mtx).c_str());
memset(myprivkey,0,sizeof(myprivkey));
return("");
// serialize cc:
UniValue ccjson;
ccjson.read(cc_conditionToJSONString(cond));
if (ccjson.empty())
{
fprintf(stderr, "vini.%d can't serialize CC.(%s) %s\n", i, destaddr, EncodeHexTx(mtx).c_str());
memset(myprivkey, 0, sizeof(myprivkey));
return sigDataNull;
}
AddSigData2UniValue(sigData, i, ccjson, std::string(), vintx.vout[utxovout].nValue); // store vin i with scriptPubKey
}
}
} else fprintf(stderr,"FinalizeCCTx2 couldnt find %s mgret.%d\n",mtx.vin[i].prevout.hash.ToString().c_str(),mgret);
@ -334,8 +382,12 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
memset(myprivkey,0,sizeof(myprivkey));
std::string strHex = EncodeHexTx(mtx);
if ( strHex.size() > 0 )
return(strHex);
else return("0");
result.push_back(Pair(JSON_HEXTX, strHex));
else {
result.push_back(Pair(JSON_HEXTX, "0"));
}
if (sigData.size() > 0) result.push_back(Pair(JSON_SIGDATA,sigData));
return result;
}
void NSPV_CCunspents(std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > &unspentOutputs,char *coinaddr,bool ccflag);
@ -412,7 +464,10 @@ void SetCCtxids(std::vector<uint256> &txids,char *coinaddr,bool ccflag, uint8_t
{
if ( GetAddressIndex((*it).first, (*it).second, addressIndex) == 0 )
return;
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it1=addressIndex.begin(); it1!=addressIndex.end(); it1++) txids.push_back(it1->first.txhash);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it1=addressIndex.begin(); it1!=addressIndex.end(); it1++)
{
if (it1->second>=0) txids.push_back(it1->first.txhash);
}
}
}
@ -579,11 +634,15 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *
else return(belowi);
}
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs)
int64_t AddNormalinputsLocal(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs)
{
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector<COutput> vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up;
if ( KOMODO_NSPV_SUPERLITE )
return(NSPV_AddNormalinputs(mtx,mypk,total,maxinputs,&NSPV_U));
// if (mypk != pubkey2pk(Mypubkey())) //remote superlite mypk, do not use wallet since it is not locked for non-equal pks (see rpcs with nspv support)!
// return(AddNormalinputs3(mtx, mypk, total, maxinputs));
#ifdef ENABLE_WALLET
assert(pwalletMain != NULL);
const CKeyStore& keystore = *pwalletMain;
@ -675,12 +734,20 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
return(0);
}
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs)
// always uses -pubkey param as mypk
int64_t AddNormalinputs2(CMutableTransaction &mtx, int64_t total, int32_t maxinputs)
{
CPubKey mypk = pubkey2pk(Mypubkey());
return AddNormalinputsRemote(mtx, mypk, total, maxinputs);
}
// has additional mypk param for nspv calls
int64_t AddNormalinputsRemote(CMutableTransaction &mtx, CPubKey mypk, int64_t total, int32_t maxinputs)
{
int32_t abovei,belowi,ind,vout,i,n = 0; 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;
if ( KOMODO_NSPV_SUPERLITE )
return(NSPV_AddNormalinputs(mtx,pubkey2pk(Mypubkey()),total,maxinputs,&NSPV_U));
return(NSPV_AddNormalinputs(mtx,mypk,total,maxinputs,&NSPV_U));
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos));
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
@ -688,7 +755,7 @@ int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinput
threshold = total/maxinputs;
else threshold = total;
sum = 0;
Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG);
Getscriptaddress(coinaddr,CScript() << vscript_t(mypk.begin(), mypk.end()) << OP_CHECKSIG);
SetCCunspents(unspentOutputs,coinaddr,false);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
@ -766,3 +833,21 @@ int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinput
}
return(0);
}
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs,bool remote)
{
if (!remote) return (AddNormalinputsLocal(mtx,mypk,total,maxinputs));
else return (AddNormalinputsRemote(mtx,mypk,total,maxinputs));
}
void AddSigData2UniValue(UniValue &sigdata, int32_t vini, UniValue& ccjson, std::string sscriptpubkey, int64_t amount)
{
UniValue elem(UniValue::VOBJ);
elem.push_back(Pair("vin", vini));
if (!ccjson.empty())
elem.push_back(Pair("cc", ccjson));
if (!sscriptpubkey.empty())
elem.push_back(Pair("scriptPubKey", sscriptpubkey));
elem.push_back(Pair("amount", amount));
sigdata.push_back(elem);
}

26
src/cc/CCutilbits.cpp

@ -1,5 +1,5 @@
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* Copyright 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
@ -93,13 +93,23 @@ CPubKey buf2pk(uint8_t *buf33)
return(pk);
}
CPubKey pubkey2pk(std::vector<uint8_t> pubkey)
CPubKey pubkey2pk(std::vector<uint8_t> vpubkey)
{
CPubKey pk; int32_t i,n; uint8_t *dest,*pubkey33;
n = pubkey.size();
dest = (uint8_t *)pk.begin();
pubkey33 = (uint8_t *)pubkey.data();
for (i=0; i<n; i++)
dest[i] = pubkey33[i];
CPubKey pk;
pk.Set(vpubkey.begin(), vpubkey.end());
return(pk);
}
void CCLogPrintStr(const char *category, int level, const std::string &str)
{
if (level < 0)
level = 0;
if (level > CCLOG_MAXLEVEL)
level = CCLOG_MAXLEVEL;
for (int i = level; i <= CCLOG_MAXLEVEL; i++)
if (LogAcceptCategory((std::string(category) + std::string("-") + std::to_string(i)).c_str()) || // '-debug=cctokens-0', '-debug=cctokens-1',...
i == 0 && LogAcceptCategory(std::string(category).c_str())) { // also supporting '-debug=cctokens' for CCLOG_INFO
LogPrintStr(str);
break;
}
}

13
src/cc/CCutils.cpp

@ -16,6 +16,7 @@
/*
CCutils has low level functions that are universally useful for all contracts.
*/
#include "CCinclude.h"
#include "komodo_structs.h"
#include "key_io.h"
@ -169,7 +170,12 @@ bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_
return true;
}
// set additional 'unspendable' addr
uint32_t GetLatestTimestamp(int32_t height)
{
if ( KOMODO_NSPV_SUPERLITE ) return ((uint32_t)NSPV_blocktime(height));
return(komodo_heightstamp(height));
} // :P
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
{
cp->unspendableEvalcode2 = evalcode;
@ -178,7 +184,6 @@ void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *
strcpy(cp->unspendableaddr2,coinaddr);
}
// set yet another additional 'unspendable' addr
void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)
{
cp->unspendableEvalcode3 = evalcode;
@ -187,7 +192,6 @@ void CCaddr3set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *
strcpy(cp->unspendableaddr3,coinaddr);
}
// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 cryptocondition vout:
void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, uint8_t *priv, char *coinaddr)
{
cp->coins1of2pk[0] = pk1;
@ -196,8 +200,6 @@ void CCaddr1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, uint8_t
strcpy(cp->coins1of2addr,coinaddr);
}
// set pubkeys, myprivkey and 1of2 cc addr for spending from 1of2 token cryptocondition vout
// to get tokenaddr use GetTokensCCaddress()
void CCaddrTokens1of2set(struct CCcontract_info *cp, CPubKey pk1, CPubKey pk2, uint8_t *priv, char *tokenaddr)
{
cp->tokens1of2pk[0] = pk1;
@ -358,7 +360,6 @@ bool GetCCaddress1of2(struct CCcontract_info *cp,char *destaddr,CPubKey pk,CPubK
return(destaddr[0] != 0);
}
// get scriptPubKey adddress for three/dual eval token 1of2 cc vout
bool GetTokensCCaddress1of2(struct CCcontract_info *cp, char *destaddr, CPubKey pk, CPubKey pk2)
{
CC *payoutCond;

116
src/cc/COptCCParams.cpp

@ -0,0 +1,116 @@
/*Descriptson and examples of COptCCParams class found in:
script/standard.h/cpp
class COptCCParams
structure of data in vData payload attached to end of CCvout:
param
OP_1
param
OP_2 ... etc until OP_16
OP_PUSHDATA4 is the last OP code to tell things its at the end.
taken from standard.cpp line 22: COptCCParams::COptCCParams(std::vector<unsigned char> &vch)
EXAMPLE taken from Verus how to create scriptPubKey from COptCCParams class:
EXAMPLE taken from Verus how to decode scriptPubKey from COptCCParams class:
*/
bool MakeGuardedOutput(CAmount value, CPubKey &dest, CTransaction &stakeTx, CTxOut &vout)
{
CCcontract_info *cp, C;
cp = CCinit(&C,EVAL_STAKEGUARD);
CPubKey ccAddress = CPubKey(ParseHex(cp->CChexstr));
// return an output that is bound to the stake transaction and can be spent by presenting either a signed condition by the original
// destination address or a properly signed stake transaction of the same utxo on a fork
vout = MakeCC1of2vout(EVAL_STAKEGUARD, value, dest, ccAddress);
std::vector<CPubKey> vPubKeys = std::vector<CPubKey>();
vPubKeys.push_back(dest);
vPubKeys.push_back(ccAddress);
std::vector<std::vector<unsigned char>> vData = std::vector<std::vector<unsigned char>>();
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hw << stakeTx.vin[0].prevout.hash;
hw << stakeTx.vin[0].prevout.n;
uint256 utxo = hw.GetHash();
vData.push_back(std::vector<unsigned char>(utxo.begin(), utxo.end())); // Can we use any data here to construct vector?
CStakeParams p;
if (GetStakeParams(stakeTx, p))
{
// prev block hash and height is here to make validation easy
vData.push_back(std::vector<unsigned char>(p.prevHash.begin(), p.prevHash.end()));
std::vector<unsigned char> height = std::vector<unsigned char>(4);
for (int i = 0; i < 4; i++)
{
height[i] = (p.blkHeight >> (8 * i)) & 0xff;
}
vData.push_back(height);
COptCCParams ccp = COptCCParams(COptCCParams::VERSION, EVAL_STAKEGUARD, 1, 2, vPubKeys, vData);
vout.scriptPubKey << ccp.AsVector() << OP_DROP;
return true;
}
return false;
}
bool ValidateMatchingStake(const CTransaction &ccTx, uint32_t voutNum, const CTransaction &stakeTx, bool &cheating)
{
// an invalid or non-matching stake transaction cannot cheat
cheating = false;
//printf("ValidateMatchingStake: ccTx.vin[0].prevout.hash: %s, ccTx.vin[0].prevout.n: %d\n", ccTx.vin[0].prevout.hash.GetHex().c_str(), ccTx.vin[0].prevout.n);
if (ccTx.IsCoinBase())
{
CStakeParams p;
if (ValidateStakeTransaction(stakeTx, p))
{
std::vector<std::vector<unsigned char>> vParams = std::vector<std::vector<unsigned char>>();
CScript dummy;
if (ccTx.vout[voutNum].scriptPubKey.IsPayToCryptoCondition(&dummy, vParams) && vParams.size() > 0)
{
COptCCParams ccp = COptCCParams(vParams[0]);
if (ccp.IsValid() & ccp.vData.size() >= 3 && ccp.vData[2].size() <= 4)
{
CVerusHashWriter hw = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
hw << stakeTx.vin[0].prevout.hash;
hw << stakeTx.vin[0].prevout.n;
uint256 utxo = hw.GetHash();
uint32_t height = 0;
int i, dataLen = ccp.vData[2].size();
for (i = dataLen - 1; i >= 0; i--)
{
height = (height << 8) + ccp.vData[2][i];
}
// for debugging strange issue
// printf("iterator: %d, height: %d, datalen: %d\n", i, height, dataLen);
if (utxo == uint256(ccp.vData[0]))
{
if (p.prevHash != uint256(ccp.vData[1]) && p.blkHeight >= height)
{
cheating = true;
return true;
}
// if block height is equal and we are at the else, prevHash must have been equal
else if (p.blkHeight == height)
{
return true;
}
}
}
}
}
}
return false;
}

2
src/cc/cclib.cpp

@ -570,7 +570,7 @@ std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds)
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
cclibpk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
if ( AddNormalinputs2(mtx,funds+txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,funds,cclibpk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));

239
src/cc/channels.cpp

@ -461,30 +461,32 @@ int64_t AddChannelsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx, C
else return 0;
}
std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment, uint256 tokenid)
UniValue ChannelOpen(const CPubKey& pk, uint64_t txfee,CPubKey destpub,int32_t numpayments,int64_t payment, uint256 tokenid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
uint8_t hash[32],hashdest[32]; uint64_t amount,tokens=0,funds; int32_t i; uint256 hashchain,entropy,hentropy;
CPubKey mypk; struct CCcontract_info *cp,*cpTokens,C,CTokens;
if ( numpayments <= 0 || payment <= 0 || numpayments > CHANNELS_MAXPAYMENTS )
{
CCerror = strprintf("invalid ChannelOpen param numpayments.%d max.%d payment.%lld\n",numpayments,CHANNELS_MAXPAYMENTS,(long long)payment);
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid ChannelOpen param numpayments." << numpayments << " payment." << payment << " - max_numpayments." << CHANNELS_MAXPAYMENTS);
if (!destpub.IsFullyValid())
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid destination pubkey");
if (numpayments <1)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid number of payments, must be greater than 0");
if (payment <1)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid payment amount, must be greater than 0");
cp = CCinit(&C,EVAL_CHANNELS);
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
funds = numpayments * payment;
if (tokenid!=zeroid)
{
amount=AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,5);
amount=AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,5,pk.IsValid());
tokens=AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, funds, 64);
}
else amount=AddNormalinputs(mtx,mypk,funds+txfee+2*CC_MARKER_VALUE,64);
else amount=AddNormalinputs(mtx,mypk,funds+txfee+2*CC_MARKER_VALUE,64,pk.IsValid());
if (amount+tokens >= funds+txfee+2*CC_MARKER_VALUE)
{
hentropy = DiceHashEntropy(entropy,mtx.vin[0].prevout.hash,mtx.vin[0].prevout.n,1);
@ -500,14 +502,12 @@ std::string ChannelOpen(uint64_t txfee,CPubKey destpub,int32_t numpayments,int64
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
if (tokenid!=zeroid && tokens>funds) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,tokens-funds,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('O',tokenid,zeroid,mypk,destpub,numpayments,payment,hashchain)));
}
CCerror = strprintf("error adding funds");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding funds");
}
std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret)
UniValue ChannelPayment(const CPubKey& pk, uint64_t txfee,uint256 opentxid,int64_t amount, uint256 secret)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,srcpub,destpub; uint256 txid,hashchain,gensecret,hashblock,entropy,hentropy,prevtxid,param3,tokenid;
@ -519,41 +519,23 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
cp = CCinit(&C,EVAL_CHANNELS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
{
CCerror = strprintf("invalid channel open txid");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if (amount <1)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid payment amount, must be greater than 0");
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open txid");
if ((numvouts=channelOpenTx.vout.size()) > 0 && DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey, tokenid, txid, srcpub, destpub, totalnumpayments, payment, hashchain)=='O')
{
if (mypk != srcpub && mypk != destpub)
{
CCerror = strprintf("this is not our channel");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (mypk != srcpub && mypk != destpub)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "this is not our channel");
else if (amount % payment != 0 || amount<payment)
{
CCerror = strprintf("invalid amount, not a magnitude of payment size");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
}
else
{
CCerror = strprintf("invalid channel open tx");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
if (komodo_txnotarizedconfirmed(opentxid)==false)
{
CCerror = strprintf("channelsopen tx not yet confirmed/notarized");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid amount, not a magnitude of payment size");
else if (mypk == destpub && secret==zeroid) CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid secret, secret is necessary when making payment from destination");
}
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0)
else
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open tx");
if (komodo_txnotarizedconfirmed(opentxid)==false) CCERR_RESULT("channelscc",CCLOG_INFO, stream << "channelsopen tx not yet confirmed/notarized");
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0)
{
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && (change=funds-amount)>=0)
{
@ -563,16 +545,9 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
(funcid == 'P' || funcid=='O'))
{
if (numpayments > prevdepth)
{
CCerror = strprintf("not enough funds in channel for that amount");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
} else if (numpayments == 0)
{
CCerror = strprintf("invalid amount");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "not enough funds in channel for that amount");
else if (numpayments == 0)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid amount");
if (secret!=zeroid)
{
endiancpy(hash, (uint8_t * ) & secret, 32);
@ -582,12 +557,7 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
memcpy(hash, hashdest, 32);
}
endiancpy((uint8_t * ) & gensecret, hashdest, 32);
if (gensecret!=hashchain)
{
CCerror = strprintf("invalid secret supplied");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (gensecret!=hashchain) CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid secret supplied");
}
else
{
@ -605,33 +575,23 @@ std::string ChannelPayment(uint64_t txfee,uint256 opentxid,int64_t amount, uint2
else endiancpy((uint8_t * ) & secret, (uint8_t * ) & hentropy, 32);
}
}
else
{
CCerror = strprintf("invalid previous tx");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid previous tx");
if (tokenid!=zeroid) mtx.vout.push_back(MakeTokensCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
else mtx.vout.push_back(MakeCC1of2vout(EVAL_CHANNELS, change, srcpub, destpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,srcpub));
mtx.vout.push_back(MakeCC1vout(EVAL_CHANNELS,CC_MARKER_VALUE,destpub));
if (tokenid!=zeroid) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, amount, destpub));
else mtx.vout.push_back(CTxOut(amount, CScript() << ParseHex(HexStr(destpub)) << OP_CHECKSIG));
return (FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', tokenid, opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret)));
}
else
{
CCerror = strprintf("error adding CC inputs");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
return (FinalizeCCTxExt(pk.IsValid(), 0, cp, mtx, mypk, txfee, EncodeChannelsOpRet('P', tokenid, opentxid, srcpub, destpub, prevdepth-numpayments, numpayments, secret)));
}
else
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding CC inputs");
}
CCerror = strprintf("error adding normal inputs");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string ChannelClose(uint64_t txfee,uint256 opentxid)
UniValue ChannelClose(const CPubKey& pk, uint64_t txfee,uint256 opentxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,srcpub,destpub; struct CCcontract_info *cp,C;
@ -644,32 +604,16 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
cp = CCinit(&C,EVAL_CHANNELS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
{
CCerror = strprintf("invalid channel open txid");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open txid");
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
{
CCerror = strprintf("invalid channel open tx");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open tx");
if (komodo_txnotarizedconfirmed(opentxid)==false)
{
CCerror = strprintf("channelsopen tx not yet confirmed/notarized");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream <<"channelsopen tx not yet confirmed/notarized");
if (mypk != srcpub)
{
CCerror = strprintf("cannot close, you are not channel owner");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0 )
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "cannot close, you are not channel owner");
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0 )
{
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
{
@ -680,18 +624,12 @@ std::string ChannelClose(uint64_t txfee,uint256 opentxid)
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('C',tokenid,opentxid,mypk,destpub,funds/payment,payment,zeroid)));
}
else
{
CCerror = strprintf("error adding CC inputs");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding CC inputs");
}
CCerror = strprintf("error adding normal inputs");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
UniValue ChannelRefund(const CPubKey& pk, uint64_t txfee,uint256 opentxid,uint256 closetxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp,C; int64_t funds,payment,param2;
@ -704,56 +642,24 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
cp = CCinit(&C,EVAL_CHANNELS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if (myGetTransaction(closetxid,channelCloseTx,hashblock) == 0)
{
CCerror = strprintf("invalid channel close txid");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel close txid");
if ((numvouts=channelCloseTx.vout.size()) < 1 || DecodeChannelsOpRet(channelCloseTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,param1,param2,param3)!='C')
{
CCerror = strprintf("invalid channel close tx");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel close tx");
if (komodo_txnotarizedconfirmed(closetxid)==false)
{
CCerror = strprintf("channelsclose tx not yet confirmed/notarized");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "channelsclose tx not yet confirmed/notarized");
if (txid!=opentxid)
{
CCerror = strprintf("open and close txid are not from same channel");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "open and close txid are not from same channel");
if (myGetTransaction(opentxid,channelOpenTx,hashblock) == 0)
{
CCerror = strprintf("invalid channel open txid");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open txid");
if (komodo_txnotarizedconfirmed(opentxid)==false)
{
CCerror = strprintf("channelsopen tx not yet confirmed/notarized");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "channelsopen tx not yet confirmed/notarized");
if ((numvouts=channelOpenTx.vout.size()) < 1 || DecodeChannelsOpRet(channelOpenTx.vout[numvouts-1].scriptPubKey,tokenid,txid,srcpub,destpub,numpayments,payment,hashchain)!='O')
{
CCerror = strprintf("invalid channel open tx");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return ("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "invalid channel open tx");
if (mypk != srcpub)
{
CCerror = strprintf("cannot refund, you are not the channel owner");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3) > 0 )
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "cannot refund, you are not the channel owner");
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,3,pk.IsValid()) > 0 )
{
if ((funds=AddChannelsInputs(cp,mtx,channelOpenTx,prevtxid,mypk)) !=0 && funds>0)
{
@ -767,32 +673,22 @@ std::string ChannelRefund(uint64_t txfee,uint256 opentxid,uint256 closetxid)
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeChannelsOpRet('R',tokenid,opentxid,mypk,destpub,funds/payment,payment,closetxid)));
}
else
{
CCerror = strprintf("previous tx is invalid");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "previous tx is invalid");
}
else
{
CCerror = strprintf("error adding CC inputs");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding CC inputs");
}
CCerror = strprintf("error adding normal inputs");
LOGSTREAM("channelscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("channelscc",CCLOG_INFO, stream << "error adding normal inputs");
}
UniValue ChannelsList()
UniValue ChannelsList(const CPubKey& pk)
{
UniValue result(UniValue::VOBJ); std::vector<uint256> txids; struct CCcontract_info *cp,C; uint256 txid,hashBlock,tmp_txid,param3,tokenid;
CTransaction tx; char myCCaddr[65],addr[65],str[256]; CPubKey mypk,srcpub,destpub; int32_t vout,numvouts,param1;
CTransaction tx; char myCCaddr[65],str[512],pub[34]; CPubKey mypk,srcpub,destpub; int32_t vout,numvouts,param1;
int64_t nValue,param2;
cp = CCinit(&C,EVAL_CHANNELS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
GetCCaddress(cp,myCCaddr,mypk);
SetCCtxids(txids,myCCaddr,true,EVAL_CHANNELS,zeroid,'O');
result.push_back(Pair("result","success"));
@ -804,8 +700,7 @@ UniValue ChannelsList()
{
if (DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,tmp_txid,srcpub,destpub,param1,param2,param3) == 'O')
{
GetCCaddress1of2(cp,addr,srcpub,destpub);
sprintf(str,"%s - %lld payments of %lld satoshi",addr,(long long)param1,(long long)param2);
sprintf(str,"%lld payments of %lld satoshi to %s",(long long)param1,(long long)param2,pubkey33_str(pub,(uint8_t *)&destpub));
result.push_back(Pair(txid.GetHex().data(),str));
}
}
@ -813,7 +708,7 @@ UniValue ChannelsList()
return(result);
}
UniValue ChannelsInfo(uint256 channeltxid)
UniValue ChannelsInfo(const CPubKey& pk,uint256 channeltxid)
{
UniValue result(UniValue::VOBJ),array(UniValue::VARR); CTransaction tx,opentx; uint256 txid,tmp_txid,hashBlock,param3,opentxid,hashchain,tokenid;
struct CCcontract_info *cp,C; char CCaddr[65],addr[65],str[512]; int32_t vout,numvouts,param1,numpayments;
@ -821,7 +716,7 @@ UniValue ChannelsInfo(uint256 channeltxid)
std::vector<uint256> txids; std::vector<CTransaction> txs;
cp = CCinit(&C,EVAL_CHANNELS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if (myGetTransaction(channeltxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 &&
(DecodeChannelsOpRet(tx.vout[numvouts-1].scriptPubKey,tokenid,opentxid,srcpub,destpub,param1,param2,param3) == 'O'))

2
src/cc/customcc.cpp

@ -62,7 +62,7 @@ UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
if ( txfee == 0 )
txfee = CUSTOM_TXFEE;
mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,COIN+txfee,64) >= COIN+txfee ) // add utxo to mtx
if ( AddNormalinputs2(mtx,COIN+txfee,64) >= COIN+txfee ) // add utxo to mtx
{
// make op_return payload as normal.
CScript opret = custom_opret('1',mypk);

108
src/cc/dapps/oraclefeed.c

@ -15,12 +15,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <memory.h>
#include "cJSON.c"
bits256 zeroid;
void myprintf(const char* format, ...)
{
va_list marker;
va_start( marker, format );
vfprintf(stdout, format, marker);
fflush(stdout);
va_end( marker );
}
char hexbyte(int32_t c)
{
c &= 0xf;
@ -64,7 +74,7 @@ int32_t unhex(char c)
int32_t hex;
if ( (hex= _unhex(c)) < 0 )
{
//printf("unhex: illegal hexchar.(%c)\n",c);
//myprintf("unhex: illegal hexchar.(%c)\n",c);
}
return(hex);
}
@ -74,7 +84,7 @@ unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])
int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex)
{
int32_t adjust,i = 0;
//printf("decode.(%s)\n",hex);
//myprintf("decode.(%s)\n",hex);
if ( is_hexstr(hex,n) <= 0 )
{
memset(bytes,0,n);
@ -89,7 +99,7 @@ int32_t decode_hex(unsigned char *bytes,int32_t n,char *hex)
if ( n > 0 )
{
bytes[0] = unhex(hex[0]);
printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex));
myprintf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex));
}
bytes++;
hex++;
@ -116,10 +126,10 @@ int32_t init_hexbytes_noT(char *hexbytes,unsigned char *message,long len)
{
hexbytes[i*2] = hexbyte((message[i]>>4) & 0xf);
hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf);
//printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]);
//myprintf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]);
}
hexbytes[len*2] = 0;
//printf("len.%ld\n",len*2+1);
//myprintf("len.%ld\n",len*2+1);
return((int32_t)len*2+1);
}
@ -143,7 +153,7 @@ char *clonestr(char *str)
char *clone;
if ( str == 0 || str[0]==0)
{
printf("warning cloning nullstr.%p\n",str);
myprintf("warning cloning nullstr.%p\n",str);
//#ifdef __APPLE__
// while ( 1 ) sleep(1);
//#endif
@ -165,8 +175,8 @@ int32_t safecopy(char *dest,char *src,long len)
dest[i] = src[i];
if ( i == len )
{
printf("safecopy: %s too long %ld\n",src,len);
//printf("divide by zero! %d\n",1/zeroval());
myprintf("safecopy: %s too long %ld\n",src,len);
//myprintf("divide by zero! %d\n",1/zeroval());
#ifdef __APPLE__
//getchar();
#endif
@ -236,7 +246,7 @@ void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
{
fclose(fp);
*lenp = 0;
//printf("loadfile null size.(%s)\n",fname);
//myprintf("loadfile null size.(%s)\n",fname);
return(0);
}
if ( filesize > buflen )
@ -246,17 +256,17 @@ void *loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
}
rewind(fp);
if ( buf == 0 )
printf("Null buf ???\n");
myprintf("Null buf ???\n");
else
{
if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize )
printf("error reading filesize.%ld\n",(long)filesize);
myprintf("error reading filesize.%ld\n",(long)filesize);
buf[filesize] = 0;
}
fclose(fp);
*lenp = filesize;
//printf("loaded.(%s)\n",buf);
} //else printf("OS_loadfile couldnt load.(%s)\n",fname);
//myprintf("loaded.(%s)\n",buf);
} //else myprintf("OS_loadfile couldnt load.(%s)\n",fname);
return(buf);
}
@ -284,7 +294,7 @@ cJSON *get_urljson(char *url,char *fname)
char *jsonstr; cJSON *json = 0;
if ( (jsonstr= send_curl(url,fname)) != 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
//myprintf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse(jsonstr);
free(jsonstr);
}
@ -303,7 +313,7 @@ uint64_t get_btcusd()
if ( (bpi= jobj(pjson,"bpi")) != 0 && (usd= jobj(bpi,"USD")) != 0 )
{
btcusd = jdouble(usd,"rate_float") * SATOSHIDEN;
printf("BTC/USD %.4f\n",dstr(btcusd));
myprintf("BTC/USD %.4f\n",dstr(btcusd));
}
free_json(pjson);
}
@ -319,13 +329,13 @@ cJSON *get_cli(char *refcoin,char **retstrp,char *acname,char *method,char *arg0
if ( acname[0] != 0 )
{
if ( refcoin[0] == 0 )
printf("must supply reference coin\n");
myprintf("must supply reference coin\n");
sprintf(cmdstr,"./komodo-cli -ac_name=%s %s %s %s %s %s > %s 2>/tmp/oraclefeed.error\n",acname,method,arg0,arg1,arg2,arg3,fname);
}
else if ( REFCOIN_CLI != 0 && REFCOIN_CLI[0] != 0 )
{
sprintf(cmdstr,"%s %s %s %s %s %s > %s 2>/tmp/oraclefeed.error\n",REFCOIN_CLI,method,arg0,arg1,arg2,arg3,fname);
//printf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr);
//myprintf("ref.(%s) REFCOIN_CLI (%s)\n",refcoin,cmdstr);
}
#ifdef TESTMODE
fprintf(stderr,"cmd: %s\n",cmdstr);
@ -355,7 +365,7 @@ bits256 broadcasttx(char *refcoin,char *acname,cJSON *hexjson)
{
if ( (retjson= get_cli(refcoin,&retstr,acname,"sendrawtransaction",hexstr,"","","")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))==0) printf("%s\n",jstr(retjson,"error"));
if (strcmp("error",jstr(retjson,"result"))==0) myprintf("%s\n",jstr(retjson,"error"));
free_json(retjson);
}
else if ( retstr != 0 )
@ -457,7 +467,7 @@ cJSON *get_gatewayspending(int8_t type,char *refcoin,char *acname,char *bindtxid
else if (type==1) sprintf(function,"%s","importgatewaypendingwithdraws");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 )
{
//printf("pending.(%s)\n",jprint(retjson,0));
//myprintf("pending.(%s)\n",jprint(retjson,0));
return(retjson);
}
else if ( retstr != 0 )
@ -476,7 +486,7 @@ cJSON *get_gatewaysprocessed(int8_t type,char *refcoin,char *acname,char *bindtx
else if (type==1) sprintf(function,"%s","importgatewayprocessed");
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bindtxidstr,refcoin,"","")) != 0 )
{
//printf("pending.(%s)\n",jprint(retjson,0));
//myprintf("pending.(%s)\n",jprint(retjson,0));
return(retjson);
}
else if ( retstr != 0 )
@ -492,7 +502,7 @@ cJSON *get_rawmempool(char *refcoin,char *acname)
cJSON *retjson; char *retstr;
if ( (retjson= get_cli(refcoin,&retstr,acname,"getrawmempool","","","","")) != 0 )
{
//printf("mempool.(%s)\n",jprint(retjson,0));
//myprintf("mempool.(%s)\n",jprint(retjson,0));
return(retjson);
}
else if ( retstr != 0 )
@ -507,11 +517,11 @@ cJSON *get_addressutxos(char *refcoin,char *acname,char *coinaddr)
{
cJSON *retjson; char *retstr,jsonbuf[256];
if ( refcoin[0] != 0 && strcmp(refcoin,"KMD") != 0 )
printf("warning: assumes %s has addressindex enabled\n",refcoin);
myprintf("warning: assumes %s has addressindex enabled\n",refcoin);
sprintf(jsonbuf,"{\\\"addresses\\\":[\\\"%s\\\"]}",coinaddr);
if ( (retjson= get_cli(refcoin,&retstr,acname,"getaddressutxos",jsonbuf,"","","")) != 0 )
{
//printf("addressutxos.(%s)\n",jprint(retjson,0));
//myprintf("addressutxos.(%s)\n",jprint(retjson,0));
return(retjson);
}
else if ( retstr != 0 )
@ -561,7 +571,7 @@ void importaddress(char *refcoin,char *acname,char *depositaddr, char *label,int
else strcpy(rescanstr,"false");
if ( (retjson= get_cli(refcoin,&retstr,acname,"importaddress",depositaddr,label,rescanstr,"")) != 0 )
{
printf("importaddress.(%s)\n",jprint(retjson,0));
myprintf("importaddress.(%s)\n",jprint(retjson,0));
free_json(retjson);
}
else if ( retstr != 0 )
@ -585,7 +595,7 @@ void addmultisigaddress(char *refcoin,char *acname,int32_t M, char *pubkeys)
{
sprintf(addr,"\"%s\"",retstr);
get_cli(refcoin,&retstr,acname,"importaddress",addr,"\"\"","false","");
printf("addmultisigaddress.(%s)\n",retstr);
myprintf("addmultisigaddress.(%s)\n",retstr);
free_json(retjson);
}
}
@ -628,7 +638,7 @@ char *createrawtx(char *refcoin,char *acname,char *depositaddr,char *withdrawadd
else txfee = 10000;
if ( satoshis < txfee )
{
printf("createrawtx: satoshis %.8f < txfee %.8f\n",(double)satoshis/SATOSHIDEN,(double)txfee/SATOSHIDEN);
myprintf("createrawtx: satoshis %.8f < txfee %.8f\n",(double)satoshis/SATOSHIDEN,(double)txfee/SATOSHIDEN);
return(0);
}
sprintf(array,"\'[\"%s\"]\'",depositaddr);
@ -655,26 +665,26 @@ char *createrawtx(char *refcoin,char *acname,char *depositaddr,char *withdrawadd
sprintf(argB,"\'%s\'",tmpB);
if ( (retjson2= get_cli(refcoin,&txstr,acname,"createrawtransaction",argA,argB,"","")) != 0 )
{
printf("createrawtx: unexpected JSON2.(%s)\n",jprint(retjson2,0));
myprintf("createrawtx: unexpected JSON2.(%s)\n",jprint(retjson2,0));
free_json(retjson2);
}
else if ( txstr == 0 )
printf("createrawtx: null txstr and JSON2\n");
myprintf("createrawtx: null txstr and JSON2\n");
free(tmpA);
free(tmpB);
free(argA);
free(argB);
}
else printf("not enough funds to create withdraw tx\n");
else myprintf("not enough funds to create withdraw tx\n");
}
free_json(retjson);
}
else if ( retstr != 0 )
{
printf("createrawtx: unexpected null JSON, retstr.(%s)\n",retstr);
myprintf("createrawtx: unexpected null JSON, retstr.(%s)\n",retstr);
free(retstr);
}
else printf("createrawtx: null retstr and JSON\n");
else myprintf("createrawtx: null retstr and JSON\n");
return(txstr);
}
@ -694,7 +704,7 @@ cJSON *addsignature(char *refcoin,char *acname,char *rawtx, int M)
}
else if ( retstr != 0 )
{
printf("error parsing signrawtransaction.(%s)\n",retstr);
myprintf("error parsing signrawtransaction.(%s)\n",retstr);
free(retstr);
}
return(0);
@ -708,13 +718,13 @@ bits256 gatewayspartialsign(int8_t type,char *refcoin,char *acname,bits256 txid,
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,txid),refcoin,hex,"")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
else printf("%s\n",jstr(retjson,"error"));
else myprintf("%s\n",jstr(retjson,"error"));
free(retjson);
return (txid);
}
else if ( retstr != 0 )
{
printf("error parsing gatewayspartialsing.(%s)\n",retstr);
myprintf("error parsing gatewayspartialsing.(%s)\n",retstr);
free(retstr);
}
return (zeroid);
@ -729,13 +739,13 @@ bits256 gatewayscompletesigning(int8_t type,char *refcoin,char *acname,bits256 w
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,hex,"")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
else printf("%s\n",jstr(retjson,"error"));
else myprintf("%s\n",jstr(retjson,"error"));
free(retjson);
return (txid);
}
else if ( retstr != 0 )
{
printf("error parsing gatewayscompletesigning.(%s)\n",retstr);
myprintf("error parsing gatewayscompletesigning.(%s)\n",retstr);
free(retstr);
}
return (zeroid);
@ -750,13 +760,13 @@ bits256 gatewaysmarkdone(int8_t type,char *refcoin,char *acname,bits256 withtxid
if ( (retjson= get_cli(refcoin,&retstr,acname,function,bits256_str(str,withtxid),refcoin,"","")) != 0 )
{
if (strcmp("error",jstr(retjson,"result"))!=0) txid=broadcasttx(refcoin,acname,retjson);
else printf("%s\n",jstr(retjson,"error"));
else myprintf("%s\n",jstr(retjson,"error"));
free(retjson);
return (txid);
}
else if ( retstr != 0 )
{
printf("error parsing gatewaysmarkdone.(%s)\n",retstr);
myprintf("error parsing gatewaysmarkdone.(%s)\n",retstr);
free(retstr);
}
return (zeroid);
@ -778,7 +788,7 @@ int32_t get_gatewaysinfo(int8_t type,char *refcoin,char *acname,char *depositadd
*Mp = jint(retjson,"M");
*Np = jint(retjson,"N");
}
else printf("coin.%s vs %s\n",jstr(retjson,"coin"),coin);
else myprintf("coin.%s vs %s\n",jstr(retjson,"coin"),coin);
if ((pubarray=jarray(&n,retjson,"pubkeys"))!=0)
{
*pubkeys=malloc((sizeof(char)*70*n)+64);
@ -797,7 +807,7 @@ int32_t get_gatewaysinfo(int8_t type,char *refcoin,char *acname,char *depositadd
}
else if ( retstr != 0 )
{
printf("error parsing get_gatewaysinfo.(%s)\n",retstr);
myprintf("error parsing get_gatewaysinfo.(%s)\n",retstr);
free(retstr);
}
if ( *Mp <= 0 || *Np <= 0 )
@ -1049,10 +1059,10 @@ int32_t main(int32_t argc,char **argv)
cJSON *clijson,*clijson2,*regjson,*item; int32_t type,i,retval,M,N,n,height,prevheight = 0; char *pubkeys,*format,*acname,*oraclestr,*bindtxidstr,*pkstr,*pubstr,*retstr,*retstr2,depositaddr[64],hexstr[4096],refcoin[64]; uint64_t price; bits256 txid;
if ( argc < 6 )
{
printf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n");
myprintf("usage: oraclefeed $ACNAME $ORACLETXID $MYPUBKEY $FORMAT $BINDTXID [refcoin_cli]\n");
return(-1);
}
printf("Powered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
myprintf("Powered by CoinDesk (%s) %.8f\n","https://www.coindesk.com/price/",dstr(get_btcusd()));
acname = argv[1];
oraclestr = argv[2];
pkstr = argv[3];
@ -1063,7 +1073,7 @@ int32_t main(int32_t argc,char **argv)
else REFCOIN_CLI = "./komodo-cli";
if ( strncmp(format,"Ihh",3) != 0 && format[0] != 'L' )
{
printf("only formats of L and Ihh are supported now\n");
myprintf("only formats of L and Ihh are supported now\n");
return(-1);
}
M = N = 0;
@ -1078,7 +1088,7 @@ int32_t main(int32_t argc,char **argv)
strcpy(refcoin,jstr(clijson,"name"));
if ( strcmp("KMD",refcoin) != 0 && argc != 7 )
{
printf("need to specify path to refcoin's cli as last argv\n");
myprintf("need to specify path to refcoin's cli as last argv\n");
exit(0);
}
pubkeys=0;
@ -1086,7 +1096,7 @@ int32_t main(int32_t argc,char **argv)
else if ( get_gatewaysinfo(1,refcoin,acname,depositaddr,&M,&N,bindtxidstr,refcoin,oraclestr,&pubkeys) == 0 ) type=1;
else
{
printf("cant find bindtxid.(%s)\n",bindtxidstr);
myprintf("cant find bindtxid.(%s)\n",bindtxidstr);
exit(0);
}
if (validateaddress(refcoin,"",depositaddr,"iswatchonly")==0 && validateaddress(refcoin,"",depositaddr,"ismine")==0)
@ -1095,7 +1105,7 @@ int32_t main(int32_t argc,char **argv)
else addmultisigaddress(refcoin,"",M,pubkeys);
}
if (pubkeys!=0) free(pubkeys);
printf("set refcoin %s <- %s [%s] M.%d of N.%d\n",depositaddr,refcoin,REFCOIN_CLI,M,N);
myprintf("set refcoin %s <- %s [%s] M.%d of N.%d\n",depositaddr,refcoin,REFCOIN_CLI,M,N);
}
if ( (regjson= jarray(&n,clijson,"registered")) != 0 )
{
@ -1112,14 +1122,14 @@ int32_t main(int32_t argc,char **argv)
if ( bits256_nonz(txid) != 0 )
{
prevheight = height;
printf("%s ht.%d <- %s\n",refcoin,height,hexstr);
myprintf("%s ht.%d <- %s\n",refcoin,height,hexstr);
update_gatewayspending(type,refcoin,acname,bindtxidstr,M,N);
}
free_json(clijson2);
}
else if ( retstr2 != 0 )
{
printf("error parsing oraclesdata.(%s)\n",retstr2);
myprintf("error parsing oraclesdata.(%s)\n",retstr2);
free(retstr2);
}
}
@ -1131,7 +1141,7 @@ int32_t main(int32_t argc,char **argv)
}
if ( retstr != 0 )
{
printf("got json parse error.(%s)\n",retstr);
myprintf("got json parse error.(%s)\n",retstr);
free(retstr);
}
sleep(10);

2
src/cc/eval.h

@ -1,4 +1,3 @@
// Copyright 2019 The Hush developers
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
@ -37,6 +36,7 @@
* there should be a code identifying it. For example,
* a possible code is EVAL_BITCOIN_SCRIPT, where the entire binary
* after the code is interpreted as a bitcoin script.
* Verus EVAL_STAKEGUARD is 0x01
*/
#define FOREACH_EVAL(EVAL) \
EVAL(EVAL_IMPORTPAYOUT, 0xe1) \

34
src/cc/faucet.cpp

@ -172,20 +172,20 @@ int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
} else fprintf(stderr,"vout.%d nValue %.8f too small or already spent in mempool\n",vout,(double)nValue/COIN);
} else fprintf(stderr,"couldnt get tx\n");
} else fprintf(stderr,"couldn't get tx\n");
}
return(totalinputs);
}
std::string FaucetGet(uint64_t txfee)
UniValue FaucetGet(const CPubKey& pk, uint64_t txfee)
{
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,faucetpk; int64_t inputs,CCchange=0,nValue=FAUCETSIZE; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
CPubKey faucetpk; int64_t inputs,CCchange=0,nValue=FAUCETSIZE; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_FAUCET);
if ( txfee == 0 )
txfee = 10000;
faucetpk = GetUnspendable(cp,0);
mypk = pubkey2pk(Mypubkey());
CPubKey mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if ( (inputs= AddFaucetInputs(cp,mtx,faucetpk,nValue+txfee,60)) > 0 )
{
if ( inputs > nValue )
@ -198,42 +198,40 @@ std::string FaucetGet(uint64_t txfee)
for (i=0; i<1000000; i++,j++)
{
tmpmtx = mtx;
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FAUCET << (uint8_t)'G' << j));
if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 )
UniValue result = FinalizeCCTxExt(pk.IsValid (),-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_FAUCET << (uint8_t)'G' << j));
if ( (len= (int32_t)result[JSON_HEXTX].getValStr().size()) > 0 && len < 65536 )
{
len >>= 1;
decode_hex(buf,len,(char *)rawhex.c_str());
decode_hex(buf,len,(char *)result[JSON_HEXTX].getValStr().c_str());
hash = bits256_doublesha256(0,buf,len);
if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 )
{
fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL));
return(rawhex);
return result;
}
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
}
}
fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL));
return("");
} else fprintf(stderr,"cant find faucet inputs\n");
return("");
CCERR_RESULT("faucet",CCLOG_ERROR, stream << "couldn't generate valid txid " << (uint32_t)time(NULL));
} else CCERR_RESULT("faucet",CCLOG_ERROR, stream << "can't find faucet inputs");
}
std::string FaucetFund(uint64_t txfee,int64_t funds)
UniValue FaucetFund(const CPubKey& pk, uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,faucetpk; CScript opret; struct CCcontract_info *cp,C;
CPubKey faucetpk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_FAUCET);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
CPubKey mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
faucetpk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
if ( AddNormalinputs(mtx,mypk,funds+txfee,64,pk.IsValid()) > 0 )
{
mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,funds,faucetpk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,opret));
}
return("");
CCERR_RESULT("faucet",CCLOG_ERROR, stream << "can't find normal inputs");
}
UniValue FaucetInfo()

487
src/cc/gateways.cpp

@ -862,12 +862,12 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
return(0);
}
std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4)
UniValue GatewaysBind(const CPubKey& pk, uint64_t txfee,std::string coin,uint256 tokenid,int64_t totalsupply,uint256 oracletxid,uint8_t M,uint8_t N,std::vector<CPubKey> pubkeys,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction oracletx; uint8_t taddr,prefix,prefix2,wiftype; CPubKey mypk,gatewayspk; CScript opret; uint256 hashBlock;
struct CCcontract_info *cp,*cpTokens,C,CTokens; std::string name,description,format; int32_t i,numvouts; int64_t fullsupply;
char destaddr[64],coinaddr[64],myTokenCCaddr[64],str[65],*fstr;
char destaddr[64],coinaddr[64],myTokenCCaddr[64],*fstr;
cp = CCinit(&C,EVAL_GATEWAYS);
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
@ -887,118 +887,64 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "set prefix " << prefix << ", prefix2 " << prefix2 << ", wiftype " << wiftype << ", taddr " << taddr << " for " << coin << std::endl);
}
if ( N == 0 || N > 15 || M > N )
{
CCerror = strprintf("illegal M.%d or N.%d",M,N);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "illegal M." << M << " or N." << N);
if ( pubkeys.size() != N )
{
CCerror = strprintf("M.%d N.%d but pubkeys[%d]",M,N,(int32_t)pubkeys.size());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "M."<< M << " N." << N << " but pubkeys[" <<( int32_t)pubkeys.size() << "]");
for (i=0; i<N; i++)
{
Getscriptaddress(coinaddr,CScript() << ParseHex(HexStr(pubkeys[i])) << OP_CHECKSIG);
if ( CCaddress_balance(coinaddr,0) == 0 )
{
CCerror = strprintf("M.%d N.%d but pubkeys[%d] has no balance",M,N,i);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "M." << M << " N." << N << " but pubkeys[" << i << "] has no balance");
}
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
_GetCCaddress(myTokenCCaddr,EVAL_TOKENS,mypk);
gatewayspk = GetUnspendable(cp,0);
if ( _GetCCaddress(destaddr,EVAL_GATEWAYS,gatewayspk) == 0 )
{
CCerror = strprintf("Gateway bind.%s (%s) cant create globaladdr",coin.c_str(),uint256_str(str,tokenid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "Gateway bind." << coin << " (" << tokenid.GetHex() << ") cant create globaladdr");
if ( (fullsupply=CCfullsupply(tokenid)) != totalsupply )
{
CCerror = strprintf("Gateway bind.%s (%s) globaladdr.%s totalsupply %.8f != fullsupply %.8f",coin.c_str(),uint256_str(str,tokenid),cp->unspendableCCaddr,(double)totalsupply/COIN,(double)fullsupply/COIN);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "Gateway bind." << coin << " ("<< tokenid.GetHex() << ") globaladdr." <<cp->unspendableCCaddr << " totalsupply " << (double)totalsupply/COIN << " != fullsupply " << (double)fullsupply/COIN);
if ( CCtoken_balance(myTokenCCaddr,tokenid) != totalsupply )
{
CCerror = strprintf("token balance on %s %.8f != %.8f",myTokenCCaddr,(double)CCtoken_balance(myTokenCCaddr,tokenid)/COIN,(double)totalsupply/COIN);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "token balance on " << myTokenCCaddr << " " << (double)CCtoken_balance((char *)myTokenCCaddr,tokenid)/COIN << "!=" << (double)totalsupply/COIN);
if ( myGetTransaction(oracletxid,oracletx,hashBlock) == 0 || (numvouts= oracletx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find oracletxid %s",uint256_str(str,oracletxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex());
if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' )
{
CCerror = strprintf("mismatched oracle name %s != %s",name.c_str(),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "mismatched oracle name " << name << " != " << coin);
if ( (fstr=(char *)format.c_str()) == 0 || strncmp(fstr,"Ihh",3) != 0 )
{
CCerror = strprintf("illegal format (%s) != (%s)",fstr,(char *)"Ihh");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "illegal format (" << fstr << ") != (Ihh)");
if ( GatewaysBindExists(cp,gatewayspk,tokenid) != 0 )
{
CCerror = strprintf("Gateway bind.%s (%s) already exists",coin.c_str(),uint256_str(str,tokenid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2) > 0 )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "Gateway bind." << coin << " (" << tokenid.GetHex() << ") already exists");
if ( AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2,pk.IsValid()) > 0 )
{
if (AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, totalsupply, 64)>0)
{
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,totalsupply,gatewayspk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysBindOpRet('B',tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeGatewaysBindOpRet('B',tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)));
}
}
CCerror = strprintf("cant find enough inputs");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find enough inputs");
}
std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount)
UniValue GatewaysDeposit(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,int32_t height,std::string refcoin,uint256 cointxid,int32_t claimvout,std::string deposithex,std::vector<uint8_t>proof,CPubKey destpub,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction bindtx; CPubKey mypk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid;
CTransaction tx; CPubKey mypk; uint256 oracletxid,merkleroot,mhash,hashBlock,tokenid,txid;
int64_t totalsupply; int32_t i,m,n,numvouts; uint8_t M,N,taddr,prefix,prefix2,wiftype; std::string coin; struct CCcontract_info *cp,C;
std::vector<CPubKey> pubkeys,publishers; std::vector<uint256>txids; char str[67],depositaddr[64],txidaddr[64];
std::vector<CPubKey> pubkeys,publishers; std::vector<uint256>txids; char str[65],depositaddr[64],txidaddr[64];
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "GatewaysDeposit ht." << height << " " << refcoin << " " << (double)amount/COIN << " numpks." << (int32_t)pubkeys.size() << std::endl);
if ( myGetTransaction(bindtxid,bindtx,hashBlock) == 0 || (numvouts= bindtx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
{
CCerror = strprintf("invalid coin - bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( myGetTransaction(bindtxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find bindtxid " << bindtxid.GetHex());
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid coin - bindtxid " << bindtxid.GetHex() << " coin." << coin);
if (komodo_txnotarizedconfirmed(bindtxid)==false)
{
CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewaysbind tx not yet confirmed/notarized");
n = (int32_t)pubkeys.size();
merkleroot = zeroid;
for (i=m=0; i<n; i++)
@ -1017,141 +963,80 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
}
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "cointxid." << cointxid.GetHex() << " m." << m << " of n." << n << std::endl);
if ( merkleroot == zeroid || m < n/2 )
{
CCerror = strprintf("couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d",height,coin.c_str(),uint256_str(str,oracletxid),m,n);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "couldnt find merkleroot for ht." << height << " " << coin << " oracle." << oracletxid.GetHex() << " m." << m << " vs n." << n);
if ( CCCointxidExists("gatewayscc-1",cointxid) != 0 )
{
CCerror = strprintf("cointxid.%s already exists",uint256_str(str,cointxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cointxid." << cointxid.GetHex() << " already exists");
if ( GatewaysVerify(depositaddr,oracletxid,claimvout,coin,cointxid,deposithex,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount )
{
CCerror = strprintf("deposittxid didnt validate");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,3) > 0 )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "deposittxid didnt validate");
if ( AddNormalinputs(mtx,mypk,txfee+2*CC_MARKER_VALUE,3,pk.IsValid()) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,destpub));
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,cointxid))) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysDepositOpRet('D',bindtxid,coin,publishers,txids,height,cointxid,claimvout,deposithex,proof,destpub,amount)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeGatewaysDepositOpRet('D',bindtxid,coin,publishers,txids,height,cointxid,claimvout,deposithex,proof,destpub,amount)));
}
CCerror = strprintf("cant find enough inputs");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find enough inputs");
}
std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount)
UniValue GatewaysClaim(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,std::string refcoin,uint256 deposittxid,CPubKey destpub,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; CPubKey mypk,gatewayspk,tmpdestpub; struct CCcontract_info *cp,C; uint8_t M,N,taddr,prefix,prefix2,wiftype;
std::string coin, deposithex; std::vector<CPubKey> msigpubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0;
std::string coin, deposithex; std::vector<CPubKey> pubkeys,publishers; int64_t totalsupply,depositamount,tmpamount,inputs,CCchange=0;
int32_t numvouts,claimvout,height; std::vector<uint8_t> proof;
uint256 hashBlock,tokenid,oracletxid,tmptxid,cointxid; char str[65],depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> txids;
uint256 hashBlock,tokenid,oracletxid,tmptxid,cointxid; char depositaddr[64],coinaddr[64],destaddr[64]; std::vector<uint256> txids;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( myGetTransaction(bindtxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || coin != refcoin )
{
CCerror = strprintf("invalid coin - bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find bindtxid " << bindtxid.GetHex());
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid coin - bindtxid " << bindtxid.GetHex() << " coin." << coin);
if (komodo_txnotarizedconfirmed(bindtxid)==false)
{
CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewaysbind tx not yet confirmed/notarized");
if ( myGetTransaction(deposittxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find deposittxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find deposittxid " << bindtxid.GetHex());
if (DecodeGatewaysDepositOpRet(tx.vout[numvouts-1].scriptPubKey,tmptxid,coin,publishers,txids,height,cointxid,claimvout,deposithex,proof,tmpdestpub,tmpamount) != 'D' || coin != refcoin)
{
CCerror = strprintf("invalid coin - deposittxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid coin - deposittxid " << bindtxid.GetHex() << " coin." << coin);
if (komodo_txnotarizedconfirmed(deposittxid)==false)
{
CCerror = strprintf("gatewaysdeposit tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewaysdeposit tx not yet confirmed/notarized");
if (tmpdestpub!=destpub)
{
CCerror = strprintf("different destination pubkey from desdeposit tx");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "different destination pubkey from desdeposit tx");
if ( (depositamount=GatewaysDepositval(tx,mypk)) != amount )
{
CCerror = strprintf("invalid Gateways deposittxid %s %.8f != %.8f",uint256_str(str,deposittxid),(double)depositamount/COIN,(double)amount/COIN);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid Gateways deposittxid " << deposittxid.GetHex() << " " << (double)depositamount/COIN << " != " << (double)amount/COIN << ", remember claim must be done from destination pubkey from deposit tx!");
if ((inputs=AddGatewaysInputs(cp, mtx, gatewayspk, bindtxid, amount, 60)) > 0)
{
if ( inputs > amount ) CCchange = (inputs - amount);
mtx.vin.push_back(CTxIn(deposittxid,0,CScript()));
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS,amount,destpub));
if ( CCchange != 0 ) mtx.vout.push_back(MakeTokensCC1vout(EVAL_GATEWAYS,CCchange,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysClaimOpRet('C',tokenid,bindtxid,refcoin,deposittxid,destpub,amount)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeGatewaysClaimOpRet('C',tokenid,bindtxid,refcoin,deposittxid,destpub,amount)));
}
CCerror = strprintf("cant find enough tokens in gateways address for given amount");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find enough tokens in gateways address for given amount");
}
std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount)
UniValue GatewaysWithdraw(const CPubKey& pk, uint64_t txfee,uint256 bindtxid,std::string refcoin,CPubKey withdrawpub,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CTransaction tx; CPubKey mypk,gatewayspk,signerpk; uint256 txid,tokenid,hashBlock,oracletxid,tmptokenid,tmpbindtxid,withdrawtxid; int32_t vout,numvouts;
int64_t nValue,totalsupply,inputs,CCchange=0,tmpamount; uint8_t funcid,K,M,N,taddr,prefix,prefix2,wiftype; std::string coin,hex;
std::vector<CPubKey> msigpubkeys; char depositaddr[64],str[65],coinaddr[64]; struct CCcontract_info *cp,C,*cpTokens,CTokens;
std::vector<CPubKey> pubkeys; char depositaddr[64],coinaddr[64]; struct CCcontract_info *cp,C,*cpTokens,CTokens;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_GATEWAYS);
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp, 0);
if( myGetTransaction(bindtxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || coin != refcoin )
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( myGetTransaction(bindtxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find bindtxid " << bindtxid.GetHex());
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid coin - bindtxid " << bindtxid.GetHex() << " coin." << coin);
if (komodo_txnotarizedconfirmed(bindtxid)==false)
{
CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewaysbind tx not yet confirmed/notarized");
_GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk);
SetCCunspents(unspentOutputs,coinaddr,true);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
@ -1165,23 +1050,14 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
{
if (funcid=='W' && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,tmpbindtxid,coin,withdrawpub,tmpamount)=='W'
&& refcoin==coin && tmptokenid==tokenid && tmpbindtxid==bindtxid)
{
CCerror = strprintf("unable to create withdraw, another withdraw pending");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "unable to create withdraw, another withdraw pending");
else if (funcid=='P' && DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,hex)=='P' &&
myGetTransaction(withdrawtxid,tx,hashBlock)!=0 && (numvouts=tx.vout.size())>0 && DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,tmpbindtxid,coin,withdrawpub,tmpamount)=='W'
&& refcoin==coin && tmptokenid==tokenid && tmpbindtxid==bindtxid)
{
CCerror = strprintf("unable to create withdraw, another withdraw pending");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "unable to create withdraw, another withdraw pending");
}
}
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 2) > 0 )
if( AddNormalinputs(mtx, mypk, txfee+CC_MARKER_VALUE, 2,pk.IsValid()) > 0 )
{
if ((inputs = AddTokenCCInputs(cpTokens, mtx, mypk, tokenid, amount, 60)) > 0)
{
@ -1189,286 +1065,159 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
mtx.vout.push_back(MakeTokensCC1vout(EVAL_GATEWAYS,amount,gatewayspk));
if ( CCchange != 0 ) mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, CCchange, mypk));
return(FinalizeCCTx(0, cpTokens, mtx, mypk, txfee,EncodeGatewaysWithdrawOpRet('W',tokenid,bindtxid,refcoin,withdrawpub,amount)));
return(FinalizeCCTxExt(pk.IsValid(),0, cpTokens, mtx, mypk, txfee,EncodeGatewaysWithdrawOpRet('W',tokenid,bindtxid,refcoin,withdrawpub,amount)));
}
else
{
CCerror = strprintf("not enough balance of tokens for withdraw");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "not enough balance of tokens for withdraw");
}
CCerror = strprintf("cant find enough normal inputs");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cant find enough normal inputs");
}
std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refcoin, std::string hex)
UniValue GatewaysPartialSign(const CPubKey& pk, uint64_t txfee,uint256 lasttxid,std::string refcoin, std::string hex)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,withdrawpub,signerpk,gatewayspk; struct CCcontract_info *cp,C; CTransaction tx,tmptx;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; char funcid,str[65],depositaddr[64];
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; char funcid,depositaddr[64];
int32_t numvouts; uint256 withdrawtxid,hashBlock,bindtxid,tokenid,oracletxid,tmptokenid; std::string coin,tmphex; int64_t amount,totalsupply;
uint8_t K=0,M,N,taddr,prefix,prefix2,wiftype; std::vector<CPubKey> pubkeys;
cp = CCinit(&C,EVAL_GATEWAYS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if (myGetTransaction(lasttxid,tx,hashBlock)==0 || (numvouts= tx.vout.size())<=0
|| (funcid=DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey))==0 || (funcid!='W' && funcid!='P'))
{
CCerror = strprintf("can't find last tx %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find last tx " << lasttxid.GetHex());
if (funcid=='W')
{
withdrawtxid=lasttxid;
if (DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("invalid withdraw tx %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid withdraw tx " << lasttxid.GetHex());
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewayswithdraw tx not yet confirmed/notarized");
else if (myGetTransaction(bindtxid,tmptx,hashBlock)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find bind tx " << bindtxid.GetHex());
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid bind tx " << bindtxid.GetHex());
}
else if (funcid=='P')
{
if (DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin)
{
CCerror = strprintf("cannot decode partialsign tx opret %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cannot decode partialsign tx opret " << lasttxid.GetHex());
else if (myGetTransaction(withdrawtxid,tmptx,hashBlock)==0 || (numvouts= tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find withdraw tx %s",uint256_str(str,withdrawtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find withdraw tx " << withdrawtxid.GetHex());
else if (DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W'
|| refcoin!=coin)
{
CCerror = strprintf("invalid withdraw tx %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid withdraw tx " << withdrawtxid.GetHex());
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewayswithdraw tx not yet confirmed/notarized");
else if (myGetTransaction(bindtxid,tmptx,hashBlock)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find bind tx " << bindtxid.GetHex());
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid bind tx " << bindtxid.GetHex());
}
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
if (AddNormalinputs(mtx,mypk,txfee,1,pk.IsValid())!=0)
{
mtx.vin.push_back(CTxIn(tx.GetHash(),0,CScript()));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysPartialOpRet('P',withdrawtxid,refcoin,K+1,mypk,hex)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeGatewaysPartialOpRet('P',withdrawtxid,refcoin,K+1,mypk,hex)));
}
CCerror = strprintf("error adding funds for partialsign");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "error adding funds for partialsign");
}
std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string refcoin,std::string hex)
UniValue GatewaysCompleteSigning(const CPubKey& pk, uint64_t txfee,uint256 lasttxid,std::string refcoin,std::string hex)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,gatewayspk,signerpk,withdrawpub; struct CCcontract_info *cp,C; char funcid,str[65],depositaddr[64]; int64_t amount,totalsupply;
CPubKey mypk,gatewayspk,signerpk,withdrawpub; struct CCcontract_info *cp,C; char funcid,depositaddr[64]; int64_t amount,totalsupply;
std::string coin,tmphex; CTransaction tx,tmptx; uint256 withdrawtxid,hashBlock,tokenid,tmptokenid,bindtxid,oracletxid; int32_t numvouts;
uint8_t K=0,M,N,taddr,prefix,prefix2,wiftype; std::vector<CPubKey> pubkeys;
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
if ( txfee == 0 )
txfee = 10000;
if (myGetTransaction(lasttxid,tx,hashBlock)==0 || (numvouts= tx.vout.size())<=0
|| (funcid=DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey))==0 || (funcid!='W' && funcid!='P'))
{
CCerror = strprintf("invalid last txid %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid last txid " << lasttxid.GetHex());
if (funcid=='W')
{
withdrawtxid=lasttxid;
if (DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("cannot decode withdraw tx opret %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (myGetTransaction(bindtxid,tmptx,hashBlock)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid withdraw tx " << lasttxid.GetHex());
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewayswithdraw tx not yet confirmed/notarized");
else if (myGetTransaction(bindtxid,tmptx,hashBlock)==0 || (numvouts=tmptx.vout.size())<=0)
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find bind tx " << bindtxid.GetHex());
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid bind tx " << bindtxid.GetHex());
}
else if (funcid=='P')
{
if (DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin)
{
CCerror = strprintf("cannot decode partialsign tx opret %s",uint256_str(str,lasttxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (myGetTransaction(withdrawtxid,tmptx,hashBlock)==0 || (numvouts=tmptx.vout.size())==0)
{
CCerror = strprintf("invalid withdraw txid %s",uint256_str(str,withdrawtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("cannot decode withdraw tx opret %s",uint256_str(str,withdrawtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin)
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cannot decode partialsign tx opret " << lasttxid.GetHex());
else if (myGetTransaction(withdrawtxid,tmptx,hashBlock)==0 || (numvouts= tmptx.vout.size())<=0)
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find withdraw tx " << withdrawtxid.GetHex());
else if (DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W'
|| refcoin!=coin)
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid withdraw tx " << withdrawtxid.GetHex());
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewayswithdraw tx not yet confirmed/notarized");
else if (myGetTransaction(bindtxid,tmptx,hashBlock)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find bind tx " << bindtxid.GetHex());
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid bind tx " << bindtxid.GetHex());
}
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
if (AddNormalinputs(mtx,mypk,txfee,1,pk.IsValid())!=0)
{
mtx.vin.push_back(CTxIn(lasttxid,0,CScript()));
mtx.vout.push_back(MakeCC1vout(EVAL_GATEWAYS,CC_MARKER_VALUE,gatewayspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysCompleteSigningOpRet('S',withdrawtxid,refcoin,K+1,hex)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeGatewaysCompleteSigningOpRet('S',withdrawtxid,refcoin,K+1,hex)));
}
CCerror = strprintf("error adding funds for completesigning");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "error adding funds for completesigning");
}
std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string refcoin)
UniValue GatewaysMarkDone(const CPubKey& pk, uint64_t txfee,uint256 completetxid,std::string refcoin)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp,C; char str[65],depositaddr[64]; CTransaction tx; int32_t numvouts;
CPubKey mypk; struct CCcontract_info *cp,C; char depositaddr[64]; CTransaction tx; int32_t numvouts;
uint256 withdrawtxid,bindtxid,oracletxid,tokenid,tmptokenid,hashBlock; std::string coin,hex;
uint8_t K,M,N,taddr,prefix,prefix2,wiftype; std::vector<CPubKey> pubkeys; int64_t amount,totalsupply; CPubKey withdrawpub;
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if ( txfee == 0 )
txfee = 10000;
if (myGetTransaction(completetxid,tx,hashBlock)==0 || (numvouts= tx.vout.size())<=0)
{
CCerror = strprintf("invalid completesigning txid %s",uint256_str(str,completetxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid completesigning txid " << completetxid.GetHex());
else if (DecodeGatewaysCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,hex)!='S' || refcoin!=coin)
{
CCerror = strprintf("cannot decode completesigning tx opret %s",uint256_str(str,completetxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cannot decode completesigning tx opret " << completetxid.GetHex());
if (komodo_txnotarizedconfirmed(completetxid)==false)
{
CCerror = strprintf("gatewayscompletesigning tx not yet confirmed/notarized");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "gatewayscompletesigning tx not yet confirmed/notarized");
else if (myGetTransaction(withdrawtxid,tx,hashBlock)==0 || (numvouts= tx.vout.size())==0)
{
CCerror = strprintf("invalid withdraw txid %s",uint256_str(str,withdrawtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid withdraw txid " << withdrawtxid.GetHex());
else if (DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("cannot decode withdraw tx opret %s\n",uint256_str(str,withdrawtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "cannot decode withdraw tx opret " << withdrawtxid.GetHex());
else if (myGetTransaction(bindtxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "can't find bind tx " << bindtxid.GetHex());
else if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (AddNormalinputs(mtx,mypk,txfee,1)!=0)
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "invalid bind tx " << bindtxid.GetHex());
if (AddNormalinputs(mtx,mypk,txfee,1,pk.IsValid())!=0)
{
mtx.vin.push_back(CTxIn(completetxid,0,CScript()));
mtx.vout.push_back(CTxOut(CC_MARKER_VALUE,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysMarkDoneOpRet('M',withdrawtxid,refcoin,completetxid)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeGatewaysMarkDoneOpRet('M',withdrawtxid,refcoin,completetxid)));
}
CCerror = strprintf("error adding funds for markdone");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("gatewayscc",CCLOG_INFO, stream << "error adding funds for markdone");
}
UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin)
UniValue GatewaysPendingDeposits(const CPubKey& pk, uint256 bindtxid,std::string refcoin)
{
UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string coin,hex,pub;
CPubKey mypk,gatewayspk,destpub; std::vector<CPubKey> pubkeys,publishers; std::vector<uint256> txids;
@ -1478,7 +1227,7 @@ UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin)
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
_GetCCaddress(coinaddr,EVAL_GATEWAYS,mypk);
if ( myGetTransaction(bindtxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
@ -1523,7 +1272,7 @@ UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin)
return(result);
}
UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
UniValue GatewaysPendingWithdraws(const CPubKey& pk, uint256 bindtxid,std::string refcoin)
{
UniValue result(UniValue::VOBJ),pending(UniValue::VARR); CTransaction tx; std::string coin,hex; CPubKey mypk,gatewayspk,withdrawpub,signerpk;
std::vector<CPubKey> msigpubkeys; uint256 hashBlock,tokenid,txid,tmpbindtxid,tmptokenid,oracletxid,withdrawtxid; uint8_t K,M,N,taddr,prefix,prefix2,wiftype;
@ -1532,7 +1281,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
_GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk);
GetTokensCCaddress(cp,tokensaddr,gatewayspk);
@ -1611,7 +1360,7 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
return(result);
}
UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
UniValue GatewaysProcessedWithdraws(const CPubKey& pk, uint256 bindtxid,std::string refcoin)
{
UniValue result(UniValue::VOBJ),processed(UniValue::VARR); CTransaction tx; std::string coin,hex;
CPubKey mypk,gatewayspk,withdrawpub; std::vector<CPubKey> msigpubkeys;
@ -1621,7 +1370,7 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_GATEWAYS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
gatewayspk = GetUnspendable(cp,0);
_GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk);
if ( myGetTransaction(bindtxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )

274
src/cc/heir.cpp

@ -628,72 +628,79 @@ template <typename Helper> UniValue _HeirFund(int64_t txfee, int64_t amount, std
CPubKey myPubkey = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) {
int64_t inputs, change;
if (!tokenid.IsNull()) // add normals only for tokens
{
if (AddNormalinputs(mtx, myPubkey, txfee + markerfee, 4) < txfee + markerfee)
{
std::cerr << "HeirFund() could not find normal inputs for txfee" << std::endl;
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "could not find normal inputs for txfee"));
return result;
}
}
if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, (int32_t)64)) > 0) {
mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey));
int64_t inputs;
int64_t addAmount = tokenid.IsNull() ? (txfee + markerfee + amount) : amount; // for coins add txfee markerfee amount in one call
if ((inputs=Helper::addOwnerInputs(tokenid, mtx, myPubkey, addAmount, (int32_t)64)) >= addAmount)
{
mtx.vout.push_back(Helper::make1of2Vout(amount, myPubkey, heirPubkey));
// add a marker for finding all plans in HeirList()
// TODO: change marker either to cc or normal txidaddr unspendable
struct CCcontract_info *cpHeir, heirC;
cpHeir = CCinit(&heirC, EVAL_HEIR);
CPubKey heirUnspendablePubKey = GetUnspendable(cpHeir, 0);
// mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); <-- bad marker cause it was spendable by anyone
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, markerfee, heirUnspendablePubKey)); // this marker spending is disabled in the validation code
// add a marker for finding all plans in HeirList()
// TODO: change marker either to cc or normal txidaddr unspendable
struct CCcontract_info *cpHeir, heirC;
cpHeir = CCinit(&heirC, EVAL_HEIR);
CPubKey heirUnspendablePubKey = GetUnspendable(cpHeir, 0);
// mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(heirUnspendablePubKey)) << OP_CHECKSIG)); <-- bad marker cause it was spendable by anyone
mtx.vout.push_back(MakeCC1vout(EVAL_HEIR, markerfee, heirUnspendablePubKey)); // this marker spending is disabled in the validation code
// calc and add change vout:
if (!tokenid.IsNull())
{
int64_t ccChange = 0;
// calc and add token change vout:
if (inputs > amount)
change = (inputs - amount); // -txfee <-- txfee pays user
ccChange = (inputs - amount); // -txfee <-- txfee pays user
//std::cerr << "HeirFund() inputs=" << inputs << " amount=" << amount << " txfee=" << txfee << " change=" << change << '\n';
if (change != 0) { // vout[1]
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
}
// check owner pubkey in vins
bool hasMypubkey = false;
bool hasNotMypubkey = false;
if (ccChange != 0)
mtx.vout.push_back(Helper::makeUserVout(ccChange, myPubkey));
}
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
// check owner pubkey in vins
bool hasMypubkey = false;
bool hasNotMypubkey = false;
// for initial funding do not allow to sign by non-owner key:
if (hasNotMypubkey) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "using non-owner inputs not allowed"));
return result;
}
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
// add 1of2 vout validation pubkeys:
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(myPubkey);
voutTokenPubkeys.push_back(heirPubkey);
// for initial funding do not allow to sign by non-owner key:
if (hasNotMypubkey) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "using non-owner inputs not allowed"));
return result;
}
// add 1of2 vout token validation pubkeys - used only for tokens
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(myPubkey);
voutTokenPubkeys.push_back(heirPubkey);
// add change for txfee and opreturn vouts and sign tx:
std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee,
Helper::makeCreateOpRet(tokenid, voutTokenPubkeys, myPubkey, heirPubkey, inactivityTimeSec, heirName, memo));
if (!rawhextx.empty()) {
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", rawhextx));
}
else {
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "sign error"));
}
// add change for txfee and opreturn vouts and sign tx:
std::string rawhextx = FinalizeCCTx(0, cp, mtx, myPubkey, txfee,
Helper::makeCreateOpRet(tokenid, voutTokenPubkeys, myPubkey, heirPubkey, inactivityTimeSec, heirName, memo));
if (!rawhextx.empty()) {
result.push_back(Pair("result", "success"));
result.push_back(Pair("hex", rawhextx));
}
else { // TODO: need result return unification with heiradd and claim
std::cerr << "HeirFund() could not find owner cc inputs" << std::endl;
else {
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "could not find owner cc inputs"));
result.push_back(Pair("error", "sign error"));
}
}
else {
std::cerr << "HeirFund() could not find normal inputs" << std::endl;
else { // TODO: need result return unification with heiradd and claim
std::cerr << "HeirFund() could not find owner inputs for amount (normal inputs for coins, cc inputs for tokens)" << std::endl;
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "could not find normal inputs"));
result.push_back(Pair("error", "could not find owner inputs"));
}
return result;
}
@ -716,7 +723,6 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, in
{
UniValue result(UniValue::VOBJ);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
int64_t inputs, CCchange = 0;
struct CCcontract_info *cp, C;
std::string rawhex;
@ -736,89 +742,93 @@ template <class Helper> UniValue _HeirAdd(uint256 fundingtxid, int64_t txfee, in
return result;
}
if (AddNormalinputs(mtx, myPubkey, markerfee, 3) > 0) { // some for marker
int64_t inputs, change;
if ((inputs = Helper::addOwnerInputs(tokenid, mtx, myPubkey, amount, 64)) > 0) { // TODO: why 64 max inputs?
if (!tokenid.IsNull()) // add normals only for tokens
{
if (AddNormalinputs(mtx, myPubkey, txfee + markerfee, 4) < txfee + markerfee)
{
std::cerr << "HeirFund() could not find normal inputs for txfee" << std::endl;
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "could not find normal inputs for txfee"));
return result;
}
}
int64_t inputs;
int64_t addAmount = tokenid.IsNull() ? (txfee + markerfee + amount) : amount; // for coins add txfee markerfee amount in one call
if ((inputs = Helper::addOwnerInputs(tokenid, mtx, myPubkey, addAmount, 64)) >= addAmount) { // TODO: why 64 max inputs?
// we do not use markers anymore - storing data in opreturn is better
// add marker vout:
/* char markeraddr[64];
CPubKey markerpubkey = CCtxidaddr(markeraddr, fundingtxid);
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); // txfee 1, txfee 2 - for miners
std::cerr << "HeirAdd() adding markeraddr=" << markeraddr << '\n'; */
// we do not use markers anymore - storing data in opreturn is better
// add marker vout:
/* char markeraddr[64];
CPubKey markerpubkey = CCtxidaddr(markeraddr, fundingtxid);
mtx.vout.push_back(CTxOut(txfee, CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG)); // txfee 1, txfee 2 - for miners
std::cerr << "HeirAdd() adding markeraddr=" << markeraddr << '\n'; */
// add cryptocondition to spend this funded amount for either pk
mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey));
// add cryptocondition to spend this funded amount for either pk
mtx.vout.push_back(Helper::make1of2Vout(amount, ownerPubkey, heirPubkey));
char markeraddr[64];
CPubKey markerPubkey = CCtxidaddr(markeraddr, fundingtxid);
mtx.vout.push_back(CTxOut(markerfee, CScript() << ParseHex(HexStr(markerPubkey)) << OP_CHECKSIG)); // marker to prevent archiving of the funds add vouts
char markeraddr[64];
CPubKey markerPubkey = CCtxidaddr(markeraddr, fundingtxid);
mtx.vout.push_back(CTxOut(markerfee, CScript() << ParseHex(HexStr(markerPubkey)) << OP_CHECKSIG)); // marker to prevent archiving of the funds add vouts
if (!tokenid.IsNull())
{
int64_t ccChange = 0;
if (inputs > amount)
change = (inputs - amount); // -txfee <-- txfee pays user
ccChange = (inputs - amount); // -txfee <-- txfee pays user
//std::cerr << "HeirAdd() inputs=" << inputs << " amount=" << amount << " txfee=" << txfee << " change=" << change << '\n';
if (change != 0) { // vout[1]
mtx.vout.push_back(Helper::makeUserVout(change, myPubkey));
}
// check owner pubkey in vins
bool hasMypubkey = false;
bool hasNotMypubkey = false;
if (ccChange != 0)
mtx.vout.push_back(Helper::makeUserVout(ccChange, myPubkey));
}
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
// check owner pubkey in vins
bool hasMypubkey = false;
bool hasNotMypubkey = false;
// for additional funding do not allow to sign by both owner and non-owner keys (is this a donation or not?):
if (hasMypubkey && hasNotMypubkey) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "using both owner and non-owner inputs is not allowed"));
return result;
}
CheckVinPubkey(mtx.vin, myPubkey, hasMypubkey, hasNotMypubkey);
// for additional funding do not allow to sign by both owner and non-owner keys (is this a donation or not?):
if (hasMypubkey && hasNotMypubkey) {
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "using both owner and non-owner inputs is not allowed"));
return result;
}
// warn the user he's making a donation if this is all non-owner keys:
if (hasNotMypubkey) {
result.push_back(Pair("result", "warning"));
result.push_back(Pair("warning", "you are about to make a donation to heir fund"));
}
else {
result.push_back(Pair("result", "success"));
}
// warn the user he's making a donation if this is all non-owner keys:
if (hasNotMypubkey) {
result.push_back(Pair("result", "warning"));
result.push_back(Pair("warning", "you are about to make a donation to heir fund"));
}
else {
result.push_back(Pair("result", "success"));
}
// add 1of2 vout validation pubkeys - needed only for tokens:
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(ownerPubkey);
voutTokenPubkeys.push_back(heirPubkey);
// add 1of2 vout validation pubkeys - needed only for tokens:
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(ownerPubkey);
voutTokenPubkeys.push_back(heirPubkey);
// add opreturn 'A' and sign tx: // this txfee ignored
std::string rawhextx = (FinalizeCCTx(0, cp, mtx, myPubkey, txfee,
Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun)));
if (!rawhextx.empty()) {
result.push_back(Pair("hex", rawhextx));
}
else {
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
result.clear();
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "sign error"));
}
// add opreturn 'A' and sign tx:
std::string rawhextx = (FinalizeCCTx(0, cp, mtx, myPubkey, txfee,
Helper::makeAddOpRet(tokenid, voutTokenPubkeys, fundingtxid, hasHeirSpendingBegun)));
if (!rawhextx.empty()) {
result.push_back(Pair("hex", rawhextx));
}
else {
std::cerr << "HeirAdd cannot find owner cc inputs" << std::endl;
else {
std::cerr << "HeirAdd error in FinalizeCCtx" << std::endl;
result.clear();
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "can't find owner cc inputs"));
result.push_back(Pair("error", "sign error"));
}
}
else {
std::cerr << "HeirAdd cannot find normal inputs for tx fee" << std::endl;
std::cerr << "HeirAdd cannot find owner inputs for amount (normal inputs for coins, cc inputs for tokens)" << std::endl;
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "can't find normal inputs for tx fee"));
}
result.push_back(Pair("error", "can't find owner inputs"));
}
return result;
}
@ -833,10 +843,12 @@ UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount
std::string heirName, memo;
uint8_t hasHeirSpendingBegun = 0;
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo, hasHeirSpendingBegun)) != zeroid) {
// get latest tx to see if it is a token or coin
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo, hasHeirSpendingBegun)) != zeroid)
{
if (tokenid == zeroid) {
int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN);
if (amount <= 0) {
int64_t amount = 0;
if (!ParseFixedPoint(strAmount, 8, &amount) || amount <= 0 ) {
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
@ -844,7 +856,8 @@ UniValue HeirAddCaller(uint256 fundingtxid, int64_t txfee, std::string strAmount
}
return _HeirAdd<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, hasHeirSpendingBegun);
}
else {
else
{
int64_t amount = atoll(strAmount.c_str());
if (amount <= 0) {
UniValue result(UniValue::VOBJ);
@ -1003,15 +1016,18 @@ UniValue HeirClaimCaller(uint256 fundingtxid, int64_t txfee, std::string strAmou
std::string heirName, memo;
uint8_t hasHeirSpendingBegun = 0;
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo, hasHeirSpendingBegun)) != zeroid) {
if (tokenid == zeroid) {
int64_t amount = (int64_t)(atof(strAmount.c_str()) * COIN);
if (amount < 0) {
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
return result;
}
// find latest tx to see if it is a token or coin:
if ((latesttxid = FindLatestFundingTx(fundingtxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo, hasHeirSpendingBegun)) != zeroid)
{
if (tokenid == zeroid)
{
int64_t amount = 0;
if (!ParseFixedPoint(strAmount, 8, &amount) || amount <= 0) { // using ParseFixedPoint instead atof to avoid round errors
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result", "error"));
result.push_back(Pair("error", "invalid amount"));
return result;
}
return _HeirClaim<CoinHelper>(fundingtxid, txfee, amount, latesttxid, funcId, tokenid, ownerPubkey, heirPubkey, inactivityTimeSec, hasHeirSpendingBegun);
}
else {

215
src/cc/oracles.cpp

@ -96,13 +96,6 @@ extern int32_t komodo_get_current_height();
#define PUBKEY_SPOOFING_FIX_ACTIVATION 1563148800
#define CC_MARKER_VALUE 10000
int32_t GetLatestTimestamp(int32_t height)
{
if ( KOMODO_NSPV_SUPERLITE ) return (NSPV_blocktime(height));
return(komodo_heightstamp(height));
}
// start of consensus code
CScript EncodeOraclesCreateOpRet(uint8_t funcid,std::string name,std::string description,std::string format)
{
@ -646,9 +639,15 @@ bool OraclesDataValidate(struct CCcontract_info *cp,Eval* eval,const CTransactio
else return(true);
}
/*nt32_t GetLatestTimestamp(int32_t height)
{
if ( KOMODO_NSPV_SUPERLITE ) return (NSPV_blocktime(height));
return(komodo_heightstamp(height));
} */
bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{
uint256 oracletxid,batontxid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; int64_t amount; uint256 hashblock;
uint256 oracletxid,batontxid,txid; uint64_t txfee=10000; int32_t numvins,numvouts,preventCCvins,preventCCvouts; int64_t amount; uint256 hashblock;
uint8_t *script; std::vector<uint8_t> vopret,data; CPubKey publisher,tmppk,oraclespk; char tmpaddress[64],vinaddress[64],oraclesaddr[64];
CTransaction tmptx; std::string name,desc,format;
@ -703,10 +702,16 @@ bool OraclesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
return eval->Invalid("invalid marker for oraclescreate!");
else if ( IsCCInput(tx.vin[0].scriptSig) != 0 )
return eval->Invalid("vin.0 is normal for oraclesregister!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0 || myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 0 && (*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 0)
return eval->Invalid("there is no CC vin from oraclesfund tx");
else if ((*cp->ismyvin)(tx.vin[1].scriptSig) == 1 && (myGetTransaction(tx.vin[1].prevout.hash,tmptx,hashblock)==0 || DecodeOraclesOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,txid,tmppk,amount)!='F'
|| tmptx.vout[tx.vin[1].prevout.n].nValue!=CC_MARKER_VALUE || !Getscriptaddress(vinaddress,tmptx.vout[tx.vin[1].prevout.n].scriptPubKey)
|| !GetCCaddress(cp,tmpaddress,tmppk) || strcmp(tmpaddress,vinaddress)!=0) || oracletxid!=txid)
return eval->Invalid("invalid vin.1 for oraclesregister, it must be CC vin or pubkey not same as vin pubkey, register and fund tx must be done from owner of pubkey that registers to oracle!!");
else if ((*cp->ismyvin)(tx.vin[tx.vin.size()-1].scriptSig) == 1 && (myGetTransaction(tx.vin[tx.vin.size()-1].prevout.hash,tmptx,hashblock)==0 || DecodeOraclesOpRet(tmptx.vout[tmptx.vout.size()-1].scriptPubKey,txid,tmppk,amount)!='F'
|| tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].nValue!=CC_MARKER_VALUE || !Getscriptaddress(vinaddress,tmptx.vout[tx.vin[tx.vin.size()-1].prevout.n].scriptPubKey)
|| !GetCCaddress(cp,tmpaddress,tmppk) || strcmp(tmpaddress,vinaddress)!=0)
return eval->Invalid("vin."+std::to_string(tx.vin.size()-1)+" is CC for oraclesregister or pubkey not same as vin pubkey, register must be done from owner of pubkey that registers to oracle!!");
|| !GetCCaddress(cp,tmpaddress,tmppk) || strcmp(tmpaddress,vinaddress)!=0) || oracletxid!=txid)
return eval->Invalid("invalid vin."+std::to_string(tx.vin.size()-1)+" for oraclesregister, it must be CC vin or pubkey not same as vin pubkey, register and fund tx must be done from owner of pubkey that registers to oracle!!");
else if (CCtxidaddr(tmpaddress,oracletxid).IsValid() && ConstrainVout(tx.vout[0],0,tmpaddress,txfee)==0)
return eval->Invalid("invalid marker for oraclesregister!");
else if (!Getscriptaddress(tmpaddress,CScript() << ParseHex(HexStr(tmppk)) << OP_CHECKSIG) || ConstrainVout(tx.vout[2],0,tmpaddress,CC_MARKER_VALUE)==0)
@ -852,18 +857,20 @@ int64_t AddMyOraclesFunds(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
return (0);
}
std::string OracleCreate(int64_t txfee,std::string name,std::string description,std::string format)
UniValue OracleCreate(const CPubKey& pk, int64_t txfee,std::string name,std::string description,std::string format)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C; char fmt;
CPubKey mypk,Oraclespk; struct CCcontract_info *cp,C; char fmt;
cp = CCinit(&C,EVAL_ORACLES);
if ( name.size() > 32 || description.size() > 4096 || format.size() > 4096 )
{
CCerror = strprintf("name.%d or description.%d is too big",(int32_t)name.size(),(int32_t)description.size());
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if ( name.size() > 32)
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "name."<< (int32_t)name.size() << " must be less then 32");
if (description.size() > 4096)
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "description."<< (int32_t)description.size() << " must be less then 4096");
if (format.size() > 4096 )
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "format."<< (int32_t)format.size() << " must be less then 4096");
if ( name.size() == 0 )
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "name must not be empty");
for(int i = 0; i < format.size(); i++)
{
fmt=format[i];
@ -873,154 +880,125 @@ std::string OracleCreate(int64_t txfee,std::string name,std::string description,
case 'c': case 'C': case 't': case 'T':
case 'i': case 'I': case 'l': case 'L':
case 'h': break;
default: CCerror = strprintf("invalid format type");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
default: CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid format type");
}
}
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
Oraclespk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
if ( AddNormalinputs(mtx,mypk,2*txfee,3,pk.IsValid()) > 0 )
{
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(Oraclespk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesCreateOpRet('C',name,description,format)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesCreateOpRet('C',name,description,format)));
}
CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string OracleFund(int64_t txfee,uint256 oracletxid)
UniValue OracleFund(const CPubKey& pk, int64_t txfee,uint256 oracletxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,oraclespk; struct CCcontract_info *cp,C;
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction tx;
CPubKey mypk,oraclespk; struct CCcontract_info *cp,C; std::string name,desc,format; int32_t numvouts; uint256 hashBlock;
if (GetLatestTimestamp(komodo_get_current_height())<PUBKEY_SPOOFING_FIX_ACTIVATION)
{
CCerror = strprintf("oraclesfund not active yet, activation scheduled for July 15th");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if (GetLatestTimestamp(komodo_currentheight())<PUBKEY_SPOOFING_FIX_ACTIVATION)
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "oraclesfund not active yet, activation scheduled for July 15th");
if (myGetTransaction(oracletxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("oraclecc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex());
if (DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C')
CCERR_RESULT("oraclecc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex());
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2))
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if (AddNormalinputs(mtx,mypk,txfee+CC_MARKER_VALUE,2,pk.IsValid()))
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,mypk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('F',oracletxid,mypk,CC_MARKER_VALUE)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('F',oracletxid,mypk,CC_MARKER_VALUE)));
}
CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string OracleRegister(int64_t txfee,uint256 oracletxid,int64_t datafee)
UniValue OracleRegister(const CPubKey& pk, int64_t txfee,uint256 oracletxid,int64_t datafee)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,markerpubkey,batonpk,oraclespk; struct CCcontract_info *cp,C; char markeraddr[64],batonaddr[64];
std::string name,desc,format; int32_t numvouts; uint256 hashBlock; CTransaction tx;
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
if (myGetTransaction(oracletxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("oraclecc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex());
if (DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C')
CCERR_RESULT("oraclecc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex());
if ( datafee < txfee )
{
CCerror = strprintf("datafee must be txfee or more");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
mypk = pubkey2pk(Mypubkey());
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "datafee must be txfee or more");
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
oraclespk = GetUnspendable(cp,0);
batonpk = OracleBatonPk(batonaddr,cp);
markerpubkey = CCtxidaddr(markeraddr,oracletxid);
if (AddNormalinputs(mtx,mypk,3*txfee,4))
if (AddNormalinputs(mtx,mypk,3*txfee,4,pk.IsValid()))
{
if (GetLatestTimestamp(komodo_get_current_height())>PUBKEY_SPOOFING_FIX_ACTIVATION && AddMyOraclesFunds(cp,mtx,mypk,oracletxid)!=CC_MARKER_VALUE)
{
CCerror = strprintf("error adding inputs from your Oracles CC address, please fund it first with oraclesfund rpc!");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
if (GetLatestTimestamp(komodo_currentheight())>PUBKEY_SPOOFING_FIX_ACTIVATION && AddMyOraclesFunds(cp,mtx,mypk,oracletxid)!=CC_MARKER_VALUE)
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding inputs from your Oracles CC address, please fund it first with oraclesfund rpc!");
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,batonpk));
if (GetLatestTimestamp(komodo_get_current_height())>PUBKEY_SPOOFING_FIX_ACTIVATION) mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('R',oracletxid,mypk,datafee)));
}
CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string OracleSubscribe(int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount)
UniValue OracleSubscribe(const CPubKey& pk, int64_t txfee,uint256 oracletxid,CPubKey publisher,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; char markeraddr[64];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); CTransaction tx;
CPubKey mypk,markerpubkey; struct CCcontract_info *cp,C; char markeraddr[64]; std::string name,desc,format; int32_t numvouts; uint256 hashBlock;
cp = CCinit(&C,EVAL_ORACLES);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
if (myGetTransaction(oracletxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("oraclecc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex());
if (DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,desc,format)!='C')
CCERR_RESULT("oraclecc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
markerpubkey = CCtxidaddr(markeraddr,oracletxid);
if ( AddNormalinputs(mtx,mypk,amount + 2*txfee,64) > 0 )
if ( AddNormalinputs(mtx,mypk,amount + 2*txfee,64,pk.IsValid()) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,publisher));
mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(markerpubkey)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('S',oracletxid,mypk,amount)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesOpRet('S',oracletxid,mypk,amount)));
}
CCerror = strprintf("error adding normal inputs");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector <uint8_t> data)
UniValue OracleData(const CPubKey& pk, int64_t txfee,uint256 oracletxid,std::vector <uint8_t> data)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CScript pubKey; CPubKey mypk,batonpk; int64_t offset,datafee,inputs,CCchange = 0; struct CCcontract_info *cp,C; uint256 batontxid,hashBlock;
char coinaddr[64],batonaddr[64]; std::vector <uint8_t> prevdata; CTransaction tx; std::string name,description,format; int32_t len,numvouts;
cp = CCinit(&C,EVAL_ORACLES);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
if ( data.size() > 8192 )
{
CCerror = strprintf("datasize %d is too big",(int32_t)data.size());
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "datasize " << (int32_t)data.size() << " is too big");
if ( (datafee= OracleDatafee(pubKey,oracletxid,mypk)) <= 0 )
{
CCerror = strprintf("datafee %.8f is illegal",(double)datafee/COIN);
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "datafee " << (double)datafee/COIN << "is illegal");
if ( myGetTransaction(oracletxid,tx,hashBlock) != 0 && (numvouts=tx.vout.size()) > 0 )
{
if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) == 'C' )
{
if (oracle_parse_data_format(data,format)==0)
{
CCerror = strprintf("data does not match length or content format specification");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "data does not match length or content format specification");
}
else
{
CCerror = strprintf("invalid oracle txid opret data");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracle txid opret data");
}
else
{
CCerror = strprintf("invalid oracle txid");
fprintf(stderr,"%s\n", CCerror.c_str() );
return("");
}
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "invalid oracle txid");
if ( txfee == 0 )
txfee = 10000;
GetCCaddress(cp,coinaddr,mypk);
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 ) // have enough funds even if baton utxo not there
if ( AddNormalinputs(mtx,mypk,2*txfee,3,pk.IsValid()) > 0 ) // have enough funds even if baton utxo not there
{
batonpk = OracleBatonPk(batonaddr,cp);
batontxid = OracleBatonUtxo(txfee,cp,oracletxid,batonaddr,mypk,prevdata);
@ -1032,18 +1010,13 @@ std::string OracleData(int64_t txfee,uint256 oracletxid,std::vector <uint8_t> da
if ( inputs > datafee )
CCchange = (inputs - datafee);
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,mypk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,batonpk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CC_MARKER_VALUE,batonpk));
mtx.vout.push_back(CTxOut(datafee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeOraclesData('D',oracletxid,batontxid,mypk,data)));
} else {
CCerror = strprintf("couldnt find enough oracle inputs %s, limit 1 per utxo\n",coinaddr);
fprintf(stderr,"%s\n", CCerror.c_str() );
}
} else {
CCerror = strprintf("couldnt add normal inputs");
fprintf(stderr,"%s\n", CCerror.c_str() );
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodeOraclesData('D',oracletxid,batontxid,mypk,data)));
} else
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "couldnt find enough oracle inputs " << coinaddr << ", limit 1 per utxo");
}
return("");
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "couldnt add normal inputs");
}
UniValue OracleFormat(uint8_t *data,int32_t datalen,char *format,int32_t formatlen)
@ -1097,7 +1070,7 @@ UniValue OracleDataSample(uint256 reforacletxid,uint256 txid)
UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num)
{
UniValue result(UniValue::VOBJ),b(UniValue::VARR); CTransaction tx,oracletx; uint256 txid,hashBlock,btxid,oracletxid;
CPubKey pk; std::string name,description,format; int32_t numvouts,n=0,vout; std::vector<uint8_t> data; char *formatstr = 0;
CPubKey pk; std::string name,description,format; int32_t numvouts,n=0,vout; std::vector<uint8_t> data; char *formatstr = 0, addr[64];
std::vector<uint256> txids; int64_t nValue;
result.push_back(Pair("result","success"));
@ -1111,8 +1084,10 @@ UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num)
{
const CTransaction &txmempool = *it;
const uint256 &hash = txmempool.GetHash();
if ((numvouts=txmempool.vout.size())>0 && DecodeOraclesData(txmempool.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
if ((numvouts=txmempool.vout.size())>0 && txmempool.vout[1].nValue==CC_MARKER_VALUE && DecodeOraclesData(txmempool.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
{
Getscriptaddress(addr,txmempool.vout[1].scriptPubKey);
if (strcmp(addr,batonaddr)!=0) continue;
if ( (formatstr= (char *)format.c_str()) == 0 )
formatstr = (char *)"";
UniValue a(UniValue::VOBJ);
@ -1120,7 +1095,10 @@ UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num)
a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size())));
b.push_back(a);
if ( ++n >= num && num != 0)
break;
{
result.push_back(Pair("samples",b));
return(result);
}
}
}
SetCCtxids(txids,batonaddr,true,EVAL_ORACLES,reforacletxid,'D');
@ -1131,7 +1109,7 @@ UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num)
txid=*it;
if (myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts=tx.vout.size()) > 0 )
{
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
if ( tx.vout[1].nValue==CC_MARKER_VALUE && DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,btxid,pk,data) == 'D' && reforacletxid == oracletxid )
{
if ( (formatstr= (char *)format.c_str()) == 0 )
formatstr = (char *)"";
@ -1140,13 +1118,20 @@ UniValue OracleDataSamples(uint256 reforacletxid,char* batonaddr,int32_t num)
a.push_back(Pair("data",OracleFormat((uint8_t *)data.data(),(int32_t)data.size(),formatstr,(int32_t)format.size())));
b.push_back(a);
if ( ++n >= num && num != 0)
break;
{
result.push_back(Pair("samples",b));
return(result);
}
}
}
}
}
}
else
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex());
}
else
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex());
result.push_back(Pair("samples",b));
return(result);
}
@ -1217,7 +1202,11 @@ UniValue OracleInfo(uint256 origtxid)
}
result.push_back(Pair("registered",a));
}
else
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid oracletxid " << oracletxid.GetHex());
}
else
CCERR_RESULT("oraclescc",CCLOG_INFO, stream << "cant find oracletxid " << oracletxid.GetHex());
return(result);
}

7
src/cc/payments.cpp

@ -89,6 +89,13 @@ int64_t mpz_get_si2( mpz_t op )
return ret;
}
uint64_t mpz_get_ui2( mpz_t op )
{
uint64_t ret = 0;
mpz_export(&ret, NULL, 1, sizeof(ret), 0, 0, op);
return ret;
}
CScript EncodePaymentsTxidOpRet(int64_t allocation,std::vector<uint8_t> scriptPubKey,std::vector<uint8_t> destopret)
{
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;

500
src/cc/pegs.cpp

@ -16,6 +16,8 @@
#include "CCPegs.h"
#include "../importcoin.h"
#include "key_io.h"
#include <gmp.h>
/*
pegs CC is able to create a coin backed (by any supported coin with gateways CC deposits) and pegged to any synthetic price that is able to be calculated based on prices CC
@ -88,9 +90,10 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC
// start of consensus code
#ifndef PEGS_THRESHOLDS
#define PEGS_THRESHOLDS
#define PEGS_ACCOUNT_MAX_DEBT 80
#define PEGS_GLOBAL_RED_ZONE 60
#define PEGS_ACCOUNT_YELLOW_ZONE 60
#define PEGS_ACCOUNT_THRESHOLD 90
#define PEGS_GLOBAL_THRESHOLD 60
#define PEGS_ACCOUNT_RED_ZONE 90
#endif // PEGS_THRESHOLDS
#define CC_MARKER_VALUE 10000
@ -99,6 +102,8 @@ extern uint64_t ASSETCHAINS_PEGSCCPARAMS[3];
extern uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype);
extern int64_t GetTokenBalance(CPubKey pk, uint256 tokenid);
extern int32_t komodo_currentheight();
extern int32_t prices_syntheticvec(std::vector<uint16_t> &vec, std::vector<std::string> synthetic);
extern int64_t prices_syntheticprice(std::vector<uint16_t> vec, int32_t height, int32_t minmax, int16_t leverage);
CScript EncodePegsCreateOpRet(std::vector<uint256> bindtxids)
{
@ -512,21 +517,17 @@ char PegsFindAccount(struct CCcontract_info *cp,CPubKey pk,uint256 pegstxid, uin
else return(0);
}
double PegsGetTokenPrice(uint256 tokenid)
int64_t PegsGetTokenPrice(uint256 tokenid)
{
int64_t *tokensyn,*btcusd; double price; CTransaction tokentx; uint256 hashBlock;
int64_t price; CTransaction tokentx; uint256 hashBlock; std::vector<uint16_t> exp;
std::string name,desc; std::vector<uint8_t> vorigpubkey; int32_t numvouts;
if (myGetTransaction(tokenid,tokentx,hashBlock)!=0 && (numvouts=tokentx.vout.size())>0 && DecodeTokenCreateOpRet(tokentx.vout[numvouts-1].scriptPubKey,vorigpubkey,name,desc)=='c')
{
tokensyn = (int64_t *)calloc(sizeof(*tokensyn) * 3, 1 + PRICES_DAYWINDOW * 2 + PRICES_SMOOTHWIDTH);
btcusd = (int64_t *)calloc(sizeof(*btcusd) * 3, 1 + PRICES_DAYWINDOW * 2 + PRICES_SMOOTHWIDTH);
if (komodo_priceget(tokensyn, komodo_priceind((name+"_BTC").c_str()), komodo_currentheight(), 1) >= 0 && komodo_priceget(btcusd, komodo_priceind("BTC_USD"), komodo_currentheight(), 1) >= 0)
{
price=tokensyn[2]*btcusd[2];
price=price/COIN/COIN;
std::vector<std::string> vexpr;
SplitStr(desc, vexpr);
if (prices_syntheticvec(exp, vexpr)>=0 && (price = prices_syntheticprice(exp, komodo_currentheight(), 0, 1))>=0)
return (price);
}
}
return (0);
}
@ -544,6 +545,34 @@ std::string PegsGetTokenName(uint256 tokenid)
return("");
}
int64_t PegsGetTokensAmountPerPrice(int64_t amount,uint256 tokenid)
{
mpz_t res,a,b;
mpz_init(res);
mpz_init(a);
mpz_init(b);
mpz_set_si(a, amount);
mpz_set_si(b, COIN);
mpz_mul(res, a, b);
mpz_set_si(a, PegsGetTokenPrice(tokenid));
mpz_tdiv_q(res, res, a);
return (mpz_get_si(res));
}
double PegsGetRatio(uint256 tokenid,std::pair<int64_t,int64_t> account)
{
mpz_t res,a,b;
mpz_init(res);
mpz_init(a);
mpz_init(b);
mpz_set_si(a, account.first);
mpz_set_si(b, PegsGetTokenPrice(tokenid));
mpz_mul(res, a, b);
mpz_set_si(a, COIN);
mpz_tdiv_q(res, res, a);
return ((double)account.second)*100/mpz_get_si(res);
}
double PegsGetAccountRatio(uint256 pegstxid,uint256 tokenid,uint256 accounttxid)
{
int64_t amount; uint256 hashBlock,tmptokenid,tmppegstxid;
@ -555,7 +584,7 @@ double PegsGetAccountRatio(uint256 pegstxid,uint256 tokenid,uint256 accounttxid)
(funcid=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid && tokenid==tmptokenid)
{
PegsDecodeAccountTx(tx,pk,amount,account);
return ((double)account.second*100/(account.first*PegsGetTokenPrice(tokenid)));
return PegsGetRatio(tokenid,account);
}
return (0);
}
@ -565,7 +594,7 @@ double PegsGetGlobalRatio(uint256 pegstxid)
char coinaddr[64]; int64_t nValue,amount,globaldebt=0; uint256 txid,accounttxid,hashBlock,tmppegstxid,tokenid;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,pk;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::pair<int64_t,int64_t> account;
std::map<uint256,std::pair<int64_t,int64_t>> globalaccounts; double globaldeposit=0;
std::map<uint256,std::pair<int64_t,int64_t>> globalaccounts;
struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_PEGS);
@ -598,12 +627,29 @@ double PegsGetGlobalRatio(uint256 pegstxid)
globalaccounts[tokenid].first+=nValue;
}
}
mpz_t res,globaldeposit,a,b;
mpz_init(res);
mpz_init(globaldeposit);
mpz_init(a);
mpz_init(b);
mpz_set_si(globaldeposit, 0);
for (std::map<uint256,std::pair<int64_t,int64_t>>::iterator it = globalaccounts.begin(); it != globalaccounts.end(); ++it)
{
globaldeposit+=globalaccounts[it->first].first*PegsGetTokenPrice(it->first);
mpz_set_si(res, 0);
mpz_set_si(a, globalaccounts[it->first].first);
mpz_set_si(b, PegsGetTokenPrice(it->first));
mpz_mul(res,a,b);
mpz_add(globaldeposit,globaldeposit,res);
globaldebt+=globalaccounts[it->first].second;
}
if (globaldebt>0) return ((double)globaldebt*100/globaldeposit);
if (globaldebt>0)
{
mpz_set_si(res, 0);
mpz_set_si(a, COIN);
mpz_tdiv_q(res, globaldeposit, a);
printf("%lu %lu\n",globaldebt,mpz_get_si(res));
return ((double)globaldebt)*100/mpz_get_si(res);
}
return (0);
}
@ -643,7 +689,7 @@ std::string PegsFindBestAccount(struct CCcontract_info *cp,uint256 pegstxid, uin
else return("");
}
std::string PegsCreate(uint64_t txfee,int64_t amount, std::vector<uint256> bindtxids)
UniValue PegsCreate(const CPubKey& pk,uint64_t txfee,int64_t amount, std::vector<uint256> bindtxids)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,pegspk; struct CCcontract_info *cp,C; CTransaction tx; int32_t numvouts; int64_t totalsupply; std::string coin;
@ -652,34 +698,24 @@ std::string PegsCreate(uint64_t txfee,int64_t amount, std::vector<uint256> bindt
cp = CCinit(&C,EVAL_PEGS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
for(auto txid : bindtxids)
{
if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex());
if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B')
{
CCerror = strprintf("invalid bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex());
}
if ( AddNormalinputs(mtx,mypk,amount,64) >= amount )
if ( AddNormalinputs(mtx,mypk,amount,64,pk.IsValid()) >= amount )
{
for (int i=0; i<100; i++) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,(amount-txfee)/100,pegspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsCreateOpRet(bindtxids)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsCreateOpRet(bindtxids)));
}
CCerror = strprintf("error adding normal inputs");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "error adding normal inputs");
}
std::string PegsFund(uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t amount)
UniValue PegsFund(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin;
CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,balance=0,funds=0,tokenfunds=0; uint256 accounttxid=zeroid,hashBlock,txid,tmptokenid,oracletxid;
@ -690,35 +726,18 @@ std::string PegsFund(uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t am
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find pegstxid %s",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
{
CCerror = strprintf("invalid pegstxid ",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
for(auto txid : bindtxids)
{
if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex());
if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B')
{
CCerror = strprintf("invalid bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex());
if (tmptokenid==tokenid)
{
found=true;
@ -726,21 +745,13 @@ std::string PegsFund(uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t am
}
}
if (!found)
{
CCerror = strprintf("invalid tokenid ",tokenid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex());
if ((balance=GetTokenBalance(mypk,tokenid))>=amount)
{
PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account);
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0)
{
CCerror = strprintf("previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed");
if (accounttxid!=zeroid && (funds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee)
{
funds+=2*CC_MARKER_VALUE;
@ -763,23 +774,16 @@ std::string PegsFund(uint64_t txfee,uint256 pegstxid, uint256 tokenid,int64_t am
if (funds>txfee+2*CC_MARKER_VALUE) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,funds-(txfee+2*CC_MARKER_VALUE),pegspk));
account.first+=amount;
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsFundOpRet(tokenid,pegstxid,mypk,amount,account)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsFundOpRet(tokenid,pegstxid,mypk,amount,account)));
}
}
else
{
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream <<"not enough balance in pegs global CC address");
}
CCerror = strprintf("not enough balance (%lld) for this amount of tokens %lld",balance,amount);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance (" << balance << ") for this amount of tokens " << amount);
}
std::string PegsGet(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount)
UniValue PegsGet(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount)
{
CMutableTransaction burntx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()),mtx;
CTransaction pegstx,tx; int32_t numvouts; int64_t funds=0; uint256 accounttxid=zeroid,hashBlock,pricestxid; char coinaddr[64];
@ -789,32 +793,16 @@ std::string PegsGet(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t am
cp = CCinit(&C,EVAL_PEGS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find pegstxid %s",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
{
CCerror = strprintf("invalid pegstxid ",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account)==0)
{
CCerror = strprintf("cannot find account from which to issue coins, fund account first with pegsfund!");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account from which to issue coins, fund account first with pegsfund!");
if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0)
{
CCerror = strprintf("previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
// spending markers
vouts.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk));
@ -822,6 +810,12 @@ std::string PegsGet(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t am
// coin issue
vouts.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
account.second+=amount;
if (PegsGetRatio(tokenid,account)>PEGS_ACCOUNT_MAX_DEBT)
{
CCerror = strprintf("not possible to take more than %d%% of the deposit",PEGS_ACCOUNT_MAX_DEBT);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
// burn tx does not exist in pegs method but it must be created in order for import validation to pass
// fictive burntx input of previous account state tx
@ -836,12 +830,12 @@ std::string PegsGet(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t am
Myprivkey(mypriv);
GetCCaddress1of2(cp,coinaddr,mypk,pegspk);
CCaddr1of2set(cp,mypk,pegspk,mypriv,coinaddr);
std::string retstr = FinalizeCCTx(0,cp,mtx,mypk,txfee,opret);
UniValue retstr = FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,opret);
memset(mypriv,0,sizeof(mypriv));
return(retstr);
}
std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid)
UniValue PegsRedeem(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin;
CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,amount; uint256 accounttxid=zeroid,hashBlock,txid,tmptokenid,oracletxid;
@ -852,34 +846,18 @@ std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid)
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find pegstxid %s",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
{
CCerror = strprintf("invalid pegstxid ",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
for(auto txid : bindtxids)
{
if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex());
if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B')
{
CCerror = strprintf("invalid bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex());
if (tmptokenid==tokenid)
{
found=true;
@ -887,25 +865,13 @@ std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid)
}
}
if (!found)
{
CCerror = strprintf("invalid tokenid ",tokenid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex());
if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account)==0)
{
CCerror = strprintf("cannot find account from which to redeem tokens!");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account from which to redeem tokens!");
if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0)
{
CCerror = strprintf("previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
if ((funds=AddNormalinputs(mtx,mypk,account.second,64))>=account.second )
if ((funds=AddNormalinputs(mtx,mypk,account.second,64,pk.IsValid()))>=account.second )
{
if (accounttxid!=zeroid && (pegsfunds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee)
{
@ -928,39 +894,31 @@ std::string PegsRedeem(uint64_t txfee,uint256 pegstxid, uint256 tokenid)
account.first=0;
account.second=0;
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
std::string retstr = FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsReedemOpRet(tokenid,pegstxid,mypk,amount,account));
UniValue retstr = FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsReedemOpRet(tokenid,pegstxid,mypk,amount,account));
memset(mypriv,0,32);
return(retstr);
}
else
{
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
memset(mypriv,0,32);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address");
}
}
CCerror = strprintf("not enough tokens in pegs account (%lld) to redeem this amount of tokens %lld",tokenfunds,account.first);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
memset(mypriv,0,32);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough tokens in pegs account (" << tokenfunds << ") to redeem this amount of tokens " << account.first);
}
else
{
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
memset(mypriv,0,32);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address");
}
}
CCerror = strprintf("to redeem from account and close it you must redeem full debt ammount %lld instead of %lld",account.second,funds);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
memset(mypriv,0,32);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "to redeem from account and close it you must redeem full debt ammount " << account.second << " instead of " << funds);
}
std::string PegsExchange(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount)
UniValue PegsExchange(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64_t amount)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin;
CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,tokenamount,tmpamount; uint256 accounttxid=zeroid,hashBlock,txid,tmptokenid,oracletxid;
@ -971,34 +929,18 @@ std::string PegsExchange(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find pegstxid %s",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
{
CCerror = strprintf("invalid pegstxid ",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
for(auto txid : bindtxids)
{
if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex());
if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B')
{
CCerror = strprintf("invalid bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex());
if (tmptokenid==tokenid)
{
found=true;
@ -1006,43 +948,23 @@ std::string PegsExchange(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64
}
}
if (!found)
{
CCerror = strprintf("invalid tokenid ",tokenid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex());
if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,account)!=0)
{
CCerror = strprintf("you have active account, please close account first before exchanging other coins!");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ((funds=AddNormalinputs(mtx,mypk,amount,64))>=amount )
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "you have active account, please close account first before exchanging other coins!");
if ((funds=AddNormalinputs(mtx,mypk,amount,64,pk.IsValid()))>=amount )
{
if ((pegsfunds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee)
{
tokenamount=amount/PegsGetTokenPrice(tokenid);
tokenamount=PegsGetTokensAmountPerPrice(amount,tokenid);
tokenfunds=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,pegspk,CPubKey(),tokenamount,64);
if (tokenfunds<tokenamount)
{
if (PegsFindBestAccount(cp,pegstxid,tokenid,tokenamount-tokenfunds,accounttxid,account).empty())
{
CCerror = strprintf("cannot find account from which to get tokens for exchange!");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account from which to get tokens for exchange!");
if (accounttxid!=zeroid && myGetTransaction(accounttxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0 || PegsDecodeAccountTx(tx,tmppk,tmpamount,account).empty())
{
CCerror = strprintf("invalid account tx from which to exchange coins to tokens %s!",accounttxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid account tx from which to exchange coins to tokens " << accounttxid.GetHex());
if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0)
{
CCerror = strprintf("previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed");
tokenfunds+=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,tmppk,pegspk,tokenamount,64);
mtx.vin.push_back(CTxIn(accounttxid,0,CScript()));
mtx.vin.push_back(CTxIn(accounttxid,1,CScript()));
@ -1070,35 +992,23 @@ std::string PegsExchange(uint64_t txfee,uint256 pegstxid, uint256 tokenid, int64
}
else if (pegsfunds>txfee) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,pegsfunds-txfee,pegspk));
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "modified account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsExchangeOpRet(tokenid,pegstxid,mypk,tmppk,amount,account)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsExchangeOpRet(tokenid,pegstxid,mypk,tmppk,amount,account)));
}
else
{
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address");
}
CCerror = strprintf("not enough tokens in pegs account (%lld) to exchange to this amount of tokens %lld",tokenfunds,tokenamount);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough tokens in pegs account (" << tokenfunds << ") to exchange to this amount of tokens " << tokenamount);
}
else
{
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address");
}
CCerror = strprintf("not enough funds to exchange %lld coins to tokens - balance %lld",amount,funds);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough funds to exchange " << amount << " coins to tokens - balance " << funds);
}
std::string PegsLiquidate(uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid)
UniValue PegsLiquidate(const CPubKey& pk,uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint256 liquidatetxid)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string coin;
CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,amount,burnamount;
CTransaction pegstx,tx; int32_t numvouts; int64_t totalsupply,pegsfunds=0,funds=0,tokenfunds=0,amount,tmpamount,tokenamount,burnamount;
CPubKey mypk,pegspk,tmppk; struct CCcontract_info *cp,*cpTokens,CTokens,C; char depositaddr[64],coinaddr[64]; std::pair <int64_t,int64_t> account(0,0),myaccount(0,0);
uint8_t M,N,taddr,prefix,prefix2,wiftype; std::vector<CPubKey> pubkeys; bool found=false; std::vector<uint256> bindtxids;
uint256 hashBlock,txid,tmptokenid,oracletxid,accounttxid;
@ -1107,34 +1017,18 @@ std::string PegsLiquidate(uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint
cpTokens = CCinit(&CTokens,EVAL_TOKENS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find pegstxid %s",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
{
CCerror = strprintf("invalid pegstxid ",pegstxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
for(auto txid : bindtxids)
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
for(auto txid : bindtxids)
{
if (myGetTransaction(txid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("cant find bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find bindtxid " << txid.GetHex());
if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tmptokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype)!='B')
{
CCerror = strprintf("invalid bindtxid %s",txid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid bindtxid " << txid.GetHex());
if (tmptokenid==tokenid)
{
found=true;
@ -1142,45 +1036,23 @@ std::string PegsLiquidate(uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint
}
}
if (!found)
{
CCerror = strprintf("invalid tokenid ",tokenid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid tokenid " << tokenid.GetHex());
if (PegsFindAccount(cp,mypk,pegstxid,tokenid,accounttxid,myaccount)==0)
{
CCerror = strprintf("cannot find account, you must have an account to liquidate another account!");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account, you must have an account to liquidate another account!");
if (accounttxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,accounttxid,1) != 0)
{
CCerror = strprintf("previous account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (PegsGetAccountRatio(pegstxid,tokenid,liquidatetxid)<(ASSETCHAINS_PEGSCCPARAMS[0]?ASSETCHAINS_PEGSCCPARAMS[0]:PEGS_ACCOUNT_THRESHOLD) || PegsGetGlobalRatio(pegstxid)<(ASSETCHAINS_PEGSCCPARAMS[1]?ASSETCHAINS_PEGSCCPARAMS[1]:PEGS_GLOBAL_THRESHOLD))
{
CCerror = strprintf("not able to liquidate account until account ratio > %lu%% and global ratio > %lu%%",(ASSETCHAINS_PEGSCCPARAMS[0]?ASSETCHAINS_PEGSCCPARAMS[0]:PEGS_ACCOUNT_THRESHOLD),(ASSETCHAINS_PEGSCCPARAMS[1]?ASSETCHAINS_PEGSCCPARAMS[1]:PEGS_GLOBAL_THRESHOLD));
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous account tx not yet confirmed");
if (PegsGetAccountRatio(pegstxid,tokenid,liquidatetxid)<(ASSETCHAINS_PEGSCCPARAMS[0]?ASSETCHAINS_PEGSCCPARAMS[0]:PEGS_ACCOUNT_RED_ZONE) || PegsGetGlobalRatio(pegstxid)<(ASSETCHAINS_PEGSCCPARAMS[1]?ASSETCHAINS_PEGSCCPARAMS[1]:PEGS_ACCOUNT_RED_ZONE))
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not able to liquidate account until account ratio > " << (ASSETCHAINS_PEGSCCPARAMS[0]?ASSETCHAINS_PEGSCCPARAMS[0]:PEGS_ACCOUNT_RED_ZONE) << "% and global ratio > " << (ASSETCHAINS_PEGSCCPARAMS[1]?ASSETCHAINS_PEGSCCPARAMS[1]:PEGS_ACCOUNT_RED_ZONE) << "%");
if (liquidatetxid!=zeroid && myGetTransaction(liquidatetxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0 || PegsDecodeAccountTx(tx,tmppk,amount,account).empty())
{
CCerror = strprintf("cannot find account to liquidate or invalid tx %s!",liquidatetxid.GetHex());
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cannot find account to liquidate or invalid tx " << liquidatetxid.GetHex());
if (liquidatetxid!=zeroid && myIsutxo_spentinmempool(ignoretxid,ignorevin,liquidatetxid,1) != 0)
{
CCerror = strprintf("previous liquidate account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "previous liquidate account tx not yet confirmed");
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "current accounttxid=" << accounttxid.GetHex() << " [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
amount=account.first;
burnamount=account.second*0.9;
if ((funds=AddNormalinputs(mtx,mypk,txfee+account.second,64))>=txfee+burnamount)
tokenamount=account.first;
burnamount=account.second;
tmpamount=PegsGetTokensAmountPerPrice(burnamount,tokenid)*105/100;
amount=tmpamount+((tokenamount-tmpamount)*10/100);
if ((funds=AddNormalinputs(mtx,mypk,account.second,64))>=burnamount)
{
if (liquidatetxid!=zeroid && (pegsfunds=AddPegsInputs(cp,mtx,pegspk,CPubKey(),txfee,1))>=txfee)
{
@ -1189,49 +1061,45 @@ std::string PegsLiquidate(uint64_t txfee,uint256 pegstxid, uint256 tokenid, uint
mtx.vin.push_back(CTxIn(liquidatetxid,1,CScript()));
GetCCaddress1of2(cp,coinaddr,tmppk,pegspk);
CCaddr1of2set(cp,tmppk,pegspk,cp->CCpriv,coinaddr);
if ((tokenfunds=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,tmppk,pegspk,amount,64))==amount)
if ((tokenfunds=AddPegsTokenInputs(cp,mtx,pegstxid,tokenid,tmppk,pegspk,tokenamount,64))==tokenamount)
{
if (pegsfunds>=txfee+2*CC_MARKER_VALUE)
{
mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,pegspk,pegspk));
mtx.vout.push_back(MakeCC1of2vout(EVAL_PEGS,CC_MARKER_VALUE,tmppk,pegspk));
mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS,(int64_t)(amount*0.95),mypk));
mtx.vout.push_back(MakeTokensCC1vout(EVAL_PEGS,amount-(int64_t)(amount*0.95),pegspk));
mtx.vout.push_back(MakeTokensCC1vout(EVAL_TOKENS,amount,mypk));
mtx.vout.push_back(MakeTokensCC1vout(EVAL_PEGS,tokenamount-amount,pegspk));
mtx.vout.push_back(CTxOut(burnamount,CScript() << ParseHex(HexStr(CCtxidaddr(coinaddr,pegstxid))) << OP_CHECKSIG));
if (pegsfunds>txfee+2*CC_MARKER_VALUE) mtx.vout.push_back(MakeCC1vout(EVAL_PEGS,pegsfunds-(txfee+2*CC_MARKER_VALUE),pegspk));
account.first=0;
account.second=0;
LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "new account [deposit=" << account.first << ",debt=" << account.second << "]" << std::endl);
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodePegsLiquidateOpRet(tokenid,pegstxid,mypk,amount,account)));
return(FinalizeCCTxExt(pk.IsValid(),0,cp,mtx,mypk,txfee,EncodePegsLiquidateOpRet(tokenid,pegstxid,mypk,amount,account)));
}
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address");
}
CCerror = strprintf("tokens amount in pegs account (%lld) not matching amount in account %lld",tokenfunds,account.first); // this shouldn't happen
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "tokens amount in pegs account " << tokenfunds << " not matching amount in account " << account.first); // this shouldn't happen
}
CCerror = strprintf("not enough balance in pegs global CC address");
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough balance in pegs global CC address");
}
CCerror = strprintf("not enough funds to liquidate account, you must liquidate full debt ammount %lld instead of %lld",txfee+account.second,funds);
LOGSTREAM("pegscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "not enough funds to liquidate account, you must liquidate full debt ammount " << txfee+account.second << " instead of " << funds);
}
UniValue PegsAccountHistory(uint256 pegstxid)
UniValue PegsAccountHistory(const CPubKey& pk,uint256 pegstxid)
{
char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmptokenid,tmppegstxid;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,pk; std::map<uint256,std::pair<int64_t,int64_t>> accounts;
std::vector<uint256> txids; std::pair<int64_t,int64_t> account;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,tmppk; std::map<uint256,std::pair<int64_t,int64_t>> accounts;
std::vector<uint256> txids; std::pair<int64_t,int64_t> account; std::vector<uint256> bindtxids;
UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C;
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
result.push_back(Pair("result","success"));
result.push_back(Pair("name","pegsaccounthistory"));
cp = CCinit(&C,EVAL_PEGS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,mypk,pegspk);
SetCCtxids(txids,coinaddr,true,EVAL_PEGS,pegstxid,0);
@ -1242,7 +1110,7 @@ UniValue PegsAccountHistory(uint256 pegstxid)
(funcid=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid)
{
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("action",PegsDecodeAccountTx(tx,pk,amount,account)));
obj.push_back(Pair("action",PegsDecodeAccountTx(tx,tmppk,amount,account)));
obj.push_back(Pair("amount",amount));
obj.push_back(Pair("accounttxid",txid.GetHex()));
obj.push_back(Pair("token",PegsGetTokenName(tmptokenid)));
@ -1255,17 +1123,21 @@ UniValue PegsAccountHistory(uint256 pegstxid)
return(result);
}
UniValue PegsAccountInfo(uint256 pegstxid)
UniValue PegsAccountInfo(const CPubKey& pk,uint256 pegstxid)
{
char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmptokenid,tmppegstxid; std::map<uint256,std::pair<int64_t,int64_t>> accounts;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,pk;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,tmppk; std::vector<uint256> bindtxids;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::pair<int64_t,int64_t> account;
UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C;
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
result.push_back(Pair("result","success"));
result.push_back(Pair("name","pegsaccountinfo"));
cp = CCinit(&C,EVAL_PEGS);
mypk = pubkey2pk(Mypubkey());
mypk = pk.IsValid()?pk:pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,mypk,pegspk);
SetCCunspents(unspentOutputs,coinaddr,true);
@ -1279,7 +1151,7 @@ UniValue PegsAccountInfo(uint256 pegstxid)
(funcid=DecodePegsOpRet(tx,tmppegstxid,tmptokenid))!=0 && pegstxid==tmppegstxid)
{
//LOGSTREAM("pegscc",CCLOG_DEBUG2, stream << "txid=" << txid.GetHex() << ", vout=" << vout << ", nValue=" << nValue << ", tokenid=" << tmptokenid.GetHex() << std::endl);
PegsDecodeAccountTx(tx,pk,amount,account);
PegsDecodeAccountTx(tx,tmppk,amount,account);
accounts[tmptokenid].first=account.first;
accounts[tmptokenid].second=account.second;
}
@ -1288,10 +1160,10 @@ UniValue PegsAccountInfo(uint256 pegstxid)
{
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("token",PegsGetTokenName(it->first)));
obj.push_back(Pair("deposit",(double)accounts[it->first].first/COIN));
obj.push_back(Pair("debt",(double)accounts[it->first].second/COIN));
if (accounts[it->first].first==0 || accounts[it->first].second==0 || PegsGetTokenPrice(it->first)==0) obj.push_back(Pair("ratio",0));
else obj.push_back(Pair("ratio",strprintf("%.2f%%",(double)accounts[it->first].second*100/(accounts[it->first].first*PegsGetTokenPrice(it->first)))));
obj.push_back(Pair("deposit",accounts[it->first].first));
obj.push_back(Pair("debt",accounts[it->first].second));
if (accounts[it->first].first==0 || accounts[it->first].second==0 || PegsGetTokenPrice(it->first)<=0) obj.push_back(Pair("ratio",0));
else obj.push_back(Pair("ratio",strprintf("%.2f%%",PegsGetRatio(it->first,accounts[it->first]))));
acc.push_back(obj);
}
result.push_back(Pair("account info",acc));
@ -1301,14 +1173,17 @@ UniValue PegsAccountInfo(uint256 pegstxid)
UniValue PegsWorstAccounts(uint256 pegstxid)
{
char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmppegstxid,tokenid,prev;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,pk; double ratio;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey pegspk,pk; double ratio; std::vector<uint256> bindtxids;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::pair<int64_t,int64_t> account;
UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C; std::multimap<uint256,UniValue> map;
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
result.push_back(Pair("result","success"));
result.push_back(Pair("name","pegsworstaccounts"));
cp = CCinit(&C,EVAL_PEGS);
mypk = pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,pegspk,pegspk);
SetCCunspents(unspentOutputs,coinaddr,true);
@ -1321,9 +1196,9 @@ UniValue PegsWorstAccounts(uint256 pegstxid)
(funcid=DecodePegsOpRet(tx,tmppegstxid,tokenid))!=0 && pegstxid==tmppegstxid)
{
PegsDecodeAccountTx(tx,pk,amount,account);
if (account.first==0 || account.second==0 || PegsGetTokenPrice(tokenid)==0) ratio=0;
else ratio=(double)account.second*100/(account.first*PegsGetTokenPrice(tokenid));
if (ratio>80)
if (account.first==0 || account.second==0 || PegsGetTokenPrice(tokenid)<=0) ratio=0;
else ratio=PegsGetRatio(tokenid,account);
if (ratio>PEGS_ACCOUNT_RED_ZONE)
{
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("accounttxid",txid.GetHex()));
@ -1352,15 +1227,18 @@ UniValue PegsWorstAccounts(uint256 pegstxid)
UniValue PegsInfo(uint256 pegstxid)
{
char coinaddr[64]; int64_t nValue,amount; uint256 txid,accounttxid,hashBlock,tmppegstxid,tokenid;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey mypk,pegspk,pk;
CTransaction tx; int32_t numvouts,vout; char funcid; CPubKey pegspk,pk; std::vector<uint256> bindtxids;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs; std::pair<int64_t,int64_t> account;
std::map<uint256,std::pair<int64_t,int64_t>> globalaccounts; double globaldeposit=0;
UniValue result(UniValue::VOBJ),acc(UniValue::VARR); struct CCcontract_info *cp,C;
if (myGetTransaction(pegstxid,tx,hashBlock)==0 || (numvouts=tx.vout.size())<=0)
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "cant find pegstxid " << pegstxid.GetHex());
if (DecodePegsCreateOpRet(tx.vout[numvouts-1].scriptPubKey,bindtxids)!='C')
CCERR_RESULT("pegscc",CCLOG_INFO, stream << "invalid pegstxid " << pegstxid.GetHex());
result.push_back(Pair("result","success"));
result.push_back(Pair("name","pegsinfo"));
cp = CCinit(&C,EVAL_PEGS);
mypk = pubkey2pk(Mypubkey());
pegspk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,pegspk,pegspk);
SetCCunspents(unspentOutputs,coinaddr,true);
@ -1396,8 +1274,8 @@ UniValue PegsInfo(uint256 pegstxid)
obj.push_back(Pair("token",PegsGetTokenName(it->first)));
obj.push_back(Pair("total deposit",globalaccounts[it->first].first));
obj.push_back(Pair("total debt",globalaccounts[it->first].second));
if (globalaccounts[it->first].first==0 || globalaccounts[it->first].second==0 || PegsGetTokenPrice(it->first)==0) obj.push_back(Pair("total ratio",0));
else obj.push_back(Pair("total ratio",strprintf("%.2f%%",(double)globalaccounts[it->first].second*100/(globalaccounts[it->first].first*PegsGetTokenPrice(it->first)))));
if (globalaccounts[it->first].first==0 || globalaccounts[it->first].second==0 || PegsGetTokenPrice(it->first)<=0) obj.push_back(Pair("total ratio",0));
else obj.push_back(Pair("total ratio",strprintf("%.2f%%",PegsGetRatio(it->first,globalaccounts[it->first]))));
acc.push_back(obj);
}
result.push_back(Pair("info",acc));

54
src/cc/rewards.cpp

@ -65,24 +65,62 @@
vout.n-1: opreturn 'U' sbits fundingtxid
*/
int64_t RewardsCalc(int64_t amount,uint256 txid,uint64_t APR,uint64_t minseconds,uint64_t maxseconds,uint64_t mindeposit)
/// the following are compatible with windows
/// mpz_set_lli sets a long long singed int to a big num mpz_t for very large integer math
extern void mpz_set_lli( mpz_t rop, long long op );
// mpz_get_si2 gets a mpz_t and returns a signed long long int
extern int64_t mpz_get_si2( mpz_t op );
// mpz_get_ui2 gets a mpz_t and returns a unsigned long long int
extern uint64_t mpz_get_ui2( mpz_t op );
uint64_t RewardsCalc(int64_t amount, uint256 txid, int64_t APR, int64_t minseconds, int64_t maxseconds, uint32_t timestamp)
{
int32_t numblocks; uint64_t duration,reward = 0;
int32_t numblocks; int64_t duration; uint64_t reward = 0;
//fprintf(stderr,"minseconds %llu maxseconds %llu\n",(long long)minseconds,(long long)maxseconds);
if ( (duration= CCduration(numblocks,txid)) < minseconds )
{
fprintf(stderr,"duration %llu < minseconds %llu\n",(long long)duration,(long long)minseconds);
fprintf(stderr,"duration %lli < minseconds %lli\n",(long long)duration,(long long)minseconds);
return(0);
//duration = (uint32_t)time(NULL) - (1532713903 - 3600 * 24);
} else if ( duration > maxseconds )
duration = maxseconds;
if ( 0 ) // amount * APR * duration / COIN * 100 * 365*24*3600
/* if ( 0 ) // amount * APR * duration / COIN * 100 * 365*24*3600
reward = (((amount * APR) / COIN) * duration) / (365*24*3600LL * 100);
else reward = (((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000)) / 10000;
*/
if ( !komodo_hardfork_active(timestamp) )
reward = (((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000)) / 10000;
else
{
// declare and init the mpz_t big num variables
mpz_t mpzAmount, mpzDuration, mpzReward, mpzAPR, mpzModifier;
mpz_init(mpzAmount);
mpz_init(mpzDuration);
mpz_init(mpzAPR);
mpz_init(mpzReward);
mpz_init(mpzModifier);
// set the inputs to big num variables
mpz_set_lli(mpzAmount, amount);
mpz_set_lli(mpzDuration, duration);
mpz_set_lli(mpzAPR, APR);
mpz_set_lli(mpzModifier, COIN*100*365*24*3600LL);
// (amount * APR * duration)
mpz_mul(mpzReward, mpzAmount, mpzDuration);
mpz_mul(mpzReward, mpzReward, mpzAPR);
// total_of_above / (COIN * 100 * 365*24*3600LL)
mpz_tdiv_q(mpzReward, mpzReward, mpzModifier);
// set result to variable we can use and return it.
reward = mpz_get_ui2(mpzReward);
}
if ( reward > amount )
reward = amount;
fprintf(stderr,"amount %.8f %.8f %llu -> duration.%llu reward %.8f vals %.8f %.8f\n",(double)amount/COIN,((double)amount * APR)/COIN,(long long)((amount * APR) / (COIN * 365*24*3600)),(long long)duration,(double)reward/COIN,(double)((amount * duration) / (365 * 24 * 3600LL))/COIN,(double)(((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000))/COIN);
fprintf(stderr, "amount.%lli duration.%lli APR.%lli reward.%llu\n", (long long)amount, (long long)duration, (long long)APR, (long long)reward);
//fprintf(stderr,"amount %.8f %.8f %llu -> duration.%llu reward %.8f vals %.8f %.8f\n",(double)amount/COIN,((double)amount * APR)/COIN,(long long)((amount * APR) / (COIN * 365*24*3600)),(long long)duration,(double)reward/COIN,(double)((amount * duration) / (365 * 24 * 3600LL))/COIN,(double)(((amount * duration) / (365 * 24 * 3600LL)) * (APR / 1000000))/COIN);
return(reward);
}
@ -259,7 +297,7 @@ bool RewardsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &t
if ( !CheckTxFee(tx, txfee, chainActive.LastTip()->GetHeight(), chainActive.LastTip()->nTime, dummy) )
return eval->Invalid("txfee is too high");
amount = vinTx.vout[0].nValue;
reward = RewardsCalc(amount,tx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
reward = RewardsCalc((int64_t)amount,tx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,GetLatestTimestamp(eval->GetCurrentHeight()));
if ( reward == 0 )
return eval->Invalid("no eligible rewards");
if ( numvins == 1 && tx.vout[0].scriptPubKey.IsPayToCryptoCondition() == 0 )
@ -671,7 +709,7 @@ std::string RewardsUnlock(uint64_t txfee,char *planstr,uint256 fundingtxid,uint2
}
if ( amount > txfee )
{
reward = RewardsCalc(amount,mtx.vin[0].prevout.hash,APR,minseconds,maxseconds,mindeposit);
reward = RewardsCalc((int64_t)amount,mtx.vin[0].prevout.hash,(int64_t)APR,(int64_t)minseconds,(int64_t)maxseconds,komodo_chainactive_timestamp());
if ( scriptPubKey.size() > 0 )
{
if ( reward > txfee )

Loading…
Cancel
Save