diff --git a/src/cc/CCMarmara.h b/src/cc/CCMarmara.h index 753f8edb6..d008095f7 100644 --- a/src/cc/CCMarmara.h +++ b/src/cc/CCMarmara.h @@ -24,6 +24,7 @@ #define MARMARA_MINLOCK (1440 * 3 * 30) #define MARMARA_MAXLOCK (1440 * 24 * 30) +extern uint8_t ASSETCHAINS_MARMARA; uint64_t komodo_block_prg(uint32_t nHeight); int32_t MarmaraGetcreatetxid(uint256 &createtxid,uint256 txid); int32_t MarmaraGetbatontxid(std::vector &creditloop,uint256 &batontxid,uint256 txid); diff --git a/src/cc/marmara.cpp b/src/cc/marmara.cpp index d37314e9e..c82a28f4c 100644 --- a/src/cc/marmara.cpp +++ b/src/cc/marmara.cpp @@ -245,6 +245,8 @@ int32_t MarmaraValidateCoinbase(int32_t height,CTransaction tx) bool MarmaraValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn) { std::vector vopret; CTransaction vinTx; uint256 hashBlock; int32_t numvins,numvouts,i,ht,unlockht,vht,vunlockht; uint8_t funcid,vfuncid,*script; CPubKey pk,vpk; + if ( ASSETCHAINS_MARMARA == 0 ) + return eval->Invalid("-ac_marmara must be set for marmara CC"); numvins = tx.vin.size(); numvouts = tx.vout.size(); if ( numvouts < 1 ) @@ -344,6 +346,116 @@ int64_t AddMarmaraCoinbases(struct CCcontract_info *cp,CMutableTransaction &mtx, return(totalinputs); } +UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid) +{ + CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); + UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount,remaining,change,avail; CPubKey Marmarapk,mypk,pk; std::string currency,refcurrency,rawtx; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; + if ( txfee == 0 ) + txfee = 10000; + cp = CCinit(&C,EVAL_MARMARA); + mypk = pubkey2pk(Mypubkey()); + Marmarapk = GetUnspendable(cp,0); + remaining = change = 0; + if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 ) + { + if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && (numvouts= batontx.vout.size()) > 1 ) + { + if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) + { + if ( refcreatetxid != creditloop[0] ) + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"invalid refcreatetxid, setting to creditloop[0]")); + return(result); + } + if ( chainActive.LastTip()->GetHeight() < refmatures ) + { + fprintf(stderr,"doesnt mature for another %d blocks\n",refmatures - chainActive.LastTip()->GetHeight())' + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"cant settle immature creditloop")); + return(result); + } + remaining = refamount; + GetCCaddress(cp,myCCaddr,Mypubkey()); + Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey); + if ( strcmp(myCCaddr,batonCCaddr) == 0 ) + { + mtx.vin.push_back(CTxIn(batontxid,0,CScript())); + for (i=0; i 1 ) + { + if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) + { + GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); + avail = CCaddress_balance(coinaddr); + if ( avail > remaining ) + { + // add remaining + change = (avail - remaining); + mtx.vout.push_back(CTxOut(amount,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + if ( change > txfee ) + mtx.vout.push_back(MakeCC1of2vout(EVAL_MARMARA,change,Marmarapk,pk)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,amount,matures,currency)); + result.push_back(Pair("result",(char *)"success")); + result.push_back(Pair("rawtx",rawtx)); + return(result); + } + else if ( avail > txfee ) + { + // add all utxos + remaining -= avail; + } + fprintf(stderr,"get locked funds of %s %.8f\n",coinaddr,(double)avail/COIN); + } else fprintf(stderr,"null funcid for creditloop[%d]\n",i); + } else fprintf(stderr,"couldnt get creditloop[%d]\n",i); + } + if ( amount - remaining > 2*txfee ) + { + mtx.vout.push_back(CTxOut(txfee,CScript() << ParseHex(HexStr(CCtxidaddr(txidaddr,createtxid))) << OP_CHECKSIG)); // failure marker + if ( amount-remaining > 3*txfee ) + mtx.vout.push_back(CTxOut(amount-remaining-2*txfee,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG)); + rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,MarmaraLoopOpret('S',createtxid,mypk,amount-remaining,-remaining,currency)); + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"insufficient funds")); + result.push_back(Pair("rawtx",rawtx)); + result.push_back(Pair("remaining",ValueFromAmount(remaining))); + } + else + { + // jl777: maybe fund a txfee to report no funds avail + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"no funds available at all")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"this node does not have the baton")); + result.push_back(Pair("myCCaddr",myCCaddr)); + result.push_back(Pair("batonCCaddr",batonCCaddr)); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt find batontxid")); + } + } + else + { + result.push_back(Pair("result",(char *)"error")); + result.push_back(Pair("error",(char *)"couldnt get creditloop")); + } + return(result); +} + int32_t MarmaraGetCreditloops(int64_t &totalamount,std::vector &issuances,struct CCcontract_info *cp,int32_t firstheight,int32_t lastheight,int64_t minamount,int64_t maxamount,CPubKey refpk,std::string refcurrency) { char coinaddr[64]; CPubKey Marmarapk,senderpk; int64_t amount; uint256 createtxid,txid,hashBlock; CTransaction tx; int32_t numvouts,vout,matures,n=0; std::string currency; @@ -489,70 +601,6 @@ UniValue MarmaraIssue(uint64_t txfee,uint8_t funcid,CPubKey receiverpk,int64_t a return(result); } -UniValue MarmaraSettlement(uint64_t txfee,uint256 refbatontxid) -{ - UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey Marmarapk,pk; std::string currency,refcurrency; CTransaction tx,batontx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; - if ( txfee == 0 ) - txfee = 10000; - cp = CCinit(&C,EVAL_MARMARA); - Marmarapk = GetUnspendable(cp,0); - if ( (n= MarmaraGetbatontxid(creditloop,batontxid,refbatontxid)) > 0 ) - { - if ( GetTransaction(batontxid,batontx,hashBlock,false) != 0 && (numvouts= batontx.vout.size()) > 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(batontx.vout[numvouts-1].scriptPubKey,refcreatetxid,pk,refamount,refmatures,refcurrency)) != 0 ) - { - if ( refcreatetxid != creditloop[0] ) - { - fprintf(stderr,"invalid refcreatetxid, setting to creditloop[0]\n"); - refcreatetxid = creditloop[0]; - numerrs++; - } - GetCCaddress(cp,myCCaddr,Mypubkey()); - Getscriptaddress(batonCCaddr,batontx.vout[0].scriptPubKey); - if ( strcmp(myCCaddr,batonCCaddr) == 0 ) - { - for (i=0; i 1 ) - { - if ( (funcid= MarmaraDecodeLoopOpret(tx.vout[numvouts-1].scriptPubKey,createtxid,pk,amount,matures,currency)) != 0 ) - { - GetCCaddress1of2(cp,coinaddr,Marmarapk,pk); - //make tx here - fprintf(stderr,"get locked funds of %s %.8f\n",coinaddr,(double)CCaddress_balance(coinaddr)/COIN); - } else fprintf(stderr,"null funcid for creditloop[%d]\n",i); - } else fprintf(stderr,"couldnt get creditloop[%d]\n",i); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"this node does not have the baton")); - result.push_back(Pair("myCCaddr",myCCaddr)); - result.push_back(Pair("batonCCaddr",batonCCaddr)); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get batontxid opret")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt find batontxid")); - } - } - else - { - result.push_back(Pair("result",(char *)"error")); - result.push_back(Pair("error",(char *)"couldnt get creditloop")); - } - return(result); -} - UniValue MarmaraCreditloop(uint256 txid) { UniValue result(UniValue::VOBJ),a(UniValue::VARR); std::vector creditloop; uint256 batontxid,createtxid,refcreatetxid,hashBlock; uint8_t funcid; int32_t numerrs=0,i,n,numvouts,matures,refmatures; int64_t amount,refamount; CPubKey pk; std::string currency,refcurrency; CTransaction tx; char coinaddr[64],myCCaddr[64],destaddr[64],batonCCaddr[64],str[2]; struct CCcontract_info *cp,C; diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index fc302c545..19a5f8103 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -643,6 +643,10 @@ int32_t komodo_isPoS(CBlock *pblock) { txid = pblock->vtx[n-1].vin[0].prevout.hash; vout = pblock->vtx[n-1].vin[0].prevout.n; + if ( ASSETCHAINS_MARMARA != 0 ) + { + // need to verify it was signed by the non-Marmarapk of the 1of2 + } txtime = komodo_txtime(&value,txid,vout,destaddr); if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) ) { @@ -2112,34 +2116,42 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt maxkp = numkp = 0; lasttime = 0; } - BOOST_FOREACH(const COutput& out, vecOutputs) + if ( ASSETCHAINS_MARMARA == 0 || 1 ) { - if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) + BOOST_FOREACH(const COutput& out, vecOutputs) { - fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); - return(0); - } - counter++; - if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) - { - fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); - continue; - } - CAmount nValue = out.tx->vout[out.i].nValue; - if ( nValue < COIN || !out.fSpendable ) - continue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; - if ( ExtractDestination(pk,address) != 0 ) - { - if ( IsMine(*pwalletMain,address) == 0 ) - continue; - if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) + if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight ) { - array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); - //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); + fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter); + return(0); + } + counter++; + if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth ) + { + fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth); + continue; + } + CAmount nValue = out.tx->vout[out.i].nValue; + if ( nValue < COIN || !out.fSpendable ) + continue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + if ( ExtractDestination(pk,address) != 0 ) + { + if ( IsMine(*pwalletMain,address) == 0 ) + continue; + if ( GetTransaction(out.tx->GetHash(),tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 ) + { + array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,out.tx->GetHash(),out.i,(char *)CBitcoinAddress(address).ToString().c_str(),hashbuf,(CScript)pk); + //fprintf(stderr,"addutxo numkp.%d vs max.%d\n",numkp,maxkp); + } } } } + else + { + // calc 1of2 address + // iterate all unspents not spent in mempool and komodo_addutxo + } lasttime = (uint32_t)time(NULL); //fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp); } @@ -2218,7 +2230,14 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt txNew.vout[0].nValue = *utxovaluep - txfee; txNew.nLockTime = earliest; CTransaction txNewConst(txNew); - signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); + if ( ASSETCHAINS_MARMARA == 0 || 1 ) + { + signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId); + } + else + { + // signSuccess = CCFinalizetx(...) + } if (!signSuccess) fprintf(stderr,"failed to create signature\n"); else diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 2ce2435a7..877342306 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -5554,7 +5554,7 @@ UniValue marmara_receive(const UniValue& params, bool fHelp) if ( fHelp || (params.size() != 5 && params.size() != 4) ) { // 1st marmarareceive 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1440 - // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 3903 bf6b4d42aa3ce974c853d73b06c78597dd3b5fb493d5d0d944f72c2017f561ad + // after marmarareceive 039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775 7.5 MARMARA 1168 d72d87aa0d50436de695c93e2bf3d7273c63c92ef6307913aa01a6ee6a16548b throw runtime_error("marmarareceive senderpk amount currency matures batontxid\n"); } if ( ensure_CCrequirements() < 0 ) @@ -5604,7 +5604,7 @@ UniValue marmara_transfer(const UniValue& params, bool fHelp) UniValue result(UniValue::VOBJ); uint256 approvaltxid,batontxid; std::vector receiverpub; int64_t amount; int32_t matures; std::string currency; std::vector creditloop; if ( fHelp || params.size() != 5 ) { - // marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 3903 748a4c80e6f6b725340fb0f52738f38a11c422d59b3034c8366b3d7b33c99a1e + // marmaratransfer 028076d42eb20efc10007fafb5ca66a2052523c0d2221e607adf958d1a332159f6 7.5 MARMARA 1168 1506c774e4b2804a6e25260920840f4cfca8d1fb400e69fe6b74b8e593dbedc5 throw runtime_error("marmaratransfer receiverpk amount currency matures approvaltxid\n"); } if ( ensure_CCrequirements() < 0 ) @@ -5674,7 +5674,7 @@ UniValue marmara_settlement(const UniValue& params, bool fHelp) if ( fHelp || params.size() != 1 ) { // marmarasettlement 010ff7f9256cefe3b5dee3d72c0eeae9fc6f34884e6f32ffe5b60916df54a9be - // marmarasettlement cc23bf81733556dc06db2fd9c9f4178cad44bdc237d6e62101cf0cdafb5195f7 + // marmarasettlement ff3e259869196f3da9b5ea3f9e088a76c4fc063cf36ab586b652e121d441a603 throw runtime_error("marmarasettlement batontxid\n"); } if ( ensure_CCrequirements() < 0 )