diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index 8d753d596..a6b0cbc2c 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -11,6 +11,7 @@ export BITCOIND=${REAL_BITCOIND} #Run the tests testScripts=( + 'dpowconfs.py' 'dpow.py' 'paymentdisclosure.py' 'prioritisetransaction.py' diff --git a/qa/rpc-tests/dpowconfs.py b/qa/rpc-tests/dpowconfs.py new file mode 100755 index 000000000..4941d8f0f --- /dev/null +++ b/qa/rpc-tests/dpowconfs.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python2 +# Copyright (c) 2018 The Hush developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, initialize_chain_clean, \ + start_node, stop_node, wait_bitcoinds + + +class DPoWConfsTest(BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + num_nodes = 1 + initialize_chain_clean(self.options.tmpdir, num_nodes) + + def setup_network(self): + self.nodes = [] + self.is_network_split = False + self.nodes.append(start_node(0, self.options.tmpdir)) + self.sync_all() + + def run_test(self): + rpc = self.nodes[0] + # 98 is notarized, next will be 105. Must mine at least 101 + # blocks for 100 block maturity rule + blockhashes = rpc.generate(101) + # block 98, this is 0 indexed + notarizedhash = blockhashes[97] + print rpc.getinfo() + + taddr = rpc.getnewaddress() + rpc.sendtoaddress(taddr, 1987.420) + rpc.generate(2) + + info = rpc.getinfo() + assert_equal( info['notarizedhash'], notarizedhash) + + result = rpc.listunspent() + + # this xtn has 2 raw confs, but not in a notarized block, + # so dpowconfs holds it at 1 + for res in result: + if (res['address'] == taddr and res['generated'] == 'false'): + assert_equal( result[0]['confirmations'], 1 ) + assert_equal( result[0]['rawconfirmations'], 2 ) + + +if __name__ == '__main__': + DPoWConfsTest().main() diff --git a/src/komodo_defs.h b/src/komodo_defs.h new file mode 100644 index 000000000..7c339856c --- /dev/null +++ b/src/komodo_defs.h @@ -0,0 +1,13 @@ +#ifndef KOMODO_DEFS_H +#define KOMODO_DEFS_H + +#define ASSETCHAINS_MINHEIGHT 128 +#define KOMODO_ELECTION_GAP 2000 +#define ROUNDROBIN_DELAY 61 +#define KOMODO_ASSETCHAIN_MAXLEN 65 +#define KOMODO_LIMITED_NETWORKSIZE 4 +#define IGUANA_MAXSCRIPTSIZE 10001 +#define KOMODO_MAXMEMPOOLTIME 3600 // affects consensus +#define CRYPTO777_PUBSECPSTR "020e46e79a2a8d12b9b5d12c7a91adb4e454edfae43c0a0cb805427d2ac7613fd9" + +#endif diff --git a/src/komodo_rpcblockchain.h b/src/komodo_rpcblockchain.h index a1b79cfc3..97b00d499 100644 --- a/src/komodo_rpcblockchain.h +++ b/src/komodo_rpcblockchain.h @@ -21,6 +21,25 @@ int32_t komodo_MoMdata(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_t height,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); extern char ASSETCHAINS_SYMBOL[65]; +uint32_t DPOWCONFS = 1; +extern int32_t NOTARIZED_HEIGHT; + +int32_t komodo_dpowconfs(int32_t txheight,int32_t numconfs) +{ + // DPoW confs are on by default + int32_t dpowconfs = 1; + DPOWCONFS = GetArg("-dpowconfs",dpowconfs); + if ( DPOWCONFS != 0 && txheight > 0 && numconfs > 0 ) + { + if ( NOTARIZED_HEIGHT > 0 ) + { + if ( txheight < NOTARIZED_HEIGHT ) + return(numconfs); + else return(1); + } + } + return(numconfs); +} int32_t komodo_MoM(int32_t *notarized_heightp,uint256 *MoMp,uint256 *kmdtxidp,int32_t nHeight,uint256 *MoMoMp,int32_t *MoMoMoffsetp,int32_t *MoMoMdepthp,int32_t *kmdstartip,int32_t *kmdendip) { diff --git a/src/komodo_validation011.h b/src/komodo_validation011.h index df8c730bd..9cc054ec3 100644 --- a/src/komodo_validation011.h +++ b/src/komodo_validation011.h @@ -1172,6 +1172,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) { static int32_t hwmheight; uint64_t signedmask; uint8_t scriptbuf[4096],pubkeys[64][33],scriptPubKey[35]; uint256 zero; int32_t i,j,k,m,numnotaries,notarized,scriptlen,numvalid,specialtx,notarizedheight,len,numvouts,numvins,height,txn_count; + uint256 txhash; if ( KOMODO_NEEDPUBKEYS != 0 ) { @@ -1197,7 +1198,7 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) //fprintf(stderr, "txn_count=%d\n", txn_count); for (i=0; iGetHash(); + txhash = block.vtx[i].GetHash(); numvouts = block.vtx[i].vout.size(); specialtx = notarizedheight = notarized = 0; signedmask = 0; @@ -1224,6 +1225,12 @@ void komodo_connectblock(CBlockIndex *pindex,CBlock& block) numvalid = bitweight(signedmask); if ( numvalid >= KOMODO_MINRATIFY ) notarized = 1; + if ( Params().NetworkIDString() == "regtest" && ( height%7 == 0) ) { + notarized = 1; + NOTARIZED_HEIGHT = height; + NOTARIZED_HASH = block.GetHash(); + NOTARIZED_DESTTXID = txhash; + } if ( IS_NOTARY ) LogPrint("dpow","(tx.%d: ",i); for (j=0; jnHeight + 1; - result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); + result.push_back(Pair("rawconfirmations", confirmations)); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", blockindex->nVersion)); result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex())); @@ -144,7 +146,8 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex) } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block is an orphan"); } - result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); + result.push_back(Pair("rawconfirmations", confirmations)); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); @@ -248,7 +251,8 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx // Only report confirmations if the block is on the main chain if (chainActive.Contains(blockindex)) confirmations = chainActive.Height() - blockindex->nHeight + 1; - result.push_back(Pair("confirmations", confirmations)); + result.push_back(Pair("confirmations", komodo_dpowconfs(blockindex->nHeight,confirmations))); + result.push_back(Pair("rawconfirmations", confirmations)); result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION))); result.push_back(Pair("height", blockindex->nHeight)); result.push_back(Pair("version", block.nVersion)); @@ -805,7 +809,10 @@ UniValue gettxout(const UniValue& params, bool fHelp) if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT) ret.push_back(Pair("confirmations", 0)); else - ret.push_back(Pair("confirmations", pindex->nHeight - coins.nHeight + 1)); + { + ret.push_back(Pair("confirmations", komodo_dpowconfs(coins.nHeight,pindex->nHeight - coins.nHeight + 1))); + ret.push_back(Pair("rawconfirmations", pindex->nHeight - coins.nHeight + 1)); + } ret.push_back(Pair("value", ValueFromAmount(coins.vout[n].nValue))); UniValue o(UniValue::VOBJ); ScriptPubKeyToJSON(coins.vout[n].scriptPubKey, o, true); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index c69f49bfc..05a60f577 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -29,6 +29,7 @@ #include using namespace std; +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { @@ -183,7 +184,8 @@ void TxToJSONExpanded(const CTransaction& tx, const uint256 hashBlock, UniValue& if (nConfirmations > 0) { entry.push_back(Pair("height", nHeight)); - entry.push_back(Pair("confirmations", nConfirmations)); + entry.push_back(Pair("confirmations", komodo_dpowconfs(nHeight,nConfirmations))); + entry.push_back(Pair("rawconfirmations", nConfirmations)); entry.push_back(Pair("time", nBlockTime)); entry.push_back(Pair("blocktime", nBlockTime)); } else { @@ -242,7 +244,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) CBlockIndex* pindex = (*mi).second; if (chainActive.Contains(pindex)) { entry.push_back(Pair("height", pindex->nHeight)); - entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight)); + entry.push_back(Pair("rawconfirmations", 1 + chainActive.Height() - pindex->nHeight)); + entry.push_back(Pair("confirmations", komodo_dpowconfs(pindex->nHeight,1 + chainActive.Height() - pindex->nHeight))); entry.push_back(Pair("time", pindex->GetBlockTime())); entry.push_back(Pair("blocktime", pindex->GetBlockTime())); } else { @@ -1032,4 +1035,4 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) RelayTransaction(tx); return hashTx.GetHex(); -} \ No newline at end of file +} diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5f3cfaa2c..e80a920a6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -42,6 +42,7 @@ using namespace std; using namespace libzcash; extern UniValue TxJoinSplitToJSON(const CTransaction& tx); +int32_t komodo_dpowconfs(int32_t height,int32_t numconfs); int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; @@ -77,15 +78,16 @@ void EnsureWalletIsUnlocked() void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) { int confirms = wtx.GetDepthInMainChain(); - entry.push_back(Pair("confirmations", confirms)); + entry.push_back(Pair("rawconfirmations", confirms)); if (wtx.IsCoinBase()) entry.push_back(Pair("generated", true)); if (confirms > 0) { + entry.push_back(Pair("confirmations", komodo_dpowconfs((int32_t)mapBlockIndex[wtx.hashBlock]->nHeight,confirms))); entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); entry.push_back(Pair("blockindex", wtx.nIndex)); entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime())); - } + } else entry.push_back(Pair("confirmations", confirms)); uint256 hash = wtx.GetHash(); entry.push_back(Pair("txid", hash.GetHex())); UniValue conflicts(UniValue::VARR); @@ -2418,8 +2420,12 @@ UniValue listunspent(const UniValue& params, bool fHelp) entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()))); } } + int32_t txheight; + if ( chainActive.Tip() != NULL ) + txheight = (chainActive.Tip()->nHeight - out.nDepth - 1); entry.push_back(Pair("amount",ValueFromAmount(nValue))); - entry.push_back(Pair("confirmations",out.nDepth)); + entry.push_back(Pair("rawconfirmations",out.nDepth)); + entry.push_back(Pair("confirmations",komodo_dpowconfs(txheight,out.nDepth))); entry.push_back(Pair("spendable", out.fSpendable)); results.push_back(entry); } @@ -2546,10 +2552,15 @@ UniValue z_listunspent(const UniValue& params, bool fHelp) pwalletMain->GetUnspentFilteredNotes(entries, zaddrs, nMinDepth, nMaxDepth, !fIncludeWatchonly); for (CUnspentNotePlaintextEntry & entry : entries) { UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("txid",entry.jsop.hash.ToString())); + int32_t txheight; + std::string txid = entry.jsop.hash.ToString(); + obj.push_back(Pair("txid",txid)); obj.push_back(Pair("js_index", (int)entry.jsop.js )); obj.push_back(Pair("output_index", (int)entry.jsop.n)); - obj.push_back(Pair("confirmations", entry.nHeight)); + if ( chainActive.Tip() != NULL ) + txheight = (chainActive.Tip()->nHeight - entry.nHeight - 1); + obj.push_back(Pair("rawconfirmations", entry.nHeight)); + obj.push_back(Pair("confirmations",komodo_dpowconfs(txheight,entry.nHeight))); obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(entry.address))); obj.push_back(Pair("address", CZCPaymentAddress(entry.address).ToString())); obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value))));