diff --git a/qa/rpc-tests/cryptoconditions_oracles.py b/qa/rpc-tests/cryptoconditions_oracles.py index f295bf020..048b577d1 100755 --- a/qa/rpc-tests/cryptoconditions_oracles.py +++ b/qa/rpc-tests/cryptoconditions_oracles.py @@ -112,17 +112,15 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework): # baton oraclesdata_d = self.send_and_mine(result["hex"], rpc) result = rpc.oraclessamples(globals()["oracle_{}".format("d")], oraclesdata_d, "1") - # TODO: working not correct now! - #assert_equal("[u'01']", str(result["samples"][0]), "Data match") + assert_equal("[u'01']", str(result["samples"][0]), "Data match") # D type - result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "0101") + result = rpc.oraclesdata(globals()["oracle_{}".format("D")], "010001") assert_success(result) # baton oraclesdata_D = self.send_and_mine(result["hex"], rpc) result = rpc.oraclessamples(globals()["oracle_{}".format("D")], oraclesdata_D, "1") - # TODO: working not correct now! - #assert_equal("[u'01']", str(result["samples"][0]), "Data match") + assert_equal("[u'01']", str(result["samples"][0]), "Data match") # c type result = rpc.oraclesdata(globals()["oracle_{}".format("c")], "ff") @@ -198,12 +196,12 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework): assert_equal("[u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match") # Ihh type - result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff") + result = rpc.oraclesdata(globals()["oracle_{}".format("Ihh")], "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff") assert_success(result) # baton oraclesdata_Ihh = self.send_and_mine(result["hex"], rpc) result = rpc.oraclessamples(globals()["oracle_{}".format("Ihh")], oraclesdata_Ihh, "1") - assert_equal("[u'0']", str(result["samples"][0]), "Data match") + assert_equal("[u'4294967295', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000', u'ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000']", str(result["samples"][0]), "Data match") def run_test(self): diff --git a/src/cc/CCMarmara.h b/src/cc/CCMarmara.h index 45fda83bd..8fbe25b62 100644 --- a/src/cc/CCMarmara.h +++ b/src/cc/CCMarmara.h @@ -18,6 +18,15 @@ #define CC_TRIGGERS_H #include "CCinclude.h" +#include "../komodo_cJSON.h" + +#define MARMARA_GROUPSIZE 60 +#define MARMARA_MINLOCK (1440 * 3 * 30) +#define MARMARA_MAXLOCK (1440 * 24 * 30) +uint64_t komodo_block_prg(uint32_t nHeight); +UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr); // [[pk0, shares0], [pk1, shares1], ...] +UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 createtxid); +UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 createtxid); bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn); diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 0906a57c6..aaeadcc61 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -187,5 +187,6 @@ bits256 curve25519_basepoint9(); bits256 curve25519(bits256 mysecret,bits256 basepoint); void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); bits256 bits256_doublesha256(char *deprecated,uint8_t *data,int32_t datalen); +UniValue ValueFromAmount(const CAmount& amount); #endif diff --git a/src/cc/auction.cpp b/src/cc/auction.cpp index 70bc64379..0858facfa 100644 --- a/src/cc/auction.cpp +++ b/src/cc/auction.cpp @@ -73,7 +73,7 @@ bool AuctionExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransactio bool AuctionValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; - return(false); // reject any auction CC for now + return eval->Invalid("no validation yet"); numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index f2caa508f..18df5cd2c 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -38,8 +38,9 @@ bool RunCCEval(const CC *cond, const CTransaction &tx, unsigned int nIn) pthread_mutex_lock(&KOMODO_CC_mutex); bool out = eval->Dispatch(cond, tx, nIn); pthread_mutex_unlock(&KOMODO_CC_mutex); - //fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); - assert(eval->state.IsValid() == out); + if ( eval->state.IsValid() != out) + fprintf(stderr,"out %d vs %d isValid\n",(int32_t)out,(int32_t)eval->state.IsValid()); + //assert(eval->state.IsValid() == out); if (eval->state.IsValid()) return true; diff --git a/src/cc/fsm.cpp b/src/cc/fsm.cpp index 04ca1d5a0..0bcc61a1b 100644 --- a/src/cc/fsm.cpp +++ b/src/cc/fsm.cpp @@ -75,7 +75,7 @@ bool FSMExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &t bool FSMValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; - return(false); // reject any FSM CC for now + return eval->Invalid("no validation yet"); numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; diff --git a/src/cc/heir.cpp b/src/cc/heir.cpp index 5caa6594a..44f01a8a4 100644 --- a/src/cc/heir.cpp +++ b/src/cc/heir.cpp @@ -74,7 +74,7 @@ bool HeirExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction & bool HeirValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); diff --git a/src/cc/lotto.cpp b/src/cc/lotto.cpp index 7b44a99b7..e9c263ff1 100644 --- a/src/cc/lotto.cpp +++ b/src/cc/lotto.cpp @@ -115,7 +115,7 @@ bool LottoExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction bool LottoValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i; bool retval; - return(false); // reject any lotto CC for now + return eval->Invalid("no validation yet"); numvins = tx.vin.size(); numvouts = tx.vout.size(); preventCCvins = preventCCvouts = -1; diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp index 4bbccee4a..9a5a1e6ef 100644 --- a/src/cc/marmara.cpp +++ b/src/cc/marmara.cpp @@ -33,7 +33,7 @@ int64_t IsMarmaravout(struct CCcontract_info *cp,const CTransaction& tx,int32_t return(0); } -bool MarmaraExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) +/*bool MarmaraExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee) { static uint256 zerohash; CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis; @@ -69,117 +69,328 @@ bool MarmaraExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransactio return eval->Invalid("mismatched inputs != outputs + txfee"); } else return(true); +}*/ + +int32_t MarmaraRandomize(uint32_t ind) +{ + uint64_t val64; uint32_t val,range = (MARMARA_MAXLOCK - MARMARA_MINLOCK); + val64 = komodo_block_prg(ind); + val = (uint32_t)(val64 >> 32); + val ^= (uint32_t)val64; + return((val % range) + MARMARA_MINLOCK); +} + +int32_t MarmaraUnlockht(int32_t height) +{ + uint32_t ind = height / MARMARA_GROUPSIZE; + height = (height / MARMARA_GROUPSIZE) * MARMARA_GROUPSIZE; + return(height + MarmaraRandomize(ind)); +} + +uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht) +{ + std::vector vopret; uint8_t *script,e,f,funcid; + GetOpReturnData(scriptPubKey,vopret); + script = (uint8_t *)vopret.data(); + if ( 0 ) + { + int32_t i; + for (i=0; i 2 && script[0] == EVAL_MARMARA ) + { + if ( script[1] == 'C' || script[1] == 'P' ) + { + if ( E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk; ss >> height; ss >> unlockht) != 0 ) + { + return(script[1]); + } else fprintf(stderr,"DecodeMaramaraCoinbaseOpRet unmarshal error for %c\n",script[1]); + } else fprintf(stderr,"script[1] is %d != 'C' %d or 'P' %d\n",script[1],'C','P'); + } else fprintf(stderr,"vopret.size() is %d\n",(int32_t)vopret.size()); + return(0); +} + +CScript EncodeMarmaraCoinbaseOpRet(uint8_t funcid,CPubKey pk,int32_t ht) +{ + CScript opret; int32_t unlockht; uint8_t evalcode = EVAL_MARMARA; + unlockht = MarmaraUnlockht(ht); + opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk << ht << unlockht); + if ( 0 ) + { + std::vector vopret; uint8_t *script,i; + GetOpReturnData(opret,vopret); + script = (uint8_t *)vopret.data(); + { + for (i=0; i 0 && (height & 1) == 0 && pk.size() == 33 ) + ccvout = MakeCC1vout(EVAL_MARMARA,0,pk); + return(ccvout.scriptPubKey); +} + +CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk) +{ + uint8_t *ptr; + //fprintf(stderr,"height.%d pksize.%d\n",height,(int32_t)pk.size()); + if ( height > 0 && (height & 1) == 0 && pk.size() == 33 ) + return(EncodeMarmaraCoinbaseOpRet(funcid,pk,height)); + return(CScript()); +} + +int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx) +{ + struct CCcontract_info *cp,C; CPubKey pk; int32_t ht,unlockht; CTxOut ccvout; + cp = CCinit(&C,EVAL_MARMARA); + if ( 0 ) + { + int32_t d,histo[365*2+30]; + memset(histo,0,sizeof(histo)); + for (ht=2; ht<100; ht++) + fprintf(stderr,"%d ",MarmaraUnlockht(ht)); + fprintf(stderr," <- first 100 unlock heights\n"); + for (ht=2; ht<1000000; ht+=MARMARA_GROUPSIZE) + { + d = (MarmaraUnlockht(ht) - ht) / 1440; + if ( d < 0 || d > sizeof(histo)/sizeof(*histo) ) + fprintf(stderr,"d error.%d at ht.%d\n",d,ht); + else histo[d]++; + } + for (ht=0; ht unlock.%d\n",ht,unlockht); + ccvout = MakeCC1vout(EVAL_MARMARA,0,pk); + if ( ccvout.scriptPubKey == tx.vout[0].scriptPubKey ) + return(0); + fprintf(stderr,"ht.%d mismatched CCvout scriptPubKey\n",height); + } else fprintf(stderr,"ht.%d %d vs %d unlock.%d\n",height,MarmaraUnlockht(height),ht,unlockht); + } else fprintf(stderr,"ht.%d error decoding coinbase opret\n",height); + } + return(-1); } bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { - int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); - std::vector > txids; + std::vector vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk; numvins = tx.vin.size(); numvouts = tx.vout.size(); - preventCCvins = preventCCvouts = -1; if ( numvouts < 1 ) return eval->Invalid("no vouts"); - else + else if ( tx.vout.size() >= 2 ) { - for (i=0; iInvalid("no opreturn"); + funcid = script[1]; + if ( funcid == 'P' ) { - if ( IsCCInput(tx.vin[0].scriptSig) == 0 ) + funcid = DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht); + for (i=0; iInvalid("illegal normal vini"); + if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 ) + { + if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 ) + return eval->Invalid("cant find vinTx"); + else + { + if ( vinTx.IsCoinBase() == 0 ) + return eval->Invalid("noncoinbase input"); + else if ( vinTx.vout.size() != 2 ) + return eval->Invalid("coinbase doesnt have 2 vouts"); + vfuncid = DecodeMaramaraCoinbaseOpRet(vinTx.vout[1].scriptPubKey,vpk,vht,vunlockht); + if ( vfuncid != 'C' || vpk != pk || vunlockht != unlockht ) + return eval->Invalid("mismatched opreturn"); + } + } } + return(true); } - //fprintf(stderr,"check amounts\n"); - if ( MarmaraExactAmounts(cp,eval,tx,1,10000) == false ) + else if ( funcid == 'L' ) // lock -> lock funds with a unlockht { - fprintf(stderr,"Marmaraget invalid amount\n"); - return false; + return(true); } - else + else if ( funcid == 'R' ) // receive -> agree to receive 'I' from pk, amount, currency, dueht { - txid = tx.GetHash(); - memcpy(hash,&txid,sizeof(hash)); - retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts); - if ( retval != 0 ) - fprintf(stderr,"Marmaraget validated\n"); - else fprintf(stderr,"Marmaraget invalid\n"); - return(retval); + return(true); } + else if ( funcid == 'I' ) // issue -> issue currency to pk with due date height + { + return(true); + } + else if ( funcid == 'T' ) // transfer -> given 'R' transfer 'I' or 'T' to the pk of 'R' + { + return(true); + } + else if ( funcid == 'S' ) // collect -> automatically spend issuers locked funds, given 'I' + { + return(true); // iterate from issuer all remainder after maturity + } + // staking only for locked utxo } + return eval->Invalid("fall through error"); } // end of consensus code // helper functions for rpc calls in rpcwallet.cpp -int64_t AddMarmaraInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs) +int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx,int32_t firstheight,CPubKey poolpk,int32_t maxinputs) { - // add threshold check - char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector origpubkey; CTransaction vintx; int32_t vout,n = 0; + char coinaddr[64]; CPubKey pk; int64_t nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction vintx; int32_t unlockht,ht,vout,unlocks,n = 0; std::vector > unspentOutputs; - GetCCaddress(cp,coinaddr,pk); + GetCCaddress(cp,coinaddr,poolpk); SetCCunspents(unspentOutputs,coinaddr); + unlocks = MarmaraUnlockht(firstheight); + //fprintf(stderr,"check coinaddr.(%s)\n",coinaddr); for (std::vector >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++) { txid = it->first.txhash; vout = (int32_t)it->first.index; - // no need to prevent dup + //fprintf(stderr,"txid.%s/v%d\n",txid.GetHex().c_str(),vout); if ( GetTransaction(txid,vintx,hashBlock,false) != 0 ) { - if ( (nValue= IsMarmaravout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(txid,vout) == 0 ) + if ( vintx.IsCoinBase() != 0 && vintx.vout.size() == 2 && vintx.vout[1].nValue == 0 ) { - if ( total != 0 && maxinputs != 0 ) - mtx.vin.push_back(CTxIn(txid,vout,CScript())); - nValue = it->second.satoshis; - totalinputs += nValue; - n++; - if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) ) - break; - } - } + if ( DecodeMaramaraCoinbaseOpRet(vintx.vout[1].scriptPubKey,pk,ht,unlockht) == 'C' && unlockht == unlocks && pk == poolpk && ht >= firstheight ) + { + if ( (nValue= vintx.vout[vout].nValue) > 0 && myIsutxo_spentinmempool(txid,vout) == 0 ) + { + if ( maxinputs != 0 ) + mtx.vin.push_back(CTxIn(txid,vout,CScript())); + nValue = it->second.satoshis; + totalinputs += nValue; + n++; + if ( maxinputs > 0 && n >= maxinputs ) + break; + } //else fprintf(stderr,"nValue.%8f\n",(double)nValue/COIN); + } //else fprintf(stderr,"decode error unlockht.%d vs %d pk.%d\n",unlockht,unlocks,pk == poolpk); + } else fprintf(stderr,"not coinbase\n"); + } else fprintf(stderr,"error getting tx\n"); } return(totalinputs); } -std::string MarmaraGet(uint64_t txfee,int64_t nValue) +UniValue MarmaraReceive(uint64_t txfee,CPubKey senderpk,int64_t amount,std::string currency,int32_t matures,uint256 createtxid) { - CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); - CPubKey mypk,Marmarapk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash; + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; int32_t needbaton = 0; cp = CCinit(&C,EVAL_MARMARA); if ( txfee == 0 ) txfee = 10000; - Marmarapk = GetUnspendable(cp,0); + // check for batonownership by senderpk and parameters match createtxid mypk = pubkey2pk(Mypubkey()); - if ( (inputs= AddMarmaraInputs(cp,mtx,Marmarapk,nValue+txfee,60)) > 0 ) + if ( currency != "MARMARA" ) + errorstr = (char *)"for now, only MARMARA loops are supported"; + else if ( amount < txfee ) + errorstr = (char *)"amount must be for more than txfee"; + else if ( matures <= chainActive.LastTip()->GetHeight() ) + errorstr = (char *)"it must mature in the future"; + if ( errorstr == 0 ) { - if ( inputs > nValue ) - CCchange = (inputs - nValue - txfee); - if ( CCchange != 0 ) - mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,CCchange,Marmarapk)); - mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); - fprintf(stderr,"start at %u\n",(uint32_t)time(NULL)); - j = rand() & 0xfffffff; - for (i=0; i<1000000; i++,j++) + if ( createtxid == zeroid ) + needbaton = 1; + if ( AddNormalinputs(mtx,mypk,(1+needbaton)*txfee,1) > 0 ) { - tmpmtx = mtx; - rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_MARMARA << (uint8_t)'G' << j)); - if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 ) - { - len >>= 1; - decode_hex(buf,len,(char *)rawhex.c_str()); - hash = bits256_doublesha256(0,buf,len); - if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 ) - { - fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL)); - return(rawhex); - } - //fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]); - } - } - fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL)); - return(""); - } else fprintf(stderr,"cant find Marmara inputs\n"); - return(""); + errorstr = (char *)"couldnt finalize CCtx"; + if ( needbaton != 0 ) + mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,senderpk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('R',createtxid,senderpk,amount,matures,currency)); + if ( rawtx.size() > 0 ) + errorstr = 0; + } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; + } + if ( rawtx.size() == 0 || errorstr != 0 ) + { + result.push_back(Pair("result","error")); + if ( errorstr != 0 ) + result.push_back(Pair("error",errorstr)); + } + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + result.push_back(Pair("funcid","R")); + result.push_back(Pair("createtxid",createtxid.GetHex())); + result.push_back(Pair("senderpk",HexStr(senderpk))); + result.push_back(Pair("amount",ValueFromAmount(amount))); + result.push_back(Pair("matures",matures)); + result.push_back(Pair("currency",currency)); + } + return(result); +} + +UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t amount,std::string currency,int32_t matures,uint256 createtxid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ); CPubKey mypk; struct CCcontract_info *cp,C; std::string rawtx; char *errorstr=0; + cp = CCinit(&C,EVAL_MARMARA); + if ( txfee == 0 ) + txfee = 10000; + // make sure if transfer that it is not too late + mypk = pubkey2pk(Mypubkey()); + if ( currency != "MARMARA" ) + errorstr = (char *)"for now, only MARMARA loops are supported"; + else if ( amount < txfee ) + errorstr = (char *)"amount must be for more than txfee"; + else if ( matures <= chainActive.LastTip()->GetHeight() ) + errorstr = (char *)"it must mature in the future"; + if ( errorstr == 0 ) + { + if ( AddNormalinputs(mtx,mypk,2*txfee,1) > 0 ) + { + errorstr = (char *)"couldnt finalize CCtx"; + mtx.vout.push_back(MakeCC1vout(EVAL_MARMARA,txfee,receiverpk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret(funcid,createtxid,receiverpk,amount,matures,currency)); + if ( rawtx.size() > 0 ) + errorstr = 0; + } else errorstr = (char *)"dont have enough normal inputs for 2*txfee"; + } + if ( rawtx.size() == 0 || errorstr != 0 ) + { + result.push_back(Pair("result","error")); + if ( errorstr != 0 ) + result.push_back(Pair("error",errorstr)); + } + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + char str[2]; str[0] = funcid, str[1] = 0; + result.push_back(Pair("funcid",str)); + result.push_back(Pair("createtxid",createtxid.GetHex())); + result.push_back(Pair("receiverpk",HexStr(receiverpk))); + result.push_back(Pair("amount",ValueFromAmount(amount))); + result.push_back(Pair("matures",matures)); + result.push_back(Pair("currency",currency)); + } + return(result); } std::string MarmaraFund(uint64_t txfee,int64_t funds) @@ -208,9 +419,92 @@ UniValue MarmaraInfo() result.push_back(Pair("name","Marmara")); cp = CCinit(&C,EVAL_MARMARA); Marmarapk = GetUnspendable(cp,0); - funding = AddMarmaraInputs(cp,mtx,Marmarapk,0,0); - sprintf(numstr,"%.8f",(double)funding/COIN); - result.push_back(Pair("funding",numstr)); + return(result); +} + +UniValue MarmaraPoolPayout(uint64_t txfee,int32_t firstheight,double perc,char *jsonstr) // [[pk0, shares0], [pk1, shares1], ...] +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ),a(UniValue::VARR); cJSON *item,*array; std::string rawtx; int32_t i,n; uint8_t buf[33]; CPubKey Marmarapk,pk,poolpk; int64_t payout,poolfee=0,total,totalpayout=0; double poolshares,share,shares = 0.; char *pkstr,*errorstr=0; struct CCcontract_info *cp,C; + poolpk = pubkey2pk(Mypubkey()); + if ( txfee == 0 ) + txfee = 10000; + cp = CCinit(&C,EVAL_MARMARA); + Marmarapk = GetUnspendable(cp,0); + if ( (array= cJSON_Parse(jsonstr)) != 0 && (n= cJSON_GetArraySize(array)) > 0 ) + { + for (i=0; i, ]"; + break; + } + } + if ( errorstr == 0 && shares > SMALLVAL ) + { + shares += shares * perc; + if ( (total= AddMarmaraCoinbases(cp,mtx,firstheight,poolpk,60)) > 0 ) + { + for (i=0; i SMALLVAL ) + { + payout = (share * (total - txfee)) / shares; + if ( payout > 0 ) + { + if ( (pkstr= jstr(jitem(item,0),0)) != 0 && strlen(pkstr) == 66 ) + { + UniValue x(UniValue::VOBJ); + totalpayout += payout; + decode_hex(buf,33,pkstr); + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,payout,Marmarapk,buf2pk(buf))); + x.push_back(Pair(pkstr, (double)payout/COIN)); + a.push_back(x); + } + } + } + } + if ( totalpayout > 0 && total > totalpayout-txfee ) + { + poolfee = (total - totalpayout - txfee); + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,poolfee,Marmarapk,poolpk)); + } + rawtx = FinalizeCCTx(0,cp,mtx,poolpk,txfee,MarmaraCoinbaseOpret('P',firstheight,poolpk)); + if ( rawtx.size() == 0 ) + errorstr = (char *)"couldnt finalize CCtx"; + } else errorstr = (char *)"couldnt find any coinbases to payout"; + } + else if ( errorstr == 0 ) + errorstr = (char *)"no valid shares submitted"; + free(array); + } else errorstr = (char *)"couldnt parse poolshares jsonstr"; + if ( rawtx.size() == 0 || errorstr != 0 ) + { + result.push_back(Pair("result","error")); + if ( errorstr != 0 ) + result.push_back(Pair("error",errorstr)); + } + else + { + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + if ( totalpayout > 0 && total > totalpayout-txfee ) + { + result.push_back(Pair("firstheight",firstheight)); + result.push_back(Pair("lastheight",((firstheight / MARMARA_GROUPSIZE)+1) * MARMARA_GROUPSIZE - 1)); + result.push_back(Pair("total",ValueFromAmount(total))); + result.push_back(Pair("totalpayout",ValueFromAmount(totalpayout))); + result.push_back(Pair("totalshares",shares)); + result.push_back(Pair("poolfee",ValueFromAmount(poolfee))); + result.push_back(Pair("perc",ValueFromAmount((int64_t)(100. * (double)poolfee/totalpayout * COIN)))); + result.push_back(Pair("payouts",a)); + } + } return(result); } diff --git a/src/cc/payments.cpp b/src/cc/payments.cpp index 1b6d88214..859a5ba3f 100644 --- a/src/cc/payments.cpp +++ b/src/cc/payments.cpp @@ -75,7 +75,7 @@ bool PaymentsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 4e414d695..e2893bec8 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -82,7 +82,7 @@ bool PegsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction & bool PegsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 8c2ecc021..5d919d6e8 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -89,7 +89,7 @@ uint8_t DecodePricesFundingOpRet(CScript scriptPubKey,CPubKey &planpk,uint256 &o bool PricesValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64]; - return(false); + return eval->Invalid("no validation yet"); std::vector > txids; numvins = tx.vin.size(); numvouts = tx.vout.size(); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 2f1b27f84..6b0627d20 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -108,7 +108,7 @@ public: strNetworkID = "main"; strCurrencyUnits = "KMD"; - bip44CoinType = 141; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md (ZCASH, should be VRSC) + bip44CoinType = 141; // As registered in https://github.com/satoshilabs/slips/blob/master/slip-0044.md consensus.fCoinbaseMustBeProtected = false; // true this is only true wuth Verus and enforced after block 12800 consensus.nSubsidySlowStartInterval = 20000; consensus.nSubsidyHalvingInterval = 840000; diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 4117347b6..bb85ef1d1 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1162,15 +1162,22 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height) n = pblock->vtx[i].vout.size(); for (j=0; jvtx[i].vout[j].nValue),j); if ( i != 0 || j != 1 ) total += pblock->vtx[i].vout[j].nValue; + if ( total > 1000000 * COIN ) + { + total = 1000000 * COIN; + break; + } } } - commission = ((total * ASSETCHAINS_COMMISSION) / COIN); + commission = ((total / 10000) * ASSETCHAINS_COMMISSION) / 10000; + //commission = ((total * ASSETCHAINS_COMMISSION) / COIN); } if ( commission < 10000 ) commission = 0; + //fprintf(stderr,"-> %.8f\n",(double)commission/COIN); return(commission); } @@ -1699,11 +1706,19 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height) if ( ASSETCHAINS_COMMISSION != 0 ) { checktoshis = komodo_commission(pblock,height); - //fprintf(stderr,"height.%d commission %.8f\n",height,(double)checktoshis/COIN); - if ( checktoshis != 0 ) + if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 ) + { + //fprintf(stderr,"komodo_checkcommission vsize.%d height.%d commission %.8f\n",(int32_t)pblock->vtx[0].vout.size(),height,(double)checktoshis/COIN); + return(-1); + } + else if ( checktoshis != 0 ) { script = (uint8_t *)&pblock->vtx[0].vout[1].scriptPubKey[0]; scriptlen = (int32_t)pblock->vtx[0].vout[1].scriptPubKey.size(); + //int32_t i; + //for (i=0; ivtx[0].vout[1].nValue/COIN); if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) { if ( ASSETCHAINS_SCRIPTPUB.size()/2 == scriptlen && scriptlen < sizeof(scripthex) ) @@ -1719,10 +1734,7 @@ int64_t komodo_checkcommission(CBlock *pblock,int32_t height) matched = 25; if ( matched == 0 ) { - //int32_t i; - //for (i=0; i<25; i++) - // fprintf(stderr,"%02x",script[i]); - //fprintf(stderr," payment to wrong pubkey scriptlen.%d, scriptpub[%d]\n",scriptlen,(int32_t)ASSETCHAINS_SCRIPTPUB.size()/2); + fprintf(stderr," payment to wrong pubkey scriptlen.%d, scriptpub[%d] checktoshis.%llu\n",scriptlen,(int32_t)ASSETCHAINS_SCRIPTPUB.size()/2,(long long)checktoshis); return(-1); } @@ -1740,7 +1752,7 @@ bool KOMODO_TEST_ASSETCHAIN_SKIP_POW = 0; int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) { - uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; + uint256 hash; arith_uint256 bnTarget,bhash; bool fNegative,fOverflow; uint8_t *script,pubkey33[33],pubkeys[64][33]; int32_t i,scriptlen,possible,PoSperc,is_PoSblock=0,n,failed = 0,notaryid = -1; int64_t checktoshis,value; CBlockIndex *pprev; if ( KOMODO_TEST_ASSETCHAIN_SKIP_POW == 0 && Params().NetworkIDString() == "regtest" ) KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; if ( !CheckEquihashSolution(pblock, Params()) ) @@ -1858,7 +1870,8 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height) else { script = (uint8_t *)&pblock->vtx[0].vout[0].scriptPubKey[0]; - if ( script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) + scriptlen = (int32_t)pblock->vtx[0].vout[0].scriptPubKey.size(); + if ( scriptlen != 35 || script[0] != 33 || script[34] != OP_CHECKSIG || memcmp(script+1,ASSETCHAINS_OVERRIDE_PUBKEY33,33) != 0 ) return(-1); } } @@ -2037,9 +2050,12 @@ uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komod kp->hashval = UintToArith256(hash); segid = ((nHeight + kp->segid32) & 0x3f); hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,minage,segid,nHeight,prevtime); - //for (int i=32; i>=0; i--) - // fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); - //fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime); + /*for (int i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]); + fprintf(stderr," vs "); + for (int i=31; i>=16; i--) + fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]); + fprintf(stderr," b.%u minage.%d segid.%d ht.%d prev.%u\n",blocktime,minage,segid,nHeight,prevtime);*/ if ( hashval <= bnTarget ) { for (iter=0; iternTime+60 ) *blocktimep = tipindex->nTime+60; - //fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight); +//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight); bool resetstaker = false; if ( array != 0 ) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 982f16b0b..e19d94915 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -16,6 +16,8 @@ // paxdeposit equivalent in reverse makes opreturn and KMD does the same in reverse #include "komodo_defs.h" +int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx); + int32_t pax_fiatstatus(uint64_t *available,uint64_t *deposited,uint64_t *issued,uint64_t *withdrawn,uint64_t *approved,uint64_t *redeemed,char *base) { int32_t baseid; struct komodo_state *sp; int64_t netliability,maxallowed,maxval; @@ -687,6 +689,14 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim } } } + if ( height > 0 && ASSETCHAINS_MARMARA != 0 && (height & 1) == 0 ) + { + if ( MarmaraValidateCoinbase(height,block.vtx[0]) < 0 ) + { + fprintf(stderr,"MARMARA error ht.%d constrains even height blocks to pay 100%% to CC in vout0 with opreturn\n",height); + return(-1); + } + } // we don't want these checks in VRSC, leave it at the Sapling upgrade if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_COMMISSION != 0 && height > 1) || diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 244655f5f..ef7af0ba2 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -48,7 +48,7 @@ unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,IS_STAKED_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,WHITELIST_ADDRESS,ASSETCHAINS_SELFIMPORT; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,NUM_NOTARIES; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,NUM_NOTARIES,ASSETCHAINS_MARMARA; bool VERUS_MINTBLOCKS; char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096],NOTARYADDRS[64][36]; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 17e849338..0ac40a48b 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1783,6 +1783,7 @@ void komodo_args(char *argv0) ASSETCHAINS_SCRIPTPUB = GetArg("-ac_script",""); ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0); ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0); + ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0); if ( ASSETCHAINS_BEAMPORT != 0 && ASSETCHAINS_CODAPORT != 0 ) { fprintf(stderr,"can only have one of -ac_beam or -ac_coda\n"); @@ -1862,7 +1863,12 @@ void komodo_args(char *argv0) printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); } } - if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 ) + if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_MARMARA != 0 ) + { + fprintf(stderr,"-ac_script and -ac_marmara are mutually exclusive\n"); + exit(0); + } + if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LWMAPOS != 0 || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || ASSETCHAINS_MARMARA != 0 ) { fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); extraptr = extrabuf; @@ -1936,6 +1942,8 @@ void komodo_args(char *argv0) extraptr[extralen++] = 'b'; if ( ASSETCHAINS_CODAPORT != 0 ) extraptr[extralen++] = 'c'; + if ( ASSETCHAINS_MARMARA != 0 ) + extraptr[extralen++] = ASSETCHAINS_MARMARA; } addn = GetArg("-seednode",""); diff --git a/src/main.cpp b/src/main.cpp index 92feadd4e..c1cdc3935 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3480,7 +3480,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { if ( block.vtx[0].vout.size() >= 2 && block.vtx[0].vout[1].nValue == checktoshis ) blockReward += checktoshis; - else fprintf(stderr,"checktoshis %.8f numvouts %d\n",dstr(checktoshis),(int32_t)block.vtx[0].vout.size()); + else if ( pindex->GetHeight() > 1 ) + fprintf(stderr,"checktoshis %.8f vs %.8f numvouts %d\n",dstr(checktoshis),dstr(block.vtx[0].vout[1].nValue),(int32_t)block.vtx[0].vout.size()); } } if (ASSETCHAINS_SYMBOL[0] != 0 && pindex->GetHeight() == 1 && block.vtx[0].GetValueOut() != blockReward) diff --git a/src/miner.cpp b/src/miner.cpp index 06cf809c8..26d1a1df9 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -18,6 +18,7 @@ * * ******************************************************************************/ +#include "pubkey.h" #include "miner.h" #ifdef ENABLE_MINING #include "pow/tromp/equi_miner.h" @@ -141,7 +142,7 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],NOTARYADDRS[64][36]; extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB; void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); -extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],NUM_NOTARIES; +extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],NUM_NOTARIES,ASSETCHAINS_MARMARA; uint32_t Mining_start,Mining_height; int32_t My_notaryid = -1; int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); @@ -156,19 +157,25 @@ int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33); int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex); int32_t komodo_is_notarytx(const CTransaction& tx); +CScript Marmara_scriptPubKey(int32_t height,CPubKey pk); +CScript MarmaraCoinbaseOpret(uint8_t funcid,int32_t height,CPubKey pk); -CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) +CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) { CScript scriptPubKeyIn(_scriptPubKeyIn); - CPubKey pk = CPubKey(); - std::vector> vAddrs; - txnouttype txT; - if ( scriptPubKeyIn.size() > 0 && Solver(scriptPubKeyIn, txT, vAddrs)) + CPubKey pk; + if ( _pk.size() != 33 ) { - if (txT == TX_PUBKEY) - pk = CPubKey(vAddrs[0]); - } + pk = CPubKey(); + std::vector> vAddrs; + txnouttype txT; + if ( scriptPubKeyIn.size() > 0 && Solver(scriptPubKeyIn, txT, vAddrs)) + { + if (txT == TX_PUBKEY) + pk = CPubKey(vAddrs[0]); + } + } else pk = _pk; uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params(); //fprintf(stderr,"create new block\n"); @@ -556,36 +563,17 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 ) txNew.vout[0].nValue += 5000; + pblock->vtx[0] = txNew; + //fprintf(stderr,"ht.%d cmp.%d [%d %d %d %d %d]\n",nHeight,nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0,nHeight > 1,ASSETCHAINS_SYMBOL[0] != 0, (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1), ASSETCHAINS_COMMISSION != 0,(commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0); // check if coinbase transactions must be time locked at current subsidy and prepend the time lock // to transaction if so, cast for GTE operator - if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE) + if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) { - int32_t opretlen, p2shlen, scriptlen; - CScriptExt opretScript = CScriptExt(); - txNew.vout.resize(2); - - // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins - // protected only by the time lock rather than 100% inaccessible - opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight)); - if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition()) - { - fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) - { - LEAVE_CRITICAL_SECTION(cs_main); - LEAVE_CRITICAL_SECTION(mempool.cs); - } - return 0; - } - - opretScript += scriptPubKeyIn; - - txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript)); - txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK); txNew.vout[1].nValue = 0; - } // timelocks and commissions are currently incompatible due to validation complexity of the combination + txNew.vout[1].scriptPubKey = MarmaraCoinbaseOpret('C',nHeight,pk); + } else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 ) { int32_t i; uint8_t *ptr; @@ -593,6 +581,7 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, txNew.vout[1].nValue = commission; if ( ASSETCHAINS_SCRIPTPUB.size() > 1 ) { + //fprintf(stderr,"mine to -ac_script\n"); //txNew.vout[1].scriptPubKey = CScript() << ParseHex(); int32_t len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); len >>= 1; @@ -606,11 +595,42 @@ CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0]; ptr[0] = 33; for (i=0; i<33; i++) + { ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i]; + //fprintf(stderr,"%02x",ptr[i+1]); + } ptr[34] = OP_CHECKSIG; + //fprintf(stderr," set ASSETCHAINS_OVERRIDE_PUBKEY33 into vout[1]\n"); } //printf("autocreate commision vout\n"); } + else if ( (uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE) + { + int32_t opretlen, p2shlen, scriptlen; + CScriptExt opretScript = CScriptExt(); + + txNew.vout.resize(2); + + // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins + // protected only by the time lock rather than 100% inaccessible + opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight)); + if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition()) + { + fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n"); + if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) + { + LEAVE_CRITICAL_SECTION(cs_main); + LEAVE_CRITICAL_SECTION(mempool.cs); + } + return 0; + } + + opretScript += scriptPubKeyIn; + + txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript)); + txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK); + txNew.vout[1].nValue = 0; + } // timelocks and commissions are currently incompatible due to validation complexity of the combination pblock->vtx[0] = txNew; pblocktemplate->vTxFees[0] = -nFees; @@ -778,7 +798,10 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, if ( nHeight == 1 && ASSETCHAINS_COMMISSION != 0 ) { if ( ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 ) - scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG; + { + pubkey = ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY); + scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG; + } else { len = strlen(ASSETCHAINS_SCRIPTPUB.c_str()); @@ -791,8 +814,10 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, else if ( USE_EXTERNAL_PUBKEY != 0 ) { //fprintf(stderr,"use notary pubkey\n"); - scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG; - } else + pubkey = ParseHex(NOTARY_PUBKEY); + scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG; + } + else { //if ( !isStake || ASSETCHAINS_STAKED != 0 ) { @@ -809,7 +834,11 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, scriptPubKey[34] = OP_CHECKSIG; } } - return CreateNewBlock(scriptPubKey, gpucount, isStake); + if ( ASSETCHAINS_MARMARA != 0 && nHeight > 0 && (nHeight & 1) == 0 ) + scriptPubKey = Marmara_scriptPubKey(nHeight,pubkey); + if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 ) + isStake = true; + return CreateNewBlock(pubkey,scriptPubKey, gpucount, isStake); } void komodo_broadcast(CBlock *pblock,int32_t limit) @@ -1205,14 +1234,14 @@ void static BitcoinMiner_noeq() miningTimer.start(); #ifdef ENABLE_WALLET - CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0); + CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0); #else CBlockTemplate *ptr = CreateNewBlockWithKey(); #endif if ( ptr == 0 ) { static uint32_t counter; - if ( counter++ < 100 ) + if ( counter++ < 10 ) fprintf(stderr,"created illegal block, retry\n"); continue; } @@ -1500,15 +1529,15 @@ void static BitcoinMiner() #ifdef ENABLE_WALLET // notaries always default to staking - CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", -1) == 0); + CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0); #else CBlockTemplate *ptr = CreateNewBlockWithKey(); #endif if ( ptr == 0 ) { static uint32_t counter; - if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) - fprintf(stderr,"created illegal block, retry\n"); + if ( counter++ < 10 && ASSETCHAINS_STAKED == 0 ) + fprintf(stderr,"created illegal blockB, retry\n"); sleep(1); continue; } @@ -1912,12 +1941,12 @@ void static BitcoinMiner() for (int i = 0; i < nThreads; i++) { #ifdef ENABLE_WALLET - if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH) + if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH || (ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0) ) minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); else minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet)); #else - if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH) + if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH || (ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0) ) minerThreads->create_thread(&BitcoinMiner); else minerThreads->create_thread(&BitcoinMiner_noeq); diff --git a/src/miner.h b/src/miner.h index 5494022bd..a3bedd292 100644 --- a/src/miner.h +++ b/src/miner.h @@ -43,7 +43,7 @@ struct CBlockTemplate #define KOMODO_MAXGPUCOUNT 65 /** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn, int32_t gpucount, bool isStake = false); +CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& scriptPubKeyIn, int32_t gpucount, bool isStake = false); #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake = false); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 851776695..a3d8be528 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -445,7 +445,11 @@ static const CRPCCommand vRPCCommands[] = { "pegs", "pegsaddress", &pegsaddress, true }, // Marmara - { "marmara", "Marmaraaddress", &marmaraaddress, true }, + { "marmara", "marmaraaddress", &marmaraaddress, true }, + { "marmara", "marmarapoolpayout", &marmara_poolpayout, true }, + { "marmara", "marmarareceive", &marmara_receive, true }, + { "marmara", "marmaraissue", &marmara_issue, true }, + { "marmara", "marmaratransfer", &marmara_transfer, true }, // Payments { "payments", "paymentsaddress", &paymentsaddress, true }, diff --git a/src/rpc/server.h b/src/rpc/server.h index 327d3704c..c912b39f7 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -272,6 +272,10 @@ extern UniValue pricesstatus(const UniValue& params, bool fHelp); extern UniValue pricesfinish(const UniValue& params, bool fHelp); extern UniValue pegsaddress(const UniValue& params, bool fHelp); extern UniValue marmaraaddress(const UniValue& params, bool fHelp); +extern UniValue marmara_poolpayout(const UniValue& params, bool fHelp); +extern UniValue marmara_receive(const UniValue& params, bool fHelp); +extern UniValue marmara_issue(const UniValue& params, bool fHelp); +extern UniValue marmara_transfer(const UniValue& params, bool fHelp); extern UniValue paymentsaddress(const UniValue& params, bool fHelp); extern UniValue gatewaysaddress(const UniValue& params, bool fHelp); extern UniValue gatewayslist(const UniValue& params, bool fHelp); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 6d80fc4b7..277b726c8 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -158,7 +158,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) { // Simple block creation, nothing special yet: - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 4; @@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } // Just to make sure we can still make simple blocks - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; // block sigops > limit: 1000 CHECKMULTISIG + 1 @@ -292,7 +292,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -313,14 +313,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); // orphan in mempool hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -338,7 +338,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 49000LL; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -349,7 +349,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue = 0; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -367,7 +367,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].nValue -= 10000; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); @@ -381,17 +381,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.vout[0].scriptPubKey = CScript() << OP_2; hash = tx.GetHash(); mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; mempool.clear(); // subsidy changing int nHeight = chainActive.Height(); chainActive.Tip()->SetHeight(209999); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; chainActive.Tip()->SetHeight(210000); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); delete pblocktemplate; chainActive.Tip()->SetHeight(nHeight); @@ -423,7 +423,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) mempool.addUnchecked(hash, entry.Time(GetTime()).SpendsCoinbase(true).FromTx(tx2)); BOOST_CHECK(!CheckFinalTx(tx2, LOCKTIME_MEDIAN_TIME_PAST)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); // Neither tx should have made it into the template. BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1); @@ -438,7 +438,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) //BOOST_CHECK(CheckFinalTx(tx)); //BOOST_CHECK(CheckFinalTx(tx2)); - BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey,-1)); + BOOST_CHECK(pblocktemplate = CreateNewBlock(CPubKey(),scriptPubKey,-1)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 2); delete pblocktemplate; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index ff1f70eaa..9e253b6ea 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3085,7 +3085,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); if (it != mapBlockIndex.end()) { nHeight = it->second->GetHeight(); - fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); } else { // TODO: should we throw JSONRPCError ? fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); @@ -3119,7 +3119,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); if (it != mapBlockIndex.end()) { nHeight = it->second->GetHeight(); - fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); } else { // TODO: should we throw JSONRPCError ? fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); @@ -3910,7 +3910,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); if (it != mapBlockIndex.end()) { nHeight = it->second->GetHeight(); - fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); } else { fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); } @@ -3942,7 +3942,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp) BlockMap::const_iterator it = mapBlockIndex.find(hashBlock); if (it != mapBlockIndex.end()) { nHeight = it->second->GetHeight(); - fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); + //fprintf(stderr,"blockHash %s height %d\n",hashBlock.ToString().c_str(), nHeight); } else { fprintf(stderr,"block hash %s does not exist!\n", hashBlock.ToString().c_str() ); } @@ -5666,6 +5666,95 @@ UniValue tokenaddress(const UniValue& params, bool fHelp) return(CCaddress(cp,(char *)"Assets",pubkey)); } +UniValue marmara_poolpayout(const UniValue& params, bool fHelp) +{ + int32_t firstheight; double perc; char *jsonstr; + if ( fHelp || params.size() != 3 ) + { + // marmarapoolpayout 0.5 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000],["02ebc786cb83de8dc3922ab83c21f3f8a2f3216940c3bf9da43ce39e2a3a882c92",100]]'; + marmarapoolpayout 0 2 '[["024131032ed90941e714db8e6dd176fe5a86c9d873d279edecf005c06f773da686",1000]]' + throw runtime_error("marmarapoolpayout perc firstheight \"[[\\\"pubkey\\\":shares], ...]\"\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + perc = atof(params[0].get_str().c_str()) / 100.; + firstheight = atol(params[1].get_str().c_str()); + jsonstr = (char *)params[2].get_str().c_str(); + return(MarmaraPoolPayout(0,firstheight,perc,jsonstr)); // [[pk0, shares0], [pk1, shares1], ...] +} + +UniValue marmara_receive(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 createtxid; std::vector senderpub; int64_t amount; int32_t matures; std::string currency; + if ( fHelp || (params.size() != 5 && params.size() != 4) ) + { + // 1st marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1440 + // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1440 + throw runtime_error("marmarareceive senderpk amount currency matures createtxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + memset(&createtxid,0,sizeof(createtxid)); + senderpub = ParseHex(params[0].get_str().c_str()); + if (senderpub.size()!= 33) + { + ERR_RESULT("invalid sender pubkey"); + return result; + } + amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; + currency = params[2].get_str(); + matures = atol(params[3].get_str().c_str()) + chainActive.LastTip()->GetHeight() + 1; + if ( params.size() == 5 ) + createtxid = Parseuint256((char *)params[4].get_str().c_str()); + return(MarmaraReceive(0,pubkey2pk(senderpub),amount,currency,matures,createtxid)); +} + +UniValue marmara_issue(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 createtxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; + if ( fHelp || params.size() != 5 ) + { + // marmaraissue 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 2693 e5b1ef8ec90e981d3011c8e024cef869b69af2d4dd6837d1ab1d394d3730b7cb + throw runtime_error("marmaraissue receiverpk amount currency matures createtxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + receiverpub = ParseHex(params[0].get_str().c_str()); + if (receiverpub.size()!= 33) + { + ERR_RESULT("invalid receiverpub pubkey"); + return result; + } + amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; + currency = params[2].get_str(); + matures = atol(params[3].get_str().c_str()); + createtxid = Parseuint256((char *)params[4].get_str().c_str()); + return(MarmaraIssue(0,'I',pubkey2pk(receiverpub),amount,currency,matures,createtxid)); +} + +UniValue marmara_transfer(const UniValue& params, bool fHelp) +{ + UniValue result(UniValue::VOBJ); uint256 createtxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; + if ( fHelp || params.size() != 5 ) + { + // marmaratransfer 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 2693 e5b1ef8ec90e981d3011c8e024cef869b69af2d4dd6837d1ab1d394d3730b7cb + throw runtime_error("marmaratransfer receiverpk amount currency matures createtxid\n"); + } + if ( ensure_CCrequirements() < 0 ) + throw runtime_error("to use CC contracts, you need to launch daemon with valid -pubkey= for an address in your wallet\n"); + receiverpub = ParseHex(params[0].get_str().c_str()); + if (receiverpub.size()!= 33) + { + ERR_RESULT("invalid receiverpub pubkey"); + return result; + } + amount = atof(params[1].get_str().c_str()) * COIN + 0.00000000499999; + currency = params[2].get_str(); + matures = atol(params[3].get_str().c_str()); + createtxid = Parseuint256((char *)params[4].get_str().c_str()); + return(MarmaraIssue(0,'T',pubkey2pk(receiverpub),amount,currency,matures,createtxid)); +} + UniValue channelslist(const UniValue& params, bool fHelp) { if ( fHelp || params.size() > 0 ) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 513537290..ae1f7b810 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1180,7 +1180,7 @@ bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t n assert((nWitnessCacheSize - 1) >= nd->witnesses.size()); } } - assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0); + assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0 || WITNESS_CACHE_SIZE != _COINBASE_MATURITY+10); return true; }