Merge branch 'FSM' of https://github.com/jl777/komodo into VHT

This commit is contained in:
blackjok3r
2019-01-14 17:02:41 +08:00
25 changed files with 633 additions and 169 deletions

View File

@@ -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):

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<std::pair<CAddressIndexKey, CAmount> > txids;
numvins = tx.vin.size();
numvouts = tx.vout.size();

View File

@@ -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;

View File

@@ -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<uint8_t> vopret; uint8_t *script,e,f,funcid;
GetOpReturnData(scriptPubKey,vopret);
script = (uint8_t *)vopret.data();
if ( 0 )
{
int32_t i;
for (i=0; i<vopret.size(); i++)
fprintf(stderr,"%02x",script[i]);
fprintf(stderr," <- opret\n");
}
if ( vopret.size() > 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<uint8_t> vopret; uint8_t *script,i;
GetOpReturnData(opret,vopret);
script = (uint8_t *)vopret.data();
{
for (i=0; i<vopret.size(); i++)
fprintf(stderr,"%02x",script[i]);
fprintf(stderr," <- gen opret.%c\n",funcid);
}
}
return(opret);
}
CScript MarmaraLoopOpret(uint8_t funcid,uint256 createtxid,CPubKey senderpk,int64_t amount,int32_t matures,std::string currency)
{
CScript opret; uint8_t evalcode = EVAL_MARMARA;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << createtxid << senderpk << amount << matures << currency);
return(opret);
}
CScript Marmara_scriptPubKey(int32_t height,CPubKey pk)
{
CTxOut ccvout;
if ( height > 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<sizeof(histo)/sizeof(*histo); ht++)
fprintf(stderr,"%d ",histo[ht]);
fprintf(stderr,"<- unlock histogram[%d] by days locked\n",(int32_t)(sizeof(histo)/sizeof(*histo)));
}
if ( (height & 1) != 0 )
return(0);
if ( tx.vout.size() == 2 && tx.vout[1].nValue == 0 )
{
if ( DecodeMaramaraCoinbaseOpRet(tx.vout[1].scriptPubKey,pk,ht,unlockht) == 'C' )
{
if ( ht == height && MarmaraUnlockht(height) == unlockht )
{
//fprintf(stderr,"ht.%d -> 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<std::pair<CAddressIndexKey, CAmount> > txids;
std::vector<uint8_t> 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; i<numvins; i++)
GetOpReturnData(tx.vout[tx.vout.size()-1].scriptPubKey,vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() < 2 || script[0] != EVAL_MARMARA )
return eval->Invalid("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; i<numvins; i++)
{
return eval->Invalid("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<uint8_t> 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> > 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<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::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<n; i++)
{
item = jitem(array,i);
if ( (pkstr= jstr(jitem(item,0),0)) != 0 && strlen(pkstr) == 66 )
shares += jdouble(jitem(item,1),0);
else
{
errorstr = (char *)"all items must be of the form [<pubke>, <shares>]";
break;
}
}
if ( errorstr == 0 && shares > SMALLVAL )
{
shares += shares * perc;
if ( (total= AddMarmaraCoinbases(cp,mtx,firstheight,poolpk,60)) > 0 )
{
for (i=0; i<n; i++)
{
item = jitem(array,i);
if ( (share= jdouble(jitem(item,1),0)) > 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);
}

View File

@@ -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<std::pair<CAddressIndexKey, CAmount> > txids;
numvins = tx.vin.size();
numvouts = tx.vout.size();

View File

@@ -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<std::pair<CAddressIndexKey, CAmount> > txids;
numvins = tx.vin.size();
numvouts = tx.vout.size();

View File

@@ -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<std::pair<CAddressIndexKey, CAmount> > txids;
numvins = tx.vin.size();
numvouts = tx.vout.size();

View File

@@ -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;

View File

@@ -1162,15 +1162,22 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
n = pblock->vtx[i].vout.size();
for (j=0; j<n; j++)
{
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(block.vtx[i].vout[j].nValue),j);
//fprintf(stderr,"(%d %.8f).%d ",i,dstr(pblock->vtx[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; i<scriptlen; i++)
// fprintf(stderr,"%02x",script[i]);
//fprintf(stderr," vout[1] %.8f vs %.8f\n",(double)checktoshis/COIN,(double)pblock->vtx[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; iter<maxiters; iter++)
@@ -2082,7 +2098,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
komodo_segids(hashbuf,nHeight-101,100);
if ( *blocktimep < tipindex->nTime+60 )
*blocktimep = tipindex->nTime+60;
//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
//fprintf(stderr,"Start scan of utxo for staking %u ht.%d\n",(uint32_t)time(NULL),nHeight);
bool resetstaker = false;
if ( array != 0 )

View File

@@ -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) ||

View File

@@ -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];

View File

@@ -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","");

View File

@@ -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)

View File

@@ -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<std::vector<unsigned char>> 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<std::vector<unsigned char>> 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);

View File

@@ -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<CScript> GetMinerScriptPubKey(CReserveKey& reservekey);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake = false);

View File

@@ -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 },

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<uint8_t> 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 <txid of 1st>
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<uint8_t> 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<uint8_t> 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 )

View File

@@ -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;
}