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

This commit is contained in:
blackjok3r
2019-01-23 16:57:05 +08:00
61 changed files with 7223 additions and 1530 deletions

View File

@@ -557,9 +557,9 @@ uint64_t komodo_seed(int32_t height)
return(seed);
}
uint32_t komodo_txtime(uint64_t *valuep,uint256 hash, int32_t n, char *destaddr)
uint32_t komodo_txtime(CScript &opret,uint64_t *valuep,uint256 hash, int32_t n, char *destaddr)
{
CTxDestination address; CTransaction tx; uint256 hashBlock;
CTxDestination address; CTransaction tx; uint256 hashBlock; int32_t numvouts;
*valuep = 0;
if (!GetTransaction(hash, tx,
#ifndef KOMODO_ZCASH
@@ -570,10 +570,12 @@ uint32_t komodo_txtime(uint64_t *valuep,uint256 hash, int32_t n, char *destaddr)
//fprintf(stderr,"ERROR: %s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
return(0);
}
numvouts = tx.vout.size();
//fprintf(stderr,"%s/v%d locktime.%u\n",hash.ToString().c_str(),n,(uint32_t)tx.nLockTime);
if ( n < tx.vout.size() )
if ( n < numvouts )
{
*valuep = tx.vout[n].nValue;
opret = tx.vout[numvouts-1].scriptPubKey;
if (ExtractDestination(tx.vout[n].scriptPubKey, address))
strcpy(destaddr,CBitcoinAddress(address).ToString().c_str());
}
@@ -614,12 +616,12 @@ uint32_t komodo_txtime2(uint64_t *valuep,uint256 hash,int32_t n,char *destaddr)
int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
{
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid;
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 )
{
txid = pblock->vtx[n-1].vin[0].prevout.hash;
vout = pblock->vtx[n-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr);
txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
@@ -634,23 +636,41 @@ int32_t komodo_WhoStaked(CBlock *pblock, CTxDestination &addressout)
return(0);
}
int32_t komodo_isPoS(CBlock *pblock)
bool MarmaraPoScheck(char *destaddr,CScript opret,CTransaction staketx);
int32_t komodo_isPoS(CBlock *pblock,int32_t height)
{
int32_t n,vout; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid;
int32_t n,vout,numvouts; uint32_t txtime; uint64_t value; char voutaddr[64],destaddr[64]; CTxDestination voutaddress; uint256 txid; CScript opret;
if ( ASSETCHAINS_STAKED != 0 )
{
if ( (n= pblock->vtx.size()) > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1 )
n = pblock->vtx.size();
//fprintf(stderr,"ht.%d check for PoS numtx.%d numvins.%d numvouts.%d\n",height,n,(int32_t)pblock->vtx[n-1].vin.size(),(int32_t)pblock->vtx[n-1].vout.size());
if ( n > 1 && pblock->vtx[n-1].vin.size() == 1 && pblock->vtx[n-1].vout.size() == 1+(ASSETCHAINS_MARMARA!=0) )
{
txid = pblock->vtx[n-1].vin[0].prevout.hash;
vout = pblock->vtx[n-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr);
txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
if ( ExtractDestination(pblock->vtx[n-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
if ( strcmp(destaddr,voutaddr) == 0 && pblock->vtx[n-1].vout[0].nValue == value )
//fprintf(stderr,"voutaddr.%s vs destaddr.%s\n",voutaddr,destaddr);
if ( pblock->vtx[n-1].vout[0].nValue == value && strcmp(destaddr,voutaddr) == 0 )
{
//fprintf(stderr,"is PoS block!\n");
return(1);
if ( ASSETCHAINS_MARMARA == 0 )
return(1);
else
{
if ( pblock->vtx[n-1].vout[0].scriptPubKey.IsPayToCryptoCondition() != 0 && (numvouts= pblock->vtx[n-1].vout.size()) == 2 )
{
//fprintf(stderr,"validate proper %s %s signature and unlockht preservation\n",voutaddr,destaddr);
return(MarmaraPoScheck(destaddr,opret,pblock->vtx[n-1]));
}
else
{
fprintf(stderr,"reject ht.%d PoS block\n",height);
return(strcmp(ASSETCHAINS_SYMBOL,"MTST2") == 0); // allow until MTST3
}
}
}
}
}
@@ -1162,15 +1182,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);
}
@@ -1183,7 +1210,7 @@ uint32_t komodo_segid32(char *coinaddr)
int8_t komodo_segid(int32_t nocache,int32_t height)
{
CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; int8_t segid = -1;
CTxDestination voutaddress; CBlock block; CBlockIndex *pindex; uint64_t value; uint32_t txtime; char voutaddr[64],destaddr[64]; int32_t txn_count,vout; uint256 txid; CScript opret; int8_t segid = -1;
if ( height > 0 && (pindex= komodo_chainactive(height)) != 0 )
{
if ( nocache == 0 && pindex->segid >= -1 )
@@ -1195,7 +1222,7 @@ int8_t komodo_segid(int32_t nocache,int32_t height)
{
txid = block.vtx[txn_count-1].vin[0].prevout.hash;
vout = block.vtx[txn_count-1].vin[0].prevout.n;
txtime = komodo_txtime(&value,txid,vout,destaddr);
txtime = komodo_txtime(opret,&value,txid,vout,destaddr);
if ( ExtractDestination(block.vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
@@ -1438,12 +1465,14 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
pindex = it != mapBlockIndex.end() ? it->second : NULL;
if ( pindex != 0 && pindex->segid >= -1 )
{
//fprintf(stderr,"isPoSblock segid.%d\n",pindex->segid);
if ( pindex->segid == -1 )
return(0);
else return(1);
}
txn_count = pblock->vtx.size();
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 )
//fprintf(stderr,"checkblock n.%d vins.%d vouts.%d %.8f %.8f\n",txn_count,(int32_t)pblock->vtx[txn_count-1].vin.size(),(int32_t)pblock->vtx[txn_count-1].vout.size(),(double)pblock->vtx[txn_count-1].vout[0].nValue/COIN,(double)pblock->vtx[txn_count-1].vout[1].nValue/COIN);
if ( txn_count > 1 && pblock->vtx[txn_count-1].vin.size() == 1 && pblock->vtx[txn_count-1].vout.size() == 1 + (ASSETCHAINS_MARMARA!=0) )
{
it = mapBlockIndex.find(pblock->hashPrevBlock);
if ( it != mapBlockIndex.end() && (previndex = it->second) != NULL )
@@ -1453,7 +1482,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
if ( prevtime != 0 )
{
if ( komodo_isPoS(pblock) != 0 )
if ( komodo_isPoS(pblock,height) != 0 )
{
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"");
}
@@ -1488,7 +1517,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
}
if ( slowflag == 0 && isPoS == 0 ) // maybe previous block is not seen yet, do the best approx
{
if ( komodo_isPoS(pblock) != 0 )
if ( komodo_isPoS(pblock,height) != 0 )
isPoS = 1;
}
if ( slowflag != 0 && isPoS != 0 )
@@ -1699,11 +1728,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 +1756,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 +1774,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()) )
@@ -1796,6 +1830,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1);
}
}
//fprintf(stderr,"ASSETCHAINS_STAKED.%d ht.%d\n",(int32_t)ASSETCHAINS_STAKED,height);
if ( ASSETCHAINS_STAKED != 0 && height >= 2 ) // must PoS or have at least 16x better PoW
{
if ( (is_PoSblock= komodo_is_PoSblock(slowflag,height,pblock,bnTarget,bhash)) == 0 )
@@ -1858,7 +1893,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 +2073,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++)
@@ -2059,6 +2098,9 @@ uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komod
return(0);
}
int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew);
uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht);
int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig)
{
static struct komodo_staking *array; static int32_t numkp,maxkp; static uint32_t lasttime;
@@ -2082,7 +2124,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 )
@@ -2107,31 +2149,60 @@ 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 )
{
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
{
struct CCcontract_info *cp,C; uint256 txid; int32_t vout,ht,unlockht; CAmount nValue; char coinaddr[64]; CPubKey mypk,Marmarapk,pk;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
cp = CCinit(&C,EVAL_MARMARA);
mypk = pubkey2pk(Mypubkey());
Marmarapk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,coinaddr,Marmarapk,mypk);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
if ( (nValue= it->second.satoshis) < COIN )
continue;
if ( GetTransaction(txid,tx,hashBlock,true) != 0 && (pindex= komodo_getblockindex(hashBlock)) != 0 && myIsutxo_spentinmempool(txid,vout) == 0 )
{
const CScript &scriptPubKey = tx.vout[vout].scriptPubKey;
if ( DecodeMaramaraCoinbaseOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,pk,ht,unlockht) != 0 && pk == mypk )
{
array = komodo_addutxo(array,&numkp,&maxkp,(uint32_t)pindex->nTime,(uint64_t)nValue,txid,vout,coinaddr,hashbuf,(CScript)scriptPubKey);
}
// else fprintf(stderr,"SKIP addutxo %.8f numkp.%d vs max.%d\n",(double)nValue/COIN,numkp,maxkp);
}
}
}
@@ -2213,16 +2284,26 @@ 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 (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
if ( ASSETCHAINS_MARMARA == 0 )
{
signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, *utxovaluep, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
UpdateTransaction(txNew,0,sigdata);
ptr = (uint8_t *)&sigdata.scriptSig[0];
siglen = sigdata.scriptSig.size();
for (i=0; i<siglen; i++)
utxosig[i] = ptr[i];//, fprintf(stderr,"%02x",ptr[i]);
}
else
{
siglen = MarmaraSignature(utxosig,txNew);
if ( siglen > 0 )
signSuccess = true;
else signSuccess = false;
}
if (!signSuccess)
fprintf(stderr,"failed to create signature\n");
else
{
//fprintf(stderr," siglen.%d\n",siglen);
//fprintf(stderr,"best %u from %u, gap %d lag.%d\n",earliest,*blocktimep,(int32_t)(earliest - *blocktimep),(int32_t)(time(NULL) - *blocktimep));
*blocktimep = earliest;