diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index e537df018..aa21896aa 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1917,33 +1917,37 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &Notar return(total); } -uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries) { - std::vector 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) + if ( notarypubkeys[0][0] == 0 ) + return false; + BOOST_FOREACH(const CTxIn& txin, vin) { uint256 hash; CTransaction tx1; if ( GetTransaction(txin.prevout.hash,tx1,hash,false) ) { - for (int8_t i = 0; i < numSN; i++) + for (int8_t i = 0; i < numNN; 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); } - } + } else return false; } + return true; +} + +uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) +{ + std::vector NotarisationNotaries; uint8_t *script; int32_t scriptlen; + uint64_t timestamp = pblock->nTime; + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, timestamp); + if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) ) + return(0); + // check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems) std::set checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() ); if ( checkdupes.size() != NotarisationNotaries.size() ) { diff --git a/src/notarystats.py b/src/notarystats.py new file mode 100755 index 000000000..0e7673833 --- /dev/null +++ b/src/notarystats.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +""" +sudo apt-get install python3-dev +sudo apt-get install python3 libgnutls28-dev libssl-dev +sudo apt-get install python3-pip +pip3 install setuptools +pip3 install wheel +pip3 install base58 slick-bitcoinrpc +./notarystats.py +------------------------------------------------ +""" +import platform +import os +import re +import sys +import time +import pprint +from slickrpc import Proxy + +# fucntion to define rpc_connection +def def_credentials(chain): + rpcport = ''; + operating_system = platform.system() + if operating_system == 'Darwin': + ac_dir = os.environ['HOME'] + '/Library/Application Support/Komodo' + elif operating_system == 'Linux': + ac_dir = os.environ['HOME'] + '/.komodo' + elif operating_system == 'Windows': + ac_dir = '%s/komodo/' % os.environ['APPDATA'] + if chain == 'KMD': + coin_config_file = str(ac_dir + '/komodo.conf') + else: + coin_config_file = str(ac_dir + '/' + chain + '/' + chain + '.conf') + with open(coin_config_file, 'r') as f: + for line in f: + l = line.rstrip() + if re.search('rpcuser', l): + rpcuser = l.replace('rpcuser=', '') + elif re.search('rpcpassword', l): + rpcpassword = l.replace('rpcpassword=', '') + elif re.search('rpcport', l): + rpcport = l.replace('rpcport=', '') + if len(rpcport) == 0: + if chain == 'KMD': + rpcport = 7771 + else: + print("rpcport not in conf file, exiting") + print("check " + coin_config_file) + exit(1) + return (Proxy("http://%s:%s@127.0.0.1:%d" % (rpcuser, rpcpassword, int(rpcport)))) + + +rpc = def_credentials('KMD') +pp = pprint.PrettyPrinter(indent=2) + +notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333_EU", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] +notaries = 64 * [0] + +startheight = 821657 #Second time filter for assetchains (block 821657) for KMD its 814000 +stopheight = rpc.getblockcount() # @kolo what height does season end?! +for i in range(startheight,stopheight): + ret = rpc.getNotarisationsForBlock(i) + KMD = ret['KMD'] + if len(KMD) > 0: + for obj in KMD: + #for now skip KMD for this. As official stats are from BTC chain + # this can be reversed to !== to count KMD numbers :) + if obj['chain'] == 'KMD': + continue; + for notary in obj['notaries']: + notaries[notary] = notaries[notary] + 1 + +i = 0 +SH = [] +AR = [] +EU = [] +NA = [] +for notary in notaries: + tmpnotary = {} + tmpnotary['node'] = notarynames[i] + tmpnotary['ac_count'] = notary + if notarynames[i].endswith('SH'): + SH.append(tmpnotary) + elif notarynames[i].endswith('AR'): + AR.append(tmpnotary) + elif notarynames[i].endswith('EU'): + EU.append(tmpnotary) + elif notarynames[i].endswith('NA'): + NA.append(tmpnotary) + i = i + 1 + +regions = {} +regions['SH'] = sorted(SH, key=lambda k: k['ac_count'], reverse=True) +regions['AR'] = sorted(AR, key=lambda k: k['ac_count'], reverse=True) +regions['EU'] = sorted(EU, key=lambda k: k['ac_count'], reverse=True) +regions["NA"] = sorted(NA, key=lambda k: k['ac_count'], reverse=True) + +pp.pprint(regions) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 19910b25c..cab89092c 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -171,6 +171,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "assetchainproof", 1}, { "crosschainproof", 1}, { "getproofroot", 2}, + { "getNotarisationsForBlock", 0}, { "height_MoM", 1}, { "calc_MoM", 2}, }; diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index 710f99f09..72c24086f 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -33,6 +33,7 @@ #include "script/script_error.h" #include "script/sign.h" #include "script/standard.h" +#include "notaries_staked.h" #include "key_io.h" @@ -49,6 +50,7 @@ int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_ int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); extern std::string ASSETCHAINS_SELFIMPORT; uint256 Parseuint256(char *hexstr); @@ -406,7 +408,63 @@ UniValue selfimport(const UniValue& params, bool fHelp) return result; } +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); + UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) +{ + // TODO take timestamp as param, and loop blockindex to get starting/finish height. + if (fHelp || params.size() != 1) + throw runtime_error("getNotarisationsForBlock height\n\n" + "Takes a block height and returns notarisation information " + "within the block"); + + LOCK(cs_main); + int32_t height = params[0].get_int(); + if ( height < 0 || height > chainActive.Height() ) + throw runtime_error("height out of range.\n"); + + uint256 blockHash = chainActive[height]->GetBlockHash(); + + NotarisationsInBlock nibs; + GetBlockNotarisations(blockHash, nibs); + UniValue out(UniValue::VOBJ); + //out.push_back(make_pair("blocktime",(int))); + UniValue labs(UniValue::VARR); + UniValue kmd(UniValue::VARR); + // Gets KMD notaries on KMD... but LABS notaries on labs chains needs to be fixed so LABS are identified on KMD. + int8_t numNN = 0; uint8_t notarypubkeys[64][33] = {0}; + numNN = komodo_notaries(notarypubkeys, height, chainActive[height]->nTime); + + BOOST_FOREACH(const Notarisation& n, nibs) + { + UniValue item(UniValue::VOBJ); UniValue notaryarr(UniValue::VARR); std::vector NotarisationNotaries; + if ( is_STAKED(n.second.symbol) != 0 ) + continue; // for now just skip this... need to fetch diff pubkeys for these chains. labs.push_back(item); + uint256 hash; CTransaction tx; + if ( GetTransaction(n.first,tx,hash,false) ) + { + if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) ) + continue; + if ( NotarisationNotaries.size() < numNN/5 ) + continue; + } + item.push_back(make_pair("txid", n.first.GetHex())); + item.push_back(make_pair("chain", n.second.symbol)); + item.push_back(make_pair("height", (int)n.second.height)); + item.push_back(make_pair("blockhash", n.second.blockHash.GetHex())); + item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used. + + for ( auto notary : NotarisationNotaries ) + notaryarr.push_back(notary); + item.push_back(make_pair("notaries",notaryarr)); + kmd.push_back(item); + } + out.push_back(make_pair("KMD", kmd)); + //out.push_back(make_pair("LABS", labs)); + return out; +} + +/*UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error("getNotarisationsForBlock blockHash\n\n" @@ -426,7 +484,7 @@ UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) out.push_back(item); } return out; -} +}*/ UniValue scanNotarisationsDB(const UniValue& params, bool fHelp)