diff --git a/README.md b/README.md index e8ed8c3cb..92a7014f4 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,16 @@ This is the official Komodo sourcecode repository based on https://github.com/jl ## Development Resources -- Komodo Website: [https://komodoplatform.com/](https://komodoplatform.com/) -- Komodo Blockexplorer: [https://kmdexplorer.io//](https://https://kmdexplorer.io/) -- Forum: [https://forum.komodoplatform.com/](https://forum.komodoplatform.com/) +- Komodo Website: [https://komodoplatform.com](https://komodoplatform.com/) +- Komodo Blockexplorer: [https://kmdexplorer.io](https://kmdexplorer.io/) +- Komodo Discord: [https://komodoplatform.com/discord](https://komodoplatform.com/discord) +- Forum: [https://forum.komodoplatform.com](https://forum.komodoplatform.com/) - Mail: [info@komodoplatform.com](mailto:info@komodoplatform.com) - Support: [https://support.komodoplatform.com/support/home](https://support.komodoplatform.com/support/home) -- Knowledgebase & How-to: [https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages](https://komodoplatform.atlassian.net/wiki/spaces/KPSD/pages) -- API references: [http://docs.komodoplatform.com/](http://docs.komodoplatform.com/) -- Blog: [http://blog.komodoplatform.com/](http://blog.komodoplatform.com/) -- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/wp-content/uploads/2018/03/2018-03-12-Komodo-White-Paper-Full.pdf) +- Knowledgebase & How-to: [https://support.komodoplatform.com/en/support/solutions](https://support.komodoplatform.com/en/support/solutions) +- API references & Dev Documentation: [https://docs.komodoplatform.com](https://docs.komodoplatform.com/) +- Blog: [https://blog.komodoplatform.com](https://blog.komodoplatform.com/) +- Whitepaper: [Komodo Whitepaper](https://komodoplatform.com/whitepaper) - Komodo Platform public material: [Komodo Platform public material](https://docs.google.com/document/d/1AbhWrtagu4vYdkl-vsWz-HSNyNvK-W-ZasHCqe7CZy0) ## List of Komodo Platform Technologies diff --git a/src/Makefile.am b/src/Makefile.am index 0559230c0..f18c192e2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -246,8 +246,8 @@ obj/build.h: FORCE libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: zcashd -libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) -libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) -DSERVER +libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -DSEVER libbitcoin_server_a_SOURCES = \ sendalert.cpp \ addrman.cpp \ diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 07c64caa0..640c154e4 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -10,7 +10,6 @@ komodo_test_SOURCES = \ test-komodo/test_coinimport.cpp \ test-komodo/test_eval_bet.cpp \ test-komodo/test_eval_notarisation.cpp \ - test-komodo/test_crosschain.cpp \ test-komodo/test_parse_notarisation.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/ac/dion b/src/ac/dion new file mode 100755 index 000000000..889f9e1ad --- /dev/null +++ b/src/ac/dion @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=DION $1 $2 $3 $4 $5 $6 diff --git a/src/ac/kmdice b/src/ac/kmdice new file mode 100755 index 000000000..ca91bf9a5 --- /dev/null +++ b/src/ac/kmdice @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=KMDICE $1 $2 $3 $4 $5 $6 diff --git a/src/ac/pgt b/src/ac/pgt new file mode 100755 index 000000000..8e124bbd1 --- /dev/null +++ b/src/ac/pgt @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=PGT $1 $2 $3 $4 $5 $6 diff --git a/src/assetchains.json b/src/assetchains.json index 454852efe..447de4ca6 100644 --- a/src/assetchains.json +++ b/src/assetchains.json @@ -57,5 +57,36 @@ "195.201.137.5", "195.201.20.230" ] + }, + { + "ac_name": "PGT", + "ac_supply": "10000000", + "ac_end": "1", + "addnode": [ + "190.114.254.104" + ] + }, + { + "ac_name": "KMDICE", + "ac_supply": "10500000", + "ac_reward": "2500000000", + "ac_halving": "210000", + "ac_cc": "2", + "addressindex": "1", + "spentindex": "1", + "addnode": [ + "144.76.217.232" + ] + }, + { + "ac_name": "DION", + "ac_supply": "3900000000", + "ac_reward": "22260000000", + "ac_staked": "100", + "ac_cc": "1", + "ac_end": "4300000000", + "addnode": [ + "51.75.124.34" + ] } ] diff --git a/src/assetchains.old b/src/assetchains.old index fcee4bf41..42a1effb6 100755 --- a/src/assetchains.old +++ b/src/assetchains.old @@ -41,3 +41,6 @@ echo $pubkey ./komodod -pubkey=$pubkey -ac_name=CCL -ac_supply=200000000 -ac_end=1 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=142.93.136.89 -addnode=195.201.22.89 & ./komodod -pubkey=$pubkey -ac_name=PIRATE -ac_supply=0 -ac_reward=25600000000 -ac_halving=77777 -ac_private=1 -addnode=136.243.102.225 & ./komodod -pubkey=$pubkey -ac_name=MGNX -ac_supply=12465003 -ac_staked=90 -ac_reward=2000000000 -ac_halving=525960 -ac_cc=2 -ac_end=2629800 -addnode=142.93.27.180 & +./komodod -pubkey=$pubkey -ac_name=PGT -ac_supply=10000000 -ac_end=1 -addnode=190.114.254.104 & +./komodod -pubkey=$pubkey -ac_name=KMDICE -ac_supply=10500000 -ac_reward=2500000000 -ac_halving=210000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=144.76.217.232 & +./komodod -pubkey=$pubkey -ac_name=DION -ac_supply=3900000000 -ac_reward=22260000000 -ac_staked=100 -ac_cc=1 -ac_end=4300000000 -addnode=51.75.124.34 & diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 6164cf463..d7c906669 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -10,6 +10,7 @@ #include "util.h" #include "utilstrencodings.h" + #include #include @@ -77,6 +78,8 @@ public: #include "komodo_notary.h" #include "notaries_staked.cpp" + + void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotaries,uint8_t notaryid,uint256 txhash,uint64_t voutmask,uint8_t numvouts,uint32_t *pvals,uint8_t numpvals,int32_t KMDheight,uint32_t KMDtimestamp,uint64_t opretvalue,uint8_t *opretbuf,uint16_t opretlen,uint16_t vout,uint256 MoM,int32_t MoMdepth) { diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 8be4bce29..2e447f485 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -24,7 +24,7 @@ so you can pay to a pubkey, or to its hash. or to a script's hash. the last is h all of the above are the standard bitcoin vout types and there should be plenty of materials about it Encrypted by a verified device what I did with the CC contracts is created a fourth type of vout, the CC vout. this is using the cryptoconditions standard and it is even a different signature mechanism. ed25519 instead of secp256k1. it is basically a big extension to the bitcoin script. There is a special opcode that is added that says it is a CC script. - + but it gets more interesting each CC script has an evalcode this is just an arbitrary number. but what it does is allows to create a self-contained universe of CC utxo that all have the same evalcode and that is how a faucet CC differentiates itself from a dice CC, the eval code is different @@ -55,9 +55,11 @@ extern std::string CCerror; #define SMALLVAL 0.000000000000001 #define MIN_NOTARIZATION_CONFIRMS 2 +#ifndef _BITS256 +#define _BITS256 union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; typedef union _bits256 bits256; - +#endif struct CC_utxo { uint256 txid; @@ -149,6 +151,7 @@ bool PreventCC(Eval* eval,const CTransaction &tx,int32_t preventCCvins,int32_t n bool Getscriptaddress(char *destaddr,const CScript &scriptPubKey); std::vector Mypubkey(); bool Myprivkey(uint8_t myprivkey[]); +bool pubkey2addr(char *destaddr,uint8_t *pubkey33); int64_t CCduration(int32_t &numblocks,uint256 txid); bool isCCTxNotarizedConfirmed(uint256 txid); // CCtx diff --git a/src/cc/dice.cpp b/src/cc/dice.cpp index 4271186da..c90ec0f06 100644 --- a/src/cc/dice.cpp +++ b/src/cc/dice.cpp @@ -655,7 +655,7 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK return(totalinputs); } -int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbits,struct CCcontract_info *cp,CPubKey dicepk,uint256 reffundingtxid) +int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbits,struct CCcontract_info *cp,CPubKey dicepk,uint256 reffundingtxid,int32_t &entropytxs) { char coinaddr[64],str[65]; uint64_t sbits; int64_t nValue,totalinputs = 0; uint256 hash,txid,proof,hashBlock,fundingtxid; CScript fundingPubKey; CTransaction tx,vinTx; int32_t vout,first=0,n=0; uint8_t funcid; std::vector > unspentOutputs; @@ -734,6 +734,7 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit } } fprintf(stderr,"numentropy tx %d: %.8f\n",n,(double)totalinputs/COIN); + entropytxs = n; return(totalinputs); } @@ -826,7 +827,9 @@ UniValue DiceInfo(uint256 diceid) result.push_back(Pair("timeoutblocks",timeoutblocks)); cp = CCinit(&C,EVAL_DICE); dicepk = GetUnspendable(cp,0); - funding = DicePlanFunds(entropyval,entropytxid,sbits,cp,dicepk,diceid); + int32_t entropytxs = 0; + funding = DicePlanFunds(entropyval,entropytxid,sbits,cp,dicepk,diceid,entropytxs); + result.push_back(Pair("entropytxs",entropytxs)); sprintf(numstr,"%.8f",(double)funding/COIN); result.push_back(Pair("funding",numstr)); return(result); @@ -955,7 +958,8 @@ std::string DiceBet(uint64_t txfee,char *planstr,uint256 fundingtxid,int64_t bet fprintf(stderr,"%s\n", CCerror.c_str() ); return(""); } - if ( (funding= DicePlanFunds(entropyval,entropytxid,sbits,cp,dicepk,fundingtxid)) >= 2*bet*odds+txfee && entropyval != 0 ) + int32_t entropytxs; + if ( (funding= DicePlanFunds(entropyval,entropytxid,sbits,cp,dicepk,fundingtxid,entropytxs)) >= 2*bet*odds+txfee && entropyval != 0 ) { if ( myIsutxo_spentinmempool(entropytxid,0) != 0 ) { diff --git a/src/cc/eval.cpp b/src/cc/eval.cpp index cb9774a7a..d5d6b1c51 100644 --- a/src/cc/eval.cpp +++ b/src/cc/eval.cpp @@ -164,17 +164,6 @@ bool Eval::GetNotarisationData(const uint256 notaryHash, NotarisationData &data) return true; } -/* - * Get MoMoM corresponding to a notarisation tx hash (on assetchain) - */ -bool Eval::GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const -{ - std::pair out; - if (!GetNextBacknotarisation(kmdNotarisationHash, out)) return false; - momom = out.second.MoMoM; - return true; -} - uint32_t Eval::GetAssetchainsCC() const { diff --git a/src/cc/eval.h b/src/cc/eval.h index 9ff0ca623..b9189bc89 100644 --- a/src/cc/eval.h +++ b/src/cc/eval.h @@ -103,7 +103,6 @@ public: virtual bool GetBlock(uint256 hash, CBlockIndex& blockIdx) const; virtual int32_t GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t timestamp) const; virtual bool GetNotarisationData(uint256 notarisationHash, NotarisationData &data) const; - virtual bool GetProofRoot(uint256 kmdNotarisationHash, uint256 &momom) const; virtual bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const; virtual uint32_t GetAssetchainsCC() const; virtual std::string GetAssetchainsSymbol() const; diff --git a/src/cc/import.cpp b/src/cc/import.cpp index 92e96fabb..7707cb8b4 100644 --- a/src/cc/import.cpp +++ b/src/cc/import.cpp @@ -16,6 +16,7 @@ #include "cc/eval.h" #include "cc/utils.h" #include "importcoin.h" +#include "crosschain.h" #include "primitives/transaction.h" @@ -75,14 +76,8 @@ bool Eval::ImportCoin(const std::vector params, const CTransaction &imp // Check proof confirms existance of burnTx { - uint256 momom, target; - if (!GetProofRoot(proof.first, momom)) - return Invalid("coudnt-load-momom"); - - fprintf(stderr,"IMPORT momom: %s\nKMD TX HASH: %s\n", momom.GetHex().data(),proof.first.GetHex().data()); - - target = proof.second.Exec(burnTx.GetHash()); - if (momom != proof.second.Exec(burnTx.GetHash())) + uint256 target = proof.second.Exec(burnTx.GetHash()); + if (!CheckMoMoM(proof.first, target)) return Invalid("momom-check-fail"); } diff --git a/src/cc/utils.h b/src/cc/utils.h index f0b91962d..69410adbb 100644 --- a/src/cc/utils.h +++ b/src/cc/utils.h @@ -20,6 +20,7 @@ #include "version.h" + /* * Serialisation boilerplate */ diff --git a/src/crosschain.cpp b/src/crosschain.cpp index 982f67d8b..d27bd735c 100644 --- a/src/crosschain.cpp +++ b/src/crosschain.cpp @@ -103,8 +103,9 @@ template int ScanNotarisationsFromHeight(int nHeight, const IsTarget f, Notarisation &found) { int limit = std::min(nHeight + NOTARISATION_SCAN_LIMIT_BLOCKS, chainActive.Height()); + int start = std::max(nHeight, 1); - for (int h=nHeight; hphashBlock, notarisations)) @@ -255,6 +256,38 @@ bool GetNextBacknotarisation(uint256 kmdNotarisationTxid, Notarisation &out) } +bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom) +{ + /* + * Given a notarisation hash and an MoMoM. Backnotarisations may arrive out of order + * or multiple in the same block. So dereference the notarisation hash to the corresponding + * backnotarisation and scan around the kmdheight to see if the MoMoM is a match. + * This is a sledgehammer approach... + */ + + Notarisation bn; + if (!GetBackNotarisation(kmdNotarisationHash, bn)) + return false; + + // Need to get block height of that backnotarisation + EvalRef eval; + CBlockIndex block; + CTransaction tx; + if (!eval->GetTxConfirmed(bn.first, tx, block)){ + fprintf(stderr, "Can't get height of backnotarisation, this should not happen\n"); + return false; + } + + Notarisation nota; + auto checkMoMoM = [&](Notarisation ¬a) { + return nota.second.MoMoM == momom; + }; + + return (bool) ScanNotarisationsFromHeight(block.nHeight-100, checkMoMoM, nota); + +} + + /* * On assetchain * in: txid diff --git a/src/crosschain.h b/src/crosschain.h index 29b6bec4b..c186d5161 100644 --- a/src/crosschain.h +++ b/src/crosschain.h @@ -27,7 +27,7 @@ TxProof GetCrossChainProof(const uint256 txid, const char* targetSymbol, uint32_ void CompleteImportTransaction(CTransaction &importTx); /* On assetchain */ -bool GetNextBacknotarisation(uint256 txid, std::pair &bn); +bool CheckMoMoM(uint256 kmdNotarisationHash, uint256 momom); #endif /* CROSSCHAIN_H */ diff --git a/src/fiat/dion b/src/fiat/dion new file mode 100755 index 000000000..889f9e1ad --- /dev/null +++ b/src/fiat/dion @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=DION $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/kmdice b/src/fiat/kmdice new file mode 100755 index 000000000..ca91bf9a5 --- /dev/null +++ b/src/fiat/kmdice @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=KMDICE $1 $2 $3 $4 $5 $6 diff --git a/src/fiat/pgt b/src/fiat/pgt new file mode 100755 index 000000000..8e124bbd1 --- /dev/null +++ b/src/fiat/pgt @@ -0,0 +1,2 @@ +#!/bin/bash +./komodo-cli -ac_name=PGT $1 $2 $3 $4 $5 $6 diff --git a/src/komodo.h b/src/komodo.h index d2d0231f3..48d25d776 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -797,6 +797,8 @@ int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys void komodo_connectblock(CBlockIndex *pindex,CBlock& block) { static int32_t hwmheight; + int32_t staked_era; static int32_t lastStakedEra; + 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; @@ -809,6 +811,26 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) return; } //fprintf(stderr,"%s connect.%d\n",ASSETCHAINS_SYMBOL,pindex->nHeight); + if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 || IS_STAKED_NOTARY != -1 ) { + staked_era = STAKED_era(pindex->GetBlockTime()); + if ( 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; + } numnotaries = komodo_notaries(pubkeys,pindex->nHeight,pindex->GetBlockTime()); calc_rmd160_sha256(rmd160,pubkeys[0],33); if ( pindex->nHeight > hwmheight ) @@ -831,9 +853,9 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) txn_count = block.vtx.size(); for (i=0; iGetBlockTime()) == 0)) { - printf("ERA 0 SKIP %s\n",ASSETCHAINS_SYMBOL); - continue; + if ( is_STAKED(ASSETCHAINS_SYMBOL) != 0 && staked_era == 0 ) { + // in era gap no point checking any invlaid notarisations. + break; } txhash = block.vtx[i].GetHash(); numvouts = block.vtx[i].vout.size(); diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 68eee6665..1e42ded4a 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -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 @@ -45,17 +44,18 @@ struct komodo_state KOMODO_STATES[34]; #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; -int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,ASSETCHAINS_STREAM,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; +int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,IS_STAKED_NOTARY,ASSETCHAINS_STREAM,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; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; -std::string ASSETCHAINS_OVERRIDE_ADDRESS,NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW; -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; +std::string ASSETCHAINS_OVERRIDE_ADDRESS,NOTARY_ADDRESS,NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,WHITELIST_ADDRESS; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,NUM_NOTARIES; + +char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096],NOTARYADDRS[64][36]; uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1; uint32_t ASSETCHAINS_MAGIC = 2387029918; uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; -uint64_t ASSETCHAINS_FOUNDERS_REWARD,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10; +uint64_t ASSETCHAINS_FOUNDERS_REWARD,ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY = 10,MIN_RECV_SATS; uint32_t KOMODO_INITDONE; char KMDUSERPASS[8192],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 8e2fdf6fc..96497b755 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -22,9 +22,6 @@ #define KOMODO_MAINNET_START 178999 -//extern const char *notaries_STAKED[][2]; -//extern const int num_notaries_STAKED; - const char *Notaries_genesis[][2] = { { "jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, @@ -207,15 +204,13 @@ const char *Notaries_elected1[][2] = int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) { static uint8_t elected_pubkeys0[64][33],elected_pubkeys1[64][33],did0,did1; static int32_t n0,n1; - static uint8_t staked_pubkeys1[64][33],staked_pubkeys2[64][33],didstaked1,didstaked2; static int32_t ns1,ns2; - static uint8_t staked_pubkeys3[64][33],staked_pubkeys4[64][33],didstaked3,didstaked4; static int32_t ns3,ns4; - static uint8_t null_pubkeys[64][33] = {0}; - int staked_era; 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); + timestamp = komodo_heightstamp(height); else if ( ASSETCHAINS_SYMBOL[0] == 0 ) - timestamp = 0; + timestamp = 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) { @@ -226,8 +221,9 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam if ( did0 == 0 ) { n0 = (int32_t)(sizeof(Notaries_elected0)/sizeof(*Notaries_elected0)); - for (i=0; i> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len); -extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33]; +extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],NUM_NOTARIES; uint32_t Mining_start,Mining_height; int32_t My_notaryid = -1; int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp); @@ -206,12 +206,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) double dPriority = 0; CAmount nTotalIn = 0; bool fMissingInputs = false; + bool fNotarisation = false; if (tx.IsCoinImport()) { CAmount nValueIn = GetCoinImportValue(tx); nTotalIn += nValueIn; dPriority += (double)nValueIn * 1000; // flat multiplier } else { + int numNotaryVins = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { // Read prev transaction @@ -250,8 +252,23 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) int nConf = nHeight - coins->nHeight; + if ( NOTARYADDRS[0][0] != 0 && NUM_NOTARIES != 0 ) + { + uint256 hash; CTransaction tx1; CTxDestination address; + if (GetTransaction(txin.prevout.hash,tx1,hash,false)) + { + if (ExtractDestination(tx1.vout[txin.prevout.n].scriptPubKey, address)) { + for (int i = 0; i < NUM_NOTARIES; i++) { + if ( strcmp(NOTARYADDRS[i],CBitcoinAddress(address).ToString().c_str()) == 0 ) + numNotaryVins++; + } + } + } + } dPriority += (double)nValueIn * nConf; } + if ( numNotaryVins > NUM_NOTARIES / 5 ) + fNotarisation = true; nTotalIn += tx.GetJoinSplitValueIn(); } @@ -266,6 +283,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn,int32_t gpucount) CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize); + if (fNotarisation) + dPriority = 1e16; + if (porphan) { porphan->dPriority = dPriority; diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index 966b41850..e4e1c8ddb 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -1,8 +1,15 @@ #include "notaries_staked.h" #include "crosschain.h" +#include "cc/CCinclude.h" #include +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; + // Era 1 set of pubkeys const char *notaries_STAKED1[][2] = { @@ -99,7 +106,7 @@ const char *notaries_STAKED4[][2] = int num_notaries_STAKED4 = (sizeof(notaries_STAKED4)/sizeof(*notaries_STAKED4)); -int is_STAKED(const char *chain_name) { +int8_t is_STAKED(const char *chain_name) { int STAKED = 0; if ( (strcmp(chain_name, "STAKED") == 0) || (strncmp(chain_name, "STAKED", 6) == 0) ) STAKED = 1; @@ -111,9 +118,9 @@ int is_STAKED(const char *chain_name) { return(STAKED); }; -int STAKED_era(int timestamp) +int32_t STAKED_era(int timestamp) { - int era; + int8_t era = 0; if (timestamp <= STAKED_NOTARIES_TIMESTAMP1) era = 1; else if (timestamp <= STAKED_NOTARIES_TIMESTAMP2 && timestamp >= (STAKED_NOTARIES_TIMESTAMP1 + STAKED_ERA_GAP)) @@ -124,11 +131,165 @@ int STAKED_era(int timestamp) era = 4; else era = 0; - // if we are in a gap, return era 0, this allows to invalidate notarizations when in GAP. + // if we are in a gap, return era 0, this allows to invalidate notarizations when in GAP. return(era); }; -CrosschainAuthority Choose_auth_STAKED(int chosen_era) { +#ifdef SERVER +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)); +} +#else +int8_t updateStakedNotary() { + return(-1); +} +#endif + +int8_t StakedNotaryID(std::string ¬aryname, char *Raddress) { + int8_t notaryID = -1; + if ( STAKED_ERA != 0 ) { + switch (STAKED_ERA) { + case 1: + notaryID = ScanStakedArray(notaries_STAKED1,num_notaries_STAKED1,Raddress,notaryname); + break; + case 2: + notaryID = ScanStakedArray(notaries_STAKED2,num_notaries_STAKED2,Raddress,notaryname); + break; + case 3: + notaryID = ScanStakedArray(notaries_STAKED3,num_notaries_STAKED3,Raddress,notaryname); + break; + case 4: + notaryID = ScanStakedArray(notaries_STAKED4,num_notaries_STAKED4,Raddress,notaryname); + break; + } + } + return(notaryID); +} + +int8_t numStakedNotaries(uint8_t pubkeys[64][33],int8_t era) { + int i; int8_t retval = 0; + static uint8_t staked_pubkeys1[64][33],staked_pubkeys2[64][33],didstaked1,didstaked2; + static uint8_t staked_pubkeys3[64][33],staked_pubkeys4[64][33],didstaked3,didstaked4; + static char ChainName[65]; + + if ( ChainName[0] == 0 ) + { + if ( ASSETCHAINS_SYMBOL[0] == 0 ) + strcpy(ChainName,"KMD"); + else + strcpy(ChainName,ASSETCHAINS_SYMBOL); + } + + if ( era != 0 ) { + switch (era) { + case 1: + if ( didstaked1 == 0 ) + { + for (i=0; inChainWork.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); + obj.push_back(Pair("size_on_disk", CalculateCurrentUsage())); ZCIncrementalMerkleTree tree; pcoinsTip->GetAnchorAt(pcoinsTip->GetBestAnchor(), tree); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 86a3a8865..af4eb0ee2 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -13,6 +13,7 @@ #include "timedata.h" #include "txmempool.h" #include "util.h" +#include "notaries_staked.h" #ifdef ENABLE_WALLET #include "wallet/wallet.h" #include "wallet/walletdb.h" @@ -50,22 +51,22 @@ int32_t komodo_notarized_height(int32_t *prevhtp,uint256 *hashp,uint256 *txidp); 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,int32_t height); int32_t notarizedtxid_height(char *dest,char *txidstr,int32_t *kmdnotarized_heightp); +int8_t StakedNotaryID(std::string ¬aryname, char *Raddress); #define KOMODO_VERSION "0.2.1" extern uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT; extern uint32_t ASSETCHAINS_CC; extern uint32_t ASSETCHAINS_MAGIC; extern uint64_t ASSETCHAINS_ENDSUBSIDY,ASSETCHAINS_REWARD,ASSETCHAINS_HALVING,ASSETCHAINS_DECAY,ASSETCHAINS_COMMISSION,ASSETCHAINS_STAKED,ASSETCHAINS_SUPPLY; -extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[]; +extern std::string NOTARY_PUBKEY,NOTARY_ADDRESS; extern uint8_t NOTARY_PUBKEY33[]; UniValue getinfo(const UniValue& params, bool fHelp) { uint256 notarized_hash,notarized_desttxid; int32_t prevMoMheight,notarized_height,longestchain,kmdnotarized_height,txid_height; - extern std::string NOTARY_PUBKEY; extern uint8_t NOTARY_PUBKEY33[]; if (fHelp || params.size() != 0) throw runtime_error( "getinfo\n" @@ -152,23 +153,25 @@ 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()->nHeight,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()->nHeight,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)); obj.push_back(Pair("name", ASSETCHAINS_SYMBOL[0] == 0 ? "KMD" : ASSETCHAINS_SYMBOL)); 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("p2pport", ASSETCHAINS_P2PPORT)); obj.push_back(Pair("rpcport", ASSETCHAINS_RPCPORT)); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index e692e1c84..b7ce61362 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -480,7 +480,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.data(); m = tx.vout[n].scriptPubKey.size(); @@ -1185,7 +1185,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(); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 2154aa1dc..c9d4afe09 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -494,6 +494,7 @@ static const CRPCCommand vRPCCommands[] = { "wallet", "getaccountaddress", &getaccountaddress, true }, { "wallet", "getaccount", &getaccount, true }, { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true }, + { "wallet", "cleanwalletnotarisations", &cleanwalletnotarisations, false }, { "wallet", "getbalance", &getbalance, false }, { "wallet", "getbalance64", &getbalance64, false }, { "wallet", "getnewaddress", &getnewaddress, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 81ca8a8b9..b2ec18bc0 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -299,6 +299,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 cleanwalletnotarisations(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); diff --git a/src/script/standard.cpp b/src/script/standard.cpp index fde836154..9aa02bfb7 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -263,7 +263,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) addressRet = CScriptID(uint160(vSolutions[0])); return true; } - + else if (IsCryptoConditionsEnabled() != 0 && whichType == TX_CRYPTOCONDITION) { addressRet = CKeyID(uint160(vSolutions[0])); diff --git a/src/test-komodo/test_crosschain.cpp b/src/test-komodo/test_crosschain.cpp deleted file mode 100644 index 9d24b4d1d..000000000 --- a/src/test-komodo/test_crosschain.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include "cc/eval.h" -#include "importcoin.h" -#include "base58.h" -#include "core_io.h" -#include "crosschain.h" -#include "key.h" -#include "komodo_structs.h" -#include "main.h" -#include "notarisationdb.h" -#include "primitives/block.h" -#include "primitives/transaction.h" -#include "script/cc.h" -#include "script/interpreter.h" -#include "script/serverchecker.h" -#include "txmempool.h" -#include "crosschain.h" - -#include "testutils.h" - - -extern uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); -extern bool KOMODO_TEST_ASSETCHAIN_SKIP_POW; - - -/* - * Tests for the whole process of creating and validating notary proofs - * using proof roots (MoMoMs). This is to support coin imports. - */ - -namespace TestCrossChainProof { - - -class TestCrossChain : public ::testing::Test, public Eval { -public: - bool CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const - { - NotarisationData data(2); - return ParseNotarisationOpReturn(tx, data); // If it parses it's valid - } -protected: - static void SetUpTestCase() { } - virtual void SetUp() { - KOMODO_TEST_ASSETCHAIN_SKIP_POW = 1; - ASSETCHAINS_CC = 1; - EVAL_TEST = this; - } -}; - - -uint256 endianHash(uint256 h) -{ - uint256 out; - for (int i=0; i<32; i++) { - out.begin()[31-i] = h.begin()[i]; - } - return out; -} - - -TEST_F(TestCrossChain, testCreateAndValidateImportProof) -{ - /* - * This tests the full process of creation of a cross chain proof. - * For the purposes of the test we will use one assetchain and a KMD chain. - * - * In order to do this test, we need 2 blockchains, so we'll fork and make a socket - * for IPC. - */ - - int childPid = fork(); - void *ctx = zmq_ctx_new(); - void *socket = zmq_socket(ctx, ZMQ_PAIR); - if (!childPid) - strcpy(ASSETCHAINS_SYMBOL, "PIZZA"); - setupChain(); - std::vector blocks; - blocks.resize(1000); - NotarisationData a2kmd(0), kmd2a(1); - int numTestNotarisations = 10; - - - auto SendIPC = [&] (std::vector v) { - assert(v.size() == zmq_send(socket, v.data(), v.size(), 0)); - }; - - auto RecvIPC = [&] () { - std::vector out; - out.resize(100000); - int len = zmq_recv(socket, out.data(), out.size(), 0); - assert(len != -1); - out.resize(len); - return out; - }; - - auto RecordNotarisation = [&] (CTransaction inputTx, NotarisationData data) { - CMutableTransaction mtx = spendTx(inputTx); - mtx.vout.resize(2); - mtx.vout[0].scriptPubKey << VCH(notaryKey.GetPubKey().begin(), 33) << OP_CHECKSIG; - mtx.vout[1].scriptPubKey << OP_RETURN << E_MARSHAL(ss << data); - mtx.vout[1].nValue = 0; - mtx.vin[0].scriptSig << getSig(mtx, inputTx.vout[0].scriptPubKey); - - acceptTxFail(CTransaction(mtx)); - return mtx.GetHash(); - }; - - auto RunTestAssetchain = [&] () - { - NotarisationData n(0), back(1); - strcpy(n.symbol, "PIZZA"); - n.ccId = 2; - int height = 0; - - /* - * Send notarisations and write backnotarisations - */ - for (int ni=0; ni> back)); - RecordNotarisation(blocks[height].vtx[0], back); - } - - /* - * Test a proof - */ - uint256 txid = blocks[7].vtx[0].GetHash(); - TxProof proof = GetAssetchainProof(txid); - SendIPC(E_MARSHAL(ss << txid; ss << proof)); - E_UNMARSHAL(RecvIPC(), ss >> proof); - - std::pair bn; - if (!GetNextBacknotarisation(proof.first, bn)) { - printf("GetNextBackNotarisation failed\n"); - return 1; - } - if (proof.second.Exec(txid) != bn.second.MoMoM) { - printf("MoMom incorrect\n"); - return 1; - } - return 0; - }; - - auto RunTestKmd = [&] () - { - NotarisationData n(0); - int height = 0; - - /* - * Write notarisations and send backnotarisations - */ - for (int ni=0; ni> n); - // Grab a coinbase input to fund notarisation - generateBlock(&blocks[++height]); - n.txHash = RecordNotarisation(blocks[height].vtx[0], n); - { - std::vector moms; - uint256 destNotarisationTxid; - n.MoMoM = CalculateProofRoot(n.symbol, 2, height, moms, destNotarisationTxid); - } - n.IsBackNotarisation = 1; - SendIPC(E_MARSHAL(ss << n)); - } - - /* - * Extend proof - */ - TxProof proof; - uint256 txid; - // Extend proof to MoMoM - assert(E_UNMARSHAL(RecvIPC(), ss >> txid; ss >> proof)); - proof = GetCrossChainProof(txid, (char*)"PIZZA", 2, proof); - SendIPC(E_MARSHAL(ss << proof)); - }; - - const char endpoint[] = "ipc://tmpKomodoTestCrossChainSock"; - - if (!childPid) { - assert(0 == zmq_connect(socket, endpoint)); - usleep(20000); - int out = RunTestAssetchain(); - if (!out) printf("Assetchain success\n"); - exit(out); - } - else { - assert(0 == zmq_bind(socket, endpoint)); - RunTestKmd(); - int returnStatus; - waitpid(childPid, &returnStatus, 0); - unlink("tmpKomodoTestCrossChainSock"); - ASSERT_EQ(0, returnStatus); - } - -} - - -} /* namespace TestCrossChainProof */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index f2cfae5a6..61211ec10 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -20,6 +20,7 @@ #include "primitives/transaction.h" #include "zcbenchmarks.h" #include "script/interpreter.h" +#include "notaries_staked.h" #include "utiltime.h" #include "asyncrpcoperation.h" @@ -1000,6 +1001,134 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); } +UniValue cleanwalletnotarisations(const UniValue& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return NullUniValue; + + if (fHelp || params.size() > 1 ) + throw runtime_error( + "cleanwalletnotarisations \"txid\"\n" + "\nRemove all txs which are totally spent and all notarisations created from them, 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("cleanoldtxs", "") + + HelpExampleCli("cleanoldtxs","\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + + HelpExampleRpc("cleanoldtxs", "") + + HelpExampleRpc("cleanoldtxs","\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + ); + + LOCK2(cs_main, pwalletMain->cs_wallet); + UniValue ret(UniValue::VOBJ); + uint256 exception; int32_t txs = pwalletMain->mapWallet.size(); + std::vector 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::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + txs++; + 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 + { + std::vector NotarisationTxs; + for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) + { + const CWalletTx& wtx = (*it).second; + if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 50 ) + continue; + + CCoins coins; + if (!pcoinsTip->GetCoins(wtx.GetHash(), coins)) + { + int spents = 0; int mine = 0; + for (unsigned int n = 0; n < wtx.vout.size() ; n++) + { + if ( pwalletMain->IsMine(wtx.vout[n]) ) + mine++; + if ( ((unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() ) ) + spents++; + } + if ( spents == mine ) + { + TxToRemove.push_back(wtx.GetHash()); + for (unsigned int n = 0; n < wtx.vin.size() ; n++) + { + if ( pwalletMain->IsMine(wtx.vin[n]) ) + TxToRemove.push_back(wtx.vin[n].prevout.hash); + } + } + } + + CTxDestination address; + // get all notarisations + if ( ExtractDestination(wtx.vout[0].scriptPubKey, address) ) + { + if ( strcmp(CBitcoinAddress(address).ToString().c_str(),CRYPTO777_KMDADDR) == 0 ) + NotarisationTxs.push_back(wtx); + } + } + + // Erase notarisations spending from fully spent splits. + BOOST_FOREACH (CWalletTx& tx, NotarisationTxs) + { + for (int n = 0; n < tx.vin.size(); n++) + { + BOOST_FOREACH (uint256& SpentHash, TxToRemove) + { + if ( SpentHash == tx.vin[n].prevout.hash ) + { + pwalletMain->EraseFromWallet(tx.GetHash()); + //fprintf(stderr, "ERASED Notarisation: %s\n",tx.GetHash().ToString().c_str()); + } + } + } + } + } + + // erase txs + BOOST_FOREACH (uint256& hash, TxToRemove) + { + pwalletMain->EraseFromWallet(hash); + //fprintf(stderr, "ERASED spent Tx: %s\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) { @@ -4939,6 +5068,9 @@ UniValue CCaddress(struct CCcontract_info *cp,char *name,std::vectorcs_wallet : NULL); -#else - LOCK(cs_main); -#endif char Raddress[18]; uint8_t pubkey33[33]; - extern uint8_t NOTARY_PUBKEY33[]; - extern std::string NOTARY_PUBKEY; if ( NOTARY_PUBKEY33[0] == 0 ) { if (strlen(params[0].get_str().c_str()) == 66) { decode_hex(pubkey33,33,(char *)params[0].get_str().c_str()); @@ -4982,15 +5108,23 @@ UniValue setpubkey(const UniValue& params, bool fHelp) if (isValid) { 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 - } - NOTARY_PUBKEY = params[0].get_str(); - decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + if ( mine == ISMINE_NO ) { + result.push_back(Pair("error", "privkey for this pubkey is not imported to wallet!")); + } else { + result.push_back(Pair("ismine", "true")); + NOTARY_ADDRESS = address.ToString(); + std::string notaryname; + if ( (IS_STAKED_NOTARY= StakedNotaryID(notaryname, Raddress)) > -1 ) { + result.push_back(Pair("IsNotary", notaryname)); + IS_KOMODO_NOTARY = 0; + USE_EXTERNAL_PUBKEY = 1; + } + NOTARY_PUBKEY = params[0].get_str(); + decode_hex(NOTARY_PUBKEY33,33,(char *)NOTARY_PUBKEY.c_str()); + } + } 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.")); @@ -4998,7 +5132,10 @@ UniValue setpubkey(const UniValue& params, bool fHelp) } else { result.push_back(Pair("error", "Can only set pubkey once, to change it you need to restart your daemon.")); } - result.push_back(Pair("pubkey", NOTARY_PUBKEY)); + if ( NOTARY_PUBKEY33[0] != 0 && !NOTARY_ADDRESS.empty() ) { + result.push_back(Pair("address", NOTARY_ADDRESS)); + result.push_back(Pair("pubkey", NOTARY_PUBKEY)); + } return result; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 47c93545b..ea47c39c1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -180,7 +180,7 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector &vchCryptedSecret) { - + if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret)) return false; if (!fFileBacked) @@ -520,7 +520,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er } catch (const boost::filesystem::filesystem_error&) { // failure is ok (well, not really, but it's not worse than what we started with) } - + // try again if (!bitdb.Open(GetDataDir())) { // if it still fails, it probably means we can't even create the database env @@ -529,14 +529,14 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er return true; } } - + if (GetBoolArg("-salvagewallet", false)) { // Recover readable keypairs: if (!CWalletDB::Recover(bitdb, walletFile, true)) return false; } - + if (boost::filesystem::exists(GetDataDir() / walletFile)) { CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover); @@ -550,7 +550,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er if (r == CDBEnv::RECOVER_FAIL) errorString += _("wallet.dat corrupt, salvage failed"); } - + return true; } @@ -1200,6 +1200,11 @@ 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) { { @@ -1207,8 +1212,73 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl bool fExisted = mapWallet.count(tx.GetHash()) != 0; if (fExisted && !fUpdate) return false; auto noteData = FindMyNotes(tx); + if (fExisted || IsMine(tx) || IsFromMe(tx) || noteData.size() > 0) { + if ( !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 (noteData.size() > 0) { @@ -2296,7 +2366,7 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const int nDepth = pcoin->GetDepthInMainChain(); if (nDepth < 0) continue; - + for (unsigned int i = 0; i < pcoin->vout.size(); i++) { isminetype mine = IsMine(pcoin->vout[i]); @@ -2642,7 +2712,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC CReserveKey reservekey(this); CWalletTx wtx; - + if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false)) return false; @@ -2708,7 +2778,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt txNew.nExpiryHeight = nextBlockHeight + expiryDelta; } } - + { LOCK2(cs_main, cs_wallet); { @@ -3194,7 +3264,7 @@ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) /** * Mark old keypool keys as used, - * and generate all new keys + * and generate all new keys */ bool CWallet::NewKeyPool() { @@ -3902,7 +3972,7 @@ void CWallet::GetFilteredNotes( if (ignoreUnspendable && !HaveSpendingKey(pa)) { continue; } - + // skip locked notes if (IsLockedNote(jsop.hash, jsop.js, jsop.n)) { continue;