Merge pull request #1285 from blackjok3rtt/FSMLABS

Merge from LABS.
This commit is contained in:
jl777
2019-02-26 00:37:02 -11:00
committed by GitHub
47 changed files with 2216 additions and 637 deletions

View File

@@ -204,6 +204,7 @@ BITCOIN_CORE_H = \
mruset.h \
net.h \
netbase.h \
notaries_staked.h \
noui.h \
paymentdisclosure.h \
paymentdisclosuredb.h \
@@ -311,6 +312,7 @@ libbitcoin_server_a_SOURCES = \
chain.cpp \
checkpoints.cpp \
crosschain.cpp \
crosschain_authority.cpp \
crypto/haraka.h \
crypto/haraka_portable.h \
crypto/verus_hash.h \
@@ -325,6 +327,7 @@ libbitcoin_server_a_SOURCES = \
metrics.h \
miner.cpp \
net.cpp \
notaries_staked.cpp \
noui.cpp \
notarisationdb.cpp \
paymentdisclosure.cpp \

View File

@@ -154,46 +154,17 @@ int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t time
return komodo_notaries(pubkeys, height, timestamp);
}
bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
{
if (tx.vin.size() < 11) return false;
uint8_t seenNotaries[64] = {0};
uint8_t notaries[64][33];
int nNotaries = GetNotaries(notaries, height, timestamp);
CrosschainAuthority auth;
auth.requiredSigs = 11;
auth.size = GetNotaries(auth.notaries, height, timestamp);
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
{
// Get notary pubkey
CTransaction tx;
uint256 hashBlock;
if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
if (tx.vout.size() < txIn.prevout.n) return false;
CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
if (spk.size() != 35) return false;
std::vector<unsigned char> scriptVec = std::vector<unsigned char>(spk.begin(),spk.end());
const unsigned char *pk = scriptVec.data();
if (pk++[0] != 33) return false;
if (pk[33] != OP_CHECKSIG) return false;
// Check it's a notary
for (int i=0; i<nNotaries; i++) {
if (!seenNotaries[i]) {
if (memcmp(pk, notaries[i], 33) == 0) {
seenNotaries[i] = 1;
goto found;
}
}
}
return false;
found:;
}
return true;
return CheckTxAuthority(tx, auth);
}
/*
* Get MoM from a notarisation tx hash (on KMD)
*/

View File

@@ -478,5 +478,3 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
}
return Valid();
}

View File

@@ -289,15 +289,22 @@ void *chainparams_commandline(void *ptr)
mainParams.pchMessageStart[2] = (ASSETCHAINS_MAGIC >> 16) & 0xff;
mainParams.pchMessageStart[3] = (ASSETCHAINS_MAGIC >> 24) & 0xff;
fprintf(stderr,">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY);
if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH)
if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
{
// this is only good for 60 second blocks with an averaging window of 45. for other parameters, use:
// nLwmaAjustedWeight = (N+1)/2 * (0.9989^(500/nPowAveragingWindow)) * nPowTargetSpacing
// nLwmaAjustedWeight = (N+1)/2 * (0.9989^(500/nPowAveragingWindow)) * nPowTargetSpacing
mainParams.consensus.nLwmaAjustedWeight = 1350;
mainParams.consensus.nPowAveragingWindow = 45;
mainParams.consensus.powAlternate = uint256S("00000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
}
else if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1)
{
// this is only good for 60 second blocks with an averaging window of 45. for other parameters, use:
// nLwmaAjustedWeight = (N+1)/2 * (0.9989^(500/nPowAveragingWindow)) * nPowTargetSpacing
mainParams.consensus.nLwmaAjustedWeight = 1350;
mainParams.consensus.nPowAveragingWindow = 45;
mainParams.consensus.powAlternate = uint256S("0000000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
}
if (ASSETCHAINS_LWMAPOS != 0)
{
@@ -668,7 +675,7 @@ public:
BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K));
nEquihashN = N;
nEquihashK = K;
genesis = CreateGenesisBlock(
1296688602,
uint256S("0x0000000000000000000000000000000000000000000000000000000000000009"),

View File

@@ -446,7 +446,7 @@ class CCoinsViewCache;
/**
* A reference to a mutable cache entry. Encapsulating it allows us to run
* cleanup code after the modification is finished, and keeping track of
* concurrent modifications.
* concurrent modifications.
*/
class CCoinsModifier
{
@@ -503,7 +503,7 @@ protected:
/**
* Make mutable so that we can "fill the cache" even from Get-methods
* declared as "const".
* declared as "const".
*/
mutable uint256 hashBlock;
mutable CCoinsMap cacheCoins;

View File

@@ -66,7 +66,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
int seenOwnNotarisations = 0;
bool txscl = IsTXSCL(symbol);
int authority = GetSymbolAuthority(symbol);
for (int i=0; i<NOTARISATION_SCAN_LIMIT_BLOCKS; i++) {
if (i > kmdHeight) break;
@@ -90,13 +90,20 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
if (seenOwnNotarisations == 1) {
BOOST_FOREACH(Notarisation& nota, notarisations) {
if (IsTXSCL(nota.second.symbol) == txscl)
if (nota.second.ccId == targetCCid)
moms.push_back(nota.second.MoM);
if (GetSymbolAuthority(nota.second.symbol) == authority)
if (nota.second.ccId == targetCCid) {
moms.push_back(nota.second.MoM);
//fprintf(stderr, "added mom: %s\n",nota.second.MoM.GetHex().data());
}
}
}
}
// Not enough own notarisations found to return determinate MoMoM
destNotarisationTxid = uint256();
moms.clear();
return uint256();
end:
return GetMerkleRoot(moms);
}

View File

@@ -18,6 +18,18 @@
#include "cc/eval.h"
const int CROSSCHAIN_KOMODO = 1;
const int CROSSCHAIN_TXSCL = 2;
const int CROSSCHAIN_STAKED = 3;
typedef struct CrosschainAuthority {
uint8_t notaries[64][33];
int8_t size;
int8_t requiredSigs;
} CrosschainAuthority;
int GetSymbolAuthority(const char* symbol);
bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth);
/* On assetchain */
TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx);

View File

@@ -0,0 +1,70 @@
#include "cc/eval.h"
#include "crosschain.h"
#include "notarisationdb.h"
#include "notaries_staked.h"
int GetSymbolAuthority(const char* symbol)
{
if (strncmp(symbol, "TXSCL", 5) == 0)
return CROSSCHAIN_TXSCL;
if (is_STAKED(symbol) != 0) {
//printf("RETURNED CROSSCHAIN STAKED AS TRUE\n");
return CROSSCHAIN_STAKED;
}
//printf("RETURNED CROSSCHAIN KOMODO AS TRUE\n");
return CROSSCHAIN_KOMODO;
}
bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth)
{
EvalRef eval;
if (tx.vin.size() < auth.requiredSigs) return false;
uint8_t seen[64] = {0};
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
{
// Get notary pubkey
CTransaction tx;
uint256 hashBlock;
if (!eval->GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
if (tx.vout.size() < txIn.prevout.n) return false;
CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
if (spk.size() != 35) return false;
const unsigned char *pk = &spk[0];
if (pk++[0] != 33) return false;
if (pk[33] != OP_CHECKSIG) return false;
// Check it's a notary
for (int i=0; i<auth.size; i++) {
if (!seen[i]) {
if (memcmp(pk, auth.notaries[i], 33) == 0) {
seen[i] = 1;
goto found;
} else {
//printf("notary.%i is not valid!\n",i);
}
}
}
return false;
found:;
}
return true;
}
/*
const CrosschainAuthority auth_STAKED = [&](){
CrosschainAuthority auth;
auth.requiredSigs = (num_notaries_STAKED / 5);
auth.size = num_notaries_STAKED;
for (int n=0; n<auth.size; n++)
for (size_t i=0; i<33; i++)
sscanf(notaries_STAKED[n][1]+(i*2), "%2hhx", auth.notaries[n]+i);
return auth;
}();
*/

View File

@@ -29,7 +29,9 @@ int32_t komodo_nextheight();
CTransaction MakeImportCoinTransaction(const TxProof proof, const CTransaction burnTx, const std::vector<CTxOut> payouts, uint32_t nExpiryHeightOverride)
{
std::vector<uint8_t> payload = E_MARSHAL(ss << EVAL_IMPORTCOIN);
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
if (mtx.fOverwintered)
mtx.nExpiryHeight = 0;
mtx.vin.push_back(CTxIn(COutPoint(burnTx.GetHash(), 10e8), CScript() << payload));
mtx.vout = payouts;
auto importData = E_MARSHAL(ss << proof; ss << burnTx);
@@ -70,20 +72,10 @@ bool UnmarshalBurnTx(const CTransaction &burnTx, std::string &targetSymbol, uint
std::vector<uint8_t> burnOpret; uint32_t ccid = 0;
if (burnTx.vout.size() == 0) return false;
GetOpReturnData(burnTx.vout.back().scriptPubKey, burnOpret);
E_UNMARSHAL(burnOpret, ss >> VARINT(ccid));
/*if ( ccid != 0xffffffff )
{
return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid);
ss >> targetSymbol;
ss >> payoutsHash);
}
else*/
{
return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof);
}
return E_UNMARSHAL(burnOpret, ss >> VARINT(*targetCCid);
ss >> targetSymbol;
ss >> payoutsHash;
ss >> rawproof);
}
@@ -111,7 +103,7 @@ bool VerifyCoinImport(const CScript& scriptSig, TransactionSignatureChecker& che
auto pc = scriptSig.begin();
opcodetype opcode;
std::vector<uint8_t> evalScript;
auto f = [&] () {
if (!scriptSig.GetOp(pc, opcode, evalScript))
return false;

View File

@@ -1177,7 +1177,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
globalVerifyHandle.reset(new ECCVerifyHandle());
// set the hash algorithm to use for this chain
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH;
// Again likely better solution here, than using long IF ELSE.
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1;
CVerusHash::init();
CVerusHashV2::init();
if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
@@ -1185,6 +1186,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// initialize VerusHash
CBlockHeader::SetVerusHash();
}
else if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1)
{
// initialize VerusHashV2
CBlockHeader::SetVerusHashV2();
}
// Sanity check
if (!InitSanityCheck())
@@ -1548,6 +1554,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (fReindex) {
boost::filesystem::remove(GetDataDir() / "komodostate");
boost::filesystem::remove(GetDataDir() / "signedmasks");
pblocktree->WriteReindexing(true);
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
if (fPruneMode)

View File

@@ -16,6 +16,7 @@
#ifndef H_KOMODO_H
#define H_KOMODO_H
#include "komodo_defs.h"
#include "notaries_staked.h"
#ifdef _WIN32
#define printf(...)
@@ -36,7 +37,8 @@
int32_t gettxout_scriptPubKey(uint8_t *scriptPubkey,int32_t maxsize,uint256 txid,int32_t n);
void komodo_event_rewind(struct komodo_state *sp,char *symbol,int32_t height);
void komodo_connectblock(CBlockIndex *pindex,CBlock& block);
int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block);
bool check_pprevnotarizedht();
#include "komodo_structs.h"
#include "komodo_globals.h"
@@ -530,7 +532,7 @@ int32_t komodo_validate_chain(uint256 srchash,int32_t notarized_height)
} else return(1);
}
int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp)
int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp)
{
static uint256 zero; static FILE *signedfp;
int32_t opretlen,nid,offset,k,MoMdepth,matched,len = 0; uint256 MoM,srchash,desttxid; uint8_t crypto777[33]; struct komodo_state *sp; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN];
@@ -615,7 +617,7 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
if ( j == 1 && opretlen >= len+offset-opoffset )
{
memset(&MoMoMdata,0,sizeof(MoMoMdata));
if ( matched == 0 && bitweight(signedmask) >= KOMODO_MINRATIFY )
if ( matched == 0 && signedmask != 0 && bitweight(signedmask) >= KOMODO_MINRATIFY )
notarized = 1;
if ( strcmp("PIZZA",ccdata.symbol) == 0 || strncmp("TXSCL",ccdata.symbol,5) == 0 )
notarized = 1;
@@ -684,7 +686,7 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
else
{
komodo_rwccdata(ASSETCHAINS_SYMBOL,1,&ccdata,&MoMoMdata);
if ( matched != 0 )
if ( !fJustCheck && matched != 0 )
printf("[%s] matched.%d VALID (%s) MoM.%s [%d] CCid.%u\n",ASSETCHAINS_SYMBOL,matched,ccdata.symbol,MoM.ToString().c_str(),MoMdepth&0xffff,(MoMdepth>>16)&0xffff);
}
if ( MoMoMdata.pairs != 0 )
@@ -694,6 +696,11 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
}
else if ( ASSETCHAINS_SYMBOL[0] == 0 && matched != 0 && notarized != 0 && validated != 0 )
komodo_rwccdata((char *)"KMD",1,&ccdata,0);
// Because of reorgs its not possible to use notarizations that are in order. If its validated pay the notaries!
if ( fJustCheck )
return(-2);
if ( matched != 0 && *notarizedheightp > sp->NOTARIZED_HEIGHT && *notarizedheightp < height )
{
sp->NOTARIZED_HEIGHT = *notarizedheightp;
@@ -706,11 +713,8 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
}
komodo_stateupdate(height,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,sp->MoM,sp->MoMdepth);
if ( ASSETCHAINS_SYMBOL[0] != 0 )
printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,*notarizedheightp,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth);
if ( 0 && RemoveOrphanedBlocks(*notarizedheightp))
{
//fprintf(stderr, "Sucessfully removed all known orphaned blocks before height %d\n",*notarizedheightp);
}
printf("[%s] ht.%d NOTARIZED.%d %s.%s %sTXID.%s lens.(%d %d) MoM.%s %d\n",ASSETCHAINS_SYMBOL,height,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),ASSETCHAINS_SYMBOL[0]==0?"BTC":"KMD",desttxid.ToString().c_str(),opretlen,len,sp->MoM.ToString().c_str(),sp->MoMdepth);
if ( ASSETCHAINS_SYMBOL[0] == 0 )
{
if ( signedfp == 0 )
@@ -735,13 +739,14 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen-len+4+3+(scriptbuf[1] == 0x4d),j,zero,0);
}
}
}
} //else if ( fJustCheck )
// return (-3); // if the notarisation is only invalid because its out of order it cannot be mined in a block with a valid one!
} else if ( opretlen != 149 && height > 600000 && matched != 0 )
printf("%s validated.%d notarized.%d %llx reject ht.%d NOTARIZED.%d prev.%d %s.%s DESTTXID.%s len.%d opretlen.%d\n",ccdata.symbol,validated,notarized,(long long)signedmask,height,*notarizedheightp,sp->NOTARIZED_HEIGHT,ASSETCHAINS_SYMBOL[0]==0?"KMD":ASSETCHAINS_SYMBOL,srchash.ToString().c_str(),desttxid.ToString().c_str(),len,opretlen);
}
else if ( matched != 0 && i == 0 && j == 1 && opretlen == 149 )
{
if ( notaryid >= 0 && notaryid < 64 )
if ( !fJustCheck && notaryid >= 0 && notaryid < 64 )
komodo_paxpricefeed(height,&scriptbuf[len],opretlen);
}
else if ( matched != 0 )
@@ -760,7 +765,7 @@ int32_t komodo_voutupdate(int32_t *isratificationp,int32_t notaryid,uint8_t *scr
printf("ISRATIFICATION (%s)\n",(char *)&scriptbuf[len+32*2+4]);
}
}
if ( *isratificationp == 0 && (signedmask != 0 || (scriptbuf[len] != 'X' && scriptbuf[len] != 'A')) ) // && scriptbuf[len] != 'I')
komodo_stateupdate(height,0,0,0,txhash,0,0,0,0,0,0,value,&scriptbuf[len],opretlen,j,zero,0);
}
@@ -797,16 +802,19 @@ int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys
return(-1);
}
void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
// int32_t !
int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block)
{
static int32_t hwmheight;
int32_t staked_era; static int32_t lastStakedEra;
std::vector<int32_t> notarisations;
uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp;
uint8_t scriptbuf[10001],pubkeys[64][33],rmd160[20],scriptPubKey[35]; uint256 zero,btctxid,txhash;
int32_t i,j,k,numnotaries,notarized,scriptlen,isratification,nid,numvalid,specialtx,notarizedheight,notaryid,len,numvouts,numvins,height,txn_count;
if ( pindex == 0 )
{
fprintf(stderr,"komodo_connectblock null pindex\n");
return;
return(0);
}
memset(&zero,0,sizeof(zero));
komodo_init(pindex->GetHeight());
@@ -814,9 +822,32 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
if ( (sp= komodo_stateptr(symbol,dest)) == 0 )
{
fprintf(stderr,"unexpected null komodostateptr.[%s]\n",ASSETCHAINS_SYMBOL);
return;
return(0);
}
//fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight);
// Wallet Filter. Disabled here. Cant be activated by notaries or pools with some changes.
if ( 0 & is_STAKED(ASSETCHAINS_SYMBOL) != 0 || IS_STAKED_NOTARY > -1 )
{
staked_era = STAKED_era(pindex->GetBlockTime());
if ( !fJustCheck && staked_era != lastStakedEra )
{
uint8_t tmp_pubkeys[64][33];
int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era);
UpdateNotaryAddrs(tmp_pubkeys,numSN);
STAKED_ERA = staked_era;
if ( NOTARYADDRS[0][0] != 0 && NOTARY_PUBKEY33[0] != 0 )
{
if ( (IS_STAKED_NOTARY= updateStakedNotary()) > -1 )
{
IS_KOMODO_NOTARY = 0;
if ( MIN_RECV_SATS == -1 )
MIN_RECV_SATS = 100000000;
fprintf(stderr, "Staked Notary Protection Active! NotaryID.%d RADD.%s ERA.%d MIN_TX_VALUE.%lu \n",IS_STAKED_NOTARY,NOTARY_ADDRESS.c_str(),staked_era,MIN_RECV_SATS);
}
}
lastStakedEra = staked_era;
}
}
//fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight());
numnotaries = komodo_notaries(pubkeys,pindex->GetHeight(),pindex->GetBlockTime());
calc_rmd160_sha256(rmd160,pubkeys[0],33);
if ( pindex->GetHeight() > hwmheight )
@@ -829,16 +860,27 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
komodo_purge_ccdata((int32_t)pindex->GetHeight());
hwmheight = pindex->GetHeight();
}
komodo_event_rewind(sp,symbol,pindex->GetHeight());
komodo_stateupdate(pindex->GetHeight(),0,0,0,zero,0,0,0,0,-pindex->GetHeight(),pindex->nTime,0,0,0,0,zero,0);
if (!fJustCheck)
{
komodo_event_rewind(sp,symbol,pindex->GetHeight());
komodo_stateupdate(pindex->GetHeight(),0,0,0,zero,0,0,0,0,-pindex->GetHeight(),pindex->nTime,0,0,0,0,zero,0);
}
}
komodo_currentheight_set(chainActive.LastTip()->GetHeight());
int transaction = 0;
if ( pindex != 0 )
{
height = pindex->GetHeight();
txn_count = block.vtx.size();
for (i=0; i<txn_count; i++)
{
if ( (is_STAKED(ASSETCHAINS_SYMBOL) != 0 && staked_era == 0) || (is_STAKED(ASSETCHAINS_SYMBOL) == 255) ) {
// in era gap or chain banned, no point checking any invlaid notarisations.
break;
}
// Notary pay chains need notarisation in position 1, ignore the rest on validation. Check notarisation is 1 on check.
if ( !fJustCheck && i > 1 && ASSETCHAINS_NOTARY_PAY[0] != 0 )
break;
txhash = block.vtx[i].GetHash();
numvouts = block.vtx[i].vout.size();
notaryid = -1;
@@ -863,11 +905,11 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
} //else printf("cant get scriptPubKey for ht.%d txi.%d vin.%d\n",height,i,j);
}
numvalid = bitweight(signedmask);
if ( (((height < 90000 || (signedmask & 1) != 0) && numvalid >= KOMODO_MINRATIFY) ||
if ( ((height < 90000 || (signedmask & 1) != 0) && numvalid >= KOMODO_MINRATIFY) ||
(numvalid >= KOMODO_MINRATIFY && ASSETCHAINS_SYMBOL[0] != 0) ||
numvalid > (numnotaries/5)) )
numvalid > (numnotaries/5) )
{
if ( ASSETCHAINS_SYMBOL[0] != 0 )
if ( !fJustCheck && ASSETCHAINS_SYMBOL[0] != 0)
{
static FILE *signedfp;
if ( signedfp == 0 )
@@ -884,6 +926,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
fwrite(&signedmask,1,sizeof(signedmask),signedfp);
fflush(signedfp);
}
transaction = i;
printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d <<<<<<<<<<< notarized\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts);
}
notarized = 1;
@@ -909,10 +952,16 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 )
printf("%.8f ",dstr(block.vtx[i].vout[j].nValue));
len = block.vtx[i].vout[j].scriptPubKey.size();
if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) )
{
memcpy(scriptbuf,(uint8_t *)&block.vtx[i].vout[j].scriptPubKey[0],len);
notaryid = komodo_voutupdate(&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,&notarizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime());
notaryid = komodo_voutupdate(fJustCheck,&isratification,notaryid,scriptbuf,len,height,txhash,i,j,&voutmask,&specialtx,&notarizedheight,(uint64_t)block.vtx[i].vout[j].nValue,notarized,signedmask,(uint32_t)chainActive.LastTip()->GetBlockTime());
if ( fJustCheck && notaryid == -2 )
{
// We see a valid notarisation here, save its location.
notarisations.push_back(i);
}
if ( 0 && i > 0 )
{
for (k=0; k<len; k++)
@@ -925,7 +974,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
printf(") ");
if ( 0 && ASSETCHAINS_SYMBOL[0] == 0 )
printf("[%s] ht.%d txi.%d signedmask.%llx numvins.%d numvouts.%d notarized.%d special.%d isratification.%d\n",ASSETCHAINS_SYMBOL,height,i,(long long)signedmask,numvins,numvouts,notarized,specialtx,isratification);
if ( notarized != 0 && (notarizedheight != 0 || specialtx != 0) )
if ( !fJustCheck && (notarized != 0 && (notarizedheight != 0 || specialtx != 0)) )
{
if ( isratification != 0 )
{
@@ -963,14 +1012,23 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block)
}
}
}
if ( IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 )
if ( !fJustCheck && IS_KOMODO_NOTARY != 0 && ASSETCHAINS_SYMBOL[0] == 0 )
printf("%s ht.%d\n",ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL,height);
if ( pindex->GetHeight() == hwmheight )
if ( !fJustCheck && pindex->GetHeight() == hwmheight )
komodo_stateupdate(height,0,0,0,zero,0,0,0,0,height,(uint32_t)pindex->nTime,0,0,0,0,zero,0);
} else fprintf(stderr,"komodo_connectblock: unexpected null pindex\n");
//KOMODO_INITDONE = (uint32_t)time(NULL);
//fprintf(stderr,"%s end connect.%d\n",ASSETCHAINS_SYMBOL,pindex->GetHeight());
if (fJustCheck)
{
if ( notarisations.size() == 0 )
return(0);
if ( notarisations.size() == 1 && notarisations[0] == 1 )
return(1);
if ( notarisations.size() > 1 || (notarisations.size() == 1 && notarisations[0] != 1) )
return(-1);
}
else return(0);
}
#endif

View File

@@ -25,9 +25,14 @@
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
int32_t komodo_electednotary(int32_t *numnotariesp,uint8_t *pubkey33,int32_t height,uint32_t timestamp);
int32_t komodo_voutupdate(bool fJustCheck,int32_t *isratificationp,int32_t notaryid,uint8_t *scriptbuf,int32_t scriptlen,int32_t height,uint256 txhash,int32_t i,int32_t j,uint64_t *voutmaskp,int32_t *specialtxp,int32_t *notarizedheightp,uint64_t value,int32_t notarized,uint64_t signedmask,uint32_t timestamp);
unsigned int lwmaGetNextPOSRequired(const CBlockIndex* pindexLast, const Consensus::Params& params);
bool EnsureWalletIsAvailable(bool avoidException);
extern bool fRequestShutdown;
int32_t MarmaraSignature(uint8_t *utxosig,CMutableTransaction &txNew);
uint8_t DecodeMaramaraCoinbaseOpRet(const CScript scriptPubKey,CPubKey &pk,int32_t &height,int32_t &unlockht);
//#define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"curl",(char *)"http://127.0.0.1:7776",0,0,(char *)(cmdstr))
struct MemoryStruct { char *memory; size_t size; };
@@ -1180,6 +1185,10 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
uint64_t komodo_commission(const CBlock *pblock,int32_t height)
{
// LABS fungible chains, cannot have any block reward!
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 )
return(0);
int32_t i,j,n=0,txn_count; int64_t nSubsidy; uint64_t commission,total = 0;
txn_count = pblock->vtx.size();
if ( ASSETCHAINS_FOUNDERS != 0 )
@@ -1190,7 +1199,12 @@ uint64_t komodo_commission(const CBlock *pblock,int32_t height)
if ( ASSETCHAINS_FOUNDERS > 1 )
{
if ( (height % ASSETCHAINS_FOUNDERS) == 0 )
commission = commission * ASSETCHAINS_FOUNDERS;
{
if ( ASSETCHAINS_FOUNDERS_REWARD == 0 )
commission = commission * ASSETCHAINS_FOUNDERS;
else
commission = ASSETCHAINS_FOUNDERS_REWARD;
}
else commission = 0;
}
}
@@ -1250,7 +1264,8 @@ int8_t komodo_segid(int32_t nocache,int32_t height)
if ( strcmp(destaddr,voutaddr) == 0 && block.vtx[txn_count-1].vout[0].nValue == value )
{
segid = komodo_segid32(voutaddr) & 0x3f;
//fprintf(stderr,"komodo_segid.(%d) -> %02x\n",height,segid);
pindex->segid = segid;
//fprintf(stderr,"komodo_segid.(%d) -> %d\n",height,pindex->segid);
}
} else fprintf(stderr,"komodo_segid ht.%d couldnt extract voutaddress\n",height);
}
@@ -1293,100 +1308,18 @@ uint32_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256
return(addrhash.uints[0]);
}
uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr)
{
bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t diff=0,segid,minage,i,iter=0; uint32_t txtime,segid32,winner = 0 ; uint64_t value,coinage;
txtime = komodo_txtime2(&value,txid,vout,address);
if ( validateflag == 0 )
{
//fprintf(stderr,"blocktime.%u -> ",blocktime);
if ( blocktime < prevtime+3 )
blocktime = prevtime+3;
if ( blocktime < GetAdjustedTime()-60 )
blocktime = GetAdjustedTime()+30;
//fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime);
}
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
{
//fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
return(0);
}
if ( value < SATOSHIDEN )
return(0);
value /= SATOSHIDEN;
mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
komodo_segids(hashbuf,nHeight-101,100);
segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
segid = ((nHeight + segid32) & 0x3f);
for (iter=0; iter<600; iter++)
{
if ( blocktime+iter+segid*2 < txtime+minage )
continue;
diff = (iter + blocktime - txtime - minage);
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
{
//printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage);
diff = 3600*24*30;
}
if ( iter > 0 )
diff += segid*2;
coinage = (value * diff);
if ( blocktime+iter+segid*2 > prevtime+480 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (UintToArith256(hash) / coinage256);
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
//fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid);
blocktime += iter;
blocktime += segid * 2;
}
break;
}
if ( validateflag != 0 )
{
/*for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff);*/
break;
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 0 && validateflag != 0 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d ht.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff,nHeight);
}
if ( nHeight < 10 )
return(blocktime);
return(blocktime * winner);
}
arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc)
{
int32_t oldflag = 0,dispflag = 0;
CBlockIndex *pindex; arith_uint256 easydiff,bnTarget,hashval,sum,ave; bool fNegative,fOverflow; int32_t i,n,m,ht,percPoS,diff,val;
*percPoSp = percPoS = 0;
if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
if ( height <= 10 || (ASSETCHAINS_STAKED == 100 && height <= 100) )
return(target);
sum = arith_uint256(0);
ave = sum;
easydiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
easydiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow);
for (i=n=m=0; i<100; i++)
{
ht = height - 100 + i;
@@ -1408,12 +1341,22 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
sum += UintToArith256(pindex->GetBlockHash());
m++;
}
}
} //else fprintf(stderr, "pindex returned null ht.%i\n",ht);
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 && (i % 10) == 9 )
fprintf(stderr," %d, ",percPoS);
}
if ( m+n < 100 )
percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
{
// We do actual PoS % at the start. Requires coin distribution in first 10 blocks!
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
percPoS = (percPoS*100) / (m+n);
else
// This seems to be inverse. The actual PoS % is backwards in the first 100 blocks.
// I dont't understand the math here, or why its backwards, so I am just disabling it for VerusHash.
// No doubt this is probably wrong for equihash aswell, we may need to test an equihash chain with the rule above.
// Need to ask james what the deal is here! Seems to be causeing ALL the problems.
percPoS = ((percPoS * n) + (goalperc * (100-n))) / 100;
}
if ( dispflag != 0 && ASSETCHAINS_STAKED < 100 )
fprintf(stderr," -> %d%% percPoS vs goalperc.%d ht.%d\n",percPoS,goalperc,height);
*percPoSp = percPoS;
@@ -1472,13 +1415,127 @@ arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t he
fprintf(stderr," ht.%d percPoS.%d vs goal.%d -> diff %d\n",height,percPoS,goalperc,goalperc - percPoS);
}
}
else bnTarget = ave; // recent ave is perfect
else
bnTarget = ave; // recent ave is perfect
return(bnTarget);
}
uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 txid,int32_t vout,uint32_t blocktime,uint32_t prevtime,char *destaddr,int32_t PoSperc)
{
bool fNegative,fOverflow; uint8_t hashbuf[256]; char address[64]; bits256 addrhash; arith_uint256 hashval,mindiff,ratio,coinage256; uint256 hash,pasthash; int32_t segid,minage,i,iter=0; int64_t diff=0; uint32_t txtime,segid32,winner = 0 ; uint64_t value,coinage;
txtime = komodo_txtime2(&value,txid,vout,address);
if ( validateflag == 0 )
{
//fprintf(stderr,"blocktime.%u -> ",blocktime);
if ( blocktime < prevtime+3 )
blocktime = prevtime+3;
if ( blocktime < GetAdjustedTime()-60 )
blocktime = GetAdjustedTime()+30;
//fprintf(stderr,"blocktime.%u txtime.%u\n",blocktime,txtime);
}
if ( value == 0 || txtime == 0 || blocktime == 0 || prevtime == 0 )
{
//fprintf(stderr,"komodo_stake null %.8f %u %u %u\n",dstr(value),txtime,blocktime,prevtime);
return(0);
}
if ( value < SATOSHIDEN )
return(0);
value /= SATOSHIDEN;
mindiff.SetCompact(STAKING_MIN_DIFF,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
komodo_segids(hashbuf,nHeight-101,100);
segid32 = komodo_stakehash(&hash,address,hashbuf,txid,vout);
segid = ((nHeight + segid32) & 0x3f);
for (iter=0; iter<600; iter++)
{
if ( blocktime+iter+segid*2 < txtime+minage )
continue;
diff = (iter + blocktime - txtime - minage);
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
{
/*if ( PoSperc < ASSETCHAINS_STAKED )
{
// Under PoS % target and we need to increase diff.
//fprintf(stderr, "PoS too low diff.%i changed to.",diff);
diff = diff * ( (ASSETCHAINS_STAKED - PoSperc + 1) * (ASSETCHAINS_STAKED - PoSperc + 1) * ( nHeight < 50 ? 1000 : 1));
//fprintf(stderr, "%i \n",diff);
}
else */
if ( PoSperc > ASSETCHAINS_STAKED )
{
// Over PoS target need to lower diff.
//fprintf(stderr, "PoS too high diff.%i changed to.",diff);
diff = diff / ( (PoSperc - ASSETCHAINS_STAKED + 1) * (PoSperc - ASSETCHAINS_STAKED + 1) );
//fprintf(stderr, "%i \n",diff);
}
}
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
{
//printf("diff.%d (iter.%d blocktime.%u txtime.%u minage.%d)\n",(int32_t)diff,iter,blocktime,txtime,(int32_t)minage);
diff = 3600*24*30;
}
if ( iter > 0 )
diff += segid*2;
coinage = (value * diff);
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
{
if ( PoSperc < ASSETCHAINS_STAKED )
{
// Under PoS % target and we need to increase diff.
//fprintf(stderr, "PoS too low diff.%i changed to.",diff);
if ( blocktime+iter+segid*2 > prevtime+128 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+102));
//fprintf(stderr, "%i \n",diff);
}
}
if ( blocktime+iter+segid*2 > prevtime+480 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (UintToArith256(hash) / coinage256);
if ( hashval <= bnTarget )
{
winner = 1;
if ( validateflag == 0 )
{
//fprintf(stderr,"winner blocktime.%u iter.%d segid.%d\n",blocktime,iter,segid);
blocktime += iter;
blocktime += segid * 2;
}
break;
}
if ( validateflag != 0 )
{
/*for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff); */
break;
}
}
//fprintf(stderr,"iterated until i.%d winner.%d\n",i,winner);
if ( 0 && validateflag != 0 )
{
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&hashval)[i]);
fprintf(stderr," vs ");
for (i=31; i>=24; i--)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," segid.%d iter.%d winner.%d coinage.%llu %d ht.%d t.%u v%d diff.%d ht.%d\n",segid,iter,winner,(long long)coinage,(int32_t)(blocktime - txtime),nHeight,blocktime,(int32_t)value,(int32_t)diff,nHeight);
}
if ( nHeight < 10 )
return(blocktime);
return(blocktime * winner);
}
int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_uint256 bnTarget,arith_uint256 bhash)
{
CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress;
CBlockIndex *previndex,*pindex; char voutaddr[64],destaddr[64]; uint256 txid; uint32_t txtime,prevtime=0; int32_t vout,PoSperc,txn_count,eligible=0,isPoS = 0,segid; uint64_t value; CTxDestination voutaddress; arith_uint256 POWTarget;
if ( ASSETCHAINS_STAKED == 100 && height <= 10 )
return(1);
BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash());
@@ -1490,6 +1547,9 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
return(0);
else return(1);
}
// Get PoSperc and POW Target. slowflag only here, calling it when blocks out of order causes problems.
if ( slowflag != 0 )
POWTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
txn_count = pblock->vtx.size();
//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) )
@@ -1500,17 +1560,17 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
txid = pblock->vtx[txn_count-1].vin[0].prevout.hash;
vout = pblock->vtx[txn_count-1].vin[0].prevout.n;
if ( prevtime != 0 )
if ( slowflag != 0 && prevtime != 0 )
{
if ( komodo_isPoS(pblock,height) != 0 )
{
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"");
eligible = komodo_stake(1,bnTarget,height,txid,vout,pblock->nTime,prevtime+27,(char *)"",PoSperc);
}
if ( eligible == 0 || eligible > pblock->nTime )
{
if ( 0 && ASSETCHAINS_STAKED < 100 )
fprintf(stderr,"komodo_is_PoSblock PoS failure ht.%d eligible.%u vs blocktime.%u, lag.%d -> check to see if it is PoW block\n",height,eligible,(uint32_t)pblock->nTime,(int32_t)(eligible - pblock->nTime));
if ( slowflag != 0 && pindex != 0 )
if ( pindex != 0 )
{
pindex->segid = -1;
//fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid);
@@ -1519,24 +1579,20 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
else
{
isPoS = 2; // 2 means staking utxo validated
if ( slowflag != 0 && height > 100 )
CTxDestination voutaddress; char voutaddr[64];
if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{
CTxDestination voutaddress; char voutaddr[64];
if ( ExtractDestination(pblock->vtx[txn_count-1].vout[0].scriptPubKey,voutaddress) )
{
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
segid = komodo_segid32(voutaddr) & 0x3f;
//fprintf(stderr,"komodo_segid.(%d) -> %d\n",height,segid);
}
if ( pindex != 0 && segid >= 0 )
{
pindex->segid = segid;
//fprintf(stderr,"B set segid.%d <- %d\n",height,pindex->segid);
} //else fprintf(stderr,"unexpected null pindex for slowflag set ht.%d segid.%d:%d\n",height,pindex!=0?pindex->segid:-3,segid);
strcpy(voutaddr,CBitcoinAddress(voutaddress).ToString().c_str());
segid = komodo_segid32(voutaddr) & 0x3f;
}
if ( pindex != 0 && segid >= 0 )
{
pindex->segid = segid;
//fprintf(stderr,"PoS block set segid.%d <- %d\n",height,pindex->segid);
} //else fprintf(stderr,"unexpected null pindex for slowflag set ht.%d segid.%d:%d\n",height,pindex!=0?pindex->segid:-3,segid);
}
}
if ( slowflag == 0 && isPoS == 0 ) // maybe previous block is not seen yet, do the best approx
}
else if ( slowflag == 0 ) // previous blocks are not seen yet, do the best approx
{
if ( komodo_isPoS(pblock,height) != 0 )
isPoS = 1;
@@ -1550,8 +1606,7 @@ int32_t komodo_is_PoSblock(int32_t slowflag,int32_t height,CBlock *pblock,arith_
}
else
{
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
if ( bhash < bnTarget )
if ( bhash < POWTarget )
{
//fprintf(stderr,"ht.%d isPoS but meets PoW diff!\n",height);
isPoS = 0;
@@ -1743,10 +1798,209 @@ bool verusCheckPOSBlock(int32_t slowflag, CBlock *pblock, int32_t height)
return(isPOS);
}
uint64_t komodo_notarypayamount(int32_t nHeight, int64_t notarycount)
{
int8_t curEra = 0; int64_t ret = 0;
// if we have an end block in the first era, find our current era
if ( ASSETCHAINS_ENDSUBSIDY[0] > 1 )
{
for ( curEra = 0; curEra <= ASSETCHAINS_LASTERA; curEra++ )
{
if ( ASSETCHAINS_ENDSUBSIDY[curEra] > nHeight || ASSETCHAINS_ENDSUBSIDY[curEra] == 0 )
break;
}
}
if ( curEra > ASSETCHAINS_LASTERA )
return(0);
if ( notarycount == 0 )
{
fprintf(stderr, "komodo_notarypayamount failed num notaries is 0!\n");
return(0);
}
// Because of reorgs we cannot use the notarized height value.
// We need to basically guess here and just pay some static amount.
// Has the unwanted effect of varying coin emission, but cannot be helped.
fprintf(stderr, "era.%i paying total of %lu\n",curEra, ASSETCHAINS_NOTARY_PAY[curEra]);
ret = ASSETCHAINS_NOTARY_PAY[curEra] / notarycount;
return(ret);
}
int32_t komodo_getnotarizedheight(uint32_t timestamp,int32_t height, uint8_t *script, int32_t len)
{
// Check the notarisation is valid, and extract notarised height.
uint64_t voutmask;
uint8_t scriptbuf[10001];
int32_t isratification,specialtx,notarizedheight;
if ( len >= sizeof(uint32_t) && len <= sizeof(scriptbuf) )
{
memcpy(scriptbuf,script,len);
if ( komodo_voutupdate(true,&isratification,0,scriptbuf,len,height,uint256(),1,1,&voutmask,&specialtx,&notarizedheight,0,1,0,timestamp) == -2 )
{
fprintf(stderr, ">>>>>>VALID NOTARIZATION ht.%i\n",notarizedheight);
}
else
{
// This should no longer happen. Unless notaries are making actual invalid notarizations.
fprintf(stderr, "<<<<<<INVALID NOTARIZATION ht.%i\n",notarizedheight);
return(0);
}
} else return(0);
return(notarizedheight);
}
uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len)
{
// fetch notary pubkey array.
uint64_t total = 0, AmountToPay = 0;
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
numSN = komodo_notaries(notarypubkeys, height, timestamp);
// No point going further, no notaries can be paid.
if ( notarypubkeys[0][0] == 0 )
return(0);
// Check the notarisation is valid.
int32_t notarizedheight = komodo_getnotarizedheight(timestamp, height, script, len);
if ( notarizedheight == 0 )
return(0);
// resize coinbase vouts to number of notary nodes +1 for coinbase itself.
txNew.vout.resize(NotarisationNotaries.size()+1);
// Calcualte the amount to pay according to the current era.
AmountToPay = komodo_notarypayamount(height,NotarisationNotaries.size());
if ( AmountToPay == 0 )
return(0);
// loop over notarisation vins and add transaction to coinbase.
// Commented prints here can be used to verify manually the pubkeys match.
for (int8_t n = 0; n < NotarisationNotaries.size(); n++)
{
uint8_t *ptr;
txNew.vout[n+1].scriptPubKey.resize(35);
ptr = (uint8_t *)&txNew.vout[n+1].scriptPubKey[0];
ptr[0] = 33;
for (int8_t i=0; i<33; i++)
{
ptr[i+1] = notarypubkeys[NotarisationNotaries[n]][i];
//fprintf(stderr,"%02x",ptr[i+1]);
}
ptr[34] = OP_CHECKSIG;
//fprintf(stderr," set notary %i PUBKEY33 into vout[%i] amount.%lu\n",NotarisationNotaries[n],n+1,AmountToPay);
txNew.vout[n+1].nValue = AmountToPay;
total += txNew.vout[n+1].nValue;
}
return(total);
}
uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height)
{
std::vector<int8_t> NotarisationNotaries;
uint32_t timestamp = pblock->nTime;
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
numSN = komodo_notaries(notarypubkeys, height, timestamp);
// No point going further, no notaries can be paid.
if ( notarypubkeys[0][0] == 0 )
return(0);
uint8_t *script; int32_t scriptlen;
// Loop over the notarisation and extract the position of the participating notaries in the array of pukeys for this era.
BOOST_FOREACH(const CTxIn& txin, pblock->vtx[1].vin)
{
uint256 hash; CTransaction tx1;
if ( GetTransaction(txin.prevout.hash,tx1,hash,false) )
{
for (int8_t i = 0; i < numSN; i++)
{
script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0];
scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size();
if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 )
NotarisationNotaries.push_back(i);
}
}
}
// check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems)
std::set<int> checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() );
if ( checkdupes.size() != NotarisationNotaries.size() ) {
fprintf(stderr, "Possible notarisation is signed multiple times by same notary. It is invalid.\n");
return(0);
}
const CChainParams& chainparams = Params();
const Consensus::Params &consensusParams = chainparams.GetConsensus();
uint64_t totalsats = 0;
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, height);
if ( pblock->vtx[1].vout.size() == 2 && pblock->vtx[1].vout[1].nValue == 0 )
{
// Get the OP_RETURN for the notarisation
uint8_t *script = (uint8_t *)&pblock->vtx[1].vout[1].scriptPubKey[0];
int32_t scriptlen = (int32_t)pblock->vtx[1].vout[1].scriptPubKey.size();
if ( script[0] == OP_RETURN )
{
// Create the coinbase tx again, using the extracted data, this is the same function the miner uses, with the same data.
// This allows us to know exactly that the coinbase is correct.
totalsats = komodo_notarypay(txNew, NotarisationNotaries, pblock->nTime, height, script, scriptlen);
}
else
{
fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
return(0);
}
} else return(0);
// if notarypay fails, because the notarisation is not valid, exit now as txNew was not created.
// This should never happen, as the notarisation is checked before this function is called.
if ( totalsats == 0 )
{
fprintf(stderr, "notary pay returned 0!\n");
return(0);
}
int8_t n = 0, i = 0, matches = 0;
uint64_t total = 0, AmountToPay = 0;
// get the pay amount from the created tx.
AmountToPay = txNew.vout[1].nValue;
// Check the created coinbase pays the correct notaries.
BOOST_FOREACH(const CTxOut& txout, pblock->vtx[0].vout)
{
// skip the coinbase paid to the miner.
if ( n == 0 )
{
n++;
continue;
}
// Check the pubkeys match the pubkeys in the notarisation.
script = (uint8_t *)&txout.scriptPubKey[0];
scriptlen = (int32_t)txout.scriptPubKey.size();
if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[NotarisationNotaries[n-1]],33) == 0 )
{
// check the value is correct
if ( pblock->vtx[0].vout[n].nValue == AmountToPay )
{
matches++;
total += txout.nValue;
//fprintf(stderr, "MATCHED AmountPaid.%lu notaryid.%i\n",AmountToPay,NotarisationNotaries[n-1]);
}
else fprintf(stderr, "NOT MATCHED AmountPaid.%lu AmountToPay.%lu notaryid.%i\n", pblock->vtx[0].vout[n].nValue, AmountToPay, NotarisationNotaries[n-1]);
}
n++;
}
if ( matches != 0 && matches == NotarisationNotaries.size() && totalsats == total )
{
fprintf(stderr, "Validated coinbase matches notarisation in tx position 1.\n" );
return(totalsats);
}
return(0);
}
int64_t komodo_checkcommission(CBlock *pblock,int32_t height)
{
int64_t checktoshis=0; uint8_t *script,scripthex[8192]; int32_t scriptlen,matched = 0;
if ( ASSETCHAINS_COMMISSION != 0 )
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
checktoshis = komodo_commission(pblock,height);
if ( checktoshis >= 10000 && pblock->vtx[0].vout.size() < 2 )
@@ -1862,8 +2116,7 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1);
else
{
if ( slowflag != 0 )
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
bnTarget = komodo_PoWtarget(&PoSperc,bnTarget,height,ASSETCHAINS_STAKED);
if ( bhash > bnTarget )
{
for (i=31; i>=16; i--)
@@ -1873,7 +2126,17 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
fprintf(stderr,"%02x",((uint8_t *)&bnTarget)[i]);
fprintf(stderr," ht.%d PoW diff violation PoSperc.%d vs goalperc.%d\n",height,PoSperc,(int32_t)ASSETCHAINS_STAKED);
return(-1);
} else failed = 0;
} else
{
failed = 0;
CBlockIndex *pindex;
BlockMap::const_iterator it = mapBlockIndex.find(pblock->GetHash());
pindex = it != mapBlockIndex.end() ? it->second : NULL;
if ( pindex != 0 && pindex->segid == -2 ) {
pindex->segid = -1;
//fprintf(stderr,"PoW block detected set segid.%d <- %d\n",height,pindex->segid);
}
}
}
}
else if ( is_PoSblock < 0 )
@@ -1914,6 +2177,32 @@ int32_t komodo_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height)
return(-1);
}
}
// Consensus rule to force miners to mine the notary coinbase payment happens in ConnectBlock
// the default daemon miner, checks the actual vins so the only way this will fail, is if someone changes the miner,
// and then creates txs to the crypto address meeting min sigs and puts it in tx position 1.
// If they go through this effort, the block will still fail at connect block, and will be auto purged by the temp file fix.
if ( failed == 0 && ASSETCHAINS_NOTARY_PAY[0] != 0 && pblock->vtx[0].vout.size() > 1 )
{
// We check the full validation in ConnectBlock directly to get the amount for coinbase. So just approx here.
if ( slowflag == 0 )
{
// Check the notarisation tx is to the crypto address.
if ( !komodo_is_notarytx(pblock->vtx[1]) == 1 )
{
fprintf(stderr, "notarisation is not to crypto address ht.%i\n",height);
return(-1);
}
// Check min sigs.
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
numSN = komodo_notaries(notarypubkeys, height, pblock->nTime);
if ( pblock->vtx[1].vin.size() < numSN/5 )
{
fprintf(stderr, "ht.%i does not meet minsigs.%i sigs.%li\n",height,numSN/5,pblock->vtx[1].vin.size());
return(-1);
}
}
}
//fprintf(stderr,"komodo_checkPOW possible.%d slowflag.%d ht.%d notaryid.%d failed.%d\n",possible,slowflag,height,notaryid,failed);
if ( failed != 0 && possible == 0 && notaryid < 0 )
return(-1);
@@ -2057,70 +2346,15 @@ struct komodo_staking *komodo_addutxo(struct komodo_staking *array,int32_t *numk
return(array);
}
arith_uint256 _komodo_eligible(struct komodo_staking *kp,arith_uint256 ratio,uint32_t blocktime,int32_t iter,int32_t minage,int32_t segid,int32_t nHeight,uint32_t prevtime)
{
int32_t diff; uint64_t coinage; arith_uint256 coinage256,hashval;
diff = (iter + blocktime - kp->txtime - minage);
if ( diff < 0 )
diff = 60;
else if ( diff > 3600*24*30 )
diff = 3600*24*30;
if ( iter > 0 )
diff += segid*2;
coinage = ((uint64_t)kp->nValue * diff);
if ( blocktime+iter+segid*2 > prevtime+480 )
coinage *= ((blocktime+iter+segid*2) - (prevtime+400));
coinage256 = arith_uint256(coinage+1);
hashval = ratio * (kp->hashval / coinage256);
return(hashval);
}
uint32_t komodo_eligible(arith_uint256 bnTarget,arith_uint256 ratio,struct komodo_staking *kp,int32_t nHeight,uint32_t blocktime,uint32_t prevtime,int32_t minage,uint8_t *hashbuf)
{
int32_t maxiters = 600; uint256 hash;
int32_t segid,iter,diff; uint64_t coinage; arith_uint256 hashval,coinage256;
komodo_stakehash(&hash,kp->address,hashbuf,kp->txid,kp->vout);
kp->hashval = UintToArith256(hash);
segid = ((nHeight + kp->segid32) & 0x3f);
hashval = _komodo_eligible(kp,ratio,blocktime,maxiters,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++)
{
if ( blocktime+iter+segid*2 < kp->txtime+minage )
continue;
hashval = _komodo_eligible(kp,ratio,blocktime,iter,minage,segid,nHeight,prevtime);
if ( hashval <= bnTarget )
{
//fprintf(stderr,"winner %.8f blocktime.%u iter.%d segid.%d\n",(double)kp->nValue/COIN,blocktime,iter,segid);
blocktime += iter;
blocktime += segid * 2;
return(blocktime);
}
}
} else fprintf(stderr,"maxiters is not good enough\n");
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;
set<CBitcoinAddress> setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,eligible2,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock;
int32_t PoSperc;
set<CBitcoinAddress> setAddress; struct komodo_staking *kp; int32_t winners,segid,minage,nHeight,counter=0,i,m,siglen=0,nMinDepth = 1,nMaxDepth = 99999999; vector<COutput> vecOutputs; uint32_t block_from_future_rejecttime,besttime,eligible,earliest = 0; CScript best_scriptPubKey; arith_uint256 mindiff,ratio,bnTarget,tmpTarget; CBlockIndex *tipindex,*pindex; CTxDestination address; bool fNegative,fOverflow; uint8_t hashbuf[256]; CTransaction tx; uint256 hashBlock;
if (!EnsureWalletIsAvailable(0))
return 0;
bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
mindiff.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
ratio = (mindiff / bnTarget);
assert(pwalletMain != NULL);
*utxovaluep = 0;
memset(utxotxidp,0,sizeof(*utxotxidp));
@@ -2129,10 +2363,12 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
if ( (tipindex= chainActive.Tip()) == 0 )
return(0);
nHeight = tipindex->GetHeight() + 1;
// Get the PoS% so we can pass it to komodo_stake, this is to adjust PoS dofficulty when it is under the target %!
tmpTarget = komodo_PoWtarget(&PoSperc,bnTarget,nHeight,ASSETCHAINS_STAKED);
if ( (minage= nHeight*3) > 6000 ) // about 100 blocks
minage = 6000;
komodo_segids(hashbuf,nHeight-101,100);
if ( *blocktimep < tipindex->nTime+60 )
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);
@@ -2150,7 +2386,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
}
}
if ( time(NULL) > lasttime+600 || array == 0 || resetstaker )
if ( resetstaker || array == 0 || time(NULL) > lasttime+600 )
{
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
@@ -2173,7 +2409,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
counter++;
if ( out.nDepth < nMinDepth || out.nDepth > nMaxDepth )
{
fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
//fprintf(stderr,"komodo_staked invalid depth %d\n",(int32_t)out.nDepth);
continue;
}
CAmount nValue = out.tx->vout[out.i].nValue;
@@ -2222,27 +2458,25 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
//fprintf(stderr,"finished kp data of utxo for staking %u ht.%d numkp.%d maxkp.%d\n",(uint32_t)time(NULL),nHeight,numkp,maxkp);
}
//fprintf(stderr,"numkp.%d blocktime.%u\n",numkp,*blocktimep);
block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
block_from_future_rejecttime = (uint32_t)GetAdjustedTime() + 57;
for (i=winners=0; i<numkp; i++)
{
if (fRequestShutdown)
break;
if ( fRequestShutdown || !GetBoolArg("-gen",false) )
return(0);
if ( (tipindex= chainActive.Tip()) == 0 || tipindex->GetHeight()+1 > nHeight )
{
fprintf(stderr,"chain tip changed during staking loop t.%u counter.%d\n",(uint32_t)time(NULL),counter);
return(0);
}
kp = &array[i];
if ( (eligible2= komodo_eligible(bnTarget,ratio,kp,nHeight,*blocktimep,(uint32_t)tipindex->nTime+27,minage,hashbuf)) == 0 )
continue;
eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
eligible = komodo_stake(0,bnTarget,nHeight,kp->txid,kp->vout,0,(uint32_t)tipindex->nTime+27,kp->address,PoSperc);
//fprintf(stderr,"i.%d %u vs %u\n",i,eligible2,eligible);
if ( eligible > 0 )
{
besttime = m = 0;
if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
if ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address,PoSperc) )
{
while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address) )
while ( eligible == komodo_stake(1,bnTarget,nHeight,kp->txid,kp->vout,eligible,(uint32_t)tipindex->nTime+27,kp->address,PoSperc) )
{
besttime = eligible;
eligible--;
@@ -2269,7 +2503,7 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
decode_hex((uint8_t *)utxotxidp,32,(char *)kp->txid.GetHex().c_str());
*utxovoutp = kp->vout;
*txtimep = kp->txtime;//(uint32_t)out.tx->nLockTime;
fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
//fprintf(stderr,"ht.%d earliest.%u [%d].%d (%s) nValue %.8f locktime.%u counter.%d winners.%d\n",nHeight,earliest,(int32_t)(earliest - tipindex->nTime),m,kp->address,(double)kp->nValue/COIN,*txtimep,counter,winners);
}
} //else fprintf(stderr,"utxo not eligible\n");
}

View File

@@ -40,18 +40,18 @@ extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAIN_INIT, ASSETCHAINS_MAGIC,ASSETCHAINS_BLOCKTIME;
extern int32_t VERUS_BLOCK_POSUNITS, ASSETCHAINS_LWMAPOS, ASSETCHAINS_SAPLING, ASSETCHAINS_OVERWINTER;
extern uint64_t ASSETCHAINS_SUPPLY;
extern uint64_t ASSETCHAINS_SUPPLY, ASSETCHAINS_FOUNDERS_REWARD;
extern uint64_t ASSETCHAINS_TIMELOCKGTE;
extern uint32_t ASSETCHAINS_ALGO, ASSETCHAINS_VERUSHASH,ASSETCHAINS_EQUIHASH,KOMODO_INITDONE;
extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,KOMODO_ON_DEMAND,KOMODO_PASSPORT_INITDONE,ASSETCHAINS_STAKED;
extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_LASTERA;
extern bool VERUS_MINTBLOCKS;
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
extern const char *ASSETCHAINS_ALGORITHMS[];
extern int32_t VERUS_MIN_STAKEAGE;
extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
extern uint32_t ASSETCHAINS_VERUSHASH, ASSETCHAINS_VERUSHASHV1_1, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY,ASSETCHAINS_SCRIPTPUB;
extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_MARMARA;
@@ -74,5 +74,7 @@ extern int32_t VERUS_MIN_STAKEAGE;
extern std::string DONATION_PUBKEY;
extern uint8_t ASSETCHAINS_PRIVATE;
extern int32_t USE_EXTERNAL_PUBKEY;
extern char NOTARYADDRS[64][36];
extern uint8_t NUM_NOTARIES;
#endif

View File

@@ -710,7 +710,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim
}
// we don't want these checks in VRSC, leave it at the Sapling upgrade
if ( ASSETCHAINS_SYMBOL[0] == 0 ||
(ASSETCHAINS_COMMISSION != 0 && height > 1) ||
((ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1) ||
NetworkUpgradeActive(height, Params().GetConsensus(), Consensus::UPGRADE_SAPLING) )
{
n = block.vtx[0].vout.size();
@@ -772,7 +772,7 @@ int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtim
else
{
checktoshis = 0;
if ( ASSETCHAINS_COMMISSION != 0 && height > 1 )
if ( (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD) && height > 1 )
{
if ( (checktoshis= komodo_checkcommission((CBlock *)&block,height)) < 0 )
{

View File

@@ -29,9 +29,8 @@ uint64_t komodo_paxtotal();
int32_t komodo_longestchain();
uint64_t komodo_maxallowed(int32_t baseid);
int32_t komodo_bannedset(int32_t *indallvoutsp,uint256 *array,int32_t max);
bool pubkey2addr(char *destaddr,uint8_t *pubkey33);
pthread_mutex_t komodo_mutex;
pthread_mutex_t komodo_mutex,staked_mutex;
#define KOMODO_ELECTION_GAP 2000 //((ASSETCHAINS_SYMBOL[0] == 0) ? 2000 : 100)
#define KOMODO_ASSETCHAIN_MAXLEN 65
@@ -46,15 +45,15 @@ struct komodo_state KOMODO_STATES[34];
int COINBASE_MATURITY = _COINBASE_MATURITY;//100;
unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10;
int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS;
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,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA;
std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,WHITELIST_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB;
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];
char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096],NOTARYADDRS[64][36];
uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT;
uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1;
uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1,STAKING_MIN_DIFF;
uint32_t ASSETCHAINS_MAGIC = 2387029918;
int64_t ASSETCHAINS_GENESISTXVAL = 5000000000;
@@ -69,20 +68,23 @@ int64_t MAX_MONEY = 200000000 * 100000000LL;
uint64_t ASSETCHAINS_TIMELOCKGTE = _ASSETCHAINS_TIMELOCKOFF;
uint64_t ASSETCHAINS_TIMEUNLOCKFROM = 0, ASSETCHAINS_TIMEUNLOCKTO = 0;
uint32_t ASSETCHAINS_LASTERA = 1;
uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS];
uint64_t ASSETCHAINS_LASTERA = 1;
uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_DECAY[ASSETCHAINS_MAX_ERAS],ASSETCHAINS_NOTARY_PAY[ASSETCHAINS_MAX_ERAS];
uint8_t ASSETCHAINS_CCDISABLES[256];
#define _ASSETCHAINS_EQUIHASH 0
uint32_t ASSETCHAINS_NUMALGOS = 2;
uint32_t ASSETCHAINS_NUMALGOS = 3;
uint32_t ASSETCHAINS_EQUIHASH = _ASSETCHAINS_EQUIHASH;
uint32_t ASSETCHAINS_VERUSHASH = 1;
const char *ASSETCHAINS_ALGORITHMS[] = {"equihash", "verushash"};
uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff,0xfffffff};
uint32_t ASSETCHAINS_NONCESHIFT[] = {32,16};
uint32_t ASSETCHAINS_HASHESPERROUND[] = {1,4096};
uint32_t ASSETCHAINS_VERUSHASHV1_1 = 2;
const char *ASSETCHAINS_ALGORITHMS[] = {"equihash", "verushash", "verushash11"};
uint64_t ASSETCHAINS_NONCEMASK[] = {0xffff,0xfffffff,0xfffffff};
uint32_t ASSETCHAINS_NONCESHIFT[] = {32,16,16};
uint32_t ASSETCHAINS_HASHESPERROUND[] = {1,4096,4096};
uint32_t ASSETCHAINS_ALGO = _ASSETCHAINS_EQUIHASH;
// min diff returned from GetNextWorkRequired needs to be added here for each algo, so they can work with ac_staked.
uint32_t ASSETCHAINS_MINDIFF[] = {537857807,504303375,487526159};
// ^ wrong!
// Verus proof of stake controls
int32_t ASSETCHAINS_LWMAPOS = 0; // percentage of blocks should be PoS
int32_t VERUS_BLOCK_POSUNITS = 1024; // one block is 1000 units
@@ -94,7 +96,8 @@ int32_t ASSETCHAINS_SAPLING = -1;
int32_t ASSETCHAINS_OVERWINTER = -1;
uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10;
int32_t ASSETCHAINS_STAKED;
uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,MIN_RECV_SATS,ASSETCHAINS_FOUNDERS_REWARD;
uint32_t KOMODO_INITDONE;
char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771;

View File

@@ -18,6 +18,8 @@
#include "komodo_cJSON.h"
#include "notaries_staked.h"
#define KOMODO_MAINNET_START 178999
const char *Notaries_genesis[][2] =
@@ -203,19 +205,25 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam
{
static uint8_t elected_pubkeys0[64][33],elected_pubkeys1[64][33],did0,did1; static int32_t n0,n1;
int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp;
if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 )
timestamp = komodo_heightstamp(height);
else if ( ASSETCHAINS_SYMBOL[0] == 0 )
timestamp = 0;
if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 )
// If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW.
if (is_STAKED(ASSETCHAINS_SYMBOL) == 0)
{
if ( height >= KOMODO_NOTARIES_HARDCODED || ASSETCHAINS_SYMBOL[0] != 0 )
timestamp = 0;
if ( (timestamp != 0 && timestamp <= KOMODO_NOTARIES_TIMESTAMP1) || (ASSETCHAINS_SYMBOL[0] == 0 && height <= KOMODO_NOTARIES_HEIGHT1) )
{
if ( did0 == 0 )
{
n0 = (int32_t)(sizeof(Notaries_elected0)/sizeof(*Notaries_elected0));
for (i=0; i<n0; i++)
for (i=0; i<n0; i++) {
decode_hex(elected_pubkeys0[i],33,(char *)Notaries_elected0[i][1]);
}
did0 = 1;
}
memcpy(pubkeys,elected_pubkeys0,n0 * 33);
@@ -225,11 +233,12 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam
}
else //if ( (timestamp != 0 && timestamp <= KOMODO_NOTARIES_TIMESTAMP2) || height <= KOMODO_NOTARIES_HEIGHT2 )
{
if ( did1 == 0 )
if ( did1 == 0 )
{
n1 = (int32_t)(sizeof(Notaries_elected1)/sizeof(*Notaries_elected1));
for (i=0; i<n1; i++)
decode_hex(elected_pubkeys1[i],33,(char *)Notaries_elected1[i][1]);
n1 = (int32_t)(sizeof(Notaries_elected1)/sizeof(*Notaries_elected1));
for (i=0; i<n1; i++) {
decode_hex(elected_pubkeys1[i],33,(char *)Notaries_elected1[i][1]);
}
if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
fprintf(stderr,"%s height.%d t.%u elected.%d notaries2\n",ASSETCHAINS_SYMBOL,height,timestamp,n1);
did1 = 1;
@@ -238,6 +247,16 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam
return(n1);
}
}
else if (timestamp != 0)
{ // here we can activate our pubkeys for STAKED chains everythig is in notaries_staked.cpp
int32_t staked_era; int8_t numSN;
uint8_t staked_pubkeys[64][33];
staked_era = STAKED_era(timestamp);
numSN = numStakedNotaries(staked_pubkeys,staked_era);
memcpy(pubkeys,staked_pubkeys,numSN * 33);
return(numSN);
}
htind = height / KOMODO_ELECTION_GAP;
if ( htind >= KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP )
htind = (KOMODO_MAXBLOCKS / KOMODO_ELECTION_GAP) - 1;

View File

@@ -1538,7 +1538,8 @@ uint16_t komodo_port(char *symbol,uint64_t supply,uint32_t *magicp,uint8_t *extr
printf("ports\n");
}*/
char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"sapling\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\"}\"";
char *iguanafmtstr = (char *)"curl --url \"http://127.0.0.1:7776\" --data \"{\\\"conf\\\":\\\"%s.conf\\\",\\\"path\\\":\\\"${HOME#\"/\"}/.komodo/%s\\\",\\\"unitval\\\":\\\"20\\\",\\\"zcash\\\":1,\\\"RELAY\\\":-1,\\\"VALIDATE\\\":0,\\\"prefetchlag\\\":-1,\\\"poll\\\":100,\\\"active\\\":1,\\\"agent\\\":\\\"iguana\\\",\\\"method\\\":\\\"addcoin\\\",\\\"startpend\\\":4,\\\"endpend\\\":4,\\\"services\\\":129,\\\"maxpeers\\\":8,\\\"newcoin\\\":\\\"%s\\\",\\\"name\\\":\\\"%s\\\",\\\"hasheaders\\\":1,\\\"useaddmultisig\\\":0,\\\"netmagic\\\":\\\"%s\\\",\\\"p2p\\\":%u,\\\"rpc\\\":%u,\\\"pubval\\\":60,\\\"p2shval\\\":85,\\\"wifval\\\":188,\\\"txfee_satoshis\\\":\\\"10000\\\",\\\"isPoS\\\":0,\\\"minoutput\\\":10000,\\\"minconfirms\\\":2,\\\"genesishash\\\":\\\"027e3758c3a65b12aa1046462b486d0a63bfa1beae327897f56c5cfb7daaae71\\\",\\\"protover\\\":170002,\\\"genesisblock\\\":\\\"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a000000000000000000000000000000000000000000000000000000000000000029ab5f490f0f0f200b00000000000000000000000000000000000000000000000000000000000000fd4005000d5ba7cda5d473947263bf194285317179d2b0d307119c2e7cc4bd8ac456f0774bd52b0cd9249be9d40718b6397a4c7bbd8f2b3272fed2823cd2af4bd1632200ba4bf796727d6347b225f670f292343274cc35099466f5fb5f0cd1c105121b28213d15db2ed7bdba490b4cedc69742a57b7c25af24485e523aadbb77a0144fc76f79ef73bd8530d42b9f3b9bed1c135ad1fe152923fafe98f95f76f1615e64c4abb1137f4c31b218ba2782bc15534788dda2cc08a0ee2987c8b27ff41bd4e31cd5fb5643dfe862c9a02ca9f90c8c51a6671d681d04ad47e4b53b1518d4befafefe8cadfb912f3d03051b1efbf1dfe37b56e93a741d8dfd80d576ca250bee55fab1311fc7b3255977558cdda6f7d6f875306e43a14413facdaed2f46093e0ef1e8f8a963e1632dcbeebd8e49fd16b57d49b08f9762de89157c65233f60c8e38a1f503a48c555f8ec45dedecd574a37601323c27be597b956343107f8bd80f3a925afaf30811df83c402116bb9c1e5231c70fff899a7c82f73c902ba54da53cc459b7bf1113db65cc8f6914d3618560ea69abd13658fa7b6af92d374d6eca9529f8bd565166e4fcbf2a8dfb3c9b69539d4d2ee2e9321b85b331925df195915f2757637c2805e1d4131e1ad9ef9bc1bb1c732d8dba4738716d351ab30c996c8657bab39567ee3b29c6d054b711495c0d52e1cd5d8e55b4f0f0325b97369280755b46a02afd54be4ddd9f77c22272b8bbb17ff5118fedbae2564524e797bd28b5f74f7079d532ccc059807989f94d267f47e724b3f1ecfe00ec9e6541c961080d8891251b84b4480bc292f6a180bea089fef5bbda56e1e41390d7c0e85ba0ef530f7177413481a226465a36ef6afe1e2bca69d2078712b3912bba1a99b1fbff0d355d6ffe726d2bb6fbc103c4ac5756e5bee6e47e17424ebcbf1b63d8cb90ce2e40198b4f4198689daea254307e52a25562f4c1455340f0ffeb10f9d8e914775e37d0edca019fb1b9c6ef81255ed86bc51c5391e0591480f66e2d88c5f4fd7277697968656a9b113ab97f874fdd5f2465e5559533e01ba13ef4a8f7a21d02c30c8ded68e8c54603ab9c8084ef6d9eb4e92c75b078539e2ae786ebab6dab73a09e0aa9ac575bcefb29e930ae656e58bcb513f7e3c17e079dce4f05b5dbc18c2a872b22509740ebe6a3903e00ad1abc55076441862643f93606e3dc35e8d9f2caef3ee6be14d513b2e062b21d0061de3bd56881713a1a5c17f5ace05e1ec09da53f99442df175a49bd154aa96e4949decd52fed79ccf7ccbce32941419c314e374e4a396ac553e17b5340336a1a25c22f9e42a243ba5404450b650acfc826a6e432971ace776e15719515e1634ceb9a4a35061b668c74998d3dfb5827f6238ec015377e6f9c94f38108768cf6e5c8b132e0303fb5a200368f845ad9d46343035a6ff94031df8d8309415bb3f6cd5ede9c135fdabcc030599858d803c0f85be7661c88984d88faa3d26fb0e9aac0056a53f1b5d0baed713c853c4a2726869a0a124a8a5bbc0fc0ef80c8ae4cb53636aa02503b86a1eb9836fcc259823e2692d921d88e1ffc1e6cb2bde43939ceb3f32a611686f539f8f7c9f0bf00381f743607d40960f06d347d1cd8ac8a51969c25e37150efdf7aa4c2037a2fd0516fb444525ab157a0ed0a7412b2fa69b217fe397263153782c0f64351fbdf2678fa0dc8569912dcd8e3ccad38f34f23bbbce14c6a26ac24911b308b82c7e43062d180baeac4ba7153858365c72c63dcf5f6a5b08070b730adb017aeae925b7d0439979e2679f45ed2f25a7edcfd2fb77a8794630285ccb0a071f5cce410b46dbf9750b0354aae8b65574501cc69efb5b6a43444074fee116641bb29da56c2b4a7f456991fc92b2\\\",\\\"debug\\\":0,\\\"seedipaddr\\\":\\\"%s\\\",\\\"sapling\\\":1}\"";
int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp)
@@ -1646,6 +1647,9 @@ uint64_t komodo_ac_block_subsidy(int nHeight)
else
subsidy += ASSETCHAINS_SUPPLY * SATOSHIDEN + magicExtra;
}
else if ( is_STAKED(ASSETCHAINS_SYMBOL) == 2 )
return(0);
// LABS fungible chains, cannot have any block reward!
return(subsidy);
}
@@ -1656,14 +1660,19 @@ void komodo_args(char *argv0)
extern const char *Notaries_elected1[][2];
std::string name,addn; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[8192],disablebits[32],*extraptr=0; FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256];
IS_KOMODO_NOTARY = GetBoolArg("-notary", false);
IS_STAKED_NOTARY = GetArg("-stakednotary", -1);
if ( IS_STAKED_NOTARY != -1 && IS_KOMODO_NOTARY == true ) {
fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n");
exit(0);
}
MIN_RECV_SATS = GetArg("-mintxvalue",-1);
WHITELIST_ADDRESS = GetArg("-whitelistaddress","");
memset(ccenables,0,sizeof(ccenables));
memset(disablebits,0,sizeof(disablebits));
if ( GetBoolArg("-gen", false) != 0 )
{
KOMODO_MININGTHREADS = GetArg("-genproclimit",-1);
}
else KOMODO_MININGTHREADS = 0;
if ( (KOMODO_EXCHANGEWALLET= GetBoolArg("-exchange", false)) != 0 )
fprintf(stderr,"KOMODO_EXCHANGEWALLET mode active\n");
DONATION_PUBKEY = GetArg("-donation", "");
@@ -1681,13 +1690,13 @@ void komodo_args(char *argv0)
IS_KOMODO_NOTARY = 1;
KOMODO_MININGTHREADS = 1;
mapArgs ["-genproclimit"] = itostr(KOMODO_MININGTHREADS);
IS_STAKED_NOTARY = -1;
fprintf(stderr,"running as notary.%d %s\n",i,Notaries_elected1[i][0]);
break;
}
}
//KOMODO_PAX = 1;
} //else KOMODO_PAX = GetArg("-pax",0);
name = GetArg("-ac_name","");
}
name = GetArg("-ac_name","");
if ( argv0 != 0 )
{
len = (int32_t)strlen(argv0);
@@ -1714,7 +1723,7 @@ void komodo_args(char *argv0)
{
printf("KOMODO_REWIND %d\n",KOMODO_REWIND);
}
if ( name.c_str()[0] != 0 )
if ( name.c_str()[0] != 0 )
{
std::string selectedAlgo = GetArg("-ac_algo", std::string(ASSETCHAINS_ALGORITHMS[0]));
@@ -1723,6 +1732,7 @@ void komodo_args(char *argv0)
if (std::string(ASSETCHAINS_ALGORITHMS[i]) == selectedAlgo)
{
ASSETCHAINS_ALGO = i;
STAKING_MIN_DIFF = ASSETCHAINS_MINDIFF[i];
// only worth mentioning if it's not equihash
if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH)
printf("ASSETCHAINS_ALGO, algorithm set to %s\n", selectedAlgo.c_str());
@@ -1738,7 +1748,7 @@ void komodo_args(char *argv0)
if ( ASSETCHAINS_LASTERA < 1 || ASSETCHAINS_LASTERA > ASSETCHAINS_MAX_ERAS )
{
ASSETCHAINS_LASTERA = 1;
printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %u\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA);
printf("ASSETCHAINS_LASTERA, if specified, must be between 1 and %u. ASSETCHAINS_LASTERA set to %lu\n", ASSETCHAINS_MAX_ERAS, ASSETCHAINS_LASTERA);
}
ASSETCHAINS_LASTERA -= 1;
@@ -1756,6 +1766,7 @@ void komodo_args(char *argv0)
Split(GetArg("-ac_reward",""), ASSETCHAINS_REWARD, 0);
Split(GetArg("-ac_halving",""), ASSETCHAINS_HALVING, 0);
Split(GetArg("-ac_decay",""), ASSETCHAINS_DECAY, 0);
Split(GetArg("-ac_notarypay",""), ASSETCHAINS_NOTARY_PAY, 0);
for ( int i = 0; i < ASSETCHAINS_MAX_ERAS; i++ )
{
@@ -1774,6 +1785,7 @@ void komodo_args(char *argv0)
MAX_BLOCK_SIGOPS = 60000;
ASSETCHAINS_TXPOW = GetArg("-ac_txpow",0) & 3;
ASSETCHAINS_FOUNDERS = GetArg("-ac_founders",0);// & 1;
ASSETCHAINS_FOUNDERS_REWARD = GetArg("-ac_founders_reward",0);
ASSETCHAINS_SUPPLY = GetArg("-ac_supply",10);
ASSETCHAINS_COMMISSION = GetArg("-ac_perc",0);
ASSETCHAINS_OVERRIDE_PUBKEY = GetArg("-ac_pubkey","");
@@ -1781,6 +1793,11 @@ void komodo_args(char *argv0)
ASSETCHAINS_BEAMPORT = GetArg("-ac_beam",0);
ASSETCHAINS_CODAPORT = GetArg("-ac_coda",0);
ASSETCHAINS_MARMARA = GetArg("-ac_marmara",0);
if ( ASSETCHAINS_COMMISSION != 0 && ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
fprintf(stderr,"cannot use founders reward and commission on the same chain.\n");
exit(0);
}
if ( ASSETCHAINS_CC != 0 )
{
ASSETCHAINS_CCLIB = GetArg("-ac_cclib","");
@@ -1842,7 +1859,7 @@ void komodo_args(char *argv0)
}
// else it can be gateway coin
if ( (ASSETCHAINS_STAKED= GetArg("-ac_staked",0)) > 100 )
ASSETCHAINS_STAKED = 100;
@@ -1863,18 +1880,27 @@ void komodo_args(char *argv0)
}
if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 || ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
{
printf("Assetchains NOTARY PAY cannot be used with ac_pubkey or ac_script.\n");
exit(0);
}
if ( strlen(ASSETCHAINS_OVERRIDE_PUBKEY.c_str()) == 66 )
{
decode_hex(ASSETCHAINS_OVERRIDE_PUBKEY33,33,(char *)ASSETCHAINS_OVERRIDE_PUBKEY.c_str());
calc_rmd160_sha256(ASSETCHAINS_OVERRIDE_PUBKEYHASH,ASSETCHAINS_OVERRIDE_PUBKEY33,33);
}
if ( ASSETCHAINS_COMMISSION == 0 )
if ( ASSETCHAINS_COMMISSION == 0 && ASSETCHAINS_FOUNDERS != 0 )
{
if (ASSETCHAINS_FOUNDERS != 0 )
if ( ASSETCHAINS_FOUNDERS_REWARD == 0 )
{
ASSETCHAINS_COMMISSION = 53846154; // maps to 35%
printf("ASSETCHAINS_COMMISSION defaulted to 35%% when founders reward active\n");
}
else
{
printf("ASSETCHAINS_FOUNDERS_REWARD set to %ld\n", ASSETCHAINS_FOUNDERS_REWARD);
}
/*else if ( ASSETCHAINS_SELFIMPORT.size() == 0 )
{
//ASSETCHAINS_OVERRIDE_PUBKEY.clear();
@@ -1887,12 +1913,12 @@ void komodo_args(char *argv0)
if ( ASSETCHAINS_COMMISSION != 0 )
{
ASSETCHAINS_COMMISSION = 0;
printf("ASSETCHAINS_COMMISSION needs an ASETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n");
printf("ASSETCHAINS_COMMISSION needs an ASSETCHAINS_OVERRIDE_PUBKEY and cant be more than 100000000 (100%%)\n");
}
if ( ASSETCHAINS_FOUNDERS != 0 )
{
ASSETCHAINS_FOUNDERS = 0;
printf("ASSETCHAINS_FOUNDERS needs an ASETCHAINS_OVERRIDE_PUBKEY\n");
printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n");
}
}
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 && ASSETCHAINS_MARMARA != 0 )
@@ -1900,7 +1926,7 @@ void komodo_args(char *argv0)
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 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_BLOCKTIME != 60 )
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 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 )
{
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;
@@ -1909,17 +1935,20 @@ void komodo_args(char *argv0)
// if we have one era, this should create the same data structure as it used to, same if we increase _MAX_ERAS
for ( int i = 0; i <= ASSETCHAINS_LASTERA; i++ )
{
printf("ERA%u: end.%llu reward.%llu halving.%llu decay.%llu\n", i,
printf("ERA%u: end.%llu reward.%llu halving.%llu decay.%llu notarypay.%llu\n", i,
(long long)ASSETCHAINS_ENDSUBSIDY[i],
(long long)ASSETCHAINS_REWARD[i],
(long long)ASSETCHAINS_HALVING[i],
(long long)ASSETCHAINS_DECAY[i]);
(long long)ASSETCHAINS_DECAY[i],
(long long)ASSETCHAINS_NOTARY_PAY[i]);
// TODO: Verify that we don't overrun extrabuf here, which is a 256 byte buffer
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ENDSUBSIDY[i]),(void *)&ASSETCHAINS_ENDSUBSIDY[i]);
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_REWARD[i]),(void *)&ASSETCHAINS_REWARD[i]);
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_HALVING[i]),(void *)&ASSETCHAINS_HALVING[i]);
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_DECAY[i]),(void *)&ASSETCHAINS_DECAY[i]);
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_NOTARY_PAY[i]),(void *)&ASSETCHAINS_NOTARY_PAY[i]);
}
if (ASSETCHAINS_LASTERA > 0)
@@ -1946,14 +1975,19 @@ void komodo_args(char *argv0)
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_LWMAPOS),(void *)&ASSETCHAINS_LWMAPOS);
}
val = ASSETCHAINS_COMMISSION | (((uint64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW;
val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW;
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val);
if ( ASSETCHAINS_FOUNDERS != 0 )
{
uint8_t tmp = 1;
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(tmp),(void *)&tmp);
if ( ASSETCHAINS_FOUNDERS > 1 )
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS),(void *)&ASSETCHAINS_FOUNDERS);
if ( ASSETCHAINS_FOUNDERS_REWARD != 0 )
{
extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_FOUNDERS_REWARD),(void *)&ASSETCHAINS_FOUNDERS_REWARD);
}
}
if ( ASSETCHAINS_SCRIPTPUB.size() > 1 )
{
@@ -2043,7 +2077,7 @@ void komodo_args(char *argv0)
if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 )
ASSETCHAINS_RPCPORT = port;
else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1);
if (ASSETCHAINS_LASTERA == 0)
if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0)
COINBASE_MATURITY = 1;
//fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT);
}
@@ -2116,7 +2150,7 @@ void komodo_args(char *argv0)
if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 )
{
ASSETCHAINS_HALVING[0] *= 5;
fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%d\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,ASSETCHAINS_LASTERA);
fprintf(stderr,"PIRATE halving changed to %d %.1f days ASSETCHAINS_LASTERA.%lu\n",(int32_t)ASSETCHAINS_HALVING[0],(double)ASSETCHAINS_HALVING[0]/1440,ASSETCHAINS_LASTERA);
}
else if ( strcmp("VRSC",ASSETCHAINS_SYMBOL) == 0 )
dpowconfs = 0;

View File

@@ -19,7 +19,6 @@
******************************************************************************/
#include "main.h"
#include "sodium.h"
#include "addrman.h"
@@ -48,6 +47,7 @@
#include "validationinterface.h"
#include "wallet/asyncrpcoperation_sendmany.h"
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
#include "notaries_staked.h"
#include <cstring>
#include <algorithm>
@@ -186,6 +186,8 @@ namespace {
std::vector<CBlockFileInfo> vinfoBlockFile,tmpBlockFiles;
int nLastBlockFile = 0;
int nLastTmpFile = 0;
unsigned int maxTempFileSize0 = MAX_TEMPFILE_SIZE;
unsigned int maxTempFileSize1 = MAX_TEMPFILE_SIZE;
/** Global flag to indicate we should check to see if there are
* block/undo files that should be deleted. Set on startup
* or if we allocate more file space when we're in prune mode
@@ -1108,7 +1110,9 @@ bool ContextualCheckTransaction(
if (IsExpiredTx(tx, nHeight)) {
// Don't increase banscore if the transaction only just expired
int expiredDosLevel = IsExpiredTx(tx, nHeight - 1) ? (dosLevel > 10 ? dosLevel : 10) : 0;
return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction is expired"), REJECT_INVALID, "tx-overwinter-expired");
string strHex = EncodeHexTx(tx);
//fprintf(stderr, "transaction exipred.%s\n",strHex.c_str());
return state.DoS(expiredDosLevel, error("ContextualCheckTransaction(): transaction %s is expired, expiry block %i vs current block %i\n txhex.%s",tx.GetHash().ToString(),tx.nExpiryHeight,nHeight,strHex), REJECT_INVALID, "tx-overwinter-expired");
}
}
@@ -1257,6 +1261,9 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState
}
}
extern char NOTARYADDRS[64][36];
extern uint8_t NUM_NOTARIES;
int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only
{
static int32_t didinit; static char notaryaddrs[sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) + 1][64];
@@ -1274,8 +1281,8 @@ int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only
didinit = 1;
}
for (i=0; i<=sizeof(Notaries_elected1)/sizeof(*Notaries_elected1); i++)
if ( strcmp(coinaddr,notaryaddrs[i]) == 0 )
return(1);
if ( strcmp(coinaddr,notaryaddrs[i]) == 0 )
return(1);
return(0);
}
@@ -1329,9 +1336,10 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio
// Transactions containing empty `vin` must have either non-empty
// `vjoinsplit` or non-empty `vShieldedSpend`.
if (tx.vin.empty() && tx.vjoinsplit.empty() && tx.vShieldedSpend.empty())
if (tx.vin.empty() && tx.vjoinsplit.empty() && tx.vShieldedSpend.empty())
return state.DoS(10, error("CheckTransaction(): vin empty"),
REJECT_INVALID, "bad-txns-vin-empty");
// Transactions containing empty `vout` must have either non-empty
// `vjoinsplit` or non-empty `vShieldedOutput`.
if (tx.vout.empty() && tx.vjoinsplit.empty() && tx.vShieldedOutput.empty())
@@ -1588,7 +1596,6 @@ bool CheckTransactionWithoutProofVerification(uint32_t tiptime,const CTransactio
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
{
extern int32_t KOMODO_ON_DEMAND;
{
LOCK(mempool.cs);
uint256 hash = tx.GetHash();
@@ -1845,7 +1852,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Continuously rate-limit free (really, very-low-fee) transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
// be annoying or make others' transactions take longer to confirm.
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize) && !tx.IsCoinImport())
{
static CCriticalSection csFreeLimiter;
static double dFreeCount;
@@ -2269,8 +2276,9 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW)
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern uint64_t ASSETCHAINS_ENDSUBSIDY[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_HALVING[ASSETCHAINS_MAX_ERAS];
extern uint32_t ASSETCHAINS_MAGIC;
extern uint64_t ASSETCHAINS_STAKED,ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY;
extern uint64_t ASSETCHAINS_LINEAR,ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY;
extern uint8_t ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE;
extern int32_t ASSETCHAINS_STAKED;
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
{
@@ -3248,6 +3256,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
auto verifier = libzcash::ProofVerifier::Strict();
auto disabledVerifier = libzcash::ProofVerifier::Disabled();
int32_t futureblock;
CAmount blockReward = 0;
// Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in
if (!CheckBlock(&futureblock,pindex->GetHeight(),pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 )
{
@@ -3262,6 +3271,36 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return false;
fprintf(stderr,"grandfathered exception, until jan 15th 2019\n");
}
// Do this here before the block is moved to the main block files.
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 && pindex->GetHeight() > 10 )
{
// do a full block scan to get notarisation position and to enforce a valid notarization is in position 1.
// if notarisation in the block, must be position 1 and the coinbase must pay notaries.
int notarisationTx = komodo_connectblock(true,pindex,*(CBlock *)&block);
// -1 means that the valid notarization isnt in position 1 or there are too many notarizations in this block.
if ( notarisationTx == -1 )
return state.DoS(100, error("ConnectBlock(): Notarization is not in TX position 1 or block contains more than 1 notarization! Invalid Block!"),
REJECT_INVALID, "bad-notarization-position");
// 1 means this block contains a valid notarisation and its in position 1.
// its no longer possible for any attempted notarization to be in a block with a valid one!
// if notaries create a notarisation even if its not in this chain it will need to be mined inside its own block!
if ( notarisationTx == 1 )
{
// Check if the notaries have been paid.
if ( block.vtx[0].vout.size() == 1 )
return state.DoS(100, error("ConnectBlock(): Notaries have not been paid!"),
REJECT_INVALID, "bad-cb-amount");
// calculate the notaries compensation and validate the amounts and pubkeys are correct.
uint64_t notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->GetHeight());
fprintf(stderr, "notarypaycheque.%lu\n", notarypaycheque);
if ( notarypaycheque > 0 )
blockReward += notarypaycheque;
else
return state.DoS(100, error("ConnectBlock(): Notary pay validation failed!"),
REJECT_INVALID, "bad-cb-amount");
}
}
// Move the block to the main block file, we need this to create the TxIndex in the following loop.
if ( (pindex->nStatus & BLOCK_IN_TMPFILE) != 0 )
{
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
@@ -3275,7 +3314,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
return error("AcceptBlock(): ReceivedBlockTransactions failed");
setDirtyFileInfo.insert(blockPos.nFile);
fprintf(stderr,"added ht.%d copy of tmpfile to %d.%d\n",pindex->GetHeight(),blockPos.nFile,blockPos.nPos);
//fprintf(stderr,"added ht.%d copy of tmpfile to %d.%d\n",pindex->GetHeight(),blockPos.nFile,blockPos.nPos);
}
// verify that the view's current state corresponds to the previous block
uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash();
@@ -3383,6 +3422,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
{
if (!view.HaveInputs(tx))
{
fprintf(stderr, "Connect Block missing inputs tx_number.%d \nvin txid.%s vout.%d \n",i,tx.vin[0].prevout.hash.ToString().c_str(),tx.vin[0].prevout.n);
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
}
@@ -3390,6 +3430,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
if (!view.HaveJoinSplitRequirements(tx))
return state.DoS(100, error("ConnectBlock(): JoinSplit requirements not met"),
REJECT_INVALID, "bad-txns-joinsplit-requirements-not-met");
if (fAddressIndex || fSpentIndex)
{
for (size_t j = 0; j < tx.vin.size(); j++) {
@@ -3542,8 +3583,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
CAmount blockReward = nFees + GetBlockSubsidy(pindex->GetHeight(), chainparams.GetConsensus()) + sum;
if ( ASSETCHAINS_COMMISSION != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 &&
blockReward += nFees + GetBlockSubsidy(pindex->GetHeight(), chainparams.GetConsensus()) + sum;
if ( ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 ) //ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 &&
{
uint64_t checktoshis;
if ( (checktoshis= komodo_commission((CBlock *)&block,(int32_t)pindex->GetHeight())) != 0 )
@@ -3563,6 +3604,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
{
if ( ASSETCHAINS_SYMBOL[0] != 0 || pindex->GetHeight() >= KOMODO_NOTARIES_HEIGHT1 || block.vtx[0].vout[0].nValue > blockReward )
{
//fprintf(stderr, "coinbase pays too much\n");
//sleepflag = true;
return state.DoS(100,
error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)",
block.vtx[0].GetValueOut(), blockReward),
@@ -3610,7 +3653,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
setDirtyBlockIndex.insert(pindex);
}
ConnectNotarisations(block, pindex->GetHeight());
ConnectNotarisations(block, pindex->GetHeight()); // MoMoM notarisation DB.
if (fTxIndex)
if (!pblocktree->WriteTxIndex(vPos))
@@ -3666,7 +3709,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001);
//FlushStateToDisk();
komodo_connectblock(pindex,*(CBlock *)&block);
komodo_connectblock(false,pindex,*(CBlock *)&block); // dPoW state update.
return true;
}
@@ -3736,7 +3779,8 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
std::vector<std::pair<int, const CBlockFileInfo*> > vFiles;
vFiles.reserve(setDirtyFileInfo.size());
for (set<int>::iterator it = setDirtyFileInfo.begin(); it != setDirtyFileInfo.end(); ) {
vFiles.push_back(make_pair(*it, &vinfoBlockFile[*it]));
if ( *it < TMPFILE_START )
vFiles.push_back(make_pair(*it, &vinfoBlockFile[*it]));
setDirtyFileInfo.erase(it++);
}
std::vector<const CBlockIndex*> vBlocks;
@@ -3854,8 +3898,8 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
return AbortNode(state, "Failed to read block");
//if ( ASSETCHAINS_SYMBOL[0] != 0 || pindexDelete->GetHeight() > 1400000 )
{
int32_t prevMoMheight; uint256 notarizedhash,txid;
komodo_notarized_height(&prevMoMheight,&notarizedhash,&txid);
int32_t notarizedht,prevMoMheight; uint256 notarizedhash,txid;
notarizedht = komodo_notarized_height(&prevMoMheight,&notarizedhash,&txid);
if ( block.GetHash() == notarizedhash )
{
fprintf(stderr,"DisconnectTip trying to disconnect notarized block at ht.%d\n",(int32_t)pindexDelete->GetHeight());
@@ -3921,13 +3965,17 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) {
assert(pcoinsTip->GetSaplingAnchorAt(pcoinsTip->GetBestAnchor(SAPLING), newSaplingTree));
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
std::vector<uint256> TxToRemove;
for (int i = 0; i < block.vtx.size(); i++)
{
CTransaction &tx = block.vtx[i];
//if ((i == (block.vtx.size() - 1)) && ((ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock()) || (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block) != 0))))
if ((i == (block.vtx.size() - 1)) && (ASSETCHAINS_STAKED != 0 && (komodo_isPoS((CBlock *)&block,pindexDelete->GetHeight()) != 0)))
{
EraseFromWallets(tx.GetHash());
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->EraseFromWallet(tx.GetHash());
#endif
}
else
{
@@ -4578,12 +4626,20 @@ bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, u
std::vector<CBlockFileInfo> *ptr; int *lastfilep;
LOCK(cs_LastBlockFile);
unsigned int nFile;
unsigned int nFile,maxTempFileSize;
if ( tmpflag != 0 )
{
ptr = &tmpBlockFiles;
nFile = nLastTmpFile;
lastfilep = &nLastTmpFile;
if (tmpBlockFiles.size() <= nFile) {
tmpBlockFiles.resize(nFile + 1);
}
if ( nFile == 0 )
maxTempFileSize = maxTempFileSize0;
else if ( nFile == 1 )
maxTempFileSize = maxTempFileSize1;
}
else
{
@@ -4594,25 +4650,89 @@ bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, u
vinfoBlockFile.resize(nFile + 1);
}
}
if (!fKnown) {
while ((*ptr)[nFile].nSize + nAddSize >= MAX_BLOCKFILE_SIZE) {
bool tmpfileflag = false;
while ( (*ptr)[nFile].nSize + nAddSize >= ((tmpflag != 0) ? maxTempFileSize : MAX_BLOCKFILE_SIZE) ) {
if ( tmpflag != 0 && tmpfileflag )
break;
nFile++;
if ((*ptr).size() <= nFile) {
(*ptr).resize(nFile + 1);
}
tmpfileflag = true;
}
pos.nFile = nFile + tmpflag*TMPFILE_START;
pos.nPos = (*ptr)[nFile].nSize;
if ( 0 && tmpflag != 0 )
fprintf(stderr,"pos.nFile %d nPos %u\n",pos.nFile,pos.nPos);
}
if (nFile != *lastfilep) {
if (!fKnown) {
LogPrintf("Leaving block file %i: %s\n", nFile, (*ptr)[nFile].ToString());
}
FlushBlockFile(!fKnown);
//fprintf(stderr, "nFile = %i size.%li maxTempFileSize0.%u maxTempFileSize1.%u\n",nFile,tmpBlockFiles.size(),maxTempFileSize0,maxTempFileSize1);
if ( tmpflag != 0 && tmpBlockFiles.size() >= 3 )
{
if ( nFile == 1 ) // Trying to get to second temp file.
{
if (!PruneOneBlockFile(true,TMPFILE_START+1))
{
// file 1 is not ready to be used yet increase file 0's size.
fprintf(stderr, "Cant clear file 1!\n");
// We will reset the position to the end of the first file, even if its over max size.
nFile = 0;
pos.nFile = TMPFILE_START;
pos.nPos = (*ptr)[0].nSize;
// Increase temp file one's max size by a chunk, so we wait a reasonable time to recheck the other file.
maxTempFileSize0 += BLOCKFILE_CHUNK_SIZE;
}
else
{
// The file 1 is able to be used now. Reset max size, and set nfile to use file 1.
fprintf(stderr, "CLEARED file 1!\n");
maxTempFileSize0 = MAX_TEMPFILE_SIZE;
nFile = 1;
tmpBlockFiles[1].SetNull();
pos.nFile = TMPFILE_START+1;
pos.nPos = (*ptr)[1].nSize;
boost::filesystem::remove(GetBlockPosFilename(pos, "blk"));
LogPrintf("Prune: deleted temp blk (%05u)\n",nFile);
}
if ( 0 && tmpflag != 0 )
fprintf(stderr,"pos.nFile %d nPos %u\n",pos.nFile,pos.nPos);
}
else if ( nFile == 2 ) // Trying to get to third temp file.
{
if (!PruneOneBlockFile(true,TMPFILE_START))
{
fprintf(stderr, "Cant clear file 0!\n");
// We will reset the position to the end of the second block file, even if its over max size.
nFile = 1;
pos.nFile = TMPFILE_START+1;
pos.nPos = (*ptr)[1].nSize;
// Increase temp file one's max size by a chunk, so we wait a reasonable time to recheck the other file.
maxTempFileSize1 += BLOCKFILE_CHUNK_SIZE;
}
else
{
// The file 0 is able to be used now. Reset max size, and set nfile to use file 0.
fprintf(stderr, "CLEARED file 0!\n");
maxTempFileSize1 = MAX_TEMPFILE_SIZE;
nFile = 0;
tmpBlockFiles[0].SetNull();
pos.nFile = TMPFILE_START;
pos.nPos = (*ptr)[0].nSize;
boost::filesystem::remove(GetBlockPosFilename(pos, "blk"));
LogPrintf("Prune: deleted temp blk (%05u)\n",nFile);
}
if ( 0 && tmpflag != 0 )
fprintf(stderr,"pos.nFile %d nPos %u\n",pos.nFile,pos.nPos);
}
//sleep(30);
}
//fprintf(stderr, "nFile = %i size.%li maxTempFileSize0.%u maxTempFileSize1.%u\n",nFile,tmpBlockFiles.size(),maxTempFileSize0,maxTempFileSize1); sleep(30);
*lastfilep = nFile;
//fprintf(stderr, "*lastfilep = %i\n",*lastfilep);
}
(*ptr)[nFile].AddBlock(nHeight, nTime);
@@ -4884,6 +5004,7 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
if (!CheckTransaction(tiptime,tx, state, verifier))
return error("CheckBlock: CheckTransaction failed");
}
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, block.vtx)
{
@@ -5209,7 +5330,12 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C
}
int nHeight = pindex->GetHeight();
// Temp File fix. LABS has been using this for ages with no bad effects.
// Disabled here. Set use tmp to whatever you need to use this for.
int32_t usetmp = 0;
if ( IsInitialBlockDownload() )
usetmp = 0;
// Write block to history file
try {
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
@@ -5344,6 +5470,27 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo
komodo_currentheight_set(chainActive.LastTip()->GetHeight());
checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0);
bool fRequested = MarkBlockAsReceived(hash);
// Test thing on LABS to test viability of rejecting a node pushing a chain.
// Supposed to stop malicious forks being pushed. Untested. Disabled incase of problems it may cause.
if ( 0 && pfrom && !fRequested && vNodes.size() > 1 )
{
pfrom->nBlocksinARow += 1;
if ( pfrom->nBlocksinARow >= 10 )
{
pfrom->nBlocksinARow2 += 1;
if ( pfrom->nBlocksinARow2 > 5 )
{
pfrom->nBlocksinARow = 0;
pfrom->nBlocksinARow2 = 0;
fprintf(stderr, "reset node.%i\n",(int32_t)pfrom->GetId());
}
else
{
fprintf(stderr, "Requesting new peer node.%i blocksinrow.%i blocsinrow2.%i\n",(int32_t)pfrom->GetId(),pfrom->nBlocksinARow,pfrom->nBlocksinARow2);
return(false);
}
}
}
fRequested |= fForceProcessing;
if ( checked != 0 && komodo_checkPOW(0,pblock,height) < 0 ) //from_miner && ASSETCHAINS_STAKED == 0
{
@@ -5440,35 +5587,63 @@ uint64_t CalculateCurrentUsage()
}
/* Prune a block file (modify associated database entries)*/
void PruneOneBlockFile(const int fileNumber)
bool PruneOneBlockFile(bool tempfile, const int fileNumber)
{
for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it) {
uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height;
notarized_height = komodo_notarized_height(&prevMoMheight,&notarized_hash,&notarized_desttxid);
//fprintf(stderr, "pruneblockfile.%i\n",fileNumber); sleep(15);
for (BlockMap::iterator it = mapBlockIndex.begin(); it != mapBlockIndex.end(); ++it)
{
CBlockIndex* pindex = it->second;
if (pindex && pindex->nFile == fileNumber) {
if (pindex && pindex->nFile == fileNumber)
{
if ( tempfile && (pindex->nStatus & BLOCK_IN_TMPFILE != 0) )
{
if ( chainActive.Contains(pindex) )
{
// Block is in main chain so we cant clear this file!
return(false);
}
fprintf(stderr, "pindex height.%i notarized height.%i \n", pindex->GetHeight(), notarized_height);
if ( pindex->GetHeight() > notarized_height ) // Need to check this, does an invalid block have a height?
{
// This blocks height is not older than last notarization so it can be reorged into the main chain.
// We cant clear this file!
return(false);
}
else
{
// Block is not in main chain and is older than last notarised block so its safe for removal.
fprintf(stderr, "Block [%i] in tempfile.%i We can clear this block!\n",pindex->GetHeight(),fileNumber);
// Add index to list and remove after loop?
}
}
pindex->nStatus &= ~BLOCK_HAVE_DATA;
pindex->nStatus &= ~BLOCK_HAVE_UNDO;
pindex->nFile = 0;
pindex->nDataPos = 0;
pindex->nUndoPos = 0;
setDirtyBlockIndex.insert(pindex);
// Prune from mapBlocksUnlinked -- any block we prune would have
// to be downloaded again in order to consider its chain, at which
// point it would be considered as a candidate for
// mapBlocksUnlinked or setBlockIndexCandidates.
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev);
while (range.first != range.second) {
while (range.first != range.second)
{
std::multimap<CBlockIndex *, CBlockIndex *>::iterator it = range.first;
range.first++;
if (it->second == pindex) {
if (it->second == pindex)
{
mapBlocksUnlinked.erase(it);
}
}
}
}
vinfoBlockFile[fileNumber].SetNull();
if (!tempfile)
vinfoBlockFile[fileNumber].SetNull();
setDirtyFileInfo.insert(fileNumber);
return(true);
}
@@ -5515,7 +5690,7 @@ void FindFilesToPrune(std::set<int>& setFilesToPrune)
if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune)
continue;
PruneOneBlockFile(fileNumber);
PruneOneBlockFile(false, fileNumber);
// Queue up the files for removal
setFilesToPrune.insert(fileNumber);
nCurrentUsage -= nBytesToPrune;
@@ -6689,7 +6864,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
//fprintf(stderr,"netmsg: %s\n", strCommand.c_str());
//fprintf(stderr,"netmsg: %s\n", strCommand.c_str());
if (strCommand == "version")
{
@@ -6706,16 +6881,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CAddress addrFrom;
uint64_t nNonce = 1;
int nVersion; // use temporary for version, don't set version number until validated as connected
int minVersion = MIN_PEER_PROTO_VERSION;
if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 )
minVersion = STAKEDMIN_PEER_PROTO_VERSION;
vRecv >> nVersion >> pfrom->nServices >> nTime >> addrMe;
if (nVersion == 10300)
nVersion = 300;
if (nVersion < MIN_PEER_PROTO_VERSION)
if (nVersion < minVersion)
{
// disconnect from peers older than this proto version
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION));
strprintf("Version must be %d or greater", minVersion));
pfrom->fDisconnect = true;
return false;
}

View File

@@ -90,7 +90,8 @@ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default for -txexpirydelta, in number of blocks */
static const unsigned int DEFAULT_TX_EXPIRY_DELTA = 20;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
static const unsigned int MAX_TEMPFILE_SIZE = 0x1000000; // 16 MiB 0x8000000
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB
/** The pre-allocation chunk size for rev?????.dat files (since 0.8) */
@@ -807,6 +808,7 @@ bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHea
bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos,bool checkPOW);
bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex,bool checkPOW);
bool RemoveOrphanedBlocks(int32_t notarized_height);
bool PruneOneBlockFile(bool tempfile, const int fileNumber);
/** Functions for validating blocks and updating the block tree */

View File

@@ -136,7 +136,7 @@ int64_t GetUptime()
double GetLocalSolPS()
{
if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH || ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1)
{
return miningTimer.rate(nHashCount);
}

View File

@@ -55,6 +55,8 @@
#include "sodium.h"
#include "notaries_staked.h"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#ifdef ENABLE_MINING
@@ -128,8 +130,8 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
}
}
#include "komodo_defs.h"
#include "cc/CCinclude.h"
extern CCriticalSection cs_metrics;
void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
@@ -147,9 +149,11 @@ int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blockt
int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk);
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);
bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey);
uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector<int8_t> &NotarisationNotaries, uint32_t timestamp, int32_t height, uint8_t *script, int32_t len);
int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp);
CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
{
@@ -169,6 +173,8 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
} else pk = _pk;
uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params();
bool fNotarisationBlock = false; std::vector<int8_t> NotarisationNotaries;
//fprintf(stderr,"create new block\n");
// Create new block
if ( gpucount < 0 )
@@ -211,7 +217,8 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
// we will attempt to spend any cheats we see
CTransaction cheatTx;
boost::optional<CTransaction> cheatSpend;
uint256 cbHash;
uint256 cbHash;
CBlockIndex* pindexPrev = 0;
{
@@ -225,6 +232,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
uint32_t proposedTime = GetAdjustedTime();
if (proposedTime == nMedianTimePast)
{
// too fast or stuck, this addresses the too fast issue, while moving
@@ -237,6 +245,13 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
}
}
pblock->nTime = GetAdjustedTime();
// Now we have the block time + height, we can get the active notaries.
int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0};
if ( ASSETCHAINS_NOTARY_PAY[0] != 0 )
{
// Only use speical miner for notary pay chains.
numSN = komodo_notaries(notarypubkeys, nHeight, pblock->nTime);
}
CCoinsViewCache view(pcoinsTip);
uint32_t expired; uint64_t commission;
@@ -254,6 +269,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
vecPriority.reserve(mempool.mapTx.size() + 1);
// now add transactions from the mem pool
int32_t Notarisations = 0;
for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
mi != mempool.mapTx.end(); ++mi)
{
@@ -280,12 +296,18 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
CAmount nTotalIn = 0;
bool fMissingInputs = false;
bool fNotarisation = false;
std::vector<int8_t> TMP_NotarisationNotaries;
if (tx.IsCoinImport())
{
CAmount nValueIn = GetCoinImportValue(tx);
CAmount nValueIn = GetCoinImportValue(tx); // burn amount
nTotalIn += nValueIn;
dPriority += (double)nValueIn * 1000; // flat multiplier
dPriority += (double)nValueIn * 1000; // flat multiplier... max = 1e16.
} else {
TMP_NotarisationNotaries.clear();
bool fToCryptoAddress = false;
if ( numSN != 0 && notarypubkeys[0][0] != 0 && komodo_is_notarytx(tx) == 1 )
fToCryptoAddress = true;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Read prev transaction
@@ -323,9 +345,33 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
nTotalIn += nValueIn;
int nConf = nHeight - coins->nHeight;
uint8_t *script; int32_t scriptlen; uint256 hash; CTransaction tx1;
// loop over notaries array and extract index of signers.
if ( fToCryptoAddress && GetTransaction(txin.prevout.hash,tx1,hash,false) )
{
for (int8_t i = 0; i < numSN; i++)
{
script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0];
scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size();
if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 )
{
// We can add the index of each notary to vector, and clear it if this notarisation is not valid later on.
TMP_NotarisationNotaries.push_back(i);
}
}
}
dPriority += (double)nValueIn * nConf;
}
if ( numSN != 0 && TMP_NotarisationNotaries.size() >= numSN / 5 )
{
// check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems)
std::set<int> checkdupes( TMP_NotarisationNotaries.begin(), TMP_NotarisationNotaries.end() );
if ( checkdupes.size() != TMP_NotarisationNotaries.size() )
{
fprintf(stderr, "possible notarisation is signed multiple times by same notary, passed as normal transaction.\n");
} else fNotarisation = true;
}
nTotalIn += tx.GetShieldedValueIn();
}
@@ -340,6 +386,36 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
if ( fNotarisation )
{
// Special miner for notary pay chains. Can only enter this if numSN/notarypubkeys is set higher up.
if ( tx.vout.size() == 2 && tx.vout[1].nValue == 0 )
{
// Get the OP_RETURN for the notarisation
uint8_t *script = (uint8_t *)&tx.vout[1].scriptPubKey[0];
int32_t scriptlen = (int32_t)tx.vout[1].scriptPubKey.size();
if ( script[0] == OP_RETURN )
{
Notarisations++;
if ( Notarisations > 1 )
{
fprintf(stderr, "skipping notarization.%d\n",Notarisations);
// Any attempted notarization needs to be in its own block!
continue;
}
// this is the first one we see, add it to the block as TX1
NotarisationNotaries = TMP_NotarisationNotaries;
dPriority = 1e16;
fNotarisationBlock = true;
fprintf(stderr, "Notarisation %s set to maximum priority\n",hash.ToString().c_str());
}
}
}
else if ( dPriority == 1e16 )
{
dPriority -= 10;
// make sure notarisation is tx[1] in block.
}
if (porphan)
{
porphan->dPriority = dPriority;
@@ -473,7 +549,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
int32_t stakeHeight = chainActive.Height() + 1;
//LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits);
//LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x stake.%i\n", nBlockSize,blocktime,pblock->nBits,isStake);
if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake )
{
LEAVE_CRITICAL_SECTION(cs_main);
@@ -499,6 +575,21 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
//if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
// blocktime = pindexPrev->GetMedianTimePast() + 60;
siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig);
// if you skip this check it will create a block too far into the future and not pass ProcessBlock or AcceptBlock.
// This has been moved from the mining loop to save CPU, and to also make ac_staked work with the verus miner.
while ( blocktime-57 > GetAdjustedTime() )
{
sleep(1);
if ( (rand() % 100) < 1 )
fprintf(stderr, "%u seconds until elegible, waiting.\n", blocktime-((uint32_t)GetAdjustedTime()+57));
if ( chainActive.LastTip()->GetHeight() >= stakeHeight )
{
fprintf(stderr, "Block Arrived, reset staking loop.\n");
return(0);
}
if( !GetBoolArg("-gen",false) )
return(0);
}
}
if ( siglen > 0 )
@@ -512,9 +603,10 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32
pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
nFees += txfees;
pblock->nTime = blocktime;
printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
//printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
} else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
}
// Create coinbase tx
CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
txNew.vin.resize(1);
@@ -541,7 +633,7 @@ printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeigh
txNew.vout[1].nValue = 0;
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 )
else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && (ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1) && (ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_FOUNDERS_REWARD != 0) && (commission= komodo_commission((CBlock*)&pblocktemplate->block,(int32_t)nHeight)) != 0 )
{
int32_t i; uint8_t *ptr;
txNew.vout.resize(2);
@@ -584,6 +676,11 @@ printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeigh
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;
}
@@ -592,7 +689,29 @@ printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeigh
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
// timelocks and commissions are currently incompatible due to validation complexity of the combination
}
else if ( fNotarisationBlock && ASSETCHAINS_NOTARY_PAY[0] != 0 && pblock->vtx[1].vout.size() == 2 && pblock->vtx[1].vout[1].nValue == 0 )
{
// Get the OP_RETURN for the notarisation
uint8_t *script = (uint8_t *)&pblock->vtx[1].vout[1].scriptPubKey[0];
int32_t scriptlen = (int32_t)pblock->vtx[1].vout[1].scriptPubKey.size();
if ( script[0] == OP_RETURN )
{
uint64_t totalsats = komodo_notarypay(txNew, NotarisationNotaries, pblock->nTime, nHeight, script, scriptlen);
if ( totalsats == 0 )
{
fprintf(stderr, "Could not create notary payment, trying again.\n");
if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) )
{
LEAVE_CRITICAL_SECTION(cs_main);
LEAVE_CRITICAL_SECTION(mempool.cs);
}
return(0);
}
fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats);
} else fprintf(stderr, "vout 2 of notarisation is not OP_RETURN scriptlen.%i\n", scriptlen);
}
pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
@@ -790,17 +909,15 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight,
scriptPubKey.resize(35);
ptr = (uint8_t *)pubkey.begin();
scriptPubKey[0] = 33;
for (i=0; i<33; i++)
for (i=0; i<33; i++) {
scriptPubKey[i+1] = ptr[i];
}
scriptPubKey[34] = OP_CHECKSIG;
//scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
}
}
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);
return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake);
}
void komodo_broadcast(CBlock *pblock,int32_t limit)
@@ -1196,14 +1313,14 @@ void static BitcoinMiner_noeq()
miningTimer.start();
#ifdef ENABLE_WALLET
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0);
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0, ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0);
#else
CBlockTemplate *ptr = CreateNewBlockWithKey();
#endif
if ( ptr == 0 )
{
static uint32_t counter;
if ( counter++ < 10 )
if ( ASSETCHAINS_STAKED == 0 && counter++ < 10 )
fprintf(stderr,"created illegal block, retry\n");
continue;
}
@@ -1246,6 +1363,7 @@ void static BitcoinMiner_noeq()
pblock->nSolution = solnPlaceholder;
savebits = pblock->nBits;
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
HASHTarget = arith_uint256().SetCompact(savebits);
arith_uint256 mask(ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO]);
Mining_start = 0;
@@ -1263,31 +1381,53 @@ void static BitcoinMiner_noeq()
if ( ASSETCHAINS_STAKED != 0 )
{
int32_t percPoS,z;
hashTarget = komodo_PoWtarget(&percPoS,hashTarget,Mining_height,ASSETCHAINS_STAKED);
for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&hashTarget)[z]);
fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED);
int32_t percPoS,z; bool fNegative,fOverflow;
HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
LogPrintf("Block %d : PoS %d%% vs target %d%%\n", Mining_height, percPoS, (int32_t)ASSETCHAINS_STAKED);
}
while (true)
{
arith_uint256 arNonce = UintToArith256(pblock->nNonce);
int64_t *extraPtr;
// This seems to be a really bad way to do this, but its better than copy pasting the entire miner function at this stage.
CVerusHashWriter ss = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
ss << *((CBlockHeader *)pblock);
int64_t *extraPtr = ss.xI64p();
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH )
extraPtr = ss.xI64p();
CVerusHash &vh = ss.GetState();
uint256 hashResult = uint256();
vh.ClearExtra();
CVerusHashV2Writer ss2 = CVerusHashV2Writer(SER_GETHASH, PROTOCOL_VERSION);
ss2 << *((CBlockHeader *)pblock);
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
extraPtr = ss2.xI64p();
CVerusHashV2 &vh2 = ss2.GetState();
vh2.ClearExtra();
int64_t i, count = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1;
int64_t hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
if ( ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 )
{
if ( KOMODO_MININGTHREADS > 0 )
hashTarget = HASHTarget_POW;
else
hashTarget = HASHTarget;
}
else if ( ASSETCHAINS_STAKED == 100 && Mining_height > 100 )
hashTarget = HASHTarget;
// for speed check NONCEMASK at a time
for (i = 0; i < count; i++)
{
*extraPtr = i;
vh.ExtraHash((unsigned char *)&hashResult);
if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH )
vh.ExtraHash((unsigned char *)&hashResult);
else if ( ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1 )
vh2.ExtraHash((unsigned char *)&hashResult);
if ( UintToArith256(hashResult) <= hashTarget )
{
@@ -1376,8 +1516,8 @@ void static BitcoinMiner_noeq()
#else
printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
#endif
pblock->nBits = savebits;
break;
}
}
}
@@ -1499,6 +1639,13 @@ void static BitcoinMiner()
#endif
if ( ptr == 0 )
{
if ( !GetBoolArg("-gen",false))
{
miningTimer.stop();
c.disconnect();
LogPrintf("KomodoMiner terminated\n");
return;
}
static uint32_t counter;
if ( counter++ < 10 && ASSETCHAINS_STAKED == 0 )
fprintf(stderr,"created illegal blockB, retry\n");
@@ -1594,17 +1741,14 @@ void static BitcoinMiner()
} //else fprintf(stderr,"duplicate at j.%d\n",j);
} else Mining_start = 0;
} else Mining_start = 0;
if ( ASSETCHAINS_STAKED != 0 )
if ( ASSETCHAINS_STAKED > 0 )
{
int32_t percPoS,z; bool fNegative,fOverflow;
HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
if ( ASSETCHAINS_STAKED < 100 && KOMODO_MININGTHREADS == 0 )
{
for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%% ht.%d\n",percPoS,(int32_t)ASSETCHAINS_STAKED,Mining_height);
}
if ( ASSETCHAINS_STAKED < 100 )
LogPrintf("Block %d : PoS %d%% vs target %d%% \n",Mining_height,percPoS,(int32_t)ASSETCHAINS_STAKED);
}
gotinvalid = 0;
while (true)
@@ -1660,7 +1804,7 @@ void static BitcoinMiner()
if ( h > hashTarget )
{
//if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 )
// sleep(1);
// MilliSleep(30);
return false;
}
if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetAdjustedTime() )
@@ -1687,12 +1831,6 @@ void static BitcoinMiner()
}
else
{
while ( B.nTime-57 > GetAdjustedTime() )
{
sleep(1);
if ( chainActive.LastTip()->GetHeight() >= Mining_height )
return(false);
}
uint256 tmp = B.GetHash();
int32_t z; for (z=31; z>=0; z--)
fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]);
@@ -1736,7 +1874,6 @@ void static BitcoinMiner()
std::lock_guard<std::mutex> lock{m_cs};
return cancelSolver;
};
// TODO: factor this out into a function with the same API for each solver.
if (solver == "tromp" ) { //&& notaryid >= 0 ) {
// Create solver and initialize it.
@@ -1903,12 +2040,12 @@ void static BitcoinMiner()
for (int i = 0; i < nThreads; i++) {
#ifdef ENABLE_WALLET
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH || (ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0) )
if ( ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH )
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
else
minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
#else
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH || (ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0) )
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH )
minerThreads->create_thread(&BitcoinMiner);
else
minerThreads->create_thread(&BitcoinMiner_noeq);

View File

@@ -78,6 +78,8 @@ namespace {
// Global state variables
//
extern uint16_t ASSETCHAINS_P2PPORT;
extern int8_t is_STAKED(const char *chain_name);
extern char ASSETCHAINS_SYMBOL[65];
bool fDiscover = true;
bool fListen = true;
@@ -1275,7 +1277,6 @@ void ThreadSocketHandler()
}
}
void ThreadDNSAddressSeed()
{
// goal: only query DNS seeds if address need is acute
@@ -1390,13 +1391,17 @@ void ThreadOpenConnections()
if (GetTime() - nStart > 60) {
static bool done = false;
if (!done) {
//LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
LogPrintf("Adding fixed seed nodes.\n");
addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
// skip DNS seeds for staked chains.
if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) {
//LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
LogPrintf("Adding fixed seed nodes.\n");
addrman.Add(convertSeed6(Params().FixedSeeds()), CNetAddr("127.0.0.1"));
}
done = true;
}
}
//
// Choose an address to connect to based on most recently seen
//
@@ -1803,6 +1808,12 @@ void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler)
Discover(threadGroup);
// skip DNS seeds for staked chains.
extern int8_t is_STAKED(const char *chain_name);
extern char ASSETCHAINS_SYMBOL[65];
if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 )
SoftSetBoolArg("-dnsseed", false);
//
// Start threads
//

View File

@@ -293,6 +293,9 @@ public:
bool fNetworkNode;
bool fSuccessfullyConnected;
bool fDisconnect;
// count blocks seen.
int8_t nBlocksinARow;
int8_t nBlocksinARow2;
// We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message
// b) the peer may tell us in its version message that we should not relay tx invs

View File

@@ -526,7 +526,8 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
else
#endif
{
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
if ( NetworkErrorString(WSAGetLastError()) != "Network is unreachable (101)")
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
CloseSocket(hSocket);
return false;
}

140
src/notaries_staked.cpp Normal file
View File

@@ -0,0 +1,140 @@
#include "notaries_staked.h"
#include "crosschain.h"
#include "cc/CCinclude.h"
#include <cstring>
extern char NOTARYADDRS[64][36];
extern std::string NOTARY_ADDRESS,NOTARY_PUBKEY;
extern int32_t STAKED_ERA,IS_STAKED_NOTARY,IS_KOMODO_NOTARY;
extern pthread_mutex_t staked_mutex;
extern uint8_t NOTARY_PUBKEY33[33],NUM_NOTARIES;
int8_t is_STAKED(const char *chain_name)
{
static int8_t STAKED,doneinit;
if ( chain_name[0] == 0 )
return(0);
if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0)
return(STAKED);
if ( (strcmp(chain_name, "LABS") == 0) || (strcmp(chain_name, "LABSTH") == 0) )
STAKED = 1; // These chains are allowed coin emissions.
else if ( (strncmp(chain_name, "LABS", 4) == 0) )
STAKED = 2; // These chains have no coin emission, block subsidy is always 0, and comission is 0. Notary pay is allowed.
else if ( (strcmp(chain_name, "CFEK") == 0) || (strncmp(chain_name, "CFEK", 4) == 0) )
STAKED = 3; // These chains have no speical rules at all.
else if ( (strcmp(chain_name, "TEST") == 0) || (strncmp(chain_name, "TEST", 4) == 0) )
STAKED = 4; // These chains are for testing consensus to create a chain etc. Not meant to be actually used for anything important.
else if ( (strcmp(chain_name, "THIS_CHAIN_IS_BANNED") == 0) )
STAKED = 255; // Any chain added to this group is banned, no notarisations are valid, as a consensus rule. Can be used to remove a chain from cluster if needed.
doneinit = 1;
return(STAKED);
};
int32_t STAKED_era(int timestamp)
{
int8_t era = 0;
if (timestamp <= STAKED_NOTARIES_TIMESTAMP[0])
return(1);
for (int32_t i = 1; i < NUM_STAKED_ERAS; i++)
{
if (timestamp <= STAKED_NOTARIES_TIMESTAMP[i] && timestamp >= (STAKED_NOTARIES_TIMESTAMP[i-1] + STAKED_ERA_GAP))
return(i+1);
}
// if we are in a gap, return era 0, this allows to invalidate notarizations when in GAP.
return(0);
};
int8_t updateStakedNotary() {
std::string notaryname;
char Raddress[18]; uint8_t pubkey33[33];
decode_hex(pubkey33,33,(char *)NOTARY_PUBKEY.c_str());
pubkey2addr((char *)Raddress,(uint8_t *)pubkey33);
NOTARY_ADDRESS.clear();
NOTARY_ADDRESS.assign(Raddress);
return(StakedNotaryID(notaryname,Raddress));
}
int8_t StakedNotaryID(std::string &notaryname, char *Raddress) {
if ( STAKED_ERA != 0 )
{
for (int8_t i = 0; i < num_notaries_STAKED[STAKED_ERA-1]; i++) {
if ( strcmp(Raddress,NOTARYADDRS[i]) == 0 ) {
notaryname.assign(notaries_STAKED[STAKED_ERA-1][i][0]);
return(i);
}
}
}
return(-1);
}
int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era) {
int i; int8_t retval = 0;
static uint8_t staked_pubkeys[NUM_STAKED_ERAS][64][33],didinit[NUM_STAKED_ERAS];
static char ChainName[65];
if ( ChainName[0] == 0 )
{
if ( ASSETCHAINS_SYMBOL[0] == 0 )
strcpy(ChainName,"KMD");
else
strcpy(ChainName,ASSETCHAINS_SYMBOL);
}
if ( era == 0 )
{
// era is zero so we need to null out the pubkeys.
memset(pubkeys,0,64 * 33);
printf("%s is a STAKED chain and is in an ERA GAP.\n",ChainName);
return(64);
}
else
{
if ( didinit[era-1] == 0 )
{
for (i=0; i<num_notaries_STAKED[era-1]; i++) {
decode_hex(staked_pubkeys[era-1][i],33,(char *)notaries_STAKED[era-1][i][1]);
}
didinit[era-1] = 1;
printf("%s is a STAKED chain in era %i \n",ChainName,era);
}
memcpy(pubkeys,staked_pubkeys[era-1],num_notaries_STAKED[era-1] * 33);
retval = num_notaries_STAKED[era-1];
}
return(retval);
}
void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) {
static int didinit;
if ( didinit == 0 ) {
pthread_mutex_init(&staked_mutex,NULL);
didinit = 1;
}
if ( pubkeys[0][0] == 0 )
{
// null pubkeys, era 0.
pthread_mutex_lock(&staked_mutex);
memset(NOTARYADDRS,0,sizeof(NOTARYADDRS));
NUM_NOTARIES = 0;
pthread_mutex_unlock(&staked_mutex);
}
else
{
// staked era is set.
pthread_mutex_lock(&staked_mutex);
for (int i = 0; i<numNotaries; i++)
pubkey2addr((char *)NOTARYADDRS[i],(uint8_t *)pubkeys[i]);
NUM_NOTARIES = numNotaries;
pthread_mutex_unlock(&staked_mutex);
}
}
CrosschainAuthority Choose_auth_STAKED(int32_t chosen_era) {
CrosschainAuthority auth;
auth.requiredSigs = (num_notaries_STAKED[chosen_era-1] / 5);
auth.size = num_notaries_STAKED[chosen_era-1];
for (int n=0; n<auth.size; n++)
for (size_t i=0; i<33; i++)
sscanf(notaries_STAKED[chosen_era-1][n][1]+(i*2), "%2hhx", auth.notaries[n]+i);
return auth;
};

129
src/notaries_staked.h Normal file
View File

@@ -0,0 +1,129 @@
#ifndef NOTARIES_STAKED
#define NOTARIES_STAKED
#include "crosschain.h"
#include "cc/CCinclude.h"
static const int32_t iguanaPort = 9997;
static const int8_t BTCminsigs = 13;
static const int8_t overrideMinSigs = 6;
static const char *iguanaSeeds[8][1] =
{
{"80.240.17.222"},
{"103.6.12.112"},
{"18.224.176.46"},
{"45.76.120.247"},
{"185.62.57.32"},
{"103.6.12.112"},
{"103.6.12.112"},
{"103.6.12.112"},
};
static const int STAKED_ERA_GAP = 777;
static const int NUM_STAKED_ERAS = 4;
static const int STAKED_NOTARIES_TIMESTAMP[NUM_STAKED_ERAS] = {1542964044, 1549188000, 1604233333, 1604244444};
static const int32_t num_notaries_STAKED[NUM_STAKED_ERAS] = { 17, 25, 19, 17 };
// Era array of pubkeys.
static const char *notaries_STAKED[NUM_STAKED_ERAS][64][2] =
{
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "03f87f1bccb744d90fdbf7fad1515a98e9fc7feb1800e460d2e7565b88c3971bf3" }, //RMwEpnaVe3cesWbMqqKYPPkaLcDkooTDgZ
{"smk762", "02eacef682d2f86e0103c18f4da46116e17196f3fb8f73ed931acb78e81d8e1aa5" }, // RQVvzJ8gepCDVjhqCAc5Tia1kTmt8KDPL9
{"jorian", "02150c410a606b898bcab4f083e48e0f98a510e0d48d4db367d37f318d26ae72e3" }, // RFgzxZe2P4RWKx6E9QGPK3rx3TXeWxSqa8
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" }, //RN2KsQGW36Ah4NorJDxLJp2xiYJJEzk9Y6
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"Bar_F1sh_Rel", "0395f2d9dd9ccb78caf74bff49b6d959afb95af746462e1b35f4a167d8e82b3666" }, // RBbLxJagCA9QHDazQvfnDZe874V1K4Gu8t
{"jusoaresf", "02dfb7ed72a23f6d07f0ea2f28192ee174733cc8412ec0f97b073007b78fab6346" }, // RBQGfE5Hxsjm1BPraTxbneRuNasPDuoLnu
{"mylo", "03f6b7fcaf0b8b8ec432d0de839a76598b78418dadd50c8e5594c0e557d914ec09" }, // RXN4hoZkhUkkrnef9nTUDw3E3vVALAD8Kx
{"blackjok3r2", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"blackjok3r3", "03c3e4c0206551dbf3a4b24d18e5d2737080541184211e3bfd2b1092177410b9c2" }, // RMMav2AVse5XHPvDfTzRpMbFhK3GqFmtSN
{"kmdkrazy", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"alrighttest", "02e9dfe248f453b499315a90375e58a1c9ad79f5f3932ecb2205399a0f262d65fc" }, // RBevSstS8JtDXMEFNcJws4QTYN4PcE2VL5
{"alrighttest1", "03527c7ecd6a8c5db6d685a64e6e18c1edb49e2f057a434f56c3f1253a26e9c6a2" }, // RBw2jNU3dnGk86ZLqPMadJwRwg3NU8eC6s
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "024d19acf0d5de212cdd50326cd143292545d366a71b2b9c6df9f2110de2dfa1f2" }, // RKtAD2kyRRMx4EiG1eeTNprF5h2nmGbzzu
{"smk762", "029f6c1f38c4d6825acb3b4b5147f7992e943b617cdaa0f4f5f36187e239d52d5a" }, // RPy6Xj2LWrxNoEW9YyREDgBZDZZ5qURXBU
{"jorian", "0288e682c1ac449f1b85c4acb2d0bcd216d5df34c15fd18b8a8dd5fa64b8ece8ef" }, // RR1yT5aB19VwFoUCGTW4q4pk4qmhHEEE4t
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" }, //RN2KsQGW36Ah4NorJDxLJp2xiYJJEzk9Y6
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2
{"jusoaresf", "02dfb7ed72a23f6d07f0ea2f28192ee174733cc8412ec0f97b073007b78fab6346" }, // RBQGfE5Hxsjm1BPraTxbneRuNasPDuoLnu
{"mylo", "03f6b7fcaf0b8b8ec432d0de839a76598b78418dadd50c8e5594c0e557d914ec09" }, // RXN4hoZkhUkkrnef9nTUDw3E3vVALAD8Kx
{"greentea", "02054c14ae81838a063d22a75eaa3c961415f6825a57c8b8e4148d19dad64f128e" }, // REF7R76WpL1v7nSXjjiNHtRa2xYtq5qk1p
{"CMaurice", "025830ce81bd1301fb67d5872344efa7a9ff99ae85fe1234f18c085db9072b740f" }, // RX7pXUaV24xFn6DVKV8t3PrRF3gKw6TBjf
{"kmdkrazy", "02da444a2627d420f1f622fcdfb9bddb67d6d4241ad6b4d5054716ddbde8a25dfb" }, // RJPJBbHcm5mkAxhkkERHRfEE9Cvkr4Euoi
{"Bar_F1sh_Rel", "0395f2d9dd9ccb78caf74bff49b6d959afb95af746462e1b35f4a167d8e82b3666" }, // RBbLxJagCA9QHDazQvfnDZe874V1K4Gu8t
{"zatJUM", "030fff499b6dc0215344b28a0b6b4becdfb00cd34cd1b36b983ec14f47965fd4bc" }, // RSoEDLBasth7anxS8gbkg6KgeGiz8rhqv1
{"dwy", "03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff" }, // RKhZMqRF361FSGFAzstP5AhozekPjoVh5q
{"dukeleto", "03e4322510ee46d417b8382fe124f5a381a3cef6aef08f8a4e90c66a42a04b4015" }, // RB8vS1fkGuttoNYkA2B1ivNn8vhqbCEqbe
{"gcharang", "03336ca9db27cb6e882830e20dc525884e27dc94d557a5e68b972a5cbf9e8c62a8" }, // RJYiWn3FRCSSLf9Pe5RJcbrKQYosaMburP
{"ca333", "03a18a33313ccdbf3c9778776e33c423e073ff5833fa1de092ce9e921de52f22f6" }, // RX333A56jWdeW15MwZsaW3mHxGaDu2Yutp
{"computergenie", "03448ce28fb21748e8b05bbe32d6b1e758b589ac1eb359e5d552f8868f2b75dc92" }, // RGeniexxkjnR34hg7ZnCf36kmfuJusf6rE
{"daemonfox", "0383484bdc745b2b953c85b5a0c496a1f27bc42ae971f15779ed1532421b3dd943" }, //
{"SHossain", "02791f5c215b8a19c143a98e3371ff03b5613df9ac430c4a331ca55fed5761c800" }, // RKdLoHkyeorXmMtj91B1AAnAGiwsdt9MdF
{"Nabob", "03ee91c20b6d26e3604022f42df6bb8de6f669da4591f93b568778cba13d9e9ddf" }, // RRwCLPZDzpHEFJnLev4phy51e2stHRUAaU
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "024d19acf0d5de212cdd50326cd143292545d366a71b2b9c6df9f2110de2dfa1f2" }, // RKtAD2kyRRMx4EiG1eeTNprF5h2nmGbzzu
{"smk762", "029f6c1f38c4d6825acb3b4b5147f7992e943b617cdaa0f4f5f36187e239d52d5a" }, // RPy6Xj2LWrxNoEW9YyREDgBZDZZ5qURXBU
{"jorian", "0288e682c1ac449f1b85c4acb2d0bcd216d5df34c15fd18b8a8dd5fa64b8ece8ef" }, // RR1yT5aB19VwFoUCGTW4q4pk4qmhHEEE4t
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2
{"greentea", "02054c14ae81838a063d22a75eaa3c961415f6825a57c8b8e4148d19dad64f128e" }, // REF7R76WpL1v7nSXjjiNHtRa2xYtq5qk1p
{"CMaurice", "025830ce81bd1301fb67d5872344efa7a9ff99ae85fe1234f18c085db9072b740f" }, // RX7pXUaV24xFn6DVKV8t3PrRF3gKw6TBjf
{"Bar_F1sh_Rel", "0395f2d9dd9ccb78caf74bff49b6d959afb95af746462e1b35f4a167d8e82b3666" }, // RBbLxJagCA9QHDazQvfnDZe874V1K4Gu8t
{"zatJUM", "030fff499b6dc0215344b28a0b6b4becdfb00cd34cd1b36b983ec14f47965fd4bc" }, // RSoEDLBasth7anxS8gbkg6KgeGiz8rhqv1
{"dwy", "03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff" }, // RKhZMqRF361FSGFAzstP5AhozekPjoVh5q
{"gcharang", "03336ca9db27cb6e882830e20dc525884e27dc94d557a5e68b972a5cbf9e8c62a8" }, // RJYiWn3FRCSSLf9Pe5RJcbrKQYosaMburP
{"computergenie", "03448ce28fb21748e8b05bbe32d6b1e758b589ac1eb359e5d552f8868f2b75dc92" }, // RGeniexxkjnR34hg7ZnCf36kmfuJusf6rE
{"daemonfox", "0383484bdc745b2b953c85b5a0c496a1f27bc42ae971f15779ed1532421b3dd943" }, //
{"SHossain", "02791f5c215b8a19c143a98e3371ff03b5613df9ac430c4a331ca55fed5761c800" }, // RKdLoHkyeorXmMtj91B1AAnAGiwsdt9MdF
{"Nabob", "03ee91c20b6d26e3604022f42df6bb8de6f669da4591f93b568778cba13d9e9ddf" }, // RRwCLPZDzpHEFJnLev4phy51e2stHRUAaU
},
{
{"blackjok3r", "021914947402d936a89fbdd1b12be49eb894a1568e5e17bb18c8a6cffbd3dc106e" }, // RTVti13NP4eeeZaCCmQxc2bnPdHxCJFP9x
{"alright", "0285657c689b903218c97f5f10fe1d10ace2ed6595112d9017f54fb42ea1c1dda8" }, //RXmXeQ8LfJK6Y1aTM97cRz9Gu5f6fmR3sg
{"webworker01", "031d1fb39ae4dca28965c3abdbd21faa0f685f6d7b87a60561afa7c448343fef6d" }, //RGsQiArk5sTmjXZV9UzGMW5njyvtSnsTN8
{"CrisF", "03f87f1bccb744d90fdbf7fad1515a98e9fc7feb1800e460d2e7565b88c3971bf3" }, //RMwEpnaVe3cesWbMqqKYPPkaLcDkooTDgZ
{"smk762", "02eacef682d2f86e0103c18f4da46116e17196f3fb8f73ed931acb78e81d8e1aa5" }, // RQVvzJ8gepCDVjhqCAc5Tia1kTmt8KDPL9
{"jorian", "02150c410a606b898bcab4f083e48e0f98a510e0d48d4db367d37f318d26ae72e3" }, // RFgzxZe2P4RWKx6E9QGPK3rx3TXeWxSqa8
{"TonyL", "021a559101e355c907d9c553671044d619769a6e71d624f68bfec7d0afa6bd6a96" }, // RHq3JsvLxU45Z8ufYS6RsDpSG4wi6ucDev
{"Emman", "038f642dcdacbdf510b7869d74544dbc6792548d9d1f8d73a999dd9f45f513c935" }, //RN2KsQGW36Ah4NorJDxLJp2xiYJJEzk9Y6
{"CHMEX", "03ed125d1beb118d12ff0a052bdb0cee32591386d718309b2924f2c36b4e7388e6" }, // RF4HiVeuYpaznRPs7fkRAKKYqT5tuxQQTL
{"metaphilibert", "0344182c376f054e3755d712361672138660bda8005abb64067eb5aa98bdb40d10" }, // RG28QSnYFADBg1dAVkH1uPGYS6F8ioEUM2
{"jusoaresf", "02dfb7ed72a23f6d07f0ea2f28192ee174733cc8412ec0f97b073007b78fab6346" }, // RBQGfE5Hxsjm1BPraTxbneRuNasPDuoLnu
{"mylo", "03f6b7fcaf0b8b8ec432d0de839a76598b78418dadd50c8e5594c0e557d914ec09" }, // RXN4hoZkhUkkrnef9nTUDw3E3vVALAD8Kx
{"blackjok3r2", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"blackjok3r3", "03c3e4c0206551dbf3a4b24d18e5d2737080541184211e3bfd2b1092177410b9c2" }, // RMMav2AVse5XHPvDfTzRpMbFhK3GqFmtSN
{"kmdkrazy", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e" }, // RWHGbrLSP89fTzNVF9U9xiekDYJqcibTca
{"alrighttest", "02e9dfe248f453b499315a90375e58a1c9ad79f5f3932ecb2205399a0f262d65fc" }, // RBevSstS8JtDXMEFNcJws4QTYN4PcE2VL5
{"alrighttest1", "03527c7ecd6a8c5db6d685a64e6e18c1edb49e2f057a434f56c3f1253a26e9c6a2" }, // RBw2jNU3dnGk86ZLqPMadJwRwg3NU8eC6s
}
};
int8_t is_STAKED(const char *chain_name);
int32_t STAKED_era(int timestamp);
int8_t updateStakedNotary();
int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era);
int8_t StakedNotaryID(std::string &notaryname, char *Raddress);
void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries);
CrosschainAuthority Choose_auth_STAKED(int32_t chosen_era);
#endif

View File

@@ -2,7 +2,9 @@
#include "notarisationdb.h"
#include "uint256.h"
#include "cc/eval.h"
#include "crosschain.h"
#include "main.h"
#include "notaries_staked.h"
#include <boost/foreach.hpp>
@@ -17,31 +19,50 @@ NotarisationsInBlock ScanBlockNotarisations(const CBlock &block, int nHeight)
{
EvalRef eval;
NotarisationsInBlock vNotarisations;
CrosschainAuthority auth_STAKED;
int timestamp = block.nTime;
for (unsigned int i = 0; i < block.vtx.size(); i++) {
CTransaction tx = block.vtx[i];
// Special case for TXSCL. Should prob be removed at some point.
bool isTxscl = 0;
{
NotarisationData data;
if (ParseNotarisationOpReturn(tx, data))
if (IsTXSCL(data.symbol))
isTxscl = 1;
NotarisationData data;
bool parsed = ParseNotarisationOpReturn(tx, data);
if (!parsed) data = NotarisationData();
if (strlen(data.symbol) == 0)
continue;
//printf("Checked notarisation data for %s \n",data.symbol);
int authority = GetSymbolAuthority(data.symbol);
if (authority == CROSSCHAIN_KOMODO) {
if (!eval->CheckNotaryInputs(tx, nHeight, block.nTime))
continue;
//printf("Authorised notarisation data for %s \n",data.symbol);
} else if (authority == CROSSCHAIN_STAKED) {
// We need to create auth_STAKED dynamically here based on timestamp
int32_t staked_era = STAKED_era(timestamp);
if (staked_era == 0) {
// this is an ERA GAP, so we will ignore this notarization
continue;
if ( is_STAKED(data.symbol) == 255 )
// this chain is banned... we will discard its notarisation.
continue;
} else {
// pass era slection off to notaries_staked.cpp file
auth_STAKED = Choose_auth_STAKED(staked_era);
}
if (!CheckTxAuthority(tx, auth_STAKED))
continue;
}
if (isTxscl || eval->CheckNotaryInputs(tx, nHeight, block.nTime)) {
NotarisationData data;
if (ParseNotarisationOpReturn(tx, data)) {
vNotarisations.push_back(std::make_pair(tx.GetHash(), data));
//printf("Parsed a notarisation for: %s, txid:%s, ccid:%i, momdepth:%i\n",
// data.symbol, tx.GetHash().GetHex().data(), data.ccId, data.MoMDepth);
//if (!data.MoMoM.IsNull()) printf("MoMoM:%s\n", data.MoMoM.GetHex().data());
}
else
LogPrintf("WARNING: Couldn't parse notarisation for tx: %s at height %i\n",
tx.GetHash().GetHex().data(), nHeight);
}
if (parsed) {
vNotarisations.push_back(std::make_pair(tx.GetHash(), data));
//printf("Parsed a notarisation for: %s, txid:%s, ccid:%i, momdepth:%i\n",
// data.symbol, tx.GetHash().GetHex().data(), data.ccId, data.MoMDepth);
//if (!data.MoMoM.IsNull()) printf("MoMoM:%s\n", data.MoMoM.GetHex().data());
} else
LogPrintf("WARNING: Couldn't parse notarisation for tx: %s at height %i\n",
tx.GetHash().GetHex().data(), nHeight);
}
return vNotarisations;
}

View File

@@ -44,10 +44,15 @@ unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock, const Consensus::Params& params)
{
if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH)
if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH && ASSETCHAINS_STAKED == 0)
return lwmaGetNextWorkRequired(pindexLast, pblock, params);
unsigned int nProofOfWorkLimit = UintToArith256(params.powLimit).GetCompact();
arith_uint256 bnLimit;
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
bnLimit = UintToArith256(params.powLimit);
else
bnLimit = UintToArith256(params.powAlternate);
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
// Genesis block
if (pindexLast == NULL )
return nProofOfWorkLimit;
@@ -102,7 +107,13 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
nActualTimespan = params.MaxActualTimespan();
// Retarget
const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
arith_uint256 bnLimit;
if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
bnLimit = UintToArith256(params.powLimit);
else
bnLimit = UintToArith256(params.powAlternate);
const arith_uint256 bnPowLimit = bnLimit; //UintToArith256(params.powLimit);
arith_uint256 bnNew {bnAvg};
bnNew /= params.AveragingWindowTimespan();
bnNew *= nActualTimespan;
@@ -133,6 +144,8 @@ unsigned int lwmaCalculateNextWorkRequired(const CBlockIndex* pindexLast, const
bnLimit = UintToArith256(params.powAlternate);
unsigned int nProofOfWorkLimit = bnLimit.GetCompact();
//printf("PoWLimit: %u\n", nProofOfWorkLimit);
// Find the first block in the averaging interval as we total the linearly weighted average
const CBlockIndex* pindexFirst = pindexLast;

View File

@@ -46,8 +46,11 @@ uint256 CBlockHeader::GetVerusHash() const
uint256 CBlockHeader::GetVerusV2Hash() const
{
// no check for genesis block and use the optimized hash
return SerializeVerusHashV2(*this);
if (hashPrevBlock.IsNull())
// always use SHA256D for genesis block
return SerializeHash(*this);
else
return SerializeVerusHashV2(*this);
}
void CBlockHeader::SetSHA256DHash()
@@ -60,6 +63,11 @@ void CBlockHeader::SetVerusHash()
CBlockHeader::hashFunction = &CBlockHeader::GetVerusHash;
}
void CBlockHeader::SetVerusHashV2()
{
CBlockHeader::hashFunction = &CBlockHeader::GetVerusV2Hash;
}
// returns false if unable to fast calculate the VerusPOSHash from the header.
// if it returns false, value is set to 0, but it can still be calculated from the full block
// in that case. the only difference between this and the POS hash for the contest is that it is not divided by the value out

View File

@@ -106,6 +106,7 @@ public:
uint256 GetVerusEntropyHash(int32_t nHeight) const;
uint256 GetVerusV2Hash() const;
static void SetVerusHashV2();
int64_t GetBlockTime() const
{

View File

@@ -49,6 +49,7 @@ extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex);
int32_t komodo_longestchain();
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
extern int8_t komodo_segid(int32_t nocache,int32_t height);
extern int32_t KOMODO_LONGESTCHAIN;
double GetDifficultyINTERNAL(const CBlockIndex* blockindex, bool networkDifficulty)
@@ -147,7 +148,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits)));
result.push_back(Pair("difficulty", GetDifficulty(blockindex)));
result.push_back(Pair("chainwork", blockindex->chainPower.chainWork.GetHex()));
result.push_back(Pair("segid", (int64_t)blockindex->segid));
result.push_back(Pair("segid", (int)komodo_segid(0,blockindex->GetHeight())));
if (blockindex->pprev)
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
@@ -174,7 +175,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex)
result.push_back(Pair("height", blockindex->GetHeight()));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
result.push_back(Pair("segid", (int64_t)blockindex->segid));
result.push_back(Pair("segid", (int)komodo_segid(0,blockindex->GetHeight())));
UniValue deltas(UniValue::VARR);
@@ -292,7 +293,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("height", blockindex->GetHeight()));
result.push_back(Pair("version", block.nVersion));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
result.push_back(Pair("segid", (int64_t)blockindex->segid));
result.push_back(Pair("segid", (int)komodo_segid(0,blockindex->GetHeight())));
result.push_back(Pair("finalsaplingroot", block.hashFinalSaplingRoot.GetHex()));
UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
@@ -627,7 +628,7 @@ UniValue getblockhash(const UniValue& params, bool fHelp)
return pblockindex->GetBlockHash().GetHex();
}
extern uint64_t ASSETCHAINS_STAKED;
extern int32_t ASSETCHAINS_STAKED;
UniValue getlastsegidstakes(const UniValue& params, bool fHelp)
{
@@ -653,22 +654,39 @@ UniValue getlastsegidstakes(const UniValue& params, bool fHelp)
LOCK(cs_main);
int depth = params[0].get_int();
if ( depth > chainActive.Height() )
throw runtime_error("Not enough blocks to scan back that far.\n");
int32_t segids[64] = {0};
int32_t pow = 0;
int32_t notset = 0;
for (int64_t i = chainActive.Height(); i > chainActive.Height()-depth; i--)
{
CBlockIndex* pblockindex = chainActive[i];
if ( pblockindex->segid >= 0 )
segids[pblockindex->segid] += 1;
int8_t segid = komodo_segid(0,i);
//CBlockIndex* pblockindex = chainActive[i];
if ( segid >= 0 )
segids[segid] += 1;
else if ( segid == -1 )
pow++;
else
notset++;
}
int8_t posperc = 100*(depth-pow)/depth;
UniValue ret(UniValue::VOBJ);
UniValue objsegids(UniValue::VOBJ);
for (int8_t i = 0; i < 64; i++)
{
char str[4];
sprintf(str, "%d", i);
ret.push_back(Pair(str,segids[i]));
objsegids.push_back(Pair(str,segids[i]));
}
ret.push_back(Pair("NotSet",notset));
ret.push_back(Pair("PoW",pow));
ret.push_back(Pair("PoSPerc",posperc));
ret.push_back(Pair("SegIds",objsegids));
return ret;
}

View File

@@ -51,6 +51,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "sendtoaddress", 1 },
{ "sendtoaddress", 4 },
{ "settxfee", 0 },
{ "getnotarysendmany", 0 },
{ "getnotarysendmany", 1 },
{ "getreceivedbyaddress", 1 },
{ "getreceivedbyaccount", 1 },
{ "listreceivedbyaddress", 0 },
@@ -87,6 +89,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "listunspent", 2 },
{ "getblock", 1 },
{ "getblockheader", 1 },
{ "getlastsegidstakes", 0 },
{ "gettransaction", 1 },
{ "getrawtransaction", 1 },
{ "getlastsegidstakes", 0 },

View File

@@ -116,7 +116,7 @@ UniValue height_MoM(const UniValue& params, bool fHelp)
ret.push_back(Pair("kmdendi",kmdendi));
}
} else ret.push_back(Pair("error",(char *)"no MoM for height"));
return ret;
}
@@ -169,10 +169,10 @@ UniValue calc_MoM(const UniValue& params, bool fHelp)
UniValue migrate_converttoexport(const UniValue& params, bool fHelp)
{
std::vector<uint8_t> rawproof; uint8_t *ptr; int32_t i; uint32_t ccid = ASSETCHAINS_CC;
if (fHelp || params.size() != 3)
std::vector<uint8_t> rawproof; uint8_t *ptr; uint8_t i; uint32_t ccid = ASSETCHAINS_CC; uint64_t txfee = 10000;
if (fHelp || params.size() != 2)
throw runtime_error(
"migrate_converttoexport rawTx dest_symbol export_amount\n"
"migrate_converttoexport rawTx dest_symbol\n"
"\nConvert a raw transaction to a cross-chain export.\n"
"If neccesary, the transaction should be funded using fundrawtransaction.\n"
"Finally, the transaction should be signed using signrawtransaction\n"
@@ -196,22 +196,22 @@ UniValue migrate_converttoexport(const UniValue& params, bool fHelp)
if (targetSymbol.size() == 0 || targetSymbol.size() > 32)
throw runtime_error("targetSymbol length must be >0 and <=32");
CAmount burnAmount = AmountFromValue(params[2]);
if (strcmp(ASSETCHAINS_SYMBOL,targetSymbol.c_str()) == 0)
throw runtime_error("cant send a coin to the same chain");
CAmount burnAmount = 0;
for (int i=0; i<tx.vout.size(); i++) burnAmount += tx.vout[i].nValue;
if (burnAmount <= 0)
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for export");
{
CAmount needed = 0;
for (int i=0; i<tx.vout.size(); i++) needed += tx.vout[i].nValue;
if (burnAmount < needed)
throw runtime_error("export_amount too small");
}
//if ( ASSETCHAINS_SELFIMPORT.size() > 0 )
// throw runtime_error("self-import chains cant be fungible");
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export a negative or zero value.");
if (burnAmount > 1000000LL*COIN)
throw JSONRPCError(RPC_TYPE_ERROR, "Cannot export more than 1 million coins per export.");
rawproof.resize(strlen(ASSETCHAINS_SYMBOL));
ptr = rawproof.data();
for (i=0; i<rawproof.size(); i++)
ptr[i] = ASSETCHAINS_SYMBOL[i];
CTxOut burnOut = MakeBurnOutput(burnAmount, ccid, targetSymbol, tx.vout,rawproof);
CTxOut burnOut = MakeBurnOutput(burnAmount+txfee, ccid, targetSymbol, tx.vout,rawproof);
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("payouts", HexStr(E_MARSHAL(ss << tx.vout))));
tx.vout.clear();
@@ -252,8 +252,8 @@ UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp)
CTransaction burnTx;
if (!E_UNMARSHAL(txData, ss >> burnTx))
throw runtime_error("Couldn't parse burnTx");
vector<CTxOut> payouts;
if (!E_UNMARSHAL(ParseHexV(params[1], "argument 2"), ss >> payouts))
throw runtime_error("Couldn't parse payouts");
@@ -273,7 +273,7 @@ UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp)
throw runtime_error("migrate_completeimporttransaction importTx\n\n"
"Takes a cross chain import tx with proof generated on assetchain "
"and extends proof to target chain proof root");
if (ASSETCHAINS_SYMBOL[0] != 0)
throw runtime_error("Must be called on KMD");
@@ -446,7 +446,7 @@ UniValue scanNotarisationsDB(const UniValue& params, bool fHelp)
if (height == 0) {
height = chainActive.Height();
}
Notarisation nota;
int matchedHeight = ScanNotarisationsDB(height, symbol, limit, nota);
if (!matchedHeight) return NullUniValue;
@@ -456,3 +456,116 @@ UniValue scanNotarisationsDB(const UniValue& params, bool fHelp)
out.pushKV("opreturn", HexStr(E_MARSHAL(ss << nota.second)));
return out;
}
UniValue getimports(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"getimports \"hash|height\"\n"
"\n\n"
"\nResult:\n"
"{\n"
" \"imports\" : [ (json array)\n"
" \"transactionid\" : { (json object)\n"
" \"value\" : (numeric)\n"
" \"address\" : (string)\n"
" \"export\" { (json object)\n"
" \"txid\" : (string)\n"
" \"value\" : (numeric)\n"
" \"chain\" : (string)\n"
" }\n"
" }"
" ]\n"
" \"TotalImported\" : (numeric)\n"
" \"time\" : (numeric)\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getimports", "\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\"")
+ HelpExampleRpc("getimports", "\"00000000febc373a1da2bd9f887b105ad79ddc26ac26c2b28652d64e5207c5b5\"")
+ HelpExampleCli("getimports", "12800")
+ HelpExampleRpc("getimports", "12800")
);
LOCK(cs_main);
std::string strHash = params[0].get_str();
// If height is supplied, find the hash
if (strHash.size() < (2 * sizeof(uint256))) {
// std::stoi allows characters, whereas we want to be strict
regex r("[[:digit:]]+");
if (!regex_match(strHash, r)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
}
int nHeight = -1;
try {
nHeight = std::stoi(strHash);
}
catch (const std::exception &e) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block height parameter");
}
if (nHeight < 0 || nHeight > chainActive.Height()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
}
strHash = chainActive[nHeight]->GetBlockHash().GetHex();
}
uint256 hash(uint256S(strHash));
if (mapBlockIndex.count(hash) == 0)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
CBlock block;
CBlockIndex* pblockindex = mapBlockIndex[hash];
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
if(!ReadBlockFromDisk(block, pblockindex,1))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
UniValue result(UniValue::VOBJ);
CAmount TotalImported = 0;
UniValue imports(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
{
if(tx.IsCoinImport())
{
UniValue objTx(UniValue::VOBJ);
objTx.push_back(Pair("txid",tx.GetHash().ToString()));
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
TotalImported += tx.vout[1].nValue;
objTx.push_back(Pair("amount", ValueFromAmount(tx.vout[1].nValue)));
if (ExtractDestination(tx.vout[1].scriptPubKey, importaddress))
{
objTx.push_back(Pair("address", CBitcoinAddress(importaddress).ToString()));
}
UniValue objBurnTx(UniValue::VOBJ);
if (UnmarshalImportTx(tx, proof, burnTx, payouts))
{
if (burnTx.vout.size() == 0)
continue;
objBurnTx.push_back(Pair("txid", burnTx.GetHash().ToString()));
objBurnTx.push_back(Pair("amount", ValueFromAmount(burnTx.vout.back().nValue)));
// extract op_return to get burn source chain.
std::vector<uint8_t> burnOpret; std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash; std::vector<uint8_t>rawproof;
if (UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof))
{
if (rawproof.size() > 0)
{
std::string sourceSymbol(rawproof.begin(), rawproof.end());
objBurnTx.push_back(Pair("source", sourceSymbol));
}
}
}
objTx.push_back(Pair("export", objBurnTx));
imports.push_back(objTx);
}
}
result.push_back(Pair("imports", imports));
result.push_back(Pair("TotalImported", TotalImported > 0 ? ValueFromAmount(TotalImported) : 0 ));
result.push_back(Pair("time", block.GetBlockTime()));
return result;
}

View File

@@ -180,8 +180,11 @@ UniValue getgenerate(const UniValue& params, bool fHelp)
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
bool staking = VERUS_MINTBLOCKS;
if ( ASSETCHAINS_STAKED != 0 && GetBoolArg("-gen", false) && GetBoolArg("-genproclimit", -1) == 0 )
staking = true;
obj.push_back(Pair("staking", staking));
obj.push_back(Pair("generate", GetBoolArg("-gen", false) && GetBoolArg("-genproclimit", -1) != 0 ));
obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
return obj;
}
@@ -215,7 +218,18 @@ UniValue generate(const UniValue& params, bool fHelp)
#endif
}
if (!Params().MineBlocksOnDemand())
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
{
if ( params[0].get_int() == 1 )
{
mapArgs["disablemining"] = "1";
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Mining Disabled");
}
else
{
mapArgs["disablemining"] = "0";
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Mining Enabled");
}
}
int nHeightStart = 0;
int nHeightEnd = 0;
@@ -345,7 +359,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
if (params.size() > 0)
fGenerate = params[0].get_bool();
int nGenProcLimit = GetArg("-genproclimit", -1);;
int nGenProcLimit = GetArg("-genproclimit", 0);;
if (params.size() > 1)
{
nGenProcLimit = params[1].get_int();
@@ -436,8 +450,11 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
obj.push_back(Pair("chain", Params().NetworkIDString()));
#ifdef ENABLE_MINING
obj.push_back(Pair("staking", VERUS_MINTBLOCKS));
obj.push_back(Pair("generate", GetBoolArg("-gen", false)));
bool staking = VERUS_MINTBLOCKS;
if ( ASSETCHAINS_STAKED != 0 && GetBoolArg("-gen", false) && GetBoolArg("-genproclimit", -1) == 0 )
staking = true;
obj.push_back(Pair("staking", staking));
obj.push_back(Pair("generate", GetBoolArg("-gen", false) && GetBoolArg("-genproclimit", -1) != 0 ));
obj.push_back(Pair("numthreads", (int64_t)KOMODO_MININGTHREADS));
#endif
return obj;
@@ -570,6 +587,9 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "komodod compiled without wallet and -mineraddress not set");
#endif
}
if ( GetArg("disablemining",false) )
throw JSONRPCError(RPC_TYPE_ERROR, "Mining is Disabled");
UniValue lpval = NullUniValue;
// TODO: Re-enable coinbasevalue once a specification has been written
@@ -714,10 +734,12 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
}
#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain);
pblocktemplate = CreateNewBlockWithKey(reservekey,chainActive.LastTip()->GetHeight()+1,KOMODO_MAXGPUCOUNT);
LEAVE_CRITICAL_SECTION(cs_main);
pblocktemplate = CreateNewBlockWithKey(reservekey,pindexPrevNew->GetHeight()+1,KOMODO_MAXGPUCOUNT,false);
#else
pblocktemplate = CreateNewBlockWithKey();
#endif
ENTER_CRITICAL_SECTION(cs_main);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory or no available utxo for staking");

View File

@@ -28,6 +28,7 @@
#include "timedata.h"
#include "txmempool.h"
#include "util.h"
#include "notaries_staked.h"
#include "cc/eval.h"
#include "cc/CCinclude.h"
#ifdef ENABLE_WALLET
@@ -63,26 +64,131 @@ int32_t Jumblr_depositaddradd(char *depositaddr);
int32_t Jumblr_secretaddradd(char *secretaddr);
uint64_t komodo_interestsum();
int32_t komodo_longestchain();
int32_t komodo_notarized_height(int32_t *prevhtp,uint256 *hashp,uint256 *txidp);
int32_t komodo_notarized_height(int32_t *prevMoMheightp,uint256 *hashp,uint256 *txidp);
bool komodo_txnotarizedconfirmed(uint256 txid);
uint32_t komodo_chainactive_timestamp();
int32_t komodo_whoami(char *pubkeystr,int32_t height,uint32_t timestamp);
extern uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE;
extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN;
extern int32_t KOMODO_LASTMINED,JUMBLR_PAUSE,KOMODO_LONGESTCHAIN,IS_STAKED_NOTARY,IS_KOMODO_NOTARY,STAKED_ERA;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
uint32_t komodo_segid32(char *coinaddr);
int64_t komodo_coinsupply(int64_t *zfundsp,int64_t *sproutfundsp,int32_t height);
int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp);
int8_t StakedNotaryID(std::string &notaryname, char *Raddress);
#define KOMODO_VERSION "0.3.3b"
#define VERUS_VERSION "0.4.0g"
extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT;
extern uint32_t ASSETCHAINS_CC;
extern uint32_t ASSETCHAINS_MAGIC;
extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY;
extern uint32_t ASSETCHAINS_LASTERA;
extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING;
extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[];
extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[];
extern uint32_t ASSETCHAINS_MAGIC,ASSETCHAINS_ALGO;
extern uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY;
extern int32_t ASSETCHAINS_LWMAPOS,ASSETCHAINS_SAPLING,ASSETCHAINS_STAKED;
extern uint64_t ASSETCHAINS_ENDSUBSIDY[],ASSETCHAINS_REWARD[],ASSETCHAINS_HALVING[],ASSETCHAINS_DECAY[],ASSETCHAINS_NOTARY_PAY[];
extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern uint8_t NOTARY_PUBKEY33[];
int32_t getera(int timestamp)
{
for (int32_t i = 0; i < NUM_STAKED_ERAS; i++) {
if ( timestamp <= STAKED_NOTARIES_TIMESTAMP[i] ) {
return(i);
}
}
return(0);
}
UniValue getiguanajson(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error("getiguanajson\nreturns json for iguana, for the current ERA.");
UniValue json(UniValue::VOBJ);
UniValue seeds(UniValue::VARR);
UniValue notaries(UniValue::VARR);
// get the current era, use local time for now.
// should ideally take blocktime of last known block?
int now = time(NULL);
int32_t era = getera(now);
// loop over seeds array and push back to json array for seeds
for (int8_t i = 0; i < 8; i++) {
seeds.push_back(iguanaSeeds[i][0]);
}
// loop over era's notaries and push back each pair to the notary array
for (int8_t i = 0; i < num_notaries_STAKED[era]; i++) {
UniValue notary(UniValue::VOBJ);
notary.push_back(Pair(notaries_STAKED[era][i][0],notaries_STAKED[era][i][1]));
notaries.push_back(notary);
}
// get the min sigs .. this always rounds UP so min sigs in iguana is +1 min sigs in komodod, due to some rounding error.
int minsigs;
if ( num_notaries_STAKED[era]/5 > overrideMinSigs )
minsigs = (num_notaries_STAKED[era] / 5) + 1;
else
minsigs = overrideMinSigs;
json.push_back(Pair("port",iguanaPort));
json.push_back(Pair("BTCminsigs",BTCminsigs));
json.push_back(Pair("minsigs",minsigs));
json.push_back(Pair("seeds",seeds));
json.push_back(Pair("notaries",notaries));
return json;
}
UniValue getnotarysendmany(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
"getnotarysendmany\n"
"Returns a sendmany JSON array with all current notaries Raddress's.\n"
"\nExamples:\n"
+ HelpExampleCli("getnotarysendmany", "10")
+ HelpExampleRpc("getnotarysendmany", "10")
);
int amount = 0;
if ( params.size() == 1 ) {
amount = params[0].get_int();
}
int era = getera(time(NULL));
UniValue ret(UniValue::VOBJ);
for (int i = 0; i<num_notaries_STAKED[era]; i++)
{
char Raddress[18]; uint8_t pubkey33[33];
decode_hex(pubkey33,33,(char *)notaries_STAKED[era][i][1]);
pubkey2addr((char *)Raddress,(uint8_t *)pubkey33);
ret.push_back(Pair(Raddress,amount));
}
return ret;
}
UniValue geterablockheights(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getnotarysendmany\n"
"Returns a JSON object with the first block in each era.\n"
);
CBlockIndex *pindex; int8_t lastera,era = 0; UniValue ret(UniValue::VOBJ);
for (size_t i = 1; i < chainActive.LastTip()->GetHeight(); i++)
{
pindex = chainActive[i];
era = getera(pindex->nTime)+1;
if ( era > lastera )
{
char str[16];
sprintf(str, "%d", era);
ret.push_back(Pair(str,i));
lastera = era;
}
}
return(ret);
}
UniValue getinfo(const UniValue& params, bool fHelp)
{
@@ -180,17 +286,17 @@ UniValue getinfo(const UniValue& params, bool fHelp)
#endif
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
{
char pubkeystr[65]; int32_t notaryid;
if ( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.LastTip()->GetHeight(),komodo_chainactive_timestamp())) >= 0 )
{
if ( NOTARY_PUBKEY33[0] != 0 ) {
char pubkeystr[65]; int32_t notaryid; std::string notaryname;
if ( (notaryid= StakedNotaryID(notaryname, (char *)NOTARY_ADDRESS.c_str())) != -1 ) {
obj.push_back(Pair("notaryid", notaryid));
obj.push_back(Pair("notaryname", notaryname));
} else if( (notaryid= komodo_whoami(pubkeystr,(int32_t)chainActive.LastTip()->GetHeight(),komodo_chainactive_timestamp())) >= 0 ) {
obj.push_back(Pair("notaryid", notaryid));
obj.push_back(Pair("pubkey", pubkeystr));
if ( KOMODO_LASTMINED != 0 )
obj.push_back(Pair("lastmined", KOMODO_LASTMINED));
} else if ( NOTARY_PUBKEY33[0] != 0 ) {
obj.push_back(Pair("pubkey", NOTARY_PUBKEY));
obj.push_back(Pair("lastmined", KOMODO_LASTMINED));
}
obj.push_back(Pair("pubkey", NOTARY_PUBKEY));
}
if ( ASSETCHAINS_CC != 0 )
obj.push_back(Pair("CCid", (int)ASSETCHAINS_CC));
@@ -201,13 +307,15 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("rpcport", ASSETCHAINS_RPCPORT));
if ( ASSETCHAINS_SYMBOL[0] != 0 )
{
if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 )
obj.push_back(Pair("StakedEra", STAKED_ERA));
//obj.push_back(Pair("name", ASSETCHAINS_SYMBOL));
obj.push_back(Pair("magic", (int)ASSETCHAINS_MAGIC));
obj.push_back(Pair("premine", ASSETCHAINS_SUPPLY));
if ( ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_LASTERA > 0 )
{
std::string acReward = "", acHalving = "", acDecay = "", acEndSubsidy = "";
std::string acReward = "", acHalving = "", acDecay = "", acEndSubsidy = "", acNotaryPay = "";
for (int i = 0; i <= ASSETCHAINS_LASTERA; i++)
{
if (i == 0)
@@ -216,6 +324,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
acHalving = std::to_string(ASSETCHAINS_HALVING[i]);
acDecay = std::to_string(ASSETCHAINS_DECAY[i]);
acEndSubsidy = std::to_string(ASSETCHAINS_ENDSUBSIDY[i]);
acNotaryPay = std::to_string(ASSETCHAINS_NOTARY_PAY[i]);
}
else
{
@@ -223,6 +332,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
acHalving += "," + std::to_string(ASSETCHAINS_HALVING[i]);
acDecay += "," + std::to_string(ASSETCHAINS_DECAY[i]);
acEndSubsidy += "," + std::to_string(ASSETCHAINS_ENDSUBSIDY[i]);
acNotaryPay += "," + std::to_string(ASSETCHAINS_NOTARY_PAY[i]);
}
}
if (ASSETCHAINS_LASTERA > 0)
@@ -231,6 +341,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("halving", acHalving));
obj.push_back(Pair("decay", acDecay));
obj.push_back(Pair("endsubsidy", acEndSubsidy));
obj.push_back(Pair("notarypay", acNotaryPay));
}
if ( ASSETCHAINS_COMMISSION != 0 )
@@ -239,6 +350,8 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("staked", ASSETCHAINS_STAKED));
if ( ASSETCHAINS_LWMAPOS != 0 )
obj.push_back(Pair("veruspos", ASSETCHAINS_LWMAPOS));
if ( ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH )
obj.push_back(Pair("algo",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]));
}
return obj;
}
@@ -1323,15 +1436,15 @@ UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 1)
{
string msg = "txnotarizedconfirmed txid\n"
"\nReturns true if transaction is notarized on chain that has dPoW or if confirmation number is greater than 60 on chain taht does not have dPoW.\n"
"\nReturns true if transaction is notarized on chain that has dPoW or if confirmation number is greater than 60 on chain taht does not have dPoW.\n"
"\nArguments:\n"
"1. txid (string, required) Transaction id.\n"
"1. txid (string, required) Transaction id.\n"
"\nResult:\n"
"{\n"
" true, (bool) The value the check.\n"
"}\n"
" true, (bool) The value the check.\n"
"}\n"
;
throw runtime_error(msg);
}

View File

@@ -35,6 +35,7 @@
#include "script/sign.h"
#include "script/standard.h"
#include "uint256.h"
#include "importcoin.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
@@ -202,6 +203,25 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())));
else if (tx.IsCoinImport()) {
in.push_back(Pair("is_import", "1"));
TxProof proof; CTransaction burnTx; std::vector<CTxOut> payouts; CTxDestination importaddress;
if (UnmarshalImportTx(tx, proof, burnTx, payouts))
{
if (burnTx.vout.size() == 0)
continue;
in.push_back(Pair("txid", burnTx.GetHash().ToString()));
in.push_back(Pair("value", ValueFromAmount(burnTx.vout.back().nValue)));
in.push_back(Pair("valueSat", burnTx.vout.back().nValue));
// extract op_return to get burn source chain.
std::vector<uint8_t> burnOpret; std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash; std::vector<uint8_t>rawproof;
if (UnmarshalBurnTx(burnTx, targetSymbol, &targetCCid, payoutsHash, rawproof))
{
if (rawproof.size() > 0)
{
std::string sourceSymbol(rawproof.begin(), rawproof.end());
in.push_back(Pair("address", "IMP-" + sourceSymbol + "-" + burnTx.GetHash().ToString()));
}
}
}
}
else {
in.push_back(Pair("txid", txin.prevout.hash.GetHex()));
@@ -256,6 +276,14 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue&
out.push_back(Pair("n", (int64_t)i));
UniValue o(UniValue::VOBJ);
ScriptPubKeyToJSON(txout.scriptPubKey, o, true);
if (txout.scriptPubKey.IsOpReturn() && txout.nValue != 0)
{
std::vector<uint8_t> burnOpret; std::string targetSymbol; uint32_t targetCCid; uint256 payoutsHash; std::vector<uint8_t>rawproof;
if (UnmarshalBurnTx(tx, targetSymbol, &targetCCid, payoutsHash, rawproof))
{
out.push_back(Pair("target", "EXPORT->" + targetSymbol));
}
}
out.push_back(Pair("scriptPubKey", o));
// Add spent information if spentindex is enabled
@@ -565,7 +593,7 @@ int32_t gettxout_scriptPubKey(uint8_t *scriptPubKey,int32_t maxsize,uint256 txid
uint256 hashBlock;
if ( GetTransaction(txid,tx,hashBlock,false) == 0 )
return(-1);
else if ( n < tx.vout.size() )
else if ( n < tx.vout.size() )
{
ptr = (uint8_t *)&tx.vout[n].scriptPubKey[0];
m = tx.vout[n].scriptPubKey.size();
@@ -1304,7 +1332,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
}
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
}
RelayTransaction(tx);
return hashTx.GetHex();

View File

@@ -291,6 +291,9 @@ static const CRPCCommand vRPCCommands[] =
// --------------------- ------------------------ ----------------------- ----------
/* Overall control/query calls */
{ "control", "help", &help, true },
{ "control", "getiguanajson", &getiguanajson, true },
{ "control", "getnotarysendmany", &getnotarysendmany, true },
{ "control", "geterablockheights", &geterablockheights, true },
{ "control", "stop", &stop, true },
/* P2P networking */
@@ -346,6 +349,7 @@ static const CRPCCommand vRPCCommands[] =
{ "crosschain", "crosschainproof", &crosschainproof, true },
{ "crosschain", "getNotarisationsForBlock", &getNotarisationsForBlock, true },
{ "crosschain", "scanNotarisationsDB", &scanNotarisationsDB, true },
{ "crosschain", "getimports", &getimports, true },
{ "crosschain", "migrate_converttoexport", &migrate_converttoexport, true },
{ "crosschain", "migrate_createimporttransaction", &migrate_createimporttransaction, true },
{ "crosschain", "migrate_completeimporttransaction", &migrate_completeimporttransaction, true },
@@ -557,6 +561,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "getaccountaddress", &getaccountaddress, true },
{ "wallet", "getaccount", &getaccount, true },
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true },
{ "wallet", "cleanwallettransactions", &cleanwallettransactions, false },
{ "wallet", "getbalance", &getbalance, false },
{ "wallet", "getbalance64", &getbalance64, false },
{ "wallet", "getnewaddress", &getnewaddress, true },

View File

@@ -353,6 +353,7 @@ extern UniValue signmessage(const UniValue& params, bool fHelp);
extern UniValue verifymessage(const UniValue& params, bool fHelp);
extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp);
extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp);
extern UniValue cleanwallettransactions(const UniValue& params, bool fHelp);
extern UniValue getbalance(const UniValue& params, bool fHelp);
extern UniValue getbalance64(const UniValue& params, bool fHelp);
extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp);
@@ -378,6 +379,9 @@ extern UniValue validateaddress(const UniValue& params, bool fHelp);
extern UniValue txnotarizedconfirmed(const UniValue& params, bool fHelp);
extern UniValue decodeccopret(const UniValue& params, bool fHelp);
extern UniValue getinfo(const UniValue& params, bool fHelp);
extern UniValue getiguanajson(const UniValue& params, bool fHelp);
extern UniValue getnotarysendmany(const UniValue& params, bool fHelp);
extern UniValue geterablockheights(const UniValue& params, bool fHelp);
extern UniValue setpubkey(const UniValue& params, bool fHelp);
extern UniValue getwalletinfo(const UniValue& params, bool fHelp);
extern UniValue getblockchaininfo(const UniValue& params, bool fHelp);
@@ -460,6 +464,7 @@ extern UniValue assetchainproof(const UniValue& params, bool fHelp);
extern UniValue crosschainproof(const UniValue& params, bool fHelp);
extern UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp);
extern UniValue scanNotarisationsDB(const UniValue& params, bool fHelp);
extern UniValue getimports(const UniValue& params, bool fHelp);
extern UniValue migrate_converttoexport(const UniValue& params, bool fHelp);
extern UniValue migrate_createimporttransaction(const UniValue& params, bool fHelp);
extern UniValue migrate_completeimporttransaction(const UniValue& params, bool fHelp);

View File

@@ -836,7 +836,7 @@ UniValue kvsearch(const UniValue& params, bool fHelp)
" \"currentheight\": xxxxx, (numeric) current height of the chain\n"
" \"key\": \"xxxxx\", (string) key\n"
" \"keylen\": xxxxx, (string) length of the key \n"
" \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n"
" \"owner\": \"xxxxx\" (string) hex string representing the owner of the key \n"
" \"height\": xxxxx, (numeric) height the key was stored at\n"
" \"expiration\": xxxxx, (numeric) height the key will expire\n"
" \"flags\": x (numeric) 1 if the key was created with a password; 0 otherwise.\n"

View File

@@ -407,7 +407,7 @@ bool ExtractDestination(const CScript& _scriptPubKey, CTxDestination& addressRet
addressRet = CScriptID(uint160(vSolutions[0]));
return true;
}
else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION)
{
if (vSolutions.size() > 1)

View File

@@ -60,7 +60,7 @@ static const char DB_LAST_BLOCK = 'l';
CCoinsViewDB::CCoinsViewDB(std::string dbName, size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / dbName, nCacheSize, fMemory, fWipe) {
}
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe)
{
}
@@ -122,7 +122,7 @@ uint256 CCoinsViewDB::GetBestBlock() const {
uint256 CCoinsViewDB::GetBestAnchor(ShieldedType type) const {
uint256 hashBestAnchor;
switch (type) {
case SPROUT:
if (!db.Read(DB_BEST_SPROUT_ANCHOR, hashBestAnchor))
@@ -436,6 +436,7 @@ bool CBlockTreeDB::ReadAddressIndex(uint160 addressHash, int type,
}
bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address);
uint32_t komodo_segid32(char *coinaddr);
UniValue CBlockTreeDB::Snapshot(int top)
{
@@ -448,23 +449,23 @@ UniValue CBlockTreeDB::Snapshot(int top)
result.push_back(Pair("start_time", (int) time(NULL)));
std::map <std::string,int> ignoredMap = {
{"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1},
{"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1},
{"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1},
{"RBM5LofZFodMeewUzoMWcxedm3L3hYRaWg", 1},
{"RAdcko2d94TQUcJhtFHZZjMyWBKEVfgn4J", 1},
{"RLzUaZ934k2EFCsAiVjrJqM8uU1vmMRFzk", 1},
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1},
{"RUDrX1v5toCsJMUgtvBmScKjwCB5NaR8py", 1},
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1},
{"RRvwmbkxR5YRzPGL5kMFHMe1AH33MeD8rN", 1},
{"RQLQvSgpPAJNPgnpc8MrYsbBhep95nCS8L", 1},
{"RK8JtBV78HdvEPvtV5ckeMPSTojZPzHUTe", 1},
{"RHVs2KaCTGUMNv3cyWiG1jkEvZjigbCnD2", 1},
{"RE3SVaDgdjkRPYA6TRobbthsfCmxQedVgF", 1},
{"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1},
{"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1},
{"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} //Burnaddress for null privkey
{"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1},
{"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1},
{"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1},
{"RBM5LofZFodMeewUzoMWcxedm3L3hYRaWg", 1},
{"RAdcko2d94TQUcJhtFHZZjMyWBKEVfgn4J", 1},
{"RLzUaZ934k2EFCsAiVjrJqM8uU1vmMRFzk", 1},
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1},
{"RUDrX1v5toCsJMUgtvBmScKjwCB5NaR8py", 1},
{"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1},
{"RRvwmbkxR5YRzPGL5kMFHMe1AH33MeD8rN", 1},
{"RQLQvSgpPAJNPgnpc8MrYsbBhep95nCS8L", 1},
{"RK8JtBV78HdvEPvtV5ckeMPSTojZPzHUTe", 1},
{"RHVs2KaCTGUMNv3cyWiG1jkEvZjigbCnD2", 1},
{"RE3SVaDgdjkRPYA6TRobbthsfCmxQedVgF", 1},
{"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1},
{"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1},
{"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} //Burnaddress for null privkey
};
int64_t startingHeight = chainActive.Height();
@@ -526,29 +527,31 @@ UniValue CBlockTreeDB::Snapshot(int top)
//fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses);
for (std::pair<std::string, CAmount> element : addressAmounts) {
vaddr.push_back( make_pair(element.second, element.first) );
vaddr.push_back( make_pair(element.second, element.first) );
}
std::sort(vaddr.rbegin(), vaddr.rend());
UniValue obj(UniValue::VOBJ);
UniValue addressesSorted(UniValue::VARR);
int topN = 0;
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) {
UniValue obj(UniValue::VOBJ);
obj.push_back( make_pair("addr", it->second.c_str() ) );
char amount[32];
sprintf(amount, "%.8f", (double) it->first / COIN);
obj.push_back( make_pair("amount", amount) );
total += it->first;
addressesSorted.push_back(obj);
topN++;
// If requested, only show top N addresses in output JSON
if (top == topN)
break;
for (std::vector<std::pair<CAmount, std::string>>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it)
{
UniValue obj(UniValue::VOBJ);
obj.push_back( make_pair("addr", it->second.c_str() ) );
char amount[32];
sprintf(amount, "%.8f", (double) it->first / COIN);
obj.push_back( make_pair("amount", amount) );
obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) );
total += it->first;
addressesSorted.push_back(obj);
topN++;
// If requested, only show top N addresses in output JSON
if (top == topN)
break;
}
if (top)
totalAddresses = top;
totalAddresses = top;
if (totalAddresses > 0) {
// Array of all addreses with balances

View File

@@ -34,6 +34,7 @@ static const int GETHEADERS_VERSION = 31800;
//! disconnect from peers older than this proto version
static const int MIN_PEER_PROTO_VERSION = 170002;
static const int STAKEDMIN_PEER_PROTO_VERSION = 170007;
//! nTime field added to CAddress, starting with this version;
//! if possible, avoid requesting addresses nodes older than this

View File

@@ -18,6 +18,7 @@ uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC;
uint32_t ASSETCHAINS_MAGIC = 2387029918;
uint32_t ASSETCHAINS_EQUIHASH = 0;
uint32_t ASSETCHAINS_VERUSHASH = 1;
uint32_t ASSETCHAINS_VERUSHASHV1_1 = 2;
uint32_t ASSETCHAINS_ALGO = 0;
int32_t ASSETCHAINS_LWMAPOS = 0;
int32_t VERUS_BLOCK_POSUNITS = 1000;

View File

@@ -37,6 +37,7 @@
#include "zcbenchmarks.h"
#include "script/interpreter.h"
#include "zcash/zip32.h"
#include "notaries_staked.h"
#include "utiltime.h"
#include "asyncrpcoperation.h"
@@ -64,9 +65,9 @@ using namespace std;
using namespace libzcash;
extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
extern std::string ASSETCHAINS_OVERRIDE_PUBKEY;
const std::string ADDR_TYPE_SPROUT = "sprout";
const std::string ADDR_TYPE_SAPLING = "sapling";
extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
uint32_t komodo_segid32(char *coinaddr);
int32_t komodo_dpowconfs(int32_t height,int32_t numconfs);
@@ -1030,6 +1031,109 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef
}
UniValue cleanwallettransactions(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (fHelp || params.size() > 1 )
throw runtime_error(
"cleanwallettransactions \"txid\"\n"
"\nRemove all txs that are spent. You can clear all txs bar one, by specifiying a txid.\n"
"\nPlease backup your wallet.dat before running this command.\n"
"\nArguments:\n"
"1. \"txid\" (string, optional) The transaction id to keep.\n"
"\nResult:\n"
"{\n"
" \"total_transactons\" : n, (numeric) Transactions in wallet of " + strprintf("%s",komodo_chainname()) + "\n"
" \"remaining_transactons\" : n, (numeric) Transactions in wallet after clean.\n"
" \"removed_transactons\" : n, (numeric) The number of transactions removed.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("cleanwallettransactions", "")
+ HelpExampleCli("cleanwallettransactions","\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ HelpExampleRpc("cleanwallettransactions", "")
+ HelpExampleRpc("cleanwallettransactions","\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
);
LOCK2(cs_main, pwalletMain->cs_wallet);
UniValue ret(UniValue::VOBJ);
uint256 exception; int32_t txs = pwalletMain->mapWallet.size();
std::vector<uint256> TxToRemove;
if (params.size() == 1)
{
exception.SetHex(params[0].get_str());
uint256 tmp_hash; CTransaction tmp_tx;
if (GetTransaction(exception,tmp_tx,tmp_hash,false))
{
if ( !pwalletMain->IsMine(tmp_tx) )
{
throw runtime_error("\nThe transaction is not yours!\n");
}
else
{
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if ( wtx.GetHash() != exception )
{
TxToRemove.push_back(wtx.GetHash());
}
}
}
}
else
{
throw runtime_error("\nThe transaction could not be found!\n");
}
}
else
{
// get all locked utxos to relock them later.
vector<COutPoint> vLockedUTXO;
pwalletMain->ListLockedCoins(vLockedUTXO);
// unlock all coins so that the following call containes all utxos.
pwalletMain->UnlockAllCoins();
// listunspent call... this gets us all the txids that are unspent, we search this list for the oldest tx,
vector<COutput> vecOutputs;
assert(pwalletMain != NULL);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
int32_t oldestTxDepth = 0;
BOOST_FOREACH(const COutput& out, vecOutputs)
{
if ( out.nDepth > oldestTxDepth )
oldestTxDepth = out.nDepth;
}
oldestTxDepth = oldestTxDepth + 1; // add extra block just for safety.
// lock all the previouly locked coins.
BOOST_FOREACH(COutPoint &outpt, vLockedUTXO) {
pwalletMain->LockCoin(outpt);
}
// then add all txs in the wallet before this block to the list to remove.
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.GetDepthInMainChain() > oldestTxDepth)
TxToRemove.push_back(wtx.GetHash());
}
}
// erase txs
BOOST_FOREACH (uint256& hash, TxToRemove)
{
pwalletMain->EraseFromWallet(hash);
LogPrintf("Erased %s from wallet.\n",hash.ToString().c_str());
}
// build return JSON for stats.
int remaining = pwalletMain->mapWallet.size();
ret.push_back(Pair("total_transactons", (int)txs));
ret.push_back(Pair("remaining_transactons", (int)remaining));
ret.push_back(Pair("removed_transactions", (int)(txs-remaining)));
return (ret);
}
UniValue getbalance(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
@@ -2671,6 +2775,8 @@ UniValue resendwallettransactions(const UniValue& params, bool fHelp)
return result;
}
extern uint32_t komodo_segid32(char *coinaddr);
UniValue listunspent(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
@@ -2765,6 +2871,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
if (fValidAddress) {
entry.push_back(Pair("address", EncodeDestination(address)));
entry.push_back(Pair("segid", (int)komodo_segid32((char*)EncodeDestination(address).c_str()) & 0x3f ));
if (pwalletMain->mapAddressBook.count(address))
entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name));
@@ -4640,54 +4747,56 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
strDisabledMsg = experimentalDisabledHelpMsg("z_mergetoaddress", enableArg);
}
if (fHelp || params.size() < 2 || params.size() > 6)
if (fHelp || params.size() < 2 || params.size() > 7)
throw runtime_error(
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
+ strDisabledMsg +
"\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
"\nto combine those into a single note."
"\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
"\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
"\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
"\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
"\nnumber of UTXOs. Any limit is constrained by the consensus rule defining a maximum transaction size of"
+ strprintf("\n%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. fromaddresses (string, required) A JSON array with addresses.\n"
" The following special strings are accepted inside the array:\n"
" - \"ANY_TADDR\": Merge UTXOs from any t-addrs belonging to the wallet.\n"
" - \"ANY_SPROUT\": Merge notes from any Sprout z-addrs belonging to the wallet.\n"
" - \"ANY_SAPLING\": Merge notes from any Sapling z-addrs belonging to the wallet.\n"
" If a special string is given, any given addresses of that type will be ignored.\n"
" [\n"
" \"address\" (string) Can be a t-addr or a z-addr\n"
" ,...\n"
" ]\n"
"2. \"toaddress\" (string, required) The t-addr or z-addr to send the funds to.\n"
"3. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"4. transparent_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
"4. shielded_limit (numeric, optional, default="
+ strprintf("%d Sprout or %d Sapling Notes", MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT, MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
"5. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
"\nResult:\n"
"{\n"
" \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
" \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
" \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
" \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
" \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
" \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
" \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
" \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
+ HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"zs14d8tc0hl9q0vg5l28uec5vk6sk34fkj2n8s7jalvw5fxpy6v39yn4s2ga082lymrkjk0x2nqg37\"")
);
"z_mergetoaddress [\"fromaddress\", ... ] \"toaddress\" ( fee ) ( transparent_limit ) ( shielded_limit ) ( memo )\n"
+ strDisabledMsg +
"\nMerge multiple UTXOs and notes into a single UTXO or note. Coinbase UTXOs are ignored; use `z_shieldcoinbase`"
"\nto combine those into a single note."
"\n\nThis is an asynchronous operation, and UTXOs selected for merging will be locked. If there is an error, they"
"\nare unlocked. The RPC call `listlockunspent` can be used to return a list of locked UTXOs."
"\n\nThe number of UTXOs and notes selected for merging can be limited by the caller. If the transparent limit"
"\nparameter is set to zero, and Overwinter is not yet active, the -mempooltxinputlimit option will determine the"
"\nnumber of UTXOs. Any limit is constrained by the consensus rule defining a maximum transaction size of"
+ strprintf("\n%d bytes before Sapling, and %d bytes once Sapling activates.", MAX_TX_SIZE_BEFORE_SAPLING, MAX_TX_SIZE_AFTER_SAPLING)
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. fromaddresses (string, required) A JSON array with addresses.\n"
" The following special strings are accepted inside the array:\n"
" - \"*\": Merge both UTXOs and notes from all addresses belonging to the wallet.\n"
" - \"ANY_TADDR\": Merge UTXOs from all t-addrs belonging to the wallet.\n"
" - \"ANY_ZADDR\": Merge notes from all z-addrs belonging to the wallet.\n"
" If a special string is given, any given addresses of that type will be ignored.\n"
" [\n"
" \"address\" (string) Can be a t-addr or a z-addr\n"
" ,...\n"
" ]\n"
"2. \"toaddress\" (string, required) The t-addr or z-addr to send the funds to.\n"
"3. fee (numeric, optional, default="
+ strprintf("%s", FormatMoney(MERGE_TO_ADDRESS_OPERATION_DEFAULT_MINERS_FEE)) + ") The fee amount to attach to this transaction.\n"
"4. transparent_limit (numeric, optional, default="
+ strprintf("%d", MERGE_TO_ADDRESS_DEFAULT_TRANSPARENT_LIMIT) + ") Limit on the maximum number of UTXOs to merge. Set to 0 to use node option -mempooltxinputlimit (before Overwinter), or as many as will fit in the transaction (after Overwinter).\n"
"4. shielded_limit (numeric, optional, default="
+ strprintf("%d Sprout or %d Sapling Notes", MERGE_TO_ADDRESS_DEFAULT_SPROUT_LIMIT, MERGE_TO_ADDRESS_DEFAULT_SAPLING_LIMIT) + ") Limit on the maximum number of notes to merge. Set to 0 to merge as many as will fit in the transaction.\n"
"5. maximum_utxo_size (numeric, optional) eg, 0.0001 anything under 10000 satoshies will be merged, ignores 10,000 sat p2pk utxo that iguana uses, and merges coinbase utxo.\n"
"6. \"memo\" (string, optional) Encoded as hex. When toaddress is a z-addr, this will be stored in the memo field of the new note.\n"
"\nResult:\n"
"{\n"
" \"remainingUTXOs\": xxx (numeric) Number of UTXOs still available for merging.\n"
" \"remainingTransparentValue\": xxx (numeric) Value of UTXOs still available for merging.\n"
" \"remainingNotes\": xxx (numeric) Number of notes still available for merging.\n"
" \"remainingShieldedValue\": xxx (numeric) Value of notes still available for merging.\n"
" \"mergingUTXOs\": xxx (numeric) Number of UTXOs being merged.\n"
" \"mergingTransparentValue\": xxx (numeric) Value of UTXOs being merged.\n"
" \"mergingNotes\": xxx (numeric) Number of notes being merged.\n"
" \"mergingShieldedValue\": xxx (numeric) Value of notes being merged.\n"
" \"opid\": xxx (string) An operationid to pass to z_getoperationstatus to get the result of the operation.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("z_mergetoaddress", "'[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"]' ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf")
+ HelpExampleRpc("z_mergetoaddress", "[\"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPV\"], \"ztfaW34Gj9FrnGUEf833ywDVL62NWXBM81u6EQnM6VR45eYnXhwztecW1SjxA7JrmAXKJhxhj3vDNEpVCQoSvVoSpmbhtjf\"")
);
if (!fEnableMergeToAddress) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: z_mergetoaddress is disabled.");
@@ -4802,9 +4911,19 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
saplingNoteLimit = nNoteLimit;
}
std::string memo;
CAmount maximum_utxo_size;
if (params.size() > 5) {
memo = params[5].get_str();
maximum_utxo_size = AmountFromValue( params[5] );
if (maximum_utxo_size < 10) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Maximum size must be bigger than 0.00000010.");
}
} else {
maximum_utxo_size = 0;
}
std::string memo;
if (params.size() > 6) {
memo = params[6].get_str();
if (!(isToSproutZaddr || isToSaplingZaddr)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Memo can not be used with a taddr. It can only be used with a zaddr.");
} else if (!IsHex(memo)) {
@@ -4842,7 +4961,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
if (useAnyUTXO || taddrs.size() > 0) {
// Get available utxos
vector<COutput> vecOutputs;
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, false);
pwalletMain->AvailableCoins(vecOutputs, true, NULL, false, maximum_utxo_size != 0 ? true : false);
// Find unspent utxos and update estimated size
for (const COutput& out : vecOutputs) {
@@ -4861,9 +4980,18 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
continue;
}
utxoCounter++;
CAmount nValue = out.tx->vout[out.i].nValue;
if (maximum_utxo_size != 0)
{
//fprintf(stderr, "utxo txid.%s vout.%i nValue.%li scriptpubkeylength.%i\n",out.tx->GetHash().ToString().c_str(),out.i,nValue,out.tx->vout[out.i].scriptPubKey.size());
if (nValue > maximum_utxo_size)
continue;
if (nValue == 10000 && out.tx->vout[out.i].scriptPubKey.size() == 35)
continue;
}
utxoCounter++;
if (!maxedOutUTXOsFlag) {
size_t increase = (boost::get<CScriptID>(&address) != nullptr) ? CTXIN_SPEND_P2SH_SIZE : CTXIN_SPEND_DUST_SIZE;
if (estimatedTxSize + increase >= max_tx_size ||
@@ -4965,10 +5093,11 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
size_t numUtxos = utxoInputs.size();
size_t numNotes = sproutNoteInputs.size() + saplingNoteInputs.size();
if (numUtxos == 0 && numNotes == 0) {
//fprintf(stderr, "num utxos.%li\n", numUtxos);
if (numUtxos < 2 && numNotes == 0) {
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Could not find any funds to merge.");
}
// Sanity check: Don't do anything if:
// - We only have one from address
// - It's equal to toaddress
@@ -5082,9 +5211,6 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp)
#include "script/sign.h"
int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex);
extern std::string NOTARY_PUBKEY;
uint32_t komodo_stake(int32_t validateflag,arith_uint256 bnTarget,int32_t nHeight,uint256 hash,int32_t n,uint32_t blocktime,uint32_t prevtime,char *destaddr);
int8_t komodo_stakehash(uint256 *hashp,char *address,uint8_t *hashbuf,uint256 txid,int32_t vout);
void komodo_segids(uint8_t *hashbuf,int32_t height,int32_t n);
int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
{
@@ -5145,8 +5271,8 @@ int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33)
// ((uint8_t *)&revtxid)[i] = ((uint8_t *)&utxotxid)[31 - i];
txNew.vin[0].prevout.hash = utxotxid; //revtxid;
txNew.vin[0].prevout.n = utxovout;
txNew.vout[0].scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG;
txNew.vout[0].nValue = utxovalue - txfee;
txNew.vout[0].scriptPubKey = CScript() << ParseHex(CRYPTO777_PUBSECPSTR) << OP_CHECKSIG;
CTransaction txNewConst(txNew);
signSuccess = ProduceSignature(TransactionSignatureCreator(&keystore, &txNewConst, 0, utxovalue, SIGHASH_ALL), best_scriptPubKey, sigdata, consensusBranchId);
if (!signSuccess)
@@ -5279,11 +5405,14 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vector<unsigned ch
}
bool pubkey2addr(char *destaddr,uint8_t *pubkey33);
extern int32_t IS_KOMODO_NOTARY,IS_STAKED_NOTARY,USE_EXTERNAL_PUBKEY;
extern uint8_t NOTARY_PUBKEY33[];
extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS;
UniValue setpubkey(const UniValue& params, bool fHelp)
{
UniValue result(UniValue::VOBJ);
if ( fHelp || params.size() != 1 )
if ( fHelp || params.size() > 1 )
throw runtime_error(
"setpubkey\n"
"\nSets the -pubkey if the daemon was not started with it, if it was already set, it returns the pubkey, and its Raddress.\n"
@@ -5300,52 +5429,59 @@ UniValue setpubkey(const UniValue& params, bool fHelp)
+ HelpExampleRpc("setpubkey", "02f7597468703c1c5c8465dd6d43acaae697df9df30bed21494d193412a1ea193e")
);
#ifdef ENABLE_WALLET
LOCK2(cs_main, pwalletMain ? &pwalletMain->cs_wallet : NULL);
#else
LOCK(cs_main);
#endif
char Raddress[64];
uint8_t pubkey33[33];
if ( NOTARY_PUBKEY33[0] == 0 || (strcmp(ASSETCHAINS_SYMBOL, "MUSIG") == 0) )
if ( NOTARY_PUBKEY33[0] == 0 )
{
if (strlen(params[0].get_str().c_str()) == 66)
if (strlen(params[0].get_str().c_str()) == 66)
{
decode_hex(pubkey33,33,(char *)params[0].get_str().c_str());
pubkey2addr((char *)Raddress,(uint8_t *)pubkey33);
if ( 0 && strcmp("RRmWExvapDM9YbLT9X9xAyzDgxomYf63ng",Raddress) == 0) // no idea what this addr is
CBitcoinAddress address(Raddress);
bool isValid = address.IsValid();
if (isValid)
{
result.push_back(Pair("error", "pubkey entered is invalid."));
}
else
{
CBitcoinAddress address(Raddress);
bool isValid = address.IsValid();
if (isValid)
CTxDestination dest = address.Get();
isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
if ( mine == ISMINE_NO )
result.push_back(Pair("WARNING", "privkey for this pubkey is not imported to wallet!"));
else
{
CTxDestination dest = address.Get();
string currentAddress = address.ToString();
result.push_back(Pair("address", currentAddress));
#ifdef ENABLE_WALLET
isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
result.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
#endif
result.push_back(Pair("ismine", "true"));
std::string notaryname;
if ( (IS_STAKED_NOTARY= StakedNotaryID(notaryname, Raddress)) > -1 )
{
result.push_back(Pair("IsNotary", notaryname));
IS_KOMODO_NOTARY = 0;
}
}
NOTARY_PUBKEY = params[0].get_str();
decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str());
USE_EXTERNAL_PUBKEY = 1;
NOTARY_ADDRESS = address.ToString();
}
} else result.push_back(Pair("error", "pubkey is wrong length, must be 66 char hex string."));
else
result.push_back(Pair("error", "pubkey entered is invalid."));
}
else
result.push_back(Pair("error", "pubkey is wrong length, must be 66 char hex string."));
}
else
else
{
result.push_back(Pair("error", "Can only set pubkey once, to change it you need to restart your daemon, pubkey in use is below."));
pubkey2addr((char *)Raddress,(uint8_t *)NOTARY_PUBKEY33);
std::string address_ret; address_ret.assign(Raddress);
result.push_back(Pair("address",address_ret));
if ( NOTARY_ADDRESS.empty() )
{
pubkey2addr((char *)Raddress,(uint8_t *)NOTARY_PUBKEY33);
NOTARY_ADDRESS.assign(Raddress);
}
result.push_back(Pair("error", "Can only set pubkey once, to change it you need to restart your daemon."));
}
if ( NOTARY_PUBKEY33[0] != 0 && !NOTARY_ADDRESS.empty() )
{
result.push_back(Pair("address", NOTARY_ADDRESS));
result.push_back(Pair("pubkey", NOTARY_PUBKEY));
}
result.push_back(Pair("pubkey", NOTARY_PUBKEY));
return result;
}

View File

@@ -170,7 +170,7 @@ SaplingPaymentAddress CWallet::GenerateNewSaplingZKey()
return addr;
}
// Add spending key to keystore
// Add spending key to keystore
bool CWallet::AddSaplingZKey(
const libzcash::SaplingExtendedSpendingKey &sk,
const libzcash::SaplingPaymentAddress &defaultAddr)
@@ -180,7 +180,7 @@ bool CWallet::AddSaplingZKey(
if (!CCryptoKeyStore::AddSaplingSpendingKey(sk, defaultAddr)) {
return false;
}
if (!fFileBacked) {
return true;
}
@@ -189,7 +189,7 @@ bool CWallet::AddSaplingZKey(
auto ivk = sk.expsk.full_viewing_key().in_viewing_key();
return CWalletDB(strWalletFile).WriteSaplingZKey(ivk, sk, mapSaplingZKeyMetadata[ivk]);
}
return true;
}
@@ -571,10 +571,10 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
return false;
}
void CWallet::ChainTip(const CBlockIndex *pindex,
void CWallet::ChainTip(const CBlockIndex *pindex,
const CBlock *pblock,
SproutMerkleTree sproutTree,
SaplingMerkleTree saplingTree,
SaplingMerkleTree saplingTree,
bool added)
{
if (added) {
@@ -1154,7 +1154,7 @@ bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t n
if (nd->witnesses.size() > 0) {
nd->witnesses.pop_front();
}
// indexHeight is the height of the block being removed, so
// indexHeight is the height of the block being removed, so
// the new witness cache height is one below it.
nd->witnessHeight = indexHeight - 1;
}
@@ -1404,8 +1404,8 @@ int32_t CWallet::VerusStakeTransaction(CBlock *pBlock, CMutableTransaction &txNe
return 0;
}
bool signSuccess;
SignatureData sigdata;
bool signSuccess;
SignatureData sigdata;
uint64_t txfee;
auto consensusBranchId = CurrentEpochBranchId(stakeHeight, Params().GetConsensus());
@@ -1744,10 +1744,17 @@ bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx)
* pblock is optional, but should be provided if the transaction is known to be in a block.
* If fUpdate is true, existing transactions will be updated.
*/
extern uint8_t NOTARY_PUBKEY33[33];
extern std::string NOTARY_ADDRESS,WHITELIST_ADDRESS;
extern int32_t IS_STAKED_NOTARY;
extern uint64_t MIN_RECV_SATS;
bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
{
AssertLockHeld(cs_wallet);
if ( tx.IsCoinBase() && tx.vout[0].nValue == 0 )
return false;
bool fExisted = mapWallet.count(tx.GetHash()) != 0;
if (fExisted && !fUpdate) return false;
auto sproutNoteData = FindMySproutNotes(tx);
@@ -1761,6 +1768,71 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
}
if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0)
{
// wallet filter for notary nodes. Disabled! Can be reenabled or customised for any specific use, pools could also use this to prevent wallet dwy attack.
if ( 0 & !tx.IsCoinBase() && !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 )
{
int numvinIsOurs = 0, numvoutIsOurs = 0, numvinIsWhiteList = 0; int64_t totalvoutvalue = 0;
for (size_t i = 0; i < tx.vin.size(); i++)
{
uint256 hash; CTransaction txin; CTxDestination address;
if (GetTransaction(tx.vin[i].prevout.hash,txin,hash,false))
{
if (ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address))
{
if ( CBitcoinAddress(address).ToString() == NOTARY_ADDRESS )
numvinIsOurs++;
if ( !WHITELIST_ADDRESS.empty() )
{
//fprintf(stderr, "white list address: %s recv address: %s\n", WHITELIST_ADDRESS.c_str(),CBitcoinAddress(address).ToString().c_str());
if ( CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) {
//fprintf(stderr, "whitlisted is set to true here.\n");
numvinIsWhiteList++;
}
}
}
}
}
// Now we know if it was a tx sent to us, that wasnt from ourself or the whitelist address if set..
if ( numvinIsOurs != 0 )
fprintf(stderr, "We sent from address: %s vins: %d\n",NOTARY_ADDRESS.c_str(),numvinIsOurs);
if ( numvinIsWhiteList != 0 )
fprintf(stderr, "We received from whitelisted address: %s\n",WHITELIST_ADDRESS.c_str());
// Count vouts, check if OUR notary address is the receiver.
if ( numvinIsOurs == 0 && numvinIsWhiteList == 0 )
{
for (size_t i = 0; i < tx.vout.size() ; i++)
{
CTxDestination address2;
if ( ExtractDestination(tx.vout[i].scriptPubKey, address2))
{
if ( CBitcoinAddress(address2).ToString() == NOTARY_ADDRESS )
{
numvoutIsOurs++;
totalvoutvalue += tx.vout[i].nValue;
}
}
}
// if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions.
if ( MIN_RECV_SATS == 0 ) {
fprintf(stderr, "This node is on full lock down all txs are ignored! \n");
return false;
}
// If no vouts are to the notary address we will ignore them.
if ( numvoutIsOurs == 0 ) {
fprintf(stderr, "Received transaction to address other than notary address, ignored! \n");
return false;
}
fprintf(stderr, "address: %s received %ld sats from %d vouts.\n",NOTARY_ADDRESS.c_str(),totalvoutvalue,numvoutIsOurs);
// here we add calculation for number if vouts received, average size and determine if we accept them to wallet or not.
int64_t avgVoutSize = totalvoutvalue / numvoutIsOurs;
if ( avgVoutSize < MIN_RECV_SATS ) {
// average vout size is less than set minimum, default is 1 coin, we will ignore it
fprintf(stderr, "ignored: %d vouts average size of %ld sats.\n",numvoutIsOurs, avgVoutSize);
return false;
}
}
}
CWalletTx wtx(this,tx);
if (sproutNoteData.size() > 0) {
@@ -2177,7 +2249,7 @@ isminetype CWallet::IsMine(const CTransaction& tx, uint32_t voutNum)
case TX_SCRIPTHASH:
scriptID = CScriptID(uint160(vSolutions[0]));
if (this->GetCScript(scriptID, subscript))
if (this->GetCScript(scriptID, subscript))
{
// if this is a CLTV, handle it differently
if (subscript.IsCheckLockTimeVerify())
@@ -2765,6 +2837,8 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
void CWallet::ReacceptWalletTransactions()
{
if ( IsInitialBlockDownload() )
return;
// If transactions aren't being broadcasted, don't let them into local mempool either
if (!fBroadcastTransactions)
return;
@@ -3234,7 +3308,7 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
int nDepth = pcoin->GetDepthInMainChain();
if (nDepth < 0)
continue;
for (int i = 0; i < pcoin->vout.size(); i++)
{
isminetype mine = IsMine(pcoin->vout[i]);
@@ -4872,7 +4946,7 @@ void CWallet::GetFilteredNotes(
}
/**
* Find notes in the wallet filtered by payment addresses, min depth, max depth,
* Find notes in the wallet filtered by payment addresses, min depth, max depth,
* if the note is spent, if a spending key is required, and if the notes are locked.
* These notes are decrypted and added to the output parameter vector, outEntries.
*/
@@ -5125,10 +5199,10 @@ SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingE
m_wallet->mapSaplingZKeyMetadata[ivk].seedFp = seedFp;
}
return KeyAdded;
}
}
}
}
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
SpendingKeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::InvalidEncoding& no) const {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}

View File

@@ -878,7 +878,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
static bool IsKeyType(string strType)
{
return (strType== "key" || strType == "wkey" ||
return (strType == "key" || strType == "wkey" ||
strType == "hdseed" || strType == "chdseed" ||
strType == "zkey" || strType == "czkey" ||
strType == "sapzkey" || strType == "csapzkey" ||
@@ -1001,7 +1001,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
if (wss.fAnyUnordered)
result = ReorderTransactions(pwallet);
return result;
}

View File

@@ -42,21 +42,16 @@ if [ "x$*" = 'x--help' ]
then
cat <<EOF
Usage:
$0 --help
Show this help message and exit.
$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ MAKEARGS... ]
Build Zcash and most of its transitive dependencies from
source. MAKEARGS are applied to both dependencies and Zcash itself.
If --enable-lcov is passed, Zcash is configured to add coverage
instrumentation, thus enabling "make cov" to work.
If --disable-tests is passed instead, the Zcash tests are not built.
If --disable-mining is passed, Zcash is configured to not build any mining
code. It must be passed after the test arguments, if present.
If --enable-proton is passed, Zcash is configured to build the Apache Qpid Proton
library required for AMQP support. This library is not built by default.
It must be passed after the test/mining arguments, if present.
@@ -101,8 +96,11 @@ eval "$MAKE" --version
as --version
ld -v
HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1
./autogen.sh
CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" $CONFIGURE_FLAGS CXXFLAGS='-g'
#BUILD CCLIB
WD=$PWD
@@ -111,6 +109,4 @@ echo $PWD
./makerogue
cd $WD
./autogen.sh
CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" $CONFIGURE_FLAGS CXXFLAGS='-g'
"$MAKE" "$@" V=1