diff --git a/configure.ac b/configure.ac
index ea248f28b..7fa0f437c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 1)
define(_CLIENT_VERSION_MINOR, 1)
define(_CLIENT_VERSION_REVISION, 8)
-define(_CLIENT_VERSION_BUILD, 6)
+define(_CLIENT_VERSION_BUILD, 7)
define(_CLIENT_VERSION_IS_RELEASE, true)
define(_COPYRIGHT_YEAR, 2018)
AC_INIT([biblepay Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/biblepaypay/biblepay/issues],[biblepaycore])
diff --git a/src/clientversion.cpp b/src/clientversion.cpp
index 5abc3fb85..d840421b8 100644
--- a/src/clientversion.cpp
+++ b/src/clientversion.cpp
@@ -19,7 +19,7 @@ const std::string CLIENT_NAME("Biblepay Core");
const int BIBLEPAY_VERSION_MAJOR = 1;
const int BIBLEPAY_VERSION_MINOR = 1;
const int BIBLEPAY_VERSION_REVISION = 8;
-const int BIBLEPAY_VERSION_BUILD = 6;
+const int BIBLEPAY_VERSION_BUILD = 7;
const int BIBLE_VERSION = 1000000 * BIBLEPAY_VERSION_MAJOR
diff --git a/src/main.cpp b/src/main.cpp
index 9aa1191b0..30ff929aa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1699,8 +1699,33 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
}
}
}
+ // BiblePay - If Difficulty is < MIN_POG_DIFF and POG_COUNT > MAX_POG_COUNT, reject the transaction - R ANDREWS - 2/9/2019
+ if (chainActive.Tip() != NULL)
+ {
+ int nTitheCount = pool.getTitheCount();
+ double dPogDiff = GetPOGDifficulty(chainActive.Tip());
+ std::string sRecipient = PubKeyToAddress(tx.vout[0].scriptPubKey);
+ bool bIsTithe = (sRecipient == chainparams.GetConsensus().FoundationAddress);
+ if (bIsTithe && dPogDiff < LOW_POG_DIFF && nTitheCount > TITHE_OVERFLOW)
+ {
+ LogPrintf("AcceptToMemPool::Tithe Overflow Type I; Tithe Rejected; Tithe Count %f, Pog Diff %f ", nTitheCount, dPogDiff);
+ return false;
+ }
+ else if (bIsTithe && nTitheCount > (TITHE_OVERFLOW * 2))
+ {
+ LogPrintf("AcceptToMemPool::Tithe Overflow Type II; Tithe Rejected; Tithe Count %f, Pog Diff %f ", nTitheCount, dPogDiff);
+ return false;
+ }
+ else if (bIsTithe && dPogDiff < LOW_POG_DIFF && chainActive.Height() < POG_V2_CUTOVER_HEIGHT_PROD && nTitheCount > (TITHE_OVERFLOW / 15))
+ {
+ LogPrintf("AcceptToMemPool::Tithe Overflow Type III; Tithe Rejected; Tithe Count %f, Pog Diff %f ", nTitheCount, dPogDiff);
+ return false;
+ }
+ LogPrintf("Tithe Count %f, Diff %f ",(double)nTitheCount, dPogDiff);
+ }
+
// If we aren't going to actually accept it but just were verifying it, we are fine already
- if(fDryRun) return true;
+ if (fDryRun) return true;
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
diff --git a/src/main.h b/src/main.h
index 9954b010f..855b1bdb8 100644
--- a/src/main.h
+++ b/src/main.h
@@ -87,9 +87,13 @@ static const int F14000_CUTOVER_HEIGHT_PROD = 77000; // October 14th, 2018
static const int F14000_CUTOVER_HEIGHT_TESTNET = 54300; // Sep. 1, 2018
static const int FPOG_CUTOVER_HEIGHT_TESTNET = 95945; // Dec. 23rd, 2018
static const int FPOG_CUTOVER_HEIGHT_PROD = 100001; // Feb 7th, 2019 (100,001)
-static const int PODC_LAST_BLOCK_PROD = 106150; // March 8th, 2019 (106,150)
+static const int PODC_LAST_BLOCK_PROD = 107000; // March 13th, 2019
static const int PODC_LAST_BLOCK_TESTNET = 126150;
+static const int POG_V2_CUTOVER_HEIGHT_PROD = 102025;
+static const int LOW_POG_DIFF = 5000;
+static const int TITHE_OVERFLOW = 75;
static const int MINIMUM_EMAIL_LENGTH = 5; // 3 character domain + . + 1 character name
+
/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default for -limitancestorcount, max number of in-mempool ancestors */
diff --git a/src/miner.cpp b/src/miner.cpp
index 679afd8b9..0fa99a1f2 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -809,7 +809,7 @@ void static BibleMiner(const CChainParams& chainparams, int iThreadID, int iFeat
// POG - R ANDREWS - 12/6/2018 - Once every 4 hours, tithe if profitable and possible
int64_t nPOGTitheAge = GetAdjustedTime() - nLastPOGTithe;
- if (fPOGEnabled && nPOGTitheFrequency > 120 && iThreadID == 0 && (nPOGTitheAge > (nPOGTitheFrequency)))
+ if (fPOGEnabled && nPOGTitheFrequency > 119 && iThreadID == 0 && (nPOGTitheAge > (nPOGTitheFrequency)))
{
nLastPOGTithe = GetAdjustedTime();
CAmount nTitheAmount = SelectCoinsForTithing(chainActive.Tip());
diff --git a/src/qt/businessobjectlist.cpp b/src/qt/businessobjectlist.cpp
index 77786ec67..11606704d 100644
--- a/src/qt/businessobjectlist.cpp
+++ b/src/qt/businessobjectlist.cpp
@@ -95,6 +95,8 @@ void BusinessObjectList::createUI(const QStringList &headers, const QString &pSt
{
ui->tableWidget->setShowGrid(true);
ui->tableWidget->setRowCount(0);
+ ui->tableWidget->setSortingEnabled(false);
+
ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
@@ -134,6 +136,7 @@ void BusinessObjectList::createUI(const QStringList &headers, const QString &pSt
for(int j = 0; j < cols; j++)
{
QTableWidgetItem* q = new QTableWidgetItem(pMatrix[i][j]);
+ if (j == iAmountCol) q = new QTableWidgetItem(cdbl(GUIUtil::FROMQS(pMatrix[i][j]), 2));
ui->tableWidget->setItem(i, j, q);
}
if (bHighlighted)
@@ -150,6 +153,9 @@ void BusinessObjectList::createUI(const QStringList &headers, const QString &pSt
if (ObjectType == "pog_leaderboard")
{
+ // Sort by ShareWeight descending
+ ui->tableWidget->sortByColumn(5, Qt::DescendingOrder);
+ ui->tableWidget->setSortingEnabled(true);
std::string sXML = GUIUtil::FROMQS(pStr);
addFooterRow(rows, iFooterRow, "Difficulty:", ExtractXML(sXML, "",""));
addFooterRow(rows, iFooterRow, "My Tithes:", ExtractXML(sXML, "",""));
@@ -265,7 +271,13 @@ void BusinessObjectList::slotReviewLetter()
{
QMessageBox msgBox;
std::string id = GUIUtil::FROMQS(ui->tableWidget->item(row, 0)->text());
- WriteOrphan *dlg = new WriteOrphan(this, "REVIEW", "", id);
+ // If we wrote this letter, allow edit:
+ std::string sReceivingAddress = DefaultRecAddress(BUSINESS_OBJECTS);
+ int iCol = GetUrlColumn("receiving_address");
+ std::string sWriterAddr = GUIUtil::FROMQS(ui->tableWidget->item(row, iCol)->text());
+ bool bOwned = (sWriterAddr == sReceivingAddress && !sWriterAddr.empty());
+ std::string sMode = bOwned ? "EDIT" : "REVIEW";
+ WriteOrphan *dlg = new WriteOrphan(this, sMode, "", id);
dlg->show();
}
}
diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp
index 0d54f9dad..776430a26 100644
--- a/src/qt/masternodelist.cpp
+++ b/src/qt/masternodelist.cpp
@@ -173,6 +173,8 @@ void MasternodeList::StartAll(std::string strCommand)
void MasternodeList::StartOne()
{
+ return;
+
int nCountSuccessful = 0;
int nCountFailed = 0;
std::string strFailedHtml;
diff --git a/src/qt/writeorphan.cpp b/src/qt/writeorphan.cpp
index f103dc079..a3d3a1c6b 100644
--- a/src/qt/writeorphan.cpp
+++ b/src/qt/writeorphan.cpp
@@ -19,7 +19,17 @@
#include
#include
-
+std::string GetLetterId(std::string sObjId)
+{
+ std::vector vFields = Split(sObjId.c_str(), "-");
+ if (vFields.size() > 1)
+ {
+ std::string sID = vFields[1];
+ return sID;
+ }
+ return sObjId;
+}
+
WriteOrphan::WriteOrphan(QWidget *parent, std::string xMode, std::string xOrphanID, std::string xLetterID) : QDialog(parent),ui(new Ui::WriteOrphan)
{
ui->setupUi(this);
@@ -40,7 +50,7 @@ WriteOrphan::WriteOrphan(QWidget *parent, std::string xMode, std::string xOrphan
else
{
// The letter ID is the IPFS letter ID
- sObjectID = xLetterID;
+ sObjectID = GetLetterId(xLetterID);
}
// The Attachment directory is the hash of the letterID
sDir = GetSANDirectory2() + RetrieveMd5(sObjectID) + "/";
@@ -51,6 +61,12 @@ WriteOrphan::WriteOrphan(QWidget *parent, std::string xMode, std::string xOrphan
ui->btnSave->setEnabled(false);
ui->btnAttachImage->setEnabled(false);
}
+ else if (sMode == "EDIT")
+ {
+ Load();
+ ui->btnSave->setEnabled(true);
+ ui->btnAttachImage->setEnabled(true);
+ }
PopulateAttachedPics();
connect(ui->btnAttachImage, SIGNAL(clicked()), this, SLOT(AttachImage()));
connect(ui->btnSave, SIGNAL(clicked()), this, SLOT(SaveRecord()));
@@ -60,7 +76,7 @@ WriteOrphan::WriteOrphan(QWidget *parent, std::string xMode, std::string xOrphan
void WriteOrphan::SaveRecord()
{
std::string sTXID = Save();
- std::string sNarr = (sTXID.empty()) ? "Unable to save record. (Ensure wallet is unlocked and retry, next check IPFS configuration.)" : "Successfully saved letter " + sTXID + ". Thank you for writing to BiblePay Orphans!";
+ std::string sNarr = (sTXID.empty()) ? "Unable to save record. (Ensure wallet is unlocked and retry, next check IPFS configuration.)" : "Successfully saved letter " + sObjectID + "-" + sTXID + ". Thank you for writing to BiblePay Orphans!";
QMessageBox::warning(this, tr("Save Letter"), GUIUtil::TOQS(sNarr));
}
@@ -147,9 +163,7 @@ void WriteOrphan::Load()
if (nTries > MAX_RETRIES_NETWORK_FAILURE) return; // In case of network failure, this occurs if the page links cannot be downloaded
std::string sError;
UniValue aBO(UniValue::VOBJ);
- std::vector vFields = Split(sObjectID.c_str(), "-");
-
- aBO = GetBusinessObject("LETTER", vFields[1], sError);
+ aBO = GetBusinessObject("LETTER", GetLetterId(sObjectID), sError);
sOrphanID = aBO["orphanid"].getValStr();
std::string sBody = aBO["body"].getValStr();
std::string sAdded = aBO["added"].getValStr();
@@ -182,6 +196,7 @@ std::string WriteOrphan::Save()
UniValue oBO(UniValue::VOBJ);
oBO.push_back(Pair("objecttype", "letter"));
oBO.push_back(Pair("primarykey", "letter"));
+ // Allow re-saving the object using the original object ID if the user has permissions
oBO.push_back(Pair("secondarykey", sObjectID));
oBO.push_back(Pair("added", RoundToString(GetAdjustedTime(), 0)));
oBO.push_back(Pair("deleted", "0"));
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index b1a94d130..86219b0a2 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -3188,6 +3188,10 @@ UniValue exec(const UniValue& params, bool fHelp)
results.push_back(Pair("vout", sRecipient));
}
}
+ int nTitheCount = mempool.getTitheCount();
+ double dPogDiff = GetPOGDifficulty(chainActive.Tip());
+ results.push_back(Pair("tithe_count", nTitheCount));
+ results.push_back(Pair("pog_difficulty", dPogDiff));
}
else if (sItem == "chat1")
{
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index 5cb3dc44d..b1fa75cfc 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -103,7 +103,7 @@ UniValue getinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("timeoffset", GetTimeOffset()));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string())));
- obj.push_back(Pair("difficulty", (double)GetDifficulty()));
+ obj.push_back(Pair("difficulty", (double)GetDifficultyN(NULL, 10)));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
#ifdef ENABLE_WALLET
if (pwalletMain) {
diff --git a/src/rpcpog.cpp b/src/rpcpog.cpp
index c8feda2fa..d9d0c4ddc 100644
--- a/src/rpcpog.cpp
+++ b/src/rpcpog.cpp
@@ -172,6 +172,7 @@ TitheDifficultyParams GetTitheParams(const CBlockIndex* pindex)
td.min_coin_amount = 0;
td.max_tithe_amount = 0;
if (pindex == NULL || pindex->nHeight == 0) return td;
+ if (fProd && pindex->nHeight > POG_V2_CUTOVER_HEIGHT_PROD) return GetTitheParams2(pindex);
CAmount nTitheCap = GetTitheCap(pindex);
if (nTitheCap < 1) return td;
double nQLevel = (((double)pindex->n24HourTithes/COIN) / ((double)nTitheCap/COIN));
@@ -181,6 +182,30 @@ TitheDifficultyParams GetTitheParams(const CBlockIndex* pindex)
return td;
}
+TitheDifficultyParams GetTitheParams2(const CBlockIndex* pindex)
+{
+ // V2.0 - R ANDREWS - BIBLEPAY - FEB 9th, 2019
+ // V1.0 was subject to catastrophic cycling (due to a high max_tithe_amount accomodating too few participants and due to having no coin age requirement at the lowest diff - and due to the mempool overflow rejection business logic rule not being in place in prod)
+ // After the cutover height, we use V2.0 in prod
+
+ // Tithe Parameter Ranges:
+ // min_coin_age : .25 - 60 (days)
+ // min_coin_amount : 1 - 25000
+ // max_tithe_amount: 10 - .25 (descending)
+ TitheDifficultyParams td;
+ td.min_coin_age = 99999;
+ td.min_coin_amount = 0;
+ td.max_tithe_amount = 0;
+ if (pindex == NULL || pindex->nHeight == 0) return td;
+ CAmount nTitheCap = GetTitheCap(pindex);
+ if (nTitheCap < 1) return td;
+ double nQLevel = (((double)pindex->n24HourTithes/COIN) / ((double)nTitheCap/COIN));
+ td.min_coin_age = R2X(Quantize(.25, 60, nQLevel));
+ td.min_coin_amount = R2X(Quantize(1, 25000, nQLevel)) * COIN;
+ td.max_tithe_amount = R2X(Quantize(10, .25, nQLevel)) * COIN; // Descending tithe amount
+ return td;
+}
+
CAmount SelectCoinsForTithing(const CBlockIndex* pindex)
{
TitheDifficultyParams tdp = GetTitheParams(pindex);
@@ -784,6 +809,7 @@ std::string StoreBusinessObjectWithPK(UniValue& oBusinessObject, std::string& sE
double dStorageFee = 1;
std::string sTxId = "";
sTxId = SendBusinessObject(sOT, sPK + sSecondaryKey, sIPFSHash, dStorageFee, sSignKey, true, sError);
+ WriteCache(sPK, sSecondaryKey, sIPFSHash, GetAdjustedTime());
return sTxId;
}
return "";
@@ -1697,7 +1723,6 @@ std::string SendBusinessObject(std::string sType, std::string sPrimaryKey, std::
if (bSigned)
{
sMessageSig = "" + sSignature + "";
- WriteCache(sType, sSignKey, sValue, GetAdjustedTime());
}
}
std::string s1 = sMessageType + sMessageKey + sMessageValue + sNonce + sBOSignKey + sMessageSig;
@@ -1710,8 +1735,6 @@ std::string SendBusinessObject(std::string sType, std::string sPrimaryKey, std::
return wtx.GetHash().GetHex().c_str();
}
-
-
int GetSignalInt(std::string sLocalSignal)
{
boost::to_upper(sLocalSignal);
diff --git a/src/rpcpog.h b/src/rpcpog.h
index cb62cae99..46f04a2ad 100644
--- a/src/rpcpog.h
+++ b/src/rpcpog.h
@@ -105,6 +105,7 @@ struct TitheDifficultyParams
};
TitheDifficultyParams GetTitheParams(const CBlockIndex* pindex);
+TitheDifficultyParams GetTitheParams2(const CBlockIndex* pindex);
std::vector ReadBytesAll(char const* filename);
std::string VectToString(std::vector v);
CAmount StringToAmount(std::string sValue);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index abfc56a82..f2662702d 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -16,6 +16,7 @@
#include "utilmoneystr.h"
#include "utiltime.h"
#include "version.h"
+#include "chainparams.h"
using namespace std;
@@ -865,6 +866,31 @@ void CTxMemPool::queryHashes(vector& vtxid)
vtxid.push_back(mi->GetTx().GetHash());
}
+int CTxMemPool::getTitheCount()
+{
+ std::vector vtxid;
+ queryHashes(vtxid);
+ int i = 0;
+ BOOST_FOREACH(uint256& hash, vtxid)
+ {
+ CTransaction tx;
+ bool fInMemPool = mempool.lookup(hash, tx);
+ if (fInMemPool)
+ {
+ for (unsigned int z = 0; z < tx.vout.size(); z++)
+ {
+ std::string sRecip = PubKeyToAddress(tx.vout[z].scriptPubKey);
+ if (sRecip == Params().GetConsensus().FoundationAddress)
+ {
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ return i;
+}
+
bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
{
LOCK(cs);
diff --git a/src/txmempool.h b/src/txmempool.h
index 030012b76..3a47d516a 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -8,13 +8,13 @@
#include
#include
-
#include "addressindex.h"
#include "spentindex.h"
#include "amount.h"
#include "coins.h"
#include "primitives/transaction.h"
#include "sync.h"
+#include "chainparams.h"
#undef foreach
#include "boost/multi_index_container.hpp"
@@ -482,6 +482,8 @@ class CTxMemPool
void clear();
void _clear(); //lock free
void queryHashes(std::vector& vtxid);
+ int getTitheCount();
+
void pruneSpent(const uint256& hash, CCoins &coins);
unsigned int GetTransactionsUpdated() const;
void AddTransactionsUpdated(unsigned int n);